A tag: href vs. onClick

U

usenet

See

<ul>
<li><a name="link1" onClick="alert(this.name);return false;"
href="#">Link1</a></li>
<li><a name="link2" href="javascript:alert(this);">Link2</a></li>
<li>Item 3</li>
</ul>

Clicking on the first list item gives me "link1" because "this" refers
to the A node so this.name returns the value of the name attribute of
that node.

But in the second link, "this" seems to refer to the window node!

Why is this? Why does the meaning of "this" change so drastically when
used in a href=javascript: vs. a onClick=

Thanks
 
R

Randy Webb

(e-mail address removed) said the following on 10/22/2005 11:00 PM:
See

<ul>
<li><a name="link1" onClick="alert(this.name);return false;"
href="#">Link1</a></li>
<li><a name="link2" href="javascript:alert(this);">Link2</a></li>
<li>Item 3</li>
</ul>

Clicking on the first list item gives me "link1" because "this" refers
to the A node so this.name returns the value of the name attribute of
that node.

But in the second link, "this" seems to refer to the window node!

Yeppers. Because the javascript: pseudo-protocol is executed in the
global context.
Why is this? Why does the meaning of "this" change so drastically when
used in a href=javascript: vs. a onClick=

this doesn't change, what changes is the context in which it is executed.

Don't use javascript:, use the onclick and you don't have that problem.
 
L

Lee

(e-mail address removed) said:
See

<ul>
<li><a name="link1" onClick="alert(this.name);return false;"
href="#">Link1</a></li>
<li><a name="link2" href="javascript:alert(this);">Link2</a></li>
<li>Item 3</li>
</ul>

Clicking on the first list item gives me "link1" because "this" refers
to the A node so this.name returns the value of the name attribute of
that node.

But in the second link, "this" seems to refer to the window node!

Why is this? Why does the meaning of "this" change so drastically when
used in a href=javascript: vs. a onClick

The onclick handler is a method of the link. The "javascript:"
pseudo-protocol is a mechanism for loading new content into the page.
For example:

<a href="javascript:(new Date()).toLocaleString()">What time is it?</a>

Using it to execute arbitrary functions is a perversion of its intended
function. Since it is loading new content into the page, the page
(ie, the window) is its execution context.
 
V

VK

<a href="javascript:(new Date()).toLocaleString()">What time is it?</a>

I'd just like to point again that you *never ever* should use
javascript:someFunction() syntacs. The only place and time for it is
when you're replacing the current page by a new HTML page generated by
someFunction.

To call JavaScript from javascript: while staying on the same page you
have to use void() wrapper:
javascript:void(whateverYouWant)
Otherwise it's going to be a gross misuse of javascript:
pseudo-protocol.
 
T

Thomas 'PointedEars' Lahn

Why is this? Why does the meaning of "this" change so drastically when
used in a href=javascript: vs. a onClick=

