Skip to content

Commit

Permalink
Fixed #11353, added support for passive events.
Browse files Browse the repository at this point in the history
  • Loading branch information
raf18seb committed Oct 14, 2020
1 parent 39e37fa commit bc15974
Show file tree
Hide file tree
Showing 16 changed files with 123 additions and 27 deletions.
2 changes: 1 addition & 1 deletion js/Accessibility/AccessibilityComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ AccessibilityComponent.prototype = {
}
e.stopPropagation();
e.preventDefault();
});
}, { passive: false });
});
},
/**
Expand Down
3 changes: 3 additions & 0 deletions js/Core/Chart/Chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ var Chart = /** @class */ (function () {
if (isFunction(event)) {
addEvent(chart, eventType, event);
}
else if (isObject(event)) {
addEvent(chart, eventType, event.listener, event.options);
}
});
}
/**
Expand Down
21 changes: 19 additions & 2 deletions js/Core/Globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,23 @@ typeof win !== 'undefined' ?
doc.createElementNS &&
!!doc.createElementNS(SVG_NS, 'svg').createSVGRect), isMS = /(edge|msie|trident)/i.test(userAgent) && !glob.opera, isFirefox = userAgent.indexOf('Firefox') !== -1, isChrome = userAgent.indexOf('Chrome') !== -1, hasBidiBug = (isFirefox &&
parseInt(userAgent.split('Firefox/')[1], 10) < 4 // issue #38
);
), noop = function () { },
// Checks whether the browser supports passive events, (#11353).
checkPassiveEvents = function () {
var supportsPassive = false;
// Object.defineProperty doesn't work on IE as well as passive events -
// instead of using polyfill, we can exclude IE totally.
if (!isMS) {
var opts = Object.defineProperty({}, 'passive', {
get: function () {
supportsPassive = true;
}
});
glob.addEventListener('testPassive', noop, opts);
glob.removeEventListener('testPassive', noop, opts);
}
return supportsPassive;
};
var H = {
product: 'Highcharts',
version: '@product.version@',
Expand All @@ -45,11 +61,12 @@ var H = {
SVG_NS: SVG_NS,
chartCount: 0,
seriesTypes: {},
isPassiveEvent: checkPassiveEvents(),
symbolSizes: {},
svg: svg,
win: glob,
marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'],
noop: function () { },
noop: noop,
/**
* Theme options that should get applied to the chart. In module mode it
* might not be possible to change this property because of read-only
Expand Down
3 changes: 3 additions & 0 deletions js/Core/Interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,9 @@ extend(Point.prototype, /** @lends Highcharts.Point.prototype */ {
if (isFunction(event)) {
addEvent(point, eventType, event);
}
else if (isObject(event)) {
addEvent(point, eventType, event.listener, event.options);
}
});
this.hasImportedEvents = true;
}
Expand Down
14 changes: 13 additions & 1 deletion js/Core/Utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ import H from './Globals.js';
* added.
* @name Highcharts.EventOptionsObject#order
* @type {number}
*/ /**
* Whether an event should be passive or not.
* When set to `true`, the function specified by listener will never call
* `preventDefault()`.
* @name Highcharts.EventOptionsObject#passive
* @type boolean
*/
/**
* Formats data as a string. Usually the data is accessible throught the `this`
Expand Down Expand Up @@ -1719,8 +1725,14 @@ var addEvent = H.addEvent = function (el, type, fn, options) {
el.series.chart.runTrackerClick = true;
}
// Handle DOM events
// If the browser supports passive events, add it to improve performance
// on touch events (#11353).
if (addEventListener) {
addEventListener.call(el, type, fn, false);
addEventListener.call(el, type, fn, H.isPassiveEvent ? {
passive: options.passive === void 0 ?
type.indexOf('touch') !== -1 : options.passive,
capture: false
} : false);
}
if (!events[type]) {
events[type] = [];
Expand Down
2 changes: 1 addition & 1 deletion js/Extensions/Annotations/Mixins/EventEmitterMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var eventEmitterMixin = {
var emitter = this, addMouseDownEvent = function (element) {
addEvent(element, H.isTouchDevice ? 'touchstart' : 'mousedown', function (e) {
emitter.onMouseDown(e);
});
}, { passive: false });
};
addMouseDownEvent(this.graphic.element);
(emitter.labels || []).forEach(function (label) {
Expand Down
6 changes: 3 additions & 3 deletions js/Extensions/DraggablePoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ Point.prototype.showDragHandles = function () {
// Add events
addEvents(handle.element, ['touchstart', 'mousedown'], function (e) {
onResizeHandleMouseDown(getNormalizedEvent(e, chart), point, key);
});
}, { passive: false });
addEvent(chart.dragHandles.group.element, 'mouseover', function () {
chart.dragDropData = chart.dragDropData || {};
chart.dragDropData.isHoveringHandle = point.id;
Expand Down Expand Up @@ -2216,13 +2216,13 @@ function addDragDropEvents(chart) {
});
addEvents(container, ['mousemove', 'touchmove'], function (e) {
mouseMove(getNormalizedEvent(e, chart), chart);
});
}, { passive: false });
addEvent(container, 'mouseleave', function (e) {
mouseUp(getNormalizedEvent(e, chart), chart);
});
chart.unbindDragDropMouseUp = addEvents(doc, ['mouseup', 'touchend'], function (e) {
mouseUp(getNormalizedEvent(e, chart), chart);
});
}, { passive: false });
// Add flag to avoid doing this again
chart.hasAddedDragDropEvents = true;
// Add cleanup to make sure we don't pollute document
Expand Down
2 changes: 1 addition & 1 deletion ts/Accessibility/AccessibilityComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ AccessibilityComponent.prototype = {

e.stopPropagation();
e.preventDefault();
});
}, { passive: false });
});
},

Expand Down
4 changes: 3 additions & 1 deletion ts/Core/Chart/Chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,14 +535,16 @@ class Chart {
*/
chart.index = charts.length; // Add the chart to the global lookup

charts.push(chart as any);
charts.push(chart);
H.chartCount++;

// Chart event handlers
if (chartEvents) {
objectEach(chartEvents, function (event, eventType): void {
if (isFunction(event)) {
addEvent(chart, eventType, event);
} else if (isObject(event)) {
addEvent(chart, eventType, event.listener, event.options);
}
});
}
Expand Down
26 changes: 24 additions & 2 deletions ts/Core/Globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ declare global {
const marginNames: Array<string>;
const noop: () => void;
const product: string;
const isPassiveEvent: boolean;
const symbolSizes: Dictionary<SizeObject>;
const win: GlobalWindow;
const svg: boolean;
Expand Down Expand Up @@ -164,7 +165,27 @@ var glob = ( // @todo UMD variable named `window`, and glob named `win`
hasBidiBug = (
isFirefox &&
parseInt(userAgent.split('Firefox/')[1], 10) < 4 // issue #38
);
),
noop = function (): void {},
// Checks whether the browser supports passive events, (#11353).
checkPassiveEvents = function (): boolean {
let supportsPassive = false;

// Object.defineProperty doesn't work on IE as well as passive events -
// instead of using polyfill, we can exclude IE totally.
if (!isMS) {
const opts = Object.defineProperty({}, 'passive', {
get: function (): void {
supportsPassive = true;
}
});

glob.addEventListener('testPassive', noop, opts);
glob.removeEventListener('testPassive', noop, opts);
}

return supportsPassive;
};

var H: typeof Highcharts = {
product: 'Highcharts',
Expand All @@ -182,11 +203,12 @@ var H: typeof Highcharts = {
SVG_NS: SVG_NS,
chartCount: 0,
seriesTypes: {} as Highcharts.SeriesTypesDictionary,
isPassiveEvent: checkPassiveEvents(),
symbolSizes: {},
svg: svg,
win: glob,
marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'],
noop: function (): void {},
noop: noop,

/**
* Theme options that should get applied to the chart. In module mode it
Expand Down
16 changes: 9 additions & 7 deletions ts/Core/Interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1117,14 +1117,16 @@ extend(Point.prototype, /** @lends Highcharts.Point.prototype */ {

point.events = events;

objectEach(events, function (
event: Function,
eventType: string
): void {
if (isFunction(event)) {
addEvent(point, eventType, event);
objectEach(
events as Highcharts.PointEventsOptionsObject,
function (event, eventType): void {
if (isFunction(event)) {
addEvent(point, eventType, event);
} else if (isObject(event)) {
addEvent(point, eventType, event.listener, event.options);
}
}
});
);
this.hasImportedEvents = true;

}
Expand Down
9 changes: 8 additions & 1 deletion ts/Core/Options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ declare global {
interface ChartClickCallbackFunction {
(this: Chart, event: PointerEventObject): void;
}
interface ChartClickCallbackObjectOptions {
passive?: boolean;
}
interface ChartClickCallbackObject {
listener: ChartClickCallbackFunction;
options?: ChartClickCallbackObjectOptions;
}
interface ChartClickEventAxisObject {
axis: Axis;
value: number;
Expand All @@ -83,7 +90,7 @@ declare global {
}
interface ChartEventsOptions {
addSeries?: ChartAddSeriesCallbackFunction;
click?: ChartClickCallbackFunction;
click?: ChartClickCallbackFunction|ChartClickCallbackObject;
load?: ChartLoadCallbackFunction;
redraw?: ChartRedrawCallbackFunction;
render?: ChartRenderCallbackFunction;
Expand Down
9 changes: 8 additions & 1 deletion ts/Core/Series/Point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,18 @@ declare global {
interface PointClickCallbackFunction {
(this: Point, event: PointClickEventObject): void;
}
interface PointClickCallbackObject {
listener: PointClickCallbackFunction;
options?: PointClickCallbackObjectOptions;
}
interface PointClickCallbackObjectOptions {
passive?: boolean;
}
interface PointClickEventObject extends PointerEventObject {
point: Point;
}
interface PointEventsOptionsObject {
click?: PointClickCallbackFunction;
click?: PointClickCallbackFunction|PointClickCallbackObject;
mouseOut?: PointMouseOutCallbackFunction;
mouseOver?: PointMouseOverCallbackFunction;
remove?: PointRemoveCallbackFunction;
Expand Down
20 changes: 19 additions & 1 deletion ts/Core/Utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ declare global {
}
interface EventOptionsObject {
order?: number;
passive?: boolean;
}
interface EventWrapperObject<T> {
fn: Highcharts.EventCallbackFunction<T>;
Expand Down Expand Up @@ -501,6 +502,12 @@ declare global {
* added.
* @name Highcharts.EventOptionsObject#order
* @type {number}
*//**
* Whether an event should be passive or not.
* When set to `true`, the function specified by listener will never call
* `preventDefault()`.
* @name Highcharts.EventOptionsObject#passive
* @type boolean
*/

/**
Expand Down Expand Up @@ -2341,8 +2348,19 @@ const addEvent = H.addEvent = function<T> (
}

// Handle DOM events
// If the browser supports passive events, add it to improve performance
// on touch events (#11353).
if (addEventListener) {
addEventListener.call(el, type, fn, false);
addEventListener.call(
el,
type,
fn,
H.isPassiveEvent ? {
passive: options.passive === void 0 ?
type.indexOf('touch') !== -1 : options.passive,
capture: false
} : false
);
}

if (!events[type]) {
Expand Down
3 changes: 2 additions & 1 deletion ts/Extensions/Annotations/Mixins/EventEmitterMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ const eventEmitterMixin: Highcharts.AnnotationEventEmitterMixin = {
H.isTouchDevice ? 'touchstart' : 'mousedown',
(e: Highcharts.AnnotationEventObject): void => {
emitter.onMouseDown(e);
}
},
{ passive: false }
);
};

Expand Down
10 changes: 6 additions & 4 deletions ts/Extensions/DraggablePoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ declare global {
}
interface PointEventsOptionsObject {
drag?: PointDragCallbackFunction;
dragDrop?: DragDropOptionsObject;
dragStart?: PointDragStartCallbackFunction;
drop?: PointDropCallbackFunction;
}
Expand Down Expand Up @@ -2627,7 +2626,8 @@ Point.prototype.showDragHandles = function (): void {
point,
key
);
}
},
{ passive: false }
);
addEvent(
(chart.dragHandles as any).group.element,
Expand Down Expand Up @@ -3029,7 +3029,8 @@ function addDragDropEvents(chart: Chart): void {
['mousemove', 'touchmove'],
function (e: PointerEvent): void {
mouseMove(getNormalizedEvent(e, chart), chart);
}
},
{ passive: false }
);
addEvent(
container,
Expand All @@ -3043,7 +3044,8 @@ function addDragDropEvents(chart: Chart): void {
['mouseup', 'touchend'],
function (e: PointerEvent): void {
mouseUp(getNormalizedEvent(e, chart), chart);
}
},
{ passive: false }
);

// Add flag to avoid doing this again
Expand Down

0 comments on commit bc15974

Please sign in to comment.