Various DOM-related wrappers (Code Worth Recommending Project)

P

Peter Michaux

[snip]
I may have been wrong saying that
ns[ns.length] = el;
is faster than
ns.push(el)

It seemed to me that push would be faster. I haven't had time to test
it though. As I use a wrapper for push, I have typically used the
former method, which is obviously faster than calling a wrapper. But,
for example, the XPath code doesn't need to worry about
Array.prototype.push, so it would be a okay to use it without the
wrapper.

The most popular browser, still by a long shot, is IE which doesn't
have XPath. That means the non-XPath version still needs to be fast.
It will be impossible to prove that there isn't one. I can only say
that I can't find a reference to one.


If a bug can be confirmed, I am sure I can write a feature test for
it. There isn't really a need to compare them for speed as XPath is
going to be faster than looping in virtually every case.

In many cases, download time of more code will far outweigh any speed
advantage of the XPath branch. I always try to keep in mind that many
people are still using 56K modems.
 
P

Peter Michaux

[snip]


If you find out that there is no problem with xpath and safari or that
there is a feature test, perhaps we can compare the two for speed.

I just spotted a mistake in the queryXPath function. Remove
"global." Also, for this version, the queryString variable is
unneeded (can just be an expression passed to evaluate.)

It also looks like there could be some additional consolidation
between the two branches if size is an issue

It is always an issue!

[snip]
 
P

Peter Michaux

[snip]
how big this code is I think speed profiles would be good if this is
to be recommended over the non-xpath version. I think that there won't
be too much difference for simple selectors.

It is an order or magnitude faster for all cases, but won't have a big
impact unless the fallback branch loops through lots of results (e.g.
finding className matches for any tagName.) I definitely think this
should be an alternate version. Especially if you think we will want
to provide a wrapper for gEBCS that does more than just tagNames and
classNames.

I do think the XPATH version should be included. I don't think we
should make gEBCS handle more complex selectors for now.

[snip]
 
P

Peter Michaux

[snip]


What I would like to know is why in Prototype.js they turn off using
xpath for any browser with "AppleWebKit" in navigator.userAgent. Do
early versions of Safari have a bug in the xpath implementation. If
there is a bug, a feature test would be needed.

I found it. It is as I suspected. They found a specific selector
syntax that failed in Safari 3 and instead of feature testing for that
issue, they disabled XPath altogether (based on the userAgent
string.) The post did say that they plan to implement proper feature
testing for this in the next release.

It is an emergency situation that needs fixing. If they don't have a
feature test for it now then they have to disable the whole thing in
Safari otherwise the library is broken. That makes some sense to me.

Why they don't just scrap the whole project and start over is a mystery.

They would need to abandon their fundamental concept which is
augmenting built in prototypes.
 
V

VK

Even the documentation doesn't address the IE id/name problem.

id/name problem is not the preoccupation of a library developer: it is
the preoccupation of developer making the final script running on a
particular page. If she makes a broken page w/o any testing then it is
he free choice but not your headache.
A tangential thinker, eh?

A very soft definition, appreciated. :) Normally if assume the
possibility do not care of say IE4 or IE5 it is diagnosed as
"clueless !@#$% programmer". I just looked at the direction of the
discussion and I saw - maybe mistakenly - that it goes once again
towards the "programming onanism". So for some very simple task all
possible _theoretical_ possibilities to fail being collected from all
imaginable sources: W3C proposals, ancient browsers, personal fears
etc. and then all these theoretical problems overcame with very
practical processor time.

function $(id) {
return document.getElementById(id);
}

Again: what exactly browser being in use this year will fail to
execute properly this function?
 
V

VK

The most popular browser, still by a long shot, is IE which doesn't
have XPath.

You may want to update your data: IE supports XPath for the last 8
years at least. The only possible issue may be with MSXML3 where the
default selection language XSLPatterns and not XPath. However low
chances are to get IE4/IE5 on Windows 2000/ME, you may set the
language explicitly in your script before XPath usage:
xmlDoc.setProperty('SelectionLanguage', 'XPath');
 
D

David Mark

