/**
|
* @fileoverview Bind DOM events
|
* @author NHN FE Development Lab <dl_javascript@nhn.com>
|
*/
|
|
'use strict';
|
|
var isString = require('../type/isString');
|
var forEach = require('../collection/forEach');
|
|
var safeEvent = require('./_safeEvent');
|
|
/**
|
* Bind DOM events.
|
* @param {HTMLElement} element - element to bind events
|
* @param {(string|object)} types - Space splitted events names or eventName:handler object
|
* @param {(function|object)} handler - handler function or context for handler method
|
* @param {object} [context] context - context for handler method.
|
* @memberof module:domEvent
|
* @example
|
* const div = document.querySelector('div');
|
*
|
* // Bind one event to an element.
|
* on(div, 'click', toggle);
|
*
|
* // Bind multiple events with a same handler to multiple elements at once.
|
* // Use event names splitted by a space.
|
* on(div, 'mouseenter mouseleave', changeColor);
|
*
|
* // Bind multiple events with different handlers to an element at once.
|
* // Use an object which of key is an event name and value is a handler function.
|
* on(div, {
|
* keydown: highlight,
|
* keyup: dehighlight
|
* });
|
*
|
* // Set a context for handler method.
|
* const name = 'global';
|
* const repository = {name: 'CodeSnippet'};
|
* on(div, 'drag', function() {
|
* console.log(this.name);
|
* }, repository);
|
* // Result when you drag a div: "CodeSnippet"
|
*/
|
function on(element, types, handler, context) {
|
if (isString(types)) {
|
forEach(types.split(/\s+/g), function(type) {
|
bindEvent(element, type, handler, context);
|
});
|
|
return;
|
}
|
|
forEach(types, function(func, type) {
|
bindEvent(element, type, func, handler);
|
});
|
}
|
|
/**
|
* Bind DOM events
|
* @param {HTMLElement} element - element to bind events
|
* @param {string} type - events name
|
* @param {function} handler - handler function or context for handler method
|
* @param {object} [context] context - context for handler method.
|
* @private
|
*/
|
function bindEvent(element, type, handler, context) {
|
/**
|
* Event handler
|
* @param {Event} e - event object
|
*/
|
function eventHandler(e) {
|
handler.call(context || element, e || window.event);
|
}
|
|
if ('addEventListener' in element) {
|
element.addEventListener(type, eventHandler);
|
} else if ('attachEvent' in element) {
|
element.attachEvent('on' + type, eventHandler);
|
}
|
memorizeHandler(element, type, handler, eventHandler);
|
}
|
|
/**
|
* Memorize DOM event handler for unbinding.
|
* @param {HTMLElement} element - element to bind events
|
* @param {string} type - events name
|
* @param {function} handler - handler function that user passed at on() use
|
* @param {function} wrappedHandler - handler function that wrapped by domevent for implementing some features
|
* @private
|
*/
|
function memorizeHandler(element, type, handler, wrappedHandler) {
|
var events = safeEvent(element, type);
|
var existInEvents = false;
|
|
forEach(events, function(obj) {
|
if (obj.handler === handler) {
|
existInEvents = true;
|
|
return false;
|
}
|
|
return true;
|
});
|
|
if (!existInEvents) {
|
events.push({
|
handler: handler,
|
wrappedHandler: wrappedHandler
|
});
|
}
|
}
|
|
module.exports = on;
|