Code being multiplied and all instances are running - javascript

My website works in a way so that any links clicked do not load a new page but however trigger a .load() event into a div named "content".
Everything has been nice and dandy but now I have run into a small problem.
On one of the content pages, I have the following code:
$('.count').each(function () {
$this = $(this);
countdown = setInterval(function(){
countnow = parseInt($('.remain', $this).html());
$('.remain', $this).html(countnow-1);
}, 1000);
return false;
});
The code works... it works very well. But when I load that same page again, it seems like the code is running twice because the seconds are going down by 2 at a time. Then when I load it again, it's going down by 3 seconds at a time. Another load, and it goes down by 4 seconds at a time. I load it a couple more times and it goes down faster then I can read.
I tried giving the .count divs their own unique id's (the .remain div is nested inside the .count div), even when pages are subsequently loaded the id is still entirely different and this did not fix my problem. I also tried putting clearInterval(countdown) right before the function but that just made it stop working entirely. Any suggestions?
And yes I know the countdown doesn't currently stop when it reaches 0.

Try this:
var countdown;
$('.count').each(function () {
$this = $(this);
if (!countdown)
countdown = setInterval(function(){
countnow = parseInt($('.remain', $this).html());
$('.remain', $this).html(countnow-1);
}, 1000);
return false;
});

Related

Is there a way to wait till a new page is loaded before executing another function in JavaScript?

I have spend a lot of time think about this and tried different things now. I want to scrape a webpage with multiple pages but the page does not reload on page change. Instead, some container data is changed on each changed page. The most difficult thing to do is know when to click the next page button.
Someone might think that this is pretty easy and I thought the same and started off by doing:
$('.pagn a').each(function() {
console.log(`Loop counter`)
$(this).click()
//Code to scrape the new page
})
Now, the loop runs 13 times but only one page is changed. This is because the pagination itself is inside the container that reloads so all other button presses are basically ignored.
To tackle this I needed some kind of a check that makes sure that the new content has loaded before proceeding but if I try to do something like:
$('.pagn a').each(function() {
console.log(`Loop counter`)
while (someConditionToCheckIfPageLoaded) {
}
$(this).click()
//Code to scrape the new page
})
This would be an infinite loop because JavaScript is single threaded and the code to change the condition never fires.
I also tried this which I now know is incorrect.
The indicator for page being loaded is if the button URL matches the page URL.
$('.pagn a').each(function() {
let visitedURL = [];
if ($(this).attr('data-url')) {
let button = $(this)
buttonURL = "https://www.ebay.com/myb/PurchaseHistory#" + $(this).attr('data-url');
(function wait() {
button.click()
if (buttonURL == location.href && !visitedURL.includes(button.html())) {
console.log(button.html())
button.click()
visitedURL.push(button.html())
console.log(buttonURL);
console.log(location.href);
//Scrape page
} else {
setInterval(wait, 5000);
}
})();
}
})
This also only changes one page.
If someone has been able to scrape webpages with multiple pages with JavaScript please let me know how.
Edit1:
Also, I am not sure why this creates an infinite loop as well:
let glbElements = []
$('.pagn a').each(function() {
glbElements.push($(this))
})
for(let i = 0 ; i<glbElements.length; i++){
console.log(`Loop Counter`)
setTimeout(function(){
console.log(`Inside SetTimeout`)
glbElements[i].click()
glbElements.splice(i,1)
},2000)
}
Lopp Counter *5
Inside SetInterval -- Keeps printing
You can use the setTimeout() function to wait after a user clicks a button.
Like this:
<a href='newpage.html'><button id='click'>Click!</button</a>
$('#click').click(function() {
setTimeout(function() {
// code you want executed after page is loaded
}, 100);
});

Using jQuery's .each feature when page is constantly updating

I've been trying to get to find a solution for this all day but can't think of a good one that I can get working.
Basically, I made some jQuery/javascript code that runs an each() loop for certain items on a web page. This works well, but the page it runs on updates when you scroll to the bottom, adding more results. At the moment, my script can only go through as many items as there are loaded on the page. I would love for it to be able to go through all of them that are loaded, then scroll to the bottom and go through all the new results and continually repeat this process.
I've tried a lot of different solutions but can't seem to make one that works well.
Any help would definitely be appreciated.
Thanks :)
Edit:
Here are some of the concepts I've tried so far:
Place the code in a while loop and add an offset so it skips all of the items its already gone over
var a = 0;
var offset = 0;
while (a == 0) {
jQuery('.Grid-cell .js-stream-item .ProfileCard').each(function (i, ele) {
if (i >= offset) {
//Run script
}
});
offset = offset + 18; //18 is how many new items are added each time
setTimeout(function () {
jQuery('html, body').animate({scrollTop:$(document).height()}, 'fast'); //To scroll to the bottom
}, 5000);
}
Place code in while loop but no offset
(Similar to previous but offset removed since I figured it could just runover the ones already done)
This one was a bit more experimental since I was getting desperate after the previous attempts failed. Basically, I added a hidden checkbox, then I put my script and the each loop inside of a function. Then whenever the checkbox was clicked it would run the function which ran my script and once the each loop was complete it would scroll to the bottom of the page and click the checkbox to make the function go again
$( ".Footer-copyright" ).append( "<input type='checkbox' class='functionclass' style='display:none' value='no' />" );
jQuery(".functionclass").on("click", function() {
myfunction();
})
function myfunction() {
jQuery('.Grid-cell .js-stream-item .ProfileCard').each(function (i, ele) {
//Run script
});
jQuery('html, body').animate({scrollTop:$(document).height()}, 'fast');
jQuery(".functionclass").click();
}
jQuery(".functionclass").click();
So I believe I've found a solution to my issue. It's not exactly the cleanest solution ever, but it seems to get the job done. Basically, I've put the task inside of a setInterval() function and so it will now complete the task every 5 seconds and will scroll to the bottom after 15 tasks. This allows it to get an updated list of all of the elements every time it runs. Here is the code for anyone curious:
var i = 0;
task = setInterval(function(){
var elements = jQuery(".Grid-cell .js-stream-item .ProfileCard"); //Gets all of the elemnts
var element = jQuery(elements[i]); //Gets the element for the attempt number
//Completes task
if (i % 15 === 0){
jQuery('html, body').animate({scrollTop:$(document).height()}, 'fast'); //Scrolls to bottom when attempt number is divisible by 15
}
i++;
}, 5000);

