polymer-rails 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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');