I'm trying to make a random text effect kinda like the one at the end of the movie War Games (Matthew Broderick). The idea is to have individual letters change randomly when ever the user hovers over one of the letters in the word. Eventually after a short time the letter would end up being "decoded" meaning that it would end up on the right letter or number. I have built basic effect but the part I am struggling with is setting the timer. I want to create a small delay between the hover-out event and the actual display of the decoded character. When i add a settimeout however. The script breaks and seems to stack timers. I'm not sure what I'm doing wrong. Below is the code I've got so far.. any help would be great.
function setDecodedChar(object){
var decodedMessage = "HELLO WORLD";
var index = object.attr('class').substring(4);
console.log(index);
object.html(decodedMessage[index]);
}
function changeChar(object){
var randomchar = getrandomChar();
object.html(randomchar);
}
function getrandomChar(){
var char = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
char = possible.charAt(Math.floor(Math.random() * possible.length));
return char;
}
$(function() {
typesetting.letters('.title-text');
var target = $(".title-text").children();
console.log(target);
var timer;
var gate = true;
$(target).hover(function(){
var charChar = $(this);
//on hover-over
if(gate){
gate = false;
timer=setInterval(function(){
changeChar(charChar);
},100);
}
},function(){
//on hover-out
setTimeout(function(){ //<-- breaks here
clearInterval(timer)
setDecodedChar($(this));
},1000);
gate = true;
}
);
});
Here is a jsfiddle of the effect as I currently have it working. http://jsfiddle.net/thesnooker/htsS3/
I really like your idea, and I worked on it. I got it working.
First, here a fiddle : http://jsfiddle.net/htsS3/2/
I must say, i don't know if its the optimal way, but it still working!
The problem with you method is that you have 1 timer for every character, they override themselves, so some letters wont stop.
How i solve it:
I set the timer in the data of every letter like that :
$(this).data('timer', setInterval(function () {
changeChar(charChar);
}, 100));
Not every span have their own timer.
On hover out, i ad to save the $(this) reference into a `var since you lost it in the timeout. I alos saved the timeout into the data so i could stop it when you hover it and it's still changing. Well it look like that now :
var $this = $(this);
$this.data('timeout', setTimeout(function(){
clearInterval($this.data('timer'));
setDecodedChar($this);
},1000))
And finally, on hover, i had to clear timeout and interval:
clearInterval($(this).data('timer'));
clearTimeout($(this).data('timeout'));
Well, I find it hard to explain in my own word, so take a good look at the code and enjoy!
setsetTimeout(function(){ //<-- breaks here
clearInterval(timer)
setDecodedChar($(this));
},1000);
You have an extra 'set'
setTimeout(function(){ //<-- breaks here
clearInterval(timer)
setDecodedChar($(this));
},1000);
So the issue could be related to the timer. It changes every time the setInterval is called. If you were to store the interval on the hover object then clear it by using the stored reference it works.
Cool concept by the way.
$(function () {
var target = $(".text").children();
var timer;
$(target).hover(function () {
var charChar = $(this);
if($(this).data("timer") == void(0)) {
if($(this).data("timeout") != void(0)) {
clearTimeout($(this).data("timeout"));
}
$(this).data("timer", setInterval(function () {
changeChar(charChar);
}, 100));
}
}, function () {
//on hover-out
var timerObject = $(this);
timerObject.data("timeout", setTimeout(function() {
clearInterval(timerObject.data("timer"));
setDecodedChar(timerObject);
timerObject.removeData("timer");
}, 1000));
});
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.
Since people are misunderstanding my wording, I will rewrite it, I want "with the following code below" to ignore the function which i have commented on below in my jquery if it happened in the last "X" seconds.
Here is my code.
EDIT:: Please write answers in reference to this, example. "the script ignores the change in class and the delay wont work" http://www.w3schools.com/code/tryit.asp?filename=FBC4LK96GO6H
Sorry for confusing everyone including myself.
Edited due to author's post update.
You can create custon event. By this function you will define: "delayedClick" event on the selected objects.
function delayedClickable(selector, delayTime){
$(document).ready(function(){
$(selector).each(function () {
var lastTimeFired = 0;
$(this).click(function(){
if(Date.now() - delayTime > lastTimeFired) {
lastTimeFired = Date.now();
$(this).trigger('delayedClick');
}
});
});
});
}
Remeber that you should define delayTime and this event on selected elements by:
var delayTime = 3 * 1000; // 3 sec delay between firing action
delayedClickable('.Img2', delayTime);
And then just use your event on elements. For example click event can be used in that way:
$element.on('click', function () {
// ...
});
And your custom delayedClick event should be used in that way:
$element.on('delayedEvent', function () {
// ...
});
Full example:
http://www.w3schools.com/code/tryit.asp?filename=FBC56VJ9JCA5
#UPDATE
I've found some another tricky way to keep using click function and makes it works as expected:
function delayedClickable(selector, delayTime){
$(document).ready(function(){
$(selector).each(function () {
var scope = this;
$(this).click(function(){
scope.style.pointerEvents = 'none';
setTimeout(function () {
scope.style.pointerEvents = 'auto';
}, delayTime);
});
});
});
}
And then
var delayTime = 3 * 1000; // 3 sec delay between firing action
delayedClickable('.Img2', delayTime);
That's all.
The key of second way is that we are disabling any pointer event on element when clicked and then after timeout we're turning these events back to work.
https://developer.mozilla.org/en/docs/Web/CSS/pointer-events
And full example:
http://www.w3schools.com/code/tryit.asp?filename=FBC678H21H5F
Can use setTimeout() to change a flag variable and a conditional to check flag in the event handler
var allowClick = true,
delaySeconds = 5;
$(".element1").click(function(){
if(!allowClick){
return; // do nothing and don't proceed
}
allowClick = false;
setTimeout(function(){
allowClick = true;
}, delaySeconds * 1000 );
// other element operations
})
As the title suggests I'm stuck with a MouseDown problem.
What I want in "pseudocode"
While ("#arrowUp").mouseDown(function() {
counter++; //One time directly when pressed
if(MouseDownTime > 500){ //500ms that is
setTimeOut({counter++}, 75); //Meaning, every 75ms counter++
}
}
I have been looking around at Stack Overflow for over two days now. And I succeeded to increment every 75ms, but then I couldn't build in the if(MouseDownTime > 500)-statement, while still being able to increase the counter every 75ms after the 500ms.
$("#tempUp").mousedown(function() { //When longer pressed, automatically faster increase Temperature
int = setInterval(editTemp(currTemp+1), 250);
})
.mouseup(function() {
clearInterval(int);
numberOfRepeats = 0;
});
This is code I have of of my function so far. Could anyone help me out? Or am I asking the question in a wrong way? (non-constructive)
If I understand you correctly you can make use of a combination of setTimeout and setInterval, like so:
$(document).ready(function ()
{
var temp = 0;
var to = null;
var iv = null;
$("#ClickMe").on("mousedown", function ()
{
temp++;
$("#Temp").html(temp);
to = setTimeout(function ()
{
iv = setInterval(function ()
{
temp++;
$("#Temp").html(temp);
}, 75);
}, 500);
}).on("mouseup mouseleave", function ()
{
clearTimeout(to);
clearInterval(iv);
});
});
See this FIDDLE for an example.
EDIT: Added the mouseleave event as well as suggested by José F. Romaniello.
I'm using JS to animate two images by having them toggle on and off. I have an initial image which, when the animation is turned on, appears on the screen and stays on. The second image, which has a higher z value, is then set to toggle on and off every 1 second in the same location as the first image, so it appears as if the two are alternating.
I'm using window.setInterval to make the second image blink, but when I need to turn the animation off (and I'm removing both images from the screen), my window.clearInterval is not "working" The first image will be gone, but the second one keeps blinking on and off every second.
Code:
function notebookNotification(setting)
{
$("#lightNotificationContainer").show();
var notificationAnimation = window.setInterval('$("#darkNotificationContainer").toggle()', 1000);
if(setting == 0)
{
window.clearInterval(notificationAnimation);
$("#lightNotificationContainer").hide();
$("#darkNotificationContainer").hide();
}
}
Anyone see why it isn't working?
Reading between the lines, I think what you're saying is this:
You execute notebookNotification(1); and the animation starts
You execute notebookNotification(0); and the animation does not stop.
My guess is that you want notebookNotification(0) to disable the flashing.
In order to do that, you need to rework this function considerably. You need to store the intervalID that comes from setInterval in a variable that survives outside of the scope of this function and can be used for clearInterval on subsequent calls to this function.
For example:
var intervalID;
function notebookNotification(setting)
{
if(setting == 0)
{
if(intervalID) {
window.clearInterval(intervalID);
intervalID = null;
}
$("#lightNotificationContainer").hide();
$("#darkNotificationContainer").hide();
}
else
{
$("#lightNotificationContainer").show();
if(!intervalID) {
intervalID = window.setInterval('$("#darkNotificationContainer").toggle()', 1000);
}
}
}
Here, try this:
http://jsfiddle.net/WGxmy/
Saving the interval to a global variable -- not one inside a function -- lets you clear it later.
var keepflashing = true;
var isShowing = true;
function notebookNotification()
{
if(!isShowing)
$("#lightNotificationContainer").show();
else
$("#lightNotificationContainer").show();
isShowing = !isShowing;
if(keepflashing)
setTimeout( function(){ notebookNotification(setting); },100);
else
{
$("#lightNotificationContainer").hide();
$("#darkNotificationContainer").hide();
}
}
Maybe you can avoid calling clearInterval() generally?
function notebookNotification(setting)
{
if(setting == 0)
{
$("#lightNotificationContainer").hide();
$("#darkNotificationContainer").hide();
}
else
{
$("#lightNotificationContainer").show();
window.setInterval('$("#darkNotificationContainer").toggle()', 1000);
}
}
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);
}