Difficulty constructing Absolute URL - javascript

www.baxter.com source page, shows most of the href links starting with the word baxter, like this -
href="/baxter/corporate.page?">About Baxter<
So the way I can construct an absolute url from the above is by combining the base url, www.baxter.com and the relative url /baxter/corporate.page?giving me www.baxter.com/baxter/corporate.page? which results in 404, cause the actual url is www.baxter.com/corporate.page?
I know how to generally parse relative URLs in PHP but is there a way to sense and remove words from relative urls like these?
Also mouseover on About Baxter on www.baxter.com web page displays the correct url, www.baxter.com/corporate.page? at bottom left of the page - where is this coming from? can it be accessed?
Will deeply appreciate any help/pointers...
EDIT on Nov 7:
In main.js, they are removing /baxter:
var fixer = function() {
var init = function() {
var digitasFinder = /(proto)|(cms-)|(teamsite-)/
, baxterFinder = /(\/baxter\/)/
, $allAnchors = $("a")
, $allForms = $("form");
digitasFinder.test(location.host) || ($allAnchors.each(function() {
var $this = $(this)
, actualHref = $this.attr("href");
if (baxterFinder.test(actualHref)) {
var newHref = actualHref.replace(baxterFinder, "/");
$this.attr("href", newHref)
}
}
),
$allForms.each(function() {
var $this = $(this)
, actualAction = $this.attr("action");
if (baxterFinder.test(actualAction)) {
var newAction = actualAction.replace(baxterFinder, "/");
$this.attr("action", newAction)
}
}
))
}
;
return {
init: init
}
}

Looks like some JavaScript executed on page load is modifying the hrefs of the links.
You could try duplicating the effects of the JS code (ie. remove '/baxter' from the links), or for a more generic solution, you could use a headless browser to execute the JS code and then evaluate the resulting DOM. Look into the Mink project for a PHP-based solution.

Related

Need a javascript function to load new page

