- From: Rick Waldron <waldron.rick@gmail.com>
- Date: Thu, 27 Oct 2011 01:39:12 -0400
- To: Kentaro Hara <haraken@chromium.org>
- Cc: public-webapps@w3.org, Dominic Cooney <dominicc@chromium.org>
- Message-ID: <CAHfnhfoa6qtxB487XmUg4zVz6VdpzJjn6CurZs2AQY_oOWrW4w@mail.gmail.com>
On Thu, Oct 27, 2011 at 1:34 AM, Kentaro Hara <haraken@chromium.org> wrote: > Thanks, all! > > Adam: > > Another solution to that "more than one tag per interface" problem is> to > introduce subclasses of those interfaces for each tag. > I agree. "new HTMLInsElement()" is more consistent with other Element > constructors than "new HTMLModificationElement( {tagName: 'ins'} )". > > > Rick: > > As a developer that writes JavaScript every single day, > > the sheer amount of typed characters required for using > > the constructors in this proposal is enough for me to avoid it at all > costs. > > I think that > > new HTMLButtonElement( {disabled: true}, > [new Text("Click Me!!"), > new Image( {src: > "http://example.com/xxx.png"} ) ] ); > > is as simple as you write it using Element.create(), and is much > simpler and more readable than you write it using button.disabled and > button.appendChild(). In any way, consistency with other DOM > constructable objects and sub-typing are the advantages for letting > Elements have constructors, as I described in the first mail. > > No developer will ever opt-in to typing "HTMLButtonElement" over and over again - the amount of shift-key holding alone is unacceptable. > > >> (c) How to specify child Elements in the constructor argument > >> Possible approaches are as follows: > >> (c-1) As variable arguments, e.g. new HTMLButtonElement( { ... }, > child1, child2, child3, ...) > >> (c-2) As an array, e.g. new HTMLButtonElement( { ... }, [child1, child2, > child3] ) > >> (c-3) As variable arguments. We expand arguments of type array. e.g. new > HTMLButtonElement( { ... }, child1, [child2, child3], child4, ...) is > equivalent to new HTMLButtonElement({ ... }, child1, child2, child3, child4, > ...) > > Alex Russell told me a better idea, just making the children array an > optional "childNodes" or "children" property of the dictionary, like > this: > > new HTMLButtonElement( { disable: true, childNodes: [child1, > child2, ...] } ) > > We now do not need the second argument. I feel that just "a dictionary > of Element properties" in the first argument is easy-to-understand. > > > > 2011年10月27日8:07 Rick Waldron <waldron.rick@gmail.com>: > > > > As a developer that writes JavaScript every single day, the sheer amount > of typed characters required for using the constructors in this proposal is > enough for me to avoid it at all costs. > > > > > > On Tue, Oct 25, 2011 at 11:42 PM, Kentaro Hara <haraken@chromium.org> > wrote: > >> > >> Hi folks, > >> * Background * > >> I have been working on making DOM objects look and feel more like > ordinary JavaScript objects. I implemented Event constructors [1], for > example. > >> > >> * Proposal * > >> Element.create() has proposed and been under discussion [2]. Besides > Element.create(), I propose constructors for Elements, like "new > HTMLButtonElement(...)", "new HTMLDivElement(...)" and "new > HTMLVideoElement(...)". I think that both Element.create() *and* Element > constructors are useful. > >> For example, > >> var button = new HTMLButtonElement( {disabled: true}, > >> > [new TextNode("Click Me!!"), > >> > new Image( {src: "http://example.com/xxx.png"} ) ] ); > >> document.body.appendChild(button); > >> is equivalent to the following HTML: > >> <button disabled> > >> Click Me!! > >> <img src = "http://example.com/xxx.png" /> > >> </button> > >> As shown in above, the constructor has two arguments. The first one is a > dictionary of Element properties. The second one is an array of Nodes, which > become child nodes of the Element. > >> > >> * Advantages of Element constructors * > >> (a) Better errors when you misspell it > >> Element.create("vdieo", {src: ...} ) ==> No error; HTMLUnknownElement is > created > >> new HTMLVdieoElement( {src: ...} ) ==> ReferenceError; Stack trace > points you to the faulty line of code > >> (b) Consistency with other constructable DOM objects > >> e.g. new XMLHttpRequest(), new Image(), new Event(), new CustomEvent(), > new MessageEvent(), ... > >> (c) Enables to subtype DOM objects in the future > >> We are planning to make DOM objects subtype-able, like this: > >> function MyButton(text) { > >> HTMLButtonElement.call(this); /* (#) */ > >> this.textContent = text; > >> } > >> MyButton.prototype = Object.create(HTMLButtonElement.prototype, > {...}); > >> var fancyButton = new MyButton("Click Me!!"); > >> In order to make the line (#) work, HTMLButtonElement must have a > constructor. > >> > >> * Spec examples * > >> interface [ > >> NamedConstructor(optional HTMLButtonElementInit initDict, optional > NodeArray children) > >> ] HTMLButtonElement : HTMLElement { > >> attribute boolean disabled; > >> attribute DOMString value; > >> ... (omitted) > >> } > >> dictionary HTMLButtonElementInit : HTMLElementInit { > >> boolean disabled; > >> DOMString value; > >> ... (omitted) > >> } > >> interface [ > >> NamedConstructor(optional HTMLElementInit initDict, optional > NodeArray children) > >> ] HTMLElement : Element { > >> attribute DOMString lang; > >> attribute DOMString className; > >> ... (omitted) > >> } > >> dictionary HTMLElementInit : ElementInit { > >> DOMString lang; > >> DOMString className; > >> ... (omitted) > >> } > >> interface Element : Node { > >> readonly attribute DOMString tagName; > >> ... (omitted) > >> } > >> dictionary ElementInit : NodeInit { > >> DOMString tagName; > >> ... (omitted) > >> } > >> interface Node { > >> readonly attribute unsigned short nodeType; > >> ... (omitted) > >> } > >> dictionary NodeInit { > >> unsigned short nodeType; > >> ... (omitted) > >> } > >> > >> * Discussion > >> (a) Element.create() *and* Element constructors? > >> I think that both are useful for the reasons that dominicc pointed out > in [3]. Element.create() is good when we have a tag name in hand, like > >> var tag = "button"; > >> Element.create(tag, { }, ...); > >> On the other hand, Element constructors have the advantages that I > described above. > >> (b) How to specify properties and attributes in the dictionary argument > >> A property and an attribute are two different things [4]. A property is > the thing that can be set by a setter like foo.value, and an attribute is > the thing that can be set by foo.setAttribute(). A discussion has been > conducted on how we can set up properties and attributes in the dictionary > argument [2]. Proposed approaches in [2] are as follows: > >> (b-1) Let a constructor have two dictionaries, one for properties and > the other for attributes, e.g. new HTMLButtonElement( {disabled: true}, > {class: "myButton", onclick: func}, ...) > >> (b-2) Add a prefix character to attributes, e.g new HTMLButtonElement( > {disabled: true, "@class": "myButton", "@onclick": func} ) > >> (b-3) Introduce a reserved key "attributes", e.g new HTMLButtonElement( > {disabled: true, attributes: {class: "myButton", onclick: func} } ) > >> Another difficulty around attributes is how to naturally set a value of > a boolean attribute in the dictionary when we have the value in hand. In > case of a property, you just need to write like this: > >> var b = new HTMLButtonElement({disabled: value}); > >> However, in case of an attribute, we need to write like this: > >> var options = {}; > >> if (value) > >> options.disabled = ""; > >> var b = new HTMLButtonElement(options); > >> Basically, I think that we should keep the succinctness of constructors > and should not introduce a new syntax just for allowing people to set > attributes in the constructor. Thus, I propose that we allow only properties > in the dictionary, at least at the present moment. If we found in the future > that people wish to set attributes in the constructor, we can discuss the > feature again then. > >> (c) How to specify child Elements in the constructor argument > >> Possible approaches are as follows: > >> (c-1) As variable arguments, e.g. new HTMLButtonElement( { ... }, > child1, child2, child3, ...) > >> (c-2) As an array, e.g. new HTMLButtonElement( { ... }, [child1, child2, > child3] ) > >> (c-3) As variable arguments. We expand arguments of type array. e.g. new > HTMLButtonElement( { ... }, child1, [child2, child3], child4, ...) is > equivalent to new HTMLButtonElement({ ... }, child1, child2, child3, child4, > ...) > >> I guess that (c-3) is not good for the complicated rule. I think that > both (c-1) and (c-2) are possible, but I prefer (c-1). I think that implicit > array expansion is not necessary, since ES6 is introducing "..." operator > for array expansion [6]. In other words, you can write like this: > >> var array = [child1, child2, child3, ......]; > >> new HTMLButtonElement({ ...... }, ...array); > >> (d) What should the owner document of the created Element be? > >> I think that we can assume that the owner document is window.document, > as existing constructors (new Image(), new Audio() and new Option()) is > assuming. Some cases can expect an owner document other than > window.document, but they are not so common. I believe that we should focus > on making most of practical use cases simpler rather than supporting > specialized cases that do not really need a convenience shortcut. > >> (e) How to specify a namespace of attributes > >> I propose that we do not support namespaced attributes like "xmlns:foo", > since they are rare [5]. Again, we should focus on making most of practical > use cases simpler. > >> (f) How to create an unknown element that can be created by > document.createElement("unknooooown") > >> Fortunately, the HTML5 spec has HTMLUnknownElement. You can create an > unknown element by new HTMLUnknownElement( {tagName: "unknooooown"}, ...) > >> (g) How to handle HTMLElements that have more than one tags > >> For example, both <ins> and <del> are tags of HTMLModificationElement. > Then, how does the constructor look like? I think that we can easily handle > this issue by distinguishing tags using a tagName property, e.g. new > HTMLModificationElement( {tagName: "ins"}, ...) or new > HTMLModificationElement( {tagName: "del"}, ...) > >> > >> [1] https://bugs.webkit.org/show_bug.cgi?id=67824 > >> [2] > http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0537.html > >> [3] > http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0707.html > >> [4] > http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0666.html > >> [5] > http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0721.html > >> [6] http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts (11.2.4 > Argument Lists) > >> > >> > >> -- > >> Kentaro Hara, Tokyo, Japan (http://haraken.info) > > > > > > -- > Kentaro Hara, Tokyo, Japan (http://haraken.info) >
Received on Thursday, 27 October 2011 05:40:03 UTC