Assigning same onclick dynamically and statically

R

RobG

I have a function whose parameter is a reference the element that called it:

function someFunction(el)
{
...
}

The function is assigned to the onclick event of some elements in the
HTML source:

<input ... onclick="someFunction(this);" ...>

and dynamically to others:

elRef.onclick = someFunction;


When someFunction() is called from the statically-assigned onclick, el
is a reference to the element. But when it has been added dynamically,
el will be either undefined (IE) or 'event' (Mozilla et al).

To assign the right value to el, I can test if el exists and if it does,
whether its constructor is some type of HTML element or 'Event'. But IE
doesn't support the constructor property for elements (or have I just
not found it yet?) nor does it understand 'Event' the way Mozilla does.

Anyhow, the following test does the job:

function someFunction(el)
{
var el=(!el || (el.constructor && Event == el.constructor))? this : el;
...

If el is undefined:
- have IE dynamically added event, el is assigned the value of 'this'

If el is defined
- have IE statically added event, el is assigned the value of el
OR
- have Mozilla:
- if el.constructor is Event, have dynamically added event,
el is assigned the value of this
- if el.constructor is not Event, have statically added event,
el is assigned the value of el


It works, but seems long winded and dependent on the vagaries of the two
event models. As a result, I've been using:

var el = (el && el.nodeName)? el : this;

This seems much simpler - if el is defined and has a nodeName, use it.
Otherwise, use this.

Rather than detecting if the function was passed a reference to 'event'
or not, it sees if an element was passed. It works and assigns a
reference to the element whether called from the statically or
dynamically attached function.

Is that reasonable logic, or should the first method be used? Or is
there a better way of doing what I'm after?


Some sample code:


<input type="button" value="Replace onclick" onclick="
replaceOnclick(this);
alert('Old onclick replaced');
">

<script type="text/javascript">
function replaceOnclick(el)
{
// Short version
var el = (el && el.nodeName)? el : this;

// Long version (wrapped for posting)
// var el = ( !el || (el.constructor
&& Event == el.constructor) )? this : el;

el.onclick = replaceOnclick;
alert( el.nodeName + ': new onclick');
}
</script>
 
M

Martin Honnen

RobG wrote:

<input ... onclick="someFunction(this);" ...>

and dynamically to others:

elRef.onclick = someFunction;

You need
elRef.onclick = function (evt) {
someFunction(this);
};
then to have the same as that onclick attribute in the HTML markup creates.
 
V

VK

RobG said:
I have a function whose parameter is a reference the element that called it:

function someFunction(el)
{
...
}

The function is assigned to the onclick event of some elements in the
HTML source:

<input ... onclick="someFunction(this);" ...>

and dynamically to others:

elRef.onclick = someFunction;


When someFunction() is called from the statically-assigned onclick, el
is a reference to the element. But when it has been added dynamically,
el will be either undefined (IE) or 'event' (Mozilla et al).

To assign the right value to el, I can test if el exists and if it does,
whether its constructor is some type of HTML element or 'Event'. But IE
doesn't support the constructor property for elements (or have I just
not found it yet?) nor does it understand 'Event' the way Mozilla does.

Another (clearer??) way:

function someFunction() {
var el = someFunction.arguments[1] ||
someFunction.arguments[0].target;
...
}

<input ... onclick="someFunction(null,this);" ...>

elRef.onclick = someFunction;

I say that Mozilla/3W way demostrates its big flaw here: it leads to
the left/right arguments' shift in functions depending on how they are
being called: from the program stream or by event listeners. That's a
pain for distributed libraries.
 
R

RobG

VK said:
RobG said:
I have a function whose parameter is a reference the element that called it:

function someFunction(el)
{
...
}

The function is assigned to the onclick event of some elements in the
HTML source:

<input ... onclick="someFunction(this);" ...>

and dynamically to others:

elRef.onclick = someFunction;


When someFunction() is called from the statically-assigned onclick, el
is a reference to the element. But when it has been added dynamically,
el will be either undefined (IE) or 'event' (Mozilla et al).

To assign the right value to el, I can test if el exists and if it does,
whether its constructor is some type of HTML element or 'Event'. But IE
doesn't support the constructor property for elements (or have I just
not found it yet?) nor does it understand 'Event' the way Mozilla does.


Another (clearer??) way:

function someFunction() {
var el = someFunction.arguments[1] ||
someFunction.arguments[0].target;
...
}

<input ... onclick="someFunction(null,this);" ...>

elRef.onclick = someFunction;

I don't think that's an improvement - it introduces peculiarities at
both ends.
I say that Mozilla/3W way demostrates its big flaw here: it leads to
the left/right arguments' shift in functions depending on how they are
being called: from the program stream or by event listeners. That's a
pain for distributed libraries.

The 'flaw', if there is one, is that there are two models - I can't
comment on whether one is better than the other.

Martin's suggestion is fine, I've used it frequently but it seems a bit
of a hack to use an anonymous function to call another function (I guess
views on that differ).

Incidentally, nice you see you're back contributing :)
 
V

VK

VK said:
... it leads to the left/right arguments' shift in functions depending on...

Correcting myself as a wrong wording and explanation: there is not any
*shift* here. The first argument in each function (3W model) is
reserved for the Event data. You can use it for other purposes but it
will be like sitting on someone place ready to leave at any moment. As
soon as your function is called by an event listener, the first
argument will contain the Event data no matter what kind of argument
your function was really expecting. We may call it "a different
approach" or "an unforseen oops of the chosen model", it's really a
question of preferences :)
So wrappers from anonymous functions (despite their semi-ugliness)
would be a choice I guess.

the following test does the job:
function someFunction(el)
{
var el=(!el || (el.constructor && Event == el.constructor))? this : el;

There must be some surrounding code missing because here (and in the
other variant) you assign window object to el in IE case (this ==
window.self within named function body). That doesn't seem your aim.

Incidentally, nice you see you're back contributing :)
;-)
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top