• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @license
3 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7 * Code distributed by Google as part of the polymer project is also
8 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9 */
10// @version 0.7.24
11if (typeof WeakMap === "undefined") {
12  (function() {
13    var defineProperty = Object.defineProperty;
14    var counter = Date.now() % 1e9;
15    var WeakMap = function() {
16      this.name = "__st" + (Math.random() * 1e9 >>> 0) + (counter++ + "__");
17    };
18    WeakMap.prototype = {
19      set: function(key, value) {
20        var entry = key[this.name];
21        if (entry && entry[0] === key) entry[1] = value; else defineProperty(key, this.name, {
22          value: [ key, value ],
23          writable: true
24        });
25        return this;
26      },
27      get: function(key) {
28        var entry;
29        return (entry = key[this.name]) && entry[0] === key ? entry[1] : undefined;
30      },
31      "delete": function(key) {
32        var entry = key[this.name];
33        if (!entry || entry[0] !== key) return false;
34        entry[0] = entry[1] = undefined;
35        return true;
36      },
37      has: function(key) {
38        var entry = key[this.name];
39        if (!entry) return false;
40        return entry[0] === key;
41      }
42    };
43    window.WeakMap = WeakMap;
44  })();
45}
46
47(function(global) {
48  if (global.JsMutationObserver) {
49    return;
50  }
51  var registrationsTable = new WeakMap();
52  var setImmediate;
53  if (/Trident|Edge/.test(navigator.userAgent)) {
54    setImmediate = setTimeout;
55  } else if (window.setImmediate) {
56    setImmediate = window.setImmediate;
57  } else {
58    var setImmediateQueue = [];
59    var sentinel = String(Math.random());
60    window.addEventListener("message", function(e) {
61      if (e.data === sentinel) {
62        var queue = setImmediateQueue;
63        setImmediateQueue = [];
64        queue.forEach(function(func) {
65          func();
66        });
67      }
68    });
69    setImmediate = function(func) {
70      setImmediateQueue.push(func);
71      window.postMessage(sentinel, "*");
72    };
73  }
74  var isScheduled = false;
75  var scheduledObservers = [];
76  function scheduleCallback(observer) {
77    scheduledObservers.push(observer);
78    if (!isScheduled) {
79      isScheduled = true;
80      setImmediate(dispatchCallbacks);
81    }
82  }
83  function wrapIfNeeded(node) {
84    return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node;
85  }
86  function dispatchCallbacks() {
87    isScheduled = false;
88    var observers = scheduledObservers;
89    scheduledObservers = [];
90    observers.sort(function(o1, o2) {
91      return o1.uid_ - o2.uid_;
92    });
93    var anyNonEmpty = false;
94    observers.forEach(function(observer) {
95      var queue = observer.takeRecords();
96      removeTransientObserversFor(observer);
97      if (queue.length) {
98        observer.callback_(queue, observer);
99        anyNonEmpty = true;
100      }
101    });
102    if (anyNonEmpty) dispatchCallbacks();
103  }
104  function removeTransientObserversFor(observer) {
105    observer.nodes_.forEach(function(node) {
106      var registrations = registrationsTable.get(node);
107      if (!registrations) return;
108      registrations.forEach(function(registration) {
109        if (registration.observer === observer) registration.removeTransientObservers();
110      });
111    });
112  }
113  function forEachAncestorAndObserverEnqueueRecord(target, callback) {
114    for (var node = target; node; node = node.parentNode) {
115      var registrations = registrationsTable.get(node);
116      if (registrations) {
117        for (var j = 0; j < registrations.length; j++) {
118          var registration = registrations[j];
119          var options = registration.options;
120          if (node !== target && !options.subtree) continue;
121          var record = callback(options);
122          if (record) registration.enqueue(record);
123        }
124      }
125    }
126  }
127  var uidCounter = 0;
128  function JsMutationObserver(callback) {
129    this.callback_ = callback;
130    this.nodes_ = [];
131    this.records_ = [];
132    this.uid_ = ++uidCounter;
133  }
134  JsMutationObserver.prototype = {
135    observe: function(target, options) {
136      target = wrapIfNeeded(target);
137      if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) {
138        throw new SyntaxError();
139      }
140      var registrations = registrationsTable.get(target);
141      if (!registrations) registrationsTable.set(target, registrations = []);
142      var registration;
143      for (var i = 0; i < registrations.length; i++) {
144        if (registrations[i].observer === this) {
145          registration = registrations[i];
146          registration.removeListeners();
147          registration.options = options;
148          break;
149        }
150      }
151      if (!registration) {
152        registration = new Registration(this, target, options);
153        registrations.push(registration);
154        this.nodes_.push(target);
155      }
156      registration.addListeners();
157    },
158    disconnect: function() {
159      this.nodes_.forEach(function(node) {
160        var registrations = registrationsTable.get(node);
161        for (var i = 0; i < registrations.length; i++) {
162          var registration = registrations[i];
163          if (registration.observer === this) {
164            registration.removeListeners();
165            registrations.splice(i, 1);
166            break;
167          }
168        }
169      }, this);
170      this.records_ = [];
171    },
172    takeRecords: function() {
173      var copyOfRecords = this.records_;
174      this.records_ = [];
175      return copyOfRecords;
176    }
177  };
178  function MutationRecord(type, target) {
179    this.type = type;
180    this.target = target;
181    this.addedNodes = [];
182    this.removedNodes = [];
183    this.previousSibling = null;
184    this.nextSibling = null;
185    this.attributeName = null;
186    this.attributeNamespace = null;
187    this.oldValue = null;
188  }
189  function copyMutationRecord(original) {
190    var record = new MutationRecord(original.type, original.target);
191    record.addedNodes = original.addedNodes.slice();
192    record.removedNodes = original.removedNodes.slice();
193    record.previousSibling = original.previousSibling;
194    record.nextSibling = original.nextSibling;
195    record.attributeName = original.attributeName;
196    record.attributeNamespace = original.attributeNamespace;
197    record.oldValue = original.oldValue;
198    return record;
199  }
200  var currentRecord, recordWithOldValue;
201  function getRecord(type, target) {
202    return currentRecord = new MutationRecord(type, target);
203  }
204  function getRecordWithOldValue(oldValue) {
205    if (recordWithOldValue) return recordWithOldValue;
206    recordWithOldValue = copyMutationRecord(currentRecord);
207    recordWithOldValue.oldValue = oldValue;
208    return recordWithOldValue;
209  }
210  function clearRecords() {
211    currentRecord = recordWithOldValue = undefined;
212  }
213  function recordRepresentsCurrentMutation(record) {
214    return record === recordWithOldValue || record === currentRecord;
215  }
216  function selectRecord(lastRecord, newRecord) {
217    if (lastRecord === newRecord) return lastRecord;
218    if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
219    return null;
220  }
221  function Registration(observer, target, options) {
222    this.observer = observer;
223    this.target = target;
224    this.options = options;
225    this.transientObservedNodes = [];
226  }
227  Registration.prototype = {
228    enqueue: function(record) {
229      var records = this.observer.records_;
230      var length = records.length;
231      if (records.length > 0) {
232        var lastRecord = records[length - 1];
233        var recordToReplaceLast = selectRecord(lastRecord, record);
234        if (recordToReplaceLast) {
235          records[length - 1] = recordToReplaceLast;
236          return;
237        }
238      } else {
239        scheduleCallback(this.observer);
240      }
241      records[length] = record;
242    },
243    addListeners: function() {
244      this.addListeners_(this.target);
245    },
246    addListeners_: function(node) {
247      var options = this.options;
248      if (options.attributes) node.addEventListener("DOMAttrModified", this, true);
249      if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true);
250      if (options.childList) node.addEventListener("DOMNodeInserted", this, true);
251      if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true);
252    },
253    removeListeners: function() {
254      this.removeListeners_(this.target);
255    },
256    removeListeners_: function(node) {
257      var options = this.options;
258      if (options.attributes) node.removeEventListener("DOMAttrModified", this, true);
259      if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true);
260      if (options.childList) node.removeEventListener("DOMNodeInserted", this, true);
261      if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true);
262    },
263    addTransientObserver: function(node) {
264      if (node === this.target) return;
265      this.addListeners_(node);
266      this.transientObservedNodes.push(node);
267      var registrations = registrationsTable.get(node);
268      if (!registrations) registrationsTable.set(node, registrations = []);
269      registrations.push(this);
270    },
271    removeTransientObservers: function() {
272      var transientObservedNodes = this.transientObservedNodes;
273      this.transientObservedNodes = [];
274      transientObservedNodes.forEach(function(node) {
275        this.removeListeners_(node);
276        var registrations = registrationsTable.get(node);
277        for (var i = 0; i < registrations.length; i++) {
278          if (registrations[i] === this) {
279            registrations.splice(i, 1);
280            break;
281          }
282        }
283      }, this);
284    },
285    handleEvent: function(e) {
286      e.stopImmediatePropagation();
287      switch (e.type) {
288       case "DOMAttrModified":
289        var name = e.attrName;
290        var namespace = e.relatedNode.namespaceURI;
291        var target = e.target;
292        var record = new getRecord("attributes", target);
293        record.attributeName = name;
294        record.attributeNamespace = namespace;
295        var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
296        forEachAncestorAndObserverEnqueueRecord(target, function(options) {
297          if (!options.attributes) return;
298          if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
299            return;
300          }
301          if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
302          return record;
303        });
304        break;
305
306       case "DOMCharacterDataModified":
307        var target = e.target;
308        var record = getRecord("characterData", target);
309        var oldValue = e.prevValue;
310        forEachAncestorAndObserverEnqueueRecord(target, function(options) {
311          if (!options.characterData) return;
312          if (options.characterDataOldValue) return getRecordWithOldValue(oldValue);
313          return record;
314        });
315        break;
316
317       case "DOMNodeRemoved":
318        this.addTransientObserver(e.target);
319
320       case "DOMNodeInserted":
321        var changedNode = e.target;
322        var addedNodes, removedNodes;
323        if (e.type === "DOMNodeInserted") {
324          addedNodes = [ changedNode ];
325          removedNodes = [];
326        } else {
327          addedNodes = [];
328          removedNodes = [ changedNode ];
329        }
330        var previousSibling = changedNode.previousSibling;
331        var nextSibling = changedNode.nextSibling;
332        var record = getRecord("childList", e.target.parentNode);
333        record.addedNodes = addedNodes;
334        record.removedNodes = removedNodes;
335        record.previousSibling = previousSibling;
336        record.nextSibling = nextSibling;
337        forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function(options) {
338          if (!options.childList) return;
339          return record;
340        });
341      }
342      clearRecords();
343    }
344  };
345  global.JsMutationObserver = JsMutationObserver;
346  if (!global.MutationObserver) {
347    global.MutationObserver = JsMutationObserver;
348    JsMutationObserver._isPolyfilled = true;
349  }
350})(self);