Infinite self invoking function - javascript

I am working on a piece of code that is supposed to randomly display a view count on my site. It all works fine, except that it only runs once on page load. Its supposed to change the view count every 10 seconds after the initial first run. E.g. run this code snippet every 10 seconds after page load. I have tried multiple ways with setInterval but found that it is supposedly bad practice to use anyways after so many failed attempts?
Could you guys point me in the right direction. I have been reading posts on Stack overflow for hours and none had an answer to my issue. I have a feeling, that I am overlooking something obvious here.
document.addEventListener('page:loaded', function() { //// Page has loaded and theme assets are ready
(function() {
var f = function() {
document.addEventListener('DOMContentLoaded', function() {
// Minimum view count
var minViews = 2;
// Maximum view count
var maxViews = 20;
// Text to show after the view count number
var text = 'people are viewing this product right now.';
// Create the new element to display on the page
$(".view-count").get().forEach(function(entry, index, array) {
var $viewCountElement = Math.floor(Math.random() * (maxViews - minViews) + minViews) + ' ' + text;
$(entry).html($viewCountElement);
});
});
};
window.setInterval(f, 10000); //10 sec interval
f();
})();
});

You may not need nested event listener. You can just call the setInterval in the call back function of DOMContentLoaded.
function elementDisplay() {
// Minimum view count
var minViews = 2;
// Maximum view count
var maxViews = 20;
// Text to show after the view count number
var text = 'people are viewing this product right now.';
// Create the new element to display on the page
$(".view-count").get().forEach(function(entry, index, array) {
var $viewCountElement = Math.floor(Math.random() * (maxViews - minViews) + minViews) + ' ' + text;
$(entry).html($viewCountElement);
});
}
document.addEventListener('DOMContentLoaded', function() {
window.setInterval(elementDisplay, 10000); //10 sec interval
});

