views:

5850

answers:

3

Queston:

IE and Firefox / Safari seem to deal differently with BASE HREF and Javascript window.location type requests. First, is this an accurate description of the problem? What's going on? And what's the best cross-browser solution to deal with this situation?

Context:

I have a small PHP flat file sitelet (it's actually a usability testing prototype).

I dynamically generate the BASE tag's HREF value in PHP, i.e. if it's running on our company's server, it's:

$basehref = 'http://www.mysite.com/alpha/bravo/UsabilityTest/';

and on my local dev machine, it's:

$basehref = 'http://ellen.local/delta/echo/foxtrot/UsabilityTest/';

For one of the tasks, I collect some user input, do some transformations on it in Javascript, and send to the server using code like this:

function allDone() {
    // elided code for simplicity of stackoverflow question
    var URI = "ProcessUserInput.php?";
    URI = URI + "alphakeys=" + encodeURI( keys.join(",") );
    URI = URI + "&sortedvalues=" + encodeURI( values.join(",") );
    window.location = URI;
}

Both the javascript file (containing function allDone()) and the processing PHP script (ProcessUserInput.php) live in a subdirectory of UsabilityTest. In other words, their actual URL is

http://www.mysite.com/alpha/bravo/UsabilityTest/foxtrot/ProcessUserInput.php aka

$basehref . '/foxtrot/ProcessUserInput.php'

The Problem

IE's JavaScript basically seems to ignore the BASE HREF. The javascript and the PHP processor live in the same directory, so the call to ProcessUserInput.php works out fine. The input gets processed and everything works fine.

But when I test on Firefox, the JavaScript does appear to use the BASE HREF, because the script's output gets sent to

$basehref . '/ProcessUserInput.php'

This breaks, because ProcessUserInput.php is in a subdirectory of basehref. However, if I add the subdirectory name to the javascript, it no longer works in IE.

Solutions?

I can think of a few ways to solve this:

  • In Javascript, read the HREF property of the BASE tag and manually prepend to var URI in the javascript, calling a fully-resolved absolute URL
  • Process the .js file with PHP and insert the $basehref variable into the script
  • Move the files around
  • Something else?

I'm sure there must be other ways to solve this too. What's the best way to deal with BASE HREF in JavaScript when IE and Firefox apply it differently in JavaScript?

+1  A: 

I believe you want to modify window.location.pathname, not window.location. window.location is a Location object, that has multiple variables. As a result, the effects of changing it is not well defined. However, window.location.pathname is defined as the path relative to the host, which is what you want.

If you want to read up more on the many variables you can change in window.location, I'd check here. According to Mozilla's documentation, changing any variable in window.location should reload the page with a new URL corresponding to those changes.

Daniel Lew
Writing a string to a location is fine, doc'd back as far as JS 1.0. See http://docs.sun.com/source/816-6408-10/location.htm#1193137 – “If you assign a string to the location property of an object, JavaScript creates a location object and assigns that string to its href property.”
bobince
+2  A: 

IE and Firefox / Safari seem to deal differently with BASE HREF and Javascript window.location type requests.

Yes, this is a long-standing difference going back to the early days of Netscape-vs-IE.

IE enforces base-href only at the point a document element is interacted-with. So, you can createElement('a'), set a relative href and click() it*, but the base-href will be ignored; appendChild it to the document containing the base-href, and it'll work.

On the other browsers the base-href is taken as global per-window and always applied. Which is right? It seems to be unspecified. The original JavaScript docs say only that location.hash (and hence, location applied as a string):

represents a complete URL

So setting it to a relative URL would seem to be an undefined operation.

(*: link.click() is a non-standard method supported by IE and Opera)

read the HREF property of the BASE tag and manually prepend

Probably what I'd do, yeah, if you're dead set on using <base>.

bobince
+4  A: 

Using the assign method of window.location seems like the most straightforward answer.

Instead of

window.location = URI;

I'm using this:

window.location.assign( URI );

which is doing the right thing in both IE and Firefox.

Ellen B