support basic tag in TEXTAREA

This commit is contained in:
David Greenspan
2013-12-10 12:57:42 -08:00
parent bcad63a027
commit 35341b44b4
8 changed files with 80 additions and 26 deletions

View File

@@ -210,9 +210,8 @@ getRCData = function (scanner, tagName, shouldStopFunc) {
} else if (token.t === 'CharRef') {
items.push(convertCharRef(token));
} else if (token.t === 'Special') {
scanner.fatal("NOT IMPLEMENTED: Can't have template tags in " + tagName);
// token.v is an object `{ ... }`
//items.push(HTML.Special(token.v));
items.push(HTML.Special(token.v));
} else {
// (can't happen)
scanner.fatal("Unknown or unexpected token type: " + token.t);

View File

@@ -52,25 +52,29 @@ var extendAttrs = function (tgt, src, parentComponent) {
}
};
HTML.Tag.prototype.evaluateDynamicAttributes = function (parentComponent) {
if (this.attrs && (this.attrs.$dynamic instanceof Array)) {
var attrs = {};
extendAttrs(attrs, this.attrs, parentComponent);
// iterate over this.attrs.$dynamic, calling each element if it
// is a function and then using it to extend `attrs`.
var dynamics = this.attrs.$dynamic;
HTML.evaluateDynamicAttributes = function (attrs, parentComponent) {
if (attrs && (attrs.$dynamic instanceof Array)) {
var result = {};
extendAttrs(result, attrs, parentComponent);
// iterate over attrs.$dynamic, calling each element if it
// is a function and then using it to extend `result`.
var dynamics = attrs.$dynamic;
for (var i = 0; i < dynamics.length; i++) {
var moreAttrs = dynamics[i];
if (typeof moreAttrs === 'function')
moreAttrs = moreAttrs();
extendAttrs(attrs, moreAttrs, parentComponent);
extendAttrs(result, moreAttrs, parentComponent);
}
return attrs;
return result;
} else {
return this.attrs;
return attrs;
}
};
HTML.Tag.prototype.evaluateDynamicAttributes = function (parentComponent) {
return HTML.evaluateDynamicAttributes(this.attrs, parentComponent);
};
// Given "P" create the function `HTML.P`.
var makeTagConstructor = function (tagName) {
// Do a little dance so that tags print nicely in the Chrome console.

View File

@@ -235,3 +235,7 @@
<template name="spacebars_template_test_constant">
{{#constant}}hello{{/constant}}
</template>
<template name="spacebars_template_test_textarea">
<textarea>{{foo}}</textarea>
</template>

View File

@@ -668,3 +668,23 @@ Tinytest.add('spacebars - templates - constant', function (test) {
test.equal(canonicalizeHtml(div.innerHTML), 'hello');
});
Tinytest.add('spacebars - templates - textarea', function (test) {
var tmpl = Template.spacebars_template_test_textarea;
var R = ReactiveVar('hello');
tmpl.foo = function () {
return R.get();
};
debugger;
var div = renderToDiv(tmpl);
var textarea = div.querySelector('textarea');
test.equal(textarea.value, 'hello');
R.set('world');
Deps.flush();
test.equal(textarea.value, 'world');
});

View File

@@ -233,4 +233,12 @@ Tinytest.add("spacebars - compiler output", function (test) {
});
});
run("<textarea>{{foo}}</textarea>",
function () {
var self = this;
return HTML.TEXTAREA(function () {
return Spacebars.mustache(self.lookup("foo"));
});
});
});

View File

@@ -74,25 +74,34 @@ var ClassHandler = AttributeHandler.extend({
}
});
var SelectedHandler = AttributeHandler.extend({
var BooleanHandler = AttributeHandler.extend({
update: function (element, oldValue, value) {
var name = this.name;
if (value == null) {
if (oldValue != null)
element.selected = false;
element[name] = false;
} else {
element.selected = true;
element[name] = true;
}
}
});
var ValueHandler = AttributeHandler.extend({
update: function (element, oldValue, value) {
element.value = value;
}
});
// XXX make it possible for users to register attribute handlers!
makeAttributeHandler = function (name, value) {
makeAttributeHandler = function (tagName, name, value) {
// XXX will need one for 'style' on IE, though modern browsers
// seem to handle setAttribute ok.
if (name === 'class') {
return new ClassHandler(name, value);
} else if (name === 'selected') {
return new SelectedHandler(name, value);
return new BooleanHandler(name, value);
} else if (tagName === 'TEXTAREA' && name === 'value') {
return new ValueHandler(name, value);
} else {
return new AttributeHandler(name, value);
}

View File

@@ -217,7 +217,7 @@ var updateAttributes = function(elem, newAttrs, handlers) {
if ((! handlers) || (! handlers.hasOwnProperty(k))) {
if (value !== null) {
// make new handler
handler = makeAttributeHandler(k, value);
handler = makeAttributeHandler(elem.tagName, k, value);
if (handlers)
handlers[k] = handler;
oldValue = null;
@@ -300,13 +300,21 @@ var materialize = function (node, parent, before, parentComponent) {
insert(range, parent, before);
} else if (node instanceof HTML.Tag) {
var elem = document.createElement(node.tagName);
if (node.attrs) {
var rawAttrs = node.attrs;
var children = node.children;
if (node.tagName === 'TEXTAREA') {
rawAttrs = (rawAttrs || {});
rawAttrs.value = children;
children = [];
};
if (rawAttrs) {
var attrUpdater = Deps.autorun(function (c) {
if (! c.handlers)
c.handlers = {};
try {
var attrs = node.evaluateDynamicAttributes(parentComponent);
var attrs = HTML.evaluateDynamicAttributes(rawAttrs, parentComponent);
var stringAttrs = {};
if (attrs) {
for (var k in attrs) {
@@ -323,11 +331,8 @@ var materialize = function (node, parent, before, parentComponent) {
attrUpdater.stop();
});
}
if (node.tagName === 'TEXTAREA') {
elem.value = HTML.toText(node.children, HTML.TEXTMODE.STRING, parentComponent);
} else {
materialize(node.children, elem, null, parentComponent);
}
materialize(children, elem, null, parentComponent);
insert(elem, parent, before);
} else if (typeof node.instantiate === 'function') {
// component

View File

@@ -89,7 +89,8 @@ Tinytest.add("ui - render - textarea", function (test) {
test.equal(div.querySelector('textarea').value, text);
test.equal(toHTML(node), html);
test.equal(toCode(node), code);
if (typeof code === 'string')
test.equal(toCode(node), code);
};
run('Hello',
@@ -109,6 +110,10 @@ Tinytest.add("ui - render - textarea", function (test) {
'<textarea>&amp;</textarea>',
'HTML.TEXTAREA(HTML.CharRef({html: "&amp;", str: "&"}))');
run(['a', function () { return 'b'; }, 'c'],
'abc',
'<textarea>abc</textarea>');
});
Tinytest.add("ui - render - closures", function (test) {