I think I don't really understand attributes and properties ... and
their difference, probably because their meaning is very similar (if
not the same) when I translate them on my native language. In some
way, I can understand difference in general, but can someone explain
them to me in the world of HTML & JS ... what is attribute, what is
property and what is(are) their difference(s)?
I've found some online resources, but the explanation is very poor. :(
I'm asking this because I've read some discussions about Jquery mixing
attributes and properties ... and I found one problem with Jquery.
This is for David Mark's joy and happiness. :)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/
TR/html4/strict.dtd">
<html>
<head>
<title>Mylib vs Jquery</title>
<script type="text/javascript" src="mylib.js"></script>
<script type="text/javascript" src="jquery-1.4.js"></script>
<script type="text/javascript">
window.onload = function() {
API.setAttribute(API.getEBI("mylibInput"), "type", "text");
$("#jqueryInput").attr("type", "text");
}
</script>
</head>
<body>
<input type="hidden" id="mylibInput">
<input type="hidden" id="jqueryInput">
</body>
</html>
Mylib sets attribute with no problem and input's type is changed to
"text".
On other hand Jquery throws exception:
uncaught exception: type property can't be changed
First of all ... I see that Jquery is mixing properties and attributes
(attr method tries to set property). And it isn't working (correct me
if my code isn't valid in some way). But, I've noticed that input's
~property~ can't be changed, but ~attribute~ can. And that confused
me, because attribute and property are the same in this case.
So, what's the difference between attribute and property?
Thanks for you answers.
Ivan
It doesn't work on IE7 (I haven't test it on other versions), other
mayor browsers works like charm. :)
There are no stupid questions, just stupid people. :)
> I think I don't really understand attributes and properties ... and
> their difference, probably because their meaning is very similar (if
> not the same) when I translate them on my native language. In some
> way, I can understand difference in general, but can someone explain
> them to me in the world of HTML & JS ... what is attribute, what is
> property and what is(are) their difference(s)?
Attributes are nodes on the document tree. DOM properties provide an
interface to read and write attributes. The attibutes values are
always strings. DOM properties provide a higher-level interface,
converting attribute values (somewhat) according to the DOM specs and
filling in the cracks with browser/user defaults, as well as user data
(e.g. entered form control values).
For example, if there is a TABINDEX attribute node on the element (and
that element allows for that attribute), the tabIndex property
reflects it as a number. If there is no such attribute, the tabIndex
property returns the default tab index (usually 0 or -1, depending on
the type of element).
The attribute methods (e.g. getAttribute/setAttribute/removeAttribute)
provide a lower level interface than DOM properties and are virtually
_never_ needed in an HTML DOM as you can use the higher level DOM
interfaces. As with all of this stuff, the context dictates the
required interfaces. For example, an editor application would need
the attribute methods to convert a document to a canonical form (i.e.
without browser/user defaults or user data.
Also, the attribute methods are Broken as Designed in IE < 8 and IE8
compatibility mode, requiring non-trivial feature testing and evasive
action for the still-popular MS browser. So there's another reason to
avoid those methods entirely.
>
> I've found some online resources, but the explanation is very poor. :(
Shocking. :) You'll find lots of online scripts that de
>
> I'm asking this because I've read some discussions about Jquery mixing
> attributes and properties ... and I found one problem with Jquery.
Yes, they have always been completely clueless about the difference.
What's the difference between you and them? You are in here asking
questions and they are over there with their heads in the sand,
pretending that there's no problem (crisis what crisis?) Resig's
"test-driven" development means nobody really understands anything
about browser scripting, so they peer at the latest major browsers
hoping to spot patterns (they've filled in a few cracks here and there
over the years, changing the behavior of the script a little with each
release) and ultimately giving up when the next batch of browsers
comes out (and then bitching at end-users for using "ancient"
browsers). This is how they see the "Real World" of software. No
shock that the end-users see it very differently (e.g. with lots of
script errors, broken pages, memory leaks, etc.)
> This is for David Mark's joy and happiness. :)
No it isn't. I can't stand it that _all_ of those miserable
"standard", "major" pieces of shit are written by clueless hobbyists.
Apple, IBM and Yahoo. What do these three behemoths have in common?
They are all using browser sniffing diaries on their Websites, rather
than proper cross-browser scripts. Hard to believe they can't find
_anyone_ but free code monkeys to cobble together the "logic" that
runs their public sites.
Why do they think these "programmers" are free? It's absolute madness
from every perspective (particularly from a business perspective).
It's irritating to me as I have to browse the Web too and I _know_
their sites could have been done right as easily (or easier) as
wrong. But the hacks don't want to hear that as they are not
programmers at all (just pattern memorizers). It's like building a
house and letting the paper hangers draw up the plans.
>
> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/
> TR/html4/strict.dtd">
> <html>
>
> <head>
> <title>Mylib vs Jquery</title>
>
> <script type="text/javascript" src="mylib.js"></script>
> <script type="text/javascript" src="jquery-1.4.js"></script>
>
> <script type="text/javascript">
> window.onload = function() {
> API.setAttribute(API.getEBI("mylibInput"), "type", "text");
> $("#jqueryInput").attr("type", "text");}
>
> </script>
Also see:-
http://www.cinsoft.net/attributes.html
...for the last pieces of this "puzzle". Those methods will be
transplanted into My Library shortly.
>
> </head>
>
> <body>
>
> <input type="hidden" id="mylibInput">
> <input type="hidden" id="jqueryInput">
>
> </body>
> </html>
>
> Mylib sets attribute with no problem and input's type is changed to
> "text".
> On other hand Jquery throws exception:
>
> uncaught exception: type property can't be changed
And actually, you picked the one they got "right". You can only set
the type property once in IE, so I have no problem with throwing an
exception for all. Of course, the My Library core does not use try-
catch at all.
Now, a function that sets multiple attributes should definitely set
the type attribute first. Document that the type property should
always be set first when using the single setter (e.g. setAttribute,
attr) method and recommend the multiple setter for beginners. Still,
the throw above is not a bad way to go.
>
> First of all ... I see that Jquery is mixing properties and attributes
> (attr method tries to set property). And it isn't working (correct me
> if my code isn't valid in some way).
Do not use the attr method under any circumstances. It uses the above-
mentioned (taboo) attribute methods in some cases and properties for
others. It's a patchwork of observations and the equivalent of a
major fault line for apps built on top of jQuery. The major problem I
see is that virtually every jQuery book and example (typically written
by clueless, gushing journalists) uses the attr method. (!) This is a
DOM scripting library that complicates the hell out of DOM scripting
because the authors don't understand how documents work (and seem
completely unwilling to learn). I know. Who would put a penny on
them? :(
> But, I've noticed that input's
> ~property~ can't be changed, but ~attribute~ can. And that confused
> me, because attribute and property are the same in this case.
No, setting the value property does not change the value attribute.
It can't as the value attribute is reflected by the defaultValue
property. The original (default) value specified in the markup cannot
be stepped on by user input. This is the same for selected/
defaultSelected (options) and checked/defaultChecked (checkbox/radio
buttons).
>
> So, what's the difference between attribute and property?
See above.
>
> Thanks for you answers.
NP. Thanks for asking!
From your OP I assume that you don't want Thomas to point out that
"doesn't work" is a worthless failure description, so I will.
If you really are trying to change an existing <input type="hidden">
field into an <input type="text"> field then you are not going to get
that to "work" cross-browser (or even that multi-browser).
Richard.
You can't set the type property (IE mixes up attributes and properties
behind the scenes) once it has been (explicitly or implicitly) set.
But I am sure there is some (soon to be removed) hack-y workaround in
My Library that can do it (replacing and returning a whole new node in
the process). What happened when you tried this in IE7?
Thanks! Now it's more clearer to me, although I think I'll have to
contemplate over some things for some time. :)
Oops, there was a typo short-circuiting the hack. Not that I care
about this particular behavior, but it had the potential to break more
meaningful workarounds. So it's fixed and you can actually change the
type attribute in IE (except IE8 standards mode, of course). As
mentioned, this hack will be gone shortly (and replaced with
documentation for setAttribute).
The typo was not present in the attributes test page, so this bug (and
a few others) would have been squashed on transplant anyway.
:)
That post was only for mr. Mark, I thought that was a bug in his
library (or IE7 only) ... but the bug was in my code. Nevermind that.
I'll try to post an error message in the future, I forgot it this
time.
> If you really are trying to change an existing <input type="hidden">
> field into an <input type="text"> field then you are not going to get
> that to "work" cross-browser (or even that multi-browser).
Yes, I was trying to do that.
Ok, tnx, I'll find other solution.
Ivan
NP. Contemplation (and research) trumps ignorance every time. ;)
> I think I don't really understand attributes and properties ... and
> their difference, probably because their meaning is very similar (if
> not the same) when I translate them on my native language. In some
> way, I can understand difference in general, but can someone explain
> them to me in the world of HTML & JS ... what is attribute, what is
> property and what is(are) their difference(s)?
Skipping the differences between My Library and jQuery (you can find out
yourself why one works and the other does not by debugging), an attempt at
an explanation. Please read this carefully, do not hesistate to ask if
there are any further questions (and CMIIW):
Elements, as provided by an SGML-based markup language, have _attributes_.
<http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2>
For example, A elements have an attribute named `href':
<a href="http://foo.example/">...</a>
That attribute is declared in one of the HTML DTDs:
<!ATTLIST A
...
href CDATA #IMPLIED
...>
and defined in the HTML Specifications, for example in HTML 4.01:
<http://www.w3.org/TR/html4/struct/links.html#h-12.2>
Objects, as provided by an ECMAScript-based programming language, have
_properties_. For example, the object created with the Object initializer
{foo: "bar"}
has a property named `foo' with string value "bar".
In DOM implementations, elements are represented by host objects, called
"element objects". (They are termed "host objects" per the ECMAScript
Specifications as they are provided by the *host* runtime environment, not
the programming language [native, built-in] or the user [native, user-
defined]. Certain freedoms are afforded to host objects by the ECMAScript
Specifications as compared to other objects.) Those element objects can
implement certain interfaces (a common set of named values and behaviors).
Those element objects, like other objects, have properties.
Element objects can have "normal" properties: Properties that do not relate
to an attribute of the represented element. For example, most element
objects have a proprietary `offsetWidth' property. ("Proprietary" means
here that, although maybe widely implemented, there is no public standard
to specify that feature.)
Element objects also can have attribute properties: Properties that relate,
directly or indirectly, to the value of an attribute of the represented
element. Many, if not all of them, are standardized. An example would be
the `type' attribute property that relates to the `type' attribute in the
markup. Another common example is the `className' property that relates to
the `class' attribute of HTML elements.
And here is probably the major source of the confusion:
The W3C DOM API Specifications define interfaces. Interfaces have
attributes. But those attributes are not to be confused with the
attributes in the markup. Instead, they are implemented as properties on
the (element) object that implements the interface (if the term "property"
is used for those values in the programming language used to implement
them, as in the programming languages we are dealing with here).
However, as I said before, some of those *API* attributes, and consequently
some of the element object's properties, relate to the *markup* attributes
of the represented element.
Which is why the API terms them "property attributes"; while we, when
talking about DOM implementations, term them "attribute properties".
A less careful observer could easily get the idea that attributes and
properties are all the same.
<http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-642250288>
<http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html>
In addition, element objects implement methods that set or retrieve markup
attribute values. Those are the methods provided by the Element interface
of the W3C DOM Level 2+ Core Specifications: getAttribute(),
getAttributeNS(), setAttribute(), and setAttributeNS().
For historical reasons ("DOM Level 0"), attribute properties are usually
"live", meaning that their value would reflect the current status of the
element object. In most cases, attributes values as not retrieved using
attribute properties instead reflect the original state of the element as
it is in the markup. Example:
Let `o' be a reference to the object that represents the following element:
<input value="foo">
Now
o.value
would reflect the current status of the element object; that is, suppose
the user has replaced the control's value with "bar", it would yield "bar".
However,
o.getAttribute("value")
should still return "foo".
Finally, there are DOM implementations, most notably the MSHTML DOM, that
are not fully standards-compliant: They access attributes as if you would
access the attribute property and vice-versa. This adds to the confusion.
HTH
PointedEars
IE7 thrown an error saying:
Char: 11154
Error: Could not get the type property. This command is not supported.
Code: 0
> As mentioned, this hack will be gone shortly (and replaced with documentation for setAttribute).
I think that's a great thing! :)
If you build a new library, it will now "work" for all but IE8
standards mode. But I don't want it to work like that, so soon it
will fail for all. Always set the type attribute/property _first_ (or
use a wrapper that does that for you).
>
> I think that's a great thing! :)
Thanks!
Thanks for very technical answer. :)
I'll read it all carefully once more very soon (I don't have much time
right now) and shall return if I'll have more question.
And that wrapper is API.createElementWithAttributes:-
var el = API.createElementWithAttributes('input', {
name:'hello'
type:'hidden'
value:'world'
});
The type attribute will be set first, so that's one less thing for you
to worry about (and renders the aforementioned hack superfluous).
There is a similar issue with the name attribute/property in that it
must be set after appending the element if it is to show up in the
appropriate DOM collection (e.g. document.forms, document.images,
window.frames). That is an issue best handled with a wrapper that
creates _and_ appends an element. Call it
createAndAppendElementWithAttributes perhaps? Yes, the typical
library devotee will cry foul at all of that typing. Of course, I
call a foul any time I have to read their "concise" (read illegible)
bullshit. :)
The problem is that I already have a markup with hidden input fields
which now has to be shown to the user if he clicks on the checkbox
(nevermind why).
The simplest solution was to change type property using javascript ...
but it didn't work (I didn't know that I can't change type property
once it is set).
I could replace that ("hidden") element with new one ("text") when
user clicks checkbox using DOM methods, but I think simpler solution
is to change markup ("hidden" to "text") and than simply hide that
input elements and show them when user clicks on checkbox.
> On Jan 21, 8:10 am, David Mark <dmark.cins...@gmail.com> wrote:
>> If you build a new library, it will now "work" for all but IE8
>> standards mode. But I don't want it to work like that, so soon it
>> will fail for all. Always set the type attribute/property _first_ (or
>> use a wrapper that does that for you).
>
> And that wrapper is API.createElementWithAttributes:-
You can't be serious. What's wrong with `API.createElement', the `API'
aside (see below)?
> [...]
> There is a similar issue with the name attribute/property in that it
> must be set after appending the element if it is to show up in the
> appropriate DOM collection (e.g. document.forms, document.images,
> window.frames). That is an issue best handled with a wrapper that
> creates _and_ appends an element. Call it
> createAndAppendElementWithAttributes perhaps?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
No, thanks.
> Yes, the typical library devotee will cry foul at all of that typing.
You forgot to consider the shades of gray. It is not just about typing.
> Of course, I call a foul any time I have to read their "concise" (read
> illegible) bullshit. :)
You can make code readable and concise.
BTW, I don't think the container object should be referrable through `API',
but something less ambiguous (and less error-prone?), say `MyLib', instead.
Is it even intended to be a constructor?
PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
> The problem is that I already have a markup with hidden input fields
> which now has to be shown to the user if he clicks on the checkbox
> (nevermind why).
> The simplest solution was to change type property using javascript ...
> but it didn't work (I didn't know that I can't change type property
> once it is set).
But you can, just not in the MSHTML DOM. Instead of dealing with the
`value' attribute/property security issue as reasonable implementations like
Gecko, M$ throws exceptions on setting `type' afterwards. We've been over
this.
The obvious solution is not to toggle the `type' of the control but the
visibility of the element: Use the `visibility' or `display' style
properties to hide/show it.
Either one is poor UI design, though. Disable/enable the always visible
input element instead; if the default state is disabled, disable it onload
the document body so that it is still usable without scripting (unless, of
course, a real form submission is needed anyway to re-enable it).
PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16
Absolutely. It isn't about typing at all. That's what I find so
humorous about the whole "do more, type less, debug forever" mantra.
The amount of "typing" (quotes indicate macros, Intellisense, etc. may
be used) is irrelevant.
>
> > Of course, I call a foul any time I have to read their "concise" (read
> > illegible) bullshit. :)
>
> You can make code readable and concise.
Absolutely. I don't think the length of an identifier makes it any
more or less concise. The question is whether it describes the value.
>
> BTW, I don't think the container object should be referrable through `API',
> but something less ambiguous (and less error-prone?), say `MyLib', instead.
Possibly. Of course, that's more typing. :)
> Is it even intended to be a constructor?
No, it is a reference to an Object object that is a (mostly) flat
"namespace" of methods (and a few non-method properties). I stopped
short of creating a hierarchical namespace as it was determined that
it would add overhead with no benefit to the user. You know at build
(or pre-build test) time what interfaces are possible (from the
documentation or console), so there is no need to provide an
indication of which modules provided each. In other words, there is
no concept of modules once the library is built. It's just a single
(dynamic at run time) API at that point.
And all caps means global to me. I know, why isn't my "global" call
caps? That's just the way I wrote it back then. I use "GLOBAL" now.
I assure you I am. :)
> What's wrong with `API.createElement', the `API'
> aside (see below)?
It's not a contest and those are apples and oranges. The
createElementWithAttributes method is built on top of createElement.
I think the names make that clear and the longer wrapper takes care of
the issue with the type property. ;)
>
> > [...]
> > There is a similar issue with the name attribute/property in that it
> > must be set after appending the element if it is to show up in the
> > appropriate DOM collection (e.g. document.forms, document.images,
> > window.frames). That is an issue best handled with a wrapper that
> > creates _and_ appends an element. Call it
> > createAndAppendElementWithAttributes perhaps?
>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> No, thanks.
Because it is a long name? Then do this:-
var myCoolMethod = API.createAndAppendElementWithAttributes;
myCoolMethod('input', { name:'test', type:'button', value='test' },
document.forms['myform']);
Then you know that the type and name issues are taken care of. For
the latter issue, the wrapper will set the name property _after_
appending the element. I believe for IFRAME elements, it is necessary
to set el.contentWindow.name as well. That's about it. I'll add it
when I get a chance.
> Thomas 'PointedEars' Lahn wrote:
>> You can make code readable and concise.
>
> Absolutely. I don't think the length of an identifier makes it any
> more or less concise. The question is whether it describes the value.
Last I checked, shortness was one attribute that defined "concise".
> And all caps means global to me. I know, why isn't my "global" call
> caps? That's just the way I wrote it back then. I use "GLOBAL" now.
I don't think that's a good idea.
PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300...@news.demon.co.uk> (2004)
But do short identifiers lead to concise code? I'd say only in a very
literal (and narrow) sense. Concise code is produced by eliminating
redundancies (like with these create element wrappers).
>
> > And all caps means global to me. I know, why isn't my "global" call
> > caps? That's just the way I wrote it back then. I use "GLOBAL" now.
>
> I don't think that's a good idea.
>
Noted.
> Thomas 'PointedEars' Lahn wrote:
>> David Mark wrote:
>> > On Jan 21, 8:10 am, David Mark <dmark.cins...@gmail.com> wrote:
>> >> If you build a new library, it will now "work" for all but IE8
>> >> standards mode. But I don't want it to work like that, so soon it
>> >> will fail for all. Always set the type attribute/property _first_
>> >> (or use a wrapper that does that for you).
>> >
>> > And that wrapper is API.createElementWithAttributes:-
>>
>> You can't be serious.
>
> I assure you I am. :)
>
>> What's wrong with `API.createElement', the `API' aside (see below)?
>
> It's not a contest
Well, *you* want My Library used above others, most notably jQuery, do you
not? Insofar it is a contest for sure.
> and those are apples and oranges. The
> createElementWithAttributes method is built on top of createElement.
> I think the names make that clear and the longer wrapper takes care of
> the issue with the type property. ;)
That doesn't make sense. The extension can be facilitated with one method
with an optional argument.
>> > [...]
>> > There is a similar issue with the name attribute/property in that it
>> > must be set after appending the element if it is to show up in the
>> > appropriate DOM collection (e.g. document.forms, document.images,
>> > window.frames). That is an issue best handled with a wrapper that
>> > creates _and_ appends an element. Call it
>> > createAndAppendElementWithAttributes perhaps?
>>
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> No, thanks.
>
> Because it is a long name?
Yes. A long name, hard to remember to begin with.
> Then do this:-
>
> var myCoolMethod = API.createAndAppendElementWithAttributes;
>
> myCoolMethod('input', { name:'test', type:'button', value='test' },
> document.forms['myform']);
If `API' has any meaning, that is not the same.
How is that hard to remember?
>
> > Then do this:-
>
> > var myCoolMethod = API.createAndAppendElementWithAttributes;
>
> > myCoolMethod('input', { name:'test', type:'button', value='test' },
> > document.forms['myform']);
>
> If `API' has any meaning, that is not the same.
>
API has the meaning I gave previously. And it is the same. None of
the methods cares what - this - is set to. Why should they when it
would just foul up calls like the above. ;)
> Thomas 'PointedEars' Lahn wrote:
>> David Mark wrote:
>> > Thomas 'PointedEars' Lahn wrote:
>> >> You can make code readable and concise.
>> > Absolutely. I don't think the length of an identifier makes it any
>> > more or less concise. The question is whether it describes the value.
>> Last I checked, shortness was one attribute that defined "concise".
>
> But do short identifiers lead to concise code?
*Shorter* identifiers than this (`createElementWithAttributes') lead to
more concise and easier readable code for sure.
> I'd say only in a very literal (and narrow) sense.
Well, from what I have read you have been doing it before: API.getEBI().
To be consistent, you would need to rename it to API.getElementById(), or
rename API.createElementWithAttributes() to API.createEWA() and the like.
However, API.createElement() with an optional argument strikes me as the
better choice.
> Concise code is produced by eliminating redundancies (like with these
> create element wrappers).
You should listen to your own words.
As for the createElement...AndAppend() method, you should consider the GNU
approach instead: One tool for one purpose (here: one method for one
purpose). Their combination makes the difference, makes the API robust and
flexible.
I do. :)
>
> As for the createElement...AndAppend() method, you should consider the GNU
> approach instead: One tool for one purpose (here: one method for one
> purpose). Their combination makes the difference, makes the API robust and
> flexible.
>
You misunderstand something. There is already a createElement
method. On top of that, there is a createElementWithAttributes
wrapper. You can use either. The whole library is built in layers
like that.
Here's the third tier for element creation:-
createAndAppendElementWithAttributes = function(tag, attributes,
appendTo, docNode) {
var el = createElementWithAttributes(tag, attributes,
docNode);
var name = attributes.name;
if (el) {
appendTo.appendChild(el);
if (name) {
el.name = name;
if (el.tagName.toLowerCase() == 'iframe' &&
isHostObjectProperty(el, 'contentWindow')) {
el.contentWindow.name = name;
}
}
}
return el;
};
I can tell you for sure that if you need to create a DOM structure on
the fly that includes forms, iframes, images, etc., such wrappers are
invaluable (and eliminate a lot of redundancy). The layer(s) used
depends on the context (as always). If you use the lower level
wrappers (e.g. createElement), you have to know a bit more about what
you are doing than with the higher-ups. That's another common theme.
You can trust that _I_ know what I'm doing. ;)
And it isn't lost on me that this latest wrapper cannot be used to
insert before a specific node. That operation has always been handled
at the OO level:-
D().createElementWithAttributes(...).insertBefore(el);
D().createElementWithAttributes(...).insertAfter(el);
But I don't care for that at this point, so I will likely move the
insertBefore/After logic down a level. It won't invalidate the
interface, but will make it more flexible by adding additional API
methods (and perhaps a new option for the existing wrappers).
> Thomas 'PointedEars' Lahn wrote:
>> As for the createElement...AndAppend() method, you should consider the
>> GNU approach instead: One tool for one purpose (here: one method for one
>> purpose). Their combination makes the difference, makes the API robust
>> and flexible.
>
> You misunderstand something
No, I don't think so.
> There is already a createElement method.
I figured as much.
> On top of that, there is a createElementWithAttributes
> wrapper. You can use either. The whole library is built in layers
> like that.
Then I'd rather not use or recommend it.
> Here's the third tier for element creation:-
>
> createAndAppendElementWithAttributes = function(tag, attributes,
> appendTo, docNode) {
> var el = createElementWithAttributes(tag, attributes,
> docNode);
I did that one wrong once, too. Better to pass the reference to the object
and use that reference instead of passing strings on to a subroutine.
Reduces stack usage and is much more flexible. Like I said, one tool for
one purpose. Makes shorter identifiers and argument lists, too.
PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
Wouldn't it be simpler to just hide an <input type="text"> element
using CSS, then show it?
Changing element types isn't reliable and should always be avoided.
Matt Kruse
I think you misunderstood the problem. Markup with hidden inputs was
already there. So, there is / was no point in making *hidden* inputs
visible ... but if they were text fields ... :)
I just had to change markup and make that fields invisible ... now
it's working fine.
You figured right. It's there because My Library supports XHTML as well
as the requisite HTML (something that will soon be optional through the
builder). Also, it would be there any as there is the chance that
document.createElement will not exist (or will be unusable). In those
cases, API.createElement is pruned. Therefore, the calling app's
gateway starts out like:-
if (API && API.createElement) {
// Good to create elements
}
The alternative without the wrapper is to do all of the feature testing
inline, which is hardly concise (or readable) and certainly prone to
mistakes (e.g. bad pastes).
>
> > On top of that, there is a createElementWithAttributes
> > wrapper. You can use either. The whole library is built in layers
> > like that.
>
> Then I'd rather not use or recommend it.
You aren't making any sense at all. The layers are good. ISTM that was
your argument to begin with. Tangling everything up in one layer is bad
(see jQuery, Prototype, etc.)
>
> > Here's the third tier for element creation:-
>
> > createAndAppendElementWithAttributes = function(tag, attributes,
> > appendTo, docNode) {
> > var el = createElementWithAttributes(tag, attributes,
> > docNode);
>
> I did that one wrong once, too.
You never did that one at all. I _just_ wrote it.
> Better to pass the reference to the object
> and use that reference instead of passing strings on to a subroutine.
You would have to pass a string to a function that _creates_ elements.
So you would use the middle tier (createElementWithAttributes), which
returns a reference to an element. Then you can append/insertBefore the
element. As mentioned, you have to know a bit more about what you are
doing as you go down in levels. In this case, you would need to account
for the name property issue.
> Reduces stack usage and is much more flexible. Like I said, one tool for
> one purpose. Makes shorter identifiers and argument lists, too.
>
You still aren't making any sense. The lower level methods (e.g.
createElement) have shorter identifiers and argument lists. As you go
up each level, the identifiers and argument lists get longer, which is
to be expected. Use whatever layer fits your needs. It's all good. ;)
> Thomas 'PointedEars' Lahn wrote:
>> The obvious solution is not to toggle the `type' of the control but the
>> visibility of the element: Use the `visibility' or `display' style
>> properties to hide/show it.
>
> I think you misunderstood the problem. Markup with hidden inputs was
> already there. So, there is / was no point in making *hidden* inputs
> visible ... but if they were text fields ... :)
You wanted to toggle the `type' of the already inserted `input' element
from `hidden' to `text' (and perhaps back), and failed to do that because
MSHTML did not allow it, did you not?
> I just had to change markup and make that fields invisible ... now
> it's working fine.
For fitting values of "fine". I have already told you that this is it is
poor UI design, and offered a better alternative.
Oops, you can probably tell I don't use the OO interface (never even
include it in the build).
E(D().createElementWithAttributes(...)).insertBefore(el);
The createElement* methods do not return wrapped elements. I toyed with
the idea of making all of the methods return wrapped elements (as
opposed to element references), but decided most apps would be better
off deciding what to do with the reference (no superfluous wrapper
objects are created and discarded). Speaking of that, I prefer:-
var elNew = D().createElementWithAttributes(...);
E(elNew}.insertBefore(el);
...or even:
var myDoc = D();
var elNew = myDoc.createElementWithAttributes(...);
var myEl = E(elNew);
myEl.insertBefore(el);
...as then you can re-use the wrapper objects (see the load methods).
Beats the living shit out of dollar signs for everything. ;)
Unless perhaps you mean the lack of a setAttributes (which would of
course take an element reference) wrapper on top of setAttribute.
That's a hole for sure, but easily plugged (in fact it is in the sequel).
> Thomas 'PointedEars' Lahn wrote:
>> David Mark wrote:
>> > Thomas 'PointedEars' Lahn wrote:
>> >> As for the createElement...AndAppend() method, you should consider
>> >> the GNU approach instead: One tool for one purpose (here: one method
>> >> for one purpose). Their combination makes the difference, makes the
>> >> API robust and flexible.
>> > You misunderstand something
>>
>> No, I don't think so.
>>
>> > There is already a createElement method.
>>
>> I figured as much.
>
> You figured right. It's there because My Library supports XHTML as well
> as the requisite HTML (something that will soon be optional through the
> builder). [...]
Non sequitur, though.
>> > On top of that, there is a createElementWithAttributes
>> > wrapper. You can use either. The whole library is built in layers
>> > like that.
>> Then I'd rather not use or recommend it.
>
> You aren't making any sense at all.
Perhaps after you have read below.
> The layers are good.
Not as implemented, no.
> ISTM that was your argument to begin with.
No, you must have completely misunderstood me.
> Tangling everything up in one layer is bad
> (see jQuery, Prototype, etc.)
Exactly.
>> > Here's the third tier for element creation:-
>>
>> > createAndAppendElementWithAttributes = function(tag, attributes,
>> > appendTo, docNode) {
>> > var el = createElementWithAttributes(tag, attributes,
>> > docNode);
>>
>> I did that one wrong once, too.
>
> You never did that one at all. I _just_ wrote it.
As it happens, JSX has a little longer history than My Library. Yes, I did
that one before, and have found it to be the wrong approach. That is, the
methodology; not exactly this code, of course.
>> Better to pass the reference to the object
>> and use that reference instead of passing strings on to a subroutine.
>
> You would have to pass a string to a function that _creates_ elements.
> So you would use the middle tier (createElementWithAttributes), which
> returns a reference to an element. Then you can append/insertBefore the
> element. As mentioned, you have to know a bit more about what you are
> doing as you go down in levels. In this case, you would need to account
> for the name property issue.
I think you misunderstand me. Instead of wrapping everything into one
method (which, regardless of the layering, is not much different from
jQuery's approach, BTW), I would do (or have done) something along:
var o = _createElement("foo", {bar: "baz"}, d);
var o2 = _createElement("blurb", {bla: "blue"}, d);
_appendChild(o, o2);
instead of
var o2 = _createElement("blurb", {bla: "blue"}, d);
_createElementAndAppendChild("foo", {bar: "baz"}, o2, d);
AISB, one tool for one purpose.
>> Reduces stack usage and is much more flexible. Like I said, one tool
>> for one purpose. Makes shorter identifiers and argument lists, too.
>
> You still aren't making any sense. The lower level methods (e.g.
> createElement) have shorter identifiers and argument lists.
But not the higher-level ones because you need to drag the rest of the
argument list of the lower-level ones with you. And should a considerable
change be necessary in one of the lower-level methods that cannot be
compensated by the arguments list of the higher-level method, all methods
need to change signature. BTDT; never again.
> As you go up each level, the identifiers and argument lists get longer,
> which is to be expected.
Maybe in your book, not in mine. Long argument lists and needless stacking
are an API killer.
PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>
Perhaps.
>
>> The layers are good.
>
> Not as implemented, no.
That has no real meaning. These are about as simple as wrappers get.
There's only so much to point out (e.g. setAttributes is a missing
piece). Pointing out nothing isn't helping at all.
>
>> ISTM that was your argument to begin with.
>
> No, you must have completely misunderstood me.
That's possible.
>
>> Tangling everything up in one layer is bad
>> (see jQuery, Prototype, etc.)
>
> Exactly.
Good.
>
>>>> Here's the third tier for element creation:-
>>>> createAndAppendElementWithAttributes = function(tag, attributes,
>>>> appendTo, docNode) {
>>>> var el = createElementWithAttributes(tag, attributes,
>>>> docNode);
>>> I did that one wrong once, too.
>> You never did that one at all. I _just_ wrote it.
>
> As it happens, JSX has a little longer history than My Library. Yes, I did
> that one before, and have found it to be the wrong approach. That is, the
> methodology; not exactly this code, of course.
I understood what you meant. :) Still, I don't see what your point is
with regard to createElementWithAttributes. It definitely rocks!
>
>>> Better to pass the reference to the object
>>> and use that reference instead of passing strings on to a subroutine.
>> You would have to pass a string to a function that _creates_ elements.
>> So you would use the middle tier (createElementWithAttributes), which
>> returns a reference to an element. Then you can append/insertBefore the
>> element. As mentioned, you have to know a bit more about what you are
>> doing as you go down in levels. In this case, you would need to account
>> for the name property issue.
>
> I think you misunderstand me. Instead of wrapping everything into one
> method (which, regardless of the layering, is not much different from
> jQuery's approach, BTW), I would do (or have done) something along:
It is nothing like jQuery's approach. Everything in jQuery is tangled
up. You can't peel away layers of jQuery at all. I suppose if they
could, they'd have a builder like this:
http://www.cinsoft.net/mylib-builder.asp
>
> var o = _createElement("foo", {bar: "baz"}, d);
> var o2 = _createElement("blurb", {bla: "blue"}, d);
> _appendChild(o, o2);
Aha! Now we are getting somewhere. That last one is useless. Change to:-
var el = createElement(...);
var el2 = createElement(...);
el.appendChild(el2);
...as there's no need for an appendChild wrapper. As for feature
detection, just check API.createElement*. It would seem unlikely that
an implementation would feature createElement but not appendChild, but
you never know. ;)
if (API.createElement) {
var el = createElement(...);
var el2 = createElement(...);
if (API.isHostMethod(el, 'appendChild')) { // Likely superfluous check
el.appendChild(el2);
}
}
if (API.createAndAppendElementWithAttributes) {
...
}
Clearly the latter will be pruned if the appendChild method is not
featured by the DOM.
if (html && isHostMethod(html, 'appendChild')) {
createAndAppendElementWithAttributes = function(tag, attributes,
appendTo, docNode) {
var el = createElementWithAttributes(tag, attributes, docNode);
var name = attributes.name;
if (el) {
appendTo.appendChild(el);
if (name) {
el.name = name;
}
if (el.tagName.toLowerCase() == 'iframe' &&
isHostObjectProperty(el, 'contentWindow')) {
el.contentWindow.name = name;
}
}
return el;
};
}
>
> instead of
>
> var o2 = _createElement("blurb", {bla: "blue"}, d);
> _createElementAndAppendChild("foo", {bar: "baz"}, o2, d);
>
> AISB, one tool for one purpose.
But you didn't notice that the more granular tools are one floor down. ;)
>
>>> Reduces stack usage and is much more flexible. Like I said, one tool
>>> for one purpose. Makes shorter identifiers and argument lists, too.
>> You still aren't making any sense. The lower level methods (e.g.
>> createElement) have shorter identifiers and argument lists.
>
> But not the higher-level ones because you need to drag the rest of the
> argument list of the lower-level ones with you.
I take it you only write very low-level API's. At some point somebody
has to build on the foundation. If the project is a GP library for
non-programmers, it has to include higher-level methods and objects.
> And should a considerable
> change be necessary in one of the lower-level methods that cannot be
> compensated by the arguments list of the higher-level method, all methods
> need to change signature. BTDT; never again.
I'm aware of that consideration. I don't deliberately paint myself into
corners (and know how to extricate if I make a mistake).
>
>> As you go up each level, the identifiers and argument lists get longer,
>> which is to be expected.
>
> Maybe in your book, not in mine. Long argument lists and needless stacking
> are an API killer.
Long is relative. As I explained, createElement has one (or two if you
need to specify another document) argument. Not unsurprisingly, the
createElementWithAttributes wrapper has an additional argument for the
attributes. No "API killers" there. :)
There are too many edge cases support. There are problems with nodes
that can't accept other nodes, special handling for certain attributes
(cellPadding, name).
If the problem is narrower there aren't as many edge cases. For example,
a hidden method `createCalendarOnDemand` creates HTML for the calendar
widget. It has no options to determine the HTML structure, and so there
is not testing multiple contexts and configurations. I like that.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
That's meaningless.
> There are problems with nodes
> that can't accept other nodes, special handling for certain attributes
> (cellPadding, name).
There are no issues if you have competently written wrappers. Of
course, that lets out... virtually everyone. As for problems of nodes
not accepting other nodes, that's inherent to the underlying DOM
interface, so is irrelevant for a wrapper (unless it claims to support
non-standard behavior).
>
> If the problem is narrower there aren't as many edge cases. For example,
> a hidden method `createCalendarOnDemand` creates HTML for the calendar
> widget.
What calendar widget? And why does that method create HTML? Also,
aren't all methods on demand?
> It has no options to determine the HTML structure, and so there
> is not testing multiple contexts and configurations. I like that.
Yes, context specific solutions always trump GP. But we are talking
about (though not necessarily advocating) a GP library.
> I think you misunderstand me. Â Instead of wrapping everything into one
> method (which, regardless of the layering, is not much different from
> jQuery's approach, BTW), I would do (or have done) something along:
>
> Â var o = _createElement("foo", {bar: "baz"}, d);
> Â var o2 = _createElement("blurb", {bla: "blue"}, d);
> Â _appendChild(o, o2);
>
> instead of
>
> Â var o2 = _createElement("blurb", {bla: "blue"}, d);
> Â _createElementAndAppendChild("foo", {bar: "baz"}, o2, d);
This is made even more pointed by the order of the arguments in that
last line. Why in the world would o2 be placed in the middle of the
set of parameters sent to the lower-level API? How is a developer
supposed to remember that order? The usual reasons for such strange
orderings is backward compatibility. It's possible that the last
parameter to both the createElement and the
createElementAndAppendChild did not exist in an earlier version of the
API and were added to the end so that existing code needed less
change. Either that or d is an optional argument that has to be
carried through, and you want all the optional ones at the end. But
if that's the case, implementation convenience is trumping solid API
design -- never a good idea.
One advantage to Thomas' suggestion is that you don't need to carry
this baggage through multiple levels of API.
But to me the main issue is the intellectual weight. Perhaps most of
the work I would need to do could be done through the upper-level
APIs, but I imagine that occasionally I would need to use the lower
levels too, right? At that point, I have to remember the simpler
lower-level versions and the more complex higher-level ones. Keeping
track of parameter order is an issue, but even remembering whether
it's called "createAndAppendElementWithAttributes" or
"createElementWithAttributesAndAppend" gets to be an intellectual
burden.
For example, in Java, the IO libraries are well layered, but this
comes at a heavy price for users. I'm going to try this from memory,
but would not be at all surprised if I'm wrong:
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(
new File(filename))));
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
It's a bit of a feat to get that right if you haven't been using the
API for a while. Meanwhile in Python, I have little doubt about this
code:
f = open(filename, 'r')
for line in f:
print line,
The Python API simply has less to remember, less to get wrong. It is
less flexible, perhaps. But for most of my day-to-day work, I would
rather be using a simple-to-remember and simple-to-use API than one
with lots of bells and whistles.
>> As you go up each level, the identifiers and argument lists get longer,
>> which is to be expected.
>
> Maybe in your book, not in mine. Â Long argument lists and needless stacking
> are an API killer.
Yes, *needless* stacking. It's not that stacking cannot be useful.
But if not done extremely carefully, it bloats an API and makes it
harder to remember and to effectively use.
-- Scott
And I should have added, that when we do this in JS we can gain
flexibility with an options object:
var o = _createElement("foo");
var o = _createElement("foo", {attributes: {bar: "baz"});
var o = _createElement("foo", {attributes: {bar: "baz"}, docNode:
node, appendTo: parent});
-- Scott
It is because d (document) is an option used only with frames (another
layer of support that will be filtered by the builder shortly). JFTR,
the above functions are from the PE collection (though my
createElementWithAttributes has arguments in similar order).
> Why in the world would o2 be placed in the middle of the
> set of parameters sent to the lower-level API?
Because the optional one is best last.
> How is a developer
> supposed to remember that order?
You almost never use the optional one and the optional one is always last.
> The usual reasons for such strange
> orderings is backward compatibility.
Nothing strange above, other than the underscores.
> It's possible that the last
> parameter to both the createElement and the
> createElementAndAppendChild did not exist in an earlier version of the
> API and were added to the end so that existing code needed less
> change.
Could be, but no.
> Either that or d is an optional argument that has to be
> carried through, and you want all the optional ones at the end.
It is optional and as such, it does not necessarily have to be carried
through (unless it is passed to the higher level function).
> But
> if that's the case, implementation convenience is trumping solid API
> design -- never a good idea.
There's nothing like that going on with these simple wrappers. It
wouldn't make them better to move the optional document argument to the
middle.
>
> One advantage to Thomas' suggestion is that you don't need to carry
> this baggage through multiple levels of API.
What suggestion? I explained that he could do what he wanted to do with
my API, which is not very much unlike his.
>
> But to me the main issue is the intellectual weight.
There's nothing intellectual about these simple wrappers.
var el = API.createElement('div');
var el = API.createElementWithAtttributes('div', { ... });
But wait, you want to use frames? How could that work?
var el = API.createElement('div', doc);
var el = API.createElementWithAtttributes('div', { ... }, doc);
Yes, just tack the optional document argument onto the end, exactly
where it should go.
> Perhaps most of
> the work I would need to do could be done through the upper-level
> APIs, but I imagine that occasionally I would need to use the lower
> levels too, right?
Sure, as in the above example.
> At that point, I have to remember the simpler
> lower-level versions and the more complex higher-level ones.
Not in the above example. There's nothing to remember.
> Keeping
> track of parameter order is an issue, but even remembering whether
> it's called "createAndAppendElementWithAttributes" or
> "createElementWithAttributesAndAppend" gets to be an intellectual
> burden.
So create a macro. ;) Or do this (you should anyway):-
var myMethod = API.createAndAppendElementWithAttributes;
var el = myMethod(this, that, there);
And if you want to use frames:-
var el = myMethod(this, that, there, doc);
Yes, tack on the optional document argument, the only place it could
logically go.
>
> For example, in Java, the IO libraries are well layered, but this
> comes at a heavy price for users. I'm going to try this from memory,
> but would not be at all surprised if I'm wrong:
>
> BufferedReader reader = new BufferedReader(
> new InputStreamReader(
> new FileInputStream(
> new File(filename))));
> String line;
> while((line = reader.readLine()) != null) {
> System.out.println(line);
> }
>
> It's a bit of a feat to get that right if you haven't been using the
> API for a while. Meanwhile in Python, I have little doubt about this
> code:
And what is that feat? Printing a file to the console? If so, Java
sucks for file IO and I am sure some smart egg has written a
higher-level console API.
>
> f = open(filename, 'r')
> for line in f:
> print line,
That's better.
>
> The Python API simply has less to remember, less to get wrong. It is
> less flexible, perhaps. But for most of my day-to-day work, I would
> rather be using a simple-to-remember and simple-to-use API than one
> with lots of bells and whistles.
Yes, but how does that apply to the wrappers at hand? Could they
possibly be made simpler? About the only hole I see is a setAttributes
wrapper. I suppose you could add an append/insertBefore wrapper too
(those exist only in the OO layer in mine, which does leave gaps in the
lower levels).
>
>
>>> As you go up each level, the identifiers and argument lists get longer,
>>> which is to be expected.
>> Maybe in your book, not in mine. Long argument lists and needless stacking
>> are an API killer.
>
> Yes, *needless* stacking. It's not that stacking cannot be useful.
> But if not done extremely carefully, it bloats an API and makes it
> harder to remember and to effectively use.
>
Yes, I agree that needless stacking is bad. I just don't think it's
been shown that the three methods in question are needlessly stacked.
Each layer serves a specific purpose. There are problems with creation
and problems with appending. Each layer deals with its own problems.
You have failed to post a coherent follow-up. Please try again. General
characteristics of a coherent follow-up include, but are not limited to:
Correct and understandable language, reference to the statements in the
precursor or, as an exception, its precursors. Thank you in advance.
Yes, I don't have any problem with that, but I don't find it any more
memorable. Fouls up things like Intellisense as well, but that may not
be a concern.
> Scott Sauyet wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> I think you misunderstand me. Instead of wrapping everything into one
>>> method (which, regardless of the layering, is not much different from
>>> jQuery's approach, BTW), I would do (or have done) something along:
>>>
>>> var o = _createElement("foo", {bar: "baz"}, d);
>>> var o2 = _createElement("blurb", {bla: "blue"}, d);
>>> _appendChild(o, o2);
>>>
>>> instead of
>>>
>>> var o2 = _createElement("blurb", {bla: "blue"}, d);
>>> _createElementAndAppendChild("foo", {bar: "baz"}, o2, d);
>>
>> This is made even more pointed by the order of the arguments in that
>> last line.
>
> It is because d (document) is an option used only with frames (another
> layer of support that will be filtered by the builder shortly). JFTR,
> the above functions are from the PE collection (though my
> createElementWithAttributes has arguments in similar order).
AISB, it is only example code.
>> Why in the world would o2 be placed in the middle of the
>> set of parameters sent to the lower-level API?
>
> Because the optional one is best last.
You do see the inconcistency here, don't you?
>> How is a developer supposed to remember that order?
>
> You almost never use the optional one and the optional one is always
> last.
He was rightfully talking about the order of arguments as to their meaning,
not their requirement.
>> Either that or d is an optional argument that has to be
>> carried through, and you want all the optional ones at the end.
>
> It is optional and as such, it does not necessarily have to be carried
> through (unless it is passed to the higher level function).
That "unless" is the point of the argument. *You* need to carry it
through.
>> But if that's the case, implementation convenience is trumping solid
>> API design -- never a good idea.
>
> There's nothing like that going on with these simple wrappers.
Yes, it is. Too bad that you cannot see it right now.
>> One advantage to Thomas' suggestion is that you don't need to carry
>> this baggage through multiple levels of API.
>
> What suggestion?
That suggestion of mine to keep argument lists short by having one tool for
one purpose, and not one tool implicitly using another one.
> I explained that he could do what he wanted to do with
> my API, which is not very much unlike his.
Yes, it is.
>> But to me the main issue is the intellectual weight.
>
> There's nothing intellectual about these simple wrappers.
Yes, you have to consider limitations in human's short-term memory
(usability studies show this to be a maximum of 7 +/- 2 elements
accessible at once.)
> var el = API.createElement('div');
>
> var el = API.createElementWithAtttributes('div', { ... });
You don't find identifiers that long hard to remember? Lucky one.
However, it is not you who is supposed to be the main user of this
library, right? Else you would not publish it, would you?
> But wait, you want to use frames? How could that work?
I am afraid you are missing the point.
>> At that point, I have to remember the simpler
>> lower-level versions and the more complex higher-level ones.
>
> Not in the above example. There's nothing to remember.
Surely you can see that the more is to remember the more complex it becomes
what the method is doing. However, a good interface should be kept as
simple as possible and reasonably regardless what the implementation is
doing.
>> Keeping track of parameter order is an issue, but even remembering
>> whether it's called "createAndAppendElementWithAttributes" or
>> "createElementWithAttributesAndAppend" gets to be an intellectual
>> burden.
>
> So create a macro. ;) Or do this (you should anyway):-
You are missing the point. A good library makes it easy for users to use
it by itself. It does not require the creation of macros to do that.
After all, regardless the misguided realization with the one-function-
method, that is why jQuery has gotten so popular; the *interface* is
concise and consistent. ISTM you are going to the other extreme now, and I
think that is an equally bad idea. I am afraid My Library is going to be
DOA if you don't start considering the larger picture, and that would
really be a shame.
>> The Python API simply has less to remember, less to get wrong. It is
>> less flexible, perhaps. But for most of my day-to-day work, I would
>> rather be using a simple-to-remember and simple-to-use API than one
>> with lots of bells and whistles.
>
> Yes, but how does that apply to the wrappers at hand? Could they
> possibly be made simpler?
Yes, definitely. If you allowed the user to pass the result of one wrapper
to the next instead of having one wrapper implicitly use another, the API
would not only become more flexible, but also had less for the user to keep
in mind when using it. Surely you can see that would be an important
advantage, both for you as the library author and for the library user, of
course.
>>>> As you go up each level, the identifiers and argument lists get
>>>> longer, which is to be expected.
>>> Maybe in your book, not in mine. Long argument lists and needless
>>> stacking are an API killer.
>> Yes, *needless* stacking. It's not that stacking cannot be useful.
>> But if not done extremely carefully, it bloats an API and makes it
>> harder to remember and to effectively use.
>
> Yes, I agree that needless stacking is bad. I just don't think it's
> been shown that the three methods in question are needlessly stacked.
> Each layer serves a specific purpose. There are problems with creation
> and problems with appending. Each layer deals with its own problems.
No, evidently it does not. The implementation of layer n+1 depends on the
implementation of layer n, needlessly. Such interdependence is best
avoided in an API.
> Scott Sauyet wrote:
>> Scott Sauyet wrote:
>>> The Python API simply has less to remember, less to get wrong. It is
>>> less flexible, perhaps. But for most of my day-to-day work, I would
>>> rather be using a simple-to-remember and simple-to-use API than one
>>> with lots of bells and whistles.
>>
>> And I should have added, that when we do this in JS we can gain
>> flexibility with an options object:
>>
>> var o = _createElement("foo");
>> var o = _createElement("foo", {attributes: {bar: "baz"});
>> var o = _createElement("foo", {attributes: {bar: "baz"}, docNode:
>> node, appendTo: parent});
>
> Yes, I don't have any problem with that, but I don't find it any more
> memorable.
Order (numbers) has (have) mostly been replaced with names. One less thing
to remember, or if you want, something replaced with something else easier
to remember.
> Fouls up things like Intellisense as well, but that may not be a concern.
Whatever "Intellisense" is, a good code completion feature should be able
to handle that as well.
PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
I do find it more memorable. If I need to do a lot of plain calls
like this:
var o = _createElement("foo")
but also often have to do some like this:
var o = _createElement("foo", {attributes: {bar: "baz"});
it's usually not a leap for me to add
var o = _createElement("foo", {attributes: {bar: "baz"}, appendTo:
parent);
Yes, I still need to know the "appendTo" name, but for me that is much
easier to remember than that it is supposed to be the third parameter
to a function named "createAndAppendElementWithAttributes". In fact,
I confused myself earlier by offering a competing long name for that
function, and I'll be damned if I'm going to look back to check if I
used your original name or my alternative; I *think* that's right.
This is part of the point, though. I'm very likely to remember the
name "createElement".
I don't really know Intellisense. As much as my day job will allow
me, I still work in a programmer's text editor. I hear and understand
all the benefits of powerful IDEs, but I never really feel that they
help me more than they get in my way. Can Intellisense not be
configured to understand named parameters as well as positional ones?
-- Scott
And if you keep going with this, you end up with method chaining,
which is even easier to read, IMO:
var o = _createElement("foo", {attributes:{bar:"baz"}).appendTo
(parent);
Matt Kruse
> Scott Sauyet wrote:
>> var o = _createElement("foo", {attributes: {bar: "baz"});
>> it's usually not a leap for me to add
>> var o = _createElement("foo", {attributes: {bar: "baz"}, appendTo:
>> parent);
>
> And if you keep going with this, you end up with method chaining,
> which is even easier to read, IMO:
>
> var o = _createElement("foo", {attributes:{bar:"baz"}).appendTo
> (parent);
But it is error-prone, unless you want to go down the jQuery road and create
a wrapper object that you return a reference to, which in turn is less
efficient instead. All in all, not a good idea.
It's a sliding scale.
At one end, you have minimal wrappers around core functionality that
are less prone to problems, but your API is clunky and verbose, and
developers are not abstracted from the pains of repetitive tasks,
checking for defined objects, etc.
At the other end, you have a fancy API that is concise and full of
sugar and reads more like pseudo-code, but you sacrifice efficiency,
have the potential for more bugs, and your code risks becoming a mess
internally because of your attempt to handle every case.
David's library (which desperately needs to be renamed) is closer to
the first approach, while something like jQuery is closer to the
second approach.
David's library will appeal to experienced js developers who opt for
robust cross-browser coding and efficiency over a sweet and convenient
API, while jQuery will appeal to average or beginner developers who
opt for layers of abstraction and convenience over efficiency and wide
browser support.
There is a need for both, IMO, because the two extremes cannot both be
satisfied in a single library. The reason David's library avoids some
of the problems that jQuery has is because he says, "Abstracting
functionality X into a general method is not possible without
sacrificing browser support or accuracy in some cases, therefore I
choose not to do it." Instead, he provides the core tools for the user
to implement it himself, with code specific to the context.
There are a number of developers who lack the skill required to take
those core tools and implement the functionality correctly, and will
gladly sacrifice browser support and accuracy in some cases and use an
abstraction that works well enough for their situation. This group is
the vast majority, IMO. Hence the popularity of jQuery.
I think that a tool like David's library will only become popular and
widely used if he can A) Educate developers about why they should seek
a better solution than something like jQuery (and do so with grace,
which he lacks) and B) provide a migration path for users to move
towards his library (or something like it).
If his goal is to fill the niche of a toolkit for experienced
developers and not to appeal to the masses, then that's fine too, but
it seems to me that he seeks the latter. Otherwise his target would
surely not be the major libraries like jQuery.
Matt Kruse
> Thomas 'PointedEars' Lahn wrote:
>> But it is error-prone, unless you want to go down the jQuery road and
>> create a wrapper object that you return a reference to, which in turn is
>> less efficient instead. All in all, not a good idea.
>
> It's a sliding scale.
>
> At one end, you have minimal wrappers around core functionality that
> are less prone to problems, but your API is clunky and verbose, and
> developers are not abstracted from the pains of repetitive tasks,
> checking for defined objects, etc.
>
> At the other end, you have a fancy API that is concise and full of
> sugar and reads more like pseudo-code, but you sacrifice efficiency,
> have the potential for more bugs, and your code risks becoming a mess
> internally because of your attempt to handle every case. [...]
Let us be clear about this: by "not a good idea" I was referring to *your*
idea of "method chaining". Regardless, I think there is a third dimension
that you are missing here.
That's a pretty vague point. Care to elaborate?
-- Scott
> Thomas 'PointedEars' Lahn wrote:
>> Regardless, I think there is a third dimension
>> that you are missing here.
>
> That's a pretty vague point. Care to elaborate?
Sure, if you had cared quoting something for me to refer to.
Your signature is borken, too.
>At the other end, you have a fancy API that is concise and full of
>sugar and reads more like pseudo-code, but you sacrifice efficiency,
>have the potential for more bugs, and your code risks becoming a mess
>internally because of your attempt to handle every case.
Yes, somebody should do it right, without bugs and without
writing messy code. That's certainly possible, even if jQuery
doesn't measure up.
That leaves the efficiency question. My opinion on that is that
efficiency becomes less important year by year, as the machines
get faster and JavaScript perhaps becomes a compiled language.
Also there are many cases, particularly the simple things done
by beginners, that don't need any high efficiency. I guess the
vast majority of web site code is fast enough with jQuery for
most purposes.
If I see any problems with jQuery, then low efficiency is the
least of my worries. If I need high efficiency, I don't have to
use jQuery, or any library, for that matter.
It is good to give the programmer a choice, but he has that
anyway. He can always choose to replace jQuery calls with
hand-coded JavaScript.
When I write jQuery here, I actually mean anything jQuery-like.
Hans-Georg
>.insertAfter(el)
Isn't that method deprecated or even removed altogether? Use
.insertBefore(el) always.
Hans-Georg
Do you really want to write a wrapper to address that? I'll pass on that.
>> If the problem is narrower there aren't as many edge cases. For example,
>> a hidden method `createCalendarOnDemand` creates HTML for the calendar
>> widget.
>
> What calendar widget? And why does that method create HTML? Also,
> aren't all methods on demand?
>
The widget in particular is beside the point: Creating HTML for a
specific case can be simple, unlike trying to fulfill all cases. But
since you asked, here is the calendar:
http://github.com/GarrettS/ape-javascript-library/blob/master/src/widget/calendar/Calendar.js
The method creates the HTML so that the user will have something to
interact with. The HTML could be in the page. That would be a little bit
harder to use the API. The way it is now, the HTML is pretty simple:
| <div class="ape-calendar-container" id="start-container">
| <label for="start" id='sf'>Start (YYYY-MM-DD)</label>
|
| <input id="start" name="start" type="date"
| class="ape-calendar-input">
| </div>
Are all methods on demand?
Not all methods do something on-demand. The method
`createCalendarOnDemand` creates the calendar HTML if it doesn't exist.
| if(d.getElementById(calendar.calendarId) !== null) return;
The HTML for the calendar is called only after the user has started
interacting with the INPUT.
Even though it's beside the point, I'd like to get any feedback on that.
>> It has no options to determine the HTML structure, and so there
>> is not testing multiple contexts and configurations. I like that.
>
> Yes, context specific solutions always trump GP. But we are talking
> about (though not necessarily advocating) a GP library.
Reusable wrappers are great for avoiding rewriting things. Ideally.
Sometimes what seems like a simple wrapper -- and this is especially
true for dom stuff -- is that it has to address too much complexity with
divergent browser object models.
What about it?!
> How about creating a named anchor, an
What are you having problems with?
> element, anything with `class` or `for` attribute, or any attribute that
> IE sees as a property, or needs special case handling, such as cellPadding.
I take it you have been paying only cursory attention.
http://www.cinsoft.net/attributes.html
This stuff is not new.
>
> Do you really want to write a wrapper to address that? I'll pass on that.
Are you paying _any_ attention at all? I wrote the wrapper years ago.
You need something like that for certain types of projects (e.g.
anything with a CSS selector query interface, editors, etc.) It's not a
philosophical question.
>
>>> If the problem is narrower there aren't as many edge cases. For example,
>>> a hidden method `createCalendarOnDemand` creates HTML for the calendar
>>> widget.
>>
>> What calendar widget? And why does that method create HTML? Also,
>> aren't all methods on demand?
>>
>
> The widget in particular is beside the point: Creating HTML for a
> specific case can be simple, unlike trying to fulfill all cases. But
> since you asked, here is the calendar:
> http://github.com/GarrettS/ape-javascript-library/blob/master/src/widget/calendar/Calendar.js
But why HTML? I thought we were talking about creating/mutating DOM
nodes. Is that what you mean? Regardless, I know you don't need such a
wrapper for such a widget. It doesn't really fall into the categories
that have been listed (endlessly it seems).
>
>
> The method creates the HTML so that the user will have something to
> interact with.
The DOM structure? HTML to me means you are creating a string of markup.
> The HTML could be in the page. That would be a little bit
> harder to use the API. The way it is now, the HTML is pretty simple:
>
> | <div class="ape-calendar-container" id="start-container">
> | <label for="start" id='sf'>Start (YYYY-MM-DD)</label>
> |
> | <input id="start" name="start" type="date"
> | class="ape-calendar-input">
> | </div>
That markup doesn't make sense to me. I'm picturing it without
scripting. Or is this what the widget creates?
>
>
> Are all methods on demand?
The quoting is screwed up here.
>
> Not all methods do something on-demand. The method
> `createCalendarOnDemand` creates the calendar HTML if it doesn't exist.
Whatever. I don't think it creates HTML at all. And how does "on
demand" simplify things? I'd through that thing out as soon as I read
the name of that method. I don't want to have to remember what you
consider "on demand" to mean. ;)
>
> | if(d.getElementById(calendar.calendarId) !== null) return;
Yes, so? You return early if the element is not in the document. I
hate it (for so many reasons). :(
>
> The HTML for the calendar is called only after the user has started
> interacting with the INPUT.
That sounds more like "on demand" to me. Still, if you can't explain it
without inducing confusing...
>
> Even though it's beside the point, I'd like to get any feedback on that.
I absolutely can't stand the idea of a function that does something,
except when it doesn't. Break that up into two (one that checks if the
element is there and one that appends it). Creating it "on demand"
(according to the last bit of the explanation) can be useful though.
You might want to make it an option. And realize that the user's
interaction has nothing to do with whether the element is in the
document. You've got some wires crossed there.
>
>>> It has no options to determine the HTML structure, and so there
>>> is not testing multiple contexts and configurations. I like that.
>>
>> Yes, context specific solutions always trump GP. But we are talking
>> about (though not necessarily advocating) a GP library.
> Reusable wrappers are great for avoiding rewriting things. Ideally.
> Sometimes what seems like a simple wrapper -- and this is especially
> true for dom stuff -- is that it has to address too much complexity with
> divergent browser object models.
Except that isn't the case at all for attributes. There's exactly two
models and one of those is never going to change again.
Really, you need more context? I'm referring to message
<2401506.B...@PointedEars.de>
which can also be found online at
http://groups.google.com/group/comp.lang.javascript/msg/c9e63eddc8bfecef
and which you posted approximately seven minutes before I responded,
and about fourteen minutes before the message in which seem to have
forgotten the context.
But just for your edification, Matt Kruse had quoted you as saying
||| But it is error-prone, unless you want to go down the jQuery road
and
||| create a wrapper object that you return a reference to, which in
turn is
||| less efficient instead. All in all, not a good idea.
and then responded with:
|| It's a sliding scale.
||
|| At one end, you have minimal wrappers around core functionality
that
|| are less prone to problems, but your API is clunky and verbose, and
|| developers are not abstracted from the pains of repetitive tasks,
|| checking for defined objects, etc.
||
|| At the other end, you have a fancy API that is concise and full of
|| sugar and reads more like pseudo-code, but you sacrifice
efficiency,
|| have the potential for more bugs, and your code risks becoming a
mess
|| internally because of your attempt to handle every case. [...]
To which you said
| Let us be clear about this: by "not a good idea" I was referring to
*your*
| idea of "method chaining". Regardless, I think there is a third
dimension
| that you are missing here.
Is that exchange familiar? Did you really need me to quote it here to
give context?
Now, back to the original question. What third dimension are you
suggesting need to be considered on top of Matt's (one-dimensional!)
scale of API efficiency versus API power?
> Your signature is borken, too.
>
> PointedEars
> --
> Prototype.js was written by people who don't know javascript for people
> who don't know javascript. People who don't know javascript are not
> the best source of advice on designing systems that use javascript.
> Â -- Richard Cornford, cljs, <f806at$ail$1$8300d...@news.demon.co.uk>
I have no .sig file, believing that my FROM address header should be
all the contact information necessary and that posting five or six
lines of quotation is simply a waste of other user's bandwidth.
Instead, I manually type what is sometimes called a signature line, as
in this quote from (en) Wikipedia:
| A shortened form of a signature block (sometimes called a
"signature
| line"), only including one's name, often with some distinguishing
| prefix, can be used to simply indicate the end of a post or
| response. -- http://en.wikipedia.org/wiki/Signature_block
Mine is usually two spaces followed by two hyphens (the ususal ASCII
representation of a dash), a space, and my first name. It is set off
from the preceding text by a blank line, for a total of around a dozen
characters including new lines. In contrast, the signature you used
was six lines long, and nearly 300 characters. It consists of your
_nom de guerre_, a signature cut line, and a quotation (one of several
in rotation or randomly chosen, I've noticed) which might be vaguely
amusing the first time read but just becomes tiresome when seen
repeatedly. Your signature, is of course below the McQuarry limit --
I would expect no less -- but it is still a waste of bandwidth, IMHO.
What do you find wrong with my signature, then?
-- Scott
It is unwise to take on Sir Pointy Ears in a contest of pettiness and
triviality - even in jest - for you shall always lose to his
overwhelming talent.
- --- xoxo Matt Kruse (c) (tm)
--
<Insert pithy quote here to demonstrate elevated intellect>
Okay.
>
> At one end, you have minimal wrappers around core functionality that
> are less prone to problems, but your API is clunky and verbose, and
> developers are not abstracted from the pains of repetitive tasks,
> checking for defined objects, etc.
I sense an oversimplification here.
>
> At the other end, you have a fancy API that is concise and full of
> sugar and reads more like pseudo-code, but you sacrifice efficiency,
> have the potential for more bugs, and your code risks becoming a mess
> internally because of your attempt to handle every case.
And then there's the possibility that the core beneath the sugar is
rotten (seemingly always).
>
> David's library (which desperately needs to be renamed)
Yeah, I can buy that. I guess my thinking is that it shouldn't
matter. I'm not selling sizzle (no pun intended). I've got the whole
steak wrapped up and ready for your grill. And I support the thing,
so it's really a no-brainer. :)
> is closer to
> the first approach, while something like jQuery is closer to the
> second approach.
Sort of. It is an API, but certainly it simplifies checking for
"defined objects". The whole point is that feature detection/testing
is not for beginners, so why not provide an interface that shields
them from that entirely. And, of course, without the innovation of
the dynamic API, there'd be no shot of doing "progressive enhancement"
at all. Zero. Did that practice just fall by the wayside with the
arrival of cheap scripts like Prototype and jQuery? Doesn't make a
lot of sense as all they talk about is progressive enhancement (and
the real world, of course).
And then there is the fact that there is an _optional_ OO interface.
It's always been there, supports "chaining" and queries and all of the
rest of what people seem to like about jQuery. And it's _very_ easy
to read that code (DOM | Query | Wrapper Objects). Anyone could put
their own "face" on the underlying API.
>
> David's library will appeal to experienced js developers who opt for
> robust cross-browser coding and efficiency over a sweet and convenient
> API, while jQuery will appeal to average or beginner developers who
> opt for layers of abstraction and convenience over efficiency and wide
> browser support.
No, I've got both the apples and the oranges and I support both. Game
over. Nobody should want or need jQuery's shriveled up oranges at
this point.
>
> There is a need for both, IMO, because the two extremes cannot both be
> satisfied in a single library.
Oh but they _can_.
> The reason David's library avoids some
> of the problems that jQuery has is because he says, "Abstracting
> functionality X into a general method is not possible without
> sacrificing browser support or accuracy in some cases, therefore I
> choose not to do it."
I don't remember saying that at all? What is it you find lacking in
the feature set?
> Instead, he provides the core tools for the user
> to implement it himself, with code specific to the context.
Yes. And the higher-level stuff is there to pile on if you need it.
It's the best of both worlds (and perfectly suited for the "real
world" as imagined by jQuery advocates). :)
>
> There are a number of developers who lack the skill required to take
> those core tools and implement the functionality correctly, and will
> gladly sacrifice browser support and accuracy in some cases and use an
> abstraction that works well enough for their situation.
But, but, but... See above.
> This group is
> the vast majority, IMO. Hence the popularity of jQuery.
But none of this adds up and you are just looking at the sordid past
anyway. Things changed dramatically with the arrival of IE8 (who
could have predicted that).
>
> I think that a tool like David's library will only become popular and
> widely used if he can A) Educate developers about why they should seek
> a better solution than something like jQuery (and do so with grace,
> which he lacks)
It's not my job to educate developers. I do have openings for
"evangelists" though...
> and B) provide a migration path for users to move
> towards his library (or something like it).
I don't follow. If you can do $('#test'), you can do E('#test'). Or
you can skip both of those as they are unnecessary abstractions on top
of gEBI wrappers (e.g. API.getEBI('test'))
>
> If his goal is to fill the niche of a toolkit for experienced
> developers and not to appeal to the masses, then that's fine too, but
> it seems to me that he seeks the latter.
I seek nothing. I am found. All I had to do was say a few choice
words a month ago to get the ball rolling. It will flatten jQuery
eventually.
> Otherwise his target would
> surely not be the major libraries like jQuery.
>
Target? The "major" libraries are so named because they came out (and
were heavily marketed) years ago. That's all. Since then, jQuery has
started to look more and more like My Library. If it weren't for
copied innovations, they'd have nothing but endless rewrites to "keep
up" with the latest set of major browsers. Oh, and "Live". That's a
complete and utter failure for a cross-browser script. Write once, do
nothing, run anywhere, forever. Does jQuery sound anything like that?
It is perhaps unmanly to joust with the court jester, but sometimes
it's just so much fun! :-)
-- Scott
A wrapper that allows appending a SELECT to an OPTION should probably
address the differences. That would best be done in a separate function.
Adding an option to a SELECT is a lot simpler than adding anything to
anything with any attributes.
>> How about creating a named anchor, an
>
> What are you having problems with?
>
Links to the anchor don't work:
<a href="#myNewAnchor">
Plenty more examples related to NAME on MSDN.
http://msdn.microsoft.com/en-us/library/ms536389%28VS.85%29.aspx
>> element, anything with `class` or `for` attribute, or any attribute that
>> IE sees as a property, or needs special case handling, such as cellPadding.
>
> I take it you have been paying only cursory attention.
>
> http://www.cinsoft.net/attributes.html
>
> This stuff is not new.
>
You didn't like the feedback I gave you last time?
>> Do you really want to write a wrapper to address that? I'll pass on that.
>
> Are you paying _any_ attention at all? I wrote the wrapper years ago.
So?
> You need something like that for certain types of projects (e.g.
> anything with a CSS selector query interface, editors, etc.) It's not a
> philosophical question.
>
I don't need a CSS Selector Query interface.
I can see the use of an attributes wrapper for an Editor. For that, it
might make sense to limit the attribute reading to be used for the editor.
>>>> If the problem is narrower there aren't as many edge cases. For example,
>>>> a hidden method `createCalendarOnDemand` creates HTML for the calendar
>>>> widget.
>>> What calendar widget? And why does that method create HTML? Also,
>>> aren't all methods on demand?
>>>
>> The widget in particular is beside the point: Creating HTML for a
>> specific case can be simple, unlike trying to fulfill all cases. But
>> since you asked, here is the calendar:
>> http://github.com/GarrettS/ape-javascript-library/blob/master/src/widget/calendar/Calendar.js
>
> But why HTML? I thought we were talking about creating/mutating DOM
> nodes. Is that what you mean?
The reason that that is mentioned
Regardless, I know you don't need such a
> wrapper for such a widget. It doesn't really fall into the categories
> that have been listed (endlessly it seems).
>
You listed two:-
1) CSS Query Selector
2) Editor
The most complex, feature rich applications will not need a CSS Selector
Query interface.
I can see the use for an Editor. For that, it might make sense to limit
the parsing of editor's html to a narrower scope.
>>
>> The method creates the HTML so that the user will have something to
>> interact with.
>
> The DOM structure? HTML to me means you are creating a string of markup.
>
>> The HTML could be in the page. That would be a little bit
>> harder to use the API. The way it is now, the HTML is pretty simple:
>>
>> | <div class="ape-calendar-container" id="start-container">
>> | <label for="start" id='sf'>Start (YYYY-MM-DD)</label>
>> |
>> | <input id="start" name="start" type="date"
>> | class="ape-calendar-input">
>> | </div>
>
> That markup doesn't make sense to me. I'm picturing it without
> scripting. Or is this what the widget creates?
>
When script is disabled, the user sees an input and a label:
"Start (YYYY-MM-DD)" [ ]
>>
>> Are all methods on demand?
>
> The quoting is screwed up here.
>
You're still using googlegroups.com, so that could be related to the
problem. You might want to consider getting a newsserver.
>> Not all methods do something on-demand. The method
>> `createCalendarOnDemand` creates the calendar HTML if it doesn't exist.
>
> Whatever. I don't think it creates HTML at all. And how does "on
> demand" simplify things?
The calendar widget is not created unless it is needed. Less html =
lighter page.
The benefit of creating the widget on-demand (lazily, when user
interacts), is efficiency.
Consider the alternative. The normal way, building that HTML in an init
method, called onload would have two effects:
1) slow down page load with creating extra HTML
2) adds extra HTML to the DOM, even if it is not needed.
A page that tries to create many widgets during an/or after load slows
down more noticeably. The value in saving those precious milliseconds on
load is even more noticeable when many widgets are used.
I'd through that thing out as soon as I read
> the name of that method. I don't want to have to remember what you
> consider "on demand" to mean. ;)
>
Interesting. How were you planning on calling that method?
>> | if(d.getElementById(calendar.calendarId) !== null) return;
>
> Yes, so? You return early if the element is not in the document. I
> hate it (for so many reasons). :(
>
You're completely wrong here. It is only one line of code. A code
comment seemed like extraneous noise, but if that line is confusing,
then does this seem any clearer:
| // If the element is not null, exit.
| if(d.getElementById(calendar.calendarId) !== null) return;
?
>> The HTML for the calendar is called only after the user has started
>> interacting with the INPUT.
>
> That sounds more like "on demand" to me. Still, if you can't explain it
> without inducing confusing...
>
I didn't explain it. You sort of did, but got it wrong.
>> Even though it's beside the point, I'd like to get any feedback on that.
>
> I absolutely can't stand the idea of a function that does something,
> except when it doesn't. Break that up into two (one that checks if the
> element is there and one that appends it).
I don't find the null check to be confusing at all.
Creating it "on demand"
> (according to the last bit of the explanation) can be useful though.
> You might want to make it an option.
An option? No, absolutely not. That is something that client of the API
has no knowledge of. The client of the API calls:-
Calendar.getById("birthday");
And realize that the user's
> interaction has nothing to do with whether the element is in the
> document. You've got some wires crossed there.
>
The user's interation has nothing to do with whether the element is in
the document? Where are you getting this?
>>>> It has no options to determine the HTML structure, and so there
>>>> is not testing multiple contexts and configurations. I like that.
>>> Yes, context specific solutions always trump GP. But we are talking
>>> about (though not necessarily advocating) a GP library.
>> Reusable wrappers are great for avoiding rewriting things. Ideally.
>> Sometimes what seems like a simple wrapper -- and this is especially
>> true for dom stuff -- is that it has to address too much complexity with
>> divergent browser object models.
>
> Except that isn't the case at all for attributes. There's exactly two
> models and one of those is never going to change again.
There is IE with attribute-as-properties and then there is the DOM
attributes.
A DOM wrapper for attributes or properties in the general sense seems
like a good exercise for learning about browser quirks.
The nodes for a widget can be build where needed for that widget. The
solution for that might use Array methods, set innerHTML, or assign
property values.
The code you wrote might come in handy for an editor.
Oh, forget that bullshit. That property doesn't matter until you append
the thing to a document. Host objects 101. Don't try to do stupid things.
>
> A wrapper that allows appending a SELECT to an OPTION should probably
> address the differences. That would best be done in a separate function.
I don't follow that, even if you mean adding an option to a select. The
way to address the "issue" is in a function that finds the selected option.
>
> Adding an option to a SELECT is a lot simpler than adding anything to
> anything with any attributes.
Yes, that's true.
>
>>> How about creating a named anchor, an
>>
>> What are you having problems with?
>>
>
> Links to the anchor don't work:
>
> <a href="#myNewAnchor">
So? You don't know how to fix that? See the wrapper posted in this
thread. ;)
>
> Plenty more examples related to NAME on MSDN.
>
> http://msdn.microsoft.com/en-us/library/ms536389%28VS.85%29.aspx
Examples of what? That anchors don't show up in the anchors or links
collections if you name them prematurely? Same for forms, iframes, etc.
It's an old issue and easily dealt with in a wrapper.
>
>>> element, anything with `class` or `for` attribute, or any attribute that
>>> IE sees as a property, or needs special case handling, such as
>>> cellPadding.
>>
>> I take it you have been paying only cursory attention.
>>
>> http://www.cinsoft.net/attributes.html
>>
>> This stuff is not new.
>>
>
> You didn't like the feedback I gave you last time?
About what? The unit tests (and don't start with semantics again?) No,
not really as it was sort of missing the point.
>
>>> Do you really want to write a wrapper to address that? I'll pass on
>>> that.
>>
>> Are you paying _any_ attention at all? I wrote the wrapper years ago.
>
> So?
So nothing. It's there. This stuff should not be an issue in 2010 for
a browser that came out in 1999. The whole idea is beyond belief.
>
>> You need something like that for certain types of projects (e.g.
>> anything with a CSS selector query interface, editors, etc.) It's not a
>> philosophical question.
>>
>
> I don't need a CSS Selector Query interface.
Few do, but everybody seems to want one anyway. ;)
>
> I can see the use of an attributes wrapper for an Editor. For that, it
> might make sense to limit the attribute reading to be used for the editor.
>
>>>>> If the problem is narrower there aren't as many edge cases. For
>>>>> example,
>>>>> a hidden method `createCalendarOnDemand` creates HTML for the calendar
>>>>> widget.
>>>> What calendar widget? And why does that method create HTML? Also,
>>>> aren't all methods on demand?
>>>>
>>> The widget in particular is beside the point: Creating HTML for a
>>> specific case can be simple, unlike trying to fulfill all cases. But
>>> since you asked, here is the calendar:
>>> http://github.com/GarrettS/ape-javascript-library/blob/master/src/widget/calendar/Calendar.js
>>>
>>
>> But why HTML? I thought we were talking about creating/mutating DOM
>> nodes. Is that what you mean?
>
> The reason that that is mentioned
Looks like your reply ran aground here. (?)
>
> Regardless, I know you don't need such a
>> wrapper for such a widget. It doesn't really fall into the categories
>> that have been listed (endlessly it seems).
>>
> You listed two:-
> 1) CSS Query Selector
> 2) Editor
Or parser or anything that needs to canonicalize the document. Use your
imagination.
>
> The most complex, feature rich applications will not need a CSS Selector
> Query interface.
Almost nobody does, but...
>
> I can see the use for an Editor. For that, it might make sense to limit
> the parsing of editor's html to a narrower scope.
Which is something you can build on top of the low-level functions. And
not just for an editor either. Are you familiar with things like the
Dijit (ecch) parser? See what I'm getting at? All of these things out
there, ostensibly produced by huge concerns (e.g. IBM, Apple) are
slipping around on shitty foundations and apologizing profusely for it,
year after year (at least they are polite about it). It is time
somebody cried foul. It's not the browsers causing the mess. It's
_them_. Hell, the browsers have been great for years. All you have to
do is run my test page back through time and the drop-offs become apparent.
>
>>>
>>> The method creates the HTML so that the user will have something to
>>> interact with.
>>
>> The DOM structure? HTML to me means you are creating a string of markup.
>>
>>> The HTML could be in the page. That would be a little bit
>>> harder to use the API. The way it is now, the HTML is pretty simple:
>>>
>>> | <div class="ape-calendar-container" id="start-container">
>>> | <label for="start" id='sf'>Start (YYYY-MM-DD)</label>
>>> |
>>> | <input id="start" name="start" type="date"
>>> | class="ape-calendar-input">
>>> | </div>
>>
>> That markup doesn't make sense to me. I'm picturing it without
>> scripting. Or is this what the widget creates?
>>
>
> When script is disabled, the user sees an input and a label:
>
> "Start (YYYY-MM-DD)" [ ]
That's what I would have expected. Somehow I didn't see that earlier
(just the DIV with the funny class).
>
>>>
>>> Are all methods on demand?
>>
>> The quoting is screwed up here.
>>
>
> You're still using googlegroups.com, so that could be related to the
> problem. You might want to consider getting a newsserver.
No, I am not still using anything specifically. I use whatever is
handy. And yes, I "got" a news server (I'm using it now). ;)
>
>>> Not all methods do something on-demand. The method
>>> `createCalendarOnDemand` creates the calendar HTML if it doesn't exist.
>>
>> Whatever. I don't think it creates HTML at all. And how does "on
>> demand" simplify things?
>
> The calendar widget is not created unless it is needed. Less html =
> lighter page.
Yes, I am all for lighter pages.
>
> The benefit of creating the widget on-demand (lazily, when user
> interacts), is efficiency.
Sometimes sacrificing responsiveness. It's a trade-off that depends on
context, which is why I suggested a configuration flag for that.
>
> Consider the alternative. The normal way, building that HTML in an init
> method, called onload would have two effects:
I don't see that as the "normal" way (just another way).
>
> 1) slow down page load with creating extra HTML
Will you stop fucking calling it HTML. There's enough confusion in this
group as there is. You aren't creating HTML any more than Resig is
detecting "object literals". You are creating a DOM structure.
> 2) adds extra HTML to the DOM, even if it is not needed.
:(
>
> A page that tries to create many widgets during an/or after load slows
> down more noticeably. The value in saving those precious milliseconds on
> load is even more noticeable when many widgets are used.
As mentioned, it all comes down to context (e.g. how many widgets, how
long do they take to create, etc.)
>
> I'd through that thing out as soon as I read
Dammit. Your quoting is fucking up here again. No way this is my
fault. I used GG for years and never hard this problem.
>> the name of that method. I don't want to have to remember what you
>> consider "on demand" to mean. ;)
>>
>
> Interesting. How were you planning on calling that method?
I wasn't.
>
>>> | if(d.getElementById(calendar.calendarId) !== null) return;
>>
>> Yes, so? You return early if the element is not in the document. I
>> hate it (for so many reasons). :(
>>
>
> You're completely wrong here.
No I am not. You are barking up the wrong tree.
> It is only one line of code.
That tree.
> A code
> comment seemed like extraneous noise, but if that line is confusing,
> then does this seem any clearer:
Of course not. It has to do with code design, not clarity. Returning
early like that is bullshit. Restructure the design so that the caller
doesn't call in the first place in that circumstance. If you are
worried about public API calls, you don't want those to fail silently
either. ;)
>
> | // If the element is not null, exit.
> | if(d.getElementById(calendar.calendarId) !== null) return;
>
> ?
>
>>> The HTML for the calendar is called only after the user has started
>>> interacting with the INPUT.
>>
>> That sounds more like "on demand" to me. Still, if you can't explain it
>> without inducing confusing...
>>
>
> I didn't explain it. You sort of did, but got it wrong.
Bullshit and no time for semantic arguments. Thanks anyway.
>
>>> Even though it's beside the point, I'd like to get any feedback on that.
>>
>> I absolutely can't stand the idea of a function that does something,
>> except when it doesn't. Break that up into two (one that checks if the
>> element is there and one that appends it).
>
> I don't find the null check to be confusing at all.
Confusion is not the issue either.
>
> Creating it "on demand"
Again, the quoting is off. The problem is in your set.
>> (according to the last bit of the explanation) can be useful though.
>> You might want to make it an option.
>
> An option? No, absolutely not. That is something that client of the API
> has no knowledge of. The client of the API calls:-
And why not? They don't have to have knowledge of it. It could be
optional with the default the same as it is now. Context is everything
with this stuff. You can't decide what is best for all apps.
>
> Calendar.getById("birthday");
>
> And realize that the user's
>> interaction has nothing to do with whether the element is in the
>> document. You've got some wires crossed there.
>>
>
> The user's interation has nothing to do with whether the element is in
> the document? Where are you getting this?
You aren't thinking. What you repeated is correct, but there seems to
be some design concepts that aren't registering with you. Asking where
I am "getting this" isn't likely to bear fruit.
>
>>>>> It has no options to determine the HTML structure, and so there
>>>>> is not testing multiple contexts and configurations. I like that.
>>>> Yes, context specific solutions always trump GP. But we are talking
>>>> about (though not necessarily advocating) a GP library.
>>> Reusable wrappers are great for avoiding rewriting things. Ideally.
>>> Sometimes what seems like a simple wrapper -- and this is especially
>>> true for dom stuff -- is that it has to address too much complexity with
>>> divergent browser object models.
>>
>> Except that isn't the case at all for attributes. There's exactly two
>> models and one of those is never going to change again.
> There is IE with attribute-as-properties and then there is the DOM
> attributes.
>
> A DOM wrapper for attributes or properties in the general sense seems
> like a good exercise for learning about browser quirks.
So is writing a calendar widget, yet they both have practical
applications as well.
>
> The nodes for a widget can be build where needed for that widget. The
> solution for that might use Array methods, set innerHTML, or assign
> property values.
>
> The code you wrote might come in handy for an editor.
Or anything else that creates elements. It depends on the author(s),
context, scope of the project, etc. Certainly an editor (which seems to
be the centerpiece of every widget library) is the quintessential example.
I missed a comma right after "narrower".
In the third sentence, could have used "That method" instead of "It", as
in:-
"That method has no options to..."
DOn't try stupid things? Like what? Append an OPTION to a SELECT and
then append the SELECT to the DOM, but expect something related to the
option being selected? Nope, I have a different approach for SELECTs.
Here's another stupid idea: A wrapper for DOM attributes.
>> A wrapper that allows appending a SELECT to an OPTION should probably
>> address the differences. That would best be done in a separate function.
>
> I don't follow that, even if you mean adding an option to a select. The
> way to address the "issue" is in a function that finds the selected option.
>
A function createAndAppendElementWithAttributes would seem to be capable
of creating and appending an element with attributes. It should also be
reasonably expected to be consistent across browsers.
>> Adding an option to a SELECT is a lot simpler than adding anything to
>> anything with any attributes.
>
> Yes, that's true.
>
You don't even need to know about the problems with adding an OPTION to
a SELECT to recognize the obviousness of that.
>>>> How about creating a named anchor, an
>>> What are you having problems with?
>>>
>> Links to the anchor don't work:
>>
>> <a href="#myNewAnchor">
>
> So? You don't know how to fix that? See the wrapper posted in this
> thread. ;)
>
The solution I am familiar with is using MS createElement nonstandard
extension.
That approach is specified to throw errors, and so if it is used, then
it must be feature tested and the feature test would involve try-catch.
>> Plenty more examples related to NAME on MSDN.
>>
>> http://msdn.microsoft.com/en-us/library/ms536389%28VS.85%29.aspx
>
> Examples of what? That anchors don't show up in the anchors or links
> collections if you name them prematurely? Same for forms, iframes, etc.
> It's an old issue and easily dealt with in a wrapper.
>
>>>> element, anything with `class` or `for` attribute, or any attribute that
>>>> IE sees as a property, or needs special case handling, such as
>>>> cellPadding.
>>> I take it you have been paying only cursory attention.
>>>
>>> http://www.cinsoft.net/attributes.html
>>>
>>> This stuff is not new.
>>>
>> You didn't like the feedback I gave you last time?
>
> About what? The unit tests (and don't start with semantics again?) No,
> not really as it was sort of missing the point.
>
No, that too, though. I commented on the long section of statements you
refer to as a "unit test" in your viewport function.
>>>> Do you really want to write a wrapper to address that? I'll pass on
>>>> that.
>>> Are you paying _any_ attention at all? I wrote the wrapper years ago.
>> So?
>
> So nothing. It's there. This stuff should not be an issue in 2010 for
> a browser that came out in 1999. The whole idea is beyond belief.
>
I do not keep tabs on when you write things.
>> I can see the use of an attributes wrapper for an Editor. For that, it
>> might make sense to limit the attribute reading to be used for the editor.
>>
>>>>>> If the problem is narrower there aren't as many edge cases. For
>>>>>> example,
>>>>>> a hidden method `createCalendarOnDemand` creates HTML for the calendar
>>>>>> widget.
>>>>> What calendar widget? And why does that method create HTML? Also,
>>>>> aren't all methods on demand?
>>>>>
>>>> The widget in particular is beside the point: Creating HTML for a
>>>> specific case can be simple, unlike trying to fulfill all cases. But
>>>> since you asked, here is the calendar:
>>>> http://github.com/GarrettS/ape-javascript-library/blob/master/src/widget/calendar/Calendar.js
>>>>
>>> But why HTML? I thought we were talking about creating/mutating DOM
>>> nodes. Is that what you mean?
>> The reason that that is mentioned
>
> Looks like your reply ran aground here. (?)
>
Creating nodes can work for specific tasks such as above, but for
general purpose, it is unneeded.
>> Regardless, I know you don't need such a
>>> wrapper for such a widget. It doesn't really fall into the categories
>>> that have been listed (endlessly it seems).
>>>
>> You listed two:-
>> 1) CSS Query Selector
>> 2) Editor
>
> Or parser or anything that needs to canonicalize the document. Use your
> imagination.
>
Speculate on a need that does not exist? Never.
Work the other way.
Create abstractions as they're needed. Organize the abstractions to
allow for effective reuse.
Test the abstractions. When something doesn't work, the test can be
added to the suite. When the abstration gets refactored, then the tests
can reflect that.
Adding OPTION to a SELECT is very generic, but probably can work in
almost any normal context.
Creating a specific widget (UserPanel) is going to be more specific. In
a specific case, for a higher level widget, the nodes/html for the
widget can be generated in a self-contained function.
>> The most complex, feature rich applications will not need a CSS Selector
>> Query interface.
>
> Almost nobody does, but...
>
Nope.
>> I can see the use for an Editor. For that, it might make sense to limit
>> the parsing of editor's html to a narrower scope.
>
> Which is something you can build on top of the low-level functions. And
> not just for an editor either. Are you familiar with things like the
> Dijit (ecch) parser?
Feel free to enlighten me.
My experiences with Dojo based applications is that they tend to be slow
to load. Well I've only worked on two applications that used Dojo.
Other applications that use dojo that I interviewed for, they complained
about slow performance.
[...]
>
>> I'd through that thing out as soon as I read
>
>
> Dammit. Your quoting is fucking up here again. No way this is my
> fault. I used GG for years and never hard this problem.
>
?
>>> the name of that method. I don't want to have to remember what you
>>> consider "on demand" to mean. ;)
>>>
>> Interesting. How were you planning on calling that method?
>
> I wasn't.
>
Why would you have to remember the name of that method?
>>>> | if(d.getElementById(calendar.calendarId) !== null) return;
>>> Yes, so? You return early if the element is not in the document. I
>>> hate it (for so many reasons). :(
>>>
>> You're completely wrong here.
>
> No I am not. You are barking up the wrong tree.
>
YOu wrote "You return early if the element is not in the document." That
is wrong. Please do look at that one line of code.
>> It is only one line of code.
>
> That tree.
>
It is not a tree.
>> A code
>> comment seemed like extraneous noise, but if that line is confusing,
>> then does this seem any clearer:
>
> Of course not. It has to do with code design, not clarity. Returning
> early like that is bullshit.
Oh really? It is "bullshit" to return early? Who taught you that? Or
better yet, why did you believe it?
Restructure the design so that the caller
> doesn't call in the first place in that circumstance. If you are
> worried about public API calls, you don't want those to fail silently
> either. ;)
>
What caller and what circumstance?
The caller of that method calls it so that the calendar can be created.
If the calendar is already created, then the method exits.
>> | // If the element is not null, exit.
>> | if(d.getElementById(calendar.calendarId) !== null) return;
>>
>> ?
>>
>>>> The HTML for the calendar is called only after the user has started
>>>> interacting with the INPUT.
>>> That sounds more like "on demand" to me. Still, if you can't explain it
>>> without inducing confusing...
>>>
>> I didn't explain it. You sort of did, but got it wrong.
>
> Bullshit and no time for semantic arguments. Thanks anyway.
>
Apparently the code comment did *not* help. So it is down to an English
problem. What meaning do you get from: "If the element is not null, exit."
>>>> Even though it's beside the point, I'd like to get any feedback on that.
>>> I absolutely can't stand the idea of a function that does something,
>>> except when it doesn't. Break that up into two (one that checks if the
>>> element is there and one that appends it).
>> I don't find the null check to be confusing at all.
>
> Confusion is not the issue either.
>
Apparently it was.
>> Creating it "on demand"
>
> Again, the quoting is off. The problem is in your set.
>
>>> (according to the last bit of the explanation) can be useful though.
>>> You might want to make it an option.
>> An option? No, absolutely not. That is something that client of the API
>> has no knowledge of. The client of the API calls:-
>
> And why not? They don't have to have knowledge of it. It could be
> optional with the default the same as it is now. Context is everything
> with this stuff. You can't decide what is best for all apps.
>
The job of the API is to define a public interface. More options means
more complexity, more bloat, longer methods, harder to read, more bugs,
more maintenance time.
>> Calendar.getById("birthday");
>>
>> And realize that the user's
>>> interaction has nothing to do with whether the element is in the
>>> document. You've got some wires crossed there.
>>>
>> The user's interation has nothing to do with whether the element is in
>> the document? Where are you getting this?
>
> You aren't thinking.
I asked you to explain yourself.
You misinterpreted that one line of code. It seems likely that you're
misunderstanding other things about that code.
Don't blame me for your misunderstanding. Don't call bullshit and say
that I'm not thinking.
What you repeated is correct, but there seems to
> be some design concepts that aren't registering with you. Asking where
> I am "getting this" isn't likely to bear fruit.
>
What I repeated was what you stated, but in question form. I can't make
sense of what you're saying here, or why.
>>>>>> It has no options to determine the HTML structure, and so there
>>>>>> is not testing multiple contexts and configurations. I like that.
>>>>> Yes, context specific solutions always trump GP. But we are talking
>>>>> about (though not necessarily advocating) a GP library.
>>>> Reusable wrappers are great for avoiding rewriting things. Ideally.
>>>> Sometimes what seems like a simple wrapper -- and this is especially
>>>> true for dom stuff -- is that it has to address too much complexity with
>>>> divergent browser object models.
>>> Except that isn't the case at all for attributes. There's exactly two
>>> models and one of those is never going to change again.
>> There is IE with attribute-as-properties and then there is the DOM
>> attributes.
>>
>> A DOM wrapper for attributes or properties in the general sense seems
>> like a good exercise for learning about browser quirks.
>
> So is writing a calendar widget, yet they both have practical
> applications as well.
>
A Calendar widget is not limited to learning about browser quirks.
>> The nodes for a widget can be build where needed for that widget. The
>> solution for that might use Array methods, set innerHTML, or assign
>> property values.
>>
>> The code you wrote might come in handy for an editor.
>
> Or anything else that creates elements.
Nope. Because sometimes, innerHTML might be a better option. Sometimes
Array.prototype.join or Array.prototype.push would be good options for
that. In some cases, not all cases, the code might have a browser quirk
to deal with. In other cases, another browser quirk might appear.
What sorts of quirks? Creating a table with cellPadding, creating a
named anchor.
It depends on the author(s),
> context, scope of the project, etc. Certainly an editor (which seems to
> be the centerpiece of every widget library) is the quintessential example.
If the attribute wrapper is needed for an Editor then limit it to that.
That's the stupid solution. Did you read this thread?
>
> That approach is specified to throw errors, and so if it is used, then
> it must be feature tested and the feature test would involve try-catch.
Which sucks.
>
>>> Plenty more examples related to NAME on MSDN.
>>>
>>> http://msdn.microsoft.com/en-us/library/ms536389%28VS.85%29.aspx
>>
>> Examples of what? That anchors don't show up in the anchors or links
>> collections if you name them prematurely? Same for forms, iframes, etc.
>> It's an old issue and easily dealt with in a wrapper.
>>
>>>>> element, anything with `class` or `for` attribute, or any attribute
>>>>> that
>>>>> IE sees as a property, or needs special case handling, such as
>>>>> cellPadding.
>>>> I take it you have been paying only cursory attention.
>>>>
>>>> http://www.cinsoft.net/attributes.html
>>>>
>>>> This stuff is not new.
>>>>
>>> You didn't like the feedback I gave you last time?
>>
>> About what? The unit tests (and don't start with semantics again?) No,
>> not really as it was sort of missing the point.
>>
>
> No, that too, though. I commented on the long section of statements you
> refer to as a "unit test" in your viewport function.
There you go again with semantics. I _hate_ that fucking shit. Yes, I
know I pointed out my "assertions" in that page as examples of simple
tests and you've been harping on the "those are not unit tests" bullshit
for weeks since. No wonder nothing ever gets settled in here. Where
are we on the new Viewport FAQ entry?
>
>>>>> Do you really want to write a wrapper to address that? I'll pass on
>>>>> that.
>>>> Are you paying _any_ attention at all? I wrote the wrapper years ago.
>>> So?
>>
>> So nothing. It's there. This stuff should not be an issue in 2010 for
>> a browser that came out in 1999. The whole idea is beyond belief.
>>
>
> I do not keep tabs on when you write things.
You could hardly miss most of it (and haven't IIRC).
>
>>> I can see the use of an attributes wrapper for an Editor. For that, it
>>> might make sense to limit the attribute reading to be used for the
>>> editor.
>>>
>>>>>>> If the problem is narrower there aren't as many edge cases. For
>>>>>>> example,
>>>>>>> a hidden method `createCalendarOnDemand` creates HTML for the
>>>>>>> calendar
>>>>>>> widget.
>>>>>> What calendar widget? And why does that method create HTML? Also,
>>>>>> aren't all methods on demand?
>>>>>>
>>>>> The widget in particular is beside the point: Creating HTML for a
>>>>> specific case can be simple, unlike trying to fulfill all cases. But
>>>>> since you asked, here is the calendar:
>>>>> http://github.com/GarrettS/ape-javascript-library/blob/master/src/widget/calendar/Calendar.js
>>>>>
>>>>>
>>>> But why HTML? I thought we were talking about creating/mutating DOM
>>>> nodes. Is that what you mean?
>>> The reason that that is mentioned
>>
>> Looks like your reply ran aground here. (?)
>>
>
> Creating nodes can work for specific tasks such as above, but for
> general purpose, it is unneeded.
What the hell does that mean?
>
>>> Regardless, I know you don't need such a
>>>> wrapper for such a widget. It doesn't really fall into the categories
>>>> that have been listed (endlessly it seems).
>>>>
>>> You listed two:-
>>> 1) CSS Query Selector
>>> 2) Editor
>>
>> Or parser or anything that needs to canonicalize the document. Use your
>> imagination.
>>
>
> Speculate on a need that does not exist? Never.
Whatever.
>
> Work the other way.
This isn't working (in any sense of the word).
>
> Create abstractions as they're needed. Organize the abstractions to
> allow for effective reuse.
Well, parsers, editors, queries, etc. have been around forever. It's
not some new need I have identified. It's an old need that was never
filled because nobody bothered to figure it out. It's beyond belief,
but there it is.
>
> Test the abstractions. When something doesn't work, the test can be
> added to the suite. When the abstration gets refactored, then the tests
> can reflect that.
You are rambling.
>
> Adding OPTION to a SELECT is very generic, but probably can work in
> almost any normal context.
>
> Creating a specific widget (UserPanel) is going to be more specific. In
> a specific case, for a higher level widget, the nodes/html for the
> widget can be generated in a self-contained function.
Whatever.
>
>>> The most complex, feature rich applications will not need a CSS Selector
>>> Query interface.
>>
>> Almost nobody does, but...
>>
>
> Nope.
Nope what? My point was that though nobody needs one, seemingly
everybody wants one.
>
>>> I can see the use for an Editor. For that, it might make sense to limit
>>> the parsing of editor's html to a narrower scope.
>>
>> Which is something you can build on top of the low-level functions. And
>> not just for an editor either. Are you familiar with things like the
>> Dijit (ecch) parser?
>
> Feel free to enlighten me.
Never mind. Look at it if you want to. It parses fucking documents.
Get the picture? Same as queries query documents. It's all based on
getting an accurate view of the document (something that all of these
stupid projects neglected).
>
> My experiences with Dojo based applications is that they tend to be slow
> to load. Well I've only worked on two applications that used Dojo.
Not a big enough sample, but "slow to load" was the first thing out of
my mouth when I was first tapped to assess it. I sped it up quite a bit
(to say the least), but, of course...
>
> Other applications that use dojo that I interviewed for, they complained
> about slow performance.
I'm hardly surprised.
>
> [...]
>
>>
>>> I'd through that thing out as soon as I read
>>
>>
>> Dammit. Your quoting is fucking up here again. No way this is my
>> fault. I used GG for years and never hard this problem.
>>
>
> ?
>
>>>> the name of that method. I don't want to have to remember what you
>>>> consider "on demand" to mean. ;)
>>>>
>>> Interesting. How were you planning on calling that method?
>>
>> I wasn't.
>>
>
> Why would you have to remember the name of that method?
I don't follow and don't really care at this point.
>
>>>>> | if(d.getElementById(calendar.calendarId) !== null) return;
>>>> Yes, so? You return early if the element is not in the document. I
>>>> hate it (for so many reasons). :(
>>>>
>>> You're completely wrong here.
>>
>> No I am not. You are barking up the wrong tree.
>>
>
> YOu wrote "You return early if the element is not in the document." That
> is wrong. Please do look at that one line of code.
>
>>> It is only one line of code.
>>
>> That tree.
>>
> It is not a tree.
>
>>> A code
>>> comment seemed like extraneous noise, but if that line is confusing,
>>> then does this seem any clearer:
>>
>> Of course not. It has to do with code design, not clarity. Returning
>> early like that is bullshit.
>
> Oh really? It is "bullshit" to return early? Who taught you that? Or
> better yet, why did you believe it?
>
> Restructure the design so that the caller
>> doesn't call in the first place in that circumstance. If you are
>> worried about public API calls, you don't want those to fail silently
>> either. ;)
>>
>
> What caller and what circumstance?
Calling the function wer are talking about with whatever the hell would
make it exit early (returning undefined apparently). What were we
talking about?
>
> The caller of that method calls it so that the calendar can be created.
> If the calendar is already created, then the method exits.
And that's _stupid_. Doesn't the caller know if it has called it yet or
not? It certainly should. ;)
>
>>> | // If the element is not null, exit.
>>> | if(d.getElementById(calendar.calendarId) !== null) return;
>>>
>>> ?
>>>
>>>>> The HTML for the calendar is called only after the user has started
>>>>> interacting with the INPUT.
>>>> That sounds more like "on demand" to me. Still, if you can't
>>>> explain it
>>>> without inducing confusing...
>>>>
>>> I didn't explain it. You sort of did, but got it wrong.
>>
>> Bullshit and no time for semantic arguments. Thanks anyway.
>>
>
> Apparently the code comment did *not* help. So it is down to an English
> problem. What meaning do you get from: "If the element is not null, exit."
I have no clue what you are talking about at this point.
>
>>>>> Even though it's beside the point, I'd like to get any feedback on
>>>>> that.
>>>> I absolutely can't stand the idea of a function that does something,
>>>> except when it doesn't. Break that up into two (one that checks if the
>>>> element is there and one that appends it).
>>> I don't find the null check to be confusing at all.
>>
>> Confusion is not the issue either.
>>
>
> Apparently it was.
Heh, apparently not. :)
>
>>> Creating it "on demand"
>>
>> Again, the quoting is off. The problem is in your set.
>>
>>>> (according to the last bit of the explanation) can be useful though.
>>>> You might want to make it an option.
>>> An option? No, absolutely not. That is something that client of the API
>>> has no knowledge of. The client of the API calls:-
>>
>> And why not? They don't have to have knowledge of it. It could be
>> optional with the default the same as it is now. Context is everything
>> with this stuff. You can't decide what is best for all apps.
>>
> The job of the API is to define a public interface. More options means
> more complexity, more bloat, longer methods, harder to read, more bugs,
> more maintenance time.
All a bunch of nothingness. There's just no meaning there at all.
>
>
>>> Calendar.getById("birthday");
>>>
>>> And realize that the user's
>>>> interaction has nothing to do with whether the element is in the
>>>> document. You've got some wires crossed there.
>>>>
>>> The user's interation has nothing to do with whether the element is in
>>> the document? Where are you getting this?
>>
>> You aren't thinking.
>
> I asked you to explain yourself.
>
> You misinterpreted that one line of code.
I did not misinterpret anything. What sort of idiot would think that an
early return statement could be misinterpreted? Or perhaps this is just
more baiting?
> It seems likely that you're
> misunderstanding other things about that code.
Not a chance. It seems more likely that you don't understand the
subtleties I am describing and that's not a new experience.
>
> Don't blame me for your misunderstanding. Don't call bullshit and say
> that I'm not thinking.
Sorry, I don't take orders.
>
> What you repeated is correct, but there seems to
>> be some design concepts that aren't registering with you. Asking where
>> I am "getting this" isn't likely to bear fruit.
>>
>
> What I repeated was what you stated, but in question form. I can't make
> sense of what you're saying here, or why.
It's mutual at this point. The thread is another lost cause.
>
>>>>>>> It has no options to determine the HTML structure, and so there
>>>>>>> is not testing multiple contexts and configurations. I like that.
>>>>>> Yes, context specific solutions always trump GP. But we are talking
>>>>>> about (though not necessarily advocating) a GP library.
>>>>> Reusable wrappers are great for avoiding rewriting things. Ideally.
>>>>> Sometimes what seems like a simple wrapper -- and this is especially
>>>>> true for dom stuff -- is that it has to address too much complexity
>>>>> with
>>>>> divergent browser object models.
>>>> Except that isn't the case at all for attributes. There's exactly two
>>>> models and one of those is never going to change again.
>>> There is IE with attribute-as-properties and then there is the DOM
>>> attributes.
>>>
>>> A DOM wrapper for attributes or properties in the general sense seems
>>> like a good exercise for learning about browser quirks.
>>
>> So is writing a calendar widget, yet they both have practical
>> applications as well.
>>
>
> A Calendar widget is not limited to learning about browser quirks.
Neither are wrappers for accurately reading and mutating documents. And
how did this become calendar vs. attributes? I truly hate these detours.
>
>>> The nodes for a widget can be build where needed for that widget. The
>>> solution for that might use Array methods, set innerHTML, or assign
>>> property values.
>>>
>>> The code you wrote might come in handy for an editor.
>>
>> Or anything else that creates elements.
>
> Nope. Because sometimes, innerHTML might be a better option.
Ugh. How does matter?
> Sometimes
> Array.prototype.join or Array.prototype.push would be good options for
> that.
Good options for what?
> In some cases, not all cases, the code might have a browser quirk
> to deal with. In other cases, another browser quirk might appear.
I don't know what you are talking about. The wrappers deal with the
browser quirks behind the scenes. That's part of their utility (as well
as educational for those laboring under misconceptions about properties
and attributes).
>
> What sorts of quirks? Creating a table with cellPadding, creating a
> named anchor.
There's no issue with creating a table with cellpadding. And the anchor
issue is in another layer (createAndAppend...)
>
> It depends on the author(s),
>> context, scope of the project, etc. Certainly an editor (which seems to
>> be the centerpiece of every widget library) is the quintessential
>> example.
>
>
> If the attribute wrapper is needed for an Editor then limit it to that.
What does that mean? An editor must deal with virtually every attribute
and element type. That's what makes it such an excellent (and
ubiquitous) example. :)
Keep your general purpose wrapper. Do whatever you like with it, but it
is a foolish endeavor.
>>>> Regardless, I know you don't need such a
>>>>> wrapper for such a widget. It doesn't really fall into the categories
>>>>> that have been listed (endlessly it seems).
>>>>>
>>>> You listed two:-
>>>> 1) CSS Query Selector
>>>> 2) Editor
>>> Or parser or anything that needs to canonicalize the document. Use your
>>> imagination.
>>>
>> Speculate on a need that does not exist? Never.
>
> Whatever.
>
No, not whatever: Speculative generality is a pointless waste of time.
SOrt of like trying to explain things to you.
>> Work the other way.
>
> This isn't working (in any sense of the word).
>
>> Create abstractions as they're needed. Organize the abstractions to
>> allow for effective reuse.
>
> Well, parsers, editors, queries, etc. have been around forever. It's
> not some new need I have identified.
You've not identified anything!
Your attr function does not serve any practical purpose.
It's an old need that was never
> filled because nobody bothered to figure it out. It's beyond belief,
> but there it is.
>
>> Test the abstractions. When something doesn't work, the test can be
>> added to the suite. When the abstration gets refactored, then the tests
>> can reflect that.
>
> You are rambling.
>
you can say that I am rambling, but does that say something about what I
wrote, or does it say something about your communication skills (reading
and asking questions).
>> Adding OPTION to a SELECT is very generic, but probably can work in
>> almost any normal context.
>>
>> Creating a specific widget (UserPanel) is going to be more specific. In
>> a specific case, for a higher level widget, the nodes/html for the
>> widget can be generated in a self-contained function.
>
> Whatever.
>
No, not whatever. The point is that the General purpose wrapper is never
going to be the ideal solution. It will be mired in complexity and will
never be as efficient as something that is designed for the task.
>>>> I can see the use for an Editor. For that, it might make sense to limit
>>>> the parsing of editor's html to a narrower scope.
>>> Which is something you can build on top of the low-level functions. And
>>> not just for an editor either. Are you familiar with things like the
>>> Dijit (ecch) parser?
>> Feel free to enlighten me.
>
> Never mind. Look at it if you want to. It parses fucking documents.
> Get the picture? Same as queries query documents. It's all based on
> getting an accurate view of the document (something that all of these
> stupid projects neglected).
>
Nothing that you have posted has parsed documents; not that I've seen.
>> [...]
>>
>>>> I'd through that thing out as soon as I read
>>>
>>> Dammit. Your quoting is fucking up here again. No way this is my
>>> fault. I used GG for years and never hard this problem.
>>>
>> ?
>>
>>>>> the name of that method. I don't want to have to remember what you
>>>>> consider "on demand" to mean. ;)
>>>>>
>>>> Interesting. How were you planning on calling that method?
>>> I wasn't.
>>>
>> Why would you have to remember the name of that method?
>
> I don't follow and don't really care at this point.
>
What a cop out. You cannot remember the reason for your comment
"through that out". So either the comment was made thoughtlessly, or it
wasn't.
I have maintained this whole time that you do not understand the code.
Indeed you got that one line wrong, insisted that you were right, even
after it was pointed out to you again that you were wrong. Insisting
that I was barking.
Why are you are wasting my time with this?
No, there is no state of "function has been called before". The state is
maintained in the HTML. If the element doesn't exist, it gets created.
>>>> | // If the element is not null, exit.
>>>> | if(d.getElementById(calendar.calendarId) !== null) return;
>>>>
>>>> ?
>>>>
>>>>>> The HTML for the calendar is called only after the user has started
>>>>>> interacting with the INPUT.
>>>>> That sounds more like "on demand" to me. Still, if you can't
>>>>> explain it
>>>>> without inducing confusing...
>>>>>
>>>> I didn't explain it. You sort of did, but got it wrong.
>>> Bullshit and no time for semantic arguments. Thanks anyway.
>>>
>> Apparently the code comment did *not* help. So it is down to an English
>> problem. What meaning do you get from: "If the element is not null, exit."
>
> I have no clue what you are talking about at this point.
>
You got confused about one line of code. You made a blatantly false
statement about the code:-
| Yes, so? You return early if the element is not in the document. I
| hate it (for so many reasons).
And this was regarding the line of code:-
| if(d.getElementById(calendar.calendarId) !== null) return;
You continued to argue that that was correct and true, and that I was
wrong about the understanding of that line of my code.
>>>>>> Even though it's beside the point, I'd like to get any feedback on
>>>>>> that.
>>>>> I absolutely can't stand the idea of a function that does something,
>>>>> except when it doesn't. Break that up into two (one that checks if the
>>>>> element is there and one that appends it).
>>>> I don't find the null check to be confusing at all.
>>> Confusion is not the issue either.
>>>
>> Apparently it was.
>
> Heh, apparently not. :)
>
You're still not reading the one line of code. You've gotten the code
wrong and got the comment misinterpreted, too.
>>>> Creating it "on demand"
>>> Again, the quoting is off. The problem is in your set.
>>>
>>>>> (according to the last bit of the explanation) can be useful though.
>>>>> You might want to make it an option.
>>>> An option? No, absolutely not. That is something that client of the API
>>>> has no knowledge of. The client of the API calls:-
>>> And why not? They don't have to have knowledge of it. It could be
>>> optional with the default the same as it is now. Context is everything
>>> with this stuff. You can't decide what is best for all apps.
>>>
>> The job of the API is to define a public interface. More options means
>> more complexity, more bloat, longer methods, harder to read, more bugs,
>> more maintenance time.
>
> All a bunch of nothingness. There's just no meaning there at all.
>
No, that is a false statement.
The meaning was not understood by you. That is a fact.
The reason for that fact probably comes down to your irrationality.
>>
>>>> Calendar.getById("birthday");
>>>>
>>>> And realize that the user's
>>>>> interaction has nothing to do with whether the element is in the
>>>>> document. You've got some wires crossed there.
>>>>>
>>>> The user's interation has nothing to do with whether the element is in
>>>> the document? Where are you getting this?
>>> You aren't thinking.
>> I asked you to explain yourself.
>>
>> You misinterpreted that one line of code.
>
> I did not misinterpret anything. What sort of idiot would think that an
> early return statement could be misinterpreted? Or perhaps this is just
> more baiting?
>
I can explain it to you, but I cannot understand it for you.
For the fourth time: "If the element is not null, exit."
>> It seems likely that you're
>> misunderstanding other things about that code.
>
> Not a chance. It seems more likely that you don't understand the
> subtleties I am describing and that's not a new experience.
>
No, not "not a chance." Most likely.
You failed to correctly read one line of code.
You made a statement providing what you believed to be a reason for
"through it away" but forgot what it was.
You made some other statements but did not explain what they meant.
Given that I know the code pretty well, don't you think that it might be
the case that when I say you read the code wrongly, that I am correct
and that you have made a mistake?
Do you see the futility in furthering this discussion?
>> Don't blame me for your misunderstanding. Don't call bullshit and say
>> that I'm not thinking.
>
> Sorry, I don't take orders.
>
It is irrational to continue on the way you are. You are incorrect in
your assessment of one line of code. You are being stubborn in not
admitting that you are wrong. I would stop doing that if I were you.
>> What you repeated is correct, but there seems to
>>> be some design concepts that aren't registering with you. Asking where
>>> I am "getting this" isn't likely to bear fruit.
>>>
>> What I repeated was what you stated, but in question form. I can't make
>> sense of what you're saying here, or why.
>
> It's mutual at this point. The thread is another lost cause.
>
This thread is as useful as your attr function.
>>>>>>>> It has no options to determine the HTML structure, and so there
>>>>>>>> is not testing multiple contexts and configurations. I like that.
>>>>>>> Yes, context specific solutions always trump GP. But we are talking
>>>>>>> about (though not necessarily advocating) a GP library.
>>>>>> Reusable wrappers are great for avoiding rewriting things. Ideally.
>>>>>> Sometimes what seems like a simple wrapper -- and this is especially
>>>>>> true for dom stuff -- is that it has to address too much complexity
>>>>>> with
>>>>>> divergent browser object models.
>>>>> Except that isn't the case at all for attributes. There's exactly two
>>>>> models and one of those is never going to change again.
>>>> There is IE with attribute-as-properties and then there is the DOM
>>>> attributes.
>>>>
>>>> A DOM wrapper for attributes or properties in the general sense seems
>>>> like a good exercise for learning about browser quirks.
>>> So is writing a calendar widget, yet they both have practical
>>> applications as well.
>>>
>> A Calendar widget is not limited to learning about browser quirks.
>
> Neither are wrappers for accurately reading and mutating documents. And
> how did this become calendar vs. attributes? I truly hate these detours.
>
calendar vs. attributes is your imagination.
The point is -- and I've been saying this all along -- generalized dom
accessor (attribute property) functions have too much complexity to bear
to be useful.
Although a generalized function for creating nodes with attributes may
be too complicated, a specialized function for creating a widget can be
useful.
>>>> The nodes for a widget can be build where needed for that widget. The
>>>> solution for that might use Array methods, set innerHTML, or assign
>>>> property values.
>>>>
>>>> The code you wrote might come in handy for an editor.
>>> Or anything else that creates elements.
>> Nope. Because sometimes, innerHTML might be a better option.
>
> Ugh. How does matter?
>
If the problem is to "createAndAppendElementWithAttributes", then for a
widget that has to perform such tasks, innerHTML might work better.
>> Sometimes
>> Array.prototype.join or Array.prototype.push would be good options for
>> that.
>
> Good options for what?
>
Creating elements. Create an element and set innerHTML ,then append that
element somewhere in the document.
> Thomas 'PointedEars' Lahn wrote:
>> Garrett Smith wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> David Mark wrote:
>>>>> [...]
>>>>> There is a similar issue with the name attribute/property in that it
>>>>> must be set after appending the element if it is to show up in the
>>>>> appropriate DOM collection (e.g. document.forms, document.images,
>>>>> window.frames). That is an issue best handled with a wrapper that
>>>>> creates _and_ appends an element. Call it
>>>>> createAndAppendElementWithAttributes perhaps?
>>>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>> No, thanks.
>>> Generalized element builders.
>>>
>>> There are too many edge cases support. There are problems with nodes
>>> that can't accept other nodes, special handling for certain attributes
>>> (cellPadding, name).
>>>
>>> If the problem is narrower there aren't as many edge cases. For
>>> example, a hidden method `createCalendarOnDemand` creates HTML for the
>>> calendar widget. It has no options to determine the HTML structure, and
>>> so there is not testing multiple contexts and configurations. I like0
>>> that.
>>
>> You have failed to post a coherent follow-up.
>
> I missed a comma right after "narrower".
ISTM you missed a lot more here.
> In the third sentence, could have used "That method" instead of "It", as
> in:-
>
> "That method has no options to..."
And that is only the start of it.
Still your posting does not even remotely relate to my reply, yet you are
quoting it.
PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300...@news.demon.co.uk> (2004)