polymer-rails 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,13 +21,13 @@ Polymer.Annotations = {
21
21
  parseAnnotations: function (template) {
22
22
  var list = [];
23
23
  var content = template._content || template.content;
24
- this._parseNodeAnnotations(content, list);
24
+ this._parseNodeAnnotations(content, list, template.hasAttribute('strip-whitespace'));
25
25
  return list;
26
26
  },
27
- _parseNodeAnnotations: function (node, list) {
28
- return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list);
27
+ _parseNodeAnnotations: function (node, list, stripWhiteSpace) {
28
+ return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list, stripWhiteSpace);
29
29
  },
30
- _bindingRegex: /([^{[]*)({{|\[\[)([^}\]]*)(?:]]|}})/g,
30
+ _bindingRegex: /([^{[]*)(\{\{|\[\[)(?!\}\}|\]\])(.+?)(?:\]\]|\}\})/g,
31
31
  _parseBindings: function (text) {
32
32
  var re = this._bindingRegex;
33
33
  var parts = [];
@@ -93,7 +93,7 @@ list.push(annote);
93
93
  return annote;
94
94
  }
95
95
  },
96
- _parseElementAnnotations: function (element, list) {
96
+ _parseElementAnnotations: function (element, list, stripWhiteSpace) {
97
97
  var annote = {
98
98
  bindings: [],
99
99
  events: []
@@ -101,7 +101,7 @@ events: []
101
101
  if (element.localName === 'content') {
102
102
  list._hasContent = true;
103
103
  }
104
- this._parseChildNodesAnnotations(element, annote, list);
104
+ this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace);
105
105
  if (element.attributes) {
106
106
  this._parseNodeAttributeAnnotations(element, annote, list);
107
107
  if (this.prepElement) {
@@ -113,26 +113,38 @@ list.push(annote);
113
113
  }
114
114
  return annote;
115
115
  },
116
- _parseChildNodesAnnotations: function (root, annote, list, callback) {
116
+ _parseChildNodesAnnotations: function (root, annote, list, stripWhiteSpace) {
117
117
  if (root.firstChild) {
118
- for (var i = 0, node = root.firstChild; node; node = node.nextSibling, i++) {
118
+ var node = root.firstChild;
119
+ var i = 0;
120
+ while (node) {
121
+ var next = node.nextSibling;
119
122
  if (node.localName === 'template' && !node.hasAttribute('preserve-content')) {
120
123
  this._parseTemplate(node, i, list, annote);
121
124
  }
122
125
  if (node.nodeType === Node.TEXT_NODE) {
123
- var n = node.nextSibling;
126
+ var n = next;
124
127
  while (n && n.nodeType === Node.TEXT_NODE) {
125
128
  node.textContent += n.textContent;
129
+ next = n.nextSibling;
126
130
  root.removeChild(n);
127
- n = n.nextSibling;
131
+ n = next;
128
132
  }
133
+ if (stripWhiteSpace && !node.textContent.trim()) {
134
+ root.removeChild(node);
135
+ i--;
129
136
  }
130
- var childAnnotation = this._parseNodeAnnotations(node, list, callback);
137
+ }
138
+ if (node.parentNode) {
139
+ var childAnnotation = this._parseNodeAnnotations(node, list, stripWhiteSpace);
131
140
  if (childAnnotation) {
132
141
  childAnnotation.parent = annote;
133
142
  childAnnotation.index = i;
134
143
  }
135
144
  }
145
+ node = next;
146
+ i++;
147
+ }
136
148
  }
137
149
  },
138
150
  _parseTemplate: function (node, index, list, parent) {
@@ -267,7 +279,10 @@ _prepAnnotations: function () {
267
279
  if (!this._template) {
268
280
  this._notes = [];
269
281
  } else {
270
- Polymer.Annotations.prepElement = this._prepElement.bind(this);
282
+ var self = this;
283
+ Polymer.Annotations.prepElement = function (element) {
284
+ self._prepElement(element);
285
+ };
271
286
  if (this._template._content && this._template._content._notes) {
272
287
  this._notes = this._template._content._notes;
273
288
  } else {
@@ -314,24 +329,24 @@ note.bindings = note.bindings.concat(bindings);
314
329
  },
315
330
  _discoverTemplateParentProps: function (notes) {
316
331
  var pp = {};
317
- notes.forEach(function (n) {
318
- n.bindings.forEach(function (b) {
319
- b.parts.forEach(function (p) {
332
+ for (var i = 0, n; i < notes.length && (n = notes[i]); i++) {
333
+ for (var j = 0, b$ = n.bindings, b; j < b$.length && (b = b$[j]); j++) {
334
+ for (var k = 0, p$ = b.parts, p; k < p$.length && (p = p$[k]); k++) {
320
335
  if (p.signature) {
321
336
  var args = p.signature.args;
322
- for (var k = 0; k < args.length; k++) {
323
- pp[args[k].model] = true;
337
+ for (var kk = 0; kk < args.length; kk++) {
338
+ pp[args[kk].model] = true;
324
339
  }
325
340
  } else {
326
341
  pp[p.model] = true;
327
342
  }
328
- });
329
- });
343
+ }
344
+ }
330
345
  if (n.templateContent) {
331
346
  var tpp = n.templateContent._parentProps;
332
347
  Polymer.Base.mixin(pp, tpp);
333
348
  }
334
- });
349
+ }
335
350
  return pp;
336
351
  },
337
352
  _prepElement: function (element) {
@@ -385,44 +400,46 @@ node[name] = binding.literal;
385
400
  },
386
401
  _marshalIdNodes: function () {
387
402
  this.$ = {};
388
- this._notes.forEach(function (a) {
403
+ for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) {
389
404
  if (a.id) {
390
405
  this.$[a.id] = this._findAnnotatedNode(this.root, a);
391
406
  }
392
- }, this);
407
+ }
393
408
  },
394
409
  _marshalAnnotatedNodes: function () {
395
- if (this._nodes) {
396
- this._nodes = this._nodes.map(function (a) {
397
- return this._findAnnotatedNode(this.root, a);
398
- }, this);
410
+ if (this._notes && this._notes.length) {
411
+ var r = new Array(this._notes.length);
412
+ for (var i = 0; i < this._notes.length; i++) {
413
+ r[i] = this._findAnnotatedNode(this.root, this._notes[i]);
414
+ }
415
+ this._nodes = r;
399
416
  }
400
417
  },
401
418
  _marshalAnnotatedListeners: function () {
402
- this._notes.forEach(function (a) {
419
+ for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) {
403
420
  if (a.events && a.events.length) {
404
421
  var node = this._findAnnotatedNode(this.root, a);
405
- a.events.forEach(function (e) {
422
+ for (var j = 0, e$ = a.events, e; j < e$.length && (e = e$[j]); j++) {
406
423
  this.listen(node, e.name, e.value);
407
- }, this);
408
424
  }
409
- }, this);
425
+ }
426
+ }
410
427
  }
411
428
  });
412
429
  Polymer.Base._addFeature({
413
430
  listeners: {},
414
431
  _listenListeners: function (listeners) {
415
- var node, name, key;
416
- for (key in listeners) {
417
- if (key.indexOf('.') < 0) {
432
+ var node, name, eventName;
433
+ for (eventName in listeners) {
434
+ if (eventName.indexOf('.') < 0) {
418
435
  node = this;
419
- name = key;
436
+ name = eventName;
420
437
  } else {
421
- name = key.split('.');
438
+ name = eventName.split('.');
422
439
  node = this.$[name[0]];
423
440
  name = name[1];
424
441
  }
425
- this.listen(node, name, listeners[key]);
442
+ this.listen(node, name, listeners[eventName]);
426
443
  }
427
444
  },
428
445
  listen: function (node, eventName, methodName) {
@@ -493,6 +510,7 @@ node.removeEventListener(eventName, handler);
493
510
  });
494
511
  (function () {
495
512
  'use strict';
513
+ var wrap = Polymer.DomApi.wrap;
496
514
  var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string';
497
515
  var GESTURE_KEY = '__polymerGestures';
498
516
  var HANDLED_OBJ = '__polymerGesturesHandled';
@@ -643,8 +661,11 @@ return ev.target;
643
661
  handleNative: function (ev) {
644
662
  var handled;
645
663
  var type = ev.type;
646
- var node = ev.currentTarget;
664
+ var node = wrap(ev.currentTarget);
647
665
  var gobj = node[GESTURE_KEY];
666
+ if (!gobj) {
667
+ return;
668
+ }
648
669
  var gs = gobj[type];
649
670
  if (!gs) {
650
671
  return;
@@ -727,6 +748,7 @@ Gestures.prevent('track');
727
748
  }
728
749
  },
729
750
  add: function (node, evType, handler) {
751
+ node = wrap(node);
730
752
  var recognizer = this.gestures[evType];
731
753
  var deps = recognizer.deps;
732
754
  var name = recognizer.name;
@@ -755,6 +777,7 @@ this.setTouchAction(node, recognizer.touchAction);
755
777
  }
756
778
  },
757
779
  remove: function (node, evType, handler) {
780
+ node = wrap(node);
758
781
  var recognizer = this.gestures[evType];
759
782
  var deps = recognizer.deps;
760
783
  var name = recognizer.name;
@@ -881,7 +904,9 @@ Gestures.fire(target, type, {
881
904
  x: event.clientX,
882
905
  y: event.clientY,
883
906
  sourceEvent: event,
884
- prevent: Gestures.prevent.bind(Gestures)
907
+ prevent: function (e) {
908
+ return Gestures.prevent(e);
909
+ }
885
910
  });
886
911
  }
887
912
  });
@@ -1180,7 +1205,10 @@ Polymer.Debounce = function () {
1180
1205
  var Async = Polymer.Async;
1181
1206
  var Debouncer = function (context) {
1182
1207
  this.context = context;
1183
- this.boundComplete = this.complete.bind(this);
1208
+ var self = this;
1209
+ this.boundComplete = function () {
1210
+ self.complete();
1211
+ };
1184
1212
  };
1185
1213
  Debouncer.prototype = {
1186
1214
  go: function (callback, wait) {
@@ -1281,7 +1309,7 @@ var e$ = Polymer.dom(this).queryDistributedElements(slctr);
1281
1309
  return e$ && e$[0];
1282
1310
  },
1283
1311
  queryAllEffectiveChildren: function (slctr) {
1284
- return Polymer.dom(this).queryAllDistributedElements(slctr);
1312
+ return Polymer.dom(this).queryDistributedElements(slctr);
1285
1313
  },
1286
1314
  getContentChildNodes: function (slctr) {
1287
1315
  var content = Polymer.dom(this.root).querySelector(slctr || 'content');
@@ -1295,19 +1323,37 @@ return n.nodeType === Node.ELEMENT_NODE;
1295
1323
  fire: function (type, detail, options) {
1296
1324
  options = options || Polymer.nob;
1297
1325
  var node = options.node || this;
1298
- var detail = detail === null || detail === undefined ? Polymer.nob : detail;
1326
+ var detail = detail === null || detail === undefined ? {} : detail;
1299
1327
  var bubbles = options.bubbles === undefined ? true : options.bubbles;
1300
1328
  var cancelable = Boolean(options.cancelable);
1301
- var event = new CustomEvent(type, {
1329
+ var useCache = options._useCache;
1330
+ var event = this._getEvent(type, bubbles, cancelable, useCache);
1331
+ event.detail = detail;
1332
+ if (useCache) {
1333
+ this.__eventCache[type] = null;
1334
+ }
1335
+ node.dispatchEvent(event);
1336
+ if (useCache) {
1337
+ this.__eventCache[type] = event;
1338
+ }
1339
+ return event;
1340
+ },
1341
+ __eventCache: {},
1342
+ _getEvent: function (type, bubbles, cancelable, useCache) {
1343
+ var event = useCache && this.__eventCache[type];
1344
+ if (!event || (event.bubbles != bubbles || event.cancelable != cancelable)) {
1345
+ event = new Event(type, {
1302
1346
  bubbles: Boolean(bubbles),
1303
- cancelable: cancelable,
1304
- detail: detail
1347
+ cancelable: cancelable
1305
1348
  });
1306
- node.dispatchEvent(event);
1349
+ }
1307
1350
  return event;
1308
1351
  },
1309
1352
  async: function (callback, waitTime) {
1310
- return Polymer.Async.run(callback.bind(this), waitTime);
1353
+ var self = this;
1354
+ return Polymer.Async.run(function () {
1355
+ callback.call(self);
1356
+ }, waitTime);
1311
1357
  },
1312
1358
  cancelAsync: function (handle) {
1313
1359
  Polymer.Async.cancel(handle);
@@ -1340,11 +1386,16 @@ importHref: function (href, onload, onerror) {
1340
1386
  var l = document.createElement('link');
1341
1387
  l.rel = 'import';
1342
1388
  l.href = href;
1389
+ var self = this;
1343
1390
  if (onload) {
1344
- l.onload = onload.bind(this);
1391
+ l.onload = function (e) {
1392
+ return onload.call(self, e);
1393
+ };
1345
1394
  }
1346
1395
  if (onerror) {
1347
- l.onerror = onerror.bind(this);
1396
+ l.onerror = function (e) {
1397
+ return onerror.call(self, e);
1398
+ };
1348
1399
  }
1349
1400
  document.head.appendChild(l);
1350
1401
  return l;
@@ -1366,17 +1417,18 @@ return this.root === Polymer.dom(node).getOwnerRoot();
1366
1417
  }
1367
1418
  });
1368
1419
  Polymer.Bind = {
1420
+ _dataEventCache: {},
1369
1421
  prepareModel: function (model) {
1370
- model._propertyEffects = {};
1371
- model._bindListeners = [];
1372
1422
  Polymer.Base.mixin(model, this._modelApi);
1373
1423
  },
1374
1424
  _modelApi: {
1375
- _notifyChange: function (property) {
1376
- var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed';
1377
- Polymer.Base.fire(eventName, { value: this[property] }, {
1425
+ _notifyChange: function (source, event, value) {
1426
+ value = value === undefined ? this[source] : value;
1427
+ event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed';
1428
+ this.fire(event, { value: value }, {
1378
1429
  bubbles: false,
1379
- node: this
1430
+ cancelable: false,
1431
+ _useCache: true
1380
1432
  });
1381
1433
  },
1382
1434
  _propertySetter: function (property, value, effects, fromAbove) {
@@ -1405,12 +1457,9 @@ node[property] = value;
1405
1457
  }
1406
1458
  },
1407
1459
  _effectEffects: function (property, value, effects, old, fromAbove) {
1408
- effects.forEach(function (fx) {
1409
- var fn = Polymer.Bind['_' + fx.kind + 'Effect'];
1410
- if (fn) {
1411
- fn.call(this, property, value, fx.effect, old, fromAbove);
1460
+ for (var i = 0, l = effects.length, fx; i < l && (fx = effects[i]); i++) {
1461
+ fx.fn.call(this, property, value, fx.effect, old, fromAbove);
1412
1462
  }
1413
- }, this);
1414
1463
  },
1415
1464
  _clearPath: function (path) {
1416
1465
  for (var prop in this.__data__) {
@@ -1421,6 +1470,9 @@ this.__data__[prop] = undefined;
1421
1470
  }
1422
1471
  },
1423
1472
  ensurePropertyEffects: function (model, property) {
1473
+ if (!model._propertyEffects) {
1474
+ model._propertyEffects = {};
1475
+ }
1424
1476
  var fx = model._propertyEffects[property];
1425
1477
  if (!fx) {
1426
1478
  fx = model._propertyEffects[property] = [];
@@ -1429,10 +1481,13 @@ return fx;
1429
1481
  },
1430
1482
  addPropertyEffect: function (model, property, kind, effect) {
1431
1483
  var fx = this.ensurePropertyEffects(model, property);
1432
- fx.push({
1484
+ var propEffect = {
1433
1485
  kind: kind,
1434
- effect: effect
1435
- });
1486
+ effect: effect,
1487
+ fn: Polymer.Bind['_' + kind + 'Effect']
1488
+ };
1489
+ fx.push(propEffect);
1490
+ return propEffect;
1436
1491
  },
1437
1492
  createBindings: function (model) {
1438
1493
  var fx$ = model._propertyEffects;
@@ -1482,7 +1537,10 @@ upper: function (name) {
1482
1537
  return name[0].toUpperCase() + name.substring(1);
1483
1538
  },
1484
1539
  _addAnnotatedListener: function (model, index, property, path, event) {
1485
- var fn = this._notedListenerFactory(property, path, this._isStructured(path), this._isEventBogus);
1540
+ if (!model._bindListeners) {
1541
+ model._bindListeners = [];
1542
+ }
1543
+ var fn = this._notedListenerFactory(property, path, this._isStructured(path));
1486
1544
  var eventName = event || Polymer.CaseMap.camelToDashCase(property) + '-changed';
1487
1545
  model._bindListeners.push({
1488
1546
  index: index,
@@ -1498,31 +1556,36 @@ return path.indexOf('.') > 0;
1498
1556
  _isEventBogus: function (e, target) {
1499
1557
  return e.path && e.path[0] !== target;
1500
1558
  },
1501
- _notedListenerFactory: function (property, path, isStructured, bogusTest) {
1502
- return function (e, target) {
1503
- if (!bogusTest(e, target)) {
1504
- if (e.detail && e.detail.path) {
1505
- this._notifyPath(this._fixPath(path, property, e.detail.path), e.detail.value);
1559
+ _notedListenerFactory: function (property, path, isStructured) {
1560
+ return function (target, value, targetPath) {
1561
+ if (targetPath) {
1562
+ this._notifyPath(this._fixPath(path, property, targetPath), value);
1506
1563
  } else {
1507
- var value = target[property];
1564
+ value = target[property];
1508
1565
  if (!isStructured) {
1509
- this[path] = target[property];
1566
+ this[path] = value;
1510
1567
  } else {
1511
1568
  if (this.__data__[path] != value) {
1512
1569
  this.set(path, value);
1513
1570
  }
1514
1571
  }
1515
1572
  }
1516
- }
1517
1573
  };
1518
1574
  },
1519
1575
  prepareInstance: function (inst) {
1520
1576
  inst.__data__ = Object.create(null);
1521
1577
  },
1522
1578
  setupBindListeners: function (inst) {
1523
- inst._bindListeners.forEach(function (info) {
1579
+ var b$ = inst._bindListeners;
1580
+ for (var i = 0, l = b$.length, info; i < l && (info = b$[i]); i++) {
1524
1581
  var node = inst._nodes[info.index];
1525
- node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn));
1582
+ this._addNotifyListener(node, inst, info.event, info.changedFn);
1583
+ }
1584
+ ;
1585
+ },
1586
+ _addNotifyListener: function (element, context, event, changedFn) {
1587
+ element.addEventListener(event, function (e) {
1588
+ return context._notifyListener(changedFn, e);
1526
1589
  });
1527
1590
  }
1528
1591
  };
@@ -1540,12 +1603,12 @@ if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) {
1540
1603
  return this._applyEffectValue(effect, calc);
1541
1604
  }
1542
1605
  },
1543
- _reflectEffect: function (source) {
1544
- this.reflectPropertyToAttribute(source);
1606
+ _reflectEffect: function (source, value, effect) {
1607
+ this.reflectPropertyToAttribute(source, effect.attribute, value);
1545
1608
  },
1546
1609
  _notifyEffect: function (source, value, effect, old, fromAbove) {
1547
1610
  if (!fromAbove) {
1548
- this._notifyChange(source);
1611
+ this._notifyChange(source, effect.event, value);
1549
1612
  }
1550
1613
  },
1551
1614
  _functionEffect: function (source, value, fn, old, fromAbove) {
@@ -1631,7 +1694,8 @@ return values;
1631
1694
  });
1632
1695
  Polymer.Base._addFeature({
1633
1696
  _addPropertyEffect: function (property, kind, effect) {
1634
- Polymer.Bind.addPropertyEffect(this, property, kind, effect);
1697
+ var prop = Polymer.Bind.addPropertyEffect(this, property, kind, effect);
1698
+ prop.pathFn = this['_' + prop.kind + 'PathEffect'];
1635
1699
  },
1636
1700
  _prepEffects: function () {
1637
1701
  Polymer.Bind.prepareModel(this);
@@ -1652,10 +1716,10 @@ prop.readOnly = true;
1652
1716
  this._addComputedEffect(p, prop.computed);
1653
1717
  }
1654
1718
  if (prop.notify) {
1655
- this._addPropertyEffect(p, 'notify');
1719
+ this._addPropertyEffect(p, 'notify', { event: Polymer.CaseMap.camelToDashCase(p) + '-changed' });
1656
1720
  }
1657
1721
  if (prop.reflectToAttribute) {
1658
- this._addPropertyEffect(p, 'reflect');
1722
+ this._addPropertyEffect(p, 'reflect', { attribute: Polymer.CaseMap.camelToDashCase(p) });
1659
1723
  }
1660
1724
  if (prop.readOnly) {
1661
1725
  Polymer.Bind.ensurePropertyEffects(this, p);
@@ -1665,14 +1729,14 @@ Polymer.Bind.ensurePropertyEffects(this, p);
1665
1729
  },
1666
1730
  _addComputedEffect: function (name, expression) {
1667
1731
  var sig = this._parseMethod(expression);
1668
- sig.args.forEach(function (arg) {
1732
+ for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
1669
1733
  this._addPropertyEffect(arg.model, 'compute', {
1670
1734
  method: sig.method,
1671
1735
  args: sig.args,
1672
1736
  trigger: arg,
1673
1737
  name: name
1674
1738
  });
1675
- }, this);
1739
+ }
1676
1740
  },
1677
1741
  _addObserverEffect: function (property, observer) {
1678
1742
  this._addPropertyEffect(property, 'observer', {
@@ -1682,29 +1746,28 @@ property: property
1682
1746
  },
1683
1747
  _addComplexObserverEffects: function (observers) {
1684
1748
  if (observers) {
1685
- observers.forEach(function (observer) {
1686
- this._addComplexObserverEffect(observer);
1687
- }, this);
1749
+ for (var i = 0, o; i < observers.length && (o = observers[i]); i++) {
1750
+ this._addComplexObserverEffect(o);
1751
+ }
1688
1752
  }
1689
1753
  },
1690
1754
  _addComplexObserverEffect: function (observer) {
1691
1755
  var sig = this._parseMethod(observer);
1692
- sig.args.forEach(function (arg) {
1756
+ for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
1693
1757
  this._addPropertyEffect(arg.model, 'complexObserver', {
1694
1758
  method: sig.method,
1695
1759
  args: sig.args,
1696
1760
  trigger: arg
1697
1761
  });
1698
- }, this);
1762
+ }
1699
1763
  },
1700
1764
  _addAnnotationEffects: function (notes) {
1701
- this._nodes = [];
1702
- notes.forEach(function (note) {
1703
- var index = this._nodes.push(note) - 1;
1704
- note.bindings.forEach(function (binding) {
1705
- this._addAnnotationEffect(binding, index);
1706
- }, this);
1707
- }, this);
1765
+ for (var i = 0, note; i < notes.length && (note = notes[i]); i++) {
1766
+ var b$ = note.bindings;
1767
+ for (var j = 0, binding; j < b$.length && (binding = b$[j]); j++) {
1768
+ this._addAnnotationEffect(binding, i);
1769
+ }
1770
+ }
1708
1771
  },
1709
1772
  _addAnnotationEffect: function (note, index) {
1710
1773
  if (Polymer.Bind._shouldAddListener(note)) {
@@ -1734,11 +1797,11 @@ var sig = part.signature;
1734
1797
  if (sig.static) {
1735
1798
  this.__addAnnotatedComputationEffect('__static__', index, note, part, null);
1736
1799
  } else {
1737
- sig.args.forEach(function (arg) {
1800
+ for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
1738
1801
  if (!arg.literal) {
1739
1802
  this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg);
1740
1803
  }
1741
- }, this);
1804
+ }
1742
1805
  }
1743
1806
  },
1744
1807
  __addAnnotatedComputationEffect: function (property, index, note, part, trigger) {
@@ -1817,7 +1880,9 @@ return a;
1817
1880
  },
1818
1881
  _marshalInstanceEffects: function () {
1819
1882
  Polymer.Bind.prepareInstance(this);
1883
+ if (this._bindListeners) {
1820
1884
  Polymer.Bind.setupBindListeners(this);
1885
+ }
1821
1886
  },
1822
1887
  _applyEffectValue: function (info, value) {
1823
1888
  var node = this._nodes[info.index];
@@ -1836,11 +1901,14 @@ value = this._scopeElementClass(node, value);
1836
1901
  if (property === 'textContent' || node.localName == 'input' && property == 'value') {
1837
1902
  value = value == undefined ? '' : value;
1838
1903
  }
1839
- return node[property] = value;
1904
+ var pinfo;
1905
+ if (!node._propertyInfo || !(pinfo = node._propertyInfo[property]) || !pinfo.readOnly) {
1906
+ this.__setProperty(property, value, true, node);
1907
+ }
1840
1908
  }
1841
1909
  },
1842
1910
  _executeStaticEffects: function () {
1843
- if (this._propertyEffects.__static__) {
1911
+ if (this._propertyEffects && this._propertyEffects.__static__) {
1844
1912
  this._effectEffects('__static__', null, this._propertyEffects.__static__);
1845
1913
  }
1846
1914
  }
@@ -1848,12 +1916,14 @@ this._effectEffects('__static__', null, this._propertyEffects.__static__);
1848
1916
  Polymer.Base._addFeature({
1849
1917
  _setupConfigure: function (initialConfig) {
1850
1918
  this._config = {};
1919
+ this._handlers = [];
1920
+ if (initialConfig) {
1851
1921
  for (var i in initialConfig) {
1852
1922
  if (initialConfig[i] !== undefined) {
1853
1923
  this._config[i] = initialConfig[i];
1854
1924
  }
1855
1925
  }
1856
- this._handlers = [];
1926
+ }
1857
1927
  },
1858
1928
  _marshalAttributes: function () {
1859
1929
  this._takeAttributesToModel(this._config);
@@ -1863,7 +1933,10 @@ var model = this._clientsReadied ? this : this._config;
1863
1933
  this._setAttributeToProperty(model, name);
1864
1934
  },
1865
1935
  _configValue: function (name, value) {
1936
+ var info = this._propertyInfo[name];
1937
+ if (!info || !info.readOnly) {
1866
1938
  this._config[name] = value;
1939
+ }
1867
1940
  },
1868
1941
  _beforeClientsReady: function () {
1869
1942
  this._configure();
@@ -1872,13 +1945,15 @@ _configure: function () {
1872
1945
  this._configureAnnotationReferences();
1873
1946
  this._aboveConfig = this.mixin({}, this._config);
1874
1947
  var config = {};
1875
- this.behaviors.forEach(function (b) {
1876
- this._configureProperties(b.properties, config);
1877
- }, this);
1948
+ for (var i = 0; i < this.behaviors.length; i++) {
1949
+ this._configureProperties(this.behaviors[i].properties, config);
1950
+ }
1878
1951
  this._configureProperties(this.properties, config);
1879
- this._mixinConfigure(config, this._aboveConfig);
1952
+ this.mixin(config, this._aboveConfig);
1880
1953
  this._config = config;
1954
+ if (this._clients && this._clients.length) {
1881
1955
  this._distributeConfig(this._config);
1956
+ }
1882
1957
  },
1883
1958
  _configureProperties: function (properties, config) {
1884
1959
  for (var i in properties) {
@@ -1892,13 +1967,6 @@ config[i] = value;
1892
1967
  }
1893
1968
  }
1894
1969
  },
1895
- _mixinConfigure: function (a, b) {
1896
- for (var prop in b) {
1897
- if (!this.getPropertyInfo(prop).readOnly) {
1898
- a[prop] = b[prop];
1899
- }
1900
- }
1901
- },
1902
1970
  _distributeConfig: function (config) {
1903
1971
  var fx$ = this._propertyEffects;
1904
1972
  if (fx$) {
@@ -1931,14 +1999,22 @@ this.__setProperty(n, config[n], n in aboveConfig);
1931
1999
  }
1932
2000
  },
1933
2001
  _notifyListener: function (fn, e) {
2002
+ if (!Polymer.Bind._isEventBogus(e, e.target)) {
2003
+ var value, path;
2004
+ if (e.detail) {
2005
+ value = e.detail.value;
2006
+ path = e.detail.path;
2007
+ }
1934
2008
  if (!this._clientsReadied) {
1935
2009
  this._queueHandler([
1936
2010
  fn,
1937
- e,
1938
- e.target
2011
+ e.target,
2012
+ value,
2013
+ path
1939
2014
  ]);
1940
2015
  } else {
1941
- return fn.call(this, e, e.target);
2016
+ return fn.call(this, e.target, value, path);
2017
+ }
1942
2018
  }
1943
2019
  },
1944
2020
  _queueHandler: function (args) {
@@ -1947,7 +2023,7 @@ this._handlers.push(args);
1947
2023
  _flushHandlers: function () {
1948
2024
  var h$ = this._handlers;
1949
2025
  for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) {
1950
- h[0].call(this, h[1], h[2]);
2026
+ h[0].call(this, h[1], h[2], h[3]);
1951
2027
  }
1952
2028
  this._handlers = [];
1953
2029
  }
@@ -2056,14 +2132,14 @@ return prop;
2056
2132
  },
2057
2133
  _pathEffector: function (path, value) {
2058
2134
  var model = this._modelForPath(path);
2059
- var fx$ = this._propertyEffects[model];
2135
+ var fx$ = this._propertyEffects && this._propertyEffects[model];
2060
2136
  if (fx$) {
2061
- fx$.forEach(function (fx) {
2062
- var fxFn = this['_' + fx.kind + 'PathEffect'];
2137
+ for (var i = 0, fx; i < fx$.length && (fx = fx$[i]); i++) {
2138
+ var fxFn = fx.pathFn;
2063
2139
  if (fxFn) {
2064
2140
  fxFn.call(this, path, value, fx.effect);
2065
2141
  }
2066
- }, this);
2142
+ }
2067
2143
  }
2068
2144
  if (this._boundPaths) {
2069
2145
  this._notifyBoundPaths(path, value);
@@ -2132,7 +2208,10 @@ var eventName = dashCaseName + this._EVENT_CHANGED;
2132
2208
  this.fire(eventName, {
2133
2209
  path: path,
2134
2210
  value: value
2135
- }, { bubbles: false });
2211
+ }, {
2212
+ bubbles: false,
2213
+ _useCache: true
2214
+ });
2136
2215
  },
2137
2216
  _modelForPath: function (path) {
2138
2217
  var dot = path.indexOf('.');
@@ -2235,6 +2314,8 @@ return ret;
2235
2314
  prepareModelNotifyPath: function (model) {
2236
2315
  this.mixin(model, {
2237
2316
  fire: Polymer.Base.fire,
2317
+ _getEvent: Polymer.Base._getEvent,
2318
+ __eventCache: Polymer.Base.__eventCache,
2238
2319
  notifyPath: Polymer.Base.notifyPath,
2239
2320
  _get: Polymer.Base._get,
2240
2321
  _EVENT_CHANGED: Polymer.Base._EVENT_CHANGED,
@@ -2308,6 +2389,8 @@ node.parsedCssText = node.cssText = t.trim();
2308
2389
  if (node.parent) {
2309
2390
  var ss = node.previous ? node.previous.end : node.parent.start;
2310
2391
  t = text.substring(ss, node.start - 1);
2392
+ t = this._expandUnicodeEscapes(t);
2393
+ t = t.replace(this._rx.multipleSpaces, ' ');
2311
2394
  t = t.substring(t.lastIndexOf(';') + 1);
2312
2395
  var s = node.parsedSelector = node.selector = t.trim();
2313
2396
  node.atRule = s.indexOf(this.AT_START) === 0;
@@ -2333,6 +2416,15 @@ this._parseCss(r, text);
2333
2416
  }
2334
2417
  return node;
2335
2418
  },
2419
+ _expandUnicodeEscapes: function (s) {
2420
+ return s.replace(/\\([0-9a-f]{1,6})\s/gi, function () {
2421
+ var code = arguments[1], repeat = 6 - code.length;
2422
+ while (repeat--) {
2423
+ code = '0' + code;
2424
+ }
2425
+ return '\\' + code;
2426
+ });
2427
+ },
2336
2428
  stringify: function (node, preserveProperties, text) {
2337
2429
  text = text || '';
2338
2430
  var cssText = '';
@@ -2362,7 +2454,7 @@ text += this.CLOSE_BRACE + '\n\n';
2362
2454
  return text;
2363
2455
  },
2364
2456
  _hasMixinRules: function (rules) {
2365
- return rules[0].selector.indexOf(this.VAR_START) >= 0;
2457
+ return rules[0].selector.indexOf(this.VAR_START) === 0;
2366
2458
  },
2367
2459
  removeCustomProps: function (cssText) {
2368
2460
  cssText = this.removeCustomPropAssignment(cssText);
@@ -2388,8 +2480,9 @@ port: /@import[^;]*;/gim,
2388
2480
  customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim,
2389
2481
  mixinProp: /(?:^|[\s;])?--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim,
2390
2482
  mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim,
2391
- varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim,
2392
- keyframesRule: /^@[^\s]*keyframes/
2483
+ varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,
2484
+ keyframesRule: /^@[^\s]*keyframes/,
2485
+ multipleSpaces: /\s+/g
2393
2486
  },
2394
2487
  VAR_START: '--',
2395
2488
  MEDIA_START: '@media',
@@ -2469,21 +2562,21 @@ return cssText;
2469
2562
  cssFromModule: function (moduleId, warnIfNotFound) {
2470
2563
  var m = Polymer.DomModule.import(moduleId);
2471
2564
  if (m && !m._cssText) {
2472
- m._cssText = this._cssFromElement(m);
2565
+ m._cssText = this.cssFromElement(m);
2473
2566
  }
2474
2567
  if (!m && warnIfNotFound) {
2475
2568
  console.warn('Could not find style data in module named', moduleId);
2476
2569
  }
2477
2570
  return m && m._cssText || '';
2478
2571
  },
2479
- _cssFromElement: function (element) {
2572
+ cssFromElement: function (element) {
2480
2573
  var cssText = '';
2481
2574
  var content = element.content || element;
2482
- var e$ = Array.prototype.slice.call(content.querySelectorAll(this.MODULE_STYLES_SELECTOR));
2575
+ var e$ = Polymer.DomApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_SELECTOR));
2483
2576
  for (var i = 0, e; i < e$.length; i++) {
2484
2577
  e = e$[i];
2485
2578
  if (e.localName === 'template') {
2486
- cssText += this._cssFromElement(e);
2579
+ cssText += this.cssFromElement(e);
2487
2580
  } else {
2488
2581
  if (e.localName === 'style') {
2489
2582
  var include = e.getAttribute(this.INCLUDE_ATTR);
@@ -2732,7 +2825,7 @@ _extendRule: function (target, source) {
2732
2825
  if (target.parent !== source.parent) {
2733
2826
  this._cloneAndAddRuleToParent(source, target.parent);
2734
2827
  }
2735
- target.extends = target.extends || (target.extends = []);
2828
+ target.extends = target.extends || [];
2736
2829
  target.extends.push(source);
2737
2830
  source.selector = source.selector.replace(this.rx.STRIP, '');
2738
2831
  source.selector = (source.selector && source.selector + ',\n') + target.selector;
@@ -2773,14 +2866,18 @@ _prepStyles: function () {
2773
2866
  if (this._encapsulateStyle === undefined) {
2774
2867
  this._encapsulateStyle = !nativeShadow && Boolean(this._template);
2775
2868
  }
2869
+ if (this._template) {
2776
2870
  this._styles = this._collectStyles();
2777
2871
  var cssText = styleTransformer.elementStyles(this);
2778
- if (cssText && this._template) {
2872
+ if (cssText) {
2779
2873
  var style = styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.content : null);
2780
2874
  if (!nativeShadow) {
2781
2875
  this._scopeStyle = style;
2782
2876
  }
2783
2877
  }
2878
+ } else {
2879
+ this._styles = [];
2880
+ }
2784
2881
  },
2785
2882
  _collectStyles: function () {
2786
2883
  var styles = [];
@@ -2791,6 +2888,10 @@ cssText += styleUtil.cssFromModule(m);
2791
2888
  }
2792
2889
  }
2793
2890
  cssText += styleUtil.cssFromModule(this.is);
2891
+ var p = this._template && this._template.parentNode;
2892
+ if (this._template && (!p || p.id.toLowerCase() !== this.is)) {
2893
+ cssText += styleUtil.cssFromElement(this._template);
2894
+ }
2794
2895
  if (cssText) {
2795
2896
  var style = document.createElement('style');
2796
2897
  style.textContent = cssText;
@@ -2824,21 +2925,21 @@ var scopify = function (node) {
2824
2925
  if (node.nodeType === Node.ELEMENT_NODE) {
2825
2926
  node.className = self._scopeElementClass(node, node.className);
2826
2927
  var n$ = node.querySelectorAll('*');
2827
- Array.prototype.forEach.call(n$, function (n) {
2928
+ for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
2828
2929
  n.className = self._scopeElementClass(n, n.className);
2829
- });
2930
+ }
2830
2931
  }
2831
2932
  };
2832
2933
  scopify(container);
2833
2934
  if (shouldObserve) {
2834
2935
  var mo = new MutationObserver(function (mxns) {
2835
- mxns.forEach(function (m) {
2936
+ for (var i = 0, m; i < mxns.length && (m = mxns[i]); i++) {
2836
2937
  if (m.addedNodes) {
2837
- for (var i = 0; i < m.addedNodes.length; i++) {
2838
- scopify(m.addedNodes[i]);
2938
+ for (var j = 0; j < m.addedNodes.length; j++) {
2939
+ scopify(m.addedNodes[j]);
2940
+ }
2839
2941
  }
2840
2942
  }
2841
- });
2842
2943
  });
2843
2944
  mo.observe(container, {
2844
2945
  childList: true,
@@ -2963,7 +3064,9 @@ p = pp.join(':');
2963
3064
  parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || '';
2964
3065
  }
2965
3066
  }
2966
- return parts.join(';');
3067
+ return parts.filter(function (v) {
3068
+ return v;
3069
+ }).join(';');
2967
3070
  },
2968
3071
  applyProperties: function (rule, props) {
2969
3072
  var output = '';
@@ -3208,9 +3311,12 @@ var styleDefaults = Polymer.StyleDefaults;
3208
3311
  var nativeShadow = Polymer.Settings.useNativeShadow;
3209
3312
  Polymer.Base._addFeature({
3210
3313
  _prepStyleProperties: function () {
3211
- this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._styles) : [];
3314
+ this._ownStylePropertyNames = this._styles ? propertyUtils.decorateStyles(this._styles) : null;
3315
+ },
3316
+ customStyle: null,
3317
+ getComputedStyleValue: function (property) {
3318
+ return this._styleProperties && this._styleProperties[property] || getComputedStyle(this).getPropertyValue(property);
3212
3319
  },
3213
- customStyle: {},
3214
3320
  _setupStyleProperties: function () {
3215
3321
  this.customStyle = {};
3216
3322
  },
@@ -3307,7 +3413,7 @@ if (host) {
3307
3413
  value = host._scopeElementClass(node, value);
3308
3414
  }
3309
3415
  }
3310
- node = Polymer.dom(node);
3416
+ node = this.shadyRoot && this.shadyRoot._hasDistributed ? Polymer.dom(node) : node;
3311
3417
  serializeValueToAttribute.call(this, value, attribute, node);
3312
3418
  },
3313
3419
  _scopeElementClass: function (element, selector) {
@@ -3356,7 +3462,6 @@ var XSCOPE_NAME = propertyUtils.XSCOPE_NAME;
3356
3462
  Polymer.Base._addFeature({
3357
3463
  _registerFeatures: function () {
3358
3464
  this._prepIs();
3359
- this._prepAttributes();
3360
3465
  this._prepConstructor();
3361
3466
  this._prepTemplate();
3362
3467
  this._prepStyles();
@@ -3364,6 +3469,7 @@ this._prepStyleProperties();
3364
3469
  this._prepAnnotations();
3365
3470
  this._prepEffects();
3366
3471
  this._prepBehaviors();
3472
+ this._prepPropertyInfo();
3367
3473
  this._prepBindings();
3368
3474
  this._prepShady();
3369
3475
  },
@@ -3373,23 +3479,28 @@ this._addComplexObserverEffects(b.observers);
3373
3479
  this._addHostAttributes(b.hostAttributes);
3374
3480
  },
3375
3481
  _initFeatures: function () {
3376
- this._poolContent();
3377
3482
  this._setupConfigure();
3378
3483
  this._setupStyleProperties();
3379
- this._pushHost();
3484
+ this._setupDebouncers();
3485
+ this._registerHost();
3486
+ if (this._template) {
3487
+ this._poolContent();
3488
+ this._beginHosting();
3380
3489
  this._stampTemplate();
3381
- this._popHost();
3490
+ this._endHosting();
3382
3491
  this._marshalAnnotationReferences();
3383
- this._setupDebouncers();
3492
+ }
3384
3493
  this._marshalInstanceEffects();
3385
- this._marshalHostAttributes();
3386
3494
  this._marshalBehaviors();
3495
+ this._marshalHostAttributes();
3387
3496
  this._marshalAttributes();
3388
3497
  this._tryReady();
3389
3498
  },
3390
3499
  _marshalBehavior: function (b) {
3500
+ if (b.listeners) {
3391
3501
  this._listenListeners(b.listeners);
3392
3502
  }
3503
+ }
3393
3504
  });
3394
3505
  (function () {
3395
3506
  var nativeShadow = Polymer.Settings.useNativeShadow;
@@ -3401,6 +3512,7 @@ var styleTransformer = Polymer.StyleTransformer;
3401
3512
  Polymer({
3402
3513
  is: 'custom-style',
3403
3514
  extends: 'style',
3515
+ _template: null,
3404
3516
  properties: { include: String },
3405
3517
  ready: function () {
3406
3518
  this._tryApply();
@@ -3417,10 +3529,11 @@ styleDefaults.addStyle(e);
3417
3529
  if (e.textContent || this.include) {
3418
3530
  this._apply();
3419
3531
  } else {
3532
+ var self = this;
3420
3533
  var observer = new MutationObserver(function () {
3421
3534
  observer.disconnect();
3422
- this._apply();
3423
- }.bind(this));
3535
+ self._apply();
3536
+ });
3424
3537
  observer.observe(e, { childList: true });
3425
3538
  }
3426
3539
  }
@@ -3472,6 +3585,7 @@ this._prepParentProperties(archetype, template);
3472
3585
  archetype._prepEffects();
3473
3586
  this._customPrepEffects(archetype);
3474
3587
  archetype._prepBehaviors();
3588
+ archetype._prepPropertyInfo();
3475
3589
  archetype._prepBindings();
3476
3590
  archetype._notifyPathUp = this._notifyPathUpImpl;
3477
3591
  archetype._scopeElementClass = this._scopeElementClassImpl;
@@ -3534,7 +3648,9 @@ var c = template._content;
3534
3648
  if (!c._notes) {
3535
3649
  var rootDataHost = archetype._rootDataHost;
3536
3650
  if (rootDataHost) {
3537
- Polymer.Annotations.prepElement = rootDataHost._prepElement.bind(rootDataHost);
3651
+ Polymer.Annotations.prepElement = function () {
3652
+ rootDataHost._prepElement();
3653
+ };
3538
3654
  }
3539
3655
  c._notes = Polymer.Annotations.parseAnnotations(template);
3540
3656
  Polymer.Annotations.prepElement = null;
@@ -3562,19 +3678,29 @@ var parentProp = this._parentPropPrefix + prop;
3562
3678
  var effects = [
3563
3679
  {
3564
3680
  kind: 'function',
3565
- effect: this._createForwardPropEffector(prop)
3681
+ effect: this._createForwardPropEffector(prop),
3682
+ fn: Polymer.Bind._functionEffect
3566
3683
  },
3567
- { kind: 'notify' }
3684
+ {
3685
+ kind: 'notify',
3686
+ fn: Polymer.Bind._notifyEffect,
3687
+ effect: { event: Polymer.CaseMap.camelToDashCase(parentProp) + '-changed' }
3688
+ }
3568
3689
  ];
3569
3690
  Polymer.Bind._createAccessors(proto, parentProp, effects);
3570
3691
  }
3571
3692
  }
3693
+ var self = this;
3572
3694
  if (template != this) {
3573
3695
  Polymer.Bind.prepareInstance(template);
3574
- template._forwardParentProp = this._forwardParentProp.bind(this);
3696
+ template._forwardParentProp = function (source, value) {
3697
+ self._forwardParentProp(source, value);
3698
+ };
3575
3699
  }
3576
3700
  this._extendTemplate(template, proto);
3577
- template._pathEffector = this._pathEffectorImpl.bind(this);
3701
+ template._pathEffector = function (path, value, fromAbove) {
3702
+ return self._pathEffectorImpl(path, value, fromAbove);
3703
+ };
3578
3704
  }
3579
3705
  },
3580
3706
  _createForwardPropEffector: function (prop) {
@@ -3596,14 +3722,15 @@ this.dataHost._forwardInstanceProp(this, prop, value);
3596
3722
  };
3597
3723
  },
3598
3724
  _extendTemplate: function (template, proto) {
3599
- Object.getOwnPropertyNames(proto).forEach(function (n) {
3725
+ var n$ = Object.getOwnPropertyNames(proto);
3726
+ for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
3600
3727
  var val = template[n];
3601
3728
  var pd = Object.getOwnPropertyDescriptor(proto, n);
3602
3729
  Object.defineProperty(template, n, pd);
3603
3730
  if (val !== undefined) {
3604
3731
  template._propertySetter(n, val);
3605
3732
  }
3606
- });
3733
+ }
3607
3734
  },
3608
3735
  _showHideChildren: function (hidden) {
3609
3736
  },
@@ -3635,11 +3762,12 @@ Polymer.Base._pathEffector.call(this._templatized, path, value, fromAbove);
3635
3762
  _constructorImpl: function (model, host) {
3636
3763
  this._rootDataHost = host._getRootDataHost();
3637
3764
  this._setupConfigure(model);
3638
- this._pushHost(host);
3765
+ this._registerHost(host);
3766
+ this._beginHosting();
3639
3767
  this.root = this.instanceTemplate(this._template);
3640
3768
  this.root.__noContent = !this._notes._hasContent;
3641
3769
  this.root.__styleScoped = true;
3642
- this._popHost();
3770
+ this._endHosting();
3643
3771
  this._marshalAnnotatedNodes();
3644
3772
  this._marshalInstanceEffects();
3645
3773
  this._marshalAnnotatedListeners();
@@ -3698,6 +3826,7 @@ el = el.parentNode;
3698
3826
  Polymer({
3699
3827
  is: 'dom-template',
3700
3828
  extends: 'template',
3829
+ _template: null,
3701
3830
  behaviors: [Polymer.Templatizer],
3702
3831
  ready: function () {
3703
3832
  this.templatize(this);
@@ -3798,21 +3927,21 @@ items.push(store[key]);
3798
3927
  return items;
3799
3928
  },
3800
3929
  _applySplices: function (splices) {
3801
- var keyMap = {}, key, i;
3802
- splices.forEach(function (s) {
3930
+ var keyMap = {}, key;
3931
+ for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
3803
3932
  s.addedKeys = [];
3804
- for (i = 0; i < s.removed.length; i++) {
3805
- key = this.getKey(s.removed[i]);
3933
+ for (var j = 0; j < s.removed.length; j++) {
3934
+ key = this.getKey(s.removed[j]);
3806
3935
  keyMap[key] = keyMap[key] ? null : -1;
3807
3936
  }
3808
- for (i = 0; i < s.addedCount; i++) {
3809
- var item = this.userArray[s.index + i];
3937
+ for (var j = 0; j < s.addedCount; j++) {
3938
+ var item = this.userArray[s.index + j];
3810
3939
  key = this.getKey(item);
3811
3940
  key = key === undefined ? this.add(item) : key;
3812
3941
  keyMap[key] = keyMap[key] ? null : 1;
3813
3942
  s.addedKeys.push(key);
3814
3943
  }
3815
- }, this);
3944
+ }
3816
3945
  var removed = [];
3817
3946
  var added = [];
3818
3947
  for (var key in keyMap) {
@@ -3840,6 +3969,7 @@ return coll ? coll._applySplices(splices) : null;
3840
3969
  Polymer({
3841
3970
  is: 'dom-repeat',
3842
3971
  extends: 'template',
3972
+ _template: null,
3843
3973
  properties: {
3844
3974
  items: { type: Array },
3845
3975
  as: {
@@ -3862,22 +3992,37 @@ observe: {
3862
3992
  type: String,
3863
3993
  observer: '_observeChanged'
3864
3994
  },
3865
- delay: Number
3995
+ delay: Number,
3996
+ initialCount: {
3997
+ type: Number,
3998
+ observer: '_initializeChunking'
3999
+ },
4000
+ targetFramerate: {
4001
+ type: Number,
4002
+ value: 20
4003
+ },
4004
+ _targetFrameTime: { computed: '_computeFrameTime(targetFramerate)' }
3866
4005
  },
3867
4006
  behaviors: [Polymer.Templatizer],
3868
4007
  observers: ['_itemsChanged(items.*)'],
3869
4008
  created: function () {
3870
4009
  this._instances = [];
4010
+ this._pool = [];
4011
+ this._limit = Infinity;
4012
+ var self = this;
4013
+ this._boundRenderChunk = function () {
4014
+ self._renderChunk();
4015
+ };
3871
4016
  },
3872
4017
  detached: function () {
3873
4018
  for (var i = 0; i < this._instances.length; i++) {
3874
- this._detachRow(i);
4019
+ this._detachInstance(i);
3875
4020
  }
3876
4021
  },
3877
4022
  attached: function () {
3878
- var parentNode = Polymer.dom(this).parentNode;
4023
+ var parent = Polymer.dom(Polymer.dom(this).parentNode);
3879
4024
  for (var i = 0; i < this._instances.length; i++) {
3880
- Polymer.dom(parentNode).insertBefore(this._instances[i].root, this);
4025
+ this._attachInstance(i, parent);
3881
4026
  }
3882
4027
  },
3883
4028
  ready: function () {
@@ -3888,9 +4033,8 @@ if (!this.ctor) {
3888
4033
  this.templatize(this);
3889
4034
  }
3890
4035
  },
3891
- _sortChanged: function () {
4036
+ _sortChanged: function (sort) {
3892
4037
  var dataHost = this._getRootDataHost();
3893
- var sort = this.sort;
3894
4038
  this._sortFn = sort && (typeof sort == 'function' ? sort : function () {
3895
4039
  return dataHost[sort].apply(dataHost, arguments);
3896
4040
  });
@@ -3899,9 +4043,8 @@ if (this.items) {
3899
4043
  this._debounceTemplate(this._render);
3900
4044
  }
3901
4045
  },
3902
- _filterChanged: function () {
4046
+ _filterChanged: function (filter) {
3903
4047
  var dataHost = this._getRootDataHost();
3904
- var filter = this.filter;
3905
4048
  this._filterFn = filter && (typeof filter == 'function' ? filter : function () {
3906
4049
  return dataHost[filter].apply(dataHost, arguments);
3907
4050
  });
@@ -3910,6 +4053,32 @@ if (this.items) {
3910
4053
  this._debounceTemplate(this._render);
3911
4054
  }
3912
4055
  },
4056
+ _computeFrameTime: function (rate) {
4057
+ return Math.ceil(1000 / rate);
4058
+ },
4059
+ _initializeChunking: function () {
4060
+ if (this.initialCount) {
4061
+ this._limit = this.initialCount;
4062
+ this._chunkCount = this.initialCount;
4063
+ this._lastChunkTime = performance.now();
4064
+ }
4065
+ },
4066
+ _tryRenderChunk: function () {
4067
+ if (this.items && this._limit < this.items.length) {
4068
+ this.debounce('renderChunk', this._requestRenderChunk);
4069
+ }
4070
+ },
4071
+ _requestRenderChunk: function () {
4072
+ requestAnimationFrame(this._boundRenderChunk);
4073
+ },
4074
+ _renderChunk: function () {
4075
+ var currChunkTime = performance.now();
4076
+ var ratio = this._targetFrameTime / (currChunkTime - this._lastChunkTime);
4077
+ this._chunkCount = Math.round(this._chunkCount * ratio) || 1;
4078
+ this._limit += this._chunkCount;
4079
+ this._lastChunkTime = currChunkTime;
4080
+ this._debounceTemplate(this._render);
4081
+ },
3913
4082
  _observeChanged: function () {
3914
4083
  this._observePaths = this.observe && this.observe.replace('.*', '.').split(' ');
3915
4084
  },
@@ -3925,6 +4094,7 @@ this._error(this._logf('dom-repeat', 'expected array for `items`,' + ' found', t
3925
4094
  this._keySplices = [];
3926
4095
  this._indexSplices = [];
3927
4096
  this._needFullRefresh = true;
4097
+ this._initializeChunking();
3928
4098
  this._debounceTemplate(this._render);
3929
4099
  } else if (change.path == 'items.splices') {
3930
4100
  this._keySplices = this._keySplices.concat(change.value.keySplices);
@@ -3963,7 +4133,7 @@ var c = this.collection;
3963
4133
  if (this._needFullRefresh) {
3964
4134
  this._applyFullRefresh();
3965
4135
  this._needFullRefresh = false;
3966
- } else {
4136
+ } else if (this._keySplices.length) {
3967
4137
  if (this._sortFn) {
3968
4138
  this._applySplicesUserSort(this._keySplices);
3969
4139
  } else {
@@ -3973,16 +4143,26 @@ this._applyFullRefresh();
3973
4143
  this._applySplicesArrayOrder(this._indexSplices);
3974
4144
  }
3975
4145
  }
4146
+ } else {
3976
4147
  }
3977
4148
  this._keySplices = [];
3978
4149
  this._indexSplices = [];
3979
4150
  var keyToIdx = this._keyToInstIdx = {};
3980
- for (var i = 0; i < this._instances.length; i++) {
4151
+ for (var i = this._instances.length - 1; i >= 0; i--) {
3981
4152
  var inst = this._instances[i];
4153
+ if (inst.isPlaceholder && i < this._limit) {
4154
+ inst = this._insertInstance(i, inst.__key__);
4155
+ } else if (!inst.isPlaceholder && i >= this._limit) {
4156
+ inst = this._downgradeInstance(i, inst.__key__);
4157
+ }
3982
4158
  keyToIdx[inst.__key__] = i;
4159
+ if (!inst.isPlaceholder) {
3983
4160
  inst.__setProperty(this.indexAs, i, true);
3984
4161
  }
4162
+ }
4163
+ this._pool.length = 0;
3985
4164
  this.fire('dom-change');
4165
+ this._tryRenderChunk();
3986
4166
  },
3987
4167
  _applyFullRefresh: function () {
3988
4168
  var c = this.collection;
@@ -3998,33 +4178,34 @@ keys.push(c.getKey(items[i]));
3998
4178
  }
3999
4179
  }
4000
4180
  }
4181
+ var self = this;
4001
4182
  if (this._filterFn) {
4002
4183
  keys = keys.filter(function (a) {
4003
- return this._filterFn(c.getItem(a));
4004
- }, this);
4184
+ return self._filterFn(c.getItem(a));
4185
+ });
4005
4186
  }
4006
4187
  if (this._sortFn) {
4007
4188
  keys.sort(function (a, b) {
4008
- return this._sortFn(c.getItem(a), c.getItem(b));
4009
- }.bind(this));
4189
+ return self._sortFn(c.getItem(a), c.getItem(b));
4190
+ });
4010
4191
  }
4011
4192
  for (var i = 0; i < keys.length; i++) {
4012
4193
  var key = keys[i];
4013
4194
  var inst = this._instances[i];
4014
4195
  if (inst) {
4015
- inst.__setProperty('__key__', key, true);
4196
+ inst.__key__ = key;
4197
+ if (!inst.isPlaceholder && i < this._limit) {
4016
4198
  inst.__setProperty(this.as, c.getItem(key), true);
4199
+ }
4200
+ } else if (i < this._limit) {
4201
+ this._insertInstance(i, key);
4017
4202
  } else {
4018
- this._instances.push(this._insertRow(i, key));
4203
+ this._insertPlaceholder(i, key);
4019
4204
  }
4020
4205
  }
4021
- for (; i < this._instances.length; i++) {
4022
- this._detachRow(i);
4206
+ for (var j = this._instances.length - 1; j >= i; j--) {
4207
+ this._detachAndRemoveInstance(j);
4023
4208
  }
4024
- this._instances.splice(keys.length, this._instances.length - keys.length);
4025
- },
4026
- _keySort: function (a, b) {
4027
- return this.collection.getKey(a) - this.collection.getKey(b);
4028
4209
  },
4029
4210
  _numericSort: function (a, b) {
4030
4211
  return a - b;
@@ -4033,18 +4214,16 @@ _applySplicesUserSort: function (splices) {
4033
4214
  var c = this.collection;
4034
4215
  var instances = this._instances;
4035
4216
  var keyMap = {};
4036
- var pool = [];
4037
- var sortFn = this._sortFn || this._keySort.bind(this);
4038
- splices.forEach(function (s) {
4039
- for (var i = 0; i < s.removed.length; i++) {
4040
- var key = s.removed[i];
4217
+ for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
4218
+ for (var j = 0; j < s.removed.length; j++) {
4219
+ var key = s.removed[j];
4041
4220
  keyMap[key] = keyMap[key] ? null : -1;
4042
4221
  }
4043
- for (var i = 0; i < s.added.length; i++) {
4044
- var key = s.added[i];
4222
+ for (var j = 0; j < s.added.length; j++) {
4223
+ var key = s.added[j];
4045
4224
  keyMap[key] = keyMap[key] ? null : 1;
4046
4225
  }
4047
- }, this);
4226
+ }
4048
4227
  var removedIdxs = [];
4049
4228
  var addedKeys = [];
4050
4229
  for (var key in keyMap) {
@@ -4060,36 +4239,35 @@ removedIdxs.sort(this._numericSort);
4060
4239
  for (var i = removedIdxs.length - 1; i >= 0; i--) {
4061
4240
  var idx = removedIdxs[i];
4062
4241
  if (idx !== undefined) {
4063
- pool.push(this._detachRow(idx));
4064
- instances.splice(idx, 1);
4242
+ this._detachAndRemoveInstance(idx);
4065
4243
  }
4066
4244
  }
4067
4245
  }
4246
+ var self = this;
4068
4247
  if (addedKeys.length) {
4069
4248
  if (this._filterFn) {
4070
4249
  addedKeys = addedKeys.filter(function (a) {
4071
- return this._filterFn(c.getItem(a));
4072
- }, this);
4250
+ return self._filterFn(c.getItem(a));
4251
+ });
4073
4252
  }
4074
4253
  addedKeys.sort(function (a, b) {
4075
- return this._sortFn(c.getItem(a), c.getItem(b));
4076
- }.bind(this));
4254
+ return self._sortFn(c.getItem(a), c.getItem(b));
4255
+ });
4077
4256
  var start = 0;
4078
4257
  for (var i = 0; i < addedKeys.length; i++) {
4079
- start = this._insertRowUserSort(start, addedKeys[i], pool);
4258
+ start = this._insertRowUserSort(start, addedKeys[i]);
4080
4259
  }
4081
4260
  }
4082
4261
  },
4083
- _insertRowUserSort: function (start, key, pool) {
4262
+ _insertRowUserSort: function (start, key) {
4084
4263
  var c = this.collection;
4085
4264
  var item = c.getItem(key);
4086
4265
  var end = this._instances.length - 1;
4087
4266
  var idx = -1;
4088
- var sortFn = this._sortFn || this._keySort.bind(this);
4089
4267
  while (start <= end) {
4090
4268
  var mid = start + end >> 1;
4091
4269
  var midKey = this._instances[mid].__key__;
4092
- var cmp = sortFn(c.getItem(midKey), item);
4270
+ var cmp = this._sortFn(c.getItem(midKey), item);
4093
4271
  if (cmp < 0) {
4094
4272
  start = mid + 1;
4095
4273
  } else if (cmp > 0) {
@@ -4102,65 +4280,80 @@ break;
4102
4280
  if (idx < 0) {
4103
4281
  idx = end + 1;
4104
4282
  }
4105
- this._instances.splice(idx, 0, this._insertRow(idx, key, pool));
4283
+ this._insertPlaceholder(idx, key);
4106
4284
  return idx;
4107
4285
  },
4108
4286
  _applySplicesArrayOrder: function (splices) {
4109
- var pool = [];
4110
4287
  var c = this.collection;
4111
- splices.forEach(function (s) {
4112
- for (var i = 0; i < s.removed.length; i++) {
4113
- var inst = this._detachRow(s.index + i);
4114
- if (!inst.isPlaceholder) {
4115
- pool.push(inst);
4288
+ for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
4289
+ for (var j = 0; j < s.removed.length; j++) {
4290
+ this._detachAndRemoveInstance(s.index);
4116
4291
  }
4117
- }
4118
- this._instances.splice(s.index, s.removed.length);
4119
- for (var i = 0; i < s.addedKeys.length; i++) {
4120
- var inst = {
4121
- isPlaceholder: true,
4122
- key: s.addedKeys[i]
4123
- };
4124
- this._instances.splice(s.index + i, 0, inst);
4125
- }
4126
- }, this);
4127
- for (var i = this._instances.length - 1; i >= 0; i--) {
4128
- var inst = this._instances[i];
4129
- if (inst.isPlaceholder) {
4130
- this._instances[i] = this._insertRow(i, inst.key, pool, true);
4292
+ for (var j = 0; j < s.addedKeys.length; j++) {
4293
+ this._insertPlaceholder(s.index + j, s.addedKeys[j]);
4131
4294
  }
4132
4295
  }
4133
4296
  },
4134
- _detachRow: function (idx) {
4297
+ _detachInstance: function (idx) {
4135
4298
  var inst = this._instances[idx];
4136
4299
  if (!inst.isPlaceholder) {
4137
- var parentNode = Polymer.dom(this).parentNode;
4138
4300
  for (var i = 0; i < inst._children.length; i++) {
4139
4301
  var el = inst._children[i];
4140
4302
  Polymer.dom(inst.root).appendChild(el);
4141
4303
  }
4142
- }
4143
4304
  return inst;
4305
+ }
4144
4306
  },
4145
- _insertRow: function (idx, key, pool, replace) {
4146
- var inst;
4147
- if (inst = pool && pool.pop()) {
4307
+ _attachInstance: function (idx, parent) {
4308
+ var inst = this._instances[idx];
4309
+ if (!inst.isPlaceholder) {
4310
+ parent.insertBefore(inst.root, this);
4311
+ }
4312
+ },
4313
+ _detachAndRemoveInstance: function (idx) {
4314
+ var inst = this._detachInstance(idx);
4315
+ if (inst) {
4316
+ this._pool.push(inst);
4317
+ }
4318
+ this._instances.splice(idx, 1);
4319
+ },
4320
+ _insertPlaceholder: function (idx, key) {
4321
+ this._instances.splice(idx, 0, {
4322
+ isPlaceholder: true,
4323
+ __key__: key
4324
+ });
4325
+ },
4326
+ _stampInstance: function (idx, key) {
4327
+ var model = { __key__: key };
4328
+ model[this.as] = this.collection.getItem(key);
4329
+ model[this.indexAs] = idx;
4330
+ return this.stamp(model);
4331
+ },
4332
+ _insertInstance: function (idx, key) {
4333
+ var inst = this._pool.pop();
4334
+ if (inst) {
4148
4335
  inst.__setProperty(this.as, this.collection.getItem(key), true);
4149
4336
  inst.__setProperty('__key__', key, true);
4150
4337
  } else {
4151
- inst = this._generateRow(idx, key);
4338
+ inst = this._stampInstance(idx, key);
4152
4339
  }
4153
- var beforeRow = this._instances[replace ? idx + 1 : idx];
4154
- var beforeNode = beforeRow ? beforeRow._children[0] : this;
4340
+ var beforeRow = this._instances[idx + 1];
4341
+ var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this;
4155
4342
  var parentNode = Polymer.dom(this).parentNode;
4156
4343
  Polymer.dom(parentNode).insertBefore(inst.root, beforeNode);
4344
+ this._instances[idx] = inst;
4157
4345
  return inst;
4158
4346
  },
4159
- _generateRow: function (idx, key) {
4160
- var model = { __key__: key };
4161
- model[this.as] = this.collection.getItem(key);
4162
- model[this.indexAs] = idx;
4163
- var inst = this.stamp(model);
4347
+ _downgradeInstance: function (idx, key) {
4348
+ var inst = this._detachInstance(idx);
4349
+ if (inst) {
4350
+ this._pool.push(inst);
4351
+ }
4352
+ inst = {
4353
+ isPlaceholder: true,
4354
+ __key__: key
4355
+ };
4356
+ this._instances[idx] = inst;
4164
4357
  return inst;
4165
4358
  },
4166
4359
  _showHideChildren: function (hidden) {
@@ -4185,14 +4378,20 @@ this._notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1),
4185
4378
  }
4186
4379
  },
4187
4380
  _forwardParentProp: function (prop, value) {
4188
- this._instances.forEach(function (inst) {
4381
+ var i$ = this._instances;
4382
+ for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) {
4383
+ if (!inst.isPlaceholder) {
4189
4384
  inst.__setProperty(prop, value, true);
4190
- }, this);
4385
+ }
4386
+ }
4191
4387
  },
4192
4388
  _forwardParentPath: function (path, value) {
4193
- this._instances.forEach(function (inst) {
4389
+ var i$ = this._instances;
4390
+ for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) {
4391
+ if (!inst.isPlaceholder) {
4194
4392
  inst._notifyPath(path, value, true);
4195
- }, this);
4393
+ }
4394
+ }
4196
4395
  },
4197
4396
  _forwardItemPath: function (path, value) {
4198
4397
  if (this._keyToInstIdx) {
@@ -4200,7 +4399,7 @@ var dot = path.indexOf('.');
4200
4399
  var key = path.substring(0, dot < 0 ? path.length : dot);
4201
4400
  var idx = this._keyToInstIdx[key];
4202
4401
  var inst = this._instances[idx];
4203
- if (inst) {
4402
+ if (inst && !inst.isPlaceholder) {
4204
4403
  if (dot >= 0) {
4205
4404
  path = this.as + '.' + path.substring(dot + 1);
4206
4405
  inst._notifyPath(path, value, true);
@@ -4225,6 +4424,7 @@ return instance && instance[this.indexAs];
4225
4424
  });
4226
4425
  Polymer({
4227
4426
  is: 'array-selector',
4427
+ _template: null,
4228
4428
  properties: {
4229
4429
  items: {
4230
4430
  type: Array,
@@ -4317,6 +4517,7 @@ this.linkPaths('selectedItem', 'items.' + key);
4317
4517
  Polymer({
4318
4518
  is: 'dom-if',
4319
4519
  extends: 'template',
4520
+ _template: null,
4320
4521
  properties: {
4321
4522
  'if': {
4322
4523
  type: Boolean,
@@ -4364,20 +4565,23 @@ this._lastIf = this.if;
4364
4565
  },
4365
4566
  _ensureInstance: function () {
4366
4567
  if (!this._instance) {
4568
+ var parentNode = Polymer.dom(this).parentNode;
4569
+ if (parentNode) {
4570
+ var parent = Polymer.dom(parentNode);
4367
4571
  this._instance = this.stamp();
4368
4572
  var root = this._instance.root;
4369
- var parent = Polymer.dom(Polymer.dom(this).parentNode);
4370
4573
  parent.insertBefore(root, this);
4371
4574
  }
4575
+ }
4372
4576
  },
4373
4577
  _teardownInstance: function () {
4374
4578
  if (this._instance) {
4375
- var c = this._instance._children;
4376
- if (c) {
4377
- var parent = Polymer.dom(Polymer.dom(c[0]).parentNode);
4378
- c.forEach(function (n) {
4579
+ var c$ = this._instance._children;
4580
+ if (c$) {
4581
+ var parent = Polymer.dom(Polymer.dom(c$[0]).parentNode);
4582
+ for (var i = 0, n; i < c$.length && (n = c$[i]); i++) {
4379
4583
  parent.removeChild(n);
4380
- });
4584
+ }
4381
4585
  }
4382
4586
  this._instance = null;
4383
4587
  }
@@ -4402,8 +4606,12 @@ this._instance._notifyPath(path, value, true);
4402
4606
  Polymer({
4403
4607
  is: 'dom-bind',
4404
4608
  extends: 'template',
4609
+ _template: null,
4405
4610
  created: function () {
4406
- Polymer.RenderStatus.whenReady(this._markImportsReady.bind(this));
4611
+ var self = this;
4612
+ Polymer.RenderStatus.whenReady(function () {
4613
+ self._markImportsReady();
4614
+ });
4407
4615
  },
4408
4616
  _ensureReady: function () {
4409
4617
  if (!this._readied) {
@@ -4442,7 +4650,10 @@ var config = {};
4442
4650
  for (var prop in this._propertyEffects) {
4443
4651
  config[prop] = this[prop];
4444
4652
  }
4445
- this._setupConfigure = this._setupConfigure.bind(this, config);
4653
+ var setupConfigure = this._setupConfigure;
4654
+ this._setupConfigure = function () {
4655
+ setupConfigure.call(this, config);
4656
+ };
4446
4657
  },
4447
4658
  attached: function () {
4448
4659
  if (this._importsReady) {
@@ -4461,8 +4672,9 @@ this._prepEffects();
4461
4672
  this._prepBehaviors();
4462
4673
  this._prepConfigure();
4463
4674
  this._prepBindings();
4675
+ this._prepPropertyInfo();
4464
4676
  Polymer.Base._initFeatures.call(this);
4465
- this._children = Array.prototype.slice.call(this.root.childNodes);
4677
+ this._children = Polymer.DomApi.arrayCopyChildNodes(this.root);
4466
4678
  }
4467
4679
  this._insertChildren();
4468
4680
  this.fire('dom-change');