blob: fe6f9e6c611db4ba0ba485d9572a4521ab3e83c3 [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of template_binding;
/** Extensions to the [Node] API. */
class NodeBindExtension {
final Node _node;
/**
* Gets the data bindings that are associated with this node, if any.
*
* This starts out null, and if [enableBindingsReflection] is enabled, calls
* to [bind] will initialize this field and the binding.
*/
// Dart note: in JS this has a trailing underscore, meaning "private".
// But in dart if we made it _bindings, it wouldn't be accessible at all.
// It is unfortunately needed to implement Node.bind correctly.
Map<String, Bindable> bindings;
NodeBindExtension._(this._node);
/**
* Binds the attribute [name] to the [path] of the [model].
* Path is a String of accessors such as `foo.bar.baz`.
* Returns the [Bindable] instance.
*/
Bindable bind(String name, value, {bool oneTime: false}) {
// TODO(jmesserly): in Dart we could deliver an async error, which would
// have a similar affect but be reported as a test failure. Should we?
window.console.error('Unhandled binding to Node: '
'$this $name $value $oneTime');
return null;
}
/**
* Called when all [bind] calls are finished for a given template expansion.
*/
void bindFinished() {}
/**
* Dispatch support so custom HtmlElement's can override these methods.
*
* A public method like [this.bind] should not call another public method.
*
* Instead it should dispatch through [_self] to give the "overridden" method
* a chance to intercept.
*/
NodeBindExtension get _self => _node is NodeBindExtension ? _node : this;
TemplateInstance _templateInstance;
/** Gets the template instance that instantiated this node, if any. */
TemplateInstance get templateInstance =>
_templateInstance != null ? _templateInstance :
(_node.parent != null ? nodeBind(_node.parent).templateInstance : null);
_open(Bindable bindable, callback(value)) =>
callback(bindable.open(callback));
Bindable _maybeUpdateBindings(String name, Bindable binding) {
return enableBindingsReflection ? _updateBindings(name, binding) : binding;
}
Bindable _updateBindings(String name, Bindable binding) {
if (bindings == null) bindings = {};
var old = bindings[name];
if (old != null) old.close();
return bindings[name] = binding;
}
}
/** Information about the instantiated template. */
class TemplateInstance {
// TODO(rafaelw): firstNode & lastNode should be read-synchronous
// in cases where script has modified the template instance boundary.
/** The first node of this template instantiation. */
Node get firstNode => _firstNode;
/**
* The last node of this template instantiation.
* This could be identical to [firstNode] if the template only expanded to a
* single node.
*/
Node get lastNode => _lastNode;
/** The model used to instantiate the template. */
final model;
Node _firstNode, _lastNode;
TemplateInstance(this.model);
}