delegate.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. var closest = require('./closest');
  2. /**
  3. * Delegates event to a selector.
  4. *
  5. * @param {Element} element
  6. * @param {String} selector
  7. * @param {String} type
  8. * @param {Function} callback
  9. * @param {Boolean} useCapture
  10. * @return {Object}
  11. */
  12. function _delegate(element, selector, type, callback, useCapture) {
  13. var listenerFn = listener.apply(this, arguments);
  14. element.addEventListener(type, listenerFn, useCapture);
  15. return {
  16. destroy: function() {
  17. element.removeEventListener(type, listenerFn, useCapture);
  18. }
  19. }
  20. }
  21. /**
  22. * Delegates event to a selector.
  23. *
  24. * @param {Element|String|Array} [elements]
  25. * @param {String} selector
  26. * @param {String} type
  27. * @param {Function} callback
  28. * @param {Boolean} useCapture
  29. * @return {Object}
  30. */
  31. function delegate(elements, selector, type, callback, useCapture) {
  32. // Handle the regular Element usage
  33. if (typeof elements.addEventListener === 'function') {
  34. return _delegate.apply(null, arguments);
  35. }
  36. // Handle Element-less usage, it defaults to global delegation
  37. if (typeof type === 'function') {
  38. // Use `document` as the first parameter, then apply arguments
  39. // This is a short way to .unshift `arguments` without running into deoptimizations
  40. return _delegate.bind(null, document).apply(null, arguments);
  41. }
  42. // Handle Selector-based usage
  43. if (typeof elements === 'string') {
  44. elements = document.querySelectorAll(elements);
  45. }
  46. // Handle Array-like based usage
  47. return Array.prototype.map.call(elements, function (element) {
  48. return _delegate(element, selector, type, callback, useCapture);
  49. });
  50. }
  51. /**
  52. * Finds closest match and invokes callback.
  53. *
  54. * @param {Element} element
  55. * @param {String} selector
  56. * @param {String} type
  57. * @param {Function} callback
  58. * @return {Function}
  59. */
  60. function listener(element, selector, type, callback) {
  61. return function(e) {
  62. e.delegateTarget = closest(e.target, selector);
  63. if (e.delegateTarget) {
  64. callback.call(element, e);
  65. }
  66. }
  67. }
  68. module.exports = delegate;