skaterdav85 Posted March 21, 2011 Share Posted March 21, 2011 I was having some fun today and trying to create a small JS library like jQuery in the code below. I have a constructor function called dQuery and I pass in one argument. If the argument is a string, it assumes the argument is an ID of an element and sets a property 'this.el' to the element with that ID using getElementById(). If the argument is not a string, it assumes it is an element. What I am having trouble with, is that when you run the code within window.onload in IE and FF or Chrome, this is interpretted differently. In IE, this points to window, whereas in Chrome and FF, this points to the anchor element with an ID of prinkLink. Any idea why?HTML <a href="#" id="printLink">Print</a> JavaScript var dQuery = function (obj) { if (this === window) { return new dQuery(obj); } if (typeof obj === "string") { //assume the supplied argument is an ID this.el = document.getElementById(obj); } else if (typeof obj === "object") { //assume the supplied argument is an element this.el = obj; } this.bind = (function () { if (document.attachEvent) { return function (evt, cb) { (this.el).attachEvent('on' + evt, cb); }; } else if (document.addEventListener) { return function (evt, cb) { (this.el).addEventListener(evt, cb, false); }; } } ());}; //end of constructor function//example using the dQuery objectwindow.onload = function () { dQuery('printLink').bind('click', function () { if (this === window) { alert('this points to window'); } else if (this.tagName === 'A') { alert('this points to anchor tag'); } });}; Link to comment Share on other sites More sharing options...
justsomeguy Posted March 21, 2011 Share Posted March 21, 2011 That's just how the different browsers handle scoping in event handlers. You can always force the callback to run in a certain scope if you want to normalize how that works. Link to comment Share on other sites More sharing options...
skaterdav85 Posted March 21, 2011 Author Share Posted March 21, 2011 oh ok. I didn't know IE handled scope differently. Do you know of any references that explain this in detail?I modified my bind() method to the following, using call and caching this.el and it worked, but it'd be nice to know what the scoping differences are between IE and modern browsers. this.bind = (function () { if (document.attachEvent) { return function (evt, cb) { var el = this.el; el.attachEvent('on' + evt, function () { cb.call(el); }); }; } else if (document.addEventListener) { return function (evt, cb) { var el = this.el; el.addEventListener(evt, function () { cb.call(el); }, false); }; }} ()); Link to comment Share on other sites More sharing options...
justsomeguy Posted March 21, 2011 Share Posted March 21, 2011 Really the only detail is what you already said: for an event handler, IE runs the handler in the window scope. Other browsers run the handler in the scope of the object that the event happens on. Link to comment Share on other sites More sharing options...
skaterdav85 Posted March 21, 2011 Author Share Posted March 21, 2011 ok thanks! i just found an article on quirksmode that states what you just said as well:http://www.quirksmode.org/js/events_advanced.html Link to comment Share on other sites More sharing options...
ShadowMage Posted March 22, 2011 Share Posted March 22, 2011 I have always assigned handlers using the dot notation style:elem.onclick = function() { .... }and I have never had any problems with scoping this. Which way is more correct? (Dot notation or addEventListener/attachEvent) It seems to me that the dot notation style is more reliable. Link to comment Share on other sites More sharing options...
skaterdav85 Posted March 22, 2011 Author Share Posted March 22, 2011 the traditional event model (element.onclick, element.onmouseover, etc) is more consistent across browsers. However there are drawbacks to this approach because it only allows you to assign one function to each event type of an element. If you have a link and you want to fire 2 functions when it is clicked, you would have to refactor your code so that you only assign one function to that event type, and that function would fire the 2 functions. With addEventListener and attachEvent, you can specify more than 1 event handler to an element. Read these 2 posts. They explain it much better.http://www.quirksmode.org/js/introevents.htmlhttp://www.quirksmode.org/js/events_advanced.html Link to comment Share on other sites More sharing options...
ShadowMage Posted March 22, 2011 Share Posted March 22, 2011 So, in other words, neither is "more correct" than the other. It's simply a matter of which will work best in any given situation. Link to comment Share on other sites More sharing options...
skaterdav85 Posted March 22, 2011 Author Share Posted March 22, 2011 true. the DOM level 2 event model is just more flexible once you get past the browser inconsistencies. Link to comment Share on other sites More sharing options...
Ingolme Posted March 23, 2011 Share Posted March 23, 2011 I usually don't use "this" in event handling functions. If you want to access the element to which the event is binded you can use currentTarget of the event object. Internet Explorer doesn't support that so you have to use srcElement. The only problem is that srcElement doesn't always point to the element that the event is binded to, it points to the element that fired the event, which sometimes may be different.A fix (that might not always work) is to assign a unique property to the element while binding the event. When the event fires, keep checking parentNodes until you find the one that has the property you were looking for. Link to comment Share on other sites More sharing options...
ShadowMage Posted March 23, 2011 Share Posted March 23, 2011 I usually don't use "this" in event handling functions. If you want to access the element to which the event is binded you can use currentTarget of the event object. Internet Explorer doesn't support that so you have to use srcElement. The only problem is that srcElement doesn't always point to the element that the event is binded to, it points to the element that fired the event, which sometimes may be different.A fix (that might not always work) is to assign a unique property to the element while binding the event. When the event fires, keep checking parentNodes until you find the one that has the property you were looking for.Seems much easier to just use this. Link to comment Share on other sites More sharing options...
skaterdav85 Posted March 23, 2011 Author Share Posted March 23, 2011 interesting approach Inglome. I haven't really studied the differences of the event object for IE and modern browsers since I rarely use them. Using this does sound easier though once you normalize its scope through feature detection. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.