jQuery slider - last to first transition - javascript

I created this slider (didn't want to use plugins):
function slider(sel, intr, i) {
var _slider = this;
this.ind = i;
this.selector = sel;
this.slide = [];
this.slide_active = 0;
this.amount;
this.selector.children().each(function (i) {
_slider.slide[i] = $(this);
$(this).hide();
})
this.run();
}
slider.prototype.run = function () {
var _s = this;
this.slide[this.slide_active].show();
setTimeout(function () {
_s.slide[_s.slide_active].hide()
_s.slide_active++;
_s.run();
}, interval);
}
var slides = [];
var interval = 1000
$('.slider').each(function (i) {
slides[i] = new slider($(this), interval, i);
})
The problem I have is that I don´t know how to get it after the last slide(image), it goes back to the first slide again. Right now, it just .hide and .show till the end and if there is no image it just doesn´t start again.
Can someone help me out with a code suggestion to make it take the .length of the slider(the number of images on it) and if it is the last slide(image), then goes back to the first slide(image)... like a cycle.
Edit: Slider markup
<div class="small_box top_right slider">
<img class="fittobox" src="img/home10.jpg" alt="home10" width="854" height="592">
<img class="fittobox" src="img/home3.jpg" alt="home3" width="435" height="392">
<img class="fittobox" src="img/home4.jpg" alt="home4" width="435" height="392">
</div>

Created a fixed version for you here.
The easiest way to do this is to run a simple maths operation where you currently have
_s.slide_active++;
Instead, I get _s.slide_active, add 1, then run that through modulus (%) to the total length — which gives the remainder:
_s.slide_active = (_s.slide_active + 1) % _s.slide.length;

Take a look at this Fiddle link, this will help you create the slider in a cyclic way.If the slider reaches the last image it will start again from the first image.
var index = $selector.index();
if (index == (length - 1)) {
$('img').first().removeClass('invisible').addClass('visible');
}
I hope this will help you more. All the best.

You need to get to 0 after length-1.
One simple way to do that is to work modulo length:
_s.slide_active++;
_s.slide_active %= length;

not tested but hope helpful :
function slider(sel, intr , i){
...
this.count = this.selector.children().length;
this.run();
}
slider.prototype.run = function(){
var _s = this;
this.slide[this.slide_active].show();
setTimeout(function(){
_s.slide[_s.slide_active].hide()
if(_s.slide_active == this.count)
_s.slide_active = 0;
else
_s.slide_active++;
_s.run();
}, interval);
}

Related

How can I create a 'wheel of fortune' like effect

First let me describe the project I'm stuggeling with. English is not my foreign language so I do not know the exact name of the effect I am looking for.
Basicly I am creating a bingo type of game where the host can press on a button to start the bingo wheel. Eventually the wheel will stop and the word it has landed on is the chosen word for that round. After that, this word get removed from the game and the game starts over and over untill someone calls a bingo.
I started playing a bit around with some JSON data and how to remove the items from the array etc which is pretty easy to do. But now comes the part where I am struggeling the most. I have to create a kind of function that scrolls through all options like a wheel at a certain speed that eventually decreased in speed so it will land on the chosen word for this round. I created a fiddle with the code I currently have. Note that it's purely created for functionality instead of looks!
var json = {
"titles": [
"PLACEHOLDER_1",
"PLACEHOLDER_2",
"PLACEHOLDER_3",
"PLACEHOLDER_4",
"PLACEHOLDER_5",
"PLACEHOLDER_6",
"PLACEHOLDER_7",
"PLACEHOLDER_8",
"PLACEHOLDER_9",
"PLACEHOLDER_10",
"PLACEHOLDER_11",
"PLACEHOLDER_12",
"PLACEHOLDER_13",
"PLACEHOLDER_14",
"PLACEHOLDER_15"
]
}
$(document).ready(function() {
var app = new Bingo.init();
})
var Bingo = {
viewport: {
isMobile: 0,
isTablet: 0,
isDesktop: 1,
device: 'desktop',
browser: null
}
}
Bingo.init = function() {
Bingo.gameController.init();
};
Bingo.gameController = {
gameNames: {},
init: function() {
Bingo.gameController.general.saveJson();
$('.test').on('click', Bingo.gameController.array.pickRandomNumber)
},
general: {
saveJson: function() {
Bingo.gameController.gameNames = json.titles;
},
//General reset function
resetGame: function() {
Bingo.gameController.general.saveJson;
}
},
array: {
pickRandomNumber: function() {
//reset gamefield
Bingo.gameController.game.buildGame();
var gameNames = Bingo.gameController.gameNames;
var totalNames = gameNames.length;
//Pick a random number
var chosenNumber = Math.floor(Math.random() * totalNames);
Bingo.gameController.array.remove(chosenNumber)
},
remove: function(id) {
//remove chosen name from array
var gameNames = Bingo.gameController.gameNames;
var check = gameNames.indexOf(gameNames[id]);
Bingo.gameController.game.highlightName(id);
if (check != -1) {
gameNames.splice(check, 1);
Bingo.gameController.gameNames = gameNames;
}
}
},
game: {
buildGame: function() {
//build all the array entry's into the div
$('.page.main-game').empty();
var gameNames = Bingo.gameController.gameNames;
for (var i = 0; i < gameNames.length; i++) {
var item = '<div class="name-item" data-id="' + i + '">' + gameNames[i] + '</div>';
$('.page.main-game').append(item);
}
},
highlightName: function(id) {
//highlight the chosen number red
$('.name-item[data-id="' + id + '"]').css('color', 'red');
}
}
}
Fiddle link here
(I hope the link is correct, not using fiddle that much)
So now when you click on the 'play again' button you see that it wil highlight a word. What has to happen is when I press the play again button the red highlight has to go from the first div to the last and so forth untill it eventually stops at a div (which is chosen with the random number or something).
If someone can help me with this or could give me a hint in the right direction please let me know!
EXTRA: The app will eventually get a look like a scrollwheel that the iphone gets when you open a select box (hope you know what I am referring to). So thats why its a wheel of fortune-ish effect. If someone could provide me with the correct name for this let me know so I can adjust the title!
If any information is missing please let me know, i'd be happy to provide it! Thanks in regard!!
The basic ideas are (1) to keep the current index, so you can start the spin every time from that index, where 'spining' is just increasing that index or set to zero when reaching the maximal index; and (2) set a timeout for the next painting, and reduce that timeout everytime, until it's low enough.
JsFiddle Demo
HTML
<p><button onclick="w.spin(w.randomNext(), 8)">SPIN</button></p>
<ul id='wheel'>
<li>$100</li>
<li>$250,000</li>
<li>$25,000</li>
<li>$10,000</li>
<li>$1,000</li>
<li>$5</li>
<li>$2,000</li>
<li>30,000</li>
<li>$40</li>
</ul>
JavaScript
var wheelEl = document.getElementById('wheel');
function Wheel () {
this.current = 4;
}
Wheel.prototype.init = function () {
this.onItem();
}
Wheel.prototype.randomNext = function () {
return Math.floor(Math.random() * wheelEl.children.length);
}
Wheel.prototype.spin = function (next, itemsPerSecond) {
var timeout = setTimeout(onItem.bind(this), (1 / itemsPerSecond) * 1000);
function onItem () {
// stop if speed is low enough
if (itemsPerSecond < 1)
return;
// spin to next item
this.current ++;
if (this.current >= wheelEl.children.length)
this.current = 0;
// paint text
this.onItem();
// reduce speed
clearTimeout(timeout);
itemsPerSecond--;
timeout = setTimeout(onItem.bind(this), (1 / itemsPerSecond) * 1000);
}
}
// paints the index of this.current
Wheel.prototype.onItem = function () {
for (var i = 0 ; i < wheelEl.children.length ; i++)
wheelEl.children[i].style.color = (i == this.current) ? '#6d4321' : '#000000';
}
var w = new Wheel();
w.init();

GIFs changing randomly

I got a problem with GIFs and Javascript. I got different GIF-animations which are all the same format and I want them to change randomly after they are played one time.
I tried to solve this with Javascript but I only could make it work with an exact time to make the change and not when each GIF-animation is finished (they are all finishing at different times).
<html>
<head>
<script type="text/javascript">
<!--
var ima = [];
ima[0] = 'bilder/bild1.gif';
ima[1] = 'bilder/bild2.gif';
ima[2] = 'bilder/bild3.gif';
ima[3] = 'bilder/bild4.gif';
function BildWechsel()
{
var num = Math.random();
var ran = Math.floor((ima.length - 1) * num);
document.images['wechsel'].src = ima[ran];
}
onload = function ()
{
window.setInterval(function () { BildWechsel(); }, 10000);
}
//-->
</script>
</head>
<body>
<img id="wechsel" src="bilder/bild1.gif" border="0" alt="">
</body>
</html>
Is there any possibility to make this work? And if not in a browser, how else can you maybe make it work?
I would rewrite the Javascript like this:
window.onload = function () {
var images = [
{src:'bilder/bild1.gif',delay:3000},
{src:'bilder/bild2.gif',delay:2000},
{src:'bilder/bild3.gif',delay:1500},
{src:'bilder/bild4.gif',delay:4000}
],
element = document.images['wechsel'],
change_image = function () {
var image = images[ Math.floor( Math.random() * images.length ) ];
// (Math.random()*images.length)>>0 would be a lot faster
element.src = image.src;
setTimeout(change_image, image.delay);
};
setTimeout(change_image, 10000);
};
The delay would change based on the image you currently have.
This has a few speed improvements and the code is as simple as it can get.
This was untested!
Here is a (slightly) changed version to change the text color:
window.onload = function () {
var colors = [
{name:'red',delay:3000},
{name:'yellow',delay:1000},
{name:'green',delay:2300},
{name:'blue',delay:2600},
{name:'pink',delay:1300},
{name:'purple',delay:500},
],
element = document.getElementById('span'),
change_color = function () {
var color = colors[ ( Math.random() * colors.length )>>0 ];
element.style.color = color.name;
setTimeout(change_color, color.delay);
};
setTimeout(change_color, 2000);
};
<span id="span" style="background:black;font-family:sans-serif;font-size:20px;font-weight:bold;padding:10px;">I change color!</span>
Well, first off, there are many considerations here.
You first need to understand that you can have a multi-dimensional array consisting of a series of objects, instead of plain strings (which is what you have now).
I suggest you do some reading on this here: (take a look at Mozilla's Developer Network, or google for it).
Now, you cannot do that with an interval, because intervals happen at a preset, well, interval. You need a timeout - but timeouts happen only once.
You can see where this is going, right? So you need to call the timeout again once the previous timeout has finished - that goes to a concept of "callback" (google "javascript callbacks").
In any case, I've put up a very simple example for you in JSFiddle - it doesn't solve your problem 100%, because I think it would be cool if you'd put some thinking into how this all works, but this should get you at least something to work with (also on JSFiddle - http://jsfiddle.net/Nitrium/kyvbnxfv/)
imab = [];
imab[0] = {
image: 'bilder/bild1.gif',
time: 1000
}
imab[1] = {
image: 'bilder/bild2.gif',
time: 500
}
imab[2] = {
image: 'bilder/bild3.gif',
time: 2500
}
imab[3] = {
image: 'bilder/bild4.gif',
time: 100
}
function BildWechselB() {
var num = Math.random();
var ran = Math.floor((imab.length - 1) * num);
return imab[ran];
}
var interval;
function callBack (imageSrc) {
printImage(imageSrc);
clearInterval(interval);
var newRandomImage = BildWechselB();
interval = window.setTimeout(callBack, newRandomImage.time, newRandomImage.image)
}
function printImage (src) {
var imageSrc = document.createTextNode(src);
var bodyTag = document.getElementsByTagName('body');
bodyTag[0].appendChild(imageSrc);
}
var firstRandomImage = BildWechselB();
interval = window.setTimeout(callBack, firstRandomImage.time, firstRandomImage.image);
Hope it helps!

jQuery fade in box with unique content

I am making an info screen, and for that, it needs to show reviews from their customers pulled from Trustpilot.
I got the reviews and everything formatted in HTML showing the 20 latest, but I want to present it very sweet. I am not a JavaScript guru, but I thought i would do it using jQuery and its fadein function.
What is want, is have 20 unique divs fading in with X milliseconds difference popping randomly up. By unique I mean, that each div must have unique content. And by randomly popping up, I mean that if box 1 spawns first, then the next should be 5, then 14 etc, and then another cycle the next time around.
Just like what I made here;
$(function() {
var box = $('.box');
var delay = 100;
for (i = 0; i < 30; i++) {
setTimeout(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}
});
http://jsfiddle.net/CCawh/5/
Is this even possible, and how would this be done?
I am very new to JavaScript, so please bear with me if I ask to much
Thanks in advance.
EDIT:
The HTML i want to spawn will all be wrapped in divs, so it would go like this;
<div id="one">content</div>
<div id="two">content</div>
<div id="three">content</div>
<div id="four">content</div>
etc.
Made up a nice function for you. I believe this may be what you are looking for
Here's a rundown of how it works :
Populate an array with numbers randomly generated 1-10 in this case.
Run through that array with a set interval, and when everything has
been added stop the interval
pretty straightforward from there. Set the visibility etc. You should be able to change up the function to dynamically add HTML elements and what-not, but just giving you something to start with.
var usedNum = [];
var i, j, y;
i = 0;
for(y = 0; y < 10; y++){
var x = Math.floor((Math.random() * 10) + 1);
if(!isUsed(x)) usedNum.push(x);
else y--;
}
var showInterval = setInterval ( function(){
if(i == 10){
clearInterval(showInterval);
}
$(".container div[data-line='" + usedNum[i] + "']").css({opacity: 0.0, visibility: "visible"}).animate({opacity: 1.0});
i++;
}, 500);
function isUsed(num) {
var used = false;
for(j = 0; j < usedNum.length; j++){
if(usedNum[j] == num){
used = true;
}
}
return used;
}
Demo fiddle : http://jsfiddle.net/xS39F/3/
Edit:
You can also mess around with the speed of the animation. In this demo (http://jsfiddle.net/adjit/XYU34/1/) I set the speed to 1000 so the next element starts fading in before the last element was done fading in. Makes it look a little smoother.
Instead of using a for loop and setTimeout, would setInterval work better for what you need? Some HTML might help better understand what you're trying to achieve.
$(function() {
var box = $('.box');
var delay = 100;
var interval = setInterval(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}, delay);
});

Difficulty with setInterval loop using class of Divs

$(document).ready(function fadeIt() {
$("#cool_content > div").hide();
var sizeLoop = $("#cool_content > div").length;
var startLoop = 0;
$("#cool_content > div").first().eq(startLoop).fadeIn(500);
setInterval(function () {
$("#cool_content > div").eq(startLoop).fadeOut(1000);
if (startLoop == sizeLoop) {
startLoop = 0
} else {
startLoop++;
}
$("#cool_content > div").eq(startLoop).fadeIn(1500);
}, 2000);
});
Here I want a class of divs to animate, infinitely!
However, because the interval is set to two seconds there is period where no div is showing!
What would be an appropriate way to loop the animation of these divs?
I thought about using a for loop but couldn't figure out how to pass a class of divs as arguments. All your help is appreciated.
Thanks!
Ok, generally, you should know that Javascript is a single threaded environment. Along with this, the timer events are generally not on time accurately. I'm not sure how jQuery is doing fadeIn and fadeOut, but if it's not using CSS3 transitions, it's going to be using timeOut and Intervals. So basically, there's a lot of timer's going on.
If you go with the for loop on this one, you'd be blocking the single thread, so that's not the way to go forward. You'd have to do the fade in/out by yourself in the setInterval.
Setting the opacity on each interval call. Like div.css('opacity', (opacity -= 10) + '%')
If you're trying to fade in and out sequentially, I think maybe this code would help
var opacity = 100,
isFadingIn = false;
window.setInterval(function() {
if (isFadingIn) {
opacity += 10;
if (opacity === 100) isFadingIn = false;
} else {
opacity -= 10;
if (opacity === 0) isFadingIn = true;
}
$('#coolContent > div').css('opacity', opacity + '%');
}, 2000);
Consider the following JavaScript / jQuery:
$(function(){
var divs = $('#cool_content > div').hide();
var curDiv;
var counter = 0;
var doUpdate = function(){
// Hide any old div
if (curDiv)
curDiv.fadeOut(1000);
// Show the new div
curDiv = divs.eq(counter);
curDiv.fadeIn(1000);
// Increment the counter
counter = ++counter % divs.length;
};
doUpdate();
setInterval(doUpdate, 2000);
});
This loops infinitely through the divs. It's also more efficient than your code because it only queries the DOM for the list of divs once.
Update: Forked fiddle
instead of
if (startLoop == sizeLoop)
{
startLoop = 0
}
else
{
startLoop++;
}
use
startLoop =(startLoop+1)%sizeLoop;
Check the demo http://jsfiddle.net/JvdU9/ - 1st div is being animated just immediately after 4th disappears.
UPD:
Not sure I've undestood your question, but I'll try to answer :)
It doesn't matter how many divs you are being looped - 4, 5 or 10, since number of frames are being calculated automatically
x=(x+1)%n means that x will never be greater than n-1: x>=0 and x<n.
x=(x+1)%n is just shorten equivalent for
if(x<n-1)
x++;
else
x=0;
as for me first variant is much readable:)
And sorry, I gave you last time wrong demo. Correct one - http://jsfiddle.net/JvdU9/2/

Function not stopping when calling another one

I`m having a troubble with a simple thing.
I have an div, when clicked, an amination start (an infinite loop of images changing, simulating an animated gif).
But, when i click on the other div, the first one need to stop, and start just the other animation, and this goes on to every animation (will be 8 on total).
Here is the code for just one image loop:
var t1;
var t2;
var anim1 = new Array ('img/testes2/anim1_1.png','img/testes2/anim1_2.png');
var anim2 = new Array ('img/testes2/anim2_1.png','img/testes2/anim2_2.png');
var index = 1;
var verifica1 = 0;
var verifica2 = 0;
function rotateImage1(){
$('#imagemPrinc').fadeOut(0, function(){
$(this).attr('src', anim1[index]);
$(this).fadeIn(0, function(){
if (index == anim1.length-1){
index = 0;
}
else{
index++;
}
});
});
return false;
}
function stopTimer1(){
if(verifica1 = 1){
clearInterval(t2);
}
}
function muda1(){
if (verifica1 = 1){
//stopTimer2();
//$('#bgImagem').css({'background-image':'url(img/testes2/anim1_1.png)'});
t1 = setInterval(rotateImage1,500);
}
}
The same function for the second animation.
The verifica var, and the stopTimer function, i tried to make one stop, and just the other plays, but doesn't seems to be working. That's why it's commented on the code.
It will be easier to look the code running, so thats it ---HERE---
The clickable divs are those two Red Squares.
Someone can help me please!?
Thanks!
clearTimeout takes as argument the timer id returned by the setInterval function (here it's t1).
Instead of using fadeOut and fadeIn with a duration of 0, you should simply use hide and show.
As an aside, you can simplify this block :
if (index == anim1.length-1){
index = 0;
}
else{
index++;
}
in
index = [(index+1)%anim1.length];
And this is very wrong :
if(verifica1 = 1){
This is not a test : it always change verifica1 and is always true. You probably want ==.
Is there a point in your code where you (voluntarily) set verifica1 ?

Categories