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.6.1
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 ] : 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
+ var registrationsTable = new WeakMap ( ) ;
49
+ var setImmediate ;
50
+ if ( / T r i d e n t | E d g e / . test ( navigator . userAgent ) ) {
51
+ setImmediate = setTimeout ;
52
+ } else if ( window . setImmediate ) {
53
+ setImmediate = window . setImmediate ;
54
+ } else {
55
+ var setImmediateQueue = [ ] ;
56
+ var sentinel = String ( Math . random ( ) ) ;
57
+ window . addEventListener ( "message" , function ( e ) {
58
+ if ( e . data === sentinel ) {
59
+ var queue = setImmediateQueue ;
60
+ setImmediateQueue = [ ] ;
61
+ queue . forEach ( function ( func ) {
62
+ func ( ) ;
63
+ } ) ;
64
+ }
65
+ } ) ;
66
+ setImmediate = function ( func ) {
67
+ setImmediateQueue . push ( func ) ;
68
+ window . postMessage ( sentinel , "*" ) ;
69
+ } ;
70
+ }
71
+ var isScheduled = false ;
72
+ var scheduledObservers = [ ] ;
73
+ function scheduleCallback ( observer ) {
74
+ scheduledObservers . push ( observer ) ;
75
+ if ( ! isScheduled ) {
76
+ isScheduled = true ;
77
+ setImmediate ( dispatchCallbacks ) ;
78
+ }
79
+ }
80
+ function wrapIfNeeded ( node ) {
81
+ return window . ShadowDOMPolyfill && window . ShadowDOMPolyfill . wrapIfNeeded ( node ) || node ;
82
+ }
83
+ function dispatchCallbacks ( ) {
84
+ isScheduled = false ;
85
+ var observers = scheduledObservers ;
86
+ scheduledObservers = [ ] ;
87
+ observers . sort ( function ( o1 , o2 ) {
88
+ return o1 . uid_ - o2 . uid_ ;
89
+ } ) ;
90
+ var anyNonEmpty = false ;
91
+ observers . forEach ( function ( observer ) {
92
+ var queue = observer . takeRecords ( ) ;
93
+ removeTransientObserversFor ( observer ) ;
94
+ if ( queue . length ) {
95
+ observer . callback_ ( queue , observer ) ;
96
+ anyNonEmpty = true ;
97
+ }
98
+ } ) ;
99
+ if ( anyNonEmpty ) dispatchCallbacks ( ) ;
100
+ }
101
+ function removeTransientObserversFor ( observer ) {
102
+ observer . nodes_ . forEach ( function ( node ) {
103
+ var registrations = registrationsTable . get ( node ) ;
104
+ if ( ! registrations ) return ;
105
+ registrations . forEach ( function ( registration ) {
106
+ if ( registration . observer === observer ) registration . removeTransientObservers ( ) ;
107
+ } ) ;
108
+ } ) ;
109
+ }
110
+ function forEachAncestorAndObserverEnqueueRecord ( target , callback ) {
111
+ for ( var node = target ; node ; node = node . parentNode ) {
112
+ var registrations = registrationsTable . get ( node ) ;
113
+ if ( registrations ) {
114
+ for ( var j = 0 ; j < registrations . length ; j ++ ) {
115
+ var registration = registrations [ j ] ;
116
+ var options = registration . options ;
117
+ if ( node !== target && ! options . subtree ) continue ;
118
+ var record = callback ( options ) ;
119
+ if ( record ) registration . enqueue ( record ) ;
120
+ }
121
+ }
122
+ }
123
+ }
124
+ var uidCounter = 0 ;
125
+ function JsMutationObserver ( callback ) {
126
+ this . callback_ = callback ;
127
+ this . nodes_ = [ ] ;
128
+ this . records_ = [ ] ;
129
+ this . uid_ = ++ uidCounter ;
130
+ }
131
+ JsMutationObserver . prototype = {
132
+ observe : function ( target , options ) {
133
+ target = wrapIfNeeded ( target ) ;
134
+ if ( ! options . childList && ! options . attributes && ! options . characterData || options . attributeOldValue && ! options . attributes || options . attributeFilter && options . attributeFilter . length && ! options . attributes || options . characterDataOldValue && ! options . characterData ) {
135
+ throw new SyntaxError ( ) ;
136
+ }
137
+ var registrations = registrationsTable . get ( target ) ;
138
+ if ( ! registrations ) registrationsTable . set ( target , registrations = [ ] ) ;
139
+ var registration ;
140
+ for ( var i = 0 ; i < registrations . length ; i ++ ) {
141
+ if ( registrations [ i ] . observer === this ) {
142
+ registration = registrations [ i ] ;
143
+ registration . removeListeners ( ) ;
144
+ registration . options = options ;
145
+ break ;
146
+ }
147
+ }
148
+ if ( ! registration ) {
149
+ registration = new Registration ( this , target , options ) ;
150
+ registrations . push ( registration ) ;
151
+ this . nodes_ . push ( target ) ;
152
+ }
153
+ registration . addListeners ( ) ;
154
+ } ,
155
+ disconnect : function ( ) {
156
+ this . nodes_ . forEach ( function ( node ) {
157
+ var registrations = registrationsTable . get ( node ) ;
158
+ for ( var i = 0 ; i < registrations . length ; i ++ ) {
159
+ var registration = registrations [ i ] ;
160
+ if ( registration . observer === this ) {
161
+ registration . removeListeners ( ) ;
162
+ registrations . splice ( i , 1 ) ;
163
+ break ;
164
+ }
165
+ }
166
+ } , this ) ;
167
+ this . records_ = [ ] ;
168
+ } ,
169
+ takeRecords : function ( ) {
170
+ var copyOfRecords = this . records_ ;
171
+ this . records_ = [ ] ;
172
+ return copyOfRecords ;
173
+ }
174
+ } ;
175
+ function MutationRecord ( type , target ) {
176
+ this . type = type ;
177
+ this . target = target ;
178
+ this . addedNodes = [ ] ;
179
+ this . removedNodes = [ ] ;
180
+ this . previousSibling = null ;
181
+ this . nextSibling = null ;
182
+ this . attributeName = null ;
183
+ this . attributeNamespace = null ;
184
+ this . oldValue = null ;
185
+ }
186
+ function copyMutationRecord ( original ) {
187
+ var record = new MutationRecord ( original . type , original . target ) ;
188
+ record . addedNodes = original . addedNodes . slice ( ) ;
189
+ record . removedNodes = original . removedNodes . slice ( ) ;
190
+ record . previousSibling = original . previousSibling ;
191
+ record . nextSibling = original . nextSibling ;
192
+ record . attributeName = original . attributeName ;
193
+ record . attributeNamespace = original . attributeNamespace ;
194
+ record . oldValue = original . oldValue ;
195
+ return record ;
196
+ }
197
+ var currentRecord , recordWithOldValue ;
198
+ function getRecord ( type , target ) {
199
+ return currentRecord = new MutationRecord ( type , target ) ;
200
+ }
201
+ function getRecordWithOldValue ( oldValue ) {
202
+ if ( recordWithOldValue ) return recordWithOldValue ;
203
+ recordWithOldValue = copyMutationRecord ( currentRecord ) ;
204
+ recordWithOldValue . oldValue = oldValue ;
205
+ return recordWithOldValue ;
206
+ }
207
+ function clearRecords ( ) {
208
+ currentRecord = recordWithOldValue = undefined ;
209
+ }
210
+ function recordRepresentsCurrentMutation ( record ) {
211
+ return record === recordWithOldValue || record === currentRecord ;
212
+ }
213
+ function selectRecord ( lastRecord , newRecord ) {
214
+ if ( lastRecord === newRecord ) return lastRecord ;
215
+ if ( recordWithOldValue && recordRepresentsCurrentMutation ( lastRecord ) ) return recordWithOldValue ;
216
+ return null ;
217
+ }
218
+ function Registration ( observer , target , options ) {
219
+ this . observer = observer ;
220
+ this . target = target ;
221
+ this . options = options ;
222
+ this . transientObservedNodes = [ ] ;
223
+ }
224
+ Registration . prototype = {
225
+ enqueue : function ( record ) {
226
+ var records = this . observer . records_ ;
227
+ var length = records . length ;
228
+ if ( records . length > 0 ) {
229
+ var lastRecord = records [ length - 1 ] ;
230
+ var recordToReplaceLast = selectRecord ( lastRecord , record ) ;
231
+ if ( recordToReplaceLast ) {
232
+ records [ length - 1 ] = recordToReplaceLast ;
233
+ return ;
234
+ }
235
+ } else {
236
+ scheduleCallback ( this . observer ) ;
237
+ }
238
+ records [ length ] = record ;
239
+ } ,
240
+ addListeners : function ( ) {
241
+ this . addListeners_ ( this . target ) ;
242
+ } ,
243
+ addListeners_ : function ( node ) {
244
+ var options = this . options ;
245
+ if ( options . attributes ) node . addEventListener ( "DOMAttrModified" , this , true ) ;
246
+ if ( options . characterData ) node . addEventListener ( "DOMCharacterDataModified" , this , true ) ;
247
+ if ( options . childList ) node . addEventListener ( "DOMNodeInserted" , this , true ) ;
248
+ if ( options . childList || options . subtree ) node . addEventListener ( "DOMNodeRemoved" , this , true ) ;
249
+ } ,
250
+ removeListeners : function ( ) {
251
+ this . removeListeners_ ( this . target ) ;
252
+ } ,
253
+ removeListeners_ : function ( node ) {
254
+ var options = this . options ;
255
+ if ( options . attributes ) node . removeEventListener ( "DOMAttrModified" , this , true ) ;
256
+ if ( options . characterData ) node . removeEventListener ( "DOMCharacterDataModified" , this , true ) ;
257
+ if ( options . childList ) node . removeEventListener ( "DOMNodeInserted" , this , true ) ;
258
+ if ( options . childList || options . subtree ) node . removeEventListener ( "DOMNodeRemoved" , this , true ) ;
259
+ } ,
260
+ addTransientObserver : function ( node ) {
261
+ if ( node === this . target ) return ;
262
+ this . addListeners_ ( node ) ;
263
+ this . transientObservedNodes . push ( node ) ;
264
+ var registrations = registrationsTable . get ( node ) ;
265
+ if ( ! registrations ) registrationsTable . set ( node , registrations = [ ] ) ;
266
+ registrations . push ( this ) ;
267
+ } ,
268
+ removeTransientObservers : function ( ) {
269
+ var transientObservedNodes = this . transientObservedNodes ;
270
+ this . transientObservedNodes = [ ] ;
271
+ transientObservedNodes . forEach ( function ( node ) {
272
+ this . removeListeners_ ( node ) ;
273
+ var registrations = registrationsTable . get ( node ) ;
274
+ for ( var i = 0 ; i < registrations . length ; i ++ ) {
275
+ if ( registrations [ i ] === this ) {
276
+ registrations . splice ( i , 1 ) ;
277
+ break ;
278
+ }
279
+ }
280
+ } , this ) ;
281
+ } ,
282
+ handleEvent : function ( e ) {
283
+ e . stopImmediatePropagation ( ) ;
284
+ switch ( e . type ) {
285
+ case "DOMAttrModified" :
286
+ var name = e . attrName ;
287
+ var namespace = e . relatedNode . namespaceURI ;
288
+ var target = e . target ;
289
+ var record = new getRecord ( "attributes" , target ) ;
290
+ record . attributeName = name ;
291
+ record . attributeNamespace = namespace ;
292
+ var oldValue = e . attrChange === MutationEvent . ADDITION ? null : e . prevValue ;
293
+ forEachAncestorAndObserverEnqueueRecord ( target , function ( options ) {
294
+ if ( ! options . attributes ) return ;
295
+ if ( options . attributeFilter && options . attributeFilter . length && options . attributeFilter . indexOf ( name ) === - 1 && options . attributeFilter . indexOf ( namespace ) === - 1 ) {
296
+ return ;
297
+ }
298
+ if ( options . attributeOldValue ) return getRecordWithOldValue ( oldValue ) ;
299
+ return record ;
300
+ } ) ;
301
+ break ;
302
+
303
+ case "DOMCharacterDataModified" :
304
+ var target = e . target ;
305
+ var record = getRecord ( "characterData" , target ) ;
306
+ var oldValue = e . prevValue ;
307
+ forEachAncestorAndObserverEnqueueRecord ( target , function ( options ) {
308
+ if ( ! options . characterData ) return ;
309
+ if ( options . characterDataOldValue ) return getRecordWithOldValue ( oldValue ) ;
310
+ return record ;
311
+ } ) ;
312
+ break ;
313
+
314
+ case "DOMNodeRemoved" :
315
+ this . addTransientObserver ( e . target ) ;
316
+
317
+ case "DOMNodeInserted" :
318
+ var changedNode = e . target ;
319
+ var addedNodes , removedNodes ;
320
+ if ( e . type === "DOMNodeInserted" ) {
321
+ addedNodes = [ changedNode ] ;
322
+ removedNodes = [ ] ;
323
+ } else {
324
+ addedNodes = [ ] ;
325
+ removedNodes = [ changedNode ] ;
326
+ }
327
+ var previousSibling = changedNode . previousSibling ;
328
+ var nextSibling = changedNode . nextSibling ;
329
+ var record = getRecord ( "childList" , e . target . parentNode ) ;
330
+ record . addedNodes = addedNodes ;
331
+ record . removedNodes = removedNodes ;
332
+ record . previousSibling = previousSibling ;
333
+ record . nextSibling = nextSibling ;
334
+ forEachAncestorAndObserverEnqueueRecord ( e . relatedNode , function ( options ) {
335
+ if ( ! options . childList ) return ;
336
+ return record ;
337
+ } ) ;
338
+ }
339
+ clearRecords ( ) ;
340
+ }
341
+ } ;
342
+ global . JsMutationObserver = JsMutationObserver ;
343
+ if ( ! global . MutationObserver ) global . MutationObserver = JsMutationObserver ;
344
+ } ) ( this ) ;
0 commit comments