I have added a text slideshow to a div that is called by JQuery on hover. How do I get the slideshow to start from the beginning each time the user hovers on the div? Right now it just continues to loop after the first time it is activated.
Thanks in advance!
<script>
$(document).ready(function(){
$('#mercury .infos').hover(
function () {
if($("a.active").is('.mercury')){
$("#descriptionls").fadeIn("2000");
};
var quotes = [
"Who’s the one who’s always there when that keeps happening?",
"Learn to dismantle self-defeating behaviors",
"JOIN THE FLOW TODAY",
];
var i = 0;
setInterval(function() {
$("#lstextslide").html(quotes[i]);
if (i == quotes.length)
i=0;
else
i++;
}, 1 * 4000);
});
});
</script>
You have to cancel the previous interval and call the function that updates the HTML immediately. See http://jsfiddle.net/xozL96fj/
$(document).ready(function(){
var intervalTimer = null;
$('#mercury .infos').hover(
function () {
if($("a.active").is('.mercury')){
$("#descriptionls").fadeIn("2000");
}
if (intervalTimer !== null) {
clearInterval(intervalTimer);
}
var quotes = [
"Who’s the one who’s always there when that keeps happening?",
"Learn to dismantle self-defeating behaviors",
"JOIN THE FLOW TODAY",
];
var i = 0;
function update() {
$("#lstextslide").html(quotes[i]);
i = (i + 1) % quotes.length;
}
// Call it immediately, don't wait until the interval
update();
intervalTimer = setInterval(update, 4000);
});
});
You need to make a check if your slider has already been activated. If you hover over your slider when the slider is already active, you will have to reset $i, and call setInterval() again.
Related
I have this function to blink text in a button "AddMoney" :-
function blinker1(){
document.getElementById("AddMoney").value="Add Money";
setTimeout("document.getElementById('AddMoney').value=' '", 500);
xxxx = setTimeout("blinker1()",1500);
}
And I stop it and set the text with this function:-
function cease1() {
clearTimeout(xxxx);
document.getElementById("AddMoney").value="Add Money";
}
It works but now and again there is no text in the button.
Anyone Know why and how to fix.
Now and again there is no text in the button. Anyone Know why?
It happens whenever cease1() is called while setTimeout("document.getElementById('AddMoney').value=' '",500) is still scheduled, which happens on average every third time. In that case, the blinker1() timeout is cancelled and the content is shown, but shortly after it will be hidden again.
… and how to fix?
You'll have to cancel both timeouts:
var timerA, timerB;
function blinker() {
document.getElementById("AddMoney").value = "Add Money";
timerA = setTimeout(function() {
document.getElementById('AddMoney').value = "";
}, 500);
timerB = setTimeout(blinker1, 1500);
}
function cease1() {
clearTimeout(timerA);
clearTimeout(timerB);
document.getElementById("AddMoney").value = "Add Money";
}
Alternatively, use two functions that are mutually scheduling each other so that only one timer is active at a time:
var timer;
function blinkerA() {
document.getElementById("AddMoney").value = "Add Money";
timer = setTimeout(blinkerB, 500);
}
function blinkerB() {
document.getElementById('AddMoney').value = "";
timer = setTimeout(blinkerA, 1000);
}
function cease1() {
clearTimeout(timer);
document.getElementById("AddMoney").value = "Add Money";
}
This version should work a bit better for you. I stuck with vanilla Javascript rather the introducing jQuery:
Fiddle
var blink = window.setInterval(blinker1, 900)
function blinker1() {
var addMoney = document.getElementById("addMoney");
addMoney.innerHTML = " ";
setTimeout(function(){addMoney.innerHTML = "ADD MONEY"}, 300);
}
document.getElementById('stop').addEventListener('click', function(){
clearInterval(blink);
})
Note - it would be better and easier to achieve a blink effect using pure CSS.
The text disappears because you only set clearTimeout on xxxx, so the timeout for setTimeout("document.getElementById('AddMoney').value=' '", 500); will always execute. I think this is the reason why there is no text in the button.
My approach would be to set a counter, let say the text need to blink 10 times (based on your code it will take 15sec.) Each time when the text shown the counter will decrease until it reaches 0.
sample code (https://jsfiddle.net/2trodftu/1/)
//counter
var blinkCounter = 10;
// blink method
function blink() {
document.getElementById("AddMoney").value="Add Money";
if (blinkCounter > 0) {
setTimeout("document.getElementById('AddMoney').value=' '", 500);
setTimeout(blink,1500);
}
blinkCounter = blinkCounter - 1;
}
//initializer
blink();
Hope this helps.
Here is a code that should open and close my site's menu. The menu is divided to divs and each one is timed to enter the screen after the other.
<script type="text/javascript">
var s=0;
function menuOpen() {
if (s==0){
document.getElementById("menu_icon").src = "x.png";
document.getElementById("nav_menu").style.zIndex = "3";
$('.box-wrapper').each(function(index, element) {
setTimeout(function(){
element.classList.remove('loading');
}, index * 100);
});
s++;
} else {
document.getElementById("menu_icon").src = "menu_icon.png";
$('.box-wrapper').each(function(index, element) {
setTimeout(function(){
element.classList.add('loading');
}, index * 100);
});
s=0;
// how to make this part run after the menu has finished folding?
setTimeout(function(){
document.getElementById("nav_menu").style.zIndex = "1";
}, 1500);
}
}
</script>
The content of the page is at z-index 2. The menu when folded is at 1 and when open at 3.
Is there a way to run the command moving the menu to z-index 1 after the menu has finished folding completely?
Currently what I did was to time the animation (1600ms) and use setTimeout. But this timing will change if I'll add more lines to my menu or if someone is clicking rapidly on the menu icon.
I'm rather new to JS and Jquery so go easy on me (:
Thanks of your help.
Below you can find the code and link to jsfiddle. Unfortunetly jsfiddle blocks the animate method for unknown reason so I don't debug, but even if it code will not work :))) I hope you will cathch the idea. And also some explanation.
Firstly our items are hidden. There are two functions displayMenu and hideMenu, they are similar, but display - run animations from the top invisible, and hide - start hide items from the bottom visible. To prevent mess I use two flags and two classes, first openFlag it is say what animations should be played now. Our hide and display functions are recursive and after they end current animation(hide or show) they check openFlag, and play next hide/show or start another chain of hide/show functions. It is the most difficult to understand part) But important that with it you can click as many times as you want and all would be fine and would be never broken by clicks.
Two classes we use as animation-chain can change behaviour and we need the way to choose items that alredy visible or hidden, so this why after each animation we set only one of this classes and remove another.
Now there is one problem if all animation are ended when we click button we should start new chain of animations, but if chain has been already started we need just to switch openFlag, and when current animation stops, it will change the behaviour. So this is the reason for btnFlag it is 1 if no active chain-animations at this moment.
After the last execution of element of animation-chain it will call callback arg, that you should pass, also at this moment will set btnFlag to 0, that means that animation-chain stopped. The openFlag as you remember changed at moment og click.
function end() {
console.log("here you can set zIndex");
}
var openFlag = 0; //become 1 after we start open elems
var btnFlag = 1;
$(document).ready(function() {
$('.toggleMenu').click(function() {
if (!$('.menuBlocks').hasClass('visible')) {
if (openFlag == 0) {
openFlag = 1;
if (btnFlag) {
var items = $('.invisibleItem');
var amount = items.length;
displayMenu(0, amount, items, end);
}
}
} else {
openFlag = 0;
if (btnFlag) {
var items = $('.visibleItem');
var amount = items.length;
hideMenu(amount - 1, items, end);
}
}
});
});
function displayMenu(i, amount, items, callback) {
if (i < amount && openFlag) {
items[i].animate({
"width": "100px"
}, 1000, function() {
items[i].removeClass('invisibleItem');
items[i].addClass('visibleItem');
displayMenu(i + 1, amount, items);
});
} else if (!openFlag) {
var items = $('.visibleItem');
var amount = items.length;
hideMenu(amount - 1, items, makeToggleVisible);
} else {
btnFlag = 1; //all aniimations ended
callback();
}
}
function hideMenu(i, items, callback) {
if (i < 0 && openFlag) {
items[i].animate({
"width": "0px"
}, 1000, function() {
items[i].removeClass('visibleItem');
items[i].addClass('invisibleItem');
hideMenu(i - 1, amount, items);
});
} else if (!openFlag) {
var items = $('.invisibleItem');
var amount = items.length;
displayMenu(0, amount, items, makeToggleVisible);
} else {
btnFlag = 1; //all animations are ended
callback();
}
}
https://jsfiddle.net/ShinShil/nrtyshv5/4/
Ok fixed it.
I moved everything to jquery. Used animate and promise.
This is what came out at the end. It is a side menu that will open it's li elements one-by-one.
var s=0;
var navMenu = document.getElementById("nav_menu");
var navBtn = document.getElementById("btn");
$(document).ready(function(){
$("button").click(function(){
if (s==0) {
navMenu.style.zIndex = "4";
navBtn.classList.add('close');
$('ul').each(function() {
$(this).children().each(function(i) {
$(this).delay(i * 100).animate({left:0});
});
});
$( "li" ).promise().done(function() {
navMenu.style.zIndex = "4";
});
s++;
}
else {
navBtn.classList.remove('close');
$('ul').each(function() {
$(this).children().each(function(i) {
$(this).delay(i * 100).animate({left:"100%"});
});
});
s=0;
$( "li" ).promise().done(function() {
navMenu.style.zIndex = "1";
});
}
});
});
and with CSS transitions.
var s=0;
function menuOpen() {
if (s==0){
document.getElementById("menu_icon").src = "x.png";
document.getElementById("nav_menu").style.zIndex = "3";
$('.box-wrapper').each(function(index, element) {
setTimeout(function(){
element.classList.remove('loading');
}, index * 100);
});
s++;
$("#last").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
document.getElementById("nav_menu").style.zIndex = "3";
});
} else {
document.getElementById("menu_icon").src = "menu_icon.png";
$('.box-wrapper').each(function(index, element) {
setTimeout(function(){
element.classList.add('loading');
}, index * 100);
});
s=0;
$("#last").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
document.getElementById("nav_menu").style.zIndex = "1";
$("#nav_menu").scrollTop(0);
});
}
}
I have a setInterval on a function X that runs every 500ms. In this function X, I call another function Y that essentially binds an event on some divs. However, I would like to unbind these events the next time the function X is called (to start "fresh"). My code doesn't seem to work:
setInterval(this.board.updateBoard, 500); //called from another constructor
This then initiates the functions below:
Board.prototype.updateBoard = function() {
//I attempt to unbind ALL my divs
var divs = this.$el.find("div");
for(var i = 0; i < divs.length; i++) {
$(divs[i]).unbind(); //Apparently this doesn't work?
}
//...some code here...
//find appropriate $div's (multiple of them), and then calls this.beginWalking() below on each of those
//loop here
this.beginWalking($div, direction + "0", direction + "1");
//end of loop
}
//alternate between classes to give appearance of walking
Board.prototype.beginWalking = function ($div, dir0, dir1) {
return setInterval(function () {
if ($div.hasClass(dir0)) {
$div.removeClass(dir0);
$div.addClass(dir1);
} else {
$div.removeClass(dir1);
$div.addClass(dir0);
}
}.bind(this), 80);
};
Basically, updateBoard is called every 500ms. Each time it's called, beginWalking is called to set another interval on a div. The purpose of this other interval, which functions correctly, is to add and remove a class every 80ms. I just can't seem to unbind everything before the next updateBoard is called.
Any suggestions appreciated!
use clearInterval()
edit: $(selector).toggleClass(dir0) might also be helpful
// In other file, use a global (no var) if you need to read it from another file:
updaterGlobal = setInterval(this.board.updateBoard, 500);
// store interval references for clearing:
var updaterLocals = [];
Board.prototype.updateBoard = function() {
//I attempt to unbind ALL my divs
var divs = this.$el.find("div");
// Stop existing div timers:
while(updaterLocals.length > 0){
clearInterval(updaterLocals[0]);
updaterLocals.shift(); // remove the first timer
}
//...some code here...
//loop here to call the below on several $div's
this.beginWalking($div, direction + "0", direction + "1");
//end of loop
}
//alternate between classes to give appearance of walking
Board.prototype.beginWalking = function ($div, dir0, dir1) {
var interval = setInterval(function () {
if ($div.hasClass(dir0)) {
$div.removeClass(dir0);
$div.addClass(dir1);
} else {
$div.removeClass(dir1);
$div.addClass(dir0);
}
}.bind(this), 80);
// Save the timer:
updaterLocals.push(interval);
return;
};
Please take a look at this function:
var msgdiv, i=0;
msgdiv=$("#message");
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(messages, div){
while(i<messages.length){
div.fadeOut(1000).html('').append(messages[i]).fadeIn(1000);
i=i+1;
}
}
fadeMessages(messages,msgdiv);
What I want to do is, to show one by one elements of array. But, function above shows only last element of array messages.length time. Where I did wrong?
Live example: http://jsfiddle.net/QQy6X/
The while executes much much faster than the fadeOut/fadeIn calls, so you only see the last result. You need to make each animation wait for the previous ones to finish.
I like to solve these problems recursively. Note, it does alter the messages array, but it's not too hard to convert this to use a counter instead (like your original version). Here you go:
var $msgdiv = $('#message'),
messages = ['Xoş gəlmişsiniz!', 'Welcome!', 'Добро пожаловать!'];
function showNext() {
var msg = messages.shift();
if (msg) {
$msgdiv.fadeOut(1000, function () {
$(this).text(msg).fadeIn(1000, showNext);
});
}
}
showNext();
Demo: http://jsfiddle.net/mattball/Exj95/
Here's a version that leaves messages intact:
var $msgdiv = $('#message'),
messages = ['Xoş gəlmişsiniz!', 'Welcome!', 'Добро пожаловать!'],
i = 0;
function showNext() {
if (i < messages.length) {
var msg = messages[i];
$msgdiv.fadeOut(1000, function () {
i++;
$(this).text(msg).fadeIn(1000, showNext);
});
}
}
showNext();
Demo: http://jsfiddle.net/mattball/wALfP/
Your while loop finishes executing before the div has had a chance to fade out. Use an if statement and recursion:
var msgdiv = $("#message");
var i = 0;
var messages = ["Welcome!", "Добро пожаловать!"];
(function fadeMessages() {
if (i in messages) {
msgdiv.fadeOut(1000, function() {
$(this).html('').append(messages[i++]).fadeIn(1000, fadeMessages);
});
}
})();
http://jsfiddle.net/QQy6X/6/
Your while loop finishes very quickly; instead you should wait for the animation to finish before starting the next one. This is easy to do by adding a callback function to fadeIn. I would use this:
+function(){
var $msgdiv = $("#message");
var i = -1;
var messages = ["Xoş gəlmişsiniz!","Welcome!","Добро пожаловать!"];
+function fadeNext(){
$msgdiv.fadeOut(1000, function(){
$msgdiv.text(messages[i = (i + 1) % messages.length]);
$msgdiv.fadeIn(1000, fadeNext);
});
}();
}();
http://jsfiddle.net/Paulpro/QQy6X/7/
In jQuery, you can't intertwine animations and non-animations in the way you are doing and expect them to run in the right order. The animations will go into the animation queue and get sequenced one after another there, but the non-animations will all run immediately. Thus, things won't happen in the right order.
To do something like you want to do, you can use code like this.
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(msgs, div) {
var i = 0;
function next() {
if (i < msgs.length) {
div.fadeOut(1000, function() {
div.html(msgs[i++]).fadeIn(1000, next);
});
}
}
next();
}
fadeMesssages(messages, div);
This uses the completion functions of both fadeIn() and fadeOut() to carry out the next steps. Here's how it works:
It fades out the div.
In the completion function of the fadeOut, it sets the next message and then starts the fadeIn.
It advances the message counter.
In the completion function from the fadeIn, it calls the function to start the next iteration.
If you want a delay before the fadeOut (to make sure a given message displays for a certain amount of time), you can add that with this .delay(2000) added in the right place:
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(msgs, div) {
var i = 0;
function next() {
if (i < msgs.length) {
div.delay(2000).fadeOut(1000, function() {
div.html(msgs[i++]).fadeIn(1000, next);
});
}
}
next();
}
fadeMesssages(messages, div);
If you want a delay before the next iteration starts, you can do that like this with a setTimeout:
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(msgs, div) {
var i = 0;
function next() {
if (i < msgs.length) {
div.fadeOut(1000, function() {
div.html(msgs[i++]).fadeIn(1000, function() {
setTimeout(next, 2000);
});
});
}
}
next();
}
fadeMesssages(messages, div);
hey, how can I have my download link hidden, and make a count down type thing. Maybe have it count down from 10 and once it's done that have the download link appear, it would be best to do it in js right?
does anyone know how to do this? :D
Thanks
Complete example:
<span id="countdown"></span>
<a id="download_link" href="download.zip" style="display:none;">Download</a>
<noscript>JavaScript needs to be enabled in order to be able to download.</noscript>
<script type="application/javascript">
(function(){
var message = "%d seconds before download link appears";
// seconds before download link becomes visible
var count = 10;
var countdown_element = document.getElementById("countdown");
var download_link = document.getElementById("download_link");
var timer = setInterval(function(){
// if countdown equals 0, the next condition will evaluate to false and the else-construct will be executed
if (count) {
// display text
countdown_element.innerHTML = "You have to wait %d seconds.".replace("%d", count);
// decrease counter
count--;
} else {
// stop timer
clearInterval(timer);
// hide countdown
countdown_element.style.display = "none";
// show download link
download_link.style.display = "";
}
}, 1000);
})();
</script>
You can use setInterval for this. setInterval behaves like a timer, where you can run a certain function periodically. Something like this should do the work(untested):
$(".link").hide();
var iteration = 0;
var timer = setInterval(function() {
if(iteration++ >= 10) {
clearTimeout(timer);
$(".link").show();
$(".counter").hide();
}
$(".counter").text(10 - iteration);
}, 1000);
This will initially hide the download link and run a function every second which counts down from 10. When we reaced ten, we hide the counter and show the link. ClearTimeout is used so that we don't count after we reached ten. Easy as dell.
Edit: As mentioned in the comments, this function is using jQuery to find the elements.
Take a look at the setTimeout function. You can do something like:
function displayLink() {
document.getElementById('link_id').style.display = 'block';
}
setTimeout(displayLink, 10000);
var WAIT_FOR_SECONDS = 10;
var DOWNLOAD_BUTTON_ID = "btnDownload";
if (document.body.addEventListener) {
document.body.addEventListener("load", displayDownloadButton, false);
} else {
document.body.onload = displayDownloadButton;
}
function displayDownloadButton(event) {
setTimeout(function() {
_e(DOWNLOAD_BUTTON_ID).style.display = "";
}, WAIT_FOR_SECONDS*1000);
}
function _e(id) {
return document.getElementById(id);
}