Skip to content

Commit

Permalink
Use property effects to notify path changes upwards.
Browse files Browse the repository at this point in the history
  • Loading branch information
kaste committed Apr 21, 2016
1 parent 6d24b87 commit f9d64e1
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 22 deletions.
33 changes: 23 additions & 10 deletions src/lib/bind/accessors.html
Original file line number Diff line number Diff line change
Expand Up @@ -272,20 +272,33 @@
setupBindListeners: function(inst) {
var b$ = inst._bindListeners;
for (var i=0, l=b$.length, info; (i<l) && (info=b$[i]); i++) {
// Property listeners:
// <node>.on.<property>-changed: <path]> = e.detail.value
//console.log('[_setupBindListener]: [%s][%s] listening for [%s][%s-changed]', this.localName, info.path, info.id || info.index, info.property);
//
// TODO(sorvell): fix templatizer to support this before uncommenting
// Optimization: only add bind listeners if the bound property is notifying...
// TODO: Optimization: only add bind listeners if the bound property
// is notifying...
var node = inst._nodes[info.index];
//var p = node._propertyInfo && node._propertyInfo[info.property];
//if (node._prepParentProperties || !node._propertyInfo || (p && p.notify)) {
this._addNotifyListener(node, inst, info.event, info.changedFn);
//}
// Add DOM Event listener
this._addNotifyListener(node, inst, info.event, info.changedFn);
// For path notifications add a property effect
if (node.addPropertyEffect) {
this._addNotifyEffect(node, inst, info.property, info.changedFn);
}
}
},

_addNotifyEffect: function(node, instance, property, fn) {
node.addPropertyEffect(property, function(path, value, old, fromAbove) {
if (!fromAbove && path.indexOf('.') !== -1) {
var ev = {
target: this,
detail: {
path: path,
value: value
}
};
instance._notifyListener(fn, ev);
}
});
},

// TODO(sorvell): note, adding these synchronously may impact performance,
// measure and consider if we can defer until after first paint in some cases at least.
_addNotifyListener: function(element, context, event, changedFn) {
Expand Down
71 changes: 68 additions & 3 deletions src/lib/template/templatizer.html
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@
// Create accessors for each parent prop that forward the property to
// template instances through abstract _forwardParentProp/Path API
// that should be implemented by Templatizer users.
var propertyEffects = this.mixin({}, this._propertyEffects);
var propertyEffects = {};
var propertyInfo = this.mixin({}, this._propertyInfo);
var prefixedParentProps = {};
for (prop in parentProps) {
Expand All @@ -251,6 +251,15 @@
effect: {event:
Polymer.CaseMap.camelToDashCase(parentProp) + '-changed'}
}];
if (template !== this) {
effects.push({
kind: 'function',
effect: this._createNotifyUpListener(prop),
fn: Polymer.Bind._functionEffect,
pathFn: this._functionPathEffect,
customNotifyUp: true
});
}
propertyEffects[parentProp] = effects;
propertyInfo[parentProp] = {};
prefixedParentProps[parentProp] = true;
Expand Down Expand Up @@ -283,6 +292,33 @@
}
},

_createNotifyUpListener: function(prop) {
// We simulate something like the following upwards annotation:
//
// <x-host> <---|
// <x-templatizer> |
// <template _parent_prop="{{prop}}"> --|
// ...content...
// The template sends a notification upwards directly to the host
// (skipping (this) templatizer).
var prefix = this._parentPropPrefix;
// translate: _parent_prop -> prop
var fn = Polymer.Bind._notedListenerFactory(prefix + prop, prop, false);
return function(path, value, old, fromAbove) {
if (!fromAbove && path.indexOf('.') !== -1) {
var ev = {
target: this,
detail: {
path: path,
value: value
}
};
// This effect is memoized, so we cannot prestore the host.
var host = this.parentElement.dataHost;
host._notifyListener(fn, ev);
}
}
},

_createForwardPropEffector: function(prop) {
var prefixLength = this._parentPropPrefix.length;
Expand All @@ -299,6 +335,15 @@
},

_createHostPropEffector: function(prop) {
// Essentially a custom notify up implementation, but has to notify
// sidewards b/c of the following DOM structure:
//
// <x-templatizer>
// <TemplateInstance> --|
// <template> <-|
// A concrete TemplateInstance sends a notification to the template
// (class or type).
// Translate: prop -> _parent_prop
var prefix = this._parentPropPrefix;
var prefixedProp = prefix + prop;
return function(path, value, old, fromAbove) {
Expand All @@ -325,9 +370,11 @@
};
},

// Extends template with parent property info & effects and seed pre-bound data
// Extends template with parent property info & effects and seed pre-bound
// data
_extendTemplate: function(template, proto) {
template._propertyEffects = proto._propertyEffects;
template._propertyEffects = this._mixPropertyEffects(
template._propertyEffects, proto._propertyEffects);
template._propertyInfo = proto._propertyInfo;
var prefixedParentProps = proto.prefixedParentProps;
for (var p in prefixedParentProps) {
Expand All @@ -336,6 +383,24 @@
}
},

_mixPropertyEffects: function(target, source) {
// target = target ? Polymer.Base.chainObject({}, target) : {};
if (!target) {
target = {};
}
for (var prop in source) {
var effects = source[prop];
if (prop in target) {
// inplace concat instead?
target[prop] = target[prop].concat(effects);
} else {
// slice to get shallow copy?
target[prop] = effects;
}
}
return target;
},

// Extension points for Templatizer sub-classes
/* eslint-disable no-unused-vars */
_showHideChildren: function(hidden) { },
Expand Down
9 changes: 0 additions & 9 deletions src/standard/notify-path.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,9 @@
if (typeof value == 'object') {
this._clearPath(path);
}
// console.group((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value);
// Take path effects at this level for exact path matches,
// and notify down for any bindings to a subset of this path
this._pathEffector(path, value, fromAbove, origin, originalProperty);
// Send event to notify the path change upwards
// Optimization: don't notify up if we know the notification
// is coming from above already (avoid wasted event dispatch)
if (!fromAbove) {
// TODO(sorvell): should only notify if notify: true?
this._notifyPathUp(path, value);
}
// console.groupEnd((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value);
return true;
}
},
Expand Down

0 comments on commit f9d64e1

Please sign in to comment.