Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Unified Diff: sky/framework/sky-element/sky-binder.sky

Issue 951673003: Remove outdated examples and framework pieces (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/framework/sky-element/observe.sky ('k') | sky/framework/sky-element/sky-element.sky » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/framework/sky-element/sky-binder.sky
diff --git a/sky/framework/sky-element/sky-binder.sky b/sky/framework/sky-element/sky-binder.sky
deleted file mode 100644
index bfef1ab86162231ac2ec85065e80eb031a9d4b5e..0000000000000000000000000000000000000000
--- a/sky/framework/sky-element/sky-binder.sky
+++ /dev/null
@@ -1,498 +0,0 @@
-<!--
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
--->
-<import src="observe.sky" as="observe" />
-<import src="element-registry.sky" as="registry" />
-
-<script>
-var stagingDocument = new Document();
-
-class TemplateInstance {
- constructor() {
- this.bindings = [];
- this.terminator = null;
- this.fragment = stagingDocument.createDocumentFragment();
- Object.preventExtensions(this);
- }
- close() {
- var bindings = this.bindings;
- for (var i = 0; i < bindings.length; i++) {
- bindings[i].close();
- }
- }
-}
-
-var emptyInstance = new TemplateInstance();
-var directiveCache = new WeakMap();
-
-function createInstance(template, model) {
- var content = template.content;
- if (!content.firstChild)
- return emptyInstance;
-
- var directives = directiveCache.get(content);
- if (!directives) {
- directives = new NodeDirectives(content);
- directiveCache.set(content, directives);
- }
-
- var instance = new TemplateInstance();
-
- var length = directives.children.length;
- for (var i = 0; i < length; ++i) {
- var clone = directives.children[i].createBoundClone(instance.fragment,
- model, instance.bindings);
-
- // The terminator of the instance is the clone of the last child of the
- // content. If the last child is an active template, it may produce
- // instances as a result of production, so simply collecting the last
- // child of the instance after it has finished producing may be wrong.
- if (i == length - 1)
- instance.terminator = clone;
- }
-
- return instance;
-}
-
-function sanitizeValue(value) {
- return value == null ? '' : value;
-}
-
-function updateText(node, value) {
- node.data = sanitizeValue(value);
-}
-
-function updateAttribute(element, name, value) {
- element.setAttribute(name, sanitizeValue(value));
-}
-
-class BindingExpression {
- constructor(prefix, path) {
- this.prefix = prefix;
- this.path = observe.Path.get(path);
- Object.preventExtensions(this);
- }
-}
-
-class PropertyDirective {
- constructor(name) {
- this.name = name;
- this.expressions = [];
- this.suffix = "";
- Object.preventExtensions(this);
- }
- createObserver(model) {
- var expressions = this.expressions;
- var suffix = this.suffix;
-
- if (expressions.length == 1 && expressions[0].prefix == "" && suffix == "")
- return new observe.PathObserver(model, expressions[0].path);
-
- var observer = new observe.CompoundObserver();
-
- for (var i = 0; i < expressions.length; ++i)
- observer.addPath(model, expressions[i].path);
-
- return new observe.ObserverTransform(observer, function(values) {
- var buffer = "";
- for (var i = 0; i < values.length; ++i) {
- buffer += expressions[i].prefix;
- buffer += values[i];
- }
- buffer += suffix;
- return buffer;
- });
- }
- bindProperty(node, model) {
- var name = this.name;
- var observable = this.createObserver(model);
- if (node instanceof Text) {
- updateText(node, observable.open(function(value) {
- return updateText(node, value);
- }));
- } else if (name == 'style' || name == 'class') {
- updateAttribute(node, name, observable.open(function(value) {
- updateAttribute(node, name, value);
- }));
- } else {
- node[name] = observable.open(function(value) {
- node[name] = value;
- });
- }
- if (typeof node.addPropertyBinding == 'function')
- node.addPropertyBinding(this.name, observable);
- return observable;
- }
-}
-
-function parsePropertyDirective(value, property) {
- if (!value || !value.length)
- return;
-
- var result;
- var offset = 0;
- var firstIndex = 0;
- var lastIndex = 0;
-
- while (offset < value.length) {
- firstIndex = value.indexOf('{{', offset);
- if (firstIndex == -1)
- break;
- lastIndex = value.indexOf('}}', firstIndex + 2);
- if (lastIndex == -1)
- lastIndex = value.length;
- var prefix = value.substring(offset, firstIndex);
- var path = value.substring(firstIndex + 2, lastIndex);
- offset = lastIndex + 2;
- if (!result)
- result = new PropertyDirective(property);
- result.expressions.push(new BindingExpression(prefix, path));
- }
-
- if (result && offset < value.length)
- result.suffix = value.substring(offset);
-
- return result;
-}
-
-function parseAttributeDirectives(element, directives) {
- var attributes = element.getAttributes();
- var tagName = element.tagName;
-
- for (var i = 0; i < attributes.length; i++) {
- var attr = attributes[i];
- var name = attr.name;
- var value = attr.value;
-
- if (name.startsWith('on-')) {
- directives.eventHandlers.push(name.substring(3));
- continue;
- }
-
- if (!registry.checkAttribute(tagName, name)) {
- console.error('Element "'+ tagName +
- '" has unknown attribute "' + name + '".');
- }
-
- var property = parsePropertyDirective(value, name);
- if (property)
- directives.properties.push(property);
- }
-}
-
-function createCloneSource(element, properties) {
- if (!properties.length)
- return element;
-
- // Leave attributes alone on template so you can see the if/repeat statements
- // in the inspector.
- if (element instanceof HTMLTemplateElement)
- return element;
-
- var result = element.cloneNode(false);
-
- for (var i = 0; i < properties.length; ++i) {
- result.removeAttribute(properties[i].name);
- }
-
- return result;
-}
-
-function eventHandlerCallback(event) {
- var element = event.currentTarget;
- var method = element.getAttribute('on-' + event.type);
- var scope = element.ownerScope;
- var host = scope.host;
- var handler = host && host[method];
- if (handler instanceof Function)
- return handler.call(host, event);
-}
-
-class NodeDirectives {
- constructor(node) {
- this.eventHandlers = [];
- this.children = [];
- this.properties = [];
- this.node = node;
- this.cloneSourceNode = node;
- Object.preventExtensions(this);
-
- if (node instanceof Element) {
- parseAttributeDirectives(node, this);
- this.cloneSourceNode = createCloneSource(node, this.properties);
- } else if (node instanceof Text) {
- var property = parsePropertyDirective(node.data, 'textContent');
- if (property)
- this.properties.push(property);
- }
-
- for (var child = node.firstChild; child; child = child.nextSibling) {
- this.children.push(new NodeDirectives(child));
- }
- }
- findProperty(name) {
- for (var i = 0; i < this.properties.length; ++i) {
- if (this.properties[i].name === name)
- return this.properties[i];
- }
- return null;
- }
- createBoundClone(parent, model, bindings) {
- // TODO(esprehn): In sky instead of needing to use a staging docuemnt per
- // custom element registry we're going to need to use the current module's
- // registry.
- var clone = stagingDocument.importNode(this.cloneSourceNode, false);
-
- for (var i = 0; i < this.eventHandlers.length; ++i) {
- clone.addEventListener(this.eventHandlers[i], eventHandlerCallback);
- }
-
- for (var i = 0; i < this.properties.length; ++i) {
- bindings.push(this.properties[i].bindProperty(clone, model));
- }
-
- parent.appendChild(clone);
-
- for (var i = 0; i < this.children.length; ++i) {
- this.children[i].createBoundClone(clone, model, bindings);
- }
-
- if (clone instanceof HTMLTemplateElement) {
- var iterator = new TemplateIterator(clone);
- iterator.updateDependencies(this, model);
- bindings.push(iterator);
- }
-
- return clone;
- }
-}
-
-var iterators = new WeakMap();
-
-class TemplateIterator {
- constructor(element) {
- this.closed = false;
- this.template = element;
- this.contentTemplate = null;
- this.instances = [];
- this.hasRepeat = false;
- this.ifObserver = null;
- this.valueObserver = null;
- this.iteratedValue = [];
- this.presentValue = null;
- this.arrayObserver = null;
- Object.preventExtensions(this);
- iterators.set(element, this);
- }
-
- updateDependencies(directives, model) {
- this.contentTemplate = directives.node;
-
- var ifValue = true;
- var ifProperty = directives.findProperty('if');
- if (ifProperty) {
- this.ifObserver = ifProperty.createObserver(model);
- ifValue = this.ifObserver.open(this.updateIfValue, this);
- }
-
- var repeatProperty = directives.findProperty('repeat');
- if (repeatProperty) {
- this.hasRepeat = true;
- this.valueObserver = repeatProperty.createObserver(model);
- } else {
- var path = observe.Path.get("");
- this.valueObserver = new observe.PathObserver(model, path);
- }
-
- var value = this.valueObserver.open(this.updateIteratedValue, this);
- this.updateValue(ifValue ? value : null);
- }
-
- getUpdatedValue() {
- return this.valueObserver.discardChanges();
- }
-
- updateIfValue(ifValue) {
- if (!ifValue) {
- this.valueChanged();
- return;
- }
-
- this.updateValue(this.getUpdatedValue());
- }
-
- updateIteratedValue(value) {
- if (this.ifObserver) {
- var ifValue = this.ifObserver.discardChanges();
- if (!ifValue) {
- this.valueChanged();
- return;
- }
- }
-
- this.updateValue(value);
- }
-
- updateValue(value) {
- if (!this.hasRepeat)
- value = [value];
- var observe = this.hasRepeat && Array.isArray(value);
- this.valueChanged(value, observe);
- }
-
- valueChanged(value, observeValue) {
- if (!Array.isArray(value))
- value = [];
-
- if (value === this.iteratedValue)
- return;
-
- this.unobserve();
- this.presentValue = value;
- if (observeValue) {
- this.arrayObserver = new observe.ArrayObserver(this.presentValue);
- this.arrayObserver.open(this.handleSplices, this);
- }
-
- this.handleSplices(observe.ArrayObserver.calculateSplices(this.presentValue,
- this.iteratedValue));
- }
-
- getLastInstanceNode(index) {
- if (index == -1)
- return this.template;
- var instance = this.instances[index];
- var terminator = instance.terminator;
- if (!terminator)
- return this.getLastInstanceNode(index - 1);
-
- if (!(terminator instanceof Element) || this.template === terminator) {
- return terminator;
- }
-
- var subtemplateIterator = iterators.get(terminator);
- if (!subtemplateIterator)
- return terminator;
-
- return subtemplateIterator.getLastTemplateNode();
- }
-
- getLastTemplateNode() {
- return this.getLastInstanceNode(this.instances.length - 1);
- }
-
- insertInstanceAt(index, instance) {
- var previousInstanceLast = this.getLastInstanceNode(index - 1);
- var parent = this.template.parentNode;
- this.instances.splice(index, 0, instance);
- parent.insertBefore(instance.fragment, previousInstanceLast.nextSibling);
- }
-
- extractInstanceAt(index) {
- var previousInstanceLast = this.getLastInstanceNode(index - 1);
- var lastNode = this.getLastInstanceNode(index);
- var parent = this.template.parentNode;
- var instance = this.instances.splice(index, 1)[0];
-
- while (lastNode !== previousInstanceLast) {
- var node = previousInstanceLast.nextSibling;
- if (node == lastNode)
- lastNode = previousInstanceLast;
-
- instance.fragment.appendChild(parent.removeChild(node));
- }
-
- return instance;
- }
-
- handleSplices(splices) {
- if (this.closed || !splices.length)
- return;
-
- var template = this.template;
-
- if (!template.parentNode) {
- this.close();
- return;
- }
-
- observe.ArrayObserver.applySplices(this.iteratedValue, this.presentValue,
- splices);
-
- // Instance Removals
- var instanceCache = new Map;
- var removeDelta = 0;
- for (var i = 0; i < splices.length; i++) {
- var splice = splices[i];
- var removed = splice.removed;
- for (var j = 0; j < removed.length; j++) {
- var model = removed[j];
- var instance = this.extractInstanceAt(splice.index + removeDelta);
- if (instance !== emptyInstance) {
- instanceCache.set(model, instance);
- }
- }
-
- removeDelta -= splice.addedCount;
- }
-
- // Instance Insertions
- for (var i = 0; i < splices.length; i++) {
- var splice = splices[i];
- var addIndex = splice.index;
- for (; addIndex < splice.index + splice.addedCount; addIndex++) {
- var model = this.iteratedValue[addIndex];
- var instance = instanceCache.get(model);
- if (instance) {
- instanceCache.delete(model);
- } else {
- if (model === undefined || model === null) {
- instance = emptyInstance;
- } else {
- instance = createInstance(this.contentTemplate, model);
- }
- }
-
- this.insertInstanceAt(addIndex, instance);
- }
- }
-
- instanceCache.forEach(function(instance) {
- instance.close();
- });
- }
-
- unobserve() {
- if (!this.arrayObserver)
- return;
-
- this.arrayObserver.close();
- this.arrayObserver = null;
- }
-
- close() {
- if (this.closed)
- return;
- this.unobserve();
- for (var i = 0; i < this.instances.length; i++) {
- this.instances[i].close();
- }
-
- this.instances.length = 0;
-
- if (this.ifObserver)
- this.ifObserver.close();
- if (this.valueObserver)
- this.valueObserver.close();
-
- iterators.delete(this.template);
- this.closed = true;
- }
-}
-
-module.exports = {
- createInstance: createInstance,
-};
-</script>
« no previous file with comments | « sky/framework/sky-element/observe.sky ('k') | sky/framework/sky-element/sky-element.sky » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698