Peach is a template engine with subscribers and emitters
- Lodash
- _.assign
- _.cloneDeep
- _.forEach
- _.get
- _.kebabCase
- _.keys
- _.last
- _.merge
- _.pick
- _.remove
- _.set
- _.uniq
- Peach.fn.add
- Peach.fn.load
- Peach.fn.render
- Peach.fn.renderEach
- Peach.fn.node
- Peach.fn.nodeEach
- Peach.fn.set
- Peach.fn.get
- Peach.fn.on
- Peach.fn.tools
- Peach.fn.bind
- Peach.fn.update
A function which is used to store templates by name and value
var peach = Peach();
peach.add({
button : {
value : '<div {{attr}}>{{text}}</div>'
}
});Peach also allows loading templates as HTML. Files are loaded in an Array. A callback function can be included as a second argument, it will execute once the files are loaded and the DOM has been rendered.
var peach = Peach();
peach.load(['template.html'], callbackFunction);It is important to note that template files are whitespace active, this is an example of template.html.
button
<div class="{{self}}">{{text}}</div>
input
<div class="{{self}}">
<input {{attr_value}} {{attr_placeholder}}>
</div>A function used to render a template to a string.
var peach = Peach();
peach.render('button', { text : 'My Button' });
// -> <div class="button">My Button</div>Takes an Array as second argument to render templates as a string.
var peach = Peach();
var buttonList = [{
text : 'My Button'
}, {
text : 'My Second Button'
}];
peach.render('button', buttonList);
// -> <div class="button">My Button</div>
// <div class="button">My Second Button</div>Works the same as Peach.fn.render and returns a Node or NodeList.
var peach = Peach();
var buttonNode = peach.node('button', {
text : 'My Button'
});
// -> [object HTMLBodyElement] : <div class="button">My Button</div>Takes an Array as second argument to render a NodeList
var peach = Peach();
var buttonList = [{
text : 'My Button'
}, {
text : 'My Second Button'
}];
var buttonNodes = peach.nodeEach('button', buttonList);
// -> [object NodeList] :
// [
// 0: <div class="button">My Button</div>],
// 1: <div class="button">My Second Button</div>
// ]A function which adds storage which can be passed as an object reference to the renderer.
Uses lodash.set and returns the set value.
var peach = Peach();
peach.set('buttonList', {
myButton : {
text : 'My Button '
},
mySecondButton : {
text : 'My Second Button'
}
});Second example with setting object paths
var peach = Peach();
peach.set('buttonList.myButton', {
text : 'My Button '
});
peach.set('buttonList.mySecondButton', {
text : 'My Second Button '
});A function which retrieves storage which was created using Peach.fn.set. It uses lodash.get.
peach.get('buttonList.myButton');
// -> { text : 'My Button ' }Referencing the Object from the DOM
The @ sign is our delimiter for passing an object reference to the renderer.
<x-peach render="button@buttonList.myButton"></x-peach>Referencing the Object using Peach.fn.render
peach.render('button@buttonList.myButton');Referencing the Object using Peach.fn.node
peach.node('button@buttonList.myButton');These examples all make symmetric use to the object reference and illustrate the consistency between using functions to render or nodes.
There are two events you can bind to:
render'node'
mixinList is an Array of strings passed to the renderer.
Eg : peach.render('button:mixin1:mixin2'), : is the delimiter, and will pass the a list of ['mixin1', 'mixin2'];
peach.on('render', 'button', function (mixinList) {
...
});Here is an example where I listen for mixin1 on button
peach.on('render', 'button:mixin1', function (mixinList) {
// Do stuff
});In this example, I check the presence of mixin2 and mixin3.
peach.on('render', 'button:mixin1', function (mixinList) {
if (mixinList.has('mixin2', 'mixin3')) {
// Do stuff
} else if (mixinList.has('mixin2')) {
// Do this stuff
}
});The algorithm for passing mixins to the emitter listening on peach.render('button:mixin1:mixin2:mixin3') will trigger subscribers in this order:
'button:mixin1:mixin2:mixin3''button:mixin1:mixin2''button:mixin3''button:mixin2''button:mixin1''button'
In practical terms:
// First to trigger
peach.on('render', 'button:mixin1:mixin2:mixin3', function () {});
// Second to trigger
peach.on('render', 'button:mixin1:mixin2', function () {});
// Third to trigger
peach.on('render', 'button:mixin3', function () {});
// Fourth to trigger
peach.on('render', 'button:mixin2', function () {});
// Fifth to trigger
peach.on('render', 'button:mixin1', function () {});
// Last to trigger
peach.on('render', 'button', function () {});It also important to note, that peach.on adds the subscribers to an Array. This means you can add a virtually unlimited amount of each subcriber:
// #1
peach.on('render', 'button', function () {});
// #2
peach.on('render', 'button', function () {});
// #3
peach.on('render', 'button', function () {});
// #4
peach.on('render', 'button', function () {});
// #5
peach.on('render', 'button', function () {});
// #6
peach.on('render', 'button', function () {});It's important to note, that peach.on('render') passes this to the function as an object.
Here are the two ways in which you can add key values to this
peach.render('button', {
text : 'My Button'
});Passing a reference to an object created with Peach.fn.set
peach.render('button@myButton');An example of the value of this when simply executing peach.render('button');
attr: "class="button""
attr_class: "class="button""
class: [
0: "button"
],
self: "button"
string: "<div {{attr}}>{{text}}</div>"
An example of the value of the agumented this when pasing an object
attr: "class="button""
attr_class: "class="button""
class: [
0: "button"
],
self: "button"
string: "<div {{attr}}>{{text}}</div>",
text: "My Button"
Each one of the preceding values that are strings can be included in your template.
- The value of 'nodeElement' can be a
NodeorNodeList mixinListis anArrayof strings passed to the renderer
peach.on('node', 'button', function (nodeElement, mixinList) {
// eg : peach.node('button:mixin1:mixin2') would pass the mixinList
// of ['mixin1', 'mixin2'];
...
});To summarize it, there are certain object keys which will automatically be converted to attributes and their values:
hrefclassstyleidfornametypevaluecheckedtabindextitleplaceholderselecteddisableddata*(eg dataValue -> data-value)
In the template value, you can refer to either the whole rendered {{attr}} variable, or each member uniquely by inserting an underscore:
{{attr_href}}{{attr_class}}{{attr_style}}{{attr_id}}{{attr_for}}{{attr_name}}{{attr_type}}{{attr_value}}{{attr_checked}}{{attr_tabindex}}{{attr_title}}{{attr_placeholder}}{{attr_selected}}{{attr_disabled}}{{attr_data*}}(eg dataValue -> {{attr_data-value}})
By refering uniquely to the {{attr_*}} the renderer will flatten the values into a string, eg : {{attr_href}} -> href="http://www.myAddress.com"
The object for reference
{
class : 'this-class-name',
value : 'test'
}The rendered value of {{attr}}
class="this-class-name" value="test"The rendered value of {{attr_class}}
class="this-class-name"The rendered value of {{attr_value}}
value="test"peach.on('render', 'button', function () {
var tools = peach.tools(this);
// Add Class
tools.addClass('a-class');
tools.addClass('b-class');
// Remove Class
tools.removeClass('a-class');
// Remove Class with RegExp support
tools.removeClass(/class/);
// Has Class
tools.hasClass('b-class');
// CSS
// Note : CSS key values must be the JavaScript `camelCase` version of the CSS attribute
// CSS also supports automatically adding vendor prefixes when they are requried
tools.css({
paddingLeft : '50px',
paddingTop : '10px',
zIndex : 3,
width : (100 / 6) + '%'
});
});To take advantage of peach.tools(this).addClass, peach.tools(this).removeClass my template will require:
{{attr_class}}{{attr}}
To take advantage of peach.tools(this).css my template will require:
{{attr_style}}{{attr}}
Attaches a subscriber to a node which will be updated via Peach.fn.update
var peach = Peach();
var node = peach.node('button', { text : 'button1' });
document.body.appendChild(node);
peach.bind('button', node);Updates a node in the DOM with an updated version of that node by rendering it with the passed object properties.
peach.update('button', { text : 'button2' });You can augment the defaults during initialization:
var peach = Peach({
attr : {
dingo : {
value : 'data-dingo',
process : dingo.flatten
}
}
});Here I have a short hand key named dingo which also requires a processor named dingo.flatten -- it's value can optionally be preprocessed before rendering. The preprocessor must return a string.
The object for reference
{
dingo : 'clickHandler_myClickHandler'
}The rendered value of {{attr}}
data-dingo="clickHandler_myClickHandler"
There is a DOM interface for rendering templates. The tag is <x-peach render="button"></x-peach>
<HTML>
<body>
<x-peach render="button"><x-peach>
<script src="peach.min.js"></script>
</body>
</HTML>Everything inside the render attribute is symmetric to the first argument in peach.render() this important because of the ability to pass objects and mixins to the renderer.
For example:
<x-peach render="button:mixin1:mixin2@myButton"></x-peach>