diff --git a/polymer.html b/polymer.html index 0bdf74b521..fe5ed6732b 100644 --- a/polymer.html +++ b/polymer.html @@ -57,3 +57,4 @@ + diff --git a/src/lib/annotations/annotations.html b/src/lib/annotations/annotations.html index fdd863fe16..344b7034dd 100644 --- a/src/lib/annotations/annotations.html +++ b/src/lib/annotations/annotations.html @@ -142,12 +142,29 @@ // TODO(sjmiles): simply altering the .content reference didn't // work (there was some confusion, might need verification) var content = document.createDocumentFragment(); + content._annotes = this.parseAnnotations(node); content.appendChild(node.content); + // Special-case treatment of 'parent.*' props for nested templates + // Automatically bind `prop` on host to `_parent_prop` on template + // for any `parent.prop`'s encountered in template binding; it is + // responsibility of the template implementation to forward + // these properties as appropriate + var bindings = []; + this._discoverTemplateParentProps(content); + for (var prop in content._parentProps) { + bindings.push({ + index: i, + kind: 'property', + mode: '{', + name: '_parent_' + prop, + value: prop + }); + } // TODO(sjmiles): using `nar` to avoid unnecessary allocation; // in general the handling of these arrays needs some cleanup // in this module list.push({ - bindings: Polymer.nar, + bindings: bindings, events: Polymer.nar, templateContent: content, parent: annote, @@ -164,6 +181,42 @@ } }, + // Finds all parent.* properties in template content and stores + // the path members in content._parentPropChain, which is an array + // of maps listing the properties of parent templates required at + // each level. Each outer template merges inner _parentPropChains to + // propagate inner parent property needs to outer templates. + // The top-level parent props from the chain (corresponding to this + // template) are stored in content._parentProps. + _discoverTemplateParentProps: function(content) { + var chain = content._parentPropChain = []; + content._annotes.forEach(function(n) { + // Find all bindings to parent.* and spread them into _parentPropChain + n.bindings.forEach(function(b) { + var m; + if (m = b.value.match(/parent\.((parent\.)*[^.]*)/)) { + var parts = m[1].split('.'); + for (var i=0; i path change on instance + _forwardParentProp: function(prop, value) { + if (this._instance) { + this._instance.parent[prop] = value; + this._instance.notifyPath('parent.' + prop, value, true); + } + }, + + // Implements extension point from Templatizer + // Called as side-effect of a host path change, responsible for + // notifying parent. path change on each row + _forwardParentPath: function(path, value) { + if (this._instance) { + this._instance.notifyPath('parent.' + path, value, true); + } } }); diff --git a/src/lib/template/x-repeat.html b/src/lib/template/x-repeat.html index 584ffbaa3d..74e968f8bd 100644 --- a/src/lib/template/x-repeat.html +++ b/src/lib/template/x-repeat.html @@ -195,7 +195,7 @@ _itemsChanged: function(items, old, path) { if (path) { - this._notifyElement(path, items); + this._forwardItemPath(path, items); this._checkObservedPaths(path); } else { if (old) { @@ -204,8 +204,8 @@ if (items) { this._observeCollection(items); this.debounce('render', this.render); - } - } + } + } }, _checkObservedPaths: function(path) { @@ -260,12 +260,13 @@ var key = keys[i]; var item = c.getItem(key); var row = this.rows[i]; + rowForKey[key] = i; if (!row) { this.rows.push(row = this._insertRow(i, null, item)); } row.item = item; row.key = key; - rowForKey[key] = i; + row.index = i; } // Remove extra for (; i. change up to host + _forwardInstancePath: function(row, root, subPath, value) { + if (root == 'item') { + this.notifyPath('items.' + row.key + '.' + subPath, value); + } + }, + + // Implements extension point from Templatizer mixin + // Called as side-effect of a host property change, responsible for + // notifying parent. path change on each row + _forwardParentProp: function(prop, value) { + if (this.rows) { + this.rows.forEach(function(row) { + row.parent[prop] = value; + row.notifyPath('parent.' + prop, value, true); + }, this); + } + }, + + // Implements extension point from Templatizer + // Called as side-effect of a host path change, responsible for + // notifying parent. path change on each row + _forwardParentPath: function(path, value) { + if (this.rows) { + this.rows.forEach(function(row) { + row.notifyPath('parent.' + path, value, true); + }, this); + } }, - _notifyElement: function(path, value) { + // Called as a side effect of a host items.. path change, + // responsible for notifying item. changes to row for key + _forwardItemPath: function(path, value) { if (this._rowForKey) { // 'items.'.length == 6 var dot = path.indexOf('.', 6); diff --git a/src/mini/ready.html b/src/mini/ready.html index 6af602c195..e73d2a58d3 100644 --- a/src/mini/ready.html +++ b/src/mini/ready.html @@ -1,180 +1,188 @@ - - + + diff --git a/src/standard/notify-path.html b/src/standard/notify-path.html index c6376cd708..5372921a98 100644 --- a/src/standard/notify-path.html +++ b/src/standard/notify-path.html @@ -1,260 +1,260 @@ - - - + + + \ No newline at end of file diff --git a/test/smoke/x-if.html b/test/smoke/x-if.html index 887f9e10b9..bdad8ee94e 100644 --- a/test/smoke/x-if.html +++ b/test/smoke/x-if.html @@ -23,19 +23,21 @@ }