Element.createElement proposal

8 views
Skip to first unread message

Jonathan Watt

unread,
Aug 5, 2009, 4:52:20 AM8/5/09
to Johnny Stenback, Blake Kaplan, Jonas Sicking, Olli Pettay
Hi guys,

I've been thinking about what we can do to simplify the creation of new elements
using the DOM. I came up with a few ideas in the SVG WG, and I wondered what you
think about the following one (and how implementable it is in Mozilla). Please
bear with me to the end of the email.

It's really tedious and error prone that you have to do:

c = document.createElement('NS-people-dont-know-or-want-to-type', 'circle');
c.setAttribute('cx', '10');
c.setAttribute('cy', '10');
c.setAttribute('r', '10');
svgElement.appendChild(c);

Much better would be:

c = svgElement.createElement('circle', { cx: 10, cy: 10, r: 10} );
svgElement.appendChild(c);

or even just:

c = svgElement.createChild('circle', { cx: 10, cy: 10, r: 10} );

Basically, we'd add a createElement method to the Element interface, have it
create the new element in the same namespace as the element on which it's
called, and allow an (optional) JS object literal to be passed in to specify
attributes.

Apparently WebIDL will allow us to have optional arguments (for the attributes
argument) and to have PropertyBag type interfaces that ECMAScript bindings could
allow JS object literals to be substituted for. So it seems this could be done
spec-wise.

