Pure2 context notation

6 views
Skip to first unread message

nightshade427

unread,
Oct 22, 2009, 2:35:16 PM10/22/09
to PURE - JavaScript Templates Engine
This used to work:
<div id="item_buttons">
<ul>
<li class="context">
<button class="name inv@data-inv"></button>
</li>
</ul>
</div>

var menu = [{name: "dvd", inv: "I-9000"}];
$("#item_buttons li").autoRender(menu);

Now it doesnt work with pure2, any ideas?

Mic (BeeBole)

unread,
Oct 22, 2009, 4:32:28 PM10/22/09
to PURE - JavaScript Templates Engine
I forgot this feature while building the autoRender in the version 2.
I'll look for a fix in the coming days.
Thanks for reporting.

Mic

nightshade427

unread,
Oct 22, 2009, 8:40:15 PM10/22/09
to PURE - JavaScript Templates Engine

Wow!! Awesome!! Thank you for putting out such a great library

nightshade427

unread,
Oct 25, 2009, 3:53:17 AM10/25/09
to PURE - JavaScript Templates Engine

Let me know when it's ready so I can test :)

Mic (BeeBole)

unread,
Oct 25, 2009, 4:53:10 PM10/25/09
to PURE - JavaScript Templates Engine
Unfortunately for backward compatibility, the "context" keyword is
used in loops with directives and can't be used anymore as in your
example.
You can workaround it with something like:

<div id="item_buttons">
<ul>
<li class="loop">
<button>s</button>
</li>
</ul>
</div>
<script>
var menu = [{name: "dvd", inv: "I-9000"}, {name: "dvd1", inv:
"I-90001"}];
$("#item_buttons").autoRender({loop:menu});
</script>

Sorry about that.
Mic

nightshade427

unread,
Oct 25, 2009, 7:07:33 PM10/25/09
to PURE - JavaScript Templates Engine
How would I re-render just the payments sections for example now
without "context'? Normally I would just call "bind_payments" and it
would re-render just the payment section. Without "context" I have no
idea how I would do that without re-rendering the whole sale now. Any
ideas?

Sorry for the inlined files .. couldnt find a way to attach them.

<html>
<head>
<script src="app://vendor/javascript/jquery-1.3.2.js"></script>
<script src="app://vendor/javascript/pure.js"></script>
<script type="text/ruby" src="app://app/config.rb"></script>
<script type="text/ruby" src="index.rb"></script>
<script src="index.js"></script>
</head>
<body>
<div id="toolbar">
<p>Please enter an Inventory number in the box below or select
and item from the toolbar.</p>
<div id="item_search">
<input id="item_info">
<button id="add_item">add</button>
</div>
<div id="item_buttons">
<ul>
<li class="context">
<button class="name inv@data-inv"></button>
</li>
</ul>
</div>
</div>
<div id="sale">
<div id="info_widgets"></div>
<table id="customer">
<tr>
<td><img class="photo" src="app://images/customer.png"></td>
<td><span class="first_name"></span></td>
<td><span class="last_name"></span></td>
</tr>
</table>
<table id="sale_items">
<tr class="context">
<td><button class="void_item">X</button></td>
<td>
<span class="inventory_number"></span><br>
<span class="category"></span>
</td>
<td><span class="description"></span></td>
<td>
<input class="quantity@value">
@
<input class="selling_price@value">
</td>
</tr>
</table>
<table id="summary">
<tr>
<td>Sub Total</td>
<td><input class="sub_total@value"></td>
</tr>
<tr>
<td>Tax</td>
<td><span class="tax"></span></td>
</tr>
<tr>
<td>Total</td>
<td><span class="total"></span></td>
</tr>
</table>
<div id="payment_info">
<button id="add_payment">+</button>
<table id="payments">
<tr class="context">
<td><button class="remove_payment">X</button></td>
<td><span class="payment_type"></span></td>
<td><span class="amount"></span></td>
</tr>
</table>
</div>
<div id="sale_commands">
<ul>
<li><button id="clear_discounts">Clear Discounts</button></
li>
<li><button id="eat_tax">Eat Tax</button></li>
<li><button id="balance">Balance $<span class="balance"></
span></button></li>
</ul>
</div>
</div>
</body>
</html>

