Reading Parent's URL - javascript

I have an iFrame that is running some Javascript and I want the iFrame to behave differently depending on which page it is loaded into. I found this code which works brilliantly but it shows me the url of the iFrame not the parent.
var Page1 = "page1.html";
var Page2 = "page2.html";
var thisUrl = decodeURI(window.location);
var urlChunks = thisUrl.split("/");
for (var chunk in urlChunks) {
alert('chunk: ' + chunk);
alert('urlChunks[chunk]: ' + urlChunks[chunk]);
if (urlChunks[chunk] == Page1) {
alert('inside index.html');
}
else if (urlChunks[chunk] == Page2) {
}
else
{
}
}
What can I change the
decodeURI(window.location);
to in order to get it to read from the parent.

window.parent.location
Remember that JavaScript has the Same-Origin restriction, so when the parent document is a different origin (eg. domain), you will most probably get an access-denied exception.

Related

How to use postMassage for Cross-domain access when i need to catch two massage in one parent PHP file

I got a problem two days ago, i needed to get height of iframe from another domain and catch it at parent domain to display iframe without scrollbar.
I solved it this way.
PostMessage function at child domain, sending height of div to parent domain.
window.onload = function () {
var offsetHeight = document.getElementById('LoanToggler').offsetHeight;
parent.postMessage(offsetHeight ,"*");
};
And the function at parent domain catches Message coming from child domain.
var myEventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var myEventListener = window[myEventMethod];
var myEventMessage = myEventMethod == "attachEvent" ? "onmessage" : "message";
myEventListener(myEventMessage, function (e) {
if (e.data === parseInt(e.data))
document.getElementById('sizetracker').style.height = e.data + "px";
}, false);
It works dynamicly very well. child's height is always different so function catches it every time and displays at parent domain.
Now about my problem.
For example i have parent.php file at parent domain where i already have one iframe index.php from child domain. I need second iframe too from same child domain but form.php.
I tried this :
Write same postMessage function in form.php but parent domain catches only one massage coming from children. i duplicated cater function at parent domain and chainged variables and function names but this didn't help.
Any ideas ?
Heh, here i find solution at last.
First child php file.
window.onload = function () {
var offsetHeight = document.getElementById('LoanToggler').offsetHeight;
parent.postMessage({v1: offsetHeight} ,"*");
};
Second child php file.
window.onload = function () {
var offsetHeight = document.getElementById('childdiv2').offsetHeight;
parent.postMessage({v2: offsetHeight} ,"*");
};
Parent file where are both iframes. The catcher function everything same as above but only changes two lines :
if (e.data.v1 === parseInt(e.data.v1)){
document.getElementById('sizetracker').style.height = e.data.v1 + "px";
}
if (e.data.v2 === parseInt(e.data.v2)){
document.getElementById('parentdiv2').style.height = e.data.v2 + "px";
}

How to switch to generic auto redirect with delay

