i created a countdown feature where it only counts if the user is in the current window of the browser, and it works very well, the only problem is when i insert my code in angularjs controller. It stops working, above i leave my code to everybody have a idea what is wrong.
js:
var span = angular.element('#count');
var counter = 30;
var timer;
var startTimer = function() {
// do nothing if timer is already running
if (timer) return;
timer = setInterval(function() {
counter--;
if (counter >= 0) {
span.innerHTML = counter;
}
// Display 'counter' wherever you want to display it.
if (counter === 0) {
alert('this is where it happens');
stopTimer();
}
}, 1000);
};
var stopTimer = function() {
clearInterval(timer);
timer = null;
};
var onBlur = function() {
stopTimer();
};
var onFocus = function() {
startTimer();
};
var onLoad = function() {
startTimer();
};
angular.element(window).load(onLoad);
angular.element(window).blur(onBlur);
angular.element(window).focus(onFocus);
html:
<a class="btn btn-medium btn-orange" href="">
In<span id="count">30</span></a>
Don't use non angular functions like setTimeout or setInterval inside angular code. These functions won't be part of the digest cycle and your view won't change.
Take a look at this example for creating a timer with angular.
https://codeforgeek.com/2014/09/refresh-div-angularjs-interval/
Related
I'm trying to create a function that on the click of a button will start a loop through each function with a 5 second delay between each and loop infinitely until the button is clicked again. I'm close with this, but after 5 seconds, it only just executes the last function in the set (tuesday) and does not iterate through them with a delay between each.
function links() {
safety
daily
monday
tuesday
}
var intervalId;
function toggleIntervalb() {
if (!intervalId) {
intervalId = setTimeout(links, 5000);
} else {
clearInterval(intervalId);
intervalId = null;
}
}
function safety(){
document.getElementById("fires").style.display = 'none';
document.getElementById("safety").style.display = 'block';
document.getElementById("daily").style.display = 'none';
document.getElementById("monday").style.display = 'none';
document.getElementById("tuesday").style.display = 'none';
}
function daily(){
document.getElementById("fires").style.display = 'none';
document.getElementById("safety").style.display = 'none';
document.getElementById("daily").style.display = 'block';
document.getElementById("monday").style.display = 'none';
document.getElementById("tuesday").style.display = 'none';
}
function monday(){
document.getElementById("fires").style.display = 'none';
document.getElementById("safety").style.display = 'none';
document.getElementById("daily").style.display = 'none';
document.getElementById("monday").style.display = 'block';
document.getElementById("tuesday").style.display = 'none';
function tuesday(){
document.getElementById("fires").style.display = 'none';
document.getElementById("safety").style.display = 'none';
document.getElementById("daily").style.display = 'none';
document.getElementById("monday").style.display = 'none';
document.getElementById("tuesday").style.display = 'block';
**2nd Attempt:
Closer with this (includes button)
New to jsfiddle - can't make my code work here: https://jsfiddle.net/unqrhxtp/16
So, I am also including the pastebin (save as .html and open): https://pastebin.com/EwHVqmHJ
Currently, the code stops after executing the first function. It appears to loop on the first element only (if you click another link manually, it forces back to the first function in the set).
Thanks in advance.
Changing this line:
intervalId = setTimeout(links, 5000);
from a setTimeout to a setInterval will probably fix that
intervalId = setInterval(links, 5000);
Update
After reading your updated question I think something like this will solve your problem:
// Gather functions in an array, easier to loop trough
var links = [
safety,
daily,
monday,
tuesday,
wednesday,
thursday
]
function cyclelinks() {
links.forEach(function(link, index) {
var delay = index * 5000;
var fn = links[index];
setTimeout(fn, delay)
});
}
var intervalId;
function toggleInterval() {
var btn = document.getElementById("logo");
if (!intervalId) {
var delay = links.length * 5000; // repeat after all functions are called with 5 sec delay
cyclelinks()
intervalId = setInterval(cyclelinks, delay);
} else {
clearInterval(intervalId);
intervalId = null;
location.reload();
}
}
You should use setInterval because setTimeout runs after gived time means it works correctly because. If you run this code step by step then you can see what i am saying. When cursor on the settimeout your functions doesnt work immediately it will wait 5 secs.
I hope i could help
I managed to come up with a solution, although I'm not totally happy with it. Mostly because it forces me to wait a full 90 seconds before the looping starts. For now, this will do, but I'll leave this open in hopes someone will post a better solution.
//Loop through links upon click
function cyclelinks() {
setTimeout(safety, 10000);
setTimeout(daily, 20000);
setTimeout(monday, 30000);
setTimeout(tuesday, 40000);
setTimeout(wednesday, 50000);
setTimeout(thursday, 60000);
}
var intervalId;
function toggleInterval() {
var btn = document.getElementById("logo");
if (!intervalId) {
intervalId = setInterval(cyclelinks, 90000);
} else {
clearInterval(intervalId);
intervalId = null;
location.reload();
}
}
This question already has answers here:
How can I use setInterval and clearInterval?
(5 answers)
Closed 8 years ago.
http://jsfiddle.net/x5MY8/2/
HTML
<div id="easy">easy</div>
<div id="hard">hard</div>
JS
function test(mode) {
var asd = this;
this.mode = mode;
setInterval(function () {
alert(asd.mode);
}, 1000);
}
$(document).ready(function () {
$('#easy').on('click', function () {
var stuff = new test('easy');
});
$('#hard').on('click', function () {
var stuff = new test('hard');
});
});
Upon pressing the easy button, an event launches that alerts easy every second. If I press hard afterwards, it will start another event, and it will alert easy, hard, easy, hard.., but I want it to alert only what was pressed at the moment, so I have to clear the previous interval somehow. How can I do that? Somehow, I need to call clearInterval when a button is pressed on the other object, but I don't really know how to.
http://jsfiddle.net/x5MY8/3/
You need to store and clear the interval like so
var interval;
function test(mode) {
var asd = this;
this.mode = mode;
if (interval) {
clearInterval(interval);
}
interval = setInterval(function () {
alert(asd.mode);
}, 1000);
}
Store it in a variable:
var interval = setInterval(function(){
//your code
},1000);
Now, you can clear using clearInterval:
clearInterval(interval);
clear the value when every clicked
var clear=0;
function test(mode) {
var asd = this;
this.mode = mode;
clear=setInterval(function () {
alert(asd.mode);
}, 1000);
}
$(document).ready(function () {
$('#easy').on('click', function () {
clearInterval(clear);
var stuff = new test('easy');
});
$('#hard').on('click', function () {
clearInterval(clear);
var stuff = new test('hard');
});
});
I'm looking for a way to trigger an event for every 2 minutes when you are typing, in any input or textarea.
If you then stops typing, the event will happen one more time, in the remaining time of the 2 minutes. (Hope you understand)
It is very much the same function as the one WordPress are using, when a draft is autosaved once per minute.
I am no Wordpress expert, so I can't find the function they are using in their scripts.
This is what I've got so far:
$("input, textarea").keyup(function () {
var minutes = 2;
var time = minutes * 60000;
setInterval(function () {
// Do event here
}, time);
});
It doesn't work that well. If you are typing many characters the event will be triggered multiple times right after each others. Also the event is triggered even if you are clicking on Ctrl, the arrow keys..... which is not intended.
Fiddle Demo
And I can't seem to find a good way to detect, when a user has stopped typing.
I've found this code, but I don't know how to use it, along with the other code I'm using:
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
//on keyup, start the countdown
$('#myInput').keyup(function(){
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('#myInput').keydown(function(){
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
Can someone please help me?
You should not use setInterval but setTimout and spawn a new one only after the first has been run..
var saveTimer = null,
minutes = 2,
time = minutes*60000;
$("input, textarea").keyup(function () {
if (!saveTimer){
saveTimer = setTimeout(function() {
alert("Hello");
saveTimer = null;
}, time);
}
});
Demo at http://jsfiddle.net/gaby/h9pe3/
You could set a boolean to check for new user input like I did in this fiddle
var hasTyped = false;
$("input, textarea").keyup(function () {
hasTyped = true;
});
var minutes = 0.1;
var time = minutes*60000;
setInterval(function() {
if(hasTyped){
alert("Hello");
hasTyped = false;
}
}, time);
The other code you posted works a bit different: instead of running every 2 minutes, it will run 5 seconds after you stopped typing. For autosave this would be a good solution as well, depending on your preference.
You need something called time based event throttling.
Demo on http://jsfiddle.net/Gobie/LUv2u/
// taken from Remy Sharp's page
function throttle(fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last,
deferTimer;
return function () {
var context = scope || this;
var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
}
// actual code
var interval = 2 * 60 * 1000; // 2min
$("input, textarea").keyup(throttle(function () {
console.log(new Date);
}, interval));
Edit http://jsfiddle.net/Varinder/RWBYH/2/
//setup before functions
var typingTimer = null; //timer identifier
var doneTypingInterval = 2000; //time in ms, 2 second for example
//on keyup, start the countdown
$('input').keyup(function(){
clearTimeout(typingTimer); // clearing timer
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('input').keydown(function(){
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping() {
alert("Saving draft");
}
The sample code provided works just fine: http://jsfiddle.net/Varinder/RWBYH/1/
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
//on keyup, start the countdown
$('input, textarea').keyup(function(){
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('input, textarea').keydown(function(){
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
alert("Saving draft");
}
First we want to be able to tell if the user is typing or he as stopped. We can do that by checking every couple of seconds when the last key stroke was. If it's been, let's say 30sec. since the last one we can assume that he's not typing. The second interval will autosave every two minutes and if the user is not typing anymore it will clear itself.
var isTyping = false;
var lastKeystroke = null;
var autosaveInterval = null;
$('#myInput').keyup(function() {
lastKeystroke = Date.now();
if (autosaveInterval == null) {
startAutosaveInterval();
}
});
setInterval(function() {
if (Date.now() - lastKeystroke > 30000) { // 30 sec. since last key stroke
isTyping = false;
} else {
isTyping = true;
}
}, 2000);
function startAutosaveInterval() {
autosaveInterval = setInterval(function() {
// do whatever
if (!isTyping) {
clearInterval(autosaveInterval);
autosaveInterval = null;
}
}, 2 * 60 * 1000); // every two minutes
}
I have not tested this code. but you should be able to take it from here.
just need a little help here. My problem is, how can I count the seconds when i hover a specific element. Like for example when I hover a button, how can i count the seconds did i stayed in that button after I mouseout?
An alternate solution using setInterval. DEMO HERE
var counter = 0;
var myInterval =null;
$(document).ready(function(){
$("div").hover(function(e){
counter = 0;
myInterval = setInterval(function () {
++counter;
}, 1000);
},function(e){
clearInterval(myInterval);
alert(counter);
});
});
A simple example
var timer;
// Bind the mouseover and mouseleave events
$('button').on({
mouseover: function() {
// set the variable to the current time
timer = Date.now();
},
mouseleave: function() {
// get the difference
timer = Date.now() - timer;
console.log( parseFloat(timer/1000) + " seconds");
timer = null;
}
});
Check Fiddle
How about this quick plugin I just knocked out, which will work on multiple elements, and without using any global variables:
(function($) {
$.fn.hoverTimer = function() {
return this.on({
'mouseenter.timer': function(ev) {
$(this).data('enter', ev.timeStamp);
},
'mouseleave.timer': function(ev) {
var enter = $(this).data('enter');
if (enter) {
console.log(this, ev.timeStamp - enter);
}
}
});
};
})(jQuery);
Actually disabling the functionality is left as an exercise for the reader ;-)
Demo at http://jsfiddle.net/alnitak/r9XkX/
IMHO, anything using a timer for this is a poor implementation. It's perfectly trivial to record the time without needing to use an (inaccurate) timer event to "count" seconds. Heck, the event object even has the current time in it, as used above.
This is exam:
var begin = 0;
var end = 0;
$('#btn').hover(function () {
begin = new Date().getTime();
});
$('#btn').leave(function () {
end = new Date().getTime();
sec = (end - begin) / 1000;
alert(sec);
});
One way to go about it would be the event.timeStamp method :
var initial_hover, exit_hover;
$('#ele').hover(
function(event){
initial_hover = event.timeStamp
console.log(initial_hover);
},
function(event){
exit_hover = event.timeStamp
$(this).html(exit_hover - initial_hover);
console.log(exit_hover);
}
);
jsfiddle
You've tagged the question with JQuery, so here's a jQuery solution.
$(element).on('mouseover', function(e){
$(e.target).data('hover-start', new Date().getTime());
});
$(element).on('mouseout', function(e){
// count the difference
var difference = new Date().getTime() - $(e.target).data('hover-start');
// clean up the data
$(e.target).data('hover-start', undefined);
console.log('Mouse was over for', difference/1000, 'seconds');
});
use setInterval and store value in variable. call the function on mouserover.
function mouseover(){
var start = 0;
setInterval(function(){
start++;
var count = start;
}, 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);
}