From f3715306e185226b50f71adaaa836d82df930bba Mon Sep 17 00:00:00 2001 From: David Greenspan Date: Sat, 7 Dec 2013 10:35:36 -0800 Subject: [PATCH] Correctly materialize and toHTML textareas --- packages/ui/render.js | 26 +++++++++++++++++++++---- packages/ui/render_tests.js | 39 +++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/packages/ui/render.js b/packages/ui/render.js index 4d98bf6a79..065ae8fd14 100644 --- a/packages/ui/render.js +++ b/packages/ui/render.js @@ -301,9 +301,19 @@ var materialize = function (node, parent, before, parentComponent) { updateAttributes(elem, attrs); } } - _.each(node, function (child) { - materialize(child, elem, null, parentComponent); - }); + if (node.tagName === 'TEXTAREA') { + var value = ''; + _.each(node, function (child) { + // XXX put the functionality of attributeValueToString in + // something like UI.toText(node) + value += attributeValueToString(child); + }); + elem.value = value; + } else { + _.each(node, function (child) { + materialize(child, elem, null, parentComponent); + }); + } insert(elem, parent, before); } else if (type === 'array') { _.each(node, function (child) { @@ -507,9 +517,17 @@ var toHTML = function (node, parentComponent) { }); } result += '>'; + var contents = ''; _.each(node, function (child) { - result += toHTML(child, parentComponent); + contents += toHTML(child, parentComponent); }); + if (node.tagName === 'TEXTAREA' && + contents.slice(0, 1) === '\n') { + // TEXTAREA will absorb a newline, so if we see one, add + // another one. + result += '\n'; + } + result += contents; if (node.length || ! HTML.isVoidElement(node.tagName)) { // "Void" elements like BR are the only ones that don't get a close // tag in HTML5. They shouldn't have contents, either, so we could diff --git a/packages/ui/render_tests.js b/packages/ui/render_tests.js index d9a4814380..d6f9052ba5 100644 --- a/packages/ui/render_tests.js +++ b/packages/ui/render_tests.js @@ -12,6 +12,7 @@ var UL = HTML.Tag.UL; var LI = HTML.Tag.LI; var SPAN = HTML.Tag.SPAN; var HR = HTML.Tag.HR; +var TEXTAREA = HTML.Tag.TEXTAREA; Tinytest.add("ui - render - basic", function (test) { var run = function (input, expectedInnerHTML, expectedHTML, expectedCode) { @@ -70,6 +71,44 @@ Tinytest.add("ui - render - basic", function (test) { '
', '
', 'HTML.Tag.DIV({"class": "foo"}, HTML.Tag.UL(HTML.Tag.LI(HTML.Tag.P(HTML.Tag.A({href: "#one"}, "One"))), HTML.Tag.LI(HTML.Tag.P("Two", HTML.Tag.BR(), "Three"))))'); + +}); + +Tinytest.add("ui - render - textarea", function (test) { + var run = function (optNode, text, html, code) { + if (typeof optNode === 'string') { + // called with args (text, html, code) + code = html; + html = text; + text = optNode; + optNode = null; + } + var div = document.createElement("DIV"); + var node = TEXTAREA(optNode || text); + materialize(node, div); + test.equal(div.querySelector('textarea').value, text); + + test.equal(UI.toHTML(node), html); + test.equal(UI.toCode(node), code); + }; + + run('Hello', + '', + 'HTML.Tag.TEXTAREA("Hello")'); + + run('\nHello', + '', + 'HTML.Tag.TEXTAREA("\\nHello")'); + + run('', + '', + 'HTML.Tag.TEXTAREA("")'); + + run(CharRef({html: '&', str: '&'}), + '&', + '', + 'HTML.Tag.TEXTAREA(HTML.CharRef({html: "&", str: "&"}))'); + }); Tinytest.add("ui - render - closures", function (test) {