I've inherited a site that calls a javascript on every page to prepend every external link with a link to an exit page. On exit.html, a function in the same script (confirmExit) extracts the original intended url, and that’s served up as a link on the page by ID (<p>Continue to:</p>)
Now, instead of the user having to click on exitLink, an automatic redirect with a delay is wanted. Something like "You will now be taken to exitLink in 10 seconds …"
I’ve seen the setTimeout approach, the <META HTTP-EQUIV="refresh" CONTENT="seconds;URL=the-other-url"> approach, and even a form approach for achieving automatic redirects. Problem is, those seem intended for hard-coded, page-specific redirects. I haven’t been able to figure out how to adapt any of these to the js or the exit.html page to make them work. Sorry, I'm still low enough on the javascript learning curve that I can't seem to find the forest for the trees!
Any solution would be greatly appreciated! (Except php - I can't use that)
Here’s the javascript:
window.onload = function() {
wrapExitLinks();
}
function wrapExitLinks() {
var whiteList = "^gov^mil^";
var exitURL = document.location.protocol + "//" + document.location.host + "/exit.html"; // Default exit is /exit.html from referring site
var currentBaseURL = document.location.protocol + "//" + document.location.hostname + document.location.pathname;
var links = document.getElementsByTagName("a");
var linkDest;
var linkTLD;
var govTLD;
/* Do not wrap links on intersitial exit page */
if (currentBaseURL != exitURL) {
for (var i in links) {
if (links[i].host) {
linkTLD = links[i].hostname.substr(links[i].hostname.lastIndexOf(".") + 1); // Extract top level domain from target link
linkDest = links[i].href;
if (whiteList.indexOf("^" + linkTLD + "^") == -1) {
linkDest = exitURL + "?url=" + encodeURIComponent(linkDest);
links[i].href = linkDest;
}
}
}
} else {
confirmExit();
}
}
function confirmExit() {
var queryString = decodeURIComponent(document.location.search.substr(1));
var linkDest = queryString.substr(queryString.indexOf("url=") + 4);
var exitLink = document.getElementById("exitLink");
/* Assume http:// if no protocol provided */
if (linkDest.indexOf("://") == -1) {
linkDest = "http://" + linkDest;
}
exitLink.href = linkDest;
exitLink.innerHTML = linkDest;
}
The basic script you need is simply:
setTimeout(function () { window.location = 'http://example.com'; }, 10000);
That's all. Work it into your script somewhere.

Chrome Extension doesn't considers optionvalue until reloaded

I'm working on my first Chrome Extension. After learning some interesting notions about jquery i've moved to raw javascript code thanks to "Rob W".
Actually the extension do an XMLHttpRequest to a remote page with some parameters and, after manipulating the result, render an html list into the popup window.
Now everything is up and running so i'm moving to add some option.
The first one was "how many elements you want to load" to set a limit to the element of the list.
I'm using fancy-setting to manage my options and here's the problem.
The extension act like there's a "cache" about the local storage settings.
If i do not set anything and perform a clean installation of the extension, the default number of element is loaded correctly.
If i change the value. I need to reload the extension to see the change.
Only if a remove the setting i see the extension work as intended immediately.
Now, i'm going a little more into specific information.
This is the popup.js script:
chrome.extension.sendRequest({action: 'gpmeGetOptions'}, function(theOptions) {
//Load the limit for topic shown
console.log('NGI-LH -> Received NGI "max_topic_shown" setting ('+theOptions.max_topic_shown+')');
//Initializing the async connection
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://gaming.ngi.it/subscription.php?do=viewsubscription&pp='+theOptions.max_topic_shown+'&folderid=all&sort=lastpost&order=desc');
xhr.onload = function() {
var html = "<ul>";
var doc = xhr.response;
var TDs = doc.querySelectorAll('td[id*="td_threadtitle_"]');
[].forEach.call(TDs, function(td) {
//Removes useless elements from the source
var tag = td.querySelector('img[src="images/misc/tag.png"]'); (tag != null) ? tag.parentNode.removeChild(tag) : false;
var div_small_font = td.querySelector('div[class="smallfont"]'); (small_font != null ) ? small_font.parentNode.removeChild(small_font) : false;
var span_small_font = td.querySelector('span[class="smallfont"]'); (small_font != null ) ? small_font.parentNode.removeChild(small_font) : false;
var span = td.querySelector('span'); (span != null ) ? span.parentNode.removeChild(span) : false;
//Change the look of some elements
var firstnew = td.querySelector('img[src="images/buttons/firstnew.gif"]'); (firstnew != null ) ? firstnew.src = "/img/icons/comment.gif" : false;
var boldtext = td.querySelector('a[style="font-weight:bold"]'); (boldtext != null ) ? boldtext.style.fontWeight = "normal" : false;
//Modify the lenght of the strings
var lenght_str = td.querySelector('a[id^="thread_title_"]');
if (lenght_str.textContent.length > 40) {
lenght_str.textContent = lenght_str.textContent.substring(0, 40);
lenght_str.innerHTML += "<span style='font-size: 6pt'> [...]</span>";
}
//Removes "Poll:" and Tabulation from the strings
td.querySelector('div').innerHTML = td.querySelector('div').innerHTML.replace(/(Poll)+(:)/g, '');
//Modify the URL from relative to absolute and add the target="_newtab" for the ICON
(td.querySelector('a[id^="thread_title"]') != null) ? td.querySelector('a[id^="thread_title"]').href += "&goto=newpost" : false;
(td.querySelector('a[id^="thread_goto"]') != null) ? td.querySelector('a[id^="thread_goto"]').href += "&goto=newpost": false;
(td.querySelector('a[id^="thread_title"]') != null) ? td.querySelector('a[id^="thread_title"]').target = "_newtab": false;
(td.querySelector('a[id^="thread_goto"]') != null) ? td.querySelector('a[id^="thread_goto"]').target = "_newtab": false;
//Store the td into the main 'html' variable
html += "<li>"+td.innerHTML+"</li>";
// console.log(td);
});
html += "</ul>";
//Send the html variable to the popup window
document.getElementById("content").innerHTML = html.toString();
};
xhr.responseType = 'document'; // Chrome 18+
xhr.send();
});
Following the background.js (the html just load /fancy-settings/source/lib/store.js and this script as Fancy-Setting How-To explains)
//Initialization fancy-settings
var settings = new Store("settings", {
"old_logo": false,
"max_topic_shown": "10"
});
//Load settings
var settings = settings.toObject();
//Listener who send back the settings
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.action == 'gpmeGetOptions') {
sendResponse(settings);
}
});
The console.log show the value as it has been cached, as i said.
If i set the value to "20", It remain default until i reload the extension.
If i change it to 30, it remain at 20 until i reload the extension.
If something more is needed, just ask. I'll edit the question.
The problem appears to be a conceptual misunderstanding. The background.js script in a Chrome Extension is loaded once and continues to run until either the extension or the Chrome Browser is restarted.
This means in your current code the settings variable value is loaded only when the extension first starts. In order to access values that have been updated since the extension is loaded the settings variable value in background.js must be reloaded.
There are a number of ways to accomplish this. The simplest is to move the settings related code into the chrome.extension.onRequest.addListener callback function in background.js. This is also the most inefficient solution, as settings are reloaded every request whether they have actually been updated or not.
A better solution would be to reload the settings value in background.js only when the values are updated in the options page. This uses the persistence, or caching, of the settings variable to your advantage. You'll have to check the documentation for implementation details, but the idea would be to send a message from the options page to the background.js page, telling it to update settings after the new settings have been stored.
As an unrelated aside, the var keyword in the line var settings = settings.toObject(); is not needed. There is no need to redeclare the variable, it is already declared above.