$(function(){
var to_jquery_selector = function(dom_css_class){
var classes = dom_css_class.replace("@", "\\@").split(" ");
var morphed = classes.map(function(e){return "." + e;});
return morphed.join("");
};
var text_changed = function(property, fn){
if(property.value == ""){property.value =
property.defaultValue;}
if(property.value == property.defaultValue){return;}
property.defaultValue = property.value;
setTimeout(fn, 1);
};
var track_focus = function(){
var focused = "";
var track_focus = function(){
$(":input").each(function(i){
this.onfocus = function(e){focused = this.className;};
});
};
var set_focus = function(){
if(focused != ""){
var selector = to_jquery_selector(focused);
$(selector).focus();
};
};
return function(){
set_focus();
track_focus();
};
}();
var bind_menu = function(){
var setup_add_item = function(){
$("#add_item").click(function(){
var item = $("#item_info").val();
sale.ring_up(item);
});
$("#item_buttons button").click(function(){
sale.ring_up(this.getAttribute("data-inv"));
});
};
var setup_clear_discounts = function(){
$("#clear_discounts").click(function(){
sale.undo_price_changes();
});
};
var setup_eat_tax = function(){
$("#eat_tax").click(function(){
sale.eat_tax();
});
};
var setup_add_payment = function(){
$("#add_payment").click(function(){
sale.add_cash_payment();
});
};
var render = function(){
var menu = [{name: "dvd", inv: "I-9000"}];
$("#item_buttons li").autoRender(menu);
};
return function(){
render();
track_focus();
setup_add_item();
setup_clear_discounts();
setup_eat_tax();
setup_add_payment();
};
}();
var bind_summary = function (){
var template_summary = $("#summary").clone();
var template_balance = $("#balance").clone();
var setup_change_total = function(){
$("#summary .sub_total\\@value").blur(function(){
var that = this;
text_changed(this, function(){sale.out_door_price
(that.value)});
});
};
var render = function(){
$("#summary").autoRender(sale.view(), {}, template_summary);
$("#balance").autoRender(sale.view(), {}, template_balance);
};
return function(){
render();
track_focus();
setup_change_total();
};
}();
var bind_customer = function(){
var template = $("#customer").clone();
var render = function(){
$("#customer").autoRender(sale.view().customer, {}, template);
};
return function(){
render();
track_focus();
};
}();
var bind_payments = function(){
var template = $("#payments").clone();
var setup_remove_payment = function(){
$("#payments .remove_payment").each(function(i){
this.onclick = function(e){sale.reject(i)};
});
};
var render = function(){
$("#payments").autoRender(sale.view().payments, {}, template);
};
return function(){
render();
track_focus();
setup_remove_payment();
};
}();
var bind_items = function(){
var template = $("#sale_items").clone();
var dir = {
".quantity\\@value[class]+": function(arg){return "quantity" +
arg.pos},
".selling_price\\@value[class]+": function(arg){return
"selling_price" + arg.pos},
};
var setup_change_item = function(){
var change_item = function(index, propertyName, property){
text_changed(property, function(){
sale.change_item(index, propertyName, property.value);
});
};
var blur_handler = function(propertyName){
return function(i){
this.onblur = function(e){change_item(i, propertyName,
this);};
};
};
$("#sale_items .quantity\\@value").each(blur_handler
("quantity"));
$("#sale_items .selling_price\\@value").each(blur_handler
("selling_price"));
};
var setup_void_item = function(){
$("#sale_items .void_item").each(function(i){
this.onclick = function(e){sale["void"](i);};
});
};
var render = function(){
$("#sale_items").autoRender(sale.view().items, dir, template);
};
return function(){
render();
track_focus();
setup_change_item();
setup_void_item();
};
}();
setup({menu: bind_menu, customer: bind_customer, items:
bind_items,
summary: bind_summary, payments: bind_payments});
});

Mic Cvilic

unread,
Oct 26, 2009, 6:53:01 AM10/26/09
to Pure-Unobtrusive...@googlegroups.com
I can't test your example, here below is a guess to make it work:
Change the html with "context" -> "payments" and wrap your data in a
{payments:...} object

...


<div id="payment_info">
<button id="add_payment">+</button>
<table id="payments">

<tr class="payments">


<td><button class="remove_payment">X</button></td>
<td><span class="payment_type"></span></td>
<td><span class="amount"></span></td>
</tr>
</table>
</div>

...
var render = function(){
$("#payments").autoRender({payments:sale.view().payments},
{}, template);
};