Because it relies on `javascript:', a proprietary, almost undocumented URI
scheme. Implementors cannot be blamed in any way if they do not implement
code attached there to be run in the context of the element object that
fired the event but instead in the global context (and so have pointing
`this' to the Global Object instead which happens to be the current
`window' object in most/all HTML DOMs).


HTH

PointedEars
 
R

Richard Cornford

VK said:
I'd just like to point again that you *never ever* should use
javascript:someFunction() syntacs. The only place and time
for it is when you're replacing the current page by a new
HTML page generated by someFunction.

To call JavaScript from javascript: while staying on the same
page you have to use void() wrapper:
javascript:void(whateverYouWant)
Otherwise it's going to be a gross misuse of javascript:
pseudo-protocol.

The void operator produces an expression that results in the value -
Undefined -. It takes the value of its operand and throws it away, and
evaluated to Undefined instead. Whenever a function call is that
operand, and that function itself returns - Undefined -, using that
function call as an operand to - void - is redundant and pointless.

If the value of the expression was such that not applying the - void -
operator would result in the replacement of the current document, and
the replacement of the current document was not desired, then applying
the - void - operator would make sense. But suggesting that all function
calls used in a javascript pseudo-protocol context should be made into
operands of - void - is taking an action that has a known rational, an
purpose under _some_ circumstances, and promoting it to the status of a
mystical incantation, to be chanted in the face of all javascript HREFs.
This does not represent a contribution to computer programming.

Richard.
 
R

Richard Cornford

<ul>
<li><a name="link1" onClick="alert(this.name);return false;"
href="#">Link1</a></li>
<li><a name="link2" href="javascript:alert(this);">Link2</a></li>
<li>Item 3</li>
</ul>

Clicking on the first list item gives me "link1" because "this"
refers to the A node so this.name returns the value of the name
attribute of that node.

But in the second link, "this" seems to refer to the window node!

Why is this? Why does the meaning of "this" change so drastically
when used in a href=javascript: vs. a onClick=

The only circumstances under which the - this - keyword refers to
anything other than the global object (which is also the window object
in web browsers) is when a function is *executed* as a method of an
object.

A web browser will take he string provided as the value of an onclick
attribute and use it as the body of a function that it creates
internally and attaches to the - onclick - property of the corresponding
element in the DOM. When the corresponding event occurs this internally
generated function is called as a method of the element in question, and
so the - this - reference has the normal handling for methods and refers
to the element.

Code executed as a result of acting upon a javascript pseudo-protocol
HREF is not executed as a function at all. This can be demonstrated by
executing - href="javascript:return false;" -, which produces a syntax
error along the lines of 'return outside of function'.

The javascript pseudo-protocol is unspecified and nearly undocumented so
its actual behaviour is uncertain, implementation depended and extremely
variable. In the past it has been possible to extract clues about the
behaviour of specific implementations, for example, in IE 4 triggering:-

<a href="javascript:'cc';" target="_blank">
Javascript Pseudo-protocol test</a>

- had the effect of opening a new window (because of target="_blank")
and viewing the source in that new window showed:-

<HTML>
<SCRIPT LANGUAGE=javascript>
var __w='cc';
if(__w!=null)document.write(__w);
</SCRIPT>
</HTML>

- and so provided an insight into how IE 4 implemented the javascript
pseudo-protocol. Later IE versions removed the ability to see this code
by viewing the source of such a pop-up.

You will observe that the code following the - javascript:- in the HREF
(the string literal 'cc' in this case) is inserted into a code block in
a context where it represents the right hand side of an assignment
expression that is executed as an ExpressionStatement in a global
context. The result of the evaluation of that expression (as assigned to
the global variable - __w -) is then tested for type-converted
equivalence with - null - and, when _not_ equivalent, passed through the
document.write method (with all of its implications for the destruction
of any "current" document).

It has also been observed that executing a javascript pseudo-protocol
HREF in some browsers triggers a 'state' change. Apparently a result of
'navigation' associated with the expected outcome of triggering any
link's HREF (and the resulting anticipated replacement of the page's
contents). The most evident symptom of this 'state' change is provided
by Windows IE, where triggering a javascript pseudo-protocol HREF
immediately terminates the animation of animated GIF images. However,
many other unexpected symptoms are suspected to be a result of this
'state' change, and so it can only be reasonably recommended that
javascript pseudo-protocol HREFs never be used unless their expected
action is to replace the current page (or page contents) in the browser.

Richard.
 
V

VA

Thanks for everyone's input.

To summarize: When the javascript: pseudo-protocol is used in the HREF
attribute of the A tag, it executes in the global context and so "this"
refers to the window object. When it is used in the onClick event
handler, the "this" refers to the A node.

I was surprised to get so much "never ever use the href=javascript:
URI, it is baaad, evil, etc" comments. Come on guys, leave the
"language purists" stuff aside...In 2005, is there any modern
website/web app that really runs at all if I turn off Javascript.
Client-side scripting and DOM manipulation is so ingrained in the web
development world that it can safely be taken for granted. So, to me,
href="javascript:something()" and onClick="something();return false;"
are really equivalent for all practical intents and purposes. Of
course, If you need to use "this" in your function and need it to refer
to the A node, use the event handler variant, simple.

Thanks
 
V

VA

Richard said:
It has also been observed that executing a javascript pseudo-protocol
HREF in some browsers triggers a 'state' change. Apparently a result of
'navigation' associated with the expected outcome of triggering any
link's HREF (and the resulting anticipated replacement of the page's
contents).

I am not sure I understand. The expected outcome of triggering any
link's HREF is not always to replace the page's content. Even if we
leave Javascript out of this, how about <a href="#anchor">? Following
that HREF just navigates to a different section of the currently loaded
document. So does this also trigger the "state change" you mention?

Thanks
 
P

PointedEars

VA said:
To summarize: When the javascript: pseudo-protocol is used in the HREF
attribute of the A tag, it executes in the global context and so "this"
refers to the window object.

Maybe, maybe not. That's the problem with proprietary features.
When it is used in the onClick event handler, the "this" refers to the
A node.

Most certainly.
I was surprised to get so much "never ever use the href=javascript:
URI, it is baaad, evil, etc" comments. Come on guys, leave the
"language purists" stuff aside...

Some things work reliably, others don't. This has nothing to do with
purity, it has to do with how to get the job done and maintained
efficiently. `href="javascript:..."' is considered a Bad Thing for
good reasons. One reason is that it is not reliable (as you have
experienced) and another one that it does not only not degrade
gracefully itself, using it in place of a proper `http:' URI prevents
the link from degrading gracefully.
In 2005, is there any modern website/web app that really runs at
all if I turn off Javascript.

Oh yes, there are plenty. And the more plain ignorance towards the user
such as displayed by you is taken away from the minds of Web designers, the
more they become Web authors who write for their readers, the less services
will no longer not degrade gracefully, so allowing hopefully *all* users an
adequate experience of the presented content, whether they use a desktop
PC, a notebook, a PDA, a mobile phone, a Braille line, a reading machine,
a printer or any other device.
Client-side scripting and DOM manipulation is so ingrained in the web
development world that it can safely be taken for granted.

Definitely not. But you are still missing the point anyway.
So, to me, href="javascript:something()" and onClick="something();return
false;" are really equivalent for all practical intents and purposes.

They are not.
Of course, If you need to use "this" in your function and need it
to refer to the A node, use the event handler variant, simple.

No, the two features are following completely different approaches.
And while the DOM event model continues to evolve, `javascript:' is
supported merely for reasons of backwards compatibility.