Is there a client-side way to detect X-Frame-Options?

Is there any good way to detect when a page isn't going to display in a frame because of the X-Frame-Options header? I know I can request the page serverside and look for the header, but I was curious if the browser has any mechanism for catching this error.
OK, this one is old but still relevant.
Fact:
When an iframe loads a url which is blocked by a X-Frame-Options the loading time is very short.
Hack:
So if the onload occurs immediately I know it's probably a X-Frame-Options issue.
Disclaimer:
This is probably one of the 'hackiest' code I've written, so don't expect much:
var timepast=false;
var iframe = document.createElement("iframe");
iframe.style.cssText = "position:fixed; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;";
iframe.src = "http://pix.do"; // This will work
//iframe.src = "http://google.com"; // This won't work
iframe.id = "theFrame";
// If more then 500ms past that means a page is loading inside the iFrame
setTimeout(function() {
timepast = true;
},500);
if (iframe.attachEvent){
iframe.attachEvent("onload", function(){
if(timepast) {
console.log("It's PROBABLY OK");
}
else {
console.log("It's PROBABLY NOT OK");
}
});
}
else {
iframe.onload = function(){
if(timepast) {
console.log("It's PROBABLY OK");
}
else {
console.log("It's PROBABLY NOT OK");
}
};
}
document.body.appendChild(iframe);
Disclaimer: this answer I wrote in 2012(Chrome was version ~20 at that time) is outdated and I'll keep it here for historical purposes only. Read and use at your own risk.
Ok, this is a bit old question, but here's what I found out (it's not a complete answer) for Chrome/Chromium.
the way do detect if a frame pointing to a foreign address has loaded is simply to try to access its contentWindow or document.
here's the code I used:
element.innerHTML = '<iframe class="innerPopupIframe" width="100%" height="100%" src="'+href+'"></iframe>';
myframe = $(element).find('iframe');
then, later:
try {
var letstrythis = myframe.contentWindow;
} catch(ex) {
alert('the frame has surely started loading');
}
the fact is, if the X-Frame-Options forbid access, then myFrame.contentWindow will be accessible.
the problem here is what I called "then, later". I haven't figured out yet on what to rely, which event to subsribe to find when is the good time to perform the test.
This is based on #Iftach's answer, but is a slightly less hacky.
It checks to see if iframe.contentWindow.length > 0 which would suggest that the iframe has successfully loaded.
Additionally, it checks to see if the iframe onload event has fired within 5s and alerts that too. This catches failed loading of mixed content (in an albeit hacky manner).
var iframeLoaded = false;
var iframe = document.createElement('iframe');
// ***** SWAP THE `iframe.src` VALUE BELOW FOR DIFFERENT RESULTS ***** //
// iframe.src = "https://davidsimpson.me"; // This will work
iframe.src = "https://google.com"; // This won't work
iframe.id = 'theFrame';
iframe.style.cssText = 'position:fixed; top:40px; left:10px; bottom:10px;'
+ 'right:10px; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;';
var iframeOnloadEvent = function () {
iframeLoaded = true;
var consoleDiv = document.getElementById('console');
if (iframe.contentWindow.length > 0) {
consoleDiv.innerHTML = '✔ Content window loaded: ' + iframe.src;
consoleDiv.style.cssText = 'color: green;'
} else {
consoleDiv.innerHTML = '✘ Content window failed to load: ' + iframe.src;
consoleDiv.style.cssText = 'color: red;'
}
}
if (iframe.attachEvent){
iframe.attachEvent('onload', iframeOnloadEvent);
} else {
iframe.onload = iframeOnloadEvent;
}
document.body.appendChild(iframe);
// iframe.onload event doesn't trigger in firefox if loading mixed content (http iframe in https parent) and it is blocked.
setTimeout(function () {
if (iframeLoaded === false) {
console.error('%c✘ iframe failed to load within 5s', 'font-size: 2em;');
consoleDiv.innerHTML = '✘ iframe failed to load within 5s: ' + iframe.src;
consoleDiv.style.cssText = 'color: red;'
}
}, 5000);
Live demo here - https://jsfiddle.net/dvdsmpsn/7qusz4q3/ - so you can test it in the relevant browsers.
At time of writing, it works on the current version on Chrome, Safari, Opera, Firefox, Vivaldi & Internet Explorer 11. I've not tested it in other browsers.
The only thing I can think of is to proxy an AJAX request for the url, then look at the headers, and if it doesn't have X-Frame-Options, then show it in the iframe. Far from ideal, but better than nothing.
At least in Chrome, you can notice the failure to load because the iframe.onload event doesn't trigger. You could use that as an indicator that the page might not allow iframing.
Online test tools might be useful.
I used https://www.hurl.it/.
you can clearly see the response header.
Look for X-frame-option. if value is deny - It will not display in iframe.
same origin- only from the same domain,
allow- will allow from specific websites.
If you want to try another tool, you can simply google for 'http request test online'.
This is how I had checked for X-Frames-Options for one of my requirements. On load of a JSP page, you can use AJAX to send an asynchronous request to the specific URL as follows:
var request = new XMLHttpRequest();
request.open('GET', <insert_URL_here>, false);
request.send(null);
After this is done, you can read the response headers received as follows:
var headers = request.getAllResponseHeaders();
You can then iterate over this to find out the value of the X-Frames-Options. Once you have the value, you can use it in an appropriate logic.
This can be achieved through
a) Create a new IFrame through CreateElement
b) Set its display as 'none'
c) Load the URL through the src attribute
d) In order to wait for the iframe to load, use the SetTimeOut method to delay a function call (i had delayed the call by 10 sec)
e) In that function, check for the ContentWindow length.
f) if the length > 0, then the url is loaded else URL is not loaded due to X-Frame-Options
Below is the sample code:
function isLoaded(val) {
var elemId = document.getElementById('ctlx');
if (elemId != null)
document.body.removeChild(elemId);
var obj= document.createElement('iframe');
obj.setAttribute("id", "ctlx");
obj.src = val;
obj.style.display = 'none';
document.body.appendChild(obj);
setTimeout(canLoad, 10000);
}
function canLoad() {
//var elemId = document.getElementById('ctl100');
var elemId = document.getElementById('ctlx');
if (elemId.contentWindow.length > 0) {
elemId.style.display = 'inline';
}
else {
elemId.src = '';
elemId.style.display = 'none';
alert('not supported');
}
}

