pointer_events_polyfill
pointer_events_polyfill copied to clipboard
Vanilla JS version
Hi, i was attempting to use your polyfill for Mobile Angular UI so I re-adapted it to be used without jquery. Dropped the idea since I think nothing could be done for Opera, at least not with a lightweight solution. Never tested, but should be correct and should work.
/*
* Pointer Events Polyfill: Adds support for the style attribute "pointer-events: none" to browsers without this feature (namely, IE).
* (c) 2013, Kent Mewhort, licensed under BSD. See LICENSE.txt for details.
*/
(function() {
'use strict';
// Prevents a drunk to use it twice
if (!window.PointerEventsPolyfill) {
var attachedOnce = false;
var addEventListenerMethod = document.addEventListener ? 'addEventListener' : 'attachEvent';
// Handle multiple events with same callback. Works with ms.
var attachEvents = function(elem, events, callback) {
for (var i = 0; i < events.length; i++) {
elem[addEventListenerMethod](events[i], callback);
}
};
// Detects if pointer-events is supported
var hasNativePointerEventsSupport = function () {
var element = $document.createElement('span');
element.style.cssText = 'pointer-events:auto';
return element.style.pointerEvents === 'auto';
};
// Cross browser `window.getComputedStyle`, taken from jquery .css() source
var getElemComputedStyle = function(elem) {
if ( elem.ownerDocument.defaultView.opener ) {
return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
}
return window.getComputedStyle( elem, null );
};
var polyfillCallback = function(e) {
if (e.target.style.pointerEvents === 'none') {
var origDisplayAttribute = e.target.style.display;
e.target.style.display = 'none';
var underneathElem = document.elementFromPoint(e.clientX, e.clientY);
e.target.style.display = origDisplayAttribute;
e.target = underneathElem;
if (underneathElem.dispatchEvent) {
underneathElem.dispatchEvent(e);
} else if (underneathElem.fireEvent) {
underneathElem.fireEvent('on'+e.eventType, e);
}
return false;
} else {
return true;
}
};
PointerEventsPolyfill.attach = function(userOptions) {
userOptions = userOptions || {};
var options = {
mouseEvents: userOptions.mouseEvents || ['click', 'dblclick', 'mousedown', 'mouseup'],
usePolyfillIf: userOptions.usePolyfillIf || function(){ return !hasNativePointerEventsSupport(); }
};
if (attachedOnce || !options.usePolyfillIf()) { return false; } else {
attachedOnce = true;
attachEvents(document, userOptions.mouseEvents, polyfillCallback);
return true;
}
};
PointerEventsPolyfill.initialize = PointerEventsPolyfill.attach;
window.PointerEventsPolyfill = PointerEventsPolyfill;
}
}());
I think you forgot $document
(should be document
) and you don't seem to be using getElemComputedStyle
. Anyway, I couldn't get this to work with IE10 (e.target
seems to be read-only) and gave up.
You're right $document
should be document
in fact. I do this to 'getElemComputedStyle':
// Cross browser `window.getComputedStyle`, taken from jquery .css() source
var getElemComputedStyle = function(elem) {
if ( elem.ownerDocument.defaultView.opener ) {
return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
}
return window.getComputedStyle( elem, null );
};
I've not tested the entire polyfill I just tested small pieces of it. I think it should work against IE10. What I've done is create a small script detecting wether to use the polyfill or not without jQuery and appending the result to document.body
.
Then I tested it against IE 10 with BrowserStack and it worked. The only failing tests were with Opera, that, like it should be, does not return unsupported properties with getComputedStyle
.
Also note that this code could/should be extended to support pseudo-elements too.
Anyway in my opinion it's very strange to me that those interaction properties are made available through style API without a proper DOM API counterpart, silencing events for an element is such a common use case.