... . Others in this group have indicated that
there are other pitfalls, but as I don't use
JavaScript URIs, I've never encountered them.
<snip>
The javascript: pseudo-protocol[1] appears to be totally
un-standardised. I have certainly not been able to find any official
guidelines as to how it should be implemented, and that leaves
implementers reproducing what they recognise in other peoples
implementations with greater or lesser success. That was always going to
be a recipe for inconsistent behaviour across browsers.
However, some clues as to implementation mechanisms have come to light.
For example IE 4 & 5 (but not 5.5+) allow this page:-
<html>
<head><title></title>
</head><body>
<a href="javascript:'cc';" target="_blank">
JavaScript Pseudo-protocol test</a>
</body>
</html>
-which targets a _blank window with the results (the letters - cc - on a
white background), to expose part of the mechanism by viewing the source
of the resulting page:-
JavaScript pseudo-protocol page source from the new window (IE 4 & 5,
Win 98 and NT 4):-
<HTML>
<SCRIPT LANGUAGE=javascript>
var __w='cc';
if(__w!=null)document.write(__w);
</SCRIPT>
</HTML>
The - 'cc'; - that followed the javascript: prefix has been inserted
into the expression - var __w='cc'; - and because the resulting value
of - __w - is not equal to null that value is document.write-ed into the
new page.
Immediately this shows up a shortcoming in the common javascript URL
formulation - javascript:; - (the pseudo-protocol followed by an empty
statement (semicolon)) as the resulting expression would be - var
__w=; -, an assignment with no right hand side, and indeed when targeted
at a new window that javascript URL produces a syntax error on IE 4 & 5.
It is also clear why the use of a return statement within a javascript
URL produces the error - return statement outside of function -, an
error that IE produces even when the URL is targeted at the current
window.
The fact that IE produces the - return statement outside of function -
even when a javascript URL is targeted at the current window
demonstrates that the mechanism used when navigating the current window
is at least similar to the one used when targeting a new window.
However, when targeting the current window - javascript:; - does not
result in a - syntax error - report. It seems that syntax error reports
are internally suppressed while runtime errors are not. On the other
hand, the fact that - javascript:; - is known to be producing a syntax
error on IE 4 & 5, internally suppressed or not, should suggest that it
is a dangerous javascript URL formulation to use as any generated error
is likely to have a knock-on effect somewhere.
It seems that the javascript: pseudo-protocol was originally intended to
allow a JavaScript string to represent the source code for a replacement
HTML page. And that is clearly the primary intention of the IE 4 & 5
implementation code. So - javascript:someFunction(); - becomes - var
__w=someFunction(); - and if the function call returns a string that
string will become the new document source. In allowing the execution of
a function to return the replacement source string this mechanism
facilitates the execution of the function to produce "side effects" and
by ensuring that the function returns a value that equates to null
(usually undefined) the actual replacement of the current document can
be avoided. Ancient browsers did not provide an onclick alternative so
the execution of functions for the "side effect" was the only method of
getting a link element to execute JavaScript when clicked. And that has
become the main use that the javascript: pseudo-protocol is put to.
Though these days you would be hard pressed to find a browser still in
serious use that did not support onclick attributes on link elements.
The javascript: pseudo-protocol implementation on IceBrowser seems to
have been designed around this shift of emphasis to the execution
functions for the "side effects" and while it does execute the function
it does not ever use any returned string as new document source. Exactly
how many other browsers may have implemented the javascript:
pseudo-protocol in a way that only works for "side effects" but cannot
provide new source for the document is impossible to say, but it is not
surprising that this has happened given no clear documentation on what -
href="javascript:someFunction();" - is supposed to do.
But even with inconsistent, undocumented and ill-defined implementations
the biggest problem with the javascript: pseudo-protocol is that
clicking on <a href="javascript:someFunction();">...</a> may represent
navigation to the browser, even when the current page will never be
replaced by the "side effect" code. The most widely complained of
consequence of this type of "navigation" is that some browsers
(including some version of Windows IE) will immediately stop playing GIF
animations (though many others have come up in c.l.j questions from time
to time [2]). What seems to happen is that once the HREF has been
activated the browser, thinking that it is navigating, puts the current
page into a new state, pending replacement, in which it stops to do
seemingly redundant resource hungry activity.
As a result some features may become unavailable to JavaScript or just
cease to work. Exactly which, if any, features stop working when a
JavaScript URL is clicked on seems to depend entirely on the version of
the browser in use, with browsers for Linux and Mac seeming to manifest
more problems in this area than browsers for Window. That is a bit of a
problem in itself as many do not do much testing on non-windows systems
and may write a lot of code before encountering any manifestation of a
problem resulting from the use of the javascript pseudo-protocol, and
even when encountered may not be able to associate the cause with the
effect (or be willing to recognise the relationship given years of
apparently successful use of javascript URLs).
Unfortunately this leaves only two options if the goal is to write
reliable cross-browser/platform JavaScript, 1. using javascript URLs and
then testing on every version of ever browsers on every platform to
ensure that the consequences of any implied navigation do not manifest
themselves in a way that effects the script (not really a practical
option), or 2. follow the general advice and just *never* use a
javascript URL in an HREF.
Richard.
[1] It has been suggested that "javascript: pseudo-protocol" might not
be the most accurate term to be using. I quite like it, it does not seem
to result in any misidentification of its subject and the "pseudo"
prefix is appropriately deprecating.
[2] I did consider going through the google archives and trying to turn
up some other concrete examples of the results of the "navigation"
aspects of the use of the javascript: pseudo-protocol but I could not
think of a search that would find those and not be swamped with
thousands of posts that just recommend that it is not used.