![]() | |
#11
| |||
| |||
|
|
On Dec 8, 5:37 am, David Mark <dmark.cins... (AT) gmail (DOT) com> wrote: After a some reworking to support the "*" parameter properly in IE5 (my previous version failed to filter non-element nodes), here are my proposals for various low-level DOM-related functions and the feature tests that enable them to be created without issue. I welcome any comments. [nitpick mode on] Please use a 70 character line length to avoid wrapping. Usenet wraps at 72 so a 70 character line allows one reply without wrapping. A 2 space "tab stop" conserves line width. Neither of these are my personal preferences but are appropriate to code that will be posted to Usenet. URL:http://cljs.michaux.ca/trac/wiki/DesignGuidelines [nitpick mode off] [code quoted below reformatted and reduced to just that related to the gEBI wrapper] var element, doc, i; var reFeaturedMethod = new RegExp('^function|object$', 'i'); var global = this; // Test for host object properties that are typically callable // (e.g. all, getElementById), // which may be of type function, object (IE and possibly others) // or unknown (IE ActiveX methods) var isFeaturedMethod = function(o, m) { var t = typeof(o[m]); return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown'); }; if (isRealObjectProperty(this, 'document')) { doc = this.document; // gEBI wrapper element = (function() { function idCheck(el, id) { return (el && el.id == id) ? el : null; } if (isFeaturedMethod(doc, 'getElementById')) { return function(id, docNode) { return idCheck((docNode || doc).getElementById(id), id); }; } if (isFeaturedMethod(doc, 'all')) { return function(id, docNode) { return idCheck((docNode || doc).all[id], id); }; } })(); } Based on the repository design guidelines, the above could be substantially reduced to just if (document.getElementById) { var getEBI = function(id, d) { var el = (d||document).getElementById(id); if (el.id == id) { return el; } }; } Notes: There is no need to check for the existence of "document" as no browser, NN4+ and IE4+, missing "document". There is no need to check that document.getElementById is a callable since there has never been a known implementation where document.getElementById that is not callable. Since this is a getter the name must start with "get". I'm tempted to call it "getElementById" since that won't clash with document.getElementById. "getEBI" is shorter. It is clear that supporting IE4 requires quite a bit more code which must be downloaded by everyone. I don't mean this to start a big discussion about supporting IE4. It is just quite obvious in this example. |
#12
| |||
| |||
|
|
On Dec 9, 4:32 am, Peter Michaux <petermich... (AT) gmail (DOT) com> wrote: Based on the repository design guidelines, the above could be substantially reduced to just if (document.getElementById) { var getEBI = function(id, d) { var el = (d||document).getElementById(id); if (el.id == id) { return el; } }; } That is an absolutely terrible way to implement a _runtime_ method. DOM interface calls are the most used in any script and they have the greatest impact to the performance. JS <=> DOM calls already much slower then JS <=> JS calls and cutting their performance even further for any bit is a crime to be punished :-) :-| |
#13
| |||||||||||||||
| |||||||||||||||
|
|
Whoa, that is a lot of code! |
|
I didn't make a time test but I think the simulation of Array.prototype.filter will be very slow. I made a CSS selector |
|
function one time (something like jQuery has) and I found that any |
|
code that will operate on any medium sized DOM needs to be very fast. |
|
I also made a test between just simply looping over an array verses using a function that takes another function and iterates over all of an array. A simple loop wins by a long shot. |
|
For the repository, the above code could be substantially reduced to something like the following which will run much faster. // ----------------------------------------- // from another file in the respository if (document.documentElement) { var getAnElement = function(d) { return (d || document).documentElement; }; } // ----------------------------------------- // One implementation for developers not concerned with IE5 // problem of the browser thinking doctype and comments // are elements. if (document.getElementsByTagName && typeof getAnElement != 'undefined' && getAnElement().getElementsByTagName) { var getEBTN = function(tag, root) { var els = root.getElementsByTagName(tag); if (tag == '*' && !els.length && root.all) { els = root.all; } return els; }; } |
|
// ----------------------- // Another implementation for developers concerned with // the IE5 problem about doctype and comments if (document.getElementsByTagName && typeof getAnElement != 'undefined' && getAnElement().getElementsByTagName) { var getEBTN = function(tag, root) { var els = root.getElementsByTagName(tag); if (tag == '*' && !els.length && root.all) { var all = root.all; els = []; for (var i=0, ilen=all.length; i<ilen; i++) { var el = all[i]; |
|
// The following conditional could be factored out // if necessary. if ((el.nodeType == 1 && el.tagName != '!') || (!el.nodeType && el.tagName)) { els[els.length] = el; } } } return els; }; } I haven't actually verified the IE5 bug yet and tested the above in a wide set of browsers. I'm just looking at the packaging of the concepts. |
|
I think there is no need for two getEBTN wrappers because, I think, all of the known browsers that have document.getElementByTagName also have element.getElementByTagName. It seems overly paranoid to think that sometime in a future such a browser will be created. The reason |
|
for two feature tests is because document.getElementsByTagName is defined in the DOM2 standard as part of Document and the other getElementsByTagName is defined for Element so a test only for one could be construed as object inference. |
|
Even though the two getEBTN wrappers use different fallbacks for IE4 it looks like they could be combined into one just like I've done here with no real performance penalty. If some browsers had document.all and not element.all then that would be a problem but has that ever been the case? |
|
The API should be considered here. A getEBTN wrapper function like the above could be called "getByCssSelector" and the calls to getEBTN would become a subset of the possible calls to "getByCssSelector". |
|
There is a standard in the works for something like "document.getByCssSelector". So eventually there would be a very fast host object that could be wrapped. |
|
I think that having getEBTN as it's own function is good and both getEBID and getEBTN could be wrapped in a function getByCssSelector. |
|
This is something I'd like to add to the repository eventually. I did a couple weeks of work on these types of functions a while ago and it is very handy for enlivening pages for unobtrusive JavaScript. (Cue "PointedEars" for a "lemmings" comment.) |
#14
| |||
| |||
|
|
On Dec 8, 5:32 pm, Peter Michaux <petermich... (AT) gmail (DOT) com> wrote: On Dec 8, 5:37 am, David Mark <dmark.cins... (AT) gmail (DOT) com> wrote: [snip about gEBI wrappers for the repository] if (document.getElementById) { var getEBI = function(id, d) { var el = (d||document).getElementById(id); if (el.id == id) { return el; } }; } // the simplest possible implementation if (document.getElementById) { var getEBI = function(id, d) { return (d||document).getElementById(id); }; } // ------------------------------------------- // an implementation that *fixes* the IE name/id bug // I don't know what happens in the "hunt" if there // are frames, iframes, or object elements in the DOM |
|
var getEBI = (function() { var el; if (document.getElementById && typeof getAnElement != 'undefined' && ((el=getAnElement()).firstChild || el.firstChild === null) && (el.nextSibling || el.nextSibling === null)) { return function(id, d) { var el = (d || document).getElementById(id); if (el && el.id == id) { return el; } function hunt(node, id) { if (node.id == id) { return node; } node = node.firstChild; while (node) { var el = hunt(node, id); if (el) { return el; } node = node.nextSibling; } } return hunt(d, id); } } })(); |
#15
| |||
| |||
|
|
Peter Michaux wrote on 09 dec 2007 in comp.lang.javascript: // the simplest possible implementation if (document.getElementById) { var getEBI = function(id, d) { return (d||document).getElementById(id); }; } What is the use of testing for getElementById, as the js code will error anyway when getEBI() is subsequently called while not defined? |
|
// the simplest possible implementation var getEBI = function(id, d) { return (d||document).getElementById(id); }; |
#16
| |||
| |||
|
|
Peter Michaux wrote: Based on the repository design guidelines, the above could be substantially reduced to just [...] Notes: There is no need to check for the existence of "document" as no browser, NN4+ and IE4+, missing "document". There is no need to check that document.getElementById is a callable since there has never been a known implementation where document.getElementById that is not callable. If these are the guidelines for your project, to produce code that is not interoperable and inherently unreliable, I don't want to contribute. |
#17
| |||
| |||
|
|
On Dec 9, 4:32 am, Peter Michaux <petermich... (AT) gmail (DOT) com> wrote: Based on the repository design guidelines, the above could be substantially reduced to just if (document.getElementById) { var getEBI = function(id, d) { var el = (d||document).getElementById(id); if (el.id == id) { return el; } }; } That is an absolutely terrible way to implement a _runtime_ method. DOM interface calls are the most used in any script and they have the greatest impact to the performance. JS <=> DOM calls already much slower then JS <=> JS calls and cutting their performance even further for any bit is a crime to be punished :-) :-| Features/environment sniffing has to be done only _once_ on the instantiation stage and _never_ in a loop on each invocation. |
#18
| |||
| |||
|
|
I didn't make a time test but I think the simulation of Array.prototype.filter will be very slow. I made a CSS selector |
#19
| |||
| |||
|
|
Peter Michaux wrote on 09 dec 2007 in comp.lang.javascript: // the simplest possible implementation if (document.getElementById) { var getEBI = function(id, d) { return (d||document).getElementById(id); }; } What is the use of testing for getElementById, as the js code will error anyway when getEBI() is subsequently called while not defined? |
#20
| |||
| |||
|
|
Peter Michaux wrote: Based on the repository design guidelines, the above could be substantially reduced to just [...] Notes: There is no need to check for the existence of "document" as no browser, NN4+ and IE4+, missing "document". There is no need to check that document.getElementById is a callable since there has never been a known implementation where document.getElementById that is not callable. If these are the guidelines for your project, to produce code that is not interoperable and inherently unreliable, |
![]() |
| Thread Tools | |
| Display Modes | |
| |