Re: Element.create(): a proposal for more convenient element creation
On Sat, Aug 6, 2011 at 9:05 AM, Dominic Cooney domin...@google.com wrote: Third, is the order of attributes significant for XML namespace declarations? eg does this: x xmlns:foo=… foo:bar=… / mean the same thing as x foo:bar=… xmlns:foo=… / ? If not, including namespaces in the attribute dictionary is fraught, because the iteration order of properties is undefined. The order is unimportant when setting them via markup, but important when setting them via successive setAttribute calls. I'd prefer that the attribute bag be handled like markup attributes, where xmlns attributes are handled early so that later attributes fall into the correct namespace. ~TJ
Re: Element.create(): a proposal for more convenient element creation
On Mon, Aug 8, 2011 at 12:52 AM, Tab Atkins Jr. jackalm...@gmail.com wrote: On Sat, Aug 6, 2011 at 9:05 AM, Dominic Cooney domin...@google.com wrote: Third, is the order of attributes significant for XML namespace declarations? eg does this: x xmlns:foo=… foo:bar=… / mean the same thing as x foo:bar=… xmlns:foo=… / ? If not, including namespaces in the attribute dictionary is fraught, because the iteration order of properties is undefined. The order is unimportant when setting them via markup, but important when setting them via successive setAttribute calls. I'd prefer that the attribute bag be handled like markup attributes, where xmlns attributes are handled early so that later attributes fall into the correct namespace. Is there a reason to support namespaced attributes at all? They are extremely rare, especially on the web. Ideally I'd like to deprecate them, but I suspect that's not doable. But I see no reason to support them in new APIs. / Jonas
Re: Element.create(): a proposal for more convenient element creation
On 8/6/11, Charles Pritchard ch...@jumis.com wrote: [...] I've stated in prior threads, that unless the word is aria-* or data-*, properties are set on the element. I see. But that's inherently inconsistent and mostly misleading (attr alludes to attribute not usually property except when it's data or aria). For setting properties, though, a `setOwnProperties` method could be convenient. -- Garrett
Re: Element.create(): a proposal for more convenient element creation
On 2011-08-08 10:17, Jonas Sicking wrote: On Mon, Aug 8, 2011 at 12:52 AM, Tab Atkins Jr.jackalm...@gmail.com wrote: On Sat, Aug 6, 2011 at 9:05 AM, Dominic Cooneydomin...@google.com wrote: Third, is the order of attributes significant for XML namespace declarations? eg does this: x xmlns:foo=… foo:bar=… / mean the same thing as x foo:bar=… xmlns:foo=… / ? If not, including namespaces in the attribute dictionary is fraught, because the iteration order of properties is undefined. The order is unimportant when setting them via markup, but important when setting them via successive setAttribute calls. I'd prefer that the attribute bag be handled like markup attributes, where xmlns attributes are handled early so that later attributes fall into the correct namespace. Is there a reason to support namespaced attributes at all? They are extremely rare, especially on the web. Ideally I'd like to deprecate them, but I suspect that's not doable. But I see no reason to support them in new APIs. Isn't basic support cheap to get? Just allow the Clark notation ({ns}local) for the attribute name. Best regards, Julian
Re: Element.create(): a proposal for more convenient element creation
On Mon, Aug 8, 2011 at 2:17 AM, Julian Reschke julian.resc...@gmx.de wrote: On 2011-08-08 10:17, Jonas Sicking wrote: On Mon, Aug 8, 2011 at 12:52 AM, Tab Atkins Jr.jackalm...@gmail.com wrote: On Sat, Aug 6, 2011 at 9:05 AM, Dominic Cooneydomin...@google.com wrote: Third, is the order of attributes significant for XML namespace declarations? eg does this: x xmlns:foo=… foo:bar=… / mean the same thing as x foo:bar=… xmlns:foo=… / ? If not, including namespaces in the attribute dictionary is fraught, because the iteration order of properties is undefined. The order is unimportant when setting them via markup, but important when setting them via successive setAttribute calls. I'd prefer that the attribute bag be handled like markup attributes, where xmlns attributes are handled early so that later attributes fall into the correct namespace. Is there a reason to support namespaced attributes at all? They are extremely rare, especially on the web. Ideally I'd like to deprecate them, but I suspect that's not doable. But I see no reason to support them in new APIs. Isn't basic support cheap to get? Just allow the Clark notation ({ns}local) for the attribute name. First off, that's infinitely more work to support a rarely used feature than not supporting it at all. Second, since that notation isn't used anywhere else, it's a pretty big cost in brain print for users. So no, I wouldn't say it's cheap. / Jonas
Re: Element.create(): a proposal for more convenient element creation
On 2011-08-08 11:34, Jonas Sicking wrote: ... First off, that's infinitely more work to support a rarely used feature than not supporting it at all. Second, since that notation isn't used anywhere else, it's a pretty big cost in brain print for users. So no, I wouldn't say it's cheap. ... Well, it's cheap in that it needs no new API signature and uses a notation that is already well-established. Best regards, Julian
Re: Element.create(): a proposal for more convenient element creation
On Mon, Aug 8, 2011 at 1:17 AM, Jonas Sicking jo...@sicking.cc wrote: Is there a reason to support namespaced attributes at all? They are extremely rare, especially on the web. Ideally I'd like to deprecate them, but I suspect that's not doable. But I see no reason to support them in new APIs. SVG requires namespaced attributes for xlink, at least. We're planning to get rid of that in SVG2, but for now it would be necessary. We could, of course, just say Too bad, don't write things that need the xlink namespace, and wait for SVG2 to get rid of them. I don't think this would be very bad. ~TJ
Re: Element.create(): a proposal for more convenient element creation
On Mon, Aug 8, 2011 at 9:17 AM, Tab Atkins Jr. jackalm...@gmail.com wrote: On Mon, Aug 8, 2011 at 1:17 AM, Jonas Sicking jo...@sicking.cc wrote: Is there a reason to support namespaced attributes at all? They are extremely rare, especially on the web. Ideally I'd like to deprecate them, but I suspect that's not doable. But I see no reason to support them in new APIs. SVG requires namespaced attributes for xlink, at least. We're planning to get rid of that in SVG2, but for now it would be necessary. We could, of course, just say Too bad, don't write things that need the xlink namespace, and wait for SVG2 to get rid of them. I don't think this would be very bad. Yup, that's my take on it. It's easy enough for people to write two lines of code instead of one for now. / Jonas
Re: Element.create(): a proposal for more convenient element creation
Element.create looks neat. Three thoughts: First, I think Element.create *and* constructors like new HTMLDivElement(attributes, children) are both useful. Element.create is good when you have a tag name in hand, are creating unknown elements, or are creating elements that don’t have a specific constructor (ins/del.) New is good when you’re creating an element “statically.” It’s succinct, and if you misspell the name you get an exception instead of an unknown element, for example: Element.create('vdieo', {src: '…'}) → no error, HTMLUnknownElement that behaves nothing like video new HTMLVdieoElement({src: '…'}) → ReferenceError, stack trace points me to the faulty line of code. When the element being created is “static” I think constructors are more readable, too: var b = Element.create('button', {}, [ Element.create('img', {src: 'http://…'}), document.createTextNode('Click me!') ]); compared to: var b = new HTMLButtonElement({}, [ new Image('http://…'), new TextNode('Click me!') ]); Let me briefly reiterate that I think we want *both* Element.create and constructors; they have complementary uses. --- Second, re: setAttribute vs setting properties, there might be types other than functions we want to not treat as strings; for example if a UA implements CSSOM it might be nice to be able to set a style without having to serialize and reparse the CSSStyleDeclaration. Can we spec whether something in the attributes hash is set via setAttribute or via setting a property based on the IDL for that element? Alternatively we could provide a syntax, eg '@class': 'foo' to setAttribute('class', 'foo') and className: 'foo' to set elem.className = 'foo'. -- Third, is the order of attributes significant for XML namespace declarations? eg does this: x xmlns:foo=… foo:bar=… / mean the same thing as x foo:bar=… xmlns:foo=… / ? If not, including namespaces in the attribute dictionary is fraught, because the iteration order of properties is undefined. Dominic On Fri, Aug 5, 2011 at 3:22 PM, Garrett Smith dhtmlkitc...@gmail.comwrote: On 8/4/11, Garrett Smith dhtmlkitc...@gmail.com wrote: [...] ser-generated function function. The scope of handler attributes is explained in HTML 5, though incompletely: http://dev.w3.org/html5/spec/Overview.html#event-handler-content-attributes That's incomplete. Correction: It is complete, I just misread it. -- Garrett
Re: Element.create(): a proposal for more convenient element creation
On 8/6/2011 9:05 AM, Dominic Cooney wrote: Element.create looks neat. Three thoughts: ... Let me briefly reiterate that I think we want *both* Element.create and constructors; they have complementary uses. I agree. Second, re: setAttribute vs setting properties, there might be types other than functions we want to not treat as strings; for example if a UA implements CSSOM it might be nice to be able to set a style without having to serialize and reparse the CSSStyleDeclaration. Can we spec whether something in the attributes hash is set via setAttribute or via setting a property based on the IDL for that element? How about .attributes as another reserved word: Element.create('div', { attributes: { 'class': 'foo'} }); Element.create('div', { attributes: [ 'class','foo','class','bar'] } ).attr({textContent: 'Bar class'}); For reserved words: aria-*, data-* are always a DOMString via setAttribute and .attributes is an object or array used to run additional setAttribute calls. If attributes were to accept a DOMString: Element.create('div', { attributes: 'i-replaced=InnerHTML style=font-size: 2em' }); ... Relevant to the discussion is Doug's createChild proposal: http://www.w3.org/Graphics/SVG/WG/wiki/Simple_SVG_API#createChild Doug adds an index integer as the third argument, something to consider. Passing 0 as an argument is easier than firstChild().insertBefore() semantics. Example: parentElement.createChildNS( htmlns, 'div', { data-test: 'test' }, 0); // add to parent at position: 0. Position could be a helpful abstraction: Element.create('div').create(span,{textContent: 'second node'}). position(0).create('span', {textContent: 'first node'}); divspanfirst node/spanspansecond node/span Element.create('div').create('div').create('span', {textContent: 'span node in two divs'}). position(-1,0).create('span', {textContent: 'span node in first div, first child.'}); divspanspan node in first div, first child/span divspanspan node in two divs/span/div/div Could be handy to use with querySelector. -Charles
Re: Element.create(): a proposal for more convenient element creation
On 8/6/11, Charles Pritchard ch...@jumis.com wrote: On 8/6/2011 9:05 AM, Dominic Cooney wrote: Element.create looks neat. Three thoughts: ... Let me briefly reiterate that I think we want *both* Element.create and constructors; they have complementary uses. I agree. And for no reason, it seems. Second, re: setAttribute vs setting properties, there might be types other than functions we want to not treat as strings; for example if a UA implements CSSOM it might be nice to be able to set a style without having to serialize and reparse the CSSStyleDeclaration. Can we spec whether something in the attributes hash is set via setAttribute or via setting a property based on the IDL for that element? How about .attributes as another reserved word: Element.create('div', { attributes: { 'class': 'foo'} }); Element.create('div', { attributes: [ 'class','foo','class','bar'] } ).attr({textContent: 'Bar class'}); textContent is a property, not an attribute. Properties vs attributes was already explained in this thread. [...] -- Garrett
Re: Element.create(): a proposal for more convenient element creation
On 8/6/2011 3:54 PM, Garrett Smith wrote: On 8/6/11, Charles Pritchardch...@jumis.com wrote: On 8/6/2011 9:05 AM, Dominic Cooney wrote: Element.create looks neat. Three thoughts: ... Let me briefly reiterate that I think we want *both* Element.create and constructors; they have complementary uses. I agree. And for no reason, it seems. Dominic stated several reasons. (Element.create('div') instanceof HTMLDivElement); Second, re: setAttribute vs setting properties, there might be types other than functions we want to not treat as strings; for example if a UA implements CSSOM it might be nice to be able to set a style without having to serialize and reparse the CSSStyleDeclaration. Can we spec whether something in the attributes hash is set via setAttribute or via setting a property based on the IDL for that element? How about .attributes as another reserved word: Element.create('div', { attributes: { 'class': 'foo'} }); Element.create('div', { attributes: [ 'class','foo','class','bar'] } ).attr({textContent: 'Bar class'}); textContent is a property, not an attribute. Properties vs attributes was already explained in this thread. [...] I've stated in prior threads, that unless the word is aria-* or data-*, properties are set on the element. Here, I've added attributes as another reserved word, for setting attributes. The proposed attr() method sets properties, as create() does. Element.create('div',{className: 'class'}).attr({className: 'class ', attributes: {'class': 'class'}).getAttribute('class') == 'class';
Re: Element.create(): a proposal for more convenient element creation
On 8/4/11, Garrett Smith dhtmlkitc...@gmail.com wrote: [...] ser-generated function function. The scope of handler attributes is explained in HTML 5, though incompletely: http://dev.w3.org/html5/spec/Overview.html#event-handler-content-attributes That's incomplete. Correction: It is complete, I just misread it. -- Garrett
Re: Element.create(): a proposal for more convenient element creation
On Wed, Aug 3, 2011 at 8:10 AM, Tab Atkins Jr. jackalm...@gmail.com wrote: On Wed, Aug 3, 2011 at 12:34 AM, Anne van Kesteren ann...@opera.com wrote: On Tue, 02 Aug 2011 20:31:04 +0200, Tab Atkins Jr. jackalm...@gmail.com wrote: On Tue, Aug 2, 2011 at 11:26 AM, Glenn Maynard gl...@zewt.org wrote: On Tue, Aug 2, 2011 at 2:18 PM, Tab Atkins Jr. jackalm...@gmail.com wrote: MooTools is basically identical to Prototype, except that you can additionally set listeners on the element during creation by using a magical events property in the attribute bag, which takes an object of event names and functions. This would be nice to look into adding. Is this much better than just saying eg. Element.create(a, {href: http://link;, onclick: function(e) { ... } }, link}? Hmm, is everything exposed as on* attributes now? If so, then yeah, just do that; no need to mess around with a magic property in the attributes bag. This would still be magical as it is setting an IDL attribute rather than a content attribute. Hmm. onclick is a content attribute, no? Or do you just mean that assigning a function directly (rather than a string of code) is something that can only be done via an IDL attribute? If so, then good point, but I also expect that this wouldn't be very confusing. It would seem very inconsistent if some attributes are set using elem.setAttribute and others using elem.foo=bar. Would you make the distinction based on that the attribute name starts with on? One possible solution would be to be able to specify event handler attributes in a second object, so something like: Element.create(a, { href: ... }, { onclick: function(e) { ... } }, link, anotherChild); On the other hand, it might be ok to say that all attributes whose name start with on and whose value is a Function object is set using the IDL property rather than setAttribute. / Jonas
Re: Element.create(): a proposal for more convenient element creation
On 8/4/11, Jonas Sicking jo...@sicking.cc wrote: On Wed, Aug 3, 2011 at 8:10 AM, Tab Atkins Jr. jackalm...@gmail.com wrote: On Wed, Aug 3, 2011 at 12:34 AM, Anne van Kesteren ann...@opera.com wrote: On Tue, 02 Aug 2011 20:31:04 +0200, Tab Atkins Jr. jackalm...@gmail.com wrote: On Tue, Aug 2, 2011 at 11:26 AM, Glenn Maynard gl...@zewt.org wrote: On Tue, Aug 2, 2011 at 2:18 PM, Tab Atkins Jr. jackalm...@gmail.com wrote: MooTools is basically identical to Prototype, except that you can additionally set listeners on the element during creation by using a magical events property in the attribute bag, which takes an object of event names and functions. This would be nice to look into adding. Is this much better than just saying eg. Element.create(a, {href: http://link;, onclick: function(e) { ... } }, link}? Hmm, is everything exposed as on* attributes now? If so, then yeah, just do that; no need to mess around with a magic property in the attributes bag. This would still be magical as it is setting an IDL attribute rather than a content attribute. Hmm. onclick is a content attribute, no? Or do you just mean that assigning a function directly (rather than a string of code) is something that can only be done via an IDL attribute? There is an event handler attribute named onclick. There is an event handler property named onclick. Setting the property does not set the attribute. Setting the attribute results in the creation of a function with the value of that attribute as its FunctionBody and an augmented scope chain. When the attribute is set, the property gets that browser-generated function function. The scope of handler attributes is explained in HTML 5, though incompletely: http://dev.w3.org/html5/spec/Overview.html#event-handler-content-attributes That's incomplete. The scope chain of an event handler attribute for a form control would function as so: | input type=text onclick=alert([form, type]); value=test function anonymous() { with(document) { with(this.form) { with(this) { alert([form, type]); } } } }; Or alternatively: document.forms[0].elements[0].setAttribute(onclick, alert(form, type])); Result: [object HTMLFormElement],text Setting the property does not change the attribute. They're two different things. If so, then good point, but I also expect that this wouldn't be very confusing. I can see why you'd say that, but the fact is that attributes and properties are different things. If you take good care not to assign ID and NAME like form or body (yeah, Google doesn't really heed that rule very well), you might not see too many problems. And if you never ever use event handler attributes, you won't get stung by scope augmentation bugs. I wrote an article on this but Jim's server is perpetually down (as is my site now). Unsafe Names for Form Controls. Google cache: http://webcache.googleusercontent.com/search?q=cache:VLOWitVtytgJ:www.jibbering.com/faq/names/event_handler.html+%22Event+Handler+Scope%22+jibberingcd=1hl=enct=clnkgl=usclient=safarisource=www.google.com See also: http://code.google.com/p/chromium/issues/detail?id=80911q=bzbarskycolspec=ID%20Stars%20Pri%20Area%20Feature%20Type%20Status%20Summary%20Modified%20Owner%20Mstone%20OS Though also explained many many years ago by Cornford on c.l.js. It would seem very inconsistent if some attributes are set using elem.setAttribute and others using elem.foo=bar. Yeah, inconsistent. Sounds like jQuery. Would you make the distinction based on that the attribute name starts with on? I'm pretty sure Jonas would not do that. One possible solution would be to be able to specify event handler attributes in a second object, so something like: Element.create(a, { href: ... }, { onclick: function(e) { ... } }, link, anotherChild); The scope augmentation that goes along with the event handler attribute is undesirable here. -- Garrett
Re: Element.create(): a proposal for more convenient element creation
On Tue, 02 Aug 2011 20:31:04 +0200, Tab Atkins Jr. jackalm...@gmail.com wrote: On Tue, Aug 2, 2011 at 11:26 AM, Glenn Maynard gl...@zewt.org wrote: On Tue, Aug 2, 2011 at 2:18 PM, Tab Atkins Jr. jackalm...@gmail.com wrote: MooTools is basically identical to Prototype, except that you can additionally set listeners on the element during creation by using a magical events property in the attribute bag, which takes an object of event names and functions. This would be nice to look into adding. Is this much better than just saying eg. Element.create(a, {href: http://link;, onclick: function(e) { ... } }, link}? Hmm, is everything exposed as on* attributes now? If so, then yeah, just do that; no need to mess around with a magic property in the attributes bag. This would still be magical as it is setting an IDL attribute rather than a content attribute. -- Anne van Kesteren http://annevankesteren.nl/
Re: Element.create(): a proposal for more convenient element creation
On 8/3/2011 8:51 AM, Anne van Kesteren wrote: On Wed, 03 Aug 2011 17:46:50 +0200, Glenn Maynard gl...@zewt.org wrote: What's the difference? ele.setAttribute(x, val) works on any element. ele[x] = val does not. They also behave differently for a large number of cases and the latter often takes values of a type other than DOMString. Seems to me that aria- and data- prefixes are a special case: data-* and aria-* should always run through the setAttribute code path. IE9 does have aria attributes on the element as well, in camel case: element.ariaSelected===element.getAttribute('aria-selected') It's always going to be the case, that setting 'data-*' or 'aria-*' will assign a DOM string content attribute. I'd expect this: a = Element.create(a, {href: http://link;, onclick: function(e) { }, custom: value }, link); to be essentially equivalent to a = document.createElement(a); a.appendChild(document.createTextNode(link)); attrs = {href: http://link;, onclick: function(e) { }, custom: value }; for(key in attrs) a[key] = attrs[key]; Would you expect to write contenteditable as contenteditable or as contentEditable? Also, would you expect custom to end up as a content attribute on that link element? Because it will not with this code. contentEditable, tabIndex, innerHTML seem appropriate. data-* and aria-* should always run through the setAttribute code path. The DOM footprint should be light. Example: Element.create('a', { webkitShadow: Element.create('p','example shadow paragraph') }, 'this is a link button') . attr({role: 'button', onclick: function() { alert('clicked!') }). attr({tabIndex: 0, data-status: 'this is an example', custom-attribute: 'not serialized'}). attr({title: 'title example!', href: 'link.html'}); outerHTML, more or less: a title=title example! role=button tabindex=0 data-status=this is an example href=link.htmlthis is a link amp; button/a webkitShadow here: https://lists.webkit.org/pipermail/webkit-dev/2011-June/017340.html If an author already has their string sanitized, they would pass through the innerHTML attribute anyway. var x = document.createElement; has not been a reliable shortcut. var x = Element.create(); could be. -Charles
Re: Element.create(): a proposal for more convenient element creation
On Aug 1, 2011, at 8:36 PM, João Eiras wrote: On , Ian Hickson i...@hixie.ch wrote: On Mon, 1 Aug 2011, Ryosuke Niwa wrote: On Mon, Aug 1, 2011 at 6:33 PM, Maciej Stachowiak m...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children�) Can we alternatively extend document.createElement? Or was this intentionally avoided to associate new elements with documents? We could, but I'd much rather have the shorter name, personally. Having the name be so long really makes that API unusable. However, Nodes need a ownerDocument, and that needs to be supplied, even if optionally. Doing document.createElement implies the document, Element.create does not. The intent is that it supplies the Window's current Document. It's true that sometimes you need to make a node for another Document, sometimes even one that lacks a namespace, but that's a sufficiently specialized case that it does not really need a convenience shortcut. Regards, Maciej
Re: Element.create(): a proposal for more convenient element creation
On Aug 1, 2011, at 8:43 PM, Tab Atkins Jr. wrote: On Mon, Aug 1, 2011 at 7:05 PM, Charles Pritchard ch...@jumis.com wrote: Can we have it 'inherit' a parent namespace, and have chaining properties? Element.create('div').create('svg').create('g').create('rect', {title: 'An svg rectangle in an HTML div'}); Ooh, so .create is defined both on Element (defaults to HTML namespace, just creates an element) and on Element.prototype (defaults to namespace of the element, inserts as a child)? That's pretty interesting. Presumably the new element gets inserted as a last child of the parent. I like it. With just the old propose you could get the same effect like this: Element.create('div', {}, Element.create('svg', {}, Element.create('g', {}, Element.create('rect', {title: 'An svg rectangle in an HTML div'} Chaining .create() is certainly less verbose. Doesn't work as well for inserting multiple children into an element though. Regards, Maciej
Re: Element.create(): a proposal for more convenient element creation
On Aug 1, 2011, at 9:25 PM, Ian Hickson i...@hixie.ch wrote: On Tue, 2 Aug 2011, João Eiras wrote: While the idea is interesting, create is a too simple name to add on something as polluted as Element. Why? I think create() is fine. It's a pretty common name for a factory or constructor (in languages with named constructors), and having it on the interface object makes it pretty clear what it's a factory for. If we can get this chained, the .attr({key:val}) syntax is handy at times, too, if / when applied to existing items. At that point, it's very similar to the popular helpers out there, esp, jQuery. One nice aspect of that is that those package maintainers can feature test for the native model, even if it's a long-name to type. Might slightly (very slightly) improve performance in such code bases.
Re: Element.create(): a proposal for more convenient element creation
On Mon, Aug 1, 2011 at 6:33 PM, Maciej Stachowiak m...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children…) Creates an element with the specified tag, attributes, and children. tagName - tag name as a string; by default it does smart selection of SVG, HTML or MathML namespace. Authors can also use an html: svg: or mathml: prefix to override these defaults. (And further, you can use xmlns in attribute map to use a custom namespace.) attributeMap - JS object-as-dictonary or whatever dictionary type is appropriate to the language, or null for no attributes children… - veridic parameter, can include nodes, strings, or arrays. Strings are converted to text nodes. Arrays are unpacked and treated as lists of nodes/strings. Array support is for cases where you want to have a call-site that may take a veriable-length list, with possible prefix and suffix. Examples: Element.create(a, {href: http://google.com/}, Google} Element.create(p, null, Please consider these instructions , Element.create(em, {class: intense}, very), carefully) Element.create('svg:a', {href: 'example.html'}, 'Click Me! Yay bad link text!'); Element.create('select', {multi: ''}, optionArray); The default namespace mapping would be HTML, with possibly SVG or MathML elements that don't localName-collide with HTML elements mapping to their default namespace. I'm not sure if it's better to include the children as a var-args list, or as an array. Certainly when typing things normally var-args saves you the [ and ], but when coding, if you've built the child list dynamically and have an array, you have to make awkward .apply calls. Why Element.create() instead of new Element()? It's a factory method. In general it returns instances of many different classes. new Foo() carries a strong expectation of returning a direct instance of Foo, not one of several subclasses. This doesn't explain why a factory method is better than explicit constructors though? The above could be written as new HTMLParagraphElement(null, foo, ...); However I'm not sure what to do in situations where we don't have an explicit interface for an element, such as both ins and del both using HTMLModElement, and the long list of elements which only use HTMLElement as interface. cc'ing Alex Russel who is often a strong advocate for constructors over factory functions and who might have thought about this problem. / Jonas
Re: Element.create(): a proposal for more convenient element creation
On Tue, Aug 2, 2011 at 4:36 PM, Jonas Sicking jo...@sicking.cc wrote: This doesn't explain why a factory method is better than explicit constructors though? The above could be written as new HTMLParagraphElement(null, foo, ...); It's not a general use case, but at least when it comes to XBL-like components, having a factory method that does all the lookup and binding behing the scenes probably is easier to implement than hooking a constructor (FWIW). However I'm not sure what to do in situations where we don't have an explicit interface for an element, such as both ins and del both using HTMLModElement, and the long list of elements which only use HTMLElement as interface. cc'ing Alex Russel who is often a strong advocate for constructors over factory functions and who might have thought about this problem. Cheers, - Roland
Re: Element.create(): a proposal for more convenient element creation
On Tue, Aug 2, 2011 at 1:27 AM, Roland Steiner rolandstei...@google.com wrote: On Tue, Aug 2, 2011 at 4:36 PM, Jonas Sicking jo...@sicking.cc wrote: This doesn't explain why a factory method is better than explicit constructors though? The above could be written as new HTMLParagraphElement(null, foo, ...); It's not a general use case, but at least when it comes to XBL-like components, having a factory method that does all the lookup and binding behing the scenes probably is easier to implement than hooking a constructor (FWIW). I am not sure it will be easier but it does seem that it would be more natural to an author to write: var foo = new FooButton(); than: var foo = Element.create('x-foo-button'). :DG
Re: Element.create(): a proposal for more convenient element creation
On Mon, Aug 1, 2011 at 9:33 PM, Maciej Stachowiak m...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children…) Creates an element with the specified tag, attributes, and children. How does this compare to popular JS helper libraries like jQuery? It would be useful to know what convenience APIs authors are using now before introducing our own.
Re: Element.create(): a proposal for more convenient element creation
On Tue, 2 Aug 2011, Dimitri Glazkov wrote: On Tue, Aug 2, 2011 at 1:27 AM, Roland Steiner rolandstei...@google.com wrote: On Tue, Aug 2, 2011 at 4:36 PM, Jonas Sicking jo...@sicking.cc wrote: This doesn't explain why a factory method is better than explicit constructors though? The above could be written as new HTMLParagraphElement(null, foo, ...); It's not a general use case, but at least when it comes to XBL-like components, having a factory method that does all the lookup and binding behing the scenes probably is easier to implement than hooking a constructor (FWIW). I am not sure it will be easier but it does seem that it would be more natural to an author to write: var foo = new FooButton(); than: var foo = Element.create('x-foo-button'). One of the principles behind XB2L's design was graceful degradation, such that sites would still mostly work without the bindings being applies. It seems that if we're creating proprietary elements, that won't work. So I'm not sure this is a use case we should be addressing. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: Element.create(): a proposal for more convenient element creation
On Tue, Aug 2, 2011 at 10:37 AM, Ian Hickson i...@hixie.ch wrote: On Tue, 2 Aug 2011, Dimitri Glazkov wrote: On Tue, Aug 2, 2011 at 1:27 AM, Roland Steiner rolandstei...@google.com wrote: On Tue, Aug 2, 2011 at 4:36 PM, Jonas Sicking jo...@sicking.cc wrote: This doesn't explain why a factory method is better than explicit constructors though? The above could be written as new HTMLParagraphElement(null, foo, ...); It's not a general use case, but at least when it comes to XBL-like components, having a factory method that does all the lookup and binding behing the scenes probably is easier to implement than hooking a constructor (FWIW). I am not sure it will be easier but it does seem that it would be more natural to an author to write: var foo = new FooButton(); than: var foo = Element.create('x-foo-button'). One of the principles behind XB2L's design was graceful degradation, such that sites would still mostly work without the bindings being applies. It seems that if we're creating proprietary elements, that won't work. So I'm not sure this is a use case we should be addressing. We should have a good discussion about whether we should be aiming to subclass/extend DOM elements. Though in this particular context, graceful degradation is a useless concept: you're building DOM imperatively using APIs that haven't even yet even been invented properly. :DG
Re: Element.create(): a proposal for more convenient element creation
On Tue, Aug 2, 2011 at 12:36 AM, Jonas Sicking jo...@sicking.cc wrote: I'm not sure if it's better to include the children as a var-args list, or as an array. Certainly when typing things normally var-args saves you the [ and ], but when coding, if you've built the child list dynamically and have an array, you have to make awkward .apply calls. Read again - the idea is to auto-expand arrays. (I don't have much of a preference between just use an array and use varargs, but expand arrays. I agree that using only varargs without expansion would be bad.) ~TJ
Re: Element.create(): a proposal for more convenient element creation
On 8/2/2011 9:48 AM, Aryeh Gregor wrote: On Mon, Aug 1, 2011 at 9:33 PM, Maciej Stachowiakm...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children…) Creates an element with the specified tag, attributes, and children. How does this compare to popular JS helper libraries like jQuery? It would be useful to know what convenience APIs authors are using now before introducing our own. Here are three common helper libraries. http://mootools.net/docs/core/Element/Element var myAnchor = new Element('a', { href: 'http://mootools.net' }); // notes: namespacing requires escaping the colon \: // moo enables: new Element('a.className') as a shorthand. myAnchor.set({ key: val}); // styles and events are keywords. http://dojotoolkit.org/documentation/tutorials/1.6/dom_functions/ http://dojotoolkit.org/api/1.6/dojo var li = dojo.create(li, { innerHTML: Six}); // notes: dojo allows a third and fourth param to specify parent / child nodes and positioning. dojo.attr(li,{key: val}); http://api.jquery.com/attr/ var myAnchor = $('a href=http://api.jquery.com;'); myAnchor.attr({key: val}); // attr also acts as a getter, when a string is passed, and a computed setter, when a function is used for a value.
Re: Element.create(): a proposal for more convenient element creation
On Tue, Aug 2, 2011 at 9:48 AM, Aryeh Gregor a...@aryeh.name wrote: On Mon, Aug 1, 2011 at 9:33 PM, Maciej Stachowiak m...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children…) Creates an element with the specified tag, attributes, and children. How does this compare to popular JS helper libraries like jQuery? It would be useful to know what convenience APIs authors are using now before introducing our own. jQuery's element creation is basically driven by innerHTML. That is, to create an element, you just make a call like $('p class=foo'). I doubt that's a pattern we actually want to copy, as it's kinda dirty, and inconvenient in some cases. (For example, to apply a bag of properties as attributes, you have to first create the element, then call attr() on it. You can't pass the attrs as an initial arg without string-building.) Prototype's element creation is almost identical to what is proposed here, except it uses something that looks like a constructor. You create an element with new Element('p',{class:'foo'}). You can't set children as part of the initial call; they have to be appended in later calls. MooTools is basically identical to Prototype, except that you can additionally set listeners on the element during creation by using a magical events property in the attribute bag, which takes an object of event names and functions. This would be nice to look into adding. Dojo uses a factory method fairly similar to what's proposed (with the same name, even - Dojo.create()). Its first two arguments are the tagname and an attribute bag, same as the proposal. Its next two arguments are used to set a parent node and offset within that parent node, for automatic DOM insertion after creation. I don't think it's valuable to have this in the constructor, though the facilities that the libraries offer for easier DOM insertion should definitely be looked at separately. I think those are the major libraries to pay attention to. It looks like jQuery's model is probably not something we want to emulate, while the other three libraries are almost identical to this proposal. The one thing I suggest looking into is the ability to set listeners on an element during creation, like MooTools allows. ~TJ
Re: Element.create(): a proposal for more convenient element creation
On Tue, Aug 2, 2011 at 2:05 PM, Tab Atkins Jr. jackalm...@gmail.com wrote: Read again - the idea is to auto-expand arrays. (I don't have much of a preference between just use an array and use varargs, but expand arrays. I agree that using only varargs without expansion would be bad.) I'm against use varargs, but expand arrays if it would make sense to have one of the arguments be an array itself, as with Array.concat(), since then your code is going to mysteriously fail in the varargs case if you provide one argument that happens to be an array one time. It's also bad if we might want to add more arguments later. But in this case it seems fine. On Tue, Aug 2, 2011 at 2:12 PM, Charles Pritchard ch...@jumis.com wrote: http://mootools.net/docs/core/Element/Element . . . // moo enables: new Element('a.className') as a shorthand. . . . http://api.jquery.com/attr/ var myAnchor = $('a href=http://api.jquery.com;'); These both seem interesting. Allowing class or id to be specified as part of the first argument instead of the second one would make some very common use-cases simpler. Often you want to create some kind of wrapper with a static class or id, and Element.create(div.myClass) is both immediately understandable and significantly shorter than Element.create(div, {class: myClass}). The second one seems like it might be useful as a separate API. It could be a function that accepts a text/html string, and if the resulting tree has a single root node, it could return that. If not, it could return a DocumentFragment containing the result. Or maybe it could return a DocumentFragment unconditionally for consistency, so it would be like a much easier-to-use version of Range.createContextualFragment. Of course, this kind of thing is bad because it doesn't allow easy escaping, so maybe we shouldn't make it easier.
Re: Element.create(): a proposal for more convenient element creation
On Tue, Aug 2, 2011 at 2:18 PM, Tab Atkins Jr. jackalm...@gmail.com wrote: MooTools is basically identical to Prototype, except that you can additionally set listeners on the element during creation by using a magical events property in the attribute bag, which takes an object of event names and functions. This would be nice to look into adding. Is this much better than just saying eg. Element.create(a, {href: http://link http://google.com/, onclick: function(e) { ... } }, link}? -- Glenn Maynard
Re: Element.create(): a proposal for more convenient element creation
On 8/2/11, Tab Atkins Jr. jackalm...@gmail.com wrote: On Tue, Aug 2, 2011 at 9:48 AM, Aryeh Gregor a...@aryeh.name wrote: On Mon, Aug 1, 2011 at 9:33 PM, Maciej Stachowiak m...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children…) Creates an element with the specified tag, attributes, and children. How does this compare to popular JS helper libraries like jQuery? It Looking at it from a utilitarian perspective, I don't see why it matters. would be useful to know what convenience APIs authors are using now before introducing our own. jQuery's element creation is basically driven by innerHTML. That is, to create an element, you just make a call like $('p class=foo'). I doubt that's a pattern we actually want to copy, as it's kinda dirty, and inconvenient in some cases. (For example, to apply a bag of properties as attributes, Lost me on that one. Bag of properties? jQuery fumbled with confusing attributes and properties for many years. No idea what they do now, but probably similar. you have to first create the element, then call attr() on it. You can't pass the attrs as an initial arg without string-building.) Prototype's element creation is almost identical to what is proposed here, except it uses something that looks like a constructor. You create an element with new Element('p',{class:'foo'}). You can't set children as part of the initial call; they have to be appended in later calls. And that is the reason that it's no good to go messing with this. Prototype defines Element as a Function, there is the interface object that is an Object. MooTools is basically identical to Prototype, except that you can additionally set listeners on the element during creation by using a magical events property in the attribute bag, which takes an object of event names and functions. This would be nice to look into adding. Nope. [...] Big waste of time. -- Garrett
Re: Element.create(): a proposal for more convenient element creation
On Tue, Aug 2, 2011 at 11:26 AM, Glenn Maynard gl...@zewt.org wrote: On Tue, Aug 2, 2011 at 2:18 PM, Tab Atkins Jr. jackalm...@gmail.com wrote: MooTools is basically identical to Prototype, except that you can additionally set listeners on the element during creation by using a magical events property in the attribute bag, which takes an object of event names and functions. This would be nice to look into adding. Is this much better than just saying eg. Element.create(a, {href: http://link;, onclick: function(e) { ... } }, link}? Hmm, is everything exposed as on* attributes now? If so, then yeah, just do that; no need to mess around with a magic property in the attributes bag. ~TJ
Element.create(): a proposal for more convenient element creation
In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children…) Creates an element with the specified tag, attributes, and children. tagName - tag name as a string; by default it does smart selection of SVG, HTML or MathML namespace. Authors can also use an html: svg: or mathml: prefix to override these defaults. (And further, you can use xmlns in attribute map to use a custom namespace.) attributeMap - JS object-as-dictonary or whatever dictionary type is appropriate to the language, or null for no attributes children… - veridic parameter, can include nodes, strings, or arrays. Strings are converted to text nodes. Arrays are unpacked and treated as lists of nodes/strings. Array support is for cases where you want to have a call-site that may take a veriable-length list, with possible prefix and suffix. Examples: Element.create(a, {href: http://google.com/}, Google} Element.create(p, null, Please consider these instructions , Element.create(em, {class: intense}, very), carefully) Element.create('svg:a', {href: 'example.html'}, 'Click Me! Yay bad link text!'); Element.create('select', {multi: ''}, optionArray); The default namespace mapping would be HTML, with possibly SVG or MathML elements that don't localName-collide with HTML elements mapping to their default namespace. Why Element.create() instead of new Element()? It's a factory method. In general it returns instances of many different classes. new Foo() carries a strong expectation of returning a direct instance of Foo, not one of several subclasses. We could also add new Text('foo') for the cases where you want to create a text node without an element around it. Regards, Maciej
Re: Element.create(): a proposal for more convenient element creation
On Mon, 1 Aug 2011, Maciej Stachowiak wrote: Creates an element with the specified tag, attributes, and children. tagName - tag name as a string; by default it does smart selection of SVG, HTML or MathML namespace. Authors can also use an html: svg: or mathml: prefix to override these defaults. I'd suggest just always defaulting to HTML and requiring svg: and mathml: prefixes for those namespaces. That makes code easier to read (it's obvious what's going on, and you won't accidentally use elements from the wrong namespace). It also makes forward-compatibility easier (we don't have to worry about adding new elements to the list and what that will do to future legacy UAs). (And further, you can use xmlns in attribute map to use a custom namespace.) I wouldn't bother supporting the xmlns attribute in this API, but I don't feel strongly about this. attributeMap - JS object-as-dictonary or whatever dictionary type is appropriate to the language, or null for no attributes Optional attribute, too. children� - veridic parameter, can include nodes, strings, or arrays. Strings are converted to text nodes. Arrays are unpacked and treated as lists of nodes/strings. Array support is for cases where you want to have a call-site that may take a veriable-length list, with possible prefix and suffix. Also optional. So you could also do: var div = Element.create('div'); -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: Element.create(): a proposal for more convenient element creation
On Mon, Aug 1, 2011 at 6:33 PM, Maciej Stachowiak m...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children…) Can we alternatively extend document.createElement? Or was this intentionally avoided to associate new elements with documents? - Ryosuke
Re: Element.create(): a proposal for more convenient element creation
On Aug 1, 2011, at 6:43 PM, Ian Hickson i...@hixie.ch wrote: On Mon, 1 Aug 2011, Maciej Stachowiak wrote: Creates an element with the specified tag, attributes, and children. tagName - tag name as a string; by default it does smart selection of SVG, HTML or MathML namespace. Authors can also use an html: svg: or mathml: prefix to override these defaults. I'd suggest just always defaulting to HTML and requiring svg: and mathml: prefixes for those namespaces. Can we have it 'inherit' a parent namespace, and have chaining properties? Element.create('div').create('svg').create('g').create('rect', {title: 'An svg rectangle in an HTML div'});
Re: Element.create(): a proposal for more convenient element creation
On Mon, 1 Aug 2011, Ryosuke Niwa wrote: On Mon, Aug 1, 2011 at 6:33 PM, Maciej Stachowiak m...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children�) Can we alternatively extend document.createElement? Or was this intentionally avoided to associate new elements with documents? We could, but I'd much rather have the shorter name, personally. Having the name be so long really makes that API unusable. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: Element.create(): a proposal for more convenient element creation
On , Ian Hickson i...@hixie.ch wrote: On Mon, 1 Aug 2011, Ryosuke Niwa wrote: On Mon, Aug 1, 2011 at 6:33 PM, Maciej Stachowiak m...@apple.com wrote: In an IRC discussion with Ian Hickson and Tab Atkins, we can up with the following idea for convenient element creation: Element.create(tagName, attributeMap, children�) Can we alternatively extend document.createElement? Or was this intentionally avoided to associate new elements with documents? We could, but I'd much rather have the shorter name, personally. Having the name be so long really makes that API unusable. However, Nodes need a ownerDocument, and that needs to be supplied, even if optionally. Doing document.createElement implies the document, Element.create does not.
Re: Element.create(): a proposal for more convenient element creation
On 2/08/11 3:36 PM, João Eiras wrote: However, Nodes need a ownerDocument, and that needs to be supplied, even if optionally. Doing document.createElement implies the document, Element.create does not. I figure the ownerDocument would be window.document (where the window object is the global object that window.Element lives on).
Re: Element.create(): a proposal for more convenient element creation
On Mon, Aug 1, 2011 at 7:05 PM, Charles Pritchard ch...@jumis.com wrote: Can we have it 'inherit' a parent namespace, and have chaining properties? Element.create('div').create('svg').create('g').create('rect', {title: 'An svg rectangle in an HTML div'}); Ooh, so .create is defined both on Element (defaults to HTML namespace, just creates an element) and on Element.prototype (defaults to namespace of the element, inserts as a child)? That's pretty interesting. Presumably the new element gets inserted as a last child of the parent. I like it. ~TJ
Re: Element.create(): a proposal for more convenient element creation
On , Tab Atkins Jr. jackalm...@gmail.com wrote: On Mon, Aug 1, 2011 at 7:05 PM, Charles Pritchard ch...@jumis.com wrote: Can we have it 'inherit' a parent namespace, and have chaining properties? Element.create('div').create('svg').create('g').create('rect', {title: 'An svg rectangle in an HTML div'}); Ooh, so .create is defined both on Element (defaults to HTML namespace, just creates an element) and on Element.prototype (defaults to namespace of the element, inserts as a child)? That's pretty interesting. Presumably the new element gets inserted as a last child of the parent. I like it. While the idea is interesting, create is a too simple name to add on something as polluted as Element. I wonder if there is enough demand for this kind of chained coding to actually spec an API for this. I've rarely seen it being used, plus the notable exception that is jquery code. Perhaps createChild, would be better, but then one would need to differentiate Elements from Text.
Re: Element.create(): a proposal for more convenient element creation
On Tue, 2 Aug 2011, João Eiras wrote: However, Nodes need a ownerDocument, and that needs to be supplied, even if optionally. Doing document.createElement implies the document, Element.create does not. Just use the same document as new Image(), new Option(), or new Audio(). -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'