...

nightshade427

unread,
Oct 26, 2009, 1:31:28 PM10/26/09
to PURE - JavaScript Templates Engine
If I use this syntax

$("#sale_items").autoRender({sale_items:sale.view().items}, {},
template);

and pre-load 2 items it renders. But, if I preload more than 2 items
it errors with:

Error: { message : "Result of expression 'fns[i]' [undefined] is not a
function.
", line : 161i, sourceId : 2146918688i, sourceURL : "app://vendor/
javascript/pur
e2.js", expressionBeginOffset : 4464i, expressionCaretOffset : 4470i,
expression
EndOffset : 4478i, name : "TypeError"}

But I can bring up the js console and see that sale.view().items does
indeed have all 3 items and they cool correct.

Also if I start with 0 items then render .. then add an item and re-
render it doesnt show up. Almost like it isnt using the template
parameter I passed it?

Any thoughts on these 2 issues?

Mic Cvilic

unread,
Oct 26, 2009, 3:17:47 PM10/26/09
to Pure-Unobtrusive...@googlegroups.com
Do you have this online somewhere?

nightshade427

unread,
Oct 26, 2009, 3:43:55 PM10/26/09
to PURE - JavaScript Templates Engine
No sadly not. But here is a repo for

"Also if I start with 0 items then render .. then add an item and re-
render it doesnt show up. Almost like it isnt using the template
parameter I passed it? "

<html>
<head>
<script src="app://vendor/javascript/jquery-1.3.2.js"></script>
<script src="app://vendor/javascript/pure2.js"></script>
<script>
$(function(){
data = [];
test = function(){
var template = $("#sale_items").clone();
return function(){
$("#sale_items").autoRender({sale_items:data}, {},
template);
};
}();
test();
data = [
{
inventory_number: "I-9000",
category: "[INV]",
description: "testing",
quantity: "1",
selling_price: "19.99"
},
{
inventory_number: "I-9000",
category: "[INV]",
description: "testing",
quantity: "1",
selling_price: "19.99"
}];
test();
});
</script>
</head>
<body>
<table id="sale_items">
<tr class="sale_items">
<td><button class="void_item">X</button></td>
<td>
<span class="inventory_number"></span><br>
<span class="category"></span>
</td>
<td><span class="description"></span></td>
<td>
<input class="quantity@value">
@
<input class="selling_price@value">
</td>
</tr>
</table>
</body>
</html>

nightshade427

unread,
Oct 26, 2009, 3:46:46 PM10/26/09
to PURE - JavaScript Templates Engine
Here is repo for (after html is loaded bring up javascript console and
try and re-render using "test()"):

"Error: { message : "Result of expression 'fns[i]' [undefined] is not
a
function.
", line : 161i, sourceId : 2146918688i, sourceURL : "app://vendor/
javascript/pur
e2.js", expressionBeginOffset : 4464i, expressionCaretOffset : 4470i,
expression
EndOffset : 4478i, name : "TypeError"} "

<html>
<head>
<script src="app://vendor/javascript/jquery-1.3.2.js"></script>
<script src="app://vendor/javascript/pure2.js"></script>
<script>
$(function(){
data = [
{
inventory_number: "I-9000",
category: "[INV]",
description: "testing",
quantity: "1",
selling_price: "19.99"
},
{
inventory_number: "I-9000",
category: "[INV]",
description: "testing",
quantity: "1",
selling_price: "19.99"
}];
test = function(){
var template = $("#sale_items").clone();
return function(){
$("#sale_items").autoRender({sale_items:data}, {},
template);
};
}();
test();
});
</script>
</head>
<body>
<table id="sale_items">
<tr class="sale_items">
<td><button class="void_item">X</button></td>
<td>
<span class="inventory_number"></span><br>
<span class="category"></span>
</td>
<td><span class="description"></span></td>
<td>
<input class="quantity@value">
@
<input class="selling_price@value">
</td>
</tr>
</table>
</body>
</html>


On Oct 26, 12:17 pm, Mic Cvilic <tch...@gmail.com> wrote:

Mic Cvilic

unread,
Oct 26, 2009, 4:35:11 PM10/26/09
to Pure-Unobtrusive...@googlegroups.com
The call interface of the version 2 is very different.
I've posted a solution at:
http://www.friendpaste.com/RerbcNubKq0mbzagcQOCq

Here are the differences:

1) template = $( dom node ).compile(directive , context)
"compile" will return a JS function and we store this function in the
variable template.
directive: can be an object or false
context: if present, this will trigger the auto-rendering parsing

2) $( dom node ).render(context, template)

To reuse a template you need to use render instead of autoRender.
Then pass "template" as the 2nd parameter of "render"

"autoRender" does both steps (compile and render) at the same time.

Cheers,
Mic

nightshade427

unread,
Oct 26, 2009, 4:44:14 PM10/26/09
to PURE - JavaScript Templates Engine
So that ability for "autoRender" to take "dom/jquery" was for the
"html" parameter was removed?

http://wiki.github.com/pure/pure/jqueryautorender

nightshade427

unread,
Oct 26, 2009, 5:00:39 PM10/26/09
to PURE - JavaScript Templates Engine
I am using jquery as html parameter to autoRender in other locations
in code and it seems to work. The only difference between the code
that works with it and the code that doesnt is repeaters. The ones
that use jquery objects and work do not repeat, Is this the case? If
so that is confusing to be able to use jquery as parameter in some
cases but not in others?

Mic Cvilic

unread,
Oct 26, 2009, 5:17:54 PM10/26/09
to Pure-Unobtrusive...@googlegroups.com
Aren't you passing 3 parameters to autoRender, while it reads only the 2
first?

nightshade427

unread,
Oct 26, 2009, 5:26:28 PM10/26/09
to PURE - JavaScript Templates Engine
I am using (using all 3):
$("#sale_items").autoRender(sale.view().items, dir, template);

if I change it to (using first 2):
$("#sale_items").autoRender(sale.view().items, dir);

then it uses the target in this case "#sale_items" as the template.
Which means if I render sale_items with 2 items then add an item and
re-render I get 6 items rendered since it is now using the
"#sale_items" table with 2 rows already in it as the new template.
What is worse is if I start a new sale with 0 items then the target
has 0 rows to use as a template and nothing will ever render.

Is that what you mean? Not sure I understood the question ;)

nightshade427

unread,
Oct 26, 2009, 6:22:08 PM10/26/09
to PURE - JavaScript Templates Engine
Your suggestion of trying

"
For your trouble below I guess you should get the same result with a
correct combination of compile/render.
An example:
//run once
var template = $(domSource).clone(true);
//run at each refresh
$(domTarget).render(data, template.compile(false, data))
"

worked brilliantly!!!

nightshade427

unread,
Oct 26, 2009, 6:47:37 PM10/26/09
to PURE - JavaScript Templates Engine
To your point about me using autoRender a lot. I love autoRender is a
maintenance dream!! Whenever i need to expose a new property of my
model I just add the html with the proper classname and I am set. Love
that feature.

nightshade427

unread,
Oct 26, 2009, 6:55:32 PM10/26/09
to PURE - JavaScript Templates Engine
Is there anyway to get autoRender working again for collections (still
works great on non-collections), etc.. like it used to so I can do:
$(domTarget).autoRender(data, dir, template)

instead of:
$(domTarget).render(data, template.compile(dir, data))

Mic Cvilic

unread,
Oct 27, 2009, 10:29:28 AM10/27/09
to Pure-Unobtrusive...@googlegroups.com
Not sure I got that one...
Have you a small example of what you'd like to get?

nightshade427

unread,
Oct 27, 2009, 11:53:33 AM10/27/09
to PURE - JavaScript Templates Engine
For my arrays I want to do like I used to in V1
(domTarget).autoRender(data, dir, template)

instead of this I have to do in V2:
$(domTarget).render(data, template.compile(dir, data))

It is just cleaner. The V1 syntax still works for non arrays but not
for arrays anymore.

Mic Cvilic

unread,
Oct 27, 2009, 3:24:29 PM10/27/09
to Pure-Unobtrusive...@googlegroups.com
From V2, the functions autoRender accepts 2 parameters.
Not sure why it works on non arrays.
Probably the HTML template keeps its initial structure after the
transformation and can be reused without problems.

nightshade427

unread,
Oct 27, 2009, 3:29:05 PM10/27/09
to PURE - JavaScript Templates Engine
Ahhh I see. So autorender takes only 2 params now; data and directive?
No longer takes a template at all? So it has to use the target as the
template? That would be why arrays dont work ;)
> ...
>
> read more »
Reply all
Reply to author
Forward
0 new messages