Why does setting window.location.href not stop script execution - javascript

The following code changes the location to www.bing.com regardless of wether redirect is 1 or any other number. If redirect is 1, it logs "is redirecting" and then redirects to www.bing.com. My best guess is that when href is set a change-event is triggered, but it takes some ticks before it executes. Meanwhilethe first line of code after is still executed. Or? do anyone what happens?
if (redirect == 1) {
console.log("is redirecting");
window.location.href = "http://www.google.com";
}
window.location.href = "http://www.bing.com";

You are setting a property, not calling a method, the difference is important:
window.location.href = "something";
Javascript works asyncronous and event based,
that means the browser doesn't check for the window location changing right when you set the property, but some unpredictable time later.
Sometimes you want exit-events to be triggered or fired when the location changes.
When you compare this to the HTTP location header, the behaviour is the same.
Sometimes you want for example PHP scripts to continue even you send the location change header.

I would say the behaviour is undefined.
When you set the expected url to window.location.href, the current page will actually be in the dying state. And the result of the code written after that is simply unpredictable.

That's because everything after the if is executed as well, but it looks like there's a difference between Chrome and FF (haven't tested in IE).
Example code:
var redirect = 1;
if (redirect == 1) {
console.log("is redirecting");
document.location.assign('https://developer.mozilla.org/');
}
alert('go');
document.location.assign('https://www.bing.com/');
In Chrome 'go' is alerted, and you're redirected to bing.com.
In Firefox, 'go' is alerted, but you're redirected to MDN.
I think, the best thing to do is to wrap the other stuff in an else.

Related

Javascript: How to make sure window.open returns same window, if already opened

I am working on a web based application, in which I have to open popup window. I am using window.open() method to open the popup, like this:
window.open(url, "popupWin");
where url contains the URL I would like my popup window to navigate to. Now, the problem is, if I execute window.open() from multiple tabs (with same or different URLs), at least on Chrome, it might / might not give you the same window which was opened earlier. This behaviour is inconsistent, I mean, either it should get me fresh window every time, or it should get me previously opened window every time.
I need to persist the same popup window for entire domain. How can I do that?
Well looks like there is a direction to go or at least to give it a try.
It fully remains on localStorage which gives you ability to share the knowledge across your tabs within a single domain.
The code I give below does not work yet (it is only a direction), so don't expect too much from running it as it is.
What it does: it saves the popups by the url in a localStorage and when you try to open a new one with the same url it won't do that. If you don't want to distinguish them by URL it is even simpler: store boolean in a localStorage instead of an object.
What it does not do but should:
it should listen to the popup onunload (close) event and reset the localStorage information accordingly. Best for you here is just to set your localStorage boolean value to false
it should listen to the current tab onunload (reload, close) event and also reset something according to Your logic. As I understand the best for you would be just check whether this tab is the last one from your domain (you can also do this using localStorage, e.g. on every new tab adding its identifier, e.g. creation timestamp and destroying it on tab close) and if it is set your localStorage boolean value to false.
This, I think, would be enough to solve the problem. And finally a small piece of code:
// get the localstorage url map
function getOpenPopups() {
var obj = localStorage.getItem('mypopups');
return obj ? JSON.parse(obj) : {};
}
// set the localstorage url map
function setOpenPopups(object) {
localStorage.setItem('mypopups', JSON.stringify(object))
}
// open the popup
function popup(url, title) {
var popups = getOpenPopups();
// check whether popup with this url is already open
// if not then set it and open the popup
if (!popups[url]) {
popups[url] = true;
setOpenPopups(popups);
return window.open('abc', 'cde');
}
else {
return false;
}
}
jsFiddle
From w3c documentation we can see that window.open() returns a reference to the newly created window, or null if the call failed. That means we can keep it in memory and check for closed flag of that window.
var newWindow = window.open('/some/path', 'TestWindow');
// ...
if (!newWindow.closed) {
}
Keep in mind that if window with following name exists, page will be loaded in the same window without opening new one.
Other variants of name parameter like _blank, _self, _top, _parent you can find in official docs too.

Script not working on page load, but working from console

I wrote a script that's running from ebay listing iframe. It's working fine, it runs on $(document).ready(), sends an AJAX request to a remote server, gets some info, manipulate the DOM on 'success' callback, everything working perfect...
However, I added a piece of code, which should get the document.referrer, and extract some keywords from it, if they exist. Specifically, if a user searches ebay for a product, and clicks on my product from the results, the function extracts the keywords he entered.
Now, the problem is, that function is not running on page load at all. It seems like it blocks the script when it comes to that part. This is the function:
function getKeywords(){
var index = window.parent.document.referrer.indexOf('_nkw');
if (index >= 0){
var currentIndex = index + 5;
var keywords = '';
while (window.parent.document.referrer[currentIndex] !== '&'){
keywords += window.parent.document.referrer[currentIndex++];
}
keywords = keywords.split('+');
return keywords;
}
}
And I tried calling two logs right after it:
console.log('referrer: ' + window.parent.document.referrer);
console.log(getKeywords());
None of them is working. It's like when it comes to that 'window.parent.document.referrer' part, it stops completely.
But, when I put this all in a console, and run it, it works perfectly. It logs the right referrer, and the right keywords.
Does anybody know what might be the issue here?
The reason it is working on the console is because your window object is the outer window reference and not your iframe. Besides that, on the console:
window.parent === window
// ==> true
So, on in fact you are running window.document.referrer and not your frame's window.parent.document.referrer.
If you want to access your frame's window object you should something like
var myFrame = document.getElementsByClassName('my-frame-class')[0];
myFrame.contentWindow === window
// ==> false
myFrame.contentWindow.parent.window === window
// ==> true
This might help you debug your problem, but I guess the browser is just preventing an inner iframe from accessing the parent's window object.

javascript window.location issue with IE and Firefox

I have some strange behavior on my window.location redirects in IE and Firefox as part of my angular application. When calling window.location = xyz the first time it works fine in IE/FF/Chrome. On the second call which is supposed to go to google.com, Chrome does what it's supposed to, but IE and FF don't do anything. In the IE web console I can see that the navigation was triggered but the page and URL hasn't changed in my window. Now if I press F5 on this page it goes to the page it's supposed to even though the URL at the top is not pointing there (both in IE and FF).
Has anyone ever encountered this problem and knows how to solve it? I've tried all versions of redirecting (window.location, window.location.href, windows.location.assign(), window.location.replace() and also the angular service $window) with no luck.
First call triggered from a button press (working fine in all browsers):
$scope.pressButton = function() {
var url = 'xyz/index.html';
$window.location = url;
};
Second call triggered by a keypress (only works in Chrome):
function exitModule() {
$window.location = 'http://www.google.com';
console.log('window.location'); // still pointing to the old page
}
Update with code calling the exitModule() function:
Note: The application is built with angularjs.
The exitModule() function gets called in all browsers, it's just the redirect which doesn't happen in IE/FF.
HTML:
<body ng-app="myModule" ng-controller="MainCtrl" ng-keydown="keyPress($event);">
JS:
// Handle global key press
$scope.keyPress = function(event){
if(event.which === 27) { // EscapeKey
exitModule();
} else {
$scope.$broadcast('keyPress', event);
}
};
Alright I found the issue and I'm aware that it was almost impossible to figure this out without having the full code available. The above code was a bit simplified therefore it was missing the problem. The function exitModule gets called as soon as a promise is resolved. The call looks like this:
Correct
dataService.saveModule().then(exitModule);
My code was as shown below with the brackets after exitModule which is wrong. I don't quite understand the behavior of FF/IE compared to Chrome though ...but that's for another day.
Wrong
dataService.saveModule().then(exitModule());

Check if window.history.go successful?

Is there anyway to check if a window.history.go command is successful in changing the window.location or not?
i.e. If I do a window.history.go(-5) when there are only 3 pages in the history stack, the browser will do nothing.
Is there a way to check if that happens and run other code? An error callback, of sorts.
Thanks.
For an immediate response, first you'll want to check history.length to make sure it is at least 6, e.g. to go -5. Apart from that, I think the only way is to use setTimeout and if the script is still running, the callback will be executed.
Not really a JS expert, but if you want to perform some action when the user goes back or forward, you could use URL hashes and trigger some function using the jQuery onhashchange event. This will not give you the position in history, and i'm also not sure about cross-browser compatibility, but it did the job for me so far.
$(window).on('load' function(){
var hash = parent.top.location.hash;
if(hash == '' || hash == '#' || hash == null){
//if none, set a hash and reload page
parent.top.location.hash = '#/some/hash';
parent.top.location.reload(true);//use true if you dont want to use cached items
}
});
$(window).on('hashchange', function(){
do_something(parent.top.location.hash);
});
function do_something(hash){
//this function will be executed each time the '#' changes
console.log('hash changed to '+hash);
}

Page history - back button exists?

Is it possible check if there is a value for history.go(-1)? I know you can't access history.previous directly.
I am trying to stay away from document.referrer because I know it can be blocked in some instances.
Here is what I am trying to do. I have an error page, on this page I would like to either have a BACK button (if it's not the only item in history) or a close button (if it is).
if (history.length) {
//There is history to go back to
history.go(-1);
}
Actually, history.length is always one or more, since the current page counts. Also, if you have a forward history (i.e. you used the back button), those pages also count. So you need a more complicated check:
if( (1 < history.length) && document.referrer ) {
There is no cross-browser approach to accomplish this. Document.Referrer may be set even if no history entry exists.
I came up with the following "hack". It utilizes the onbeforeunload event to detect whether the browser starts leaving the page or not. If it does not in a certain timespan it'll just redirect to the fallback.
window.goBack = function goBack(fallback){
var useFallback = true;
window.onbeforeunload = function(){
useFallback = false;
}
window.history.back();
setTimeout(function(){
if (useFallback){ window.location.href = fallback; }
}, 100);
}
You can call this function using goBack("fallback.example.org").
One of the use cases is that you may want to add a back button to any page and also want to make sure that this back button works even if the user goes directly to this page (e.g. by bookmark, direct link etc).
So either it does perform a history.back() or if there is no entry, it'll redirect to a fallback.
If the history has a length greater than 0, then it contains at least one history point.
if (history.length)
function test() {
document.URL = document.referrer;
}

Categories

Resources