Re: [whatwg] Sample DOMTokenString Implementation

2005-09-06 Thread Lachlan Hunt

Erik Arvidsson wrote:
You are really misusing new here. You never return an object of type 
DOMTokenString. Since all your methods are linear and return a new 
string you might as well implement them on the String prototype object.


Well, yes, and in fact, when implementing the final version so that 
Element.className.add(), etc. can be used, I'll probably just have to 
extend the string prototype anyway.  It would cetainly be more efficient 
than creating a new string and adding the methods each time, but I 
wasn't sure if all strings should implement the interface.



Lachlan Hunt wrote:

s = s.add("baz quux") // returns "foo bar foo baz quux"


Shouldn't this raise an exception?


It could raise a DOMException SYNTAX_ERR [1], but what's wrong with just 
accepting it?


[1] 
http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-17189187


--
Lachlan Hunt
http://lachy.id.au/



Re: [whatwg] Sample DOMTokenString Implementation

2005-09-06 Thread Erik Arvidsson
You can get has(token) to be constant, O(1), by using a hash here. add 
and remove will remain linear as long as a copy is required.


You are really misusing new here. You never return an object of type 
DOMTokenString. Since all your methods are linear and return a new 
string you might as well implement them on the String prototype object.


String.prototype.has = function (s) {
   // TODO: Needs to validate s
   return RegExp("(^|\\s+)" + s + "(\\s+|$)", "g").test(this);
};

String.prototype.add = function (s) {
   // TODO: Needs to validate s
   //   This should check that we don't have this token already
   return this + " " + s;
};

String.prototype.remove = function (s) {
   // TODO: Needs to validate s
   return this.replace(RegExp("(^|\\s+)" + s + "(\\s+|$)", "g"), "");
};

Now native strings in JS implement the DOMTokenString interface ;-)

If you want a mutable object then we cannot extend String (as you said).

Lachlan Hunt wrote:

s = s.add("foo"); // returns "foo bar foo"


This should not add another foo


s = s.add("baz quux") // returns "foo bar foo baz quux"


Shouldn't this raise an exception?


erik


[whatwg] Sample DOMTokenString Implementation

2005-09-06 Thread Lachlan Hunt

Hi,
  I implemented a sample DOMTokenString() interface tonight [1].

Since String() is immutable in JS, I couldn't implement it as suggested 
in the current draft.  So, instead, I've implemented it like this:


interface DOMTokenString : DOMString {
boolhas(in DOMString token);
DOMTokenString  add(in DOMString token);
DOMTokenString  remove(in DOMString token);
}

The constructor accepts a single string as a parameter

new DOMTokenString(string);

The string is split into tokens and stored in an private array within 
the object:

var tokens = string.split(/\s/);

That splits it on any whitespace characters.  The tokens are then 
rejoined into a string using a single space as the separator.  This is 
similar to the way class works in HTML (at least, in Gecko).


i.e. class="foo bar" is equivalent to class=" foo   bar ", and in Gecko, 
.className returns each separated by a single space.


e.g.
var s = new DOMTokenString(" foo   bar "); // returns "foo bar"

bool has();

  * This searches the array for the first index of the specified token
and returns true if found, false otherwise.
e.g.

s.has("bar"); // returns true;
s.has ("foo bar") // returns false;

DOMTokenString add();

  * This function returns a new DOMTokenString() created from the
concatenation of the the current string(), a separator and the new
token.
  * It does not matter if the same token is already present, the new
token is just appended to the end.
  * If the token parameter is, itself, a space separated list, it is
(because of the way the new string is constructed) equivalent to
adding each token individually.

e.g.
s = s.add("foo"); // returns "foo bar foo"
s = s.add("baz quux") // returns "foo bar foo baz quux"

DOMTokenString remove();

  * This filters the tokens array, removing all occurances of matching
tokens.  The new token array is then joined and returned.

e.g.
s = s.remove("foo") // returns "bar baz quux"
s = s.remove("bar baz") // returns "bar baz quux" (i.e. no match)
s = s.remove("baz"); // returns "bar quux"

[1] http://lachy.id.au/dev/script/examples/DOM/DOMTokenString.js

--
Lachlan Hunt
http://lachy.id.au/



Re: [whatwg] Re: getElementsByClassName

2005-09-06 Thread Lachlan Hunt

Kornel Lesinski wrote:

On Tue, 06 Sep 2005 00:54:56 +0100, Ian Hickson <[EMAIL PROTECTED]> wrote:

You can just do:

  if (x) find.push("class1");
  if (y) find.push("class2");
  document.getElementsByClassName.apply(document, find);

...which seems much better to me than using a string.


It's the first time I see apply method used. I couldn't find it in  
ECMA262-3 nor in WA1.0. Can you give me a hint where it's defined?

Why is that better than using string?


It's a method of Function().
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function:apply

--
Lachlan Hunt
http://lachy.id.au/



Re: [whatwg] Re: getElementsByClassName

2005-09-06 Thread Jim Ley
On 9/6/05, Kornel Lesinski <[EMAIL PROTECTED]> wrote:
> On Tue, 06 Sep 2005 00:54:56 +0100, Ian Hickson <[EMAIL PROTECTED]> wrote:
> >   document.getElementsByClassName.apply(document, find);
> >
> > ...which seems much better to me than using a string.
> 
> It's the first time I see apply method used. I couldn't find it in
> ECMA262-3 nor in WA1.0. Can you give me a hint where it's defined?

If you can find a definition (as opposed to a description) it'll be in
the Mozilla documentation, it was a JavaScript 1.3 extension to ES,
and even in their description, it doesn't say it applies to host
objects in the ES sense, it certainly doesn't work with host objects
in other implementations.

I certainly can't see what the problem with tokenising a string on
whitespace is, that very code is required throughout browsers, and is
the sort of "my first project" in a CS course...

Jim.


Re: [whatwg] Re: getElementsByClassName

2005-09-06 Thread Kornel Lesinski

On Tue, 06 Sep 2005 00:54:56 +0100, Ian Hickson <[EMAIL PROTECTED]> wrote:


> I fear that if we use a string that must be parsed, we will encourage
> buggy implementations.

Not at all. Actually this should improve implementations, because same
parsing algorithm is used for both input string and class attribute.


Unfortunately in practice the two parts of that code are likely to be
completely unrelated parts of the codebase, so that reuse is unlikely.


Even if it isn't reused, such function is not a rocket science. Can't you  
trust implementors to trim and split string properly?




For example I may want first to find set of classes I'd like to match
against. With solution I propose it's easy and intuitive to anyone who
used .className:

if (x) find += " class1";
if (y) find += " class2";
getElementsByClassName(find);

but with varargs function it's really cumbersome:
if (x) find.push("class1");
if (y) find.push("class2");
switch(find.length)
{
 case 1: getElementsByClassName(find[0]); break;
 case 2: getElementsByClassName(find[0],find[1]); break;
 ...
}


You can just do:

  if (x) find.push("class1");
  if (y) find.push("class2");
  document.getElementsByClassName.apply(document, find);

...which seems much better to me than using a string.


It's the first time I see apply method used. I couldn't find it in  
ECMA262-3 nor in WA1.0. Can you give me a hint where it's defined?

Why is that better than using string?

--
regards, Kornel Lesinski