How to flip thru all pages and back in Jquery Datatable

In my Jquery datatable I'm programmatically navigating to the pages with setinverval function.
setInterval(function () {
table3.page('next').draw('page');
}, 5000)
This works fine but stops at last page. Once it reaches to the last page, I want it to go back to the first page and do the whole process again.
I guess I need to find out the count of pages then once it reaches that, go go page 1. But I have not have good luck on how to accomplish this.
this is what I came up with:
http://live.datatables.net/fobalaxe/1/edit
$(document).ready( function () {
var table = $('#example').DataTable({paging:true});
setInterval(function(){browse(table);} , 5000);
});
function browse(table){
if(table.page() >= table.page.info().pages - 1){
table.page('first').draw('page');
}
else {
table.page("next").draw('page');
}
}

Wait before starting JavaScript function

I'm trying to play a sound every time a user gets a new notification. The way I am loading the notifications on my page is simple:
(function($)
{
$(document).ready(function()
{
var $container = $("#noti");
$container.load("notify.php");
var refreshId = setInterval(function()
{
$container.load('notify.php');
}, 1000);
});
})(jQuery);
This works by updating a div container with whatever number the PHP code sends out. it retries every second (probably not the most efficient way, but it works).
I have another piece of code that checks when the div content changes, then creates an alert box (which I will change to playing a sound when the script is done):
var myElement = document.getElementById('noti');
if(window.addEventListener) {
// Normal browsers
myElement.addEventListener('DOMSubtreeModified', contentChanged, false);
} else
if(window.attachEvent) {
// IE
myElement.attachEvent('DOMSubtreeModified', contentChanged);
}
function contentChanged() {
// this function will run each time the content of the DIV changes
alert("js is working");
}
This script works, however it also creates an alert or the first loading of the notifications. This is because it starts of as an empty div, then it loads the data, which sets off this alert script. The only way I could think about going round this is delaying the script from loading for a couple of seconds whilst the AJAX script does its business.
Does anyone know a way I could delay this second script from doing anything for the first few seconds after page load, or perhaps a better way about going round this?
Instead of doing that, use a custom event which you trigger when load finishes:
var refreshId = setInterval(reloadContainer, 1000)
function reloadContainer() {
$container.load('notify.php', function success() {
$container.trigger('loaded')
})
}
$(myElement).on('loaded', contentChanged)

Measure loading time in Jquery

I have a question about a Javascript-file I've made. It makes sure hyperlinks open in a div and not in a new tab. However, I've also made a very simple text-inclusion to show while the page is loading.
$(document).ready(function () {
$('a').on('click', function(e){
e.preventDefault();
var page_url = $(this).prop('href');
var loading =
$('#content')
.html('<h2>The page is loading. A second please.</h2>')
.load(page_url);
});
});
However, some pages are considerably loading faster than others. In other words, in some pages it's very useful to have this script, but when a page is loading immediately, it's just simply very annoying.
Is it possible to measure the time that the 'load' takes, and accordingly, display html or not? (I was thinking about something like: "If time-loading>1000 .html('blabla') / Else").
You can do something like that:
var timer = setTimeout(function() {
$('#content').html('<h2>The page is loading. A second please.</h2>');
timer = null;
}, 1000);
$('#content').load(page_url, function() {
if (timer) {
clearTimeout(timer);
}
});
For fellow googlers, I combined the comments and the answer above to provide a solution. What I did was the following: instead of not displaying the loading message if the page was loading within a second, I made sure it was at least displaying at least a second:
$(document).ready(function () {
$('a').on('click', function(e){
e.preventDefault();
$('#content').html("<div id='status' class='status'></div>");
$('#status').html('<h2>The page is loading. A second please.</h2>');
var page_url = $(this).prop('href');
var loadingMsg = setTimeout(function(){
$('#content').load(page_url, function (){
clearTimeout(loadingMsg);
$('#status').html();
});
},1000);
});
});
The reasons why I did this, is because I couldn't get the timeout-function consistent. Sometimes it worked perfectly, but sometimes the screen just froze and nothing was displayed until the page loaded. Now, it is displayed at least a second, and if the loading takes more, it will be displayed until the page loads.
Thanks for your answers and I hope this helps for people with a similar problem!

Categories