I was wondering if there was a way to render a webpage over again, thus calling all the onload events over again, and redrawing the css?
For example, say you changed the pathway of a javascript file that is linked to an onload event and the edited page needed to reload without a refresh in order for the change to take affect.
tested, now is working:
function fireEvent(element,event){
if (document.createEventObject){
// dispatch for IE
var evt = document.createEventObject();
return element.fireEvent('on'+event,evt)
}
else{
// dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
}
}
setTimeout(function(){
var links = document.getElementsByTagName("link");
var st = [];
for(var x=0;x<links.length;x++)
if(links[x].getAttribute("rel") == "stylesheet")
{
st.push(links[x]);
links[x].wasAtt = links[x].getAttribute("href");
links[x].setAttribute("href", "");
}
setTimeout(function()
{
for(var x =0;x<st.length;x++)
st[x].setAttribute("href", st[x].wasAtt);
setTimeout(function(){
fireEvent(window, "load");
},1000);
},1000);
},5000); // test reload after five seconds
"reload without a refresh" sounds a bit confusing to me.
However I do not know if this is what you are looking for, but window.location.reload() triggers a page reload and thus will load your linked javascript files.
But changing linked files and reload the page is not a good thing to do. It would be better if your dynamic files are loaded in a dynamic way like using Ajax. So you do not need to reload the whole page. Frameworks like JQuery, ExtJS or others provide methods to do this easily.
Related
I have <a> element which clicked runs handler like:
function onCummReportClick(e) {
if ($(e.currentTarget).attr('href').indexOf('csv') !== -1) {
{
return true;
}
//Here some files loaded asynchronousely
$.ajax().success(...).always(...);
var reports = [];
var downloadedCount = 0;
var reportsCount = 9;
var oneDownloaded = function() {
if (downloadedCount === reportsCount) {
//Prepare cummulative reports CSV
$(e.currentTarget).attr('href', 'data:application/csv;charset=utf-8,'+ encodeURI(reports.join('\n\n')))
//HERE!
$(e.currentTarget).trigger('click');
} else {
setTimeout(oneDownloaded, 1000);
}
};
setTimeout(oneDownloaded, 1000);
}
I.e. it download reports, join its content to one CSV and set it as base64-encoded to original <a>'s href. After that I want it downloaded automatically without user have to click again.
And return true does not generates "normal" click flow, looks like if just skipped. i mean that I running into this handler second time, but download did not started.
If I set up href to generated value statically and in handler just returning true if works as expected - file automatically downloaded.
I know that I could download reports synchronously and make entire method sync, but I dislike this approach.
UPD: I created jsfiddle which demonstrates what I trying to do: https://jsfiddle.net/u1rs17w1/
I do not know why code from JSFiddle does not works, as I understand all assumption about "lost context" is wrong (at least half wrong) because original hyperlink is updated correctly (I mean href attribute uptdated).
But I found another solution. Instead of clicking on original link I do following:
var link = document.createElement('a');
link.download = _messages.CUMMULATIVE_REPORT_NAME;
link.href='data:application/csv;charset=utf-8,'+ encodeURI(csvFile.join('\n\n'));
//These 2 lines are required for Firefox
link.style = "display: none";
document.body.appendChild(link);
link.click();
And it is works even from setTimeout handler. I suspect that clicks by jquery-style, i.e. with return true (I cannot call it somehow clearly) works only from main thread. Each time I works with setTimeout execution continued in new thread. But creating element in new thread and clicking on it works like a charm!
Happy coding!
UPD: This solution does not works in Firefox. Nothing works in Firefox unless synchronous AJAX (ffffffuuuuuuuu!) and return true.
UPD1: Added solution for Firefox.
Below is my code but page load continuously,i want to load only once
window.onload = function () {
window.location.reload();
}
There are a few ways you could solve this, all of which require saving state across page loads. You could use cookies, localStorage, the location object itself, etc.
Here's a way that checks to see if there is a hash string 'reloaded' and, if not, adds it and reloads the page. Then, when it tries to execute again, the hash will be there and it will not reload:
if (location.hash.indexOf('reloaded') === -1) {
location.hash += 'reloaded';
location.reload();
}
$(document).ready(function(){
if(document.URL.indexOf("#")==-1){ //Check if the current URL contains '#'
url = document.URL+"#"; // use "#". Add hash to URL
location = "#";
location.reload(true); //Reload the page
}
});
Due to the if condition page will reload only once.
The other way to achieve this is :
(function()
{
if( window.localStorage )
{
if( !localStorage.getItem('firstLoad') )
{
localStorage['firstLoad'] = true;
window.location.reload();
}
else
localStorage.removeItem('firstLoad');
}
})();
window.onload = function ()
{
// for getting params value
function parse(val)
{
var result = "not found";
tmp = [];
location.search
.substr(1)
.split("&")
.forEach(function (item) {
tmp = item.split("=");
if (tmp[0] === val) result = decodeURIComponent(tmp[1]);
});
return result;
}
if(parse("load")!="once")
{
//sending parameter so next time it won't reload..
window.location.href += "?load=once";
window.location.reload();
}
}
By nature of visiting a page, It will only load once. You could change your code to prove this fact:
window.onload = function () {
alert("Loaded");
}
But, I would suggest the vapor.js route to detecting page load, that is, omit this onload call, because the lines of code in the onload function run after the page is loaded. I think you either don't know what your goal is or you have an entirely different problem you are trying to solve in a way that does not make sense
You built a loop,
site is loading
window.onload is triggered
reload is initiaded
site is (re-)loading
window.onload is triggered
reload is initiaded
.......
.......
Important fact for you to learn is that browsers run through your code from top to bottom and when you reload your page, the whole prozess repeats.
So every Time you reload, the window.onload event-listener is registered and calls the function attached to it, as soon as the window object is fully loaded.
There is no mechanism that tells the browser to stop.
if you would like run your Javascript code once the DOM is loaded, and you are looking for an browser independent solution i would recommend jQuery and its $( document ).ready() function.
with jQuery included to your Page:
$( document ).ready(function(){
//Code inside this function runs after your document is loaded
})
I have a browser-based application that I use at work (as effectively all corporate apps are now browser-based for obvious reasons) that has an annoyingly short session timeout. I'm not sure precisely what the session timeout is set to, but it's something along the order of 5-10 minutes.
Inevitably whenever I have to use it the session has timed out, I enter the information into the app, submit it, and then the page loads with a brand new session without any of the information actually being passed on - all I get is a new session. I then have to re-enter the information and submit it again in order to have it actually pull up what I want. Of course, I could first refresh the page and then enter the info, but I never know if the session is timed out or not and occasionally it runs painfully slowly so this is a waste of time. Our development team's inability to foresee that little things like this are not only annoying, but also end up costing us a ton of money when you consider the amount of time lost (I work for a VERY large corporation) just waiting for the blasted thing to reload and then having to re-enter the submitted information if a pre-refresh was forgotten as it usually is happens to be beyond me. At some point I'm hoping to become the liaison between the programmers and our customer service body.
Anyway, I digress.
What I'm looking to do is this: I'd like to create a Javascript bookmarklet or something that will automatically refresh whatever page it happens to be on if activity isn't detected within a certain timeframe. This timeframe will be a bit short of whatever I end up figuring out what the session timeout is. Basically I just want to make the page reload itself every, say, five minutes if there hasn't been activity within that period. (I don't want it to refresh out of the blue because the time is up while I'm in the middle of using the app, the only time it should do the auto-refresh is if the app page has been sitting idle)
Can this be done with a Javascript bookmarklet? Should I program a page "wrapper" of sorts that loads the application page within an iFrame or something of the sort? The app site that I use has many subpages, and I'd prefer for it to refresh whatever page I happen to be on at the time if the auto-refresh timeout occurs. Of course, if that isn't possible I'd accept it just reloading the main site page if that's not easily possible since if I've been out of the app long enough for the timeout to happen then I likely don't need to still be on whatever account/page I was on at the time.
Hopefully I've explained myself well enough. The logic is simple - if no activity detected withing x amount of time, refresh the current page is the gist of it.
Thank you, my StackOverflow brethren, yet again for your assistance.
-Sootah
Since I have no ability to influence the coding of the page itself, I've got to have the most simple solution possible. A bookmarklet that times the last refresh/pageload and then refreshes the same page if the timeout is reached would be perfect.
If that's not possible, then if I could write a simple page that I could run from the local computer that'd do the same function by loading the page in a frame or something that'd also be acceptable.
EDIT 10/3/11 7:25am MST
Since I work graves and an odd schedule at work (and this site, unfortunately, being blocked there since it's considered a 'forum' - I work in finance, they're overly cautious about information leakage) before I award the bounty, does one of these event detectors detect the last time the page loaded/? Something like document.onload or whatnot. I'm thinking that setting the timer from the last time the page was loaded is going to be the simplest and most effective approach. My mouse may move over the browser that I have the site open in inadvertently while working on other things, and if the timer resets because of that without me actually having interacted with the site in such a way that a page loads/reloads then the session times out.
This is the bookmarklet code #1 for you, set up to FIVE seconds. Change time to what you like more.
javascript:
(function () {
var q = null;
function refresh() { window.location.reload(); }
function x() { clearTimeout(q); a(); }
function a() { q = setTimeout( refresh, 5000 ); }
document.body.onclick = x;
document.body.onmousemove = x;
document.body.onmousedown = x;
document.body.onkeydown = x;
}())
p.s.: would have been nicer to include eventListeners, but i suppose you need to support IE8, too, so i replaced them with inline events, - if you DON'T need IE8, use code #2:
javascript:
(function () {
var q = null;
function refresh() { window.location.reload(); }
function x() { clearTimeout(q); a(); }
function a() { q = setTimeout( refresh, 5000 ); }
document.body.addEventListener( "click", x, false );
document.body.addEventListener( "mousemove", x, false );
document.body.addEventListener( "mousedown", x, false );
document.body.addEventListener( "keydown", x, false );
}())
edit: in response to comments, here is code #3 with pulling, instead of refreshing page. Yet, despite advices to use iframe, i decided it might be desirable to not execute scripts on that page, so we will use img instead:
javascript:
(function () {
var q = null;
var u = window.location.href;
var i = document.createElement('img');
i.style = "width: 1px; height: 1px;";
document.body.appendChild(i);
function refresh() {
i.src = "";
i.src = u;
x();
}
function x() { clearTimeout(q); a(); }
function a() { q = setTimeout( refresh, 5000 ); }
var evs = ['click', 'mousemove', 'mousedown', 'keydown'];
for( var j = 0; j < evs.length; j++) {
document.body['on'+evs[j]] = x;
}
}())
Create a bookmark and place the code below in the "url" value. Please note that you should change the values of "sessiontimeout" and "checkinterval". They're both in milliseconds.
javascript:(function(){var lastmove = new Date().valueOf(),sessiontimeout=10000,checkinterval=1000;document.onmousemove = function(e){lastmove= new Date().valueOf();};timer = setInterval( function() {var differential = (new Date().valueOf() - lastmove);if (differential > sessiontimeout) {var iframe = document.getElementById("bkmrkiframerefresher");if (iframe) { document.getElementsByTagName("body")[0].removeChild(iframe);} iframe = document.createElement("iframe");iframe.setAttribute("src", "/");iframe.setAttribute("width", 0);iframe.setAttribute("height", 0);iframe.setAttribute("style", "width:0;height:0;display:none;");iframe.setAttribute("id", "bkmrkiframerefresher");document.getElementsByTagName("body")[0].appendChild(iframe);lastmove = new Date().valueOf();} }, checkinterval);})();
This is a bookmarklet that will inject the code below in the page. I tested the bookmarklet in Chrome. It worked on multiple sites except stackoverflow, it seems that they block framing for security reasons. Before you leave your desk, open the website which session you wanna keep alive, then click the bookmarklet on it. Once you're back, refresh the page in order to get rid of the running timers.
The formatted (and commented) code is:
<script type="text/javascript">
// last time the mouse moved
var lastmove = new Date().valueOf();
var sessiontimeout=10000;
var checkinterval=1000;
// reset the last time the mouse moved
document.onmousemove = function(e){
lastmove= new Date().valueOf();
}
// check periodically for timeout
timer = setInterval( function() {
var differential = (new Date().valueOf() - lastmove);
if (differential > sessiontimeout) {
var iframe = document.getElementById("bkmrkiframerefresher");
// iframe already exists, remove it before loading it back
if (iframe) {
document.getElementsByTagName("body")[0].removeChild(iframe);
}
// alert("more than 10 secs elapsed " + differential);
// create an iframe and set its src to the website's root
iframe = document.createElement("iframe");
iframe.setAttribute("src", "/");
iframe.setAttribute("width", 0);
iframe.setAttribute("height", 0);
iframe.setAttribute("id", "bkmrkiframerefresher");
iframe.setAttribute("style", "width:0;height:0;display:none;");
document.getElementsByTagName("body")[0].appendChild(iframe);
// reset counter.
lastmove = new Date().valueOf();
}
}, checkinterval);
</script>
Stefan suggested above that you need no logic besides polling. The edited code is the following:
<script type="text/javascript">
var pollInterval=1000;
timer = setInterval( function() {
var iframe = document.getElementById("bkmrkiframerefresher");
// iframe already exists, remove it before loading it back
if (iframe) {
document.getElementsByTagName("body")[0].removeChild(iframe);
}
// create an iframe and set its src to the website's root
iframe = document.createElement("iframe");
iframe.setAttribute("src", "/");
iframe.setAttribute("width", 0);
iframe.setAttribute("height", 0);
iframe.setAttribute("id", "bkmrkiframerefresher");
iframe.setAttribute("style", "width:0;height:0;display:none;");
document.getElementsByTagName("body")[0].appendChild(iframe);
}
}, pollInterval);
</script>
This code only reload the page once
Here is a bookmarklet(inspired by Kaj Toet's pseudo code), tested in Chrome and Safari, change the timeout value with the var time at the start of the line
Onliner:
javascript:var time = 500; var timeoutFunc = function(){location.reload(true);};timeout = setTimeout(timeoutFunc,time);document.onmousemove = function() {clearTimeout(timeout);timeout = setTimeout(timeoutFunc,time); };
Code
//The time in milliseconds before reload
var time = 500;
//The function that is called when the timer has reached 0
var timeoutFunc = function() {
location.reload(true);
};
//start the timer
timeout = setTimeout(timeoutFunc,time);
//restart the timer if the mouse is moved
document.onmousemove = function() {
clearTimeout(timeout);
timeout = setTimeout(timeoutFunc,time);
};
pseudocode
timeout = settimeout("call",200);
document.onmousemove = function() { timeout = new timeout("call",200); }
function call() {
document.refresh();
}
like this?
I am using History API for my web app and have one issue.
I do Ajax calls to update some results on the page and use history.pushState() in order to update the browser's location bar without page reload. Then, of course, I use window.popstate in order to restore previous state when back-button is clicked.
The problem is well-known — Chrome and Firefox treat that popstate event differently. While Firefox doesn't fire it up on the first load, Chrome does. I would like to have Firefox-style and not fire the event up on load since it just updates the results with exactly the same ones on load. Is there a workaround except using History.js? The reason I don't feel like using it is — it needs way too many JS libraries by itself and, since I need it to be implemented in a CMS with already too much JS, I would like to minimize JS I am putting in it.
So, would like to know whether there is a way to make Chrome not fire up popstate on load or, maybe, somebody tried to use History.js as all libraries mashed up together into one file.
In Google Chrome in version 19 the solution from #spliter stopped working. As #johnnymire pointed out, history.state in Chrome 19 exists, but it's null.
My workaround is to add window.history.state !== null into checking if state exists in window.history:
var popped = ('state' in window.history && window.history.state !== null), initialURL = location.href;
I tested it in all major browsers and in Chrome versions 19 and 18. It looks like it works.
In case you do not want to take special measures for each handler you add to onpopstate, my solution might be interesting for you. A big plus of this solution is also that onpopstate events can be handled before the page loading has been finished.
Just run this code once before you add any onpopstate handlers and everything should work as expected (aka like in Mozilla ^^).
(function() {
// There's nothing to do for older browsers ;)
if (!window.addEventListener)
return;
var blockPopstateEvent = document.readyState!="complete";
window.addEventListener("load", function() {
// The timeout ensures that popstate-events will be unblocked right
// after the load event occured, but not in the same event-loop cycle.
setTimeout(function(){ blockPopstateEvent = false; }, 0);
}, false);
window.addEventListener("popstate", function(evt) {
if (blockPopstateEvent && document.readyState=="complete") {
evt.preventDefault();
evt.stopImmediatePropagation();
}
}, false);
})();
How it works:
Chrome, Safari and probably other webkit browsers fire the onpopstate event when the document has been loaded. This is not intended, so we block popstate events until the the first event loop cicle after document has been loaded. This is done by the preventDefault and stopImmediatePropagation calls (unlike stopPropagation stopImmediatePropagation stops all event handler calls instantly).
However, since the document's readyState is already on "complete" when Chrome fires onpopstate erroneously, we allow opopstate events, which have been fired before document loading has been finished to allow onpopstate calls before the document has been loaded.
Update 2014-04-23: Fixed a bug where popstate events have been blocked if the script is executed after the page has been loaded.
Using setTimeout only isn't a correct solution because you have no idea how long it will take for the content to be loaded so it's possible the popstate event is emitted after the timeout.
Here is my solution:
https://gist.github.com/3551566
/*
* Necessary hack because WebKit fires a popstate event on document load
* https://code.google.com/p/chromium/issues/detail?id=63040
* https://bugs.webkit.org/process_bug.cgi
*/
window.addEventListener('load', function() {
setTimeout(function() {
window.addEventListener('popstate', function() {
...
});
}, 0);
});
The solution has been found in jquery.pjax.js lines 195-225:
// Used to detect initial (useless) popstate.
// If history.state exists, assume browser isn't going to fire initial popstate.
var popped = ('state' in window.history), initialURL = location.href
// popstate handler takes care of the back and forward buttons
//
// You probably shouldn't use pjax on pages with other pushState
// stuff yet.
$(window).bind('popstate', function(event){
// Ignore inital popstate that some browsers fire on page load
var initialPop = !popped && location.href == initialURL
popped = true
if ( initialPop ) return
var state = event.state
if ( state && state.pjax ) {
var container = state.pjax
if ( $(container+'').length )
$.pjax({
url: state.url || location.href,
fragment: state.fragment,
container: container,
push: false,
timeout: state.timeout
})
else
window.location = location.href
}
})
A more direct solution than reimplementing pjax is set a variable on pushState, and check for the variable on popState, so the initial popState doesn't inconsistently fire on load (not a jquery-specific solution, just using it for events):
$(window).bind('popstate', function (ev){
if (!window.history.ready && !ev.originalEvent.state)
return; // workaround for popstate on load
});
// ... later ...
function doNavigation(nextPageId) {
window.history.ready = true;
history.pushState(state, null, 'content.php?id='+ nextPageId);
// ajax in content instead of loading server-side
}
Webkit's initial onpopstate event has no state assigned, so you can use this to check for the unwanted behaviour:
window.onpopstate = function(e){
if(e.state)
//do something
};
A comprehensive solution, allowing for navigation back to the original page, would build on this idea:
<body onload="init()">
page 1
page 2
<div id="content"></div>
</body>
<script>
function init(){
openURL(window.location.href);
}
function doClick(e){
if(window.history.pushState)
openURL(e.getAttribute('href'), true);
else
window.open(e.getAttribute('href'), '_self');
}
function openURL(href, push){
document.getElementById('content').innerHTML = href + ': ' + (push ? 'user' : 'browser');
if(window.history.pushState){
if(push)
window.history.pushState({href: href}, 'your page title', href);
else
window.history.replaceState({href: href}, 'your page title', href);
}
}
window.onpopstate = function(e){
if(e.state)
openURL(e.state.href);
};
</script>
While this could still fire twice (with some nifty navigation), it can be handled simply with a check against the previous href.
This is my workaround.
window.setTimeout(function() {
window.addEventListener('popstate', function() {
// ...
});
}, 1000);
Here's my solution:
var _firstload = true;
$(function(){
window.onpopstate = function(event){
var state = event.state;
if(_firstload && !state){
_firstload = false;
}
else if(state){
_firstload = false;
// you should pass state.some_data to another function here
alert('state was changed! back/forward button was pressed!');
}
else{
_firstload = false;
// you should inform some function that the original state returned
alert('you returned back to the original state (the home state)');
}
}
})
The best way to get Chrome to not fire popstate on a page load is to up-vote https://code.google.com/p/chromium/issues/detail?id=63040. They've known Chrome isn't in compliance with the HTML5 spec for two full years now and still haven't fixed it!
In case of use event.state !== null returning back in history to first loaded page won't work in non mobile browsers.
I use sessionStorage to mark when ajax navigation really starts.
history.pushState(url, null, url);
sessionStorage.ajNavStarted = true;
window.addEventListener('popstate', function(e) {
if (sessionStorage.ajNavStarted) {
location.href = (e.state === null) ? location.href : e.state;
}
}, false);
The presented solutions have a problem on page reload. The following seems to work better, but I have only tested Firefox and Chrome. It uses the actuality, that there seems to be a difference between e.event.state and window.history.state.
window.addEvent('popstate', function(e) {
if(e.event.state) {
window.location.reload(); // Event code
}
});
I know you asked against it, but you should really just use History.js as it clears up a million browser incompatibilities. I went the manual fix route only to later find there were more and more problems that you'll only find out way down the road. It really isn't that hard nowadays:
<script src="//cdnjs.cloudflare.com/ajax/libs/history.js/1.8/native.history.min.js" type="text/javascript"></script>
And read the api at https://github.com/browserstate/history.js
This solved the problem for me. All I did was set a timeout function which delays the execution of the function long enough to miss the popstate event that is fired on pageload
if (history && history.pushState) {
setTimeout(function(){
$(window).bind("popstate", function() {
$.getScript(location.href);
});
},3000);
}
You can create an event and fire it after your onload handler.
var evt = document.createEvent("PopStateEvent");
evt.initPopStateEvent("popstate", false, false, { .. state object ..});
window.dispatchEvent(evt);
Note, this is slightly broke in Chrome/Safari, but I have submitted the patch in to WebKit and it should be available soon, but it is the "most correct" way.
This worked for me in Firefox and Chrome
window.onpopstate = function(event) { //back button click
console.log("onpopstate");
if (event.state) {
window.location.reload();
}
};
Searching for a js script, which will show some message (something like "Loading, please wait") until the page loads all images.
Important - it mustn't use any js framework (jquery, mootools, etc), must be an ordinary js script.
Message must disappear when the page is loaded.
Yeah an old-school question!
This goes back to those days when we used to preload images...
Anyway, here's some code. The magic is the "complete" property on the document.images collection (Image objects).
// setup a timer, adjust the 200 to some other milliseconds if desired
var _timer = setInterval("imgloaded()",200);
function imgloaded() {
// assume they're all loaded
var loaded = true;
// test all images for "complete" property
for(var i = 0, len = document.images.length; i < len; i++) {
if(!document.images[i].complete) { loaded = false; break; }
}
// if loaded is still true, change the HTML
if(loaded) {
document.getElementById("msg").innerHTML = "Done.";
// clear the timer
clearInterval(_timer);
}
};
Of course, this assumes you have some DIV thrown in somewhere:
<div id="msg">Loading...</div>
Just add a static <div> to the page, informing user that the page is loading. Then add window.onload handler and remove the div.
BTW, what’s the reason of this? Don’t users already have page load indicators in their browsers?
You should do async ajax requests for the images and add a call back when it's finished.
Here's some code to illustrate it:
var R = new XMLHttpRequest();
R.onreadystatechange = function() {
if (R.readyState == 4) {
// Do something with R.responseXML/Text ...
stopWaiting();
}
};
Theoretically you could have an onload event on every image object that runs a function that checks if all images is loaded. This way you don´t need a setTimeOut(). This would however fail if an image didn´t load so you would have to take onerror into account also.