Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing 'Unable to preventDefault inside passive event listener' error within Chrome & OpenLayers 2

I use OpenLayers2 (v2.12) to load and generate a map in the user's browser. Recently, Chrome has released an update so that now when I use my mousewheel to zoom in and out of the OpenLayers map, it also causes the whole page to scroll up and down.

Originally, before this Chrome change, if I used my mousewheel within the map it would zoom in and out as intended, but it would not scroll the whole page. It would only start scrolling the page if I used my mousewheel outside of the OpenLayers map (as intended).

When I now use my mousewheel within the map, the following error is shown:

OpenLayers.min.js:2 [Intervention] Unable to preventDefault inside passive 
event listener due to target being treated as passive. See 
https://www.chromestatus.com/features/6662647093133312

I assume this is the error that is causing the page to scroll.

Looking at similar questions to this error, I have tried to attach a

touch-action: none;

CSS style to the OL map container, however this doesn't seem to work.

The error itself points to some code within the actual OpenLayers.js file and not my code and thus I am not completely sure how I go about fixing this error.

The code causing the error within the Openlayers.min.js file is:

OpenLayers.Event = {
    stop: function(e, t) {
        t || (e.preventDefault ? e.preventDefault() : e.returnValue = !1),
        e.stopPropagation ? e.stopPropagation() : e.cancelBubble = !0
    },
}

notably the e.preventDefault() function.

The unminified OpenLayers file that I am referencing is: https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.12/OpenLayers.min.js

The HTML code for the OL map is:

<div class="container-fluid col-xs-12" style="height: 100%;">
    <div class="row" style="height: 100%;">
        <div class="custom-col-md-10 col-sm-9 col-xs-8" style="height: 100%; overflow-y: hidden; max-height:850px;max-width:1600px;">
            <div class="panel" style="height: 100%; border: solid thin; border-color: darkblue;">
                <div class="panel-body" style="height: 100%; padding: 0px;">
                    <div tabindex="0" id="map" style="height: 100%; width: 100%;">
                    </div>
                </div>
            </div>
       </div>
    </div>
</div>

I am looking for a solution, so that when I use my mousewheel within the OpenLayers map it only zooms in and out of the map, doesn't start scrolling the page too, and the 'unable to preventDefault' error no longer appears.

This only seems to be a Chrome problem. It works as intended in Firefox and Edge.

Many thanks for any help.

like image 788
LukeOr Avatar asked May 02 '19 14:05

LukeOr


People also ask

What are passive event listeners?

Passive event listeners are an emerging web standard, new feature shipped in Chrome 51 that provide a major potential boost to scroll performance. Chrome Release Notes. It enables developers to opt-in to better scroll performance by eliminating the need for scrolling to block on touch and wheel event listeners.

Can I use passive event listeners?

Event listeners created with the passive: true option cannot cancel ( preventDefault() ) the events they receive. Primarily intended to be used with touch events and wheel events. Since they cannot prevent scrolls, passive event listeners allow the browser to perform optimizations that result in smoother scrolling.


1 Answers

There's the same problem on some of the old OpenLayers 2 examples. Using this script fixes it.

const eventListenerOptionsSupported = () => {
  let supported = false;

  try {
    const opts = Object.defineProperty({}, 'passive', {
      get() {
        supported = true;
      }
    });

    window.addEventListener('test', null, opts);
    window.removeEventListener('test', null, opts);
  } catch (e) {}

  return supported;
}

const defaultOptions = {
  passive: false,
  capture: false
};
const supportedPassiveTypes = [
  'scroll', 'wheel',
  'touchstart', 'touchmove', 'touchenter', 'touchend', 'touchleave',
  'mouseout', 'mouseleave', 'mouseup', 'mousedown', 'mousemove', 'mouseenter', 'mousewheel', 'mouseover'
];
const getDefaultPassiveOption = (passive, eventName) => {
  if (passive !== undefined) return passive;

  return supportedPassiveTypes.indexOf(eventName) === -1 ? false : defaultOptions.passive;
};

const getWritableOptions = (options) => {
  const passiveDescriptor = Object.getOwnPropertyDescriptor(options, 'passive');

  return passiveDescriptor && passiveDescriptor.writable !== true && passiveDescriptor.set === undefined
    ? Object.assign({}, options)
    : options;
};

const overwriteAddEvent = (superMethod) => {
  EventTarget.prototype.addEventListener = function (type, listener, options) {
    const usesListenerOptions = typeof options === 'object' && options !== null;
    const useCapture          = usesListenerOptions ? options.capture : options;

    options         = usesListenerOptions ? getWritableOptions(options) : {};
    options.passive = getDefaultPassiveOption(options.passive, type);
    options.capture = useCapture === undefined ? defaultOptions.capture : useCapture;

    superMethod.call(this, type, listener, options);
  };

  EventTarget.prototype.addEventListener._original = superMethod;
};

const supportsPassive = eventListenerOptionsSupported();

if (supportsPassive) {
  const addEvent = EventTarget.prototype.addEventListener;
  overwriteAddEvent(addEvent);
}
like image 99
Mike Avatar answered Oct 16 '22 14:10

Mike