PointedEars
 
R

Richard Cornford

VA said:
I am not sure I understand.

The situation is as easily demonstrated as explained. find yourself an
animated GIF, preferably one that shows constant change so that it is
instantly apparent when it stops being animated and place a reference to
it in the IMG element's SRC in the following HTML:-

<html>
<body>
<img src="anAnimated.gif">
<br>
<a href="javascript:void 0;">javascript:void 0;</a>
<br>
<a href="http://bogus.example.com/">http://bogus.example.com/</a>
</body>
</html>

- and load the result into a Windows IE 6. Then clink the javascript
pseudo-protocol link. The odds are good that the animation will stop
animating at precisely that point. If you then re-load the page the
animation should start again, and if you subsequently click the
bogus.example.com link you should (while the domain is failing to
resolve) have an opportunity to observe that the animation of the GIF
also stops. This demonstrates that the current document undergoes a
'state' change when a javascript pseudo-protocol HREF is activated that
is apparently similar to a 'state' change that accompanies requests to
navigate.
The expected outcome of triggering any link's HREF
is not always to replace the page's content. Even if we
leave Javascript out of this, how about <a href="#anchor">?
Following that HREF just navigates to a different section
of the currently loaded document. So does this also trigger
the "state change" you mention?

It is not useful to observe that a browser may recognise that the
activation of some HREFs do not represent navigation, and so do not
necessarily induce an equivalent 'state' change, so long as javascript:
HREFs can be demonstrated to be treated as navigation in some browsers.
We have a real, demonstrable, condition that applies to versions of a
web browsers that cannot be ignored in commercial web authoring. And we
have good reason to believe that the undesirable consequences of the
execution of javascrip pseudo-protocol HREFs go well beyond the visually
apparent symptoms exposed by animated GIFs.

We can speculate about the nature and extent of this 'state' change and
suffer the consequences of being overly-optimistic, or plain wrong, or
we can notice that there are no remaining circumstances in the DOM where
the execution of a javascript pseudo protocol HREF cannot be completely
avoided with the use of an appropriately default-action cancelling
intrinsic event handler, and so avoid ever having to provoke the
condition or deal with the consequences. Thus, for this reason, in
addition to many others, best practice is to never use a javascript
pseudo-protocol HREF that is not intended to completely replace the
current page.

Richard.
 
V

VA

Some things work reliably, others don't. This has nothing to do with

Just to clarify...other than the demonstrated example of "this" meaning
different things, what exactly does *not* work when href="javascript:"
is used?
experienced) and another one that it does not only not degrade
gracefully itself, using it in place of a proper `http:' URI prevents
the link from degrading gracefully.

But what if I (as the web designer) have nothing to degrade to? In
other words, the functionality that my website/app provides can only be
delivered using Javascript?

So are you suggesting that I do something like

href="sorry.html" onClick=...
where sorry.html informs the user that Javascript is required for
proper functionality?
Oh yes, there are plenty. And the more plain ignorance towards the user

Can you please point me to some? I am honestly curious to see some
commercial, useful websites providing some product/service on the
public Internet that are implemented without using Javascript.
such as displayed by you is taken away from the minds of Web designers, the [...]
adequate experience of the presented content, whether they use a desktop
PC, a notebook, a PDA, a mobile phone, a Braille line, a reading machine,
a printer or any other device.

I think your jab on my "ignorance" is not warranted. Presenting content
for all various output devices you mention above is the domain of the
presentation layer, which, I am sure you agree is CSS. CSS has plenty
of features for displaying output device-appropriate content.
(off-topic for this forum, so we'll leave it at that, shall we?).

What we are talking about in this thread is functionality ("what
happens when I click on this link?"), not presentation ("how does this
page look?").
No, the two features are following completely different approaches.
And while the DOM event model continues to evolve, `javascript:' is
supported merely for reasons of backwards compatibility.