My site has English and Spanish versions of each page. The folder structure is identical for both, but all Spanish pages are under a /_spanish folder. For example:
/index.htm is English version
/_spanish/index.htm is Spanish version
I'd like to include a button on each page making it easy to swap languages.
The logic is:
onclick parse the full current page name
if it does not contain /_spanish/
insert /_spanish/ and go to that page e.g. go from http://example.com/index.htm to
http://example.com/_spanish/index.htm
else (it does contain /_spanish/)
remove /_spanish and go to that page e.g. go from http://example.com/_spanish/index.htm to http://example.com/index.htm
Thanks in advance for any help.
I've managed to get this working - not the most elegant, but functional.
<button style="width:100px;height:100px;" onclick="myFunction()"></button>
<script>
function myFunction() {
var host = location.hostname;
var path = location.pathname;
var n = path.indexOf('/_spanish');
var len = path.length;
if (n>-1) {
/* make the new page address without _spanish */
var newpath = path.substr(10,len-9);
var newpage = '/'.concat(newpath);
}
else {
/* make the new page address with _spanish inserted*/
var newpath = path.substr(10,len-9);
var spa = "/_spanish/";
var newpages= spa.concat(path);
/*Replace double // that will occur in sub-directories */
newpage = newpages.replace(/\/\//,"/");
}
window.location.href = newpage;
}
</script>

Cannot load script into iframe

Test page: https://jsfiddle.net/y25rk55w/
On this test page you can see 3 <iframe>'s embeded into each other. Each <iframe> contains a <script> tag in it's <head> tag.
The problem is: only the <script> in the first <iframe> will be loaded by the browser. The other two <script> tags will be present in the dom but the browser will never even try to load them. The problem is not browser specific, it can be reroduced in chrome, firefox, ie. The problem cannot be fixed by adding timeouts or waiting before appending the scripts. It seems to be important that all the iframes have programatically generated content; if you replace this iframes with iframes with actual src links, the problem will disappear.
The question is: how can I actually load a script into iframes 2 and 3?
Full test code:
// It doesn't matter if the scripts exist or not
// Browser won't try to load them either way
var scripts = [
'//testdomain.test/script1.js',
'//testdomain.test/script2.js',
'//testdomain.test/script3.js'
];
function createIFrame(win, onCreated) {
var iframe = win.document.createElement('iframe');
iframe.onload = function () {
onCreated(iframe);
};
win.document.body.appendChild(iframe);
}
function loadScript(win, url) {
var script = win.document.createElement('script');
script.src = url;
script.onload = function() {
console.log("Script " + url + " is loaded.");
};
win.document.getElementsByTagName('head')[0].appendChild(script);
}
createIFrame(window, function(iframe1) {
loadScript(iframe1.contentWindow, scripts[0]);
createIFrame(iframe1.contentWindow, function (iframe2) {
loadScript(iframe2.contentWindow, scripts[1]);
createIFrame(iframe2.contentWindow, function (iframe3) {
loadScript(iframe3.contentWindow, scripts[2]);
});
});
});
Your code is working fine --> http://plnkr.co/edit/vQGsyD7JxZiDlg6EZvK4?p=preview
Make sure you execute createIFrame on window.onload or DOMContentLoaded.
var scripts = [
'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.js',
'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.2/jquery.js',
'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js'
];
function createIFrame(win, onCreated) {
var iframe = win.document.createElement('iframe');
iframe.onload = function () {
onCreated(iframe);
};
win.document.body.appendChild(iframe);
}
function loadScript(win, url) {
var script = win.document.createElement('script');
script.src = url;
script.onload = function() {
console.log("Script " + url + " is loaded.");
};
win.document.getElementsByTagName('head')[0].appendChild(script);
}
window.onload = function(){
createIFrame(window, function(iframe1) {
loadScript(iframe1.contentWindow, scripts[0]);
createIFrame(iframe1.contentWindow, function (iframe2) {
loadScript(iframe2.contentWindow, scripts[1]);
createIFrame(iframe2.contentWindow, function (iframe3) {
loadScript(iframe3.contentWindow, scripts[2]);
});
});
});
};
In the question you can see that I was ommiting the protocol:
/* This is valid to omit the http:/https: protocol.
In that case, browser should automatically append
protocol used by the parent page */
var scripts = [
'//testdomain.test/script1.js',
'//testdomain.test/script2.js',
'//testdomain.test/script3.js'
];
The thing is, programatically created iframes have protocol about: (or javascript:, depending on how you create them). I still can't explain why the first script was loading or why the other two scripts were not showing up in the network tab at all, but I guess it's not very important.
The solution: either explicitly use https:// or programatically append protocol using something like the following code:
function appendSchema(win, url) {
if (url.startsWith('//')) {
var protocol = 'https:';
try {
var wPrev = undefined;
var wCur = win;
while (wPrev != wCur) {
console.log(wCur.location.protocol);
if (wCur.location.protocol.startsWith("http")) {
protocol = wCur.location.protocol;
break;
}
wPrev = wCur;
wCur = wCur.parent;
}
} catch (e) {
/* We cannot get protocol of a cross-site iframe.
* So in case we are inside cross-site iframe, and
* there are no http/https iframes before it,
* we will just use https: */
}
return protocol + url;
}
return url;
}
I've been successful using a simpler method than what the OP proposes in the self-answer. I produce the URLs using:
new URL(scriptURL, window.location.href).toString();
where scriptURL is the URL that needs to be fixed to get a proper protocol and window is the parent of the iframe element that holds the scripts. This can take care of scenarios that differ from the OPs example URLs: like relative URLs (../foo.js) or absolute URLs that don't start with a host (/foo.js). The above code is sufficient in my case.
If I were to replicate the search through the window hierarchy that the OP used, I'd probably do something like the following. This is TypeScript code. Strip out the type annotations to get plain JavaScript.
function url(win: Window, path: string): string {
// We search up the window hierarchy for the first window which uses
// a protocol that starts with "http".
while (true) {
if (win.location.protocol.startsWith("http")) {
// Interpret the path relative to that window's href. So the path
// will acquire the protocol used by the window. And the less we
// specify in `path`, the more it gets from the window. For
// instance, if path is "/foo.js", then the host name will also be
// acquired from the window's location.
return new URL(path, win.location.href).toString();
}
// We searched all the way to the top and found nothing useful.
if (win === win.parent) {
break;
}
win = win.parent;
}
// I've got a big problem on my hands if there's nothing that works.
throw new Error("cannot normalize the URL");
}
I don't have a default return value if the window chain yield nothings useful because that would indicate a much larger issue than the issue of producing URLs. There'd be something wrong elsewhere in my setup.

Reload Parent Window without POST

I am trying to reload a parent window (same domain) with javascript from within an iframe.
window.parent.location.href = window.parent.location.href;
does not work here for some reason (no javascript errors).
I don't believe it is a problem with same origin policy, as the following works:
window.parent.location.reload();
The problem with this option is if the last request was a POST, it gets reloaded as POST.
Any ideas why the first option wouldn't work? Otherwise, is there another method that will reload the page without resubmitting any form data (e.g. perform a fresh GET request to the parent page URL)?
I have also tried:
top.frames.location.href = top.frames.location.href;
window.opener.location.href = window.opener.location.href
and various other iterations.
I tried this code:
window.location.href = window.location.href;
in an ordinary page (no frames) and it had no effect either. The browser must detect that it is the same URL being displayed and conclude that no action needs to be taken.
What you can do is add a dummy GET parameter and change it to force the browser to reload. The first load might look like this (with POST data included, not shown here of course):
http://www.example.com/page.html?a=1&b=2&dummy=32843493294348
Then to reload:
var dummy = Math.floor(Math.random() * 100000000000000);
window.parent.location.href = window.parent.location.href.replace(/dummy=[0-9]+/, "dummy=" + dummy);
Phari's answer worked for me, with a few adjustments to fit my use case:
var rdm = Math.floor(Math.random() * 100000000000000);
var url = window.parent.location.href;
if (url.indexOf("rdm") > 0) {
window.parent.location.href = url.replace(/rdm=[0-9]+/, "rdm=" + rdm);
} else {
var hsh = "";
if (url.indexOf("#") > 0) {
hash = "#" + url.split('#')[1];
url = url.split('#')[0];
}
if (url.indexOf("?") > 0) {
url = url + "&rdm=" + rdm + hsh;
} else {
url = url + "?rdm=" + rdm + hsh;
}
window.parent.location.href = url;
}
I'm sure this could be more efficient, but works ok.

Dynamic Tabs - Load Multiple Children PER Tab

So,
I'm trying to come up with a way to dynamically load content into multiple tabs, where each tab can contain anywhere from one to several elements (reports).
Currently, the reports are loaded on page load with jQuery $.load. I'm using Bootstrap and bootstrap tabs. I found a site that teaches how to load multiple tabs, but not specifically what I need to do. That site is here: http://www.mightywebdeveloper.com/coding/bootstrap-2-tabs-jquery-load-content/
In contrast, each tab is set up more like this:
<div id="tab1">
<div id="report1"></div>
<div id="report2"></div>
</div>
I cannot use the top-level div to load the content, because it will potentially have multiple children. I need to loop through the div's, use regex to parse the ID, and load each report when the tabs are changed.
I haven't yet figured out the regex expression, but it should be fairly simple - the element id will be something like this : "#be78f5aa3-25". This is an alphanumeric 9-character dbid, followed by a hypen, followed by a 1-3 digit integer (not starting in 0). Then I need to split those two strings into separate variables and inject them into an API call.
Anyone looking to load multiple pages into bootstrap tabs may find this of use. I was able to get it working using some regex (specific to my application), placing div's within the tab-pane container's that had an Element Id which could be used to create the report I wanted to load into the container using $.load. I also added a few things for persistent tabs when the user went to another page and then used the back button, and another condition to load the content in the first tab if there was no hash in the URL.
I'm sure it could be cleaned up, but you get the gist..
$(function() {
"use strict";
var baseURL, $navbox;
baseURL = window.location.protocol + "//" + window.location.hostname + "/db/";
$navbox = $("#myTabs");
$navbox.bind("show", function(e) {
var contentID, pattern, selectDiv;
pattern = /#(\Btab|tab\B)?(\Bdropdown|dropdown\B)?([1-9]{1}[0-9]*)/i;
contentID = e.target.toString().match(pattern)[0];
selectDiv = contentID + " > div";
return $(selectDiv).each(function() {
var parts = this.id.match(/(##enter regex here)/);
if (parts) {
$(this).load(baseURL + parts[0]);
return;
}
return $("#myTabs").tab();
});
});
if (window.location.hash) {
$('#myTabs').find('a[href="'+window.location.hash+'"]').tab('show');
}
else {
var elemID = "#"+$('[class^="tab-pane active"]').attr('id') + " > div";
$(elemID).each(function() {
var parts = this.id.match(/(##enter regex here)/);
$(this).load(baseURL + parts[0]);
return $("#myTabs").tab();
});
}
});
$('#myTabs a').click(function (e) {
e.preventDefault();
var bob = jQuery(this).attr("href");
bob = jQuery.trim(bob);
if(bob == "" || bob == "javascript:void(0)") {
return;
}
else {
window.location.hash = $(this).attr('href');
$(this).tab('show');
}
});

Debugging the base URL element with Firebug

I'm adding the base URL tag to the document head using JS, so the relative links on the page work. But it does not take effect, and Firebug (debugging addon for Firefox) shows the <BASE /> element greyed out.. why? Does this mean Firefox cannot understand it or the syntax is incorrect?
Image http://www.freeimagehosting.net/uploads/a3122c1ddd.png
http://www.w3schools.com/TAGS/tag_base.asp
the base tag has two components href and target. Yours seems to be fine. coold you give some example of the links on which it is failing?
see http://ashita.org/StackOverflow/base_test.html for a demonstration. (my test)
Edit: see comments
function addBase(url) {
var regex = /^(https?|ftp):\/\//;
var a = Array.prototype.slice.call(document.getElementsByTagName('a'),0);
var link = Array.prototype.slice.call(document.getElementsByTagName('link'),0);
var script = Array.prototype.slice.call(document.getElementsByTagName('script'),0);
var img = Array.prototype.slice.call(document.getElementsByTagName('img'),0);
var hrefs = a.concat(link);
var srcs = img.concat(script);
var element,href,src;
for (var i=0,len=hrefs.length;i<len;++i) {
element = hrefs[i];
href = element.getAttribute("href");
if (href) {
if (!regex.test(href)) {
href = (url + "/" + href).replace("//","/"); //to handle double slash collision
element.setAttribute("href",href);
}
}
}
for (var i=0,len=srcs.length;i<len;++i) {
element = srcs[i];
src = element.getAttribute("src");
if (src) {
if (!regex.test(src)) {
src = (url + "/" + src).replace("//","/"); //to handle double slash collision
element.setAttribute("src",src);
}
}
}
}
Tested and working in firefox

Categories