From 9ecf676e26fae377e7a61ad904d98fd13b37ff03 Mon Sep 17 00:00:00 2001 From: Rafael Weinstein Date: Tue, 14 Jan 2014 16:26:11 -0800 Subject: [PATCH] add support for svg templates This patch takes a similar approach to semantic templates (and has similar pitfalls): The svg template is removed, replaced with a html template and it's children are lifted into the html template's children. R=arv BUG= Review URL: https://codereview.appspot.com/52470043 --- src/TemplateBinding.js | 51 ++++++++++++++++++++++++++++++++---------- tests/tests.js | 24 ++++++++++++++++++++ 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/TemplateBinding.js b/src/TemplateBinding.js index 369dd3f..fbee9fb 100644 --- a/src/TemplateBinding.js +++ b/src/TemplateBinding.js @@ -145,6 +145,16 @@ return tagName.toLowerCase() + '[template]'; }).join(', '); + function isSVGTemplate(el) { + return el.tagName.toLowerCase() == 'template' && + el.namespaceURI == 'http://www.w3.org/2000/svg'; + } + + function isHTMLTemplate(el) { + return el.tagName == 'TEMPLATE' && + el.namespaceURI == 'http://www.w3.org/1999/xhtml'; + } + function isAttributeTemplate(el) { return Boolean(semanticTemplateElements[el.tagName] && el.hasAttribute('template')); @@ -157,10 +167,6 @@ return el.isTemplate_; } - function isNativeTemplate(el) { - return hasTemplateElement && el.tagName == 'TEMPLATE'; - } - // FIXME: Observe templates being added/removed from documents // FIXME: Expose imperative API to decorate and observe templates in // "disconnected tress" (e.g. ShadowRoot) @@ -270,6 +276,22 @@ return template; } + function extractTemplateFromSVGTemplate(el) { + var template = el.ownerDocument.createElement('template'); + el.parentNode.insertBefore(template, el); + + var attribs = el.attributes; + var count = attribs.length; + while (count-- > 0) { + var attrib = attribs[count]; + template.setAttribute(attrib.name, attrib.value); + el.removeAttribute(attrib.name); + } + + el.parentNode.removeChild(el); + return template; + } + function liftNonNativeTemplateChildrenIntoContent(template, el, useRoot) { var content = template.content; if (useRoot) { @@ -296,18 +318,23 @@ var templateElement = el; templateElement.templateIsDecorated_ = true; - var isNative = isNativeTemplate(templateElement); + var isNative = isHTMLTemplate(templateElement) && hasTemplateElement; var bootstrapContents = isNative; var liftContents = !isNative; var liftRoot = false; - if (!isNative && isAttributeTemplate(templateElement)) { - assert(!opt_instanceRef); - templateElement = extractTemplateFromAttributeTemplate(el); - templateElement.templateIsDecorated_ = true; - - isNative = isNativeTemplate(templateElement); - liftRoot = true; + if (!isNative) { + if (isAttributeTemplate(templateElement)) { + assert(!opt_instanceRef); + templateElement = extractTemplateFromAttributeTemplate(el); + templateElement.templateIsDecorated_ = true; + isNative = hasTemplateElement; + liftRoot = true; + } else if (isSVGTemplate(templateElement)) { + templateElement = extractTemplateFromSVGTemplate(el); + templateElement.templateIsDecorated_ = true; + isNative = hasTemplateElement; + } } if (!isNative) { diff --git a/tests/tests.js b/tests/tests.js index 6354a76..e201192 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -2568,6 +2568,30 @@ suite('Template Instantiation', function() { unbindAll(instance); }); + test('Repeat - svg', function(done) { + var div = createTestHtml( + '' + + '' + + ''); + + var model = [{ width: 10, height: 10 }, { width: 20, height: 20 }]; + var svg = div.firstChild; + var template = svg.firstChild; + template.model = model; + + then(function() { + assert.strictEqual(3, svg.childNodes.length); + assert.strictEqual('10', svg.childNodes[1].getAttribute('width')); + assert.strictEqual('10', svg.childNodes[1].getAttribute('height')); + assert.strictEqual('20', svg.childNodes[2].getAttribute('width')); + assert.strictEqual('20', svg.childNodes[2].getAttribute('height')); + + done(); + }); + }); + test('Bootstrap', function() { var div = document.createElement('div'); div.innerHTML =