UNPKG

five-bells-visualization

Version:
184 lines (160 loc) 6.36 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> /* Process inputs efficiently via a configure lifecycle callback. Configure is called top-down, host before local dom. Users should implement configure to supply a set of default values for the element by returning an object containing the properties and values to set. Configured values are not immediately set, instead they are set when an element becomes ready, after its local dom is ready. This ensures that any user change handlers are not called before ready time. */ /* Implementation notes: Configured values are collected into _config. At ready time, properties are set to the values in _config. This ensures properties are set child before host and change handlers are called only at ready time. The host will reset a value already propagated to a child, but this is not inefficient because of dirty checking at the set point. Bind notification events are sent when properties are set at ready time and thus received by the host before it is ready. Since notifications result in property updates and this triggers side effects, handling notifications is deferred until ready time. In general, events can be heard before an element is ready. This may occur when a user sends an event in a change handler or listens to a data event directly (on-foo-changed). */ Polymer.Base._addFeature({ // storage for configuration _setupConfigure: function(initialConfig) { this._config = initialConfig || {}; this._handlers = []; }, // static attributes are deserialized into _config _takeAttributes: function() { this._takeAttributesToModel(this._config); }, // at configure time values are stored in _config _configValue: function(name, value) { this._config[name] = value; }, // Override polymer-mini thunk _beforeClientsReady: function() { this._configure(); }, // configure: returns user supplied default property values // combines with _config to create final property values _configure: function() { this._configureAnnotationReferences(); // get individual default values from property configs var config = {}; this._configureProperties(this.properties, config); // behave! this.behaviors.forEach(function(b) { this._configureProperties(b.properties, config); }, this); // get add'l default values from central configure // combine defaults returned from configure with inputs in _config this._mixinConfigure(config, this._config); // this is the new _config, which are the final values to be applied this._config = config; // pass configuration data to bindings this._distributeConfig(this._config); }, _configureProperties: function(properties, config) { for (i in properties) { var c = properties[i]; if (c.value !== undefined) { var value = c.value; if (typeof value == 'function') { // pass existing config values (this._config) to value function value = value.call(this, this._config); } config[i] = value; } } }, _mixinConfigure: function(a, b) { for (var prop in b) { if (!this.isReadOnlyProperty(prop)) { a[prop] = b[prop]; } } }, // distribute config values to bound nodes. _distributeConfig: function(config) { var fx$ = this._propertyEffects; if (fx$) { for (var p in config) { var fx = fx$[p]; if (fx) { for (var i=0, l=fx.length, x; (i<l) && (x=fx[i]); i++) { if (x.kind === 'annotation') { var node = this._nodes[x.effect.index]; // seeding configuration only if (node._configValue) { var value = (p === x.effect.value) ? config[p] : this.getPathValue(x.effect.value, config); node._configValue(x.effect.name, value); } } } } } } }, // Override polymer-mini thunk _afterClientsReady: function() { this._applyConfig(this._config); this._flushHandlers(); }, // NOTE: values are already propagated to children via // _distributeConfig so propagation triggered by effects here is // redundant, but safe due to dirty checking _applyConfig: function(config) { for (var n in config) { // Don't stomp on values that may have been set by other side effects if (this[n] === undefined) { // Call _propertySet for any properties with accessors, which will // initialize read-only properties also // TODO(kschaaf): consider passing fromAbove here to prevent // unnecessary notify for: 1) possible perf, 2) debuggability var effects = this._propertyEffects[n]; if (effects) { this._propertySet(n, config[n], effects); } else { this[n] = config[n]; } } } }, // NOTE: Notifications can be processed before ready since // they are sent at *child* ready time. Since notifications cause side // effects and side effects must not be processed before ready time, // handling is queue/defered until then. _notifyListener: function(fn, e) { if (!this._clientsReadied) { this._queueHandler([fn, e, e.target]); } else { return fn.call(this, e, e.target); } }, _queueHandler: function(args) { this._handlers.push(args); }, _flushHandlers: function() { var h$ = this._handlers; for (var i=0, l=h$.length, h; (i<l) && (h=h$[i]); i++) { h[0].call(this, h[1], h[2]); } } }); </script>