How to prevent iframe load event?

I have an iframe and couple of tables on my aspx page. Now when the page loads these tables are hidden. The iframe is used to upload file to database. Depending on the result of the event I have to show a particular table on my main page (these tables basically have "Retry","next" buttons...depending on whether or not the file is uploaded I have to show respective button).
Now I have a JavaScript on the "onload" event of the iframe where I am hiding these tables to start with. When the control comes back after the event I show a particular table. But then the iframe loads again and the tables are hidden. Can any one help me with this problem. I don't want the iframe to load the second time.
Thanks
mmm you said you're on aspx page,
I suppose that the iframe do a postback, so for this it reload the page.
If you can't avoid the postback, you've to set a flag on the main page just before posting back, and check against that while you're loading...
...something like:
mainpage.waitTillPostBack = true
YourFunctionCausingPostBack();
..
onload=function(){
if(!mainpage.waitTillPostBack){
hideTables();
}
mainpage.waitTillPostBack = false;
}
I am not sure what your problem is, but perhaps your approach should be a little different. Try putting code into the iframe what would call functions of the parent. These functions would display the proper table:
<!-- in the main page --->
function showTable1() {}
<!-- in the iframe -->
window.onload = function () {
parent.showTable1();
}
This would put a lot of control into your iframe, away from the main page.
I don't have enough specifics from your question to determine if the iframe second load can be prevented. But I would suggest using a javascript variable to check if the iframe is being loaded a second time and in that case skip the logic for hiding the tables,
This is my code
function initUpload()
{
//alert("IFrame loads");
_divFrame = document.getElementById('divFrame');
_divUploadMessage = document.getElementById('divUploadMessage');
_divUploadProgress = document.getElementById('divUploadProgress');
_ifrFile = document.getElementById('ifrFile');
_tbRetry = document.getElementById('tbRetry');
_tbNext=document.getElementById('tblNext');
_tbRetry.style.display='none';
_tbNext.style.display='none';
var btnUpload = _ifrFile.contentWindow.document.getElementById('btnUpload');
btnUpload.onclick = function(event)
{
var myFile = _ifrFile.contentWindow.document.getElementById('myFile');
//Baisic validation
_divUploadMessage.style.display = 'none';
if (myFile.value.length == 0)
{
_divUploadMessage.innerHTML = '<span style=\"color:#ff0000\">Please select a file.</span>';
_divUploadMessage.style.display = '';
myFile.focus();
return;
}
var regExp = /^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.doc|.txt|.xls|.docx |.xlsx)$/;
if (!regExp.test(myFile.value)) //Somehow the expression does not work in Opera
{
_divUploadMessage.innerHTML = '<span style=\"color:#ff0000\">Invalid file type. Only supports doc, txt, xls.</span>';
_divUploadMessage.style.display = '';
myFile.focus();
return;
}
_ifrFile.contentWindow.document.getElementById('Upload').submit();
_divFrame.style.display = 'none';
}
}
function UploadComplete(message, isError)
{
alert(message);
//alert(isError);
clearUploadProgress();
if (_UploadProgressTimer)
{
clearTimeout(_UploadProgressTimer);
}
_divUploadProgress.style.display = 'none';
_divUploadMessage.style.display = 'none';
_divFrame.style.display = 'none';
_tbNext.style.display='';
if (message.length)
{
var color = (isError) ? '#008000' : '#ff0000';
_divUploadMessage.innerHTML = '<span style=\"color:' + color + '\;font-weight:bold">' + message + '</span>';
_divUploadMessage.style.display = '';
_tbNext.style.display='';
_tbRetry.style.display='none';
}
}
tblRetry and tblNext are the tables that I want to display depending on the result of the event.

Categories

Resources