UNPKG

five-bells-visualization

Version:
212 lines (188 loc) 7.1 kB
<!-- @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 --> <link rel="import" href="../lib/bind/accessors.html"> <link rel="import" href="../lib/bind/effects.html"> <script> /** * Support for property side effects. * * Key for effect objects: * * property | ann | anCmp | cmp | obs | cplxOb | description * ---------|-----|-------|-----|-----|--------|---------------------------------------- * method | | X | X | X | X | function name to call on instance * args | | X | X | | X | list of all arg descriptors for fn * arg | | X | X | | X | arg descriptor for effect * property | | | X | X | | property for effect to set or get * name | X | | | | | annotation value (text inside {{...}}) * kind | X | X | | | | binding type (property or attribute) * index | X | X | | | | node index to set * */ Polymer.Base._addFeature({ _addPropertyEffect: function(property, kind, effect) { // TODO(sjmiles): everything to the right of the first '.' is lost, implies // there is some duplicate information flow (not the only sign) var model = property.split('.').shift(); Polymer.Bind.addPropertyEffect(this, model, kind, effect); }, // prototyping _prepEffects: function() { Polymer.Bind.prepareModel(this); this._addAnnotationEffects(this._notes); }, _prepBindings: function() { Polymer.Bind.createBindings(this); }, _addPropertyEffects: function(effects) { if (effects) { for (var n in effects) { var effect = effects[n]; if (effect.observer) { this._addObserverEffect(n, effect.observer); } if (effect.computed) { this._addComputedEffect(n, effect.computed); } if (effect.notify) { this._addPropertyEffect(n, 'notify'); } if (effect.reflectToAttribute) { this._addPropertyEffect(n, 'reflect'); } if (this.isReadOnlyProperty(n)) { // Ensure accessor is created Polymer.Bind.ensurePropertyEffects(this, n); } } } }, _parseMethod: function(expression) { var m = expression.match(/(\w*)\((.*)\)/); if (m) { return { method: m[1], args: m[2].split(/[^\w.*]+/).map(this._parseArg) }; } }, _parseArg: function(arg) { var a = { name: arg }; a.structured = arg.indexOf('.') > 0; if (a.structured) { a.wildcard = (arg.slice(-2) == '.*'); if (a.wildcard) { a.name = arg.slice(0, -2); } } return a; }, _addComputedEffect: function(name, expression) { var sig = this._parseMethod(expression); sig.args.forEach(function(arg) { this._addPropertyEffect(arg.name, 'compute', { method: sig.method, args: sig.args, arg: arg, property: name }); }, this); }, _addObserverEffect: function(property, observer) { this._addPropertyEffect(property, 'observer', { method: observer, property: property }); }, _addComplexObserverEffects: function(observers) { if (observers) { observers.forEach(function(observer) { this._addComplexObserverEffect(observer); }, this); } }, _addComplexObserverEffect: function(observer) { var sig = this._parseMethod(observer); sig.args.forEach(function(arg) { this._addPropertyEffect(arg.name, 'complexObserver', { method: sig.method, args: sig.args, arg: arg }); }, this); }, _addAnnotationEffects: function(notes) { // create a virtual annotation list, must be concretized at instance time this._nodes = []; // process annotations that have been parsed from template notes.forEach(function(note) { // where to find the node in the concretized list var index = this._nodes.push(note) - 1; note.bindings.forEach(function(binding) { this._addAnnotationEffect(binding, index); }, this); }, this); }, _addAnnotationEffect: function(note, index) { // TODO(sjmiles): annotations have 'effects' proper and 'listener' if (Polymer.Bind._shouldAddListener(note)) { // <node>.on.<dash-case-property>-changed: <path> = e.detail.value Polymer.Bind._addAnnotatedListener(this, index, note.name, note.value, note.event); } var sig = this._parseMethod(note.value); if (sig) { this._addAnnotatedComputationEffect(sig, note, index); } else { // capture the node index note.index = index; // discover top-level property (model) from path var model = note.value.split('.').shift(); // add 'annotation' binding effect for property 'model' this._addPropertyEffect(model, 'annotation', note); } }, _addAnnotatedComputationEffect: function(sig, note, index) { sig.args.forEach(function(arg) { this._addPropertyEffect(arg.name, 'annotatedComputation', { kind: note.kind, method: sig.method, args: sig.args, arg: arg, property: note.name, index: index }); }, this); }, // instancing _marshalInstanceEffects: function() { Polymer.Bind.prepareInstance(this); Polymer.Bind.setupBindListeners(this); }, _applyEffectValue: function(value, info) { var node = this._nodes[info.index]; // TODO(sorvell): ideally, the info object is normalized for easy // lookup here. var property = info.property || info.name || 'textContent'; // special processing for 'class' and 'className'; 'class' handled // when attr is serialized. if (info.kind == 'attribute') { this.serializeValueToAttribute(value, property, node); } else { // TODO(sorvell): consider pre-processing this step so we don't need // this lookup. if (property === 'className') { value = this._scopeElementClass(node, value); } return node[property] = value; } } }); </script>