[snip]
I may have been wrong saying that
ns[ns.length] = el;
is faster than
ns.push(el)
It seemed to me that push would be faster. I haven't had time to test
it though. As I use a wrapper for push, I have typically used the
former method, which is obviously faster than calling a wrapper. But,
for example, the XPath code doesn't need to worry about
Array.prototype.push, so it would be a okay to use it without the
wrapper.

The most popular browser, still by a long shot, is IE which doesn't
have XPath. That means the non-XPath version still needs to be fast.
It will be impossible to prove that there isn't one. I can only say
that I can't find a reference to one.
If a bug can be confirmed, I am sure I can write a feature test for
it. There isn't really a need to compare them for speed as XPath is
going to be faster than looping in virtually every case.

In many cases, download time of more code will far outweigh any speed
advantage of the XPath branch. I always try to keep in mind that many
people are still using 56K modems.

But that's one download (assuming room in their cache) vs. however
many times the site's code queries the DOM.
 
D

David Mark

[snip]
how big this code is I think speed profiles would be good if this is
to be recommended over the non-xpath version. I think that there won't
be too much difference for simple selectors.
It is an order or magnitude faster for all cases, but won't have a big
impact unless the fallback branch loops through lots of results (e.g.
finding className matches for any tagName.) I definitely think this
should be an alternate version. Especially if you think we will want
to provide a wrapper for gEBCS that does more than just tagNames and
classNames.

I do think the XPATH version should be included. I don't think we
should make gEBCS handle more complex selectors for now.

Oops. Too late (at least here.) I compared the XPath and CSS2 specs
and decided it wouldn't be too difficult to add logic to each branch
to implement the various other selectors. The suggestion of pre-
compiling code to speed up the slower branch intrigued me enough to
try it. I am currently testing the updated parse logic without the
pre-compile trick. So far so good, but I am sure it will be useless
for "deep" queries without that optimization.
 
P

Peter Michaux

[snip]

And revisiting the feature test argument from a few posts back, I
really thing that isFeaturedMethod should be used,

Why not just "isMethod"? It is always testing a function property of
an object which is called a method. This isFeaturedMethod gets
plastered all over the place and if "isMethod" is sufficient then I
always like shorter.
instead of things
like:

if (document.getElementById)

I don't know of any browser that returns a truthy, but non-callable
value for this host method, but when you consider that every host
method should be tested in uniform fashion, you can imagine that at
least one of them might do so in some past agent. And if you exclude
that possibility, there is still the ActiveX issue to deal with.
Those host methods throw a script error when tested this way. All it
would take for the above example to break in IE8 would be for MS to
decide to implement some or all document nodes as ActiveX objects. If
that sounds far-fetched, realize that they already implement some
element nodes as ActiveX objects (e.g. anchors that link to news
resources.)

What does an anchor to a news resource look like in HTML?
I account for that possibility in my getAttribute
wrapper. In other words, this example may look perfectly benign, but
one line can currently throw a script error in IE and the other may in
the future.

var a = document.getElementById('myanchor');

How would the above line throw an error?
if (a.href) { ... }

I assume this is the same error that would occur in the first "if" of
your post above if document.getElementById was an ActiveX object.

I would prefer:

var a, doc = this.document;
if (doc && isFeaturedMethod(doc, 'getElementById') {
a = doc.getElementById('myanchor');
if (getAttribute(a, 'href')) { ... }

}

I sure hope this kind of thing doesn't need to be used frequently in
the repository. It is very bulky.

Or shortened to assume the global document property:

var a;
if (isFeaturedMethod(document, 'getElementById') {
a = document.getElementById('myanchor');
if (getAttribute(a, 'href')) { ... }

}

Granted, you wouldn't have to use a getAttribute wrapper, you could
use any function that takes the 'unknown' type into account.
I don't see this as paranoia as the problem case exists today (in IE7)
and in fact caused a script error on a group member's site a few
months back.

Here is the updated function. Looks like a couple of lines still
wrapped. Sorry. I may start linking to snippets as I really dislike
dealing with these ng issues.

The code should be posted to the group so the discussions stored in
the archives are complete. If the code is not posted to the group then
it makes it difficult to quote it and insert comments, as I have done
below.

var queryXPath, resolve;

if (isFeaturedMethod(doc, 'evaluate')) {
resolve = function() { return 'http://www.w3.org/1999/xhtml';};
queryXPath = function(a, tn, cn) {
var l, r, docNode = (a.nodeType == 9)?
a:(a.ownerDocument || doc);

I think '||doc' should be removed and thought you agreed in another
post. This will require a feature test on ownerDocument where you test
for document.evaluate.

Ihe following returns false in Firefox

document.documentElement.ownerDocument == document.documentElement

var q = [];
r = docNode.evaluate(['.//',
((xmlParseMode(docNode))?'html:':''),
tn,
((cn)?"[contains(concat(' ', @class, ' '),
' " + cn + " ')]":'')].join(''),

Is this join going to remain for some reason?

a,
(xmlParseMode(docNode))?resolve:null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null);
l = r.snapshotLength;

I like single character variable names in JavaScript because that
means an aggressive minifier doesn't need to be used. The most
controversial are 'l' and 'O'. My font shows them fine but it is just
as easy to use another character to avoid discussion. Richard Cornford
already wrote about this in a thread when I used 'l'. I think 'i' is
the best choice here. I imagine that even men like Newton probably
used 'i' for sequence and series work. All the textbooks I ever used
in Math had 'i'.
while (l--) { q[l] = r[l]; }
return q;
};
}

var getEBCN;
var getEBCS = (function() {
var m, // regexp matches and temp var in loop
tn, // tagName in s
id, // id in s
cn, // className in s
els, // candidate elements for return
ns, // elements to return
i, // loop index
el; // temp element variable
var get = (function() {
if (typeof queryXPath != 'undefined' &&
typeof getEBI != 'undefined') {
return function(d, id, tn, cn) {
if (id) {
ns = [];
if (el = getEBI(id)) {
if ((tn == '*' || el.tagName.toLowerCase() == tn) &&
(!cn || ((m = el.className) &&
(' '+m+' ').indexOf(' '+cn+' ') > -1))) {
ns = [el];
}
}
return ns;
}
return queryXPath(d, tn, cn);
};
}
if (typeof getEBI != 'undefined' &&
typeof getEBTN != 'undefined') {

return function(d, id, tn, cn) {
// Need this because getEBI only takes document object
// as optional second argument but getEBCS takes any
// element or a document as second argument.
els = (id && (d.nodeType == 9 || (!d.nodeType && !
d.tagName))) ?

How does the above fallback work and in which browser?

((el=getEBI(id, d)) ? [el] : [])
:
getEBTN(tn, d);
ns = [];
i = els.length;
while (i--) {
el = els;
// Could call an external hasClassName function but in
line
// it here for efficiency. There are no cross browser
issue
// with checking className.
if ((!cn ||
((m = el.className) &&
(' '+m+' ').indexOf(' '+cn+' ')>-1)) &&
// If tn != '*' then el necessarily has tagname
property.
(tn == '*' || el.tagName.toLowerCase() == tn) &&
(!id || el.id == id)) {
ns[ns.length] = el;
}
}
return ns.reverse();
};
}


Do you think it would be better to use my CSS-->JavaScript compiler as
the fallback? IE is the most common browser so this fallback will be
taken for many years to come.
})();

if (get) {
return function(s, d) {
m = s.match(/^([^#\.]+)/);
tn = m ? m[1] : '*';

m = s.match(/#([^\.]+)/);
id = m ? m[1] : null;

m = s.match(/\.([^#]+)/);
cn = m ? m[1] : null;

return get(d || doc, id, tn, cn);
};
}
})();

if (getEBCS) {
getEBCN = function(s, d) {
return getEBCS('.' + s, d);
};
}
 
D

David Mark

[snip]
What I would like to know is why in Prototype.js they turn off using
xpath for any browser with "AppleWebKit" in navigator.userAgent. Do
early versions of Safari have a bug in the xpath implementation. If
there is a bug, a feature test would be needed.
I found it. It is as I suspected. They found a specific selector
syntax that failed in Safari 3 and instead of feature testing for that
issue, they disabled XPath altogether (based on the userAgent
string.) The post did say that they plan to implement proper feature
testing for this in the next release.

It is an emergency situation that needs fixing. If they don't have a
feature test for it now then they have to disable the whole thing in
Safari otherwise the library is broken. That makes some sense to me.

It seems like the feature test would be dictated by whatever unit
test(s) failed.
They would need to abandon their fundamental concept which is
augmenting built in prototypes.

Among other things.
 
P

Peter Michaux

how big this code is I think speed profiles would be good if this is
to be recommended over the non-xpath version. I think that there won't
be too much difference for simple selectors.
It is an order or magnitude faster for all cases, but won't have a big
impact unless the fallback branch loops through lots of results (e.g.
finding className matches for any tagName.) I definitely think this
should be an alternate version. Especially if you think we will want
to provide a wrapper for gEBCS that does more than just tagNames and
classNames.
I do think the XPATH version should be included. I don't think we
should make gEBCS handle more complex selectors for now.

Oops. Too late (at least here.) I compared the XPath and CSS2 specs
and decided it wouldn't be too difficult to add logic to each branch
to implement the various other selectors. The suggestion of pre-
compiling code to speed up the slower branch intrigued me enough to
try it. I am currently testing the updated parse logic without the
pre-compile trick. So far so good, but I am sure it will be useless
for "deep" queries without that optimization.

If you want to see something I did that is somewhat similar

<URL: http://peter.michaux.ca/examples/css-selector-match/match.js>

I threw that one together quickly from other code and that one is
buggy when multiple, comma separated selectors are used, I believe.

I think it is best to save these complex selectors for another time. I
know I won't be using them and a code review and serious testing
doesn't interest me right now.
 
D

David Mark

id/name problem is not the preoccupation of a library developer: it is
the preoccupation of developer making the final script running on a
particular page. If she makes a broken page w/o any testing then it is
he free choice but not your headache.

You don't seem to understand that the developer may not realize they
screwed up if the gEBI wrapper is allowed to return elements without
the proper ID.
A very soft definition, appreciated. :) Normally if assume the
possibility do not care of say IE4 or IE5 it is diagnosed as
"clueless !@#$% programmer". I just looked at the direction of the
discussion and I saw - maybe mistakenly - that it goes once again
towards the "programming onanism". So for some very simple task all

I don't know if you are mistaken as I don't have time to look that up.
possible _theoretical_ possibilities to fail being collected from all
imaginable sources: W3C proposals, ancient browsers, personal fears
etc. and then all these theoretical problems overcame with very
practical processor time.

function $(id) {
return document.getElementById(id);

}

That is nonsense and we have long since moved on from gEBI. Needless
to say, the final solution did not look like that.
Again: what exactly browser being in use this year will fail to
execute properly this function?

Who knows what browsers (or other agents) are in use this year? One
thing is for sure, if you blindly declare a function that wraps a host
method which may not be supported, calling applications will have
unpredictable behavior.
 
P

Peter Michaux

[snip]
If the function is to be optimized a lot more needs to be done than
that. The CSS selector string should be compiled into a JavaScript
string which represents a function and then that function string is
evaluated. This function can be cached to be used later. This sort of
optimization is really important if selectors with several simple
selectors (e.g. div div div) because those tasks are so much more
laborious. For simple selectors it is not so important.

For example

if (typeof getEBI != 'undefined' &&
typeof getEBTN != 'undefined') {

var getEBCS;

(function() {

//http://elfz.laacz.lv/beautify/
var compile = function(s) {
var m, // regexp matches
tn, // tagName in s
id, // id in s
cn, // className in s
f; // the function body

m = s.match(/^([^#\.]+)/);
tn = m ? m[1] : null;

m = s.match(/#([^\.]+)/);
id = m ? m[1] : null;

m = s.match(/\.([^#]+)/);
cn = m ? m[1] : null;

f = 'var i,els,el,m,ns=[];';
if (id) {
f += 'els=(!d || d.documentElement) ?' +
'((el=getEBI("'+id+'", d)) ? [el] : []) :' +
'getEBTN("'+(tn||'*')+'", d);'
}
else {
f += 'els = getEBTN("'+(tn||'*')+'", d);';
}

f += 'i = els.length;' +
'while (i--) {' +
'el = els;' +
'if (';
if (id) {
f += 'el.id=="'+id+'"';
}
if ((cn||tn) && id) {
f += '&&';
}
if (tn) {
f += 'el.tagName.toLowerCase() == "' + tn + '"';
}
if (cn && tn) {
f += '&&';
}
if (cn) {
f += '((m = el.className) &&' +
'(" "+m+" ").indexOf(" '+cn+' ")>-1)';
}
f += '){' +
'ns[ns.length] = el;' +
'}' +
'}';

f += 'return ns.reverse();';

return new Function('d', f);
}

var cache = {};

getEBCS = function(s, d) {
if (!cache) {


If for some reason a user sends an s that is "toString" then this will
cause a problem. I thought it would be better to use hasOwnProperty.
There is at least one bug with hasOwnProperty in Opera when s is a
number.

<URL: http://groups.google.com/group/comp.lang.javascript/msg/7ad2adb486fc3f20>

This bug could be worked around by prefixing the selector with a fixed
string.

Are there any other bugs with hasOwnProperty?

cache = compile(s);
}
return cache(d);
}

})();

}
 
V

VK

You don't seem to understand that the developer may not realize they
screwed up if the gEBI wrapper is allowed to return elements without
the proper ID.

The developer is screwed if the docs say "$(String id) returns DOM
element reference with such ID or null if doesn't exist" - and the
developer is using it to get over it an element by NAME or get
something useful out of say $(undefined); Such developer is screwed by
default and sooner realized it so he will start to read the docs - so
better for him. By compensating rude programming errors up to the last
possibility you do not help anyone: the program will still eventually
fail, but on higher execution level where it will be times more
difficult to find the reason.
Who knows what browsers (or other agents) are in use this year?

If you don't know that then why are you trying to program in
JavaScript anything at all above simple form control helpers?
Theoretically possible someone is still using Windows 3.0 with
Netscape 2.0b (the first one with JavaScript 1.0)

Again: let's stop that fallacy pretending to program "for the
humanity's past, present and future generations". For _a hell of a
good_ start let's try to cover at least A grade UAs from Yahoo! chart
http://developer.yahoo.com/yui/articles/gbs/

If your program ever gets any popularity, you'll get a bunch of bug
reports and you'll fix them then.
One thing is for sure, if you blindly declare a function that wraps a host
method which may not be supported, calling applications will have
unpredictable behavior.

If UA doesn't have document.getElementById support then it's NN4 or
older or IE4 or older or something else from the last century. If you
really want to make it work on IE4 then I want you to make it work on
NN4 as well as of the same period browser. What the problem? Not
possible? It is possible but extremely ugly and labor intensive. Much
much more labor intensive then ...else if (document.all)... and "look
ma' now how do I care of every possible user!".
 
D

David Mark

[snip]

And revisiting the feature test argument from a few posts back, I
really thing that isFeaturedMethod should be used,

Why not just "isMethod"? It is always testing a function property of
an object which is called a method. This isFeaturedMethod gets
plastered all over the place and if "isMethod" is sufficient then I
always like shorter.

Fine by me. It is only for appropriate for testing methods of host
objects (which are the only ones that IE considers of type 'object.')
I called it "isFeaturedMethod" to make it clear that it was for
feature testing the host environment.
What does an anchor to a news resource look like in HTML?

From Dr. John Stockton's page:

<a href="
You don't see these much anymore. Why IE7 implements them as ActiveX
objects is anybody's guess.
How would the above line throw an error?

If gEBI was not a featured method of the document object or if
document were implemented as an ActiveX object.
I assume this is the same error that would occur in the first "if" of
your post above if document.getElementById was an ActiveX object.

If document was an ActiveX object. The error occurs when [[Get]] is
called on methods of ActiveX objects, not on the objects themselves.
I sure hope this kind of thing doesn't need to be used frequently in
the repository. It is very bulky.

Nothing like that would be in the repository. It is just an example.
The check for gEBI is done once when the wrapper is created. I check
document once at the top of my base module. If isn't present, then
none of the document-related functions are created. After that, any
code that requires it can just do this:

if (typeof getEBI != 'undefined') { ... }
The code should be posted to the group so the discussions stored in
the archives are complete. If the code is not posted to the group then
it makes it difficult to quote it and insert comments, as I have done
below.

Makes sense.
I think '||doc' should be removed and thought you agreed in another
post. This will require a feature test on ownerDocument where you test
for document.evaluate.
Right.


Ihe following returns false in Firefox

document.documentElement.ownerDocument == document.documentElement

As it should. However, this returns true:

document.documentElement.ownerDocument == document
var q = [];
r = docNode.evaluate(['.//',
((xmlParseMode(docNode))?'html:':''),
tn,
((cn)?"[contains(concat(' ', @class, ' '),
' " + cn + " ')]":'')].join(''),

Is this join going to remain for some reason?

Not necessarily.
I like single character variable names in JavaScript because that
means an aggressive minifier doesn't need to be used. The most
controversial are 'l' and 'O'. My font shows them fine but it is just
as easy to use another character to avoid discussion. Richard Cornford
already wrote about this in a thread when I used 'l'. I think 'i' is
the best choice here. I imagine that even men like Newton probably
used 'i' for sequence and series work. All the textbooks I ever used
in Math had 'i'.

I have been in the habit of using l for length, but in this case it
doesn't make sense as it is then used as an iterator.
while (l--) { q[l] = r[l]; }
return q;
};
}
var getEBCN;
var getEBCS = (function() {
var m, // regexp matches and temp var in loop
tn, // tagName in s
id, // id in s
cn, // className in s
els, // candidate elements for return
ns, // elements to return
i, // loop index
el; // temp element variable
var get = (function() {
if (typeof queryXPath != 'undefined' &&
typeof getEBI != 'undefined') {
return function(d, id, tn, cn) {
if (id) {
ns = [];
if (el = getEBI(id)) {
if ((tn == '*' || el.tagName.toLowerCase() == tn) &&
(!cn || ((m = el.className) &&
(' '+m+' ').indexOf(' '+cn+' ') > -1))) {
ns = [el];
}
}
return ns;
}
return queryXPath(d, tn, cn);
};
}
if (typeof getEBI != 'undefined' &&
typeof getEBTN != 'undefined') {
return function(d, id, tn, cn) {
// Need this because getEBI only takes document object
// as optional second argument but getEBCS takes any
// element or a document as second argument.
els = (id && (d.nodeType == 9 || (!d.nodeType && !
d.tagName))) ?

How does the above fallback work and in which browser?

Any browser that does not support nodeType should return true for
document nodes as they have no tagName property.
((el=getEBI(id, d)) ? [el] : [])
:
getEBTN(tn, d);
ns = [];
i = els.length;
while (i--) {
el = els;
// Could call an external hasClassName function but in
line
// it here for efficiency. There are no cross browser
issue
// with checking className.
if ((!cn ||
((m = el.className) &&
(' '+m+' ').indexOf(' '+cn+' ')>-1)) &&
// If tn != '*' then el necessarily has tagname
property.
(tn == '*' || el.tagName.toLowerCase() == tn) &&
(!id || el.id == id)) {
ns[ns.length] = el;
}
}
return ns.reverse();
};
}


Do you think it would be better to use my CSS-->JavaScript compiler as
the fallback? IE is the most common browser so this fallback will be
taken for many years to come.


Yes. I think that would be a good idea.
if (get) {
return function(s, d) {
m = s.match(/^([^#\.]+)/);
tn = m ? m[1] : '*';
m = s.match(/#([^\.]+)/);
id = m ? m[1] : null;
m = s.match(/\.([^#]+)/);
cn = m ? m[1] : null;
return get(d || doc, id, tn, cn);
};
}
})();
if (getEBCS) {
getEBCN = function(s, d) {
return getEBCS('.' + s, d);
};
}
 
P

Peter Michaux

[snip]

How would the above line throw an error?

If gEBI was not a featured method of the document object or if
document were implemented as an ActiveX object.

I was assuming document.getElementById is available.

If document is an ActiveX object why would it error to call it's
getElementById method?

I assume this is the same error that would occur in the first "if" of
your post above if document.getElementById was an ActiveX object.

If document was an ActiveX object. The error occurs when [[Get]] is
called on methods of ActiveX objects, not on the objects themselves.

I'm lost.

If document is present and an ActiveX and has a getElementById
property, what you are saying is the following line will error

if (document.getElementById)


If document is present and an ActiveX and has a getElementById
property, what will happen in the next line? I hope not an error
because then there would be no point in having methods on an ActiveX
object

document.getElementById('foo')


[snip]
Any browser that does not support nodeType should return true for
document nodes as they have no tagName property.

What I'm worried about is if the browser does not support nodeType and
some d that shouldn't have a tagName is used. Is this just a
documentation issue that says the second parameter to getEBCS(s,d)
must be a document or an element? That is fine with me.
 
D

David Mark

[snip]
how big this code is I think speed profiles would be good if this is
to be recommended over the non-xpath version. I think that there won't
be too much difference for simple selectors.
It is an order or magnitude faster for all cases, but won't have a big
impact unless the fallback branch loops through lots of results (e.g.
finding className matches for any tagName.) I definitely think this
should be an alternate version. Especially if you think we will want
to provide a wrapper for gEBCS that does more than just tagNames and
classNames.
I do think the XPATH version should be included. I don't think we
should make gEBCS handle more complex selectors for now.
Oops. Too late (at least here.) I compared the XPath and CSS2 specs
and decided it wouldn't be too difficult to add logic to each branch
to implement the various other selectors. The suggestion of pre-
compiling code to speed up the slower branch intrigued me enough to
try it. I am currently testing the updated parse logic without the
pre-compile trick. So far so good, but I am sure it will be useless
for "deep" queries without that optimization.

If you want to see something I did that is somewhat similar

<URL:http://peter.michaux.ca/examples/css-selector-match/match.js>

I threw that one together quickly from other code and that one is
buggy when multiple, comma separated selectors are used, I believe.

I wasn't going to bother with commas for the moment. Nor am I
considering spaces inside of quoted attribute values. And speaking of
things I didn't consider, I see you are doing something with
parentheses. I don't think I have ever seen CSS selectors grouped
with parentheses.

All I am doing is adding a small amount of logic to each branch to
enable things like:

div.test div a
*>div a[href="test"]
div+div a span.test

I think I have come up with a clever and efficient way of doing this.
Even without the pre-compile optimizations you suggested, it seems to
be doing pretty well in terms of speed (at least in IE) and didn't
bloat either branch too badly.
I think it is best to save these complex selectors for another time. I
know I won't be using them and a code review and serious testing
doesn't interest me right now.

I agree. I certainly won't be using them either. For now, we just
need to optimize the simple version with your Function constructor
technique. I will be interested to see how much it improves the
performance of both versions.
 
D

David Mark

On Dec 11, 4:28 am, David Mark <[email protected]> wrote:
[snip]
I account for that possibility in my getAttribute
wrapper. In other words, this example may look perfectly benign, but
one line can currently throw a script error in IE and the other may in
the future.
var a = document.getElementById('myanchor');
How would the above line throw an error?
If gEBI was not a featured method of the document object or if
document were implemented as an ActiveX object.

I was assuming document.getElementById is available.

If document is an ActiveX object why would it error to call it's
getElementById method?
If document was an ActiveX object. The error occurs when [[Get]] is
called on methods of ActiveX objects, not on the objects themselves.

I'm lost.

If document is present and an ActiveX and has a getElementById
property, what you are saying is the following line will error

if (document.getElementById)
Yep.


If document is present and an ActiveX and has a getElementById
property, what will happen in the next line? I hope not an error
because then there would be no point in having methods on an ActiveX
object

document.getElementById('foo')

No problem there. That invokes the internal [[Call]] method, not
[[Get]]. Try this out with window.external.addFavorite.
[snip]
Any browser that does not support nodeType should return true for
document nodes as they have no tagName property.

What I'm worried about is if the browser does not support nodeType and
some d that shouldn't have a tagName is used. Is this just a
documentation issue that says the second parameter to getEBCS(s,d)
must be a document or an element? That is fine with me.

Yes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,992
Messages
2,570,220
Members
46,805
Latest member
ClydeHeld1

Latest Threads

Top