version 0.7.2
TEDO
=======================================================
Template Engine, Document Oriented
This is a template engine for javascript. It is made for dynamic
pages on the client side. Compared to many other template engines,
all templates are specified in the same html-file that is sent to
the user. When the page is loaded, all templates are extracted and
put into a special javascript object, *tedo*.
The tedo project is hosted at sourceforge
<https://sourceforge.net/projects/tedo/>
Changelog
-------------------------------------
### 0.7
get(nr)
: realisator function get is renamed to nr
realisator.nr(nr)
getLength( matchType=false )
: realisator function getLength is replaced with values
length. The function of matchType is removed until needed.
realisator.length
realisation.set( {'eventListener'...
: fixed bug when adding multiple events
'event':{
'add':[
{ 'on':'click'
'do':callback
},
],
}
### 0.6
* cloning
* realisation.moveTo
* realiation.fromNode
* realisation.set( {'eventListener': ...
[TOC]
Quick introduction
------------------------------------
1. Create a html document.
2. Add the tedo script.
3. Initialise it when the document is loaded.
4. Add the tempaltes to the document from the *tedo* object.
For example:
<!DOCTYPE html>
<script type="text/javascript" src="tedo0.5.js"></script>
<script> window.addEventListener('load',function(){
tedo._init();
tedo.name.set( {'text':'tedo is running'} );
},false);</script>
<body>
<article data-tedo=name> Initial text </article>
</body>
Tips
---------------------------
It is recommended to hide all tedo templates in the root.
For example:
<style>
.tedo { display: none; }
...
<body>
<div class="tedo" data-tedos="my_tedo_list">
...
Create a template
===================================
A template has a data attribute. For example:
<div data-tedo=my_template_name></div>
Different data attributes can change the behavior of the template.
The ones available are:
* *data-tedo* == *data-tedo_show*
* *data-tedo_show*
* *data-tedo_hide*
* *data-tedos*
* *data-tedo_clone*
future planed attributes are
* data-tedos_prefilled to let data be in the document from the beginning
data-tedo
--------------------
data-tedo_show
-------------------
data-tedo_hide
-------------------
Use this template type to get an easy way to access a node and it's
attributes. If the *data-tedo_show* version is used, the template
is shown (realized) at start (or when it's parent is realized), else
it is added hidden (with the class *tedo*).
data-tedos
-------------------
This template type is used to create lists.
It holds a a list of realizations, meaning you can add multiple
elements of the same template after each other.
By creating multiple list templates as node siblings, they will
be grouped as alternatives. This way you can use different
templates for different entries in the same list (in any order).
An example:
<img data-tedos=image>
<video data-tedos=video></video>
data-tedo_clone
---------------------
This tag tells tedo to use another template instead of the current one.
The value is the template to use and it is refered to as a path,
in terms of templates from the body of the html.
To name the template *data-tedo* or *data-tedos* is used.
It is important to use the same type for the clone as for the
original object.
For example:
<body>
<div data-tedo=A>
<div data-tedo=B></div>
</div>
<div data-tedo=C data-tedo_clone=A.B>
</body>
naming limitations
------------------------
A tedo object id has some limits:
* string, not start with a number or underscore
* not be a predefined function (like set or addFirst)
* a javascript declared name for objects like prototype or constructor
Realize templates
=========================
To add a new node from a template, use for example [addLast][]:
tedo.list.addLast();
The same is if it is a list with alternatives:
tedo.image.addLast();
tedo.video.addLast();
To access a list realisation (an elment in a list) use [get][]:
tedo.list.nr(0).set({'text':'text updated'});
first_image_entry = tedo.image.nr(0, true);
obj_from_node = tedo.list.fromNode( event.srcElement );
To remove list realisations use for example [remove][] or [removeAll][]:
tedo.image.removeAll() // also remove video realisations
tedo.video.nr(0,true).remove()
Initiate tedo
======================
[init]: #initiate-tedo
Call _init to initialize tedo. Then tedo will find all templates
in the document, remove them and put them under the tedo
javascript object.
For example:
window.addEventListener('load',function(){
tedo._init();
},false);
Template
==========================
The templates are after initialized internal to tedo. There shouldn't
be any need to use them explicitly.
If needed, mostly for debugging, they are hidden under *tedo._templates*.
Instead realisators and realisations are exposed direct under the tedo
object.
Realisator
--------------------
[realisator]: #realisator
Applies to *list* templates (with and without alternatives and
also clones of lists).
A realisator is a placeholder for a list template. It is added when
the parent is realised.
Note: The *single* templates are realised directly when their parent
is realised (so they don't need a realisator).
To create and remove realisations of a template, there are some
functions under the realisator object (name should be replaced
with the realisator object, like tedo.realisator.addFirst).
To add a new realisation:
[addFirst][]
: name.addFirst( data )
[addLast][]
: name.addLast( data )
To remove realisations:
[removeFirst][]
: name.removeFirst()
[removeLast][]
: name.removeLast()
[removeAll][]
: name.removeAll()
To get a realisation:
[nr][]
: name.nr( number )
[fromNode][]
: name.fromNode( html node )
To update nodes:
[set_children][]
: name.setChildren( data )
The *data* parameter is optional and used for modifying
the inserted node. See the [set_children][] and [set][]
functions for more info.
Realisation - of list template
-------------------------------
[list realisation]: #realisation-of-list-template
A realisation of a list template ( always under a realisator ).
Get the specific realisation by calling [get][] on the realisator.
[get][]
: tedo.name.nr(0).set( data )
tedo.name.nr(2).remove()
Realisation - of single template
-----------------------------------
[single realisation]: #realisation-of-single-template
A realisation of a single template has a set of functions
for mainpulating it (name should be replaced with
the template name).
[show][]
: tedo.name.show( data )
[hide][]
: tedo.name.hide()
[set][]
: tedo.name.set( data )
Functions - more details
===============================
[functions]: #functions-more-details
nr
------------------------
[nr]: #nr
Applies to a [realisator][].
realisation = realisator.nr( number, matchTemplate )
Returns the child of specific number, and optionaly created
from same template as the realisator.
number:
Which child to return, index starts at 0. If it is negative,
count backwards from last child (-1 is the last).
returns false if index is too large or small.
matchTemplate (optional):
if true, it only counts realisations of same type as the
selected realisator.
all
------------------------
[all]: #all
Applies to a [realisator][].
[ realisation ] = realisator.all( matchTemplate )
Returns a list of all children in order of appearence,
optionally created from same template as the realisator.
matchTemplate (optional):
if true, it only counts realisations of same type as the
selected realisator.
fromNode
-----------------------
[fromNode]: #fromNode
Get a tedo object from an event on the node or any child to it.
Returns false if tedo object not found.
Very good to use when catching events:
realisator.fromNode( event.srcElement )
set_children
----------------------
[set_children]: #set_children
realisator.set( data )
Updates one or all children of a realisator.
data is build up as under [set][], but first level names the children
to modify.
data = {
'*': {}, // for all children set( set on all children
nr: {}, // set on child nr
id: {}, // set on child with id
}
set
----------------------
[set]: #set
realisation.set( data )
Update the realisation and its children according to the
data object.
The data object is a tree of settings to add to the realisation
or it's child nodes.
An example:
data = {
'classList':{
'remove':{'hidden'},
},
'att':{ 'href':'http://example.com' },
'children':{
'list':{
'*':{
'text':{'updated'},
}
}
}
}
The following properties is known to set:
attribute or att ( { name : text value } )
: Modifies tag attributes. For example **src**, **href**, **value**.
text or txt ( text )
: Replaces node content (node.textContent).
Warning! removes children if the node has any.
html ( html as text )
: Replaces node inner html.
Warning! removes children if the node has any.
classList or class ( { method : class name or names } )
: mimic the html5 classList function.
Example:
'class':{'toggle':'myclass'}
add
: List of class names to add. It is ok to add existing
classes.
remove
: List of class names to remove. It is ok to remove already
removed classes.
toggle
: List of class names to toggle (if they exist remove them,
else add them).
eventListener
: add or remove event listeners to node.
add
: needs two arguments, *on* for the event or events
('mouseup' or ['keyup','keydown']),
and *do* for the function to trigger.
There is a third optional argument, *id* that is used
if the event is to be removed later.
remove
: needs events setup with an *id*.
call with one or multiple *id*s.
realisation.set( {
'eventListener':{
'add':{
'id':'eventid', // optional
'on':'keyup',
'do':function
},
'remove':{
'id':'eventid',
}
}
});
children
: Set data to children of current node. This is equal to
run set on a child (realisation.child.set)
child_name
: For single realisations, use the template name.
realisation.singlename.set( data )
== { 'children':{singlename:data} }
child_template_name, nr/id
: For list realisations, use the template name and then
the number or id of the realisation.
See [set_children][] for more descriptions.
addFirst
-----------------
[addFirst]: #addFirst
Adds a realisation first in the [realisator][] list.
addAt
-----------------
[addAt]: #addat
Adds a realisation at specified index. Negative index means counting
backwards (-1 is the secod last).
If the index is larger than nr of elements the element is placed last,
and likewise if it is negative larger than nr of elements, the element
is placed first.
addLast
-----------------
[addLast]: #addlast
Adds a realisation last in the realisator list.
remove
------------------
[remove]: #remove
Removes a list [realisation](Realisation - of list template).
removeFirst
------------------
[removeFirst]: #removeFirst
Removes first [list realisation][] in the [realisator][] list.
removeLast
------------------
[removeLast]: #removeLast
Removes last [list realisation][] in the [realisator][] list.
removeAll
---------------------
[removeAll]: #removeAll
Removes all realisations from the [realisator][].
moveTo
-----------------
Moves a realisation to given position.
The position scheme is the same as for 'get', start at 0. Negative
starts backwards, -1 is last (length-1).
...realisation.moveTo( -2 );
show
------------------
[show]: #show
Show a [single realisation][]. (Doing this by removing
the *tedo* class).
realisation.show( data );
hide
------------------
[hide]: #hide
Hide a [single realisation][]. (Doing this by adding the *tedo* class).
realisation.hide();
not yet implemented functions
-------------------
* addBefore
* addIndex
* addAfter
* removeIndex
Ideas
------------------
get( data )
: new function similar to set but retrieves data from node
length
: some help on how it could work
tedo.__length = function() {
this.length=0;
}
tedo.__length.prototype.toString = function() { return String(this.length); };
tedo.__length.prototype.valueOf = function() { return this.length; };
tedo.__length.prototype.inc = function() { ++this.length; }
tedo.__length.prototype.dec = function() { --this.length; }
length = new getLength();
length.inc();
alert(length==1);
length.dec();
alert(length==0);
nr( from_nr, to_nr )
: add ranges to realisator.nr()
looping functions
: if these are needed, they may be implemented
realisator.forEach( function(realisation){} )
for i in realisator._children
func( realisator._children[i] )
realisation.forEachOther( function(realisation(){} )
for i in realisator._children
if realisator._children[i]!=realisation
func(realisation)
add children through set
: a good syntax is not yet found
set({
'children':{
'childname':{
'+':'addLast',
}
}
});
sort function
: realisator.sort(
function(a,b){ return a.size > b.size ? 1 : -(a.size < b.size); },
[function before move(t,list,fromIndex,toIndex){
t.style top=clientTop,
clientTop = realisator.nr(newIndex).clientTop }]
[function after move(t,list,fromIndex,toIndex){
t.style top='auto', position:relative ){ }] );
how to implement sort?
internal first, then nodes (move first to last with moveTo(X) )
function before move, function after move.
Should all add/remove functions have this pattern?
append( data, [id], function afterAdded( realisation, position ) )
insertAt( nr, data, [id], function afterAdded
remove( ... function beforeRemove
set( data )
check each key in data,
* if key is a special key, do something special:
tedo._function_set_method[method]
attribute, event, class, remove
* if key is a child realisation and value is an object:
run set on tedo child
{'child':data} => child.set( data )
* if key is a tedo.function
realisation[key].apply( value )
* if key is a _node.function
_node[key].apply(_node, value )
{ setAttribute:['id','new id'] }
* if key is a _node.object
run set on object?
{ classList:{ add:value } }
* else
assign value
_node.innerHTML = value
tedo.list.set( {
0: 'remove', # realisation.remove()
1: {data}, # realisation.set(data)
sublist:{ 'addLast':[data], }, # realisator.addLast(data) !!! cannot add multiple elements this way !!! many or not
} );
replace
var alt1 = tedo.alternative1.insertAt( 3 );
tedo.alternative2.replace( alt1 );
tedo.alternative2.replace( 3 );
Debugging
==================================
For more debug info, add the debug script after the tedo script.
<script src="tedo0.5.1.js"></script>
<script src=tedo0.5.debug.js></script>
Then open up a javascript console, like opera dragonfly or
firefox firebug? to see the output.
At the end of the document, a section is added - not implemented
that outlines all templates in the document.