PageSourceSearch

https://simpleorganic.com.br/cdn/shop/t/275/assets/dom-delegate.min.js?v=107666342965953038741781636308

js simpleorganic.com.br collected 2026-09-25 21:03:37 UTC 11,956 bytes, 449 lines download raw bytes

1/*!
2 * dom-delegate v2.2.1 (ftlabs/dom-delegate) — vendored standalone UMD build.
3 * Exposes window.domDelegate (a factory fn with a .Delegate constructor),
4 * matching the global previously produced by libs.min.js. MIT License.
5 */
6(function (root, factory) {
7  if (typeof define === "function" && define.amd) { define([], factory); }
8  else if (typeof module === "object" && module.exports) { module.exports = factory(); }
9  else { root.domDelegate = factory(); }
10}(typeof self !== "undefined" ? self : this, function () {
11  var delegateModule = { exports: {} };
12  (function (module, exports) {
13/*jshint browser:true, node:true*/
14
15'use strict';
16
17module.exports = Delegate;
18
19/**
20 * DOM event delegator
21 *
22 * The delegator will listen
23 * for events that bubble up
24 * to the root node.
25 *
26 * @constructor
27 * @param {Node|string} [root] The root node or a selector string matching the root node
28 */
29function Delegate(root) {
30
31  /**
32   * Maintain a map of listener
33   * lists, keyed by event name.
34   *
35   * @type Object
36   */
37  this.listenerMap = [{}, {}];
38  if (root) {
39    this.root(root);
40  }
41
42  /** @type function() */
43  this.handle = Delegate.prototype.handle.bind(this);
44}
45
46/**
47 * Start listening for events
48 * on the provided DOM element
49 *
50 * @param  {Node|string} [root] The root node or a selector string matching the root node
51 * @returns {Delegate} This method is chainable
52 */
53Delegate.prototype.root = function(root) {
54  var listenerMap = this.listenerMap;
55  var eventType;
56
57  // Remove master event listeners
58  if (this.rootElement) {
59    for (eventType in listenerMap[1]) {
60      if (listenerMap[1].hasOwnProperty(eventType)) {
61        this.rootElement.removeEventListener(eventType, this.handle, true);
62      }
63    }
64    for (eventType in listenerMap[0]) {
65      if (listenerMap[0].hasOwnProperty(eventType)) {
66        this.rootElement.removeEventListener(eventType, this.handle, false);
67      }
68    }
69  }
70
71  // If no root or root is not
72  // a dom node, then remove internal
73  // root reference and exit here
74  if (!root || !root.addEventListener) {
75    if (this.rootElement) {
76      delete this.rootElement;
77    }
78    return this;
79  }
80
81  /**
82   * The root node at which
83   * listeners are attached.
84   *
85   * @type Node
86   */
87  this.rootElement = root;
88
89  // Set up master event listeners
90  for (eventType in listenerMap[1]) {
91    if (listenerMap[1].hasOwnProperty(eventType)) {
92      this.rootElement.addEventListener(eventType, this.handle, true);
93    }
94  }
95  for (eventType in listenerMap[0]) {
96    if (listenerMap[0].hasOwnProperty(eventType)) {
97      this.rootElement.addEventListener(eventType, this.handle, false);
98    }
99  }
100
101  return this;
102};
103
104/**
105 * @param {string} eventType
106 * @returns boolean
107 */
108Delegate.prototype.captureForType = function(eventType) {
109  return ['blur', 'error', 'focus', 'load', 'resize', 'scroll'].indexOf(eventType) !== -1;
110};
111
112/**
113 * Attach a handler to one
114 * event for all elements
115 * that match the selector,
116 * now or in the future
117 *
118 * The handler function receives
119 * three arguments: the DOM event
120 * object, the node that matched
121 * the selector while the event
122 * was bubbling and a reference
123 * to itself. Within the handler,
124 * 'this' is equal to the second
125 * argument.
126 *
127 * The node that actually received
128 * the event can be accessed via
129 * 'event.target'.
130 *
131 * @param {string} eventType Listen for these events
132 * @param {string|undefined} selector Only handle events on elements matching this selector, if undefined match root element
133 * @param {function()} handler Handler function - event data passed here will be in event.data
134 * @param {boolean} [useCapture] see 'useCapture' in <https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener>
135 * @returns {Delegate} This method is chainable
136 */
137Delegate.prototype.on = function(eventType, selector, handler, useCapture) {
138  var root, listenerMap, matcher, matcherParam;
139
140  if (!eventType) {
141    throw new TypeError('Invalid event type: ' + eventType);
142  }
143
144  // handler can be passed as
145  // the second or third argument
146  if (typeof selector === 'function') {
147    useCapture = handler;
148    handler = selector;
149    selector = null;
150  }
151
152  // Fallback to sensible defaults
153  // if useCapture not set
154  if (useCapture === undefined) {
155    useCapture = this.captureForType(eventType);
156  }
157
158  if (typeof handler !== 'function') {
159    throw new TypeError('Handler must be a type of Function');
160  }
161
162  root = this.rootElement;
163  listenerMap = this.listenerMap[useCapture ? 1 : 0];
164
165  // Add master handler for type if not created yet
166  if (!listenerMap[eventType]) {
167    if (root) {
168      root.addEventListener(eventType, this.handle, useCapture);
169    }
170    listenerMap[eventType] = [];
171  }
172
173  if (!selector) {
174    matcherParam = null;
175
176    // COMPLEX - matchesRoot needs to have access to
177    // this.rootElement, so bind the function to this.
178    matcher = matchesRoot.bind(this);
179
180  // Compile a matcher for the given selector
181  } else if (/^[a-z]+$/i.test(selector)) {
182    matcherParam = selector;
183    matcher = matchesTag;
184  } else if (/^#[a-z0-9\-_]+$/i.test(selector)) {
185    matcherParam = selector.slice(1);
186    matcher = matchesId;
187  } else {
188    matcherParam = selector;
189    matcher = matches;
190  }
191
192  // Add to the list of listeners
193  listenerMap[eventType].push({
194    selector: selector,
195    handler: handler,
196    matcher: matcher,
197    matcherParam: matcherParam
198  });
199
200  return this;
201};
202
203/**
204 * Remove an event handler
205 * for elements that match
206 * the selector, forever
207 *
208 * @param {string} [eventType] Remove handlers for events matching this type, considering the other parameters
209 * @param {string} [selector] If this parameter is omitted, only handlers which match the other two will be removed
210 * @param {function()} [handler] If this parameter is omitted, only handlers which match the previous two will be removed
211 * @returns {Delegate} This method is chainable
212 */
213Delegate.prototype.off = function(eventType, selector, handler, useCapture) {
214  var i, listener, listenerMap, listenerList, singleEventType;
215
216  // Handler can be passed as
217  // the second or third argument
218  if (typeof selector === 'function') {
219    useCapture = handler;
220    handler = selector;
221    selector = null;
222  }
223
224  // If useCapture not set, remove
225  // all event listeners
226  if (useCapture === undefined) {
227    this.off(eventType, selector, handler, true);
228    this.off(eventType, selector, handler, false);
229    return this;
230  }
231
232  listenerMap = this.listenerMap[useCapture ? 1 : 0];
233  if (!eventType) {
234    for (singleEventType in listenerMap) {
235      if (listenerMap.hasOwnProperty(singleEventType)) {
236        this.off(singleEventType, selector, handler);
237      }
238    }
239
240    return this;
241  }
242
243  listenerList = listenerMap[eventType];
244  if (!listenerList || !listenerList.length) {
245    return this;
246  }
247
248  // Remove only parameter matches
249  // if specified
250  for (i = listenerList.length - 1; i >= 0; i--) {
251    listener = listenerList[i];
252
253    if ((!selector || selector === listener.selector) && (!handler || handler === listener.handler)) {
254      listenerList.splice(i, 1);
255    }
256  }
257
258  // All listeners removed
259  if (!listenerList.length) {
260    delete listenerMap[eventType];
261
262    // Remove the main handler
263    if (this.rootElement) {
264      this.rootElement.removeEventListener(eventType, this.handle, useCapture);
265    }
266  }
267
268  return this;
269};
270
271
272/**
273 * Handle an arbitrary event.
274 *
275 * @param {Event} event
276 */
277Delegate.prototype.handle = function(event) {
278  var i, l, type = event.type, root, phase, listener, returned, listenerList = [], target, /** @const */ EVENTIGNORE = 'ftLabsDelegateIgnore';
279
280  if (event[EVENTIGNORE] === true) {
281    return;
282  }
283
284  target = event.target;
285
286  // Hardcode value of Node.TEXT_NODE
287  // as not defined in IE8
288  if (target.nodeType === 3) {
289    target = target.parentNode;
290  }
291
292  root = this.rootElement;
293
294  phase = event.eventPhase || ( event.target !== event.currentTarget ? 3 : 2 );
295  
296  switch (phase) {
297    case 1: //Event.CAPTURING_PHASE:
298      listenerList = this.listenerMap[1][type];
299    break;
300    case 2: //Event.AT_TARGET:
301      if (this.listenerMap[0] && this.listenerMap[0][type]) listenerList = listenerList.concat(this.listenerMap[0][type]);
302      if (this.listenerMap[1] && this.listenerMap[1][type]) listenerList = listenerList.concat(this.listenerMap[1][type]);
303    break;
304    case 3: //Event.BUBBLING_PHASE:
305      listenerList = this.listenerMap[0][type];
306    break;
307  }
308
309  // Need to continuously check
310  // that the specific list is
311  // still populated in case one
312  // of the callbacks actually
313  // causes the list to be destroyed.
314  l = listenerList.length;
315  while (target && l) {
316    for (i = 0; i < l; i++) {
317      listener = listenerList[i];
318
319      // Bail from this loop if
320      // the length changed and
321      // no more listeners are
322      // defined between i and l.
323      if (!listener) {
324        break;
325      }
326
327      // Check for match and fire
328      // the event if there's one
329      //
330      // TODO:MCG:20120117: Need a way
331      // to check if event#stopImmediatePropagation
332      // was called. If so, break both loops.
333      if (listener.matcher.call(target, listener.matcherParam, target)) {
334        returned = this.fire(event, target, listener);
335      }
336
337      // Stop propagation to subsequent
338      // callbacks if the callback returned
339      // false
340      if (returned === false) {
341        event[EVENTIGNORE] = true;
342        event.preventDefault();
343        return;
344      }
345    }
346
347    // TODO:MCG:20120117: Need a way to
348    // check if event#stopPropagation
349    // was called. If so, break looping
350    // through the DOM. Stop if the
351    // delegation root has been reached
352    if (target === root) {
353      break;
354    }
355
356    l = listenerList.length;
357    target = target.parentElement;
358  }
359};
360
361/**
362 * Fire a listener on a target.
363 *
364 * @param {Event} event
365 * @param {Node} target
366 * @param {Object} listener
367 * @returns {boolean}
368 */
369Delegate.prototype.fire = function(event, target, listener) {
370  return listener.handler.call(target, event, target);
371};
372
373/**
374 * Check whether an element
375 * matches a generic selector.
376 *
377 * @type function()
378 * @param {string} selector A CSS selector
379 */
380var matches = (function(el) {
381  if (!el) return;
382  var p = el.prototype;
383  return (p.matches || p.matchesSelector || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.oMatchesSelector);
384}(Element));
385
386/**
387 * Check whether an element
388 * matches a tag selector.
389 *
390 * Tags are NOT case-sensitive,
391 * except in XML (and XML-based
392 * languages such as XHTML).
393 *
394 * @param {string} tagName The tag name to test against
395 * @param {Element} element The element to test with
396 * @returns boolean
397 */
398function matchesTag(tagName, element) {
399  return tagName.toLowerCase() === element.tagName.toLowerCase();
400}
401
402/**
403 * Check whether an element
404 * matches the root.
405 *
406 * @param {?String} selector In this case this is always passed through as null and not used
407 * @param {Element} element The element to test with
408 * @returns boolean
409 */
410function matchesRoot(selector, element) {
411  /*jshint validthis:true*/
412  if (this.rootElement === window) return element === document;
413  return this.rootElement === element;
414}
415
416/**
417 * Check whether the ID of
418 * the element in 'this'
419 * matches the given ID.
420 *
421 * IDs are case-sensitive.
422 *
423 * @param {string} id The ID to test against
424 * @param {Element} element The element to test with
425 * @returns boolean
426 */
427function matchesId(id, element) {
428  return id === element.id;
429}
430
431/**
432 * Short hand for off()
433 * and root(), ie both
434 * with no parameters
435 *
436 * @return void
437 */
438Delegate.prototype.destroy = function() {
439  this.off();
440  this.root();
441};
442
443  })(delegateModule, delegateModule.exports);
444  var Delegate = delegateModule.exports;
445  function domDelegate(root) { return new Delegate(root); }
446  domDelegate.Delegate = Delegate;
447  domDelegate.default = Delegate;
448  return domDelegate;
449}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.