EndDash is a two-way binding javascript templating framework built on top of semantic HTML
In its current release, EndDash relies on Backbone objects. See the dependency section for further details.
(Documentation is below)
Install EndDash and install grunt helper
npm install
# We use grunt for running tasks.
npm install -g grunt-cli
# Build end-dash in build/ directory
grunt build # also aliased as `grunt`
Include the library and dependencies.
<script src="https://github.com/Amicus/end-dash/raw/0.3.8/ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://backbonejs.org/backbone.js"></script>
<script src="https://github.com/Amicus/end-dash/raw/0.3.8/end-dash/build/end-dash.js"></script>
Define your templates.
<script type="text/enddash" name="character">
Hello, my name is <span class="firstName-"></span>
<span class="lastName-"></span>...
<strong class="quip-"></strong>
</script>
WARNING: A template can only have one root element. In the above case, it is the div with class 'user'.
Load your templates into EndDash.
$.ready(function() {
// Load all the templates on the page.
EndDash.bootstrap();
)};
Bind your templates to models in your application code.
var tony = new Backbone.Model({
firstName: 'Tony',
lastName: 'Stark',
quip: "You know, the question I get asked most often is, 'Tony, how do you go to the bathroom in your suit?'"
});
var template = EndDash.getTemplate('character', tony);
$('#content').html(template.el);
});
If your models changes, the DOM will update to reflect the changes.
If you clone this repo and install grunt as described above
you can play with some end-dash examples in your browser.
Just type grunt in the root directory to build the current
version of end-dash into the build directory, and then
open up any of the example html files in the examples directory
in your browser (open examples/looping.html for example works
on OS X), and you can edit the templates or models directly in the
html file if you want to experiment.
Using Model Attributes * Variables * Attribute Interpolation
Inputs * Text Inputs * Radio Buttons * Checkboxes
Looping * Simple Looping * Polymorphic Attributes * Collection Attributes
Scoping * What is scoping? * Scoping Down with a Dash * Scoping With Paths
Contributing and Future Improvements * Building and Testing * Future Improvements
EndDash variables are rendered into the body of HTML elements, displaying their values as ordinary text:
My name is <span class="firstName-"></span> <span class="lastName-"></span>.
Model properties can also be interpolated into any html tag attribute.
<a href="https://github.com/Amicus/end-dash/raw/0.3.8/person/#{firstName}"> Home Page </a>
template.bind(new Backbone.Model({firstName: 'Derrick'}));
Resulting Tag:
<a href="https://github.com/Amicus/end-dash/raw/0.3.8/person/Derrick"> Home Page </a>
EndDash does two-way binding between model attributes and input elements.
Text inputs are bound to a referenced attribute on the model in scope. To create this binding, add the attribute name with a dash at the end as a classname in the template.
What is your name?
<input type="text" class="name-">
Radio buttons bind the selected button's value to the model's referenced attribute.
Who is your favorite character?
<input type="radio" class="name-" name="name-" value="tony" id="tony"/>
<label for="tony">Tony</label>
<input type="radio" class="name-" name="name-" value="pepper" id="pepper"/>
<label for="pepper">Pepper</label>
<input type="radio" class="name-" name="name-" value="james" id="james"/>
<label for="james">James</label>
Checkboxes are trickier. When unchecked, the referenced attribute on the model will be 'false'. When checked, the referenced model's attribute will be set to the attribute value on the input element (or 'true' if no value is defined).
Do you want to receive notifications about Iron Man?
<input type="checkbox" name="notifyList" class="notify-" />
To reuse a set of DOM elements for each child model in a collection,
add the data-each attribute to the parent of this set.
The object in scope at these elements, will be iterated through (using .each).
Each child of this collection will be bound to the nested elements.
Given the above template and the collection:
var characters = new Backbone.Collection([
new Backbone.Model({firstName: 'Tony'}),
new Backbone.Model({firstName: 'Pepper'}),
new Backbone.Model({firstName: 'Iron'}),
new Backbone.Model({firstName: 'James'})
]);
the output will be:
Tony
Pepper
Iron
James
Note that the elements iterated over must have one root. (Here `
`).
If your objects have an enum field, you can branch based on its value.
For example, role behaves as a polymorphic attribute:
<span class="firstName-"></span> says:
Don't worry. I'll probably save you.
<span class="firstName-"></span> says:
Worry.
<span class="firstName-"></span> says:
Get me outta here!
Given the following objects:
new Backbone.Collection([
new Backbone.Model({firstName: 'Tony', role: 'hero'}),
new Backbone.Model({firstName: 'Pepper', role: 'civilian'}),
new Backbone.Model({firstName: 'Aldrich', role: 'villain'}),
new Backbone.Model({firstName: 'James', role: 'hero'})
]);
The template would produce the following HTML:
<span class="firstName-">Tony</span> says:
Don't worry. I'll probably save you.
<span class="firstName-">Pepper</span> says:
Get me outta here!
<span class="firstName-">Aldrich</span> says:
The whole world's gonna be watching.
<span class="firstName-">James</span> says:
Don't worry. I'll save you!
To add a default case, include a non-EndDash child div:
<span class="firstName-"></span> says:
Don't worry. I'll probably save you.
<span class="firstName-"></span> says:
I've lost my memory. I don't know who I am!
Please note: Backbone.Collection does not support attributes natively for its collections,
but there are a number of options for extending collections to do so. EndDash supports
collection attributes as long as they are implemented according to Backbone.Model API, via
the get method (which Backbone.Collection natively uses only for getting a model by id,
not an attribute by name). Typically collection attributes are used for metadata about
the collection, such as total size (if the collection is paginated and this is
different than length), as in the example below:
There are <span class="totalCount-"></span> people allowed in Tony's basement.
A ternary operator is available for presence handling via 'truthiness' for attributes that may be present, with or without a false condition:
My schedule is very full. <span class="isAvailable-">I just have a few openings</span>
The same truthiness controls conditional visibility EndDash class elements that start with is or has,
and their boolean opposites isNot and hasNo, as above with isAvailable-. EndDash will hide (via a
display:none style attribute) any such element when its named attribute is falsy (or hide when truthy in
the case of isNot and hasNo.)
template.bind({
user: new Backbone.Model({
firstName: 'Tony',
lastName: 'Stark',
alias: 'IronMan'
availability: ['10am', '2pm']
});
});
Scope in EndDash refers to the model on the top of the EndDash stack. Each template and partial is given its own scope. The 'root' scope is always the object passed to EndDash's 'bind' or 'getTemplate' function.
template.bind({
user: new Backbone.Model({
firstName: 'Tony',
lastName: 'Stark',
hobby: {
description: 'Building all the cool technology'
}
})
});
The root object is the object literal with the property 'user'.
Scope can change in two ways:
//Internal HTML
Scopes into the Backbone Model with properties: 'firstName', 'lastName', and 'hobby'. This syntax only allows scopping down.
(UNIX style)
//Iternal HTML
Scopes down into the user object and then, via the data-scope property, scopes back to the root object (the object literal with propery 'user').
Normal UNIX path shorthands apply: .. to move back up a scope level, / to seperate scope levels,
. for the current scope.
//User scope
//Hobby scope
//Back in User Scope
//Back in Hobby scope
class="user-" is actually syntactic sugar for data-scope="./user". Using data-scope like this,
at the current scope, is mainly useful for accessing a property of a nested model in the same DOM
element that you change the scope.
EndDash provides dynamic behavior often otherwise handled by views in Backbone.
If more specific dynamic behavior is required, take advantadge of EndDash's hooks to Backbone Views. Simply add
the html attribute data-view with the value of your viewName, to the template.
<h2>
Configure Iron Man's suit below:
</h2>
When EndDash runs into a data-view, it will lookup the view and initialize it
with the model in scope at the DOM element where the view is initialized.
To lookup the view, EndDash uses a simple view store. You can register views by
calling EndDash.registerView with the view name and the view class object. You can
also define your own function and pass it into EndDash.setCustomGetView
EndDash.registerView('myViewName', viewObj);
var views = {},
getViews = function(name) {
return views[name];
};
EndDash.setCustomGetView(getViews);
This can be done manually.
EndDash.registerTemplate('greetings','
Hello Citizens, I am <span class="name-"></span>
');
Or, via EndDash.bootstrap.
To bootstrap, have your templates loaded as scripts of type 'enddash' on the page.
<script type="text/enddash" name="greetings">
Hello Citizens, I am <span class="name-"></span>
</script>
Then call EndDash.bootstrap.
$.ready(function() {
// Load all the templates on the page.
EndDash.bootstrap();
)};
First, get the EndDash-parsed version of your template.
var template = EndDash.getTemplate('greetings');
Then bind it to a model.
var hero = new Backbone.Model({name: 'Superman'}),
boundTemplate = template.bind(hero);
This can be done in a single step, by passing a model
as a second argument to EndDash.getTemplate.
var hero = new Backbone.Model({name: 'Superman'}),
boundTemplate = EndDash.getTemplate('greetings', hero);
```
## Displaying HTML of a bound Template
Show the el property of the template.
```js
$('.content').html(boundTemplate.el);
Small, reusable, components of HTML can be templated in EndDash as partials.
To use a partial, add src="https://github.com/Amicus/end-dash/raw/0.3.8/templateName" as an attribute to an element with no children.
<script type="text/enddash" name="superheroes">
<img src="#{logo}" />
</script>
The partial will be passed the model in scope as its root element.
The data-replace attribute tells EndDash to substitute the partia
$ claude mcp add end-dash \
-- python -m otcore.mcp_server <graph>