pointer_events_polyfill icon indicating copy to clipboard operation
pointer_events_polyfill copied to clipboard

Vanilla JS version

Open mcasimir opened this issue 9 years ago • 3 comments

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;
  }
}());

mcasimir avatar Dec 02 '14 00:12 mcasimir

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.

gaearon avatar Dec 10 '14 16:12 gaearon

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.

mcasimir avatar Dec 10 '14 16:12 mcasimir

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.

mcasimir avatar Dec 10 '14 17:12 mcasimir