UNPKG

polymer-analyzer

Version:
159 lines (145 loc) 4.83 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 --> <script> /** * Automatically extend using objects referenced in `behaviors` array. * * someBehaviorObject = { * accessors: { * value: {type: Number, observer: '_numberChanged'} * }, * observers: [ * // ... * ], * ready: function() { * // called before prototoype's ready * }, * _numberChanged: function() {} * }; * * Polymer({ * * behaviors: [ * someBehaviorObject * ] * * ... * * }); * * @class base feature: behaviors */ Polymer.Base._addFeature({ /** * Array of objects to extend this prototype with. * * Each entry in the array may specify either a behavior object or array * of behaviors. * * Each behavior object may define lifecycle callbacks, `properties`, * `hostAttributes`, `observers` and `listeners`. * * Lifecycle callbacks will be called for each behavior in the order given * in the `behaviors` array, followed by the callback on the prototype. * Additionally, any non-lifecycle functions on the behavior object are * mixed into the base prototype, such that same-named functions on the * prototype take precedence, followed by later behaviors over earlier * behaviors. */ behaviors: [], _desugarBehaviors: function() { if (this.behaviors.length) { this.behaviors = this._desugarSomeBehaviors(this.behaviors); } }, _desugarSomeBehaviors: function(behaviors) { var behaviorSet = []; // iteration 1 behaviors = this._flattenBehaviorsList(behaviors); // iteration 2 // traverse the behaviors in _reverse_ order (youngest first) because // `_mixinBehavior` has _first property wins_ behavior, this is done // to optimize # of calls to `_copyOwnProperty` for (var i=behaviors.length-1; i>=0; i--) { var b = behaviors[i]; if (behaviorSet.indexOf(b) === -1) { this._mixinBehavior(b); behaviorSet.unshift(b); } } return behaviorSet; }, _flattenBehaviorsList: function(behaviors) { var flat = []; for (var i=0; i < behaviors.length; i++) { var b = behaviors[i]; if (b instanceof Array) { flat = flat.concat(this._flattenBehaviorsList(b)); } // filter out null entries so other iterators don't need to check else if (b) { flat.push(b); } else { this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for missing or 404 import')); } } return flat; }, _mixinBehavior: function(b) { var n$ = Object.getOwnPropertyNames(b); var useAssignment = b._noAccessors; for (var i=0, n; (i<n$.length) && (n=n$[i]); i++) { if (!Polymer.Base._behaviorProperties[n] && !this.hasOwnProperty(n)) { if (useAssignment) { this[n] = b[n]; } else { this.copyOwnProperty(n, b, this); } } } }, _prepBehaviors: function() { this._prepFlattenedBehaviors(this.behaviors); }, _prepFlattenedBehaviors: function(behaviors) { // iteration 3 // `_prepBehavior` goes in natural order // otherwise, it's a tricky detail for implementors of `_prepBehavior` for (var i=0, l=behaviors.length; i<l; i++) { this._prepBehavior(behaviors[i]); } // prep our prototype-as-behavior this._prepBehavior(this); }, _marshalBehaviors: function() { for (var i=0; i < this.behaviors.length; i++) { this._marshalBehavior(this.behaviors[i]); } this._marshalBehavior(this); } }); // special properties on behaviors are not mixed in and are instead // either processed specially (e.g. listeners, properties) or available // for calling via doBehavior (e.g. created, ready) Polymer.Base._behaviorProperties = { hostAttributes: true, beforeRegister: true, registered: true, properties: true, observers: true, listeners: true, created: true, attached: true, detached: true, attributeChanged: true, ready: true, _noAccessors: true } </script>