Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Merge pull request #135 from Polymer/master
Browse files Browse the repository at this point in the history
8/8 master -> stable
  • Loading branch information
dfreedm committed Aug 8, 2013
2 parents c126ab8 + 60d98f1 commit d70eb8d
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 441 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ _Using `<template>` to produce DOM structures:_

MDV is designed to as two primitives which could eventually become standardized and implemented natively in browsers. The following two documents specify their behavior, API and use.

* [`Node.bind`](https://github.com/Polymer/mdv/blob/master/docs/node_bind.md): Which describes how DOM nodes are bound to data values
* [`<template>` instantiation](https://github.com/Polymer/mdv/blob/master/docs/template.md): Which describes how `<template>` manages instance fragments.
* [`Node.bind`](http://www.polymer-project.org/platform/mdv/node_bind.html): Which describes how DOM nodes are bound to data values
* [`<template>` instantiation](http://www.polymer-project.org/platform/mdv/template.html): Which describes how `<template>` manages instance fragments.

### Extending MDV

MDV is mainly concerned with being robust and efficient in interacting with application data and keeping the DOM in sync , but more advanced behaviors can be accomplished via one or both of the following:

* [A Binding Delegate API](https://github.com/Polymer/mdv/blob/master/docs/syntax_api.md)
* [Expression Syntax](https://github.com/Polymer/mdv/blob/master/docs/expression_syntax.md)
* [A Binding Delegate API](http://www.polymer-project.org/platform/mdv/syntax_api.html)
* [Expression Syntax](http://www.polymer-project.org/platform/mdv/expression_syntax.html)

### Advanced Topics

Expand Down
98 changes: 2 additions & 96 deletions docs/expression_syntax.md
Original file line number Diff line number Diff line change
@@ -1,99 +1,5 @@
## Expression Syntax

An ExpressionSyntax is provided as an example of a syntax which is implemented in script using the template element's [Syntax API](https://github.com/Polymer/mdv/blob/master/docs/syntax_api.md). It allows the use of named scopes within template `bind` and `repeat` and simple inline expressions within bindings.
This doc has been moved to https://github.com/Polymer/docs/blob/master/platform/mdv/expression_syntax.md

* Include the implementation:

```HTML
<script src="util/expression_syntax.js"></script>
```

* Register the syntax for use on the template element (sub-templates will inherit its use).

```JavaScript
templateElement.bindingDelegate = new ExpressionSyntax();
```

* Use the syntax in your templates

```HTML
<template bind>
<template repeat="{{ user in users }}">
{{ user.name }} <template if="{{ user.age >= 21 }}"> Can have a drink!</template>
</template>
</template>
```

## Features

### Inline expressions

The ExpressionSyntax allows for inline expressions within bindings which support a strict subset of the JavaScript language. In order to use this feature, it's important to understand its behavior and limitations:

* The goal for inline expressions is to allow the expression of simple value concepts and relationships. It is generally bad practice to put complex logic into your HTML (view).
* Expressions are never run (e.g. eval) as page script. They cannot access any global state (e.g. window). They are parsed and converted to a simple interpretted form which is provided the present values of paths contained in the expression.

The specific subset of JavaScript which is supported is:

* Identifiers & paths, e.g. 'foo', 'foo.bar.baz'. These values are treated as relative to the local model, extracted, observed for changes and cause the expression to be re-evaluated if one or more has changed.
* The logical not operator: !
* The unary operators: + (Convert to Number), - (Convert to Number and negate).
* The binary operators: + (Addition), - (Subtraction), * (Multiplication), / (Division), % (Modulo).
* Comparators: < (less than), > (greater than), <= (less than or equal), >= (greater then or equal), == (equal), != (not equal), === (identity equally), !== (identity inequality)
* Logical comparators: || (or), && (and)
* Conditional statements: ?. e.g. 'a ? b : c'.
* Grouping (parenthesis): e.g. '(a + b) * (c + d)'
* Literal values: e.g. numbers, strings, null, undefined. Note that escaped strings and non-decimal numbers are not supported.
* Array & Object initializers: e.g. '[foo, 1]', '{ id: 1, foo: bar }'
* Labeled statements: e.g. 'foo: bar.baz; bat: boo > 2'

When an expression is used within a mustach (`{{` `}}`), it is parsed. The expression should be a single statement, or multiple labeled statements.

* If the result is a single unlabeled statement, whenever the value of one or more paths in the expression change, the value of the expression re-evaluated and the result inserted as the value of the mustache. e.g.

```HTML
<div>Jill has {{ daughter.children.length + son.children.length }} grandchildren</div>
```

* If the result is one or more labeled statements, the value of the mustache will include the set of space-separated label identifiers whose corresponding expressions are truthy. e.g.

```HTML
<div class="{{ active: user.selected; big: user.type == 'super' }}">
```

### Named scope

Named scopes are the solution to wanting to reference a model value from an "outer" model "scope". e.g.

```HTML
<template repeat="{{ user in users }}">
{{ user.name }}
<template repeat="{{ file in user.files }}">
{{ user.name }} owners {{ file.name }}
</template>
</template>
```

The scope naming is available (but optional) inside `template` `bind` and `repeat` directives.

* `bind` syntax: `<template bind="{{ expression as identifier }}">`
* `repeat` syntax: `<template repeat="{{ identifier in expression }}">`

Note that `expression` can be a simple identifier, a path or a full expression (including Object and Array literals).

Within a `template` instance produced by a template using a named scope, all ancestor scopes are visible, up-to and including the first ancestor NOT using a named scope. e.g.

```HTML
<template bind="{{ foo as foo }}">
<!-- foo.* available -->
<template bind="{{ foo.bar as bar }}">
<!-- foo.* & bar.* available -->
<template bind="{{ bar.bat }}">
<!-- only properties of bat are available -->
<template bind="{{ boo as bot }}">
<!-- bot.* and properties of bat are available. NOT foo.* or bar.* -->
</template>
</template>
</template>
</template>
```
and is viewable at http://www.polymer-project.org/platform/mdv/expression_syntax.html
73 changes: 2 additions & 71 deletions docs/node_bind.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,3 @@
## Learn the tech

### Why Node.prototype.bind?

MDV adds a `bind()` method to all DOM nodes which instructs them bind the named value to the data provided. The meaning of the binding name is interpreted by the node on which it is called.

`Text` node only handles the 'textContent' binding. `HTMLInputElement` handles the 'value' and 'checked' bindings as two-way. All other elements handles bindings as to attributes.
### Basic usage

#### Text

```JavaScript
textNode.bind('textContent', someObj, 'path.to.value');
```

Instructs the `Text` node to make its `textContent` dependent on the value `someObj.path.to.value`. Initially, and whenever the value changes, `textContent` will set to `String(someObj.path.to.value)`, or the empty string if the path is `null`, `undefined` or unreachable.

####Element attribute value

```JavaScript
myElement.bind('title', someObj, 'path.to.value');
```

Instructs the element to make the value its `title` attribute dependent on the value `someObj.path.to.value`. Initially, and whenever the value changes, the attribute value will be set to `String(someObj.path.to.value)`, or the empty string if the path is `null`, `undefined` or unreachable.

####Element attribute presence

```JavaScript
myElement.bind('hidden?', someObj, 'path.to.value');
```

Instructs the element to make the presence of its `hidden` attribute dependent on the vaue `someObj.path.to.value`. Initially, and whenever the value changes, the attribute will be set to the empty string if the value `someObj.path.to.value` is reachable and truthy, otherwise the attribute will be removed.


#### Input Element value and checked properties

```JavaScript
myValueInput.bind('value', someObj, 'path.to.value');
```

Instructs the `input` to ensure the its `value` property is equal to `String(someObje.path.to.value)`. The binding is two-way. Upon binding, if the path reachable, `value` is set to the path value. If the path is unreachable but can be made reachable by setting a single property on the final object, the property is set to `value`.


```JavaScript
myCheckboxOrRadioInput.bind('checked', someObj, 'path.to.value');
```
Instructs the `input` to ensure the its `checked` property is equal to `Boolean(someObje.path.to.value)`. The binding is two-way. Upon binding, if the path reachable, `checked` is set to the path value. If the path is unreachable but can be made reachable by setting a single property on the final object, the property is set to `checked`.

### Custom Element bindings

[Custem Elements](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html) may choose to interpret bindings as they wish. The do this by overriding the `bind` method.

```JavaScript
HTMLMyFancyWidget.prototype.bind = function(name, obj, path) {
if (name == 'myBinding')
// interpret the binding meaning
else
HTMLElement.prototype.bind.call(this, name, obj, path);
}
```

If the element does not handle the binding, it should give its super class the opportunity to by invoking its `bind` method.


### API

Note yet written. Please refer to the [HowTo examples](https://github.com/Polymer/mdv/tree/master/examples/how_to).

### Specification

Note yet written. Please refer to the [HowTo examples](https://github.com/Polymer/mdv/tree/master/examples/how_to).
This doc has been moved to https://github.com/Polymer/docs/blob/master/platform/mdv/node_bind.md

Viewable at http://www.polymer-project.org/platform/mdv/node_bind.html
104 changes: 2 additions & 102 deletions docs/syntax_api.md
Original file line number Diff line number Diff line change
@@ -1,103 +1,3 @@
## Learn the tech
This doc has been moved to https://github.com/Polymer/docs/blob/master/platform/mdv/syntax_api.md

### Why MDV Pluggable Syntax?

MDV's native features enables a wide-range of use cases, but (by design) don't attempt to implement many specialized behaviors that some MV* frameworks suport. For example:

* Inline-expressions within mustaches, e.g.:

```html
<span>{{ foo + bar ? foo : bar }}</span>
```

* "Named scopes" for iterators, e.g.:

```html
<template repeat="{{ user in users }}">
{{ user.name }}
</template>
```

* ... And anything else you'd like.

Enabling these features in MDV is a matter of implementing and registering a binding delegate.

### Basic usage

```JavaScript
templateElement.bindingDelegate = {
getBinding: function(model, path, name, node) {
// If this function is defined, the syntax can override
// the default binding behavior
},
getInstanceModel: function(template, model) {
// If this function is defined, the syntax can override
// what model is used for each template instance which is
// produced.
}
}
```

### getBinding

The `getBinding` method allows for a custom interpretation of the contents of mustaches (`{{` ... `}}`).

When a template is inserting an instance, it will invoke the `getBinding` method (if it is implemented by the syntax) for each mustache which is encountered. The function is invoked with four arguments:

```JavaScript
syntax.getBinding = function(model, path, name, node);
```

* `model`: The data context for which this instance is being created.
* `path`: The text contents (trimmed of outer whitespace) of the mustache.
* `name`: The context in which the mustache occurs. Within element attributes, this will be the name of the attribute. Within text, this will be 'textContent'.
* `node`: A reference to the node to which this binding will be created.

If the `getBinding` method wishes to handle binding, it is required to return an object which has at least a `value` property. If it does, then MDV will call

```JavaScript
node.bind(name, retval, 'value');
```

...on the node.

If the 'getBinding' wishes to decline to override, it should not return a value.

### getInstanceModel

The `getInstanceModel` method allows a syntax to provide an alterate model than the one the template would otherwise use when producing an instance.

When a template is about to create an instance, it will invoke the `getInstanceModel` method (if it is implemented by the syntax). The function is invoked with two arguments:

```JavaScript
syntax.getBinding = function(template, model);
```
* `template`: The template element which is about to create and insert an instance.
* `model`: The data context for which this instance is being created.

The template element will always use the return value of `getInstanceModel` as the model for the new instance. If the syntax does not wish to override the value, it should simply return the `model` value it was passed.

### CompoundBinding

MDV contains a helper object which is useful for the implementation of a Binding Delegate.

```JavaScript
var combinatorFunction = function(values) {
var combinedValue;
// compute combinedValue based on the current values which are provided
return combinedValue;
};

var binding = new CompoundBinding(combinatorFunction);

binding.bind('name1', obj1, path1);
binding.bind('name2', obj2, path2);
//...
binding.bind('nameN', objN, pathN);
```

`CompoundBinding` is an object which knows how to listen to multiple path values (registered via `bind`) and invoke its `combinatorFunction` when one or more of the values have changed and set its `value` property to the return value of the function. When any value has changed, all current values are provided to the `combinatorFunction` in the single `values` argument.

## Not-yet-implemented delegation functions

* `getInstanceFragment`: used to override the DOM of the instance fragent which is a produced for a new instance.
Viewable at http://www.polymer-project.org/platform/mdv/syntax_api.html
66 changes: 2 additions & 64 deletions docs/template.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,3 @@
## Learn the tech

### Why Template Instantiation?

MDV extends the capabilities of the [HTML Template Element](http://www.w3.org/TR/html-templates/). It enables `<template>` to create, manage and remove instances of its content by being bound to JavaScript data.

### Basic usage

#### bind

```html
<template bind="{{ singleton }}">
Will create a single instance with {{ bindings }} when singleton model data is provided.
</template>
```

#### repeat

```html
<template repeat="{{ collection }}">
Will create maintain exactly instance with {{ bindings }} for every element in the array collection, when it is provided.
</template>
```

#### if

```html
<template bind if="{{ conditionalValue }}">
Will bind if and only if conditionalValue is truthy.
</template>

<template if="{{ conditionalValue }}">
Will bind if and only if conditionalValue is truthy. (same as *bind if*)
</template>

<template repeat if="{{ conditionalValue }}">
Will repeat if and only if conditionalValue is truthy.
</template>
```

#### ref

```html
<template id="myTemplate">
Will be used by any template which refers to this one by the ref attribute
</template>

<template bind ref="myTemplate">
When creating instance, the content of this template will be ignored, and the contnet of #myTemplate will be used instead.
</template>
```

```JavaScript
// Causes any bind, repeat or if attribute directives on #myTemplate to begin acting.
document.getElementById('myTemplate').model = jsData;
```

### API

Note yet written. Please refer to the [HowTo examples](https://github.com/Polymer/mdv/tree/master/examples/how_to).

### Specification

Note yet written. Please refer to the [HowTo examples](https://github.com/Polymer/mdv/tree/master/examples/how_to).
This doc has been moved to https://github.com/Polymer/docs/blob/master/platform/mdv/template.md

Viewable at http://www.polymer-project.org/platform/mdv/template.html
Loading

0 comments on commit d70eb8d

Please sign in to comment.