/* * 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 */ (function(scope) { /** * @class polymer-base */ // imports var log = window.WebComponents ? WebComponents.flags.log : {}; // element api supporting mdv var mdv = { /** * Creates dom cloned from the given template, instantiating bindings * with this element as the template model and `PolymerExpressions` as the * binding delegate. * * @method instanceTemplate * @param {Template} template source template from which to create dom. */ instanceTemplate: function(template) { // ensure template is decorated (lets' things like work) HTMLTemplateElement.decorate(template); // ensure a default bindingDelegate var syntax = this.syntax || (!template.bindingDelegate && this.element.syntax); var dom = template.createInstance(this, syntax); var observers = dom.bindings_; for (var i = 0; i < observers.length; i++) { this.registerObserver(observers[i]); } return dom; }, // Called by TemplateBinding/NodeBind to setup a binding to the given // property. It's overridden here to support property bindings // in addition to attribute bindings that are supported by default. bind: function(name, observable, oneTime) { var property = this.propertyForAttribute(name); if (!property) { // TODO(sjmiles): this mixin method must use the special form // of `super` installed by `mixinMethod` in declaration/prototype.js return this.mixinSuper(arguments); } else { // use n-way Polymer binding var observer = this.bindProperty(property, observable, oneTime); // NOTE: reflecting binding information is typically required only for // tooling. It has a performance cost so it's opt-in in Node.bind. if (Platform.enableBindingsReflection && observer) { observer.path = observable.path_; this._recordBinding(property, observer); } if (this.reflect[property]) { this.reflectPropertyToAttribute(property); } return observer; } }, _recordBinding: function(name, observer) { this.bindings_ = this.bindings_ || {}; this.bindings_[name] = observer; }, // Called by TemplateBinding when all bindings on an element have been // executed. This signals that all element inputs have been gathered // and it's safe to ready the element, create shadow-root and start // data-observation. bindFinished: function() { this.makeElementReady(); }, // called at detached time to signal that an element's bindings should be // cleaned up. This is done asynchronously so that users have the chance // to call `cancelUnbindAll` to prevent unbinding. asyncUnbindAll: function() { if (!this._unbound) { log.unbind && console.log('[%s] asyncUnbindAll', this.localName); this._unbindAllJob = this.job(this._unbindAllJob, this.unbindAll, 0); } }, /** * This method should rarely be used and only if * `cancelUnbindAll` has been called to * prevent element unbinding. In this case, the element's bindings will * not be automatically cleaned up and it cannot be garbage collected * by the system. If memory pressure is a concern or a * large amount of elements need to be managed in this way, `unbindAll` * can be called to deactivate the element's bindings and allow its * memory to be reclaimed. * * @method unbindAll */ unbindAll: function() { if (!this._unbound) { this.closeObservers(); this.closeNamedObservers(); this._unbound = true; } }, /** * Call in `detached` to prevent the element from unbinding when it is * detached from the dom. The element is unbound as a cleanup step that * allows its memory to be reclaimed. * If `cancelUnbindAll` is used, consider calling * `unbindAll` when the element is no longer * needed. This will allow its memory to be reclaimed. * * @method cancelUnbindAll */ cancelUnbindAll: function() { if (this._unbound) { log.unbind && console.warn('[%s] already unbound, cannot cancel unbindAll', this.localName); return; } log.unbind && console.log('[%s] cancelUnbindAll', this.localName); if (this._unbindAllJob) { this._unbindAllJob = this._unbindAllJob.stop(); } } }; function unbindNodeTree(node) { forNodeTree(node, _nodeUnbindAll); } function _nodeUnbindAll(node) { node.unbindAll(); } function forNodeTree(node, callback) { if (node) { callback(node); for (var child = node.firstChild; child; child = child.nextSibling) { forNodeTree(child, callback); } } } var mustachePattern = /\{\{([^{}]*)}}/; // exports scope.bindPattern = mustachePattern; scope.api.instance.mdv = mdv; })(Polymer);