Script not working on page load, but working from console - javascript

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.

Related

'Uncaught TypeError' only on first page load only in Chrome on desktop. Works on second or more page loads. What is happening?

I have this problem that only exists on first page load in Chrome on desktop. It works in Chrome on the second or more page loads. It also works on mobile in Chrome on every page load.
It works fine in Safari and Firefox, MOST OF THE TIME. I have experienced the below error there as well, only on first page load, only on desktop, but I am not able to reproduce it there for about an entire day now.
Does anyone know what is going on?
The only thing I have been able to come up with is that somehow my redirect function is triggered. Because as you can see in the flow indicated below at number 6, after the error, the page redirects back to index.html. However that function would only trigger if the value of one of my sessionStorage values is null and I can see in the browser console that those values are set correctly when I press the button to go to the next page.
The error:
The flow:
Landing page is index.html with separate index.js
Upon selection of a few drop-downs, 3 values are stored in sessionStorage
Next page is called: normal-quiz.html with separate normal-quiz.js
Values from sessionStorage are retrieved to filter a data array
The loadQuiz function runs on the filtered array and sets a question element value to an object's 'english' property
On first page load, only in Chrome on desktop, the above error occurs which makes the browser return to index.html and sessionStorage is cleared
If I try the above again, it works without a problem
The line generating the error is where I use the loadQuiz function to set the question element's value in my html to the 'english' property value of the first object in the filtered array.
The code (js):
function redirect() {
if (selectedBook !== null) {
// do nothing
} else {
window.location = "<myURL>"
};
};
redirect();
function loadQuiz() {
const currentQuizData = quizArr[currentQuiz]; // currentQuiz is the question counter. It starts at 0 to get the first object, then increments by 1 after each question
questionEl.innerText = currentQuizData.english;
// line above is where the error is generated
counter.innerText = (currentQuiz + 1) + "/" + quizArr.length;
};
loadQuiz();

javascript - Getting the iframe's URL after reload of iframe content doesn't work in Chrome and Safari

I'm working on a phaser game that's to be embedded in a website via iframe. The game supports multiple languages, so we've taken to using the site the game was accessed from as an indicator (phaser-game.com/ru would be in Russian, phaser-game.com/ar would be in Arabic, etc).
Here's the code so far (fired via window.addEventListener('load', getDomainSetLanguage);:
function getDomainSetLanguage()
{
let url = (window.location !== window.parent.location) ? document.referrer : document.location.href;
console.log('url = ' + url);
for (let i = 0; i < COUNTRIES_DOMAIN.length; i++)
{
if (url.indexOf(COUNTRIES_DOMAIN[i].URL) >= 0)
{
DOMAIN_ID = COUNTRIES_DOMAIN[i].ID;
LANGUAGE_ID = COUNTRIES_DOMAIN[i].LANGUAGE_ID;
break;
}
}
if (DOMAIN_ID === -1)
{
DOMAIN_ID = 1;
}
if (LANGUAGE_ID === -1)
{
LANGUAGE_ID = 1;
}
console.log('DOMAIN_ID = ' + DOMAIN_ID + "; LANGUAGE_ID = " + LANGUAGE_ID);
}
Now this works fine, on the surface. However, the game does trigger a reload every now and then, and when the game comes back, it now gets it's own URL, not the parent's / iframe's.
This has the result of the game language defaulting to English.
Note that this only occurs in Chrome and Safari. FireFox works just fine.
Is there something I'm missing? Or is there anything else I can try?
I've tried logging the values of document.referrer and document.location.href, but I'm just getting browser errors about permissions and stuff and the game defaults to English.
I read from here that Chrome (and possibly Safari) doesn't fire the onload function of objects in the iframe, but I'm not sure if this applies to me, as I have a lot of other functions tied to onload that do work.
It should be mentioned that I cannot modify the iframe itself, so any solution must be from the game itself.
Thanks!
let url = (window.location !== window.parent.location) ? document.referrer : document.location.href;
This line from your code makes it so that when you're inside of an iframe, document.referrer is used as the URL to determine the language from.
As per the MDN page on Document.referrer:
The Document.referrer property returns the URI of the page that linked to this page.
Inside an <iframe>, the Document.referrer will initially be set to the same value as the href of the parent window's Window.location.
This means it will work on initial load just fine, as you've experienced.
As far as I can tell, the specification isn't explicit about how to handle reloading. This is probably the cause of the differences in browser behaviour. It isn't too crazy to think that is should be empty after a reload, as it wasn't loaded from the parent page that time around.
An alternate solution would be to use window.parent.location.href, which always refers to the URL of the iframe's parent window (read more in Difference between document.referrer and window.parent.location.href).
Your line of code could look something like this:
// if parent and child href are equal, using either yields the same result
// if there is no parent, window.parent will be equal to window
// therefore, the conditional statement isn't necessary
let url = window.parent.location.href;