setInterval is a browser based API, zo it should be cleaned up from the browser properly.
This is majorly for your proper implementation of setInterval. You can add your listeners, too.
FYI: jQuery.ready/DOMContentLoaded occurs when all of the HTML is ready to interact with, but often before its been rendered to the screen.
var interval;
$(document).ready(function(){
console.log("I am initialized")
var f = function() {
console.log("I am called")
// Minimum view count
var minViews = 2;
// Maximum view count
var maxViews = 20;
// Text to show after the view count number
var text = 'people are viewing this product right now.';
// Create the new element to display on the page
$(".view-count").get().forEach(function(entry, index, array) {
var $viewCountElement = Math.floor(Math.random() * (maxViews - minViews) + minViews) + ' ' + text;
$(entry).html($viewCountElement);
});
};
interval = setInterval(f, 10000);
});
$(window).on("beforeunload", function() {
// clear the interval when window closes
return clearInterval(interval);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Note: Check the console for output

Related

Refresh a DIV content after faded it out

I got X DIV (TopRowRight1, TopRowRight2, TopRowRight3...) , each containing a different Google Geochart generated by a php page : GeochartPerProvince.php?template=X.
function getResult(template){
jQuery.post("GeochartPerProvince.php?template="+template,function( data ) {
jQuery("#TopRowRight"+template).html(data);
});
}
jQuery().ready(function(){
getResult(1);
setInterval("getResult(1)",10000);
getResult(2);
setInterval("getResult(2)",10000);
getResult(3);
setInterval("getResult(3)",10000);
});
jQuery(function () {
var $els = $('div[id^=TopRowRight]'),
i = 0,
len = $els.length;
$els.slice(1).hide();
setInterval(function () {
$els.eq(i).fadeOut(function () {
i = (i + 1) % len
$els.eq(i).fadeIn();
})
}, 5000)
});
Every 5 seconds, i fade out one and fade in the next one. This works perfectly.
For now, the php page in the DIV is refreshed every 10 seconds. This works too.
But what i dream about is that the php page in the DIV is reloaded AFTER the DIV is faded out instead of every 10 seconds. How to do it?
Solved. How it works properly:
function getResult(template){
jQuery.post("GeochartPerProvince.php?template="+template,function( data ) {
jQuery("#TopRowRight"+template).html(data);
});
}
$(document).ready(function(){
getResult(0);
getResult(1);
getResult(2);
//setInterval("getResult(2)",10000); <== keep this piece of code in case of need.
});
$(document).ready(function () {
var $els = $('div[id^=TopRowRight]'),
i = 0,
len = $els.length;
$els.slice(1).hide();
setInterval(function () {
$els.eq(i).fadeOut(function () {
i = (i + 1) % len
getResult(i);
$els.eq(i).fadeIn();
})
}, 10000)
});
You're already using a callback function after the element has been faded out. So why not call your getResult function inside it?
$el.fadeOut(function(){
// stuff
getResult(i)
})
I have a few suggestions and an example code for you to achieve what you need :
Use $ instead of jQuery for easier reading / writing
$(document).ready is the proper start point for dom related functions
If only one div is visible at a time, do not use too many divs. Most of the time one div is enough for alternating / refreshing content. If there is in/out animation or cross-fading, two divs would be needed. (Example below uses two divs)
Avoid using setInterval except you really really need. Logics with setTimeout better handles unexpected delays such $.post may cause.
start with html code something like this:
...
<div class="top-row-right" style="display:block"></div>
<div class="top-row-right" style="display:none"></div>
...
js:
$(document).ready( function() {
var len = 4; // 'I got X DIV..' This is where we put the value of X.
var template = -1;
function refreshChart() {
template = (template + 1) % len;
$.post("GeochartPerProvince.php?template="+template, function(data) {
var offscreenDiv = ('.top-row-right:hidden');
var onscreenDiv = ('.top-row-right:visible');
offScreenDiv.html(data);
onScreenDiv.fadeOut('slow', function() {
offScreenDiv.fadeIn();
setTimeout(refreshChart, 10000);
});
});
}
refreshChart();
});

Multiple instances of Setinterval

I have a little problem with my code.
I have it setup so that by default, a rotating fadeIn fadeOut slider is auto playing, and when a user clicks on a li, it will jump to that 'slide' and pause the slider for x amount of time.
The problem i have is that if the user clicks on multiple li's very fast, then it will run color1() multiple times with will start colorInterval multiple times. This gives a undesired effect.
So what i need help with, is figuring out how to reset my code each time a li is clicked, so whenever ColorClick is clicked, i want to make sure that there are no other instances of colorInterval before i start a new one.
Thanks in advance!
=================================
edit:
I now have another problem, i believe that i fixed the clearInterval problem, but now if you look at var reset, you'll see that it runs color1() each time a li is clicked, which runs multiple intervals, so i need to delete the previous instance of color1() each time it is called, to make sure that it doesnt repeat any code inside multiple times. So when a li is clicked delete any instances of color1()
or
i need that instead of running color1 in var reset, i will go straight to colorInterval instead of running color1() for each li clicked,
so run colorInterval after x amount of time in var reset.
function color1() {
var pass = 0;
var counter = 2;
var animationSpeed = 500;
var $colorContent = '.color-container-1 .color-content-container'
var $li = '.color-container-1 .main-color-container li'
$($li).on('click', function() {
colorClick($(this));
});
function colorClick($this) {
var $getClass = $this.attr("class").split(' ');
var $whichNumber = $getClass[0].substr(-1);
var $Parent = '.color-container-1 ';
pass = 1;
$($colorContent).fadeOut(0);
$($colorContent + '-' + $whichNumber).fadeIn(animationSpeed);
var reset = setTimeout(function() {
clearTimeout(reset);
pass = 0;
color1();
}, 10000);
}
var colorInterval = setInterval(function() {
if (pass > 0) {
clearInterval(colorInterval);
return; //stop here so that it doesn't continue to execute below code
}
$($colorContent).fadeOut(0);
$(($colorContent + '-' + counter)).fadeIn(animationSpeed);
++counter
if (counter === $($colorContent).length + 1) {
counter = 1;
}
}, 7000);
}
You could just clear the interval inside of the click event.
var colorInterval;
$($li).on('click', function() {
clearInterval(colorInterval);
colorClick($(this));
});
//Your other code
colorInterval = setInterval(function() {
//Rest of your code
});
One thing play with is jQuery animations have a pseudo class selector :animated when animation is in progress
if(!$('.your-slide-class:animated').length){
// do next animation
}

Updating Momentjs FromNow() in a div element

I'm having this div element that shows the time past since it got created. However it doesn't get updated and always remains on few seconds ago. It looks like this
var newMsg= "<div id="chat-time">'+ moment().fromNow()+'</div>";
$("#chat-list").html( newMsg);
How can I update this text. I know I can do it with sentInterval but I can't figure out how to do it properly.It just prints out seconds! I'm using this for a chatroom. So each message will have a timestamp in the formatof momentjs.fromNow().
Does setting timer for all these message create a problem? I'd appreciate a hint.
EDIT:I'm using this code as mentioned in below but it's not showing anything:
<div id="chat-time"></div>
var messageTimeStamp = new Date();
setInterval(function(){
var time = moment(messageTimeStamp).fromNow();
$("#chat-time").html(time);
}, 1000);
To make this work you need the element in the dom and the setInterval running without being included in any string concatenation
HTML
<div id="chat-time"></div>
JS
var $chatTime = $('#chat-time').text(moment().fromNow());
setInterval(function(){
var time = moment().fromNow();
$chatTime.txt( time );
}, 1000);
UPDATE 2
Given that you're using socket.io, you'd do something like this (demo: http://plnkr.co/edit/QuaMV6x1vNB0kYPaU6i1?p=preview):
// The messages the user can currently see.
var messages = [];
// You have something like this in your code, presumably.
socket.on('new message', function(data) {
addChatMessage(data);
});
function addChatMessage(data) {
// First add the message to the dome, with a unique id for the timestamp text.
var messageElementId = 'chat-message-' + data.messageId;
$("#chat-list").prepend($("<div>" + data.message + "<i> (sent: <span id='" + messageElementId + "'>just now</span>)</i></div>"));
// When you no longer display that message in the DOM it from clear this array. I'd render the DOM based on this list if I were you.
messages.push({
messageElementId: messageElementId,
timestamp: data.timestamp
});
}
// By updating all the messages at once you don't have memory leaks.
setInterval(function() {
messages.forEach(function(message) {
var time = moment(message.timestamp).fromNow();
$("#" + message.messageElementId).text(time);
});
}, 1000);
UPDATE 1
Given this is your code:
var newMsg= "<div id="chat-time">'+ moment().fromNow()+'</div>";
$("#chat-list").html(newMsg);
You would do this, instead:
var messageTimeStamp = new Date(); // You need to grab this from somewhere.
setInterval(function(){
var time = moment(messageTimeStamp).fromNow();
$("#chat-list").html(time);
}, 1000);
You need to use moment(TIMESTAMP_OF_MESSAGE) not moment() and do something like this:
$(function(){
$("body").append($('<div id="chat-time"></div>'));
var messageTimeStamp = new Date();
var i = 0;
setInterval(function(){
var time = moment(messageTimeStamp).fromNow();
$("#chat-time").html('moment().from(messageTimeStamp): ' + time + '; setInterval calls made ' + i++);
}, 1000);
});
Here's a demo.
http://plnkr.co/edit/QuaMV6x1vNB0kYPaU6i1?p=preview
I dont see any problem using setInterval (). AngularJS wrapper setInterval on $interval service module . Check out these urls: interval Angular and Wrapper SetInterval

How do I make elements trigger to appear one after another, with a small interval?

I have a series of four elements. The first of which (#pro1) will appear on scrolling to a particular point on the page (this currently works), and the following three will trigger to appear one after another, with a small changeable interval in between each.
Any help would be greatly appreciated! A huge thank you in advance!
Here is the code for the first element, just needing to make the others appear after this one appears (#pro2, #pro3, #pro4, etc)
<script>
$(window).one("scroll", function() {
$('#pro1').each(function () {
var topOfWindow = $(window).scrollTop(),
bottomOfWindow = topOfWindow + $(window).height();
var imagePos = $(this).offset().top;
if(imagePos < bottomOfWindow-200 && imagePos >= topOfWindow-500){
$(this).addClass('bigEntrance2');
}else{
$(this).removeClass('bigEntrance2');
}
});
});
</script>
The key is using setInterval to call repeatedly the function that will create (or show if they are already created) the next elements.
It is important to not forget to clear the interval when the job is done.
Without the html and the css is difficult to realise exactly what you want to achieve, but from the next example you shouldn't have problems to update yours.
var interval = null;
var elementId = 1;
var numElements = 4;
var delay = 1000; //ms
$(document).ready(function()
{
//your first "pro1" element show up
var element = "<div>Im the pro" + elementId + " element!</div>";
$('body').append(element);
//in that moment we set the interval
interval = setInterval(show_next_element, delay);
});
function show_next_element()
{
//increment the counter elementId
elementId++;
//create the next element
var element = "<div>Im the pro" + elementId + " element!</div>";
//add it to the DOM
$('body').append(element);
//when our last element is created we clear the interval
if(elementId >= numElements)
clearInterval(interval);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hope it helps!

How to show last 5 seconds when timing is running out?

Hi i am using Javascript set timeout to run a certain function.
How do i display the last 10 seconds of the timeout when it is nearing the end?
var a = setTimeout('someFunction()', 10000);
Is it able to display something using the value that it store into the variable?
Thanks
I have created a small demo for you,
http://jsfiddle.net/praveen_prasad/DYaan/1/
<div id="target" style="display:none">
target
</div>
var target,
allotedTimeForWork=100 /*you can change this*/
;
var handler = setTimeout(function(){
if(!target)
{
target=document.getElementById('target');
}
target.style.display="block";
startTicker();
}, allotedTimeForWork);
function startTicker()
{
var counter=10;
var tickerHandler= window.setInterval(function(){
if(counter>0)
{
//cache target
target.innerHTML="you have "+counter +" seconds left";
counter--;
}
else
{
target.innerHTML="time over";
clearInterval(tickerHandler);
}
},1000);
}
It is not possible to directly get the remaining time of a Timeout.
You could either try to make multiple Timeouts for every second, or have another variable where you store when the Timeout was started.
I would use two timeouts.
The first with time minus 5 seconds, that calls a function with the second timeout (5 seconds) which would have the timer displayed.
Take a look here: http://jsfiddle.net/VCAnm/
HTML:
<span id="aaa">10</span>
JavaScript:
setInterval(function() {
var elem = document.getElementById('aaa');
elem.innerHTML = elem.innerHTML - 1;
}, 1000);
set 2 timers one for the timeout and another for the warning
var warn_time = 5000;
var function_name = 'someFunction()';
var a = setTimeout('warnFunction(function_name, warn_time)', 10000 - warn_time);
function warnFunction(function_name, time) {
alert('only ' + time + ' seconds left'); //use a div or whatever to display
var b = setTimeout(function_name, time);
}

Categories

Resources