Skip to content

Instantly share code, notes, and snippets.

@lsmith
Created September 17, 2011 04:54
Show Gist options
  • Select an option

  • Save lsmith/1223638 to your computer and use it in GitHub Desktop.

Select an option

Save lsmith/1223638 to your computer and use it in GitHub Desktop.
A fragile workaround to IE event facades calculating pageX/Y, possibly triggering a premature reflow
/*
You probably shouldn't use this. It relies on no other code on the page setting the
document.(documentElement/body).onscroll property. If other code is on the page before
this patch is executed, it will be clobbered. If after this patch is executed, all
e.pageX/Y values will be wrong in IE 6-8 if the window is scrolled.
Every major library handles IE's e.pageX/Y deficiency the same way today. Yes, it might
cause a reflow, but the 90%+ case will be that the document's scrollTop/Left properties
are accessed, but no reflow is triggered. DOM access sucks and all, but it's incredibly
unlikely this will show up on your performance profiling.
There's more risk in including this than in not including it, IMHO. Full details at
http://yuilibrary.com/projects/yui3/ticket/2531101
You've been warned.
*/
YUI.add('ie-pagex-patch', function (Y) {
var doc = Y.config.doc,
imp = doc.implementation,
scrollEl = doc.compatMode === "CSS1Compat" ? "documentElement" : "body",
_docScroll = YUI.namespace('Env.evt._docScroll'),
proto = Y.DOMEventFacade.prototype,
resolve = Y.DOM2EventFacade.resolve,
buttonMap = {
0: 1, // left click
4: 2, // middle click
2: 3 // right click
};
function updateDocScroll() {
var scroller = doc[scrollEl];
_docScroll.top = scroller.scrollTop;
_docScroll.left = scroller.scrollLeft;
}
if (imp && (!imp.hasFeature('Events', '2.0'))) {
// lazyEventFacade config uses a different IE facade
if (Y.DOMEventFacade._lazyProperties) {
delete Y.DOMEventFacade._lazyProperties.pageX;
delete Y.DOMEventFacade._lazyProperties.pageY;
proto.init = function () {
var e = this._event,
overrides = this._wrapper.overrides,
define = Y.DomEventFacade._define,
lazyProperties = Y.DomEventFacade._lazyProperties,
prop;
this.altKey = e.altKey;
this.ctrlKey = e.ctrlKey;
this.metaKey = e.metaKey;
this.shiftKey = e.shiftKey;
this.type = (overrides && overrides.type) || e.type;
this.clientX = e.clientX;
this.clientY = e.clientY;
this.pageX = e.pageX || (e.clientX + (_docScroll.left || 0));
this.pageY = e.pageY || (e.clientY + (_docScroll.top || 0));
for (prop in lazyProperties) {
if (lazyProperties.hasOwnProperty(prop)) {
define(this, prop, lazyProperties[prop]);
}
}
if (this._touch) {
this._touch(e, this._currentTarget, this._wrapper);
}
};
} else {
proto.init = function () {
Y.DOMEventFacade.superclass.init.apply(this, arguments);
var e = this._event,
t;
this.target = resolve(e.srcElement);
this.pageX = e.pageX || (e.clientX + (_docScroll.left || 0));
this.pageY = e.pageY || (e.clientY + (_docScroll.top || 0));
if (e.type == "mouseout") {
t = e.toElement;
} else if (e.type == "mouseover") {
t = e.fromElement;
}
this.relatedTarget = resolve(t || e.relatedTarget);
if (e.button !== undefined) {
this.which = this.button = buttonMap[e.button] || e.button;
}
};
}
// Document scroll position is cached globally, so only make this
// subscription once for all instances.
if (!_docScroll.subscribed) {
// Static loaded modules in head need to delay the subscription until
// the body is in the DOM.
if (scrollEl === 'body' && !doc.body) {
Y.on('available', function () {
if (!_docScroll.subscribed) {
// MUST USE DOM0. attachEvent doesn't work
doc[scrollEl].onscroll = updateDocScroll;
_docScroll.subscribed = true;
}
}, 'body');
} else {
// MUST USE DOM0. attachEvent doesn't work
doc[scrollEl].onscroll = updateDocScroll;
_docScroll.subscribed = true;
};
}
}
}, 'YMMV', { requires: ['event-dom-ie'] });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment