OLD | NEW |
(Empty) | |
| 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://polyme
r.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/CON
TRIBUTORS.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/PA
TENTS.txt |
| 9 */ |
| 10 // @version 0.7.21 |
| 11 if (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] : undefin
ed; |
| 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(nod
e) || 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.removeTransientObse
rvers(); |
| 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.characterDataOl
dValue && !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)) retur
n 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, tru
e); |
| 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("DOMNodeRe
moved", 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("DOMCharacterDataModif
ied", this, true); |
| 260 if (options.childList) node.removeEventListener("DOMNodeInserted", this, t
rue); |
| 261 if (options.childList || options.subtree) node.removeEventListener("DOMNod
eRemoved", 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.prevVa
lue; |
| 296 forEachAncestorAndObserverEnqueueRecord(target, function(options) { |
| 297 if (!options.attributes) return; |
| 298 if (options.attributeFilter && options.attributeFilter.length && optio
ns.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(names
pace) === -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(oldVal
ue); |
| 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); |
OLD | NEW |