How do I navigate to bing.com and enter a search text using the chrome console?

Below is my code.
It is resulting in unexpected behaviour.
It navigates to bing.com but it does not fill in the text field. Also, I have noticed that the console get cleared after navigating to a new webpage.
window.location = "https://www.bing.com";
window.onload = function(){
var editSearch = document.getElementById("sb_form_q");
editSearch.value = "Quux";
}
You are binding the onload function to the existing window object.
When the browser loads the new page, it will make a new window object which won't have your property set on it.
JavaScript run in one page (even when you are running it through developer tools) can't persist variables onto a different page.
(Storage mechanisms like localStorage and cookies are available, but you would need code in the subsequent page to look for them).
JavaScript is only valid for the current page you are on. When you are executing code from DevTools console, you are executing code on that page itself. So, when you navigate to another page using window.location you loose the onload handler you have defined.
To add handlers to a different page, it must be connected to your page (the parent) in some way, like an iframe or a popup.
ifrm = document.getElementById('frame');
ifrm.src = 'http://example.com';
ifrm.contentWindow.onload = function () {
// do something here with
// ifrm.contentWindow.document.getElementById('form')
}
As #Quentin said.
But you can do another way like ..
var keyword = "Quux";
window.location = "https://www.bing.com/search?q="+keyword;

Chrome JavaScript location object

I am trying to start 3 applications from a browser by use of custom protocol names associated with these applications. This might look familiar to other threads started on stackoverflow, I believe that they do not help in resolving this issue so please dont close this thread just yet, it needs a different approach than those suggested in other threads.
example:
ts3server://a.b.c?property1=value1&property2=value2
...
...
to start these applications I would do
location.href = ts3server://a.b.c?property1=value1&property2=value2
location.href = ...
location.href = ...
which would work in FF but not in Chrome
I figured that it might by optimizing the number of writes when there will be effectively only the last change present.
So i did this:
function a ()
{
var apps = ['ts3server://...', 'anotherapp://...', '...'];
b(apps);
}
function b (apps)
{
if (apps.length == 0) return;
location.href = apps[0]; alert(apps[0]);
setTimeout(function (rest) {return function () {b(rest);};} (apps.slice(1)), 1);
}
But it didn't solve my problem (actually only the first location.href assignment is taken into account and even though the other calls happen long enough after the first one (thanks to changing the timeout delay to lets say 10000) the applications do not get started (the alerts are displayed).
If I try accessing each of the URIs separately the apps get started (first I call location.href = uri1 by clicking on one button, then I call location.href = uri2 by clicking again on another button).
Replacing:
location.href = ...
with:
var form = document.createElement('form');
form.action = ...
document.body.appendChild(form);
form.submit();
does not help either, nor does:
var frame = document.createElement('iframe');
frame.src = ...
document.body.appendChild(frame);
Is it possible to do what I am trying to do? How would it be done?
EDIT:
a reworded summary
i want to start MULTIPLE applications after one click on a link or a button like element. I want to achieve that with starting applications associated to custom protocols ... i would hold a list of links (in each link there is one protocol used) and i would try to do "location.src = link" for all items of the list. Which when used with 'for' does optimize to assigning only once (the last value) so i make the function something like recursive function with delay (which eliminates the optimization and really forces 3 distinct calls of location.src = list[head] when the list gets sliced before each call so that all the links are taken into account and they are assigned to the location.src. This all works just fine in Mozilla Firefox, but in google, after the first assignment the rest of the assignments lose effect (they are probably performed but dont trigger the associated application launch))
Are you having trouble looping through the elements? if so try the for..in statement here
Or are you having trouble navigating? if so try window.location.assign(new_location);
[edit]
You can also use window.location = "...";
[edit]
Ok so I did some work, and here is what I got. in the example I open a random ace of spades link. which is a custom protocol. click here and then click on the "click me". The comments show where the JSFiddle debugger found errors.

chrome.windows.getCurrent is not returning the list of opened tabs

var windows = chrome.windows.getCurrent(
function(windows){
try{
// dont really know why this is null. it should be a list of tabs.
if(windows.tabs == null)
alert(windows.type + " " + windows.id);
}
catch(e){
alert(e);
}
});
I am using this code to get all the open tabs in the current window. But the window.tabs is always null even though there are tabs open in the current window. Is there something wrong with the concept of current window.
Could anyone please explain what is it that i am doing wrong.
Thanks.
Looks like the windows object that gets passed to your callback doesn't have a tabs field. Try this code instead:
chrome.windows.getCurrent(function(win)
{
chrome.tabs.getAllInWindow(win.id, function(tabs)
{
// Should output an array of tab objects to your dev console.
console.debug(tabs);
});
});
Also ensure that you have the tabs permission. I also ran this on a background page, so if you're not running it on a background page, you should make sure chrome.tabs is available in your context.

Categories

Resources