To avoid differences with the createElement method on the Document interface, it
would seem desirable to make the Document version behavior in a similar way with
regards to namespaces. HTML5 changes the behavior of Document.createElement to
always make it create an element in the HTML namespace (instead of the null
namespace) when called on an HTML document, so I was wondering if we could do
the same for SVG documents. At that point though, it seems like a cleaner and
more consistent solution would be to simply say that Document.createElement
creates an element in the same namespace as the document element (or null only
if it doesn't have a document element).

So it seems to me that the changes proposed are highly desirable from the user's
point of view, and that they're also specifiable. I guess it just comes down to
whether changing Document.createElement in this way would break much content
(doubtful since we'd be talking about non-HTML content?), and whether it's
implementable. Even if it would break small amounts of content, maybe it's worth
it if it's a solid step towards resolving the "namespaces are a nightmare" issue.

Thoughts?

Jonathan

Robert O'Callahan

unread,
Aug 10, 2009, 7:07:52 PM8/10/09
to
What about HTML5 SVG parsing? We want a solution that works well in an
HTML document.

So why not use the HTML5 parsing rules to determine which namespace the
element gets? The HTML5 parser already has a list of which elements
should be SVG or MathML.

Rob

Jonas Sicking

unread,
Aug 10, 2009, 7:21:29 PM8/10/09
to

That was my initial reaction too. Unfortunately there is overlap between
HTML names and SVG names. Specifically both languages have an <a>,
<style> and <script> elements. And as I understand it SVG might get a
<textarea> too.

In the parsing algorithm which one to use is determined by context. I.e.
an <a> inside a <svg> will be a svg-a.

/ Jonas

Jonas Sicking

unread,
Aug 10, 2009, 7:27:13 PM8/10/09
to

It's certainly implementable. Not sure when the property-bag thing would
happen, but I suspect it's something that other interfaces could use as
well.

In general I like the idea, but not sure how highly I would prioritize
it. And I would want to run this past other browser vendors to make sure
that they agree with. Unfortunately I don't think that w3c has any plans
to work on DOM-Core, so I'm not sure that we could get a formal spec on
this anytime soon.

/ Jonas

Johnny Stenback

unread,
Aug 10, 2009, 7:38:24 PM8/10/09
to Jonathan Watt, Blake Kaplan, Jonas Sicking, Olli Pettay
On 08/05/2009 01:52 AM, Jonathan Watt wrote:
> Hi guys,
>
> I've been thinking about what we can do to simplify the creation of new elements
> using the DOM. I came up with a few ideas in the SVG WG, and I wondered what you
> think about the following one (and how implementable it is in Mozilla). Please
> bear with me to the end of the email.
>
> It's really tedious and error prone that you have to do:
>
> c = document.createElement('NS-people-dont-know-or-want-to-type', 'circle');
> c.setAttribute('cx', '10');
> c.setAttribute('cy', '10');
> c.setAttribute('r', '10');
> svgElement.appendChild(c);
>
> Much better would be:
>
> c = svgElement.createElement('circle', { cx: 10, cy: 10, r: 10} );
> svgElement.appendChild(c);
>
> or even just:
>
> c = svgElement.createChild('circle', { cx: 10, cy: 10, r: 10} );
>

I still think element creation belongs on document objects more than it
does on elements. How about adding a createSVGElement method to our
documents instead? Since it'd be a new method, we could change the
signature of that to do things that are more developer friendly? Given
that HTML5 supports mixed in SVG, this would make some amount of sense
at least on HTML documents. Same goes for MathML too, I guess...


--
jst

Jonathan Watt

unread,
Aug 10, 2009, 8:03:54 PM8/10/09
to Robert O'Callahan

In addition to what Jonas says about tag name conflicts, making the DOM Core
spec use the HTML5 parsing rules would essentially be saying "screw you" to any
other languages that may have been using DOM Core for some time. Despite the
fact that the Web is the most important platform here, that doesn't really sit
well with me if we have a reasonable alternative, and I imagine that it'd meet
waaay more resistance. Using the same namespace as the element that the method
is called on makes it useful to all DOM consumers I think, and it's simple for
users to understand.

Jonathan

Jonathan Watt

unread,
Aug 10, 2009, 8:06:33 PM8/10/09
to Jonas Sicking

Such an a setAttributes (plural) method so you don't have to have multiple
setAttribute lines.

> In general I like the idea, but not sure how highly I would prioritize
> it. And I would want to run this past other browser vendors to make sure
> that they agree with. Unfortunately I don't think that w3c has any plans
> to work on DOM-Core, so I'm not sure that we could get a formal spec on
> this anytime soon.

Since the WebApps WG is taking on DOM 3 Events, maybe they could take on some
changes to DOM Core too?

Robert O'Callahan

unread,
Aug 10, 2009, 8:17:44 PM8/10/09
to
On 11/8/09 11:21 AM, Jonas Sicking wrote:
> That was my initial reaction too. Unfortunately there is overlap between
> HTML names and SVG names. Specifically both languages have an <a>,
> <style> and <script> elements. And as I understand it SVG might get a
> <textarea> too.

Not on my watch.

> In the parsing algorithm which one to use is determined by context. I.e.
> an <a> inside a <svg> will be a svg-a.

Let HTML win.

Rob

Robert O'Callahan

unread,
Aug 10, 2009, 8:18:33 PM8/10/09
to
On 11/8/09 12:03 PM, Jonathan Watt wrote:
> In addition to what Jonas says about tag name conflicts, making the DOM Core
> spec use the HTML5 parsing rules would essentially be saying "screw you" to any
> other languages that may have been using DOM Core for some time.

I wouldn't support changing any existing API behaviour. I would only add
new APIs like createChild. I'd probably call it something else, like
addChild.

Rob

Jonathan Watt

unread,
Aug 10, 2009, 8:22:33 PM8/10/09
to Johnny Stenback, Blake Kaplan, Jonas Sicking, Olli Pettay
On 2009-08-11 1:38 AM, Johnny Stenback wrote:
> On 08/05/2009 01:52 AM, Jonathan Watt wrote:
>> Hi guys,
>>
>> I've been thinking about what we can do to simplify the creation of new elements
>> using the DOM. I came up with a few ideas in the SVG WG, and I wondered what you
>> think about the following one (and how implementable it is in Mozilla). Please
>> bear with me to the end of the email.
>>
>> It's really tedious and error prone that you have to do:
>>
>> c = document.createElement('NS-people-dont-know-or-want-to-type', 'circle');
>> c.setAttribute('cx', '10');
>> c.setAttribute('cy', '10');
>> c.setAttribute('r', '10');
>> svgElement.appendChild(c);
>>
>> Much better would be:
>>
>> c = svgElement.createElement('circle', { cx: 10, cy: 10, r: 10} );
>> svgElement.appendChild(c);
>>
>> or even just:
>>
>> c = svgElement.createChild('circle', { cx: 10, cy: 10, r: 10} );
>>
>
> I still think element creation belongs on document objects more than it
> does on elements. How about adding a createSVGElement method to our
> documents instead? Since it'd be a new method, we could change the
> signature of that to do things that are more developer friendly? Given
> that HTML5 supports mixed in SVG, this would make some amount of sense
> at least on HTML documents. Same goes for MathML too, I guess...

Hmm. I'm not all that keen on the idea of adding separate methods like
createSVGElement, createMathMLElement and createXULElement (and
createHTMLElement?) for each namespace we may support now or in the future.
Allowing elements to create more elements on the other hand is less of a problem
to me I guess.

Jonathan

Jonathan Watt

unread,
Aug 10, 2009, 8:26:59 PM8/10/09
to Robert O'Callahan

I'm not at all keen on having such hidden gotchas.

Johnny Stenback

unread,
Aug 10, 2009, 8:39:43 PM8/10/09
to Jonathan Watt, Blake Kaplan, Jonas Sicking, Olli Pettay

I hear ya', and I'm not suggesting we do that for everything, only where
there's a real benefit to it, as I think is the case with SVG, given the
very complex DOM's you might find there.

What I don't like about svgElement.createElement() is that it seems a
bit odd to have to find an element to create one, which makes the case
where you're inserting SVG into a document where there is no existing
SVG such that developers still need to type out that namespace URI they
don't want to type out. svgElement.createChild() doesn't make any sense
to me as there's no child relationship between the element you use for
creating and the element that gets created.

> Jonathan

--
jst

Zack Weinberg

unread,
Aug 10, 2009, 9:06:39 PM8/10/09
to Johnny Stenback, Blake Kaplan, Olli, Pettay, Jonas Sicking, dev-te...@lists.mozilla.org
Johnny Stenback <j...@mozilla.com> wrote:
> What I don't like about svgElement.createElement() is that it seems a
> bit odd to have to find an element to create one, which makes the
> case where you're inserting SVG into a document where there is no
> existing SVG such that developers still need to type out that
> namespace URI they don't want to type out. svgElement.createChild()
> doesn't make any sense to me as there's no child relationship between
> the element you use for creating and the element that gets created.

What's wrong with

var parent = document.getElementById("putsvghere"); // HTML elt
var svg = parent.addChild('svg'); // HTML5 'svg' elt = SVG root elt
var circle = svg.addChild('circle', {...}); // SVG 'circle'

? The same would work for <math>.

zw

Johnny Stenback

unread,
Aug 10, 2009, 9:20:59 PM8/10/09
to Zack Weinberg, Blake Kaplan, Olli Pettay, Jonas Sicking, dev-te...@lists.mozilla.org

On 08/10/2009 06:06 PM, Zack Weinberg wrote:


> Johnny Stenback<j...@mozilla.com> wrote:
>> What I don't like about svgElement.createElement() is that it seems a
>> bit odd to have to find an element to create one, which makes the
>> case where you're inserting SVG into a document where there is no
>> existing SVG such that developers still need to type out that
>> namespace URI they don't want to type out. svgElement.createChild()
>> doesn't make any sense to me as there's no child relationship between
>> the element you use for creating and the element that gets created.
>

> What's wrong with
>
> var parent = document.getElementById("putsvghere"); // HTML elt
> var svg = parent.addChild('svg'); // HTML5 'svg' elt = SVG root elt
> var circle = svg.addChild('circle', {...}); // SVG 'circle'

What should that code do if you replace parent.addChild('svg') with
parent.addChild('a')? And does this always append, or insert at the
beginning, what if I want to insert somewhere in the middle etc etc?

>
> ? The same would work for<math>.
>
> zw

--
jst

Zack Weinberg

unread,
Aug 10, 2009, 9:28:27 PM8/10/09
to Johnny Stenback, Blake Kaplan, Olli, Pettay, Jonas Sicking, dev-te...@lists.mozilla.org
Johnny Stenback <j...@mozilla.com> wrote:
> > var parent = document.getElementById("putsvghere"); // HTML elt
> > var svg = parent.addChild('svg'); // HTML5 'svg' elt = SVG root
> > elt var circle = svg.addChild('circle', {...}); // SVG 'circle'
>
> What should that code do if you replace parent.addChild('svg') with
> parent.addChild('a')?

You get the HTML <a>. Does it *ever* make sense to have <svg:a> (or
<svg:anythingelse>) a direct child of <html:whatever>, rather than with
a <svg:svg> in between?

> And does this always append, or insert at the
> beginning, what if I want to insert somewhere in the middle etc etc?

I would expect "add" to mean appends, but I suppose you could have an
optional further argument which was either the element to insert after,
or magic constants for "at beginning"/"at end", like lseek().

zw

Jonas Sicking

unread,
Aug 10, 2009, 9:31:12 PM8/10/09
to

Yes, it's definitely WebApps WG turf, but currently WebApps isn't
chartered to revise DOM-Core.

/ Jonas

Jonas Sicking

unread,
Aug 10, 2009, 9:32:55 PM8/10/09
to

In the original proposal this would only work if the element with id
"putsvghere" is an SVG element (which I take it was not the case since
you add an <svg> element into it).

/ Jonas

Zack Weinberg

unread,
Aug 10, 2009, 9:47:58 PM8/10/09
to Jonas Sicking, dev-te...@lists.mozilla.org
Jonas Sicking <jo...@sicking.cc> wrote:

What I was trying to indicate with

// HTML5 'svg' elt = SVG root

is that creation of <svg> (or <math>) could magically switch that
element into the SVG (or MathML) namespace, just as in HTML5 parsing.

zw

Robert O'Callahan

unread,
Aug 11, 2009, 2:28:16 PM8/11/09
to
On 11/8/09 1:20 PM, Johnny Stenback wrote:
> On 08/10/2009 06:06 PM, Zack Weinberg wrote:
>> Johnny Stenback<j...@mozilla.com> wrote:
>>> What I don't like about svgElement.createElement() is that it seems a
>>> bit odd to have to find an element to create one, which makes the
>>> case where you're inserting SVG into a document where there is no
>>> existing SVG such that developers still need to type out that
>>> namespace URI they don't want to type out. svgElement.createChild()
>>> doesn't make any sense to me as there's no child relationship between
>>> the element you use for creating and the element that gets created.
>>
>> What's wrong with
>>
>> var parent = document.getElementById("putsvghere"); // HTML elt
>> var svg = parent.addChild('svg'); // HTML5 'svg' elt = SVG root elt
>> var circle = svg.addChild('circle', {...}); // SVG 'circle'
>
> What should that code do if you replace parent.addChild('svg') with
> parent.addChild('a')?

For simplicity I would say that e.addChild should always inherit the
namespace of e.

> And does this always append, or insert at the
> beginning, what if I want to insert somewhere in the middle etc etc?

I think it should always append. The use cases for the other positions
are much fewer and can be handled with existing DOM APIs.

The common case here is canvas-like scenarios where you already have an
SVG container and you're adding a lot of shapes to it.

Rob

Henri Sivonen

unread,
Oct 21, 2009, 7:00:34 AM10/21/09
to
In article <p9ydnZZQ6ODcJRzX...@mozilla.org>,

In article <OYGdncREgbrUNR3X...@mozilla.org>,


Robert O'Callahan <rob...@ocallahan.org> wrote:

> What about HTML5 SVG parsing? We want a solution that works well in an
> HTML document.
>
> So why not use the HTML5 parsing rules to determine which namespace the
> element gets? The HTML5 parser already has a list of which elements
> should be SVG or MathML.

The HTML5 parsing rules depend on context. Also, rules like deciding
what to do with <font> only make sense in parsing.

However, I like the idea of addChild() and I like the idea of being able
to pass attributes as a JS object of key-value pairs.

I suggest the following (inspired by the HTML5 parsing algorithm but
simplified and XBL2 attribute support added):

* Element.addChild(name, attrs=null): Creates an element in the same
namespace as |this| with the local name /name/. If attrs is not null,
adds attributes to the newly-created element as described below. Appends
the newly-created element as the last child of |this|.

- Exception: if |this| is in the http://www.w3.org/1999/xhtml
namespace or one of the elements that make the HTML5 parsing algorithm
allow HTML content: Behave like Document.createElement() below for the
element creation part.

* Document.createElement(name, attrs=null): If /name/ is "svg", creates
an element in the http://www.w3.org/2000/svg namespace with the local
name "svg". If the /name/ is "math", creates an element in the
http://www.w3.org/1998/Math/MathML namespace with the local name "math"
Otherwise, creates an element in the http://www.w3.org/1999/xhtml
namespace with the local name /name/. If attrs is not null, adds
attributes to the newly-created element as described below.

* Adding attributes extracts the key-value pairs from the JS object and
for each pair runs the following steps:
- If /key/ starts with "xml:", call
setAttributeNS("http://www.w3.org/XML/1998/namespace", key, value) on
the newly-created element.
- If /key/ starts with "xmlns:", call
setAttributeNS("http://www.w3.org/2000/xmlns/", key, value) on the
newly-created element.
- If /key/ starts with "xlink:", call
setAttributeNS("http://www.w3.org/1999/xlink", key, value) on the
newly-created element.
- If /key/ starts with "xbl:", call
setAttributeNS("http://www.w3.org/ns/xbl", key, value) on the
newly-created element.
- Otherwise, call setAttributeNS(null, key, value).

--
Henri Sivonen
hsiv...@iki.fi
http://hsivonen.iki.fi/

Robert O'Callahan

unread,
Oct 27, 2009, 6:44:02 PM10/27/09
to
Instead of using a JS object, it's probably more performant, and I think
slightly more convenient, to just specify extra arguments:
e.addChild("span", "class", "hello", "style", "width:100px");
You can write it as
e.addChild("span",
"class", "hello",
"style", "width:100px");
if you like.

Rob

Ted Mielczarek

unread,
Oct 28, 2009, 6:39:20 AM10/28/09
to dev-te...@lists.mozilla.org

That strikes me as less intuitive, and it also doesn't match what existing
JS libraries like jQuery provide:
http://docs.jquery.com/Attributes/attr#properties
http://docs.jquery.com/CSS/css#properties

-Ted

Mike Shaver

unread,
Oct 28, 2009, 8:09:14 AM10/28/09
to Ted Mielczarek, dev-te...@lists.mozilla.org
On Wed, Oct 28, 2009 at 6:39 AM, Ted Mielczarek
<ted.mie...@gmail.com> wrote:
> That strikes me as less intuitive, and it also doesn't match what existing
> JS libraries like jQuery provide:
> http://docs.jquery.com/Attributes/attr#properties
> http://docs.jquery.com/CSS/css#properties

I agree -- having to count out the strings to build the pairings of
attribute and value seems error-prone, and it's pretty hard to build
the parameters for such a call programmatically.

Mike

Reply all
Reply to author
Forward
0 new messages