mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
fix helpers, dynamic attributes; tests
This commit is contained in:
@@ -8,6 +8,7 @@ Package.on_test(function (api) {
|
||||
api.use('underscore');
|
||||
api.use('spacebars');
|
||||
api.use('tinytest');
|
||||
api.use('jquery');
|
||||
api.use('test-helpers');
|
||||
|
||||
api.use('templating', 'client');
|
||||
|
||||
@@ -18,3 +18,11 @@
|
||||
<template name="spacebars_template_test_dynamic_template">
|
||||
{{> foo}}
|
||||
</template>
|
||||
|
||||
<template name="spacebars_template_test_interpolate_attribute">
|
||||
<div class="aaa{{foo bar}}zzz"></div>
|
||||
</template>
|
||||
|
||||
<template name="spacebars_template_test_dynamic_attrs">
|
||||
<span {{{attrs1}}} {{{attrs2}}} {{k}}={{v}} {{x}} {{nonexistent}}>hi</span>
|
||||
</template>
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
var renderToDiv = function (comp) {
|
||||
var div = document.createElement("DIV");
|
||||
UI.insert(UI.render(comp), div);
|
||||
return div;
|
||||
};
|
||||
|
||||
Tinytest.add("spacebars - templates - simple helper", function (test) {
|
||||
var tmpl = Template.spacebars_template_test_simple_helper;
|
||||
tmpl.foo = function (x) {
|
||||
@@ -6,8 +12,7 @@ Tinytest.add("spacebars - templates - simple helper", function (test) {
|
||||
tmpl.bar = function () {
|
||||
return 123;
|
||||
};
|
||||
var div = document.createElement("DIV");
|
||||
UI.insert(UI.render(tmpl), div);
|
||||
var div = renderToDiv(tmpl);
|
||||
|
||||
test.equal(div.innerHTML, "124");
|
||||
});
|
||||
@@ -20,9 +25,7 @@ Tinytest.add("spacebars - templates - dynamic template", function (test) {
|
||||
tmpl.foo = function () {
|
||||
return R.get() === 'aaa' ? aaa : bbb;
|
||||
};
|
||||
var div = document.createElement("DIV");
|
||||
UI.insert(UI.render(tmpl), div);
|
||||
|
||||
var div = renderToDiv(tmpl);
|
||||
test.equal(div.innerHTML, "aaa");
|
||||
|
||||
R.set('bbb');
|
||||
@@ -30,3 +33,44 @@ Tinytest.add("spacebars - templates - dynamic template", function (test) {
|
||||
|
||||
test.equal(div.innerHTML, "bbb");
|
||||
});
|
||||
|
||||
Tinytest.add("spacebars - templates - interpolate attribute", function (test) {
|
||||
var tmpl = Template.spacebars_template_test_interpolate_attribute;
|
||||
tmpl.foo = function (x) {
|
||||
return x+1;
|
||||
};
|
||||
tmpl.bar = function () {
|
||||
return 123;
|
||||
};
|
||||
var div = renderToDiv(tmpl);
|
||||
|
||||
test.equal($(div).find('div')[0].className, "aaa124zzz");
|
||||
});
|
||||
|
||||
Tinytest.add("spacebars - templates - dynamic attrs", function (test) {
|
||||
var tmpl = Template.spacebars_template_test_dynamic_attrs;
|
||||
|
||||
var R1 = ReactiveVar('');
|
||||
var R2 = ReactiveVar('n=1');
|
||||
var R3 = ReactiveVar('selected');
|
||||
tmpl.attrs1 = function () { return R1.get(); };
|
||||
tmpl.attrs2 = function () { return R2.get(); };
|
||||
tmpl.k = 'x';
|
||||
tmpl.v = 'y';
|
||||
tmpl.x = function () { return R3.get(); };
|
||||
var div = renderToDiv(tmpl);
|
||||
var span = $(div).find('span')[0];
|
||||
test.equal(span.innerHTML, 'hi');
|
||||
test.equal(span.getAttribute('n'), "1");
|
||||
test.equal(span.getAttribute('x'), 'y');
|
||||
test.isTrue(span.hasAttribute('selected'));
|
||||
|
||||
R1.set('zanzibar="where the heart is"');
|
||||
R2.set('');
|
||||
R3.set('');
|
||||
Deps.flush();
|
||||
test.equal(span.innerHTML, 'hi');
|
||||
test.isFalse(span.hasAttribute('n'));
|
||||
test.isFalse(span.hasAttribute('selected'));
|
||||
test.equal(span.getAttribute('zanzibar'), 'where the heart is');
|
||||
});
|
||||
|
||||
@@ -577,6 +577,12 @@ var makeObjectLiteral = function (obj) {
|
||||
return buf.join('');
|
||||
};
|
||||
|
||||
// Generates a render function (i.e. JS source code) from a template
|
||||
// string or a pre-parsed template string. Consumes the AST from the
|
||||
// parser, which consists of HTML tokens with embedded stache tags. A
|
||||
// "block" (i.e. `{{#foo}}...{{/foo}}`) is represented as a single tag
|
||||
// (always as part of an HTML "Characters" token), which has content
|
||||
// that contains more HTML.
|
||||
Spacebars.compile = function (inputString, options) {
|
||||
var tree;
|
||||
if (typeof inputString === 'object') {
|
||||
@@ -641,15 +647,14 @@ Spacebars.compile = function (inputString, options) {
|
||||
argCode = toJSLiteral(argValue);
|
||||
break;
|
||||
case 'PATH':
|
||||
argCode = 'function () { return Spacebars.call(' +
|
||||
codeGenPath(argValue, funcInfo) + '); }';
|
||||
argCode = codeGenPath(argValue, funcInfo);
|
||||
break;
|
||||
default:
|
||||
error("Unexpected arg type: " + argType);
|
||||
}
|
||||
|
||||
if (arg.length > 2) {
|
||||
// keyword argument
|
||||
// keyword argument (represented as [type, value, name])
|
||||
options = (options || {});
|
||||
if (! (forComponentWithOpts &&
|
||||
(arg[2] in forComponentWithOpts))) {
|
||||
@@ -719,7 +724,7 @@ Spacebars.compile = function (inputString, options) {
|
||||
var nameCode = codeGenPath(tag.path, funcInfo);
|
||||
var argCode = codeGenArgs(tag.args, funcInfo);
|
||||
|
||||
return 'Spacebars.call(' + nameCode +
|
||||
return 'Spacebars.mustache(' + nameCode +
|
||||
(argCode ? ', ' + argCode.join(', ') : '') + ')';
|
||||
};
|
||||
|
||||
@@ -861,6 +866,7 @@ Spacebars.compile = function (inputString, options) {
|
||||
var name = kv.nodeName;
|
||||
var value = kv.nodeValue;
|
||||
if ((typeof name) === 'string') {
|
||||
// attribute name has no tags
|
||||
attrs = (attrs || {});
|
||||
attrs[toJSLiteral(name)] =
|
||||
interpolate(value, funcInfo,
|
||||
@@ -870,6 +876,8 @@ Spacebars.compile = function (inputString, options) {
|
||||
} else if (value === '' &&
|
||||
name.length === 1 &&
|
||||
name[0].type === 'TRIPLE') {
|
||||
// attribute name is a triple-stache, no value, as in:
|
||||
// `<div {{{attrs}}}>`.
|
||||
renderables.push(
|
||||
'{attrs: function () { return Spacebars.parseAttrs(' +
|
||||
codeGenBasicStache(name[0], funcInfo) + '); }}');
|
||||
@@ -877,7 +885,7 @@ Spacebars.compile = function (inputString, options) {
|
||||
pairsWithReactiveNames.push(
|
||||
interpolate(name, funcInfo,
|
||||
INTERPOLATE_ATTR_VALUE),
|
||||
interpolate(name, funcInfo,
|
||||
interpolate(value, funcInfo,
|
||||
INTERPOLATE_ATTR_VALUE));
|
||||
isReactive = true;
|
||||
}
|
||||
@@ -977,6 +985,21 @@ Spacebars.call = function (value/*, args*/) {
|
||||
return value.apply(null, args);
|
||||
};
|
||||
|
||||
// Executes `{{foo bar baz}}` when called on `(foo, bar, baz)`.
|
||||
// If `bar` and `baz` are functions, they are called. `foo`
|
||||
// may be a non-function, in which case the arguments are
|
||||
// discarded (though they may still be evaluated, i.e. called).
|
||||
Spacebars.mustache = function (value/*, args*/) {
|
||||
// call any arg that is a function (checked in Spacebars.call)
|
||||
for (var i = 1; i < arguments.length; i++)
|
||||
arguments[i] = Spacebars.call(arguments[i]);
|
||||
|
||||
var result = Spacebars.call.apply(null, arguments);
|
||||
// map `null` and `undefined` to "", stringify anything else
|
||||
// (e.g. strings, booleans, numbers including 0).
|
||||
return String(result == null ? '' : result);
|
||||
};
|
||||
|
||||
Spacebars.extend = function (obj/*, k1, v1, k2, v2, ...*/) {
|
||||
for (var i = 1; i < arguments.length; i += 2)
|
||||
obj[arguments[i]] = arguments[i+1];
|
||||
@@ -996,8 +1019,8 @@ Spacebars.parseAttrs = function (attrs) {
|
||||
if (tokens.length &&
|
||||
tokens[0].type === 'StartTag') {
|
||||
_.each(tokens[0].data, function (kv) {
|
||||
if (UI.isValidAttributeName(kv[0]))
|
||||
dict[kv[0]] = kv[1];
|
||||
if (UI.isValidAttributeName(kv.nodeName))
|
||||
dict[kv.nodeName] = kv.nodeValue;
|
||||
});
|
||||
}
|
||||
return dict;
|
||||
|
||||
@@ -34,10 +34,12 @@ AttributeManager = function (dictOrFunc) {
|
||||
|
||||
var handlers = self.handlers;
|
||||
for (var attrName in dict) {
|
||||
if (! attrName)
|
||||
continue; // ignore empty attribute names
|
||||
// perform a sanity check, since we'll be inserting
|
||||
// attrName directly into the HTML stream
|
||||
if (! isValidAttributeName(attrName))
|
||||
throw new Error("Illegal HTML attribute name: '" + attrName + "'");
|
||||
throw new Error("Expected single HTML attribute name, found: '" + attrName + "'");
|
||||
|
||||
handlers[attrName] = makeAttributeHandler(
|
||||
attrName, dict[attrName]);
|
||||
@@ -88,12 +90,14 @@ _extend(AttributeManager.prototype, {
|
||||
h.update(element, oldValue, h.value);
|
||||
}
|
||||
for (var k in newDict) {
|
||||
if (! k)
|
||||
continue; // ignore empty attributes
|
||||
if (! handlers.hasOwnProperty(k)) {
|
||||
// need a new handler
|
||||
var attrName = k;
|
||||
|
||||
if (! isValidAttributeName(attrName))
|
||||
throw new Error("Illegal HTML attribute name: " + attrName);
|
||||
throw new Error("Expected single HTML attribute name, found: " + attrName);
|
||||
|
||||
var h = makeAttributeHandler(
|
||||
attrName, newDict[attrName]);
|
||||
|
||||
Reference in New Issue
Block a user