Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 17
  1. #1
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts

    DOM Event Scripting, (undocumented) Tip #1: DOM2 Events and Internet Explorer

    Forgive my conciseness, but in Win/IE, if you attach a function to an event via attachEvent(), window.event is passed in as an argument to it. MSDN does not document this behavior, but it is incredibly useful:
    Code:
    function myListener(evt) {
        window.status = [evt.clientX, evt.clientY];
    }
    
    if ("addEventListener" in document) {
        document.addEventListener("mousemove", myListener, false);
    }
    else if ("attachEvent" in document) {
        document.attachEvent("onmousemove", myListener);
    }
    And that will work crossbrowser. Notice no checking for the event argument and reassigning the window.event object to the identifier.

    Further more, if you're only attaching events on a particular node, then you can extend it like so:
    Code:
    if (!("addEventListener" in document) && "attachEvent" in document) {
        document.addEventListener = function(evt, func, capture) {
            document.attachEvent("on" + evt, func);
        }
    }
    // likewise for removeEventListener, if necessary
    And you simply use document.addEventListener from now on, instead of repetitive code-branching:
    Code:
    document.addEventListener("mousemove", myListener, false);
    Enjoy.

  2. #2
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Ok, no one seems to be interested. Well, I'll one up the previous post.

    listener.htc:
    Code:
    <!--    Licensed under Creative Commons Attribution 2.0
         Original code by Jason Davis, www.jasonkarldavis.com -->
    
    <PUBLIC:COMPONENT lightWeight="true">
    	<PUBLIC:METHOD NAME="addEventListener" />
    	<PUBLIC:METHOD NAME="removeEventListener" />
    	<SCRIPT LANGUAGE="JScript">
    		function addEventListener(type, listener, useCapture) {
    			attachEvent("on" + type, listener);
    		}
    		function removeEventListener(type, listener, useCapture) {
    			detachEvent("on" + type, listener);
    		}
    	</SCRIPT>
    </PUBLIC:COMPONENT>
    listener.js
    Code:
    /*    Licensed under Creative Commons Attribution 2.0
       Original code by Jason Davis, www.jasonkarldavis.com */
    
    window.addEventListener = document.addEventListener =
    	function(type, listener, useCapture) {
    		this.attachEvent("on" + type, listener);
    	}
    
    window.removeEventListener = document.removeEventListener =
    	function(type, listener, useCapture) {
    		this.detachEvent("on" + type, listener);
    	}
    listener.css
    Code:
    /*    Licensed under Creative Commons Attribution 2.0
       Original code by Jason Davis, www.jasonkarldavis.com */
    
    * { behavior: url(listener.htc) }
    And finally, include this in the <head> of your pages:
    Code:
    <!--[if gte IE 5]>
    	<link rel="StyleSheet" type="text/css" href="listener.css" />
    	<script type="text/javascript" src="listener.js"></script>
    <![endif]-->
    Congratulations, you just made Internet Explorer support two key methods of DOM2 events on every element, document, and window. Code-forking eliminated.
    Last edited by jkd; 05-23-2005 at 07:17 PM.

  3. #3
    Regular Coder
    Join Date
    May 2005
    Posts
    313
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I think that's cool and stuff... even licensed, wow!
    Thanks in advance!

  4. #4
    Regular Coder
    Join Date
    May 2004
    Location
    Alabama, USA
    Posts
    237
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ok, no one seems to be interested.
    Oh, that's not true at all! Great stuff!

    I'll make an observation...

    attachEvent is similar to addEventListener in that it allows you to add more than one listener for the same event to the same element object. However, attachEvent has a major drawback - in your listener 'this' will not reference the correct instance, in fact it will point to window or document.

    So my advice is...

    Always use the DOM0 Events interface unless you specifically need to add more than one listener for the same event to the same element.

  5. #5
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by MikeFoster
    in your listener 'this' will not reference the correct instance, in fact it will point to window or document.

    So my advice is...

    Always use the DOM0 Events interface unless you specifically need to add more than one listener for the same event to the same element.
    Aha well .. your observation is quite correct, but the wider reasoning is more complex than it appears, as I recently discovered myself: expando context "this" discrepancy in IE

    Essentially, you shouldn't rely on "this" as a self-reference in addEventListener either, so for all encapsulated event handling, references should be obtained by upwards iteration from target|srcElement.

    btw jkd - why do you pass the useCapture argument through, when attachEvent can't use it? Wouldn't it be marginally more efficient to lose that argument, or did you foresee a future extension for it?
    Last edited by brothercake; 05-23-2005 at 04:07 PM.
    "Why bother with accessibility? ... Because deep down you know that the web is attractive to people who aren't exactly like you." - Joe Clark

  6. #6
    Regular Coder
    Join Date
    May 2004
    Location
    Alabama, USA
    Posts
    237
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ah, thanks for pointing that out. These issues are why I advise to only use the DOM0 event interface - except in a few cases.

    brothercake, in the thread you linked to I notice liorean said this:
    Quote Originally Posted by liorean
    For W3C DOM events, the Event.prototype.target property should contain a reference to the element which originally dispatched the event, which means that it should be the same as this for a DOM0 event.
    Perhaps I'm misunderstanding something by his reference to Event.prototype. I thought event.currentTarget was equivalent to this. There are situations where event.target is not equivalent to this for example during the BUBBLING_PHASE. My understanding was that event.target is only equivalent to this during the AT_TARGET phase. Perhaps I am misunderstanding liorean's statement?

  7. #7
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    No you're right, and that just makes it twice as complicated

    As you know, writing libraries is a whole different discipline from writing scripts for yourself, and for such scripting I generally go by the opposite principle - never use the DOM 0 event interface for event handling on pre-existing HTML elements - only ever use it on elements you created yourself in the script - or you risk conflict with other scripting.

    But this is a real problem - target may not be the target you want, depending on the event phase. Now I think about it, this exact problem has bugged me twice before, and I found two different solutions:

    - I maintained a manual "bubble flag" so that I could track the flow of events cross-browser

    - I just prevented event bubbling on all instances, so the issue never came up

    But both of those are solutions of convenience - the first is an ugly hack, the second is not necessarily appropriate. What we really need is an IE-equivalent of currentTarget .... but of course we don't have that.

    However IE does support the eventPhase property .. so that's probably the way in - using eventPhase discrimination at the point where the reference to "this" is derived ..

    hmm ... need to think about this one
    Last edited by brothercake; 05-23-2005 at 05:20 PM.
    "Why bother with accessibility? ... Because deep down you know that the web is attractive to people who aren't exactly like you." - Joe Clark

  8. #8
    Regular Coder
    Join Date
    May 2004
    Location
    Alabama, USA
    Posts
    237
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by brothercake
    As you know, writing libraries is a whole different discipline from writing scripts for yourself, and for such scripting I generally go by the opposite principle - never use the DOM 0 event interface for event handling on pre-existing HTML elements - only ever use it on elements you created yourself in the script - or you risk conflict with other scripting.
    Very good point - but that opens up another big can of worms similar to the one opened by the window.onload event, eh?

    Quote Originally Posted by brothercake
    However IE does support the eventPhase property ..
    ?!? are you sure?

    Quote Originally Posted by brothercake
    hmm ... need to think about this one
    Me too - this is a big can - it will take me a while to digest all the worms

  9. #9
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Quote Originally Posted by MikeFoster
    Oh, that's not true at all! Great stuff!

    I'll make an observation...

    attachEvent is similar to addEventListener in that it allows you to add more than one listener for the same event to the same element object. However, attachEvent has a major drawback - in your listener 'this' will not reference the correct instance, in fact it will point to window or document.

    So my advice is...

    Always use the DOM0 Events interface unless you specifically need to add more than one listener for the same event to the same element.
    If the reference to `this` is that important to you:
    listener.htc
    Code:
    <!--    Licensed under Creative Commons Attribution 2.0
         Original code by Jason Davis, www.jasonkarldavis.com -->
    
    <PUBLIC:COMPONENT lightWeight="true">
    	<PUBLIC:METHOD NAME="addEventListener" />
    	<PUBLIC:METHOD NAME="removeEventListener" />
    	<SCRIPT LANGUAGE="JScript">
    		var listeners = new Object();
    		function addEventListener(type, listener, useCapture) {
    			if (!(type in listeners))
    				listeners[type] = new Object();
    			listeners[type][listener] = function(event) { listener.call(element, event) };
    			attachEvent("on" + type, listeners[type][listener]);
    		}
    		function removeEventListener(type, listener, useCapture) {
    			detachEvent("on" + type, listeners[type][listener]);
    			delete listeners[type][listener];
    		}
    	</SCRIPT>
    </PUBLIC:COMPONENT>


    And brothercake, the reason for using the 3rd useCapture argument is consistency: document.addEventListener.arity == 3, so might as well keep it the same in IE.

  10. #10
    Regular Coder
    Join Date
    May 2004
    Location
    Alabama, USA
    Posts
    237
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Cool stuff, jkd!

    I played around with similar ideas several years ago - implemented DOM2 Events interface in Javascript for IE4+ as well as NN4 , but I had my fun with those toys and now I don't play with them any more

  11. #11
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Quote Originally Posted by MikeFoster
    Cool stuff, jkd!

    I played around with similar ideas several years ago - implemented DOM2 Events interface in Javascript for IE4+ as well as NN4 , but I had my fun with those toys and now I don't play with them any more
    Well, everybody and their grandma had their fun with this stuff during IE4/NS4 days. But the difference between now and then is that this is using native methods, providing an incredibly light-weight and next to zero-cost implementation (and certainly more of a bug-free experience), as opposed to reimplementing everything from scratch.

    Or at least, that's how I justify the bit of time I spent writing this.

  12. #12
    Master Coder
    Join Date
    Feb 2003
    Location
    Umeň, Sweden
    Posts
    5,578
    Thanks
    0
    Thanked 83 Times in 74 Posts
    Quote Originally Posted by MikeFoster
    Ah, thanks for pointing that out. These issues are why I advise to only use the DOM0 event interface - except in a few cases.

    brothercake, in the thread you linked to I notice liorean said this:

    Perhaps I'm misunderstanding something by his reference to Event.prototype. I thought event.currentTarget was equivalent to this. There are situations where event.target is not equivalent to this for example during the BUBBLING_PHASE. My understanding was that event.target is only equivalent to this during the AT_TARGET phase. Perhaps I am misunderstanding liorean's statement?
    By using Event.prototype I mean that all instances of the Event object have it, but not the Event object itself. This instance would be the first argument to the event listener.



    In a correct implementation, Event.prototype.target is always the element the innermost listener is attached to in all phases, but Event.prototype.currentTarget is the element the current listener is attached to in bubble and capture phases. And the this keyword always points to the element the current listener is attached to, not the element the innermost listener is attached to. So yes, you're right about capturing and bubbling phases, and that Event.prototype.currentTarget points to the same as this in those cases.

    But then of course, we have two problems I can see: Incorrect implementations (Safari 1.2, maybe later ones too) and implementations where Event.prototype.currentTarget is not present or plainly wrong (Different Opera versions exhibit both these properties. Haven't tested recent builds.) I also recall problems in some other mac browser but can't remember which. OW5 or MSN/OSX maybe?






    Of course, the real problem is that using Element.prototype.attachEvent there is no way to get a reference to the element that Event.prototype.currentTarget or this would point to except through encapsulating that in the event registration function. And doing that you've suddenly opened that whole can of worms with iew leaking memory because elements contain references to functions that contain references to elements that... well you know.
    Last edited by liorean; 05-25-2005 at 04:40 AM.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  13. #13
    Regular Coder
    Join Date
    Mar 2004
    Posts
    130
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Mike - "event.currentTarget was equivalent to this"

    Mike is right!



    Now, If someone is using a script with this faux addEventListener, and there is another script that has:

    Code:
    if(document.addEventListener) {
        document.addEventListener("mousedown", documentMouseDown, true);
    }
    
    documentMouseDown = function(e) {
        alert(e.pageX);
        alert(e.currentTarget);
        alert(this.nodeType == this.DOCUMENT_NODE);
        if(e.target.nodeType == this.TEXT_NODE) {
            alert("you clicked a text node.");
        }
    }
    javascript:alert(document.DOCUMENT_NODE); // nothing in IE.

    Faking addEventListener on node for IE is a bad approach.


    Unless you're going to support the WHOLE dom event model. (I'll leave that up to Dean Edwards).

  14. #14
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Agreed. However, for internal DHTML development (where you write everything yourself), this saves me from code-branching.

  15. #15
    Regular Coder
    Join Date
    May 2004
    Location
    Alabama, USA
    Posts
    237
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Sorry I dropped out of the conversation. Was out of town for a bit - now trying to catch up

    There's some good stuff in this thread!


 
Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •