Skip to content

Commit b9d67a7

Browse files
committed
[enhancement] add passive event support
closed [#38](#38)
1 parent 1146f68 commit b9d67a7

File tree

4 files changed

+49
-21
lines changed

4 files changed

+49
-21
lines changed

flow/module.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ declare module 'chimee-helper' {
9191
declare export function removeClassName (el: Node, cls: string): void;
9292
declare export function hasClassName (el: Node, cls: string): boolean;
9393
declare export function removeEvent (el: Node, type: string, handler: Function, once?: boolean, capture?: boolean): void;
94-
declare export function addEvent (el: Node, type: string, handler: Function, once?: boolean, capture?: boolean): void;
94+
declare export function addEvent (el: Node, type: string, handler: Function, once?: boolean, capture?: boolean | Object): void;
9595
declare export function addDelegate (el: Node, selector: string, type: string, handler: Function, capture: boolean): void;
9696
declare export function removeDelegate (el: Node, selector: string, type: string, handler: Function, capture: boolean): void;
9797
declare export function getStyle (el: Node, key: string): string;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"homepage": "https://github.com/Chimeejs/chimee#readme",
4646
"dependencies": {
4747
"babel-runtime": "^6.26.0",
48-
"chimee-helper": "^0.2.6",
48+
"chimee-helper": "^0.2.8",
4949
"chimee-kernel": "^1.0.15",
5050
"es-fullscreen": "^0.2.1",
5151
"toxic-decorators": "^0.3.8"

src/dispatcher/dom.js

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @flow
22
import { isArray, isElement, isString, isHTMLString, hypenate, isFunction, isEmpty, isPosterityNode, isObject, isBoolean, $, setStyle, getStyle, setAttr, addEvent, getAttr, removeEvent, addClassName, Log, isEvent } from 'chimee-helper';
3-
import { videoEvents, domEvents } from 'helper/const';
3+
import { videoEvents, domEvents, passiveEvents } from 'helper/const';
44
import esFullscreen from 'es-fullscreen';
55
import { autobind, before, waituntil } from 'toxic-decorators';
66
function targetCheck(target: string, ...args) {
@@ -75,6 +75,7 @@ export default class Dom {
7575
__videoExtendedNodes = [];
7676
isFullscreen = false;
7777
fullscreenElement = undefined;
78+
7879
constructor(wrapper: string | Element, dispatcher: Dispatcher) {
7980
this.__dispatcher = dispatcher;
8081
if (!isElement(wrapper) && !isString(wrapper)) throw new TypeError(`Wrapper can only be string or HTMLElement, but not ${typeof wrapper}`);
@@ -100,17 +101,12 @@ export default class Dom {
100101
* referrence of video's dom element
101102
*/
102103
this.installVideo(videoElement);
103-
domEvents.forEach(key => {
104-
const cfn = (...args: any) => this.__dispatcher.bus.triggerSync('c_' + key, ...args);
105-
this.containerDomEventHandlerList.push(cfn);
106-
addEvent(this.container, key, cfn);
107-
const wfn = (...args: any) => this.__dispatcher.bus.triggerSync('w_' + key, ...args);
108-
this.wrapperDomEventHandlerList.push(wfn);
109-
addEvent(this.wrapper, key, wfn);
110-
});
104+
this._addDomEvents(this.container, this.containerDomEventHandlerList, key => (...args: any) => this.__dispatcher.bus.triggerSync('c_' + key, ...args));
105+
this._addDomEvents(this.wrapper, this.wrapperDomEventHandlerList, key => (...args: any) => this.__dispatcher.bus.triggerSync('w_' + key, ...args));
111106
this._fullscreenMonitor();
112107
esFullscreen.on('fullscreenchange', this._fullscreenMonitor);
113108
}
109+
114110
installVideo(videoElement: HTMLVideoElement): HTMLVideoElement {
115111
this.__videoExtendedNodes.push(videoElement);
116112
setAttr(videoElement, 'tabindex', -1);
@@ -143,14 +139,11 @@ export default class Dom {
143139
this.videoEventHandlerList.push(fn);
144140
addEvent(videoElement, key, fn);
145141
});
146-
domEvents.forEach(key => {
147-
const fn = this._getEventHandler(key, { penetrate: true });
148-
this.videoDomEventHandlerList.push(fn);
149-
addEvent(videoElement, key, fn);
150-
});
142+
this._addDomEvents(videoElement, this.videoDomEventHandlerList, key => this._getEventHandler(key, { penetrate: true }));
151143
this.videoElement = videoElement;
152144
return videoElement;
153145
}
146+
154147
removeVideo(): HTMLVideoElement {
155148
const videoElement = this.videoElement;
156149
this._autoFocusToVideo(this.videoElement, false);
@@ -166,6 +159,7 @@ export default class Dom {
166159
delete this.videoElement;
167160
return videoElement;
168161
}
162+
169163
/**
170164
* each plugin has its own dom node, this function will create one or them.
171165
* we support multiple kind of el
@@ -209,11 +203,7 @@ export default class Dom {
209203
// auto forward the event if this plugin can be penetrate
210204
if (penetrate) {
211205
this.__domEventHandlerList[id] = this.__domEventHandlerList[id] || [];
212-
domEvents.forEach(key => {
213-
const fn = this._getEventHandler(key, { penetrate });
214-
addEvent(node, key, fn);
215-
this.__domEventHandlerList[id].push(fn);
216-
});
206+
this._addDomEvents(node, this.__domEventHandlerList[id], key => this._getEventHandler(key, { penetrate }));
217207
this.__videoExtendedNodes.push(node);
218208
}
219209
if (outerElement.lastChild === originElement) {
@@ -223,6 +213,7 @@ export default class Dom {
223213
outerElement.insertBefore(node, originElement.nextSibling);
224214
return node;
225215
}
216+
226217
/**
227218
* remove plugin's dom
228219
*/
@@ -241,13 +232,15 @@ export default class Dom {
241232
}
242233
delete this.plugins[id];
243234
}
235+
244236
/**
245237
* Set zIndex for a plugins list
246238
*/
247239
setPluginsZIndex(plugins: Array<string>): void {
248240
// $FlowFixMe: there are videoElment and container here
249241
plugins.forEach((key, index) => setStyle(key.match(/^(videoElement|container)$/) ? this[key] : this.plugins[key], 'z-index', ++index));
250242
}
243+
251244
/**
252245
* set attribute on our dom
253246
* @param {string} attr attribute's name
@@ -260,37 +253,45 @@ export default class Dom {
260253
// $FlowFixMe: flow do not support computed property/element on class, which is silly here.
261254
setAttr(this[target], attr, val);
262255
}
256+
263257
@before(attrOperationCheck, targetCheck)
264258
getAttr(target: string, attr: string): string {
265259
// $FlowFixMe: flow do not support computed property/element on class, which is silly here.
266260
return getAttr(this[target], attr);
267261
}
262+
268263
@before(attrOperationCheck, targetCheck)
269264
setStyle(target: string, attr: string, val: any): void {
270265
// $FlowFixMe: flow do not support computed property/element on class, which is silly here.
271266
setStyle(this[target], attr, val);
272267
}
268+
273269
@before(attrOperationCheck, targetCheck)
274270
getStyle(target: string, attr: string): string {
275271
// $FlowFixMe: flow do not support computed property/element on class, which is silly here.
276272
return getStyle(this[target], attr);
277273
}
274+
278275
@before(targetCheck)
279276
requestFullscreen(target: string) {
280277
// $FlowFixMe: flow do not support computed property/element on document, which is silly here.
281278
return esFullscreen.open(this[target]);
282279
}
280+
283281
exitFullscreen(): boolean {
284282
return esFullscreen.exit();
285283
}
284+
286285
fullscreen(request: boolean = true, target: string = 'container', ...args: any): boolean {
287286
return request
288287
? this.requestFullscreen(target, ...args)
289288
: this.exitFullscreen(...args);
290289
}
290+
291291
focus() {
292292
this.videoElement.focus();
293293
}
294+
294295
/**
295296
* function called when we distory
296297
*/
@@ -305,17 +306,36 @@ export default class Dom {
305306
delete this.wrapper;
306307
delete this.plugins;
307308
}
309+
310+
/**
311+
* bind all dom events on one element
312+
* we will use passive mode if it support
313+
*/
314+
_addDomEvents(element: Element, handlerList: Array<Function>, handlerGenerate: Function) {
315+
domEvents.forEach(key => {
316+
const fn = handlerGenerate(key);
317+
handlerList.push(fn);
318+
if (passiveEvents.indexOf(key) > -1) {
319+
addEvent(element, key, fn, false, { passive: true });
320+
return;
321+
}
322+
addEvent(element, key, fn);
323+
});
324+
}
325+
308326
_autoFocusToVideo(element: Element, remove: boolean = false): void {
309327
(remove ? removeEvent : addEvent)(element, 'mouseup', this._focusToVideo, false, true);
310328
(remove ? removeEvent : addEvent)(element, 'touchend', this._focusToVideo, false, true);
311329
}
330+
312331
@autobind
313332
_focusToVideo() {
314333
const x = window.scrollX;
315334
const y = window.scrollY;
316335
isFunction(this.videoElement.focus) && this.videoElement.focus();
317336
window.scrollTo(x, y);
318337
}
338+
319339
@autobind
320340
_fullscreenMonitor(evt?: Event) {
321341
const element = esFullscreen.fullscreenElement;
@@ -337,6 +357,7 @@ export default class Dom {
337357
this.__dispatcher.bus.triggerSync('fullscreenchange', evt);
338358
}
339359
}
360+
340361
/**
341362
* get the event handler for dom to bind
342363
*/

src/helper/const.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,19 @@ export const domEvents = [
7272
'scroll',
7373
'select',
7474
'wheel',
75+
'mousewheel',
7576
'fullscreenchange',
7677
'contextmenu',
7778
'touchstart',
7879
'touchmove',
7980
'touchend',
8081
];
82+
export const passiveEvents = [
83+
'wheel',
84+
'mousewheel',
85+
'touchstart',
86+
'touchmove',
87+
];
8188
export const selfProcessorEvents = [
8289
'silentLoad',
8390
'fullscreen',

0 commit comments

Comments
 (0)