I dont understand this. Backward compatibility comes into the picture
when Version x+1 of some technology supercedes some feature in Version
x. Until all the users of that technology "catch up", Version x+1 also
supports the usage of that feaure just as if Version x were running.

In this case, the A tag and its HREF attribute was present from Day 1.
Along comes Javascript and its onSomething event handlers. Older
browser that did NOT implement Javascript and its event handlers
therefore "ignored" the unknown (to them) onClick attribute of the A
tag.

But if they didnt understand/implement Javascript, what use is
providing a href="javasript:function()" feature? Those browsers cant
interpret/run the "function()" anyway! So whats the point? In other
words, who is the intended audience of this "backward compatibility"
feature?

Thanks
 
V

VA

Richard: Thank you for that wonderfully eloquent refutation. I am duly
enlightened. Thanks again.
 
R

Randy Webb

VA said the following on 10/23/2005 4:28 PM:
Just to clarify...other than the demonstrated example of "this" meaning
different things, what exactly does *not* work when href="javascript:"
is used?

Any link in my cell phone browser for starters.
But what if I (as the web designer) have nothing to degrade to? In
other words, the functionality that my website/app provides can only be
delivered using Javascript?

So are you suggesting that I do something like

href="sorry.html" onClick=...
where sorry.html informs the user that Javascript is required for
proper functionality?

Yes. That is preferable to getting a blank page and no indication of
why. The browser in my cell phone is a non-JS browser so at least some
kind of indication of why it isn't working is a great help.
But if they didnt understand/implement Javascript, what use is
providing a href="javasript:function()" feature? Those browsers cant
interpret/run the "function()" anyway! So whats the point? In other
words, who is the intended audience of this "backward compatibility"
feature?

See above.
 
V

VA

Randy said:
See above.

I dont understand. See above for what? My question was "if the client
cannot understand Javascript (thus causing it to ignore the onClick),
then what use is providing a href=javascript:?" That wont be understood
either.
 
R

Randy Webb

VA said the following on 10/23/2005 11:35 PM:
I dont understand. See above for what? My question was "if the client
cannot understand Javascript (thus causing it to ignore the onClick),
then what use is providing a href=javascript:?" That wont be understood
either.

My bad, I mis-read the question.


I do not believe that handling href="javascript: was in the beginnings
of the browsers. It was an afterthought (a very poorly thought out one)
when scripting came along. And it was introduced before the onclick
event handler as a way to allow a link to activate a script. Now, there
is no need for that use. As for why the browser vendors leave the
support in, who knows. Probably the same reason they leave eval support in.

But even if my intentions were to replace the entire contents of the
page via script, I still wouldn't use a href="javascript: construct to
do it.
 
V

VA

Randy said:
support in, who knows. Probably the same reason they leave eval support in.

Hm? Forgive the newbie question, but you seem to be saying "eval" is
not necessary in the Javascript language? So whats the alternative?

Thanks
 
D

Dag Sunde

VA said:
Hm? Forgive the newbie question, but you seem to be saying "eval" is
not necessary in the Javascript language? So whats the alternative?

Turn the question around:

Name a few scenarios where you feel eval() *is* neccessary, and we will
try to show you why its not...
 
V

VK

I was surprised to get so much "never
ever use the href=javascript: URI, it is baaad, evil, etc" comments.

Who said that?!? Not me.
javascript: p-protocol is a great thing. You just need to know how it
works and enjoy ever after.

1) javascript:someFunction() means: "execute someFunction and replace
current page by content from someFunction's return value". Thusly if
someFunction returns null, you'll end up with a blank page with the
proud word "null" written in the top left corner.

2) javascript:void(someFunction()) means: "where will be no new content
provided, just stay where you are; and by the way execute
someFunction".

Despite what some people says, void() operand *doesn't return* neither
null, nor undefined. As its name suggests it does not return any values
whatsoever. This is how it works in Java also (there this idea has been
taken from).
Yes if you try to assign
var foo = void(something);
then you'll get undefined. But it's the same "pseudo-value" as in case:

var arr = new Array(1,2,3);
var foo = arr[1000]; // the same undefined as with void()

JavaScript is just too samplified and user-friendly to bother you (and
itself) with fine details. So it just gives you undefined every time
you're trying to go beyond the scope of the program or to get return
value from something that doesn't have it by definition or do something
equally bizarre ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top