PageSourceSearch

https://www.safedriving.or.kr/resources/anyid/libs/polymer/3.5.2/lib/legacy/polymer.dom.js

js safedriving.or.kr collected 2026-09-26 04:01:24 UTC 14,266 bytes, 497 lines download raw bytes

1
2/**
3@license
4Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
5This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
6The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
7The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
8Code distributed by Google as part of the polymer project is also
9subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
10*/
11import '../utils/boot.js';
12import { wrap } from '../utils/wrap.js';
13import '../utils/settings.js';
14import { FlattenedNodesObserver } from '../utils/flattened-nodes-observer.js';
15export { flush, enqueueDebouncer as addDebouncer } from '../utils/flush.js';
16/* eslint-disable no-unused-vars */
17import { Debouncer } from '../utils/debounce.js';  // used in type annotations
18/* eslint-enable no-unused-vars */
19
20const p = Element.prototype;
21/**
22 * @const {function(this:Node, string): boolean}
23 */
24const normalizedMatchesSelector = p.matches || p.matchesSelector ||
25  p.mozMatchesSelector || p.msMatchesSelector ||
26  p.oMatchesSelector || p.webkitMatchesSelector;
27
28/**
29 * Cross-platform `element.matches` shim.
30 *
31 * @function matchesSelector
32 * @param {!Node}
32 node Node to check selector against
33 * @param {string} selector Selector to match
34 * @return {boolean} True if node matched selector
35 */
36export const matchesSelector = function(node, selector) {
37  return normalizedMatchesSelector.call(node, selector);
38};
39
40/**
41 * Node API wrapper class returned from `Polymer.dom.(target)` when
42 * `target` is a `Node`.
43 * @implements {PolymerDomApi}
44 * @unrestricted
45 */
46class DomApiNative {
47
48  /**
49   * @param {!Node} node Node for which to create a Polymer.dom helper object.
50   */
51  constructor(node) {
52    if (window['ShadyDOM'] && window['ShadyDOM']['inUse']) {
53      window['ShadyDOM']['patch'](node);
54    }
55    this.node = node;
56  }
57
58  /**
59   * Returns an instance of `FlattenedNodesObserver` that
60   * listens for node changes on this element.
61   *
62   * @param {function(this:HTMLElement, { target: !HTMLElement, addedNodes: !Array<!Element>, removedNodes: !Array<!Element> }):void} callback Called when direct or distributed children
63   *   of this element changes
64   * @return {!PolymerDomApi.ObserveHandle} Observer instance
65   * @override
66   */
67  observeNodes(callback) {
68    return new FlattenedNodesObserver(
69        /** @type {!HTMLElement} */(this.node), callback);
70  }
71
72  /**
73   * Disconnects an observer previously created via `observeNodes`
74   *
75   * @param {!PolymerDomApi.ObserveHandle} observerHandle Observer instance
76   *   to disconnect.
77   * @return {void}
78   * @override
79   */
80  unobserveNodes(observerHandle) {
81    observerHandle.disconnect();
82  }
83
84  /**
85   * Provided as a backwards-compatible API only.  This method does nothing.
86   * @return {void}
87   */
88  notifyObserver() {}
89
90  /**
91   * Returns true if the provided node is contained with this element's
92   * light-DOM children or shadow root, including any nested shadow roots
93   * of children therein.
94   *
95   * @param {Node} node Node to test
96   * @return {boolean} Returns true if the given `node` is contained within
97   *   this element's light or shadow DOM.
98   * @override
99   */
100  deepContains(node) {
101    if (wrap(this.node).contains(node)) {
102      return true;
103    }
104    let n = node;
105    let doc = node.ownerDocument;
106    // walk from node to `this` or `document`
107    while (n && n !== doc && n !== this.node) {
108      // use logical parentnode, or native ShadowRoot host
109      n = wrap(n).parentNode || wrap(n).host;
110    }
111    return n === this.node;
112  }
113
114  /**
115   * Returns the root node of this node.  Equivalent to `getRootNode()`.
116   *
117   * @return {!Node} Top most element in the dom tree in which the node
118   * exists. If the node is connected to a document this is either a
119   * shadowRoot or the document; otherwise, it may be the node
120   * itself or a node or document fragment containing it.
121   * @override
122   */
123  getOwnerRoot() {
124    return wrap(this.node).getRootNode();
125  }
126
127  /**
128   * For slot elements, returns the nodes assigned to the slot; otherwise
129   * an empty array. It is equivalent to `<slot>.addignedNodes({flatten:true})`.
130   *
131   * @return {!Array<!Node>} Array of assigned nodes
132   * @override
133   */
134  getDistributedNodes() {
135    return (this.node.localName === 'slot') ?
136      wrap(this.node).assignedNodes({flatten: true}) :
137      [];
138  }
139
140  /**
141   * Returns an array of all slots this element was distributed to.
142   *
143   * @return {!Array<!HTMLSlotElement>} Description
144   * @override
145   */
146  getDestinationInsertionPoints() {
147    let ip$ = [];
148    let n = wrap(this.node).assignedSlot;
149    while (n) {
150      ip$.push(n);
151      n = wrap(n).assignedSlot;
152    }
153    return ip$;
154  }
155
156  /**
157   * Calls `importNode` on the `ownerDocument` for this node.
158   *
159   * @param {!Node} node Node to import
160   * @param {boolean} deep True if the node should be cloned deeply during
161   *   import
162   * @return {Node} Clone of given node imported to this owner document
163   */
164  importNode(node, deep) {
165    let doc = this.node instanceof Document ? this.node :
166      this.node.ownerDocument;
167    return wrap(doc).importNode(node, deep);
168  }
169
170  /**
171   * @return {!Array<!Node>} Returns a flattened list of all child nodes and
172   * nodes assigned to child slots.
173   * @override
174   */
175  getEffectiveChildNodes() {
176    return FlattenedNodesObserver.getFlattenedNodes(
177        /** @type {!HTMLElement} */ (this.node));
178  }
179
180  /**
181   * Returns a filtered list of flattened child elements for this element based
182   * on the given selector.
183   *
184   * @param {string} selector Selector to filter nodes against
185   * @return {!Array<!HTMLElement>} List of flattened child elements
186   * @override
187   */
188  queryDistributedElements(selector) {
189    let c$ = this.getEffectiveChildNodes();
190    let list = [];
191    for (let i=0, l=c$.length, c; (i<l) && (c=c$[i]); i++) {
192      if ((c.nodeType === Node.ELEMENT_NODE) &&
193          matchesSelector(c, selector)) {
194        list.push(c);
195      }
196    }
197    return list;
198  }
199
200  /**
201   * For shadow roots, returns the currently focused element within this
202   * shadow root.
203   *
204   * return {Node|undefined} Currently focused element
205   * @override
206   */
207  get activeElement() {
208    let node = this.node;
209    return node._activeElement !== undefined ? node._activeElement : node.activeElement;
210  }
211}
212
213function forwardMethods(proto, methods) {
214  for (let i=0; i < methods.length; i++) {
215    let method = methods[i];
216    /* eslint-disable valid-jsdoc */
217    proto[method] = /** @this {DomApiNative} */ function() {
218      return this.node[method].apply(this.node, arguments);
219    };
220    /* eslint-enable */
221  }
222}
223
224function forwardReadOnlyProperties(proto, properties) {
225  for (let i=0; i < properties.length; i++) {
226    let name = properties[i];
227    Object.defineProperty(proto, name, {
228      get: function() {
229        const domApi = /** @type {DomApiNative} */(this);
230        return domApi.node[name];
231      },
232      configurable: true
233    });
234  }
235}
236
237function forwardProperties(proto, properties) {
238  for (let i=0; i < properties.length; i++) {
239    let name = properties[i];
240    Object.defineProperty(proto, name, {
241      /**
242       * @this {DomApiNative}
243       * @return {*} .
244       */
245      get: function() {
246        return this.node[name];
247      },
248      /**
249       * @this {DomApiNative}
250       * @param {*} value .
251       */
252      set: function(value) {
253        this.node[name] = value;
254      },
255      configurable: true
256    });
257  }
258}
259
260
261/**
262 * Event API wrapper class returned from `dom.(target)` when
263 * `target` is an `Event`.
264 */
265export class EventApi {
266  constructor(event) {
267    this.event = event;
268  }
269
270  /**
271   * Returns the first node on the `composedPath` of this event.
272   *
273   * @return {!EventTarget} The node this event was dispatched to
274   */
275  get rootTarget() {
276    return this.path[0];
277  }
278
279  /**
280   * Returns the local (re-targeted) target for this event.
281   *
282   * @return {!EventTarget} The local (re-targeted) target for this event.
283   */
284  get localTarget() {
285    return this.event.target;
286  }
287
288  /**
289   * Returns the `composedPath` for this event.
290   * @return {!Array<!EventTarget>} The nodes this event propagated through
291   */
292  get path() {
293    return this.event.composedPath();
294  }
295}
296
297/**
298 * @function
299 * @param {boolean=} deep
300 * @return {!Node}
301 */
302DomApiNative.prototype.cloneNode;
303/**
304 * @function
305 * @param {!Node} node
306 * @return {!Node}
307 */
308DomApiNative.prototype.appendChild;
309/**
310 * @function
311 * @param {!Node} newChild
312 * @param {Node} refChild
313 * @return {!Node}
314 */
315DomApiNative.prototype.insertBefore;
316/**
317 * @function
318 * @param {!Node} node
319 * @return {!Node}
320 */
321DomApiNative.prototype.removeChild;
322/**
323 * @function
324 * @param {!Node} oldChild
325 * @param {!Node} newChild
326 * @return {!Node}
327 */
328DomApiNative.prototype.replaceChild;
329/**
330 * @function
331 * @param {string} name
332 * @param {string} value
333 * @return {void}
334 */
335DomApiNative.prototype.setAttribute;
336/**
337 * @function
338 * @param {string} name
339 * @return {void}
340 */
341DomApiNative.prototype.removeAttribute;
342/**
343 * @function
344 * @param {string} selector
345 * @return {?Element}
346 */
347DomApiNative.prototype.querySelector;
348/**
349 * @function
350 * @param {string} selector
351 * @return {!NodeList<!Element>}
352 */
353DomApiNative.prototype.querySelectorAll;
354
355/** @type {?Node} */
356DomApiNative.prototype.parentNode;
357/** @type {?Node} */
358DomApiNative.prototype.firstChild;
359/** @type {?Node} */
360DomApiNative.prototype.lastChild;
361/** @type {?Node} */
362DomApiNative.prototype.nextSibling;
363/** @type {?Node} */
364DomApiNative.prototype.previousSibling;
365/** @type {?HTMLElement} */
366DomApiNative.prototype.firstElementChild;
367/** @type {?HTMLElement} */
368DomApiNative.prototype.lastElementChild;
369/** @type {?HTMLElement} */
370DomApiNative.prototype.nextElementSibling;
371/** @type {?HTMLElement} */
372DomApiNative.prototype.previousElementSibling;
373/** @type {!Array<!Node>} */
374DomApiNative.prototype.childNodes;
375/** @type {!Array<!HTMLElement>} */
376DomApiNative.prototype.children;
377/** @type {?DOMTokenList} */
378DomApiNative.prototype.classList;
379
380/** @type {string} */
381DomApiNative.prototype.textContent;
382/** @type {string} */
383DomApiNative.prototype.innerHTML;
384
385let DomApiImpl = DomApiNative;
386
387if (window['ShadyDOM'] && window['ShadyDOM']['inUse'] && window['ShadyDOM']['noPatch'] && window['ShadyDOM']['Wrapper']) {
388
389  /**
390   * @private
391   * @extends {HTMLElement}
392   */
393  class Wrapper extends window['ShadyDOM']['Wrapper'] {}
394
395  // copy bespoke API onto wrapper
396  Object.getOwnPropertyNames(DomApiNative.prototype).forEach((prop) => {
397    if (prop != 'activeElement') {
398      Wrapper.prototype[prop] = DomApiNative.prototype[prop];
399    }
400  });
401
402  // Note, `classList` is here only for legacy compatibility since it does not
403  // trigger distribution in v1 Shadow DOM.
404  forwardReadOnlyProperties(Wrapper.prototype, [
405    'classList'
406  ]);
407
408  DomApiImpl = Wrapper;
409
410  Object.defineProperties(EventApi.prototype, {
411
412    // Returns the "lowest" node in the same root as the event's currentTarget.
413    // When in `noPatch` mode, this must be calculated by walking the event's
414    // path.
415    localTarget: {
416      get() {
417        const current = this.event.currentTarget;
418        const currentRoot = current && dom(current).getOwnerRoot();
419        const p$ = this.path;
420        for (let i = 0; i < p$.length; i++) {
421          const e = p$[i];
422          if (dom(e).getOwnerRoot() === currentRoot) {
423            return e;
424          }
425        }
426      },
427      configurable: true
428    },
429
430    path: {
431      get() {
432        return window['ShadyDOM']['composedPath'](this.event);
433      },
434      configurable: true
435    }
436  });
437
438} else {
439
440  // Methods that can provoke distribution or must return the logical, not
441  // composed tree.
442  forwardMethods(DomApiNative.prototype, [
443    'cloneNode', 'appendChild', 'insertBefore', 'removeChild',
444    'replaceChild', 'setAttribute', 'removeAttribute',
445    'querySelector', 'querySelectorAll', 'attachShadow'
446  ]);
447
448  // Properties that should return the logical, not composed tree. Note, `classList`
449  // is here only for legacy compatibility since it does not trigger distribution
450  // in v1 Shadow DOM.
451  forwardReadOnlyProperties(DomApiNative.prototype, [
452    'parentNode', 'firstChild', 'lastChild',
453    'nextSibling', 'previousSibling', 'firstElementChild',
454    'lastElementChild', 'nextElementSibling', 'previousElementSibling',
455    'childNodes', 'children', 'classList', 'shadowRoot'
456  ]);
457
458  forwardProperties(DomApiNative.prototype, [
459    'textContent', 'innerHTML', 'className'
460  ]);
461}
462
463export const DomApi = DomApiImpl;
464
465/**
466 * Legacy DOM and Event manipulation API wrapper factory used to abstract
467 * differences between native Shadow DOM and "Shady DOM" when polyfilling on
468 * older browsers.
469 *
470 * Note that in Polymer 2.x use of `Polymer.dom` is no longer required and
471 * in the majority of cases simply facades directly to the standard native
472 * API.
473 *
474 * @summary Legacy DOM and Event manipulation API wrapper factory used to
475 * abstract differences between native Shadow DOM and "Shady DOM."
476 * @param {(Node|Event|DomApiNative|EventApi)=} obj Node or event to operate on
477 * @return {!DomApiNative|!EventApi} Wrapper providing either node API or event API
478 */
479export const dom = function(obj) {
480  obj = obj || document;
481  if (obj instanceof DomApiImpl) {
482    return /** @type {!DomApi} */(obj);
483  }
484  if (obj instanceof EventApi) {
485    return /** @type {!EventApi} */(obj);
486  }
487  let helper = obj['__domApi'];
488  if (!helper) {
489    if (obj instanceof Event) {
490      helper = new EventApi(obj);
491    } else {
492      helper = new DomApiImpl(/** @type {Node} */(obj));
493    }
494    obj['__domApi'] = helper;
495  }
496  return helper;
497};

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.