The old "there no event object in Firefox" question again

S

stevewy

Having Googled the internet generally, and searched this group, I
still cannot find any definitive answer to the question about how to
get an equivalent of "srcElement" and "event" in Firefox.

I've known for some time that I shouldn't use just "srcElement" to
reference which element has been clicked on, because it is only
supported by Internet Explorer, not Firefox etc. I thought I was
alright by using a combination of "srcElement" and "Target", so that I
thought the following would work (in IE and Firefox) in a function:

var obj=event.srcElement || event.target;
if (obj.type=="checkbox"){... etc

However, this validation doesn't work properly in Firefox. Firefox's
Error Console informs me that "event" is not an object, and it turns
out that Firefox does not recognise "event.target" after all.

I have looked on the internet about this but can find no "definitive"
solution. Plenty of sites saying that event is not supported in
Firefox.

Can anyone advise on a general bit of code that would work as a
substitute for "event.srcElement" and be compatible with Firefox? Is
it something simple like document.event.target or window.event.target
(except without the word "event", apparently...)?

I do have a little function to disable the Return key, that stops
people prematurely submitting the form just by pressing Enter (below),
and that achieves cross-browser compatibility - but I am uncertain why
"evt" appears in the function name as a parameter, when the
"document.onkeypress" doesn't actually pass up any parameters...

function checkCR(evt) {
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ?
evt.srcElement : null);
if ((evt.keyCode == 13) && (node.type!="textarea")) {return
false;}
}
document.onkeypress = checkCR;

Hope you can help.

Steve Wylie
src.Confused
 
J

Joost Diepenmaat

I do have a little function to disable the Return key, that stops
people prematurely submitting the form just by pressing Enter (below),
and that achieves cross-browser compatibility - but I am uncertain why
"evt" appears in the function name as a parameter, when the
"document.onkeypress" doesn't actually pass up any parameters...

function checkCR(evt) {
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ?
evt.srcElement : null);
if ((evt.keyCode == 13) && (node.type!="textarea")) {return
false;}
}
document.onkeypress = checkCR;

That quirksmode page is probably the best place to start, but in short,
in IE, event handlers can use the global "event" variable, while FF and
a few/lot of other browsers do not have a global "event" variable, but
instead pass the event object as the single argument to the event
handler.

The code dealing with this in your example is pretty unclear, though. I
prefer something like:

function checkCR(evt) {
var evt = evt || window.event; // make sure evt contains the event object
}
 
S

stevewy

Thanks for the reply, but how would your advice work with (for
example) the following function below? It's purpose is for questions
on a form where you are only allowed to check a certain number of
boxes - for instance "please tick your top three choices".

function limitchecked(max){
var obj=event.srcElement || event.target;
if (obj.type=="checkbox"){
var group=form.elements[obj.name]
var count=0;
for(var i=0;i<group.length; i++)
{count+= (Number(group.checked)) ? 1 : 0;}
if(count>max){alert("You may only check "+max+"
items.");obj.checked=false;}}}

In order to use this, I could put a <DIV> around the question and put
OnClick="limitchecked(3)" in it. But how would I pass the event up to
the function, since there is already a parameter there (the max amount
of boxes allowed to be checked)?

Steve
 
J

Joost Diepenmaat

Thanks for the reply, but how would your advice work with (for
example) the following function below? It's purpose is for questions
on a form where you are only allowed to check a certain number of
boxes - for instance "please tick your top three choices".

function limitchecked(max){
var obj=event.srcElement || event.target;
if (obj.type=="checkbox"){
var group=form.elements[obj.name]
var count=0;
for(var i=0;i<group.length; i++)
{count+= (Number(group.checked)) ? 1 : 0;}
if(count>max){alert("You may only check "+max+"
items.");obj.checked=false;}}}

In order to use this, I could put a <DIV> around the question and put
OnClick="limitchecked(3)" in it. But how would I pass the event up to
the function, since there is already a parameter there (the max amount
of boxes allowed to be checked)?


Ah, yes. In the *text* of the onclick attribute you CAN refer to
"event", even in firefox etc:

OnClick="limitchecked(event,3)"

function limitchecked(evt, max){
...
 
S

stevewy

Hmm. I've given it a go, and the only way I can get this to work (in
my example), is to call it with:

OnClick="limitchecked(this.event,3)"

.... and for the top of the function to say:

function limitchecked(evt,max){
var evt=evt || event.srcElement;
var obj=evt;
if (obj.type=="checkbox"){... etc


....and since I am at work using IE and not Firefox, I still don't know
if it is going to work when I get a chance on Firefox later. Can you
advise why window.event doesn't work, even in IE?

Steve
 
T

Thomas 'PointedEars' Lahn

If you think about it a bit longer, you'll recognize how pointless and
inefficient that is.
Likewise.

Last I checked, the type of a node is not the element type, but an integer,
and the property was `nodeType' instead. You are looking for the `tagName'
and case-insensitive matching instead.

if (/^\s*textarea\s*$/.test(node.tagName)) && evt.keyCode == 13)
{
if (isMethod(evt, "preventDefault")) evt.preventDefault();
if (typeof evt.returnValue != "undefined") evt.returnValue = false;
return false;
}

Use document.body.onkeypress or, even better, a wrapper method that
considers all of the approaches mentioned below.
That quirksmode page is probably the best place to start, but in short,
in IE, event handlers can use the global "event" variable, while FF and
a few/lot of other browsers do not have a global "event" variable, but
instead pass the event object as the single argument to the event
handler.

Utter nonsense.

In MSHTML-based user agents like IE, there is an object rather on top of the
scope chain that has an `event' property which refers to an Event object.
We can be pretty sure that the owner of this property is the host object
referrable by `window' since `window.event' works as well. It might
instead be a host-defined property of the Global Object. What matters is
that it is _not_ a variable at all.

Now, event handlers are built-in components of AOMs/DOMs, native routines
that call event listeners. Event listeners can be created in two to four
ways:

A) In the (X)HTML source code, an `on...' attribute's value specifies the
event listener code for the `...' event (barring non-standard attributes,
that's standards-compliant; it is also backwards-compatible, and
recommended unless more elaborate event-handling calls for a wrapper that
includes variant C).

B) In the script source code, assigning a reference to a callable object
(usually a Function object) to an `on...' (event-handler) property of an
object specifies the event listener for the `...' event. That's
proprietary, but mostly backwards-compatible.

C) In the script source code running in a DOM that implements W3C DOM Level
2+ Events, calling the addEventListener() method on a DOM object (event
target) and passing it the event type identifier as a string, the reference
to the event listener, and a flag that indicates whether the event listener
is a capturing one or not (that is the default).

D) In the script source code running in the MSHTML-DOM, calling the
attachEvent() method on a DOM object, and passing it the Microsoft event
name, the reference to the event listener, and optionally other things
(IIRC).

With A, one can obtain the event object reference in several HTML DOMs with
`event':

<... on...="... event ...">

However, it is prudent to do a feature test so that there are no avoidable
runtime errors:

<... on...="if (typeof event != "undefined") ... event ...">

With B, it depends on the DOM implementation whether the assigned event
listener will be passed a reference. One can use a named first argument to
ease detection and provide for alternatives:

....on...= function(e) {
if (!e) ...
};

See below. It looks like as if the MSHTML DOM is the only DOM that does not
pass the Event object reference when the event listener is assigned this
way.

C and D are not equivalent (see QuirksMode.org).

With C, which should only work in W3C-DOM-compliant DOMs, the event listener
is always passed a reference to the Event object as first argument:

foo.addEventListener("bar", function(e) { ... e ... }, false);

`this' will in most of all cases refer to the event target. (A known
exception is the listener for the `load' event of the `body' element.)

With D, since it is MSHTML-DOM-only, you have to obtain the reference
through `window.event'. `this' will seldom refer to the event target.
The code dealing with this in your example is pretty unclear, though. I
prefer something like:

function checkCR(evt) {
var evt = evt || window.event; // make sure evt contains the event
object

// add more feature-tests here
if (!evt) evt = window.event;
if (evt)
{
// ...
}


PointedEars
 
S

stevewy

function checkCR(evt) {
If you think about it a bit longer, you'll recognize how pointless and
inefficient that is.

Well, to tell you the truth, since pulling this off a Javascript site
many years ago, I do know it works but have not yet worked out what
it's doing. I presume it's using a conditional expression to decide
whether to use "event" or "evt", depending on whether the browser
being used can handle "event" or not. Isn't it?

Steve
 
T

Thomas 'PointedEars' Lahn

If you think about it a bit longer, you'll recognize how pointless and
inefficient that is.

Well, to tell you the truth, since pulling this off a Javascript site
many years ago, I do know it works but have not yet worked out what
it's doing. I presume it's using a conditional expression to decide
whether to use "event" or "evt", depending on whether the browser
being used can handle "event" or not. Isn't it?

No. What does it do? `evt' is the name of the first argument of your
function. If the value of `evt' can be type-converted to boolean so that
the result of that is `true', the value of `evt' is used; this we can
expect from UAs running a NN4-DOM- or W3C-DOM-compatible DOM
implementation. Otherwise it is tested whether the value of `event' can be
type-converted to boolean so that it is `true'. However, that is starting
from the (false) assumption that there must be an object in the scope chain
then that has `event' as its property. Or, in other words, at this point
the code could simply error out with a runtime exception because neither
yields `evt' a true-value nor can `event' be resolved. That's the first
mistake.

The second one is superficially a lighter one but it has greater a bearing
on the whole approach. Suppose `event' could be resolved as a property of
an object and can be type-converted to boolean so that the result is
`true', then the value of that property is used -- a property of *any*
object on the scope chain that has such a property, for example try this in
MSHTML:

javascript:var event = "foo"; window.document.body.onclick=function abc() {
window.alert(event); }; void 0

(then click the document.)

If type-conversion yields `false' instead, you assign `null' to `evt'
instead. Why? In the next line --

var node = (evt.target) ? evt.target : ((evt.srcElement) ?
evt.srcElement : null

-- you are not testing for `evt' being `null'; in fact, you are not testing
for `evt' at all but blindly assume that it must be convertible to an
object, although you yourself introduced the possibility that it might not:
`null'. And since `null' has no properties, you would get a(nother)
runtime exception thrown at when `evt.target' aso. is evaluated.

Much the same nonsense for `node':

  if ((evt.keyCode == 13) && (node.type!="textarea")) {return
false;}

Again, no test at all for `evt' or `evt.keyCode' or `node', but access to a
(wrong) property of the object referred to by `node'. And to make it even
worse, the (wrong) element test comes after the key test, when the order
should be reversed instead (you only want to handle the key on TEXTAREA
elements).

Please provide attribution for quoted material, and trim your quotes.

<http://jibbering.com/faq/#posting>


PointedEars
 
M

Martin Rinehart

All browsers except IE pass an event argument. Your code can simple
say:

function handleEvent( e ) {
e = e || event;

(Logical operators short-circuit, so if "e" is true (defined) "event"
is ignored. Only IE will get to "event" and it assigns one.
"window.event" and "event" are the same thing in a browser as "window"
is the global object.)

Now for the gotcha. If this is your markup:

<tag ... onmousedown=myFunc()...>

Firefox will NOT supply an event argument. To get the event argument
in all browsers, assign in the JS:

x = document.getElementById( 'anId' );
x.onmousedown=myFunc; // no parens after myFunc!

With that, FF will behave just like Chrome, Opera and Safari. Do not
let the event propagate or bubble if you want Opera to behave like the
others.

On a related subject, I tested combinations of onmousedown, onclick
and onmouseup. Do not mix onclick with either of the others if you
want cross-browser code.
 
T

Thomas 'PointedEars' Lahn

Martin said:
All browsers except IE pass an event argument.
Wrong.

Your code can simple say:

function handleEvent( e ) {
e = e || event;

But should not, for it is inherently error-prone.
(Logical operators short-circuit, so if "e" is true (defined) "event"
is ignored. Only IE will get to "event" and it assigns one.

False assumption.
"window.event" and "event" are the same thing in a browser as "window"
is the global object.)

Another false assumption.
Now for the gotcha. If this is your markup:

<tag ... onmousedown=myFunc()...>

Firefox will NOT supply an event argument.

No browser will, not even if the markup was made valid.
To get the event argument in all browsers, assign in the JS:

x = document.getElementById( 'anId' );
x.onmousedown=myFunc; // no parens after myFunc!

Nonsense. It does not take W3C DOM 2 HTML in error-prone combination
with "DOM Level 0" in order to pass an event object.
With that, FF will behave just like Chrome, Opera and Safari.

As it will with <tag ... onmousedown="if (typeof event != 'undefined')
myFunc(event)">.
Do not let the event propagate or bubble if you want Opera to behave
like the others.

How did you get that idea?
On a related subject, I tested combinations of onmousedown, onclick
and onmouseup. Do not mix onclick with either of the others if you
want cross-browser code.

Nonsense.


PointedEars
 
T

Thomas 'PointedEars' Lahn

And that's also wrong. MSHTML/IE will not pass the event object reference.

Don't listen to this wannabe.
Nonsense. It does not take W3C DOM 2 HTML in error-prone combination
with "DOM Level 0" in order to pass an event object.


PointedEars
 
L

Lasse Reichstein Nielsen

Martin Rinehart said:
Now for the gotcha. If this is your markup:

<tag ... onmousedown=myFunc()...>

Firefox will NOT supply an event argument.

Oh yes it does. Then your code summarily ignores it.

Now, if you wrote <tag ... onmousedown="myFunc(event);" ...> then you
would also pass the event argument that Firefox provided to the function
that you call from the handler. Just like all in all other browsers.

And you probably meant it to be
<tag ... onmousedown="return myFunc(event);" ...>
to match your "workaround".

/L
 
D

dhtml

Thomas said:
If you think about it a bit longer, you'll recognize how pointless and
inefficient that is.


Last I checked, the type of a node is not the element type, but an integer,
and the property was `nodeType' instead. You are looking for the `tagName'
and case-insensitive matching instead.


Last I checked, form controls had a |type| property.
Did you try getting a |type| property off a textarea?
if (/^\s*textarea\s*$/.test(node.tagName)) && evt.keyCode == 13)
{

Did you try running this in a browser?

There is no tag that starts with, or ends with whitespace. Why:
/^\s*textarea\s*$/ ?

Unless the document is XHTML (real XHTML, not tag soup), the tagNames
are all upper case.

There is no tag that starts with, or ends with whitespace. Why:
/^\s*textarea\s*$/ ?

Thus, textarea/i.test(node.tagName) would return false for a textarea in
HTML.

The statement - /textarea/i.test(node.tagName) - would be one possible
way to achieve test for the textarea|TEXTAREA.


Garrett
 
S

stevewy

Right old clash of the Titans here! So, Mr Lahn, can you provide me
with a bulletproof line(s) that I can use to capture an event and its
details, that will work with all browsers? If you state that I should
not use:

function handleEvent( e ) {
e = e || event;

.... as previously suggested by a poster, is there a straightforward
alternative, without needing reams of code?

Steve
 
T

Thomas 'PointedEars' Lahn

Right old clash of the Titans here!

So you are hallucinating already.
So, Mr Lahn,

Yes, Mr. ... e-mail address?
can you provide me with a bulletproof line(s) that I can use to capture an
event and its details, that will work with all browsers?

You seem to have fallen victim to the frequent delusion that I or anyone
else here would have to support your whims.

If you state that I should not use:

function handleEvent( e ) {
e = e || event;

.... which I have explained in-depth ...
... as previously suggested by a poster, is there a straightforward
alternative, without needing reams of code?

With DOM scripting, where host objects are involved, there can be no
bullet-proof or straightforward approach, especially not in one line.
But if you had cared to read this thread, you would have found several
more reliable than this, one by me.

BTW, this is Usenet, a thread-based electronic discussion medium; one
replies to what one is directly referring to.

<http://jibbering.com/faq/#posting>


Score adjusted

PointedEars
 
H

Henry

Hmm. I've given it a go, and the only way I can get
this to work (in my example), is to call it with:

OnClick="limitchecked(this.event,3)"

Assuming that this is an attribute in mark-up and not javascript
(there is insufficient context to be certain of that) then the -
this.event - bit is worthless as the - this - will refer to whichever
element has the attribute and elements do not have - event -
properties. The value passes to the - limitchecked - function call
will be the undefined value.

In the context of an attribute value the - event - identifier should
be used to reference the event as that will either refer to the named
parameter of the browser created function, or on IE, be scope-chain
resolved to refer to the global event object.
... and for the top of the function to say:

function limitchecked(evt,max){
var evt=evt || event.srcElement;

Because the undefined value was passed as the first argument to the
function call the - evt - parameter would have that value. Undefined
type-converts to boolean false so the result of this assignment will
always be - event.srcElement- . That will be acceptable on IE, but is
acceptable only as the outcome of a series of coincidences and in no
way appears to be planned result of programming.

It is not particularly sensible to attempt to 'normalise' the - evt -
value to an event object if an event object argument is provided or a
DOM element if the argument does not provided an event object.
var obj=evt;
if (obj.type=="checkbox"){... etc

...and since I am at work using IE and not Firefox, I still
don't know if it is going to work when I get a chance on
Firefox later.

There is absolutely no chance of the above 'working' on Firefox.
Can you
advise why window.event doesn't work, even in IE?

In what sense does - window.event - not "work" on IE. What you really
want here is advice on why the code you wrote that employed -
window.event - did not work, but for that you would have to show the
code (and probably state what 'work' and 'not work' mean to you
(remembering that, short of syntax errors, computer code always
'works', in the sense that it does precisely what it was programmed to
do. It is just that most things that 'don't work' have been programmed
to something other than what was wanted, but it is impossible to
determine what was wanted from code that has been programmed to do
something else.)).
 
S

stevewy

So, Mr Lahn,
Yes, Mr. ... e-mail address?
But if you had cared to read this thread....

.... you would see my surname at the foot of my original post.
BTW, this is Usenet, a thread-based electronic discussion medium; one replies to what one is directly referring to.

Eh?

In the guidance at http://jibbering.com/faq/#posting it states:

"Avoid being unnecessarily rude, but do not complain about other rude
posts."

You appeared to have disregarded the first part of this advice, but I
will observe the second part, and not refer to your extremely terse
and dismissive remarks concerning other people's opinions on this
thread. They also seem to be labouring under the "frequent delusion"
that people may ask for help/advice on this thread and other more
knowledgable people may help them.

I do not understand some points of your advice to me, as your
knowledge of Javascript obviously exceeds mine in this area. Your
knowledge of "netiquette" could do with some revision, however.

Anyway, thank you to all posters on this thread for the information
given.

Steve
 

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,821
Messages
2,569,748
Members
45,726
Latest member
RaleighAll

Latest Threads

Top