mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
146 lines
5.1 KiB
HTML
146 lines
5.1 KiB
HTML
<!--
|
|
@license
|
|
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
Code distributed by Google as part of the polymer project is also
|
|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
-->
|
|
<script>
|
|
|
|
using(['bind'], function(Bind) {
|
|
|
|
Bind.addComputedPropertyEffect = function(model, name, expression) {
|
|
var index = expression.indexOf('(');
|
|
var method = expression.slice(0, index);
|
|
var args = expression.slice(index + 1, -1).replace(/ /g, '').split(',');
|
|
//console.log('%c on [%s] compute [%s] via [%s]', 'color: green', args[0], name, method);
|
|
this.addPropertyEffect(model, args[0], 'compute', {
|
|
property: name,
|
|
method: method
|
|
});
|
|
};
|
|
|
|
Bind._notifyChange = function(property) {
|
|
this.fire(property + '-changed', {value: this[property]}, null, false);
|
|
};
|
|
|
|
Bind._shouldAddListener = function(info) {
|
|
return info.name &&
|
|
info.mode === '{' &&
|
|
!info.negate &&
|
|
info.kind != 'attribute';
|
|
};
|
|
|
|
Bind.addBuilders({
|
|
|
|
method: function(model, source, effect) {
|
|
// TODO(sjmiles): validation system requires a blessed
|
|
// validator effect which needs to be processed first.
|
|
/*
|
|
if (typeof this[effect] === 'function') {
|
|
return [
|
|
'var validated = this.' + effect + '(value, old)',
|
|
'if (validated !== undefined) {',
|
|
' // recurse',
|
|
' this[property] = validated;',
|
|
' return;',
|
|
'}'
|
|
].join('\n');
|
|
}
|
|
*/
|
|
//
|
|
return 'this.' + effect + '(this._data.' + source + ', old);'
|
|
},
|
|
|
|
// basic modus operandi
|
|
//
|
|
// <hostPath> %=% <targetPath>
|
|
// (node = <$.id | nodes[index]>)
|
|
// <model[.path]> %=% node.<property>
|
|
//
|
|
// flow-up:
|
|
// set(model): node.<property> = <model[.path]>
|
|
//
|
|
// flow-down:
|
|
// node.on.<property>-changed: <model[.path]> = e.detail.value
|
|
notify: function(model, source) {
|
|
model._notifyChange = Bind._notifyChange;
|
|
return 'this._notifyChange(\'' + source + '\')';
|
|
},
|
|
|
|
compute: function(model, source, effect) {
|
|
return 'this.' + effect.property
|
|
+ ' = this.' + effect.method + '(this._data.' + source + ');';
|
|
},
|
|
|
|
reflect: function(model, source) {
|
|
return 'this.reflectPropertyToAttribute(\'' + source + '\');';
|
|
},
|
|
|
|
// implement effect directives from template annotations
|
|
// _nodes[info.index][info.name] = {{info.value}}
|
|
annotation: function(model, hostProperty, info) {
|
|
var property = info.name;
|
|
if (Bind._shouldAddListener(info)) {
|
|
// <node>.on.<property>-changed: <path> = e.detail.value
|
|
Bind._addAnnotatedListener(model, info.index, property, info.value);
|
|
}
|
|
//
|
|
if (!property) {
|
|
property = 'textContent';
|
|
}
|
|
if (property === 'style') {
|
|
property = 'style.cssText';
|
|
}
|
|
//
|
|
// flow-down
|
|
//
|
|
// construct the effect to occur when [property] changes:
|
|
// set nodes[index][name] to this[value]
|
|
//
|
|
//console.log('[_annotationEffectBuilder]: [%s] %=% [%s].[%s]', info.value, info.index, property);
|
|
var parts = info.value.split('.');
|
|
var value, setData;
|
|
if (parts.length <= 1) {
|
|
setData = '';
|
|
value = 'this._data.' + info.value;
|
|
} else {
|
|
// Null check intermediate paths
|
|
var last = parts.pop();
|
|
var curr = 'this._data';
|
|
parts = parts.map(function(s) {
|
|
return curr += ('.' + s);
|
|
});
|
|
value = parts.join('!=null && ')
|
|
+ '!=null ? '
|
|
+ curr + '.' + last
|
|
+ ' : undefined'
|
|
;
|
|
// TODO(kschaaf): Update private storage for this path, for dirty-checking
|
|
// path notifications on their way up; could have been made separate PropertyEffect,
|
|
// but is coupled to (required for) path listeners to function, which is already
|
|
// bound to the annotation propertyEffect, so ROI is low
|
|
setData =
|
|
'var val = ' + value + ';\n' +
|
|
'this._data[\'' + info.value + '\'] = val;\n'
|
|
;
|
|
value = 'val';
|
|
}
|
|
value = (info.negate ? '!' : '') + value;
|
|
var node = 'this._nodes[' + info.index + ']';
|
|
if (info.kind == 'property') {
|
|
return setData + node + '.' + property + ' = ' + value + ';';
|
|
} else {
|
|
return setData + 'this.serializeValueToAttribute(' + value + ',' +
|
|
'\'' + property + '\',' + node + ');';
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
</script>
|