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!
Related
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);
});
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)
I am using CSS-Tricks dynamic page script found here.
http://css-tricks.com/dynamic-page-replacing-content/
$(function() {
var newHash = "",
$mainContent = $("#main-content"),
$pageWrap = $("#page-wrap"),
baseHeight = 0,
$el;
$pageWrap.height($pageWrap.height());
baseHeight = $pageWrap.height() - $mainContent.height();
$("nav").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
$mainContent
.find("#guts")
.fadeOut(200, function() {
$mainContent.hide().load(newHash + " #guts", function() {
$mainContent.fadeIn(200, function() {
/*
$pageWrap.animate({
height: baseHeight + $mainContent.height() + "px"
});
*/
});
$("nav a").removeClass("current");
$("nav a[href="+newHash+"]").addClass("current");
});
});
};
});
$(window).trigger('hashchange');
});
Body
<body onload="onLoad()">
I am using a number generating script (below) on one of my pages, but I am having trouble getting it to only show on one, single page. When placed in the head of the document or my includes/scripts.php that is loaded on every page, it shows on every page. When only included on the page I want, it does not work.
<script>
function counter() {
var num = 0;
for (num = 0; num < 500; num++) {
document.write(num + ' ');
}
}
counter();
</script>
I have tried a few different things but can't seem to get it to only appear on a single page. Is there any way around this without ditching the CSS-Tricks Dynamic Page?
What if you insert your code into dynamicpage.js like this?
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if(newHash === 'somePage') { // the page you want to implement the effect
// your code
}
/*
....
*/
});
You might try adding a class to your <body> tag (or other near-to-top level wrapper if you're just dynamically loading to the HTML attribute of your body tag in the first place) that lets the script distinguish between pages that ought to use the function and those that don't, something like:
$(document).ready( function() {
$(`body.usesCounter`).on(eventToBeCounted, counterFuncAsCallback);
}
But the fact that it's not working when only loaded on a single page does suggest you've got something else going on. Can you give us the header for the single page, the script block (and where it is on the page), and some sense of how/when it's called?
Are you loading the single page dynamically? If you are, the script tags won't be accessible unless you reload the DOM somehow or else do some funky binding via jQuery's $.on() or something similar that listens for changes to the DOM.
UPDATE
Looking at the tutorial you are trying to emulate, the general problem you're facing is that the JS on that page you're loading isn't going to be registered with the DOM. I've had to write code that can read dynamically lodaded JS like this, and if you want to do it both effectively and securely, it's quite a lot of effort. The point of JS-based page loading is to be fetching "view-like" content; assets, html, etc.. In a single-page environment, any required logic should—generally—exist on that page.
I highly recommend you include the code in your initial page, and then conditionally call it when the appropriate page arrives. There are lots and lots of ways to do that, basically find some distinguishing feature of the page(s) where your counter should be run, and, after having loaded the page, look for said features and, if found, allow your code to run. You might have something as simple as a variable, isCounterPage set, by default, to false. Then, after a dynamic page load occurs, if the inspection fires and this var remains false, don't execute code associated with the counter. Otherwise, let it do its thing.
I'm having a trouble with running function for checking new messages in table. When I open the message_page I want this 'setInterval' function to start running, but after leaving the page stop running (I have one html file with multiple pages). Is there a way to do that? Because my script keeps running even after leaving the page.
$(document).on('pageshow', '#message_page', function(){
$('#chat_box').scrollTop($('#chat_box').height());
setInterval( function() {checkNewMessages(c_key,m_fid);},1000);
});
Here's a working example: http://jsfiddle.net/Gajotres/QUCUt/
$(document).on('pagebeforeshow', '#index', function(){
timerHandler.timer1 = setInterval(function () {
$('#test-input').val(parseInt($('#test-input').val()) + 1);
}, 1000);
});
$(document).on('pagebeforehide', '#index', function(){
clearInterval(timerHandler.timer1);
});
var timerHandler = {
timer1 : null
}
Let me explain. If you create a timer as a object variable, it can be accessed at any moment. In this case pagebeforeshow event will start timer and pagebeforehide will pause it. You can test it on my example, just let it run a little bit, then go to the second page, wait a bit and return back. You will see that timer has been paused.
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;
});