![]() | |
#1
| |||
| |||
|
#2
| |||
| |||
|
#3
| |||
| |||
|
|
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. |
|
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); }; } })(); } |
#4
| |||
| |||
|
|
On Dec 8, 8:37 am, David Mark <dmark.cins... (AT) gmail (DOT) com> wrote: var l = a.length ... if (typeof(l) != 'undefined') |
#5
| |||
| |||
|
|
var allElements, commonElementsByTagName, documentElementsByTagName, elementElementsByTagName, doc, html, htmlElement, i; var filter, filterLegacy; var reFeaturedMethod = new RegExp('^function|object$', 'i'); var global = this; // Test for properties of host objects known not to be callable // (e.g.document nodes, elements) var isRealObjectProperty = function(o, p) { return !!(typeof(o[p]) == 'object' && o[p]); }; // 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'); }; // Filter wrapper, which is included at this stage as it is needed // for the gEBTN workaround (all returns non-element nodes.) // Standard filter wrapper is not useful for IE5.0 as it requires // Function.prototype.call. if (Array.prototype.filter) { filter = function(a, fn, context) { return a.filter(fn, context); }; } else { // Note that Array.prototype.reverse is not tested as it is // from JS 1.1 if (Function.prototype.call) { filter = function(a, fn, context) { var l = a.length, r = [], c = 0; context = context || global; // Didn't want to use in operator and for in loop does // not preserve order while (l--) { if (typeof(l) != 'undefined') { if (fn.call(context, a[l], a)) { r[c++] = a[l]; } } } return r.reverse(); }; } else { // No simulated filter possible, so add a fallback // with a slightly different interface // Parameter fn can be a string (method name) or function // Context ignored unless fn is a string filterLegacy = function(a, fn, context) { var l = a.length, r = [], c = 0; context = context || global; fn = (typeof(fn) == 'string')?context[fn]:fn; while (l--) { if (typeof(l) != 'undefined') { if (fn(a[l], a)) { r[c++] = a[l]; } } } return r.reverse(); }; } } function elementFilter(o) { // IE5 thinks comments and docTypes are elements. // Second conjunction is for agents that don't support nodeType. return (o.nodeType == 1 && o.tagName != '!') || (!o.nodeType && o.tagName); } // Used to convert array-like host objects to arrays // IIRC, Array.prototype.slice didn't work with node lists function toArray(o) { var a = []; var l = o.length; while (l--) { a[l] = o[l]; } return a; } if (isRealObjectProperty(this, 'document')) { doc = this.document; if (isFeaturedMethod(doc, 'all')) { // Internal in my framework, called by: // commonElementsByTagName and htmlElement allElements = (function() { var fnFilter = filter || filterLegacy; return function(el, bFilter) { return (bFilter) ? fnFilter(toArray(el.all), elementFilter) : el.all; }; })(); } // Called by both gEBTN wrappers commonElementsByTagName = (function() { if (isFeaturedMethod(doc, 'all') && allElements) { return function(el, t) { return (t == '*' && el.all) ? allElements(el, true) : el.getElementsByTagName(t); }; } return function(el, t) { return el.getElementsByTagName(t); }; })(); // Defined only if document nodes feature gEBTN or all. // Returns an array or array-like host object. documentElementsByTagName = (function() { if (isFeaturedMethod(doc, 'getElementsByTagName')) { return function(t, docNode) { return commonElementsByTagName(docNode || doc, t); }; } if (isFeaturedMethod(doc, 'all') && isFeaturedMethod(doc.all, 'tags')) { return function(t, docNode) { return (docNode || doc).all.tags(t); }; } })(); // Returns the HTML element by default or optionally // the first element it finds. htmlElement = function(docNode, bAnyElement) { var html, all; docNode = docNode || doc; html = isRealObjectProperty(docNode, 'documentElement') ? docNode.documentElement (documentElementsByTagNam e)?documentElementsByTagName('html', docNode)[0] : null); if (!html && allElements) { all = allElements(docNode);//Don't bother to filter for this html = all[(all[0].tagName == '!')?1:0]; if (html && !bAnyElement && html.tagName.toLowerCase() != 'html') { html = null; } } return html; }; // Retrieve any element (what follows doesn't care which one) html = htmlElement(doc, true); if (html) { // Defined only if element nodes feature gEBTN or all. // Returns an array or array-like host object. elementElementsByTagName = (function() { if (isFeaturedMethod(html, 'getElementsByTagName')) { return commonElementsByTagName; } if (isFeaturedMethod(html, 'all') && isFeaturedMethod(html.all, 'tags')) { return function(el, t) { return el.all.tags(t); }; } })(); } } |
#6
| |||
| |||
|
|
On Dec 8, 5:37 am, David Mark <dmark.cins... (AT) gmail (DOT) com> wrote: |
|
if (document.getElementById) { var getEBI = function(id, d) { var el = (d||document).getElementById(id); if (el.id == id) { return el; } }; } |
#7
| |||
| |||
|
|
// the simplest possible implementation if (document.getElementById) { var getEBI = function(id, d) { return (d||document).getElementById(id); }; } |
#8
| |||
| |||
|
|
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. |
#9
| |||
| |||
|
|
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; } }; } |
#10
| |||
| |||
|
|
On 8 ΔΕΛ, 23:46, David Mark <dmark.cins... (AT) gmail (DOT) com> wrote: On Dec 8, 8:37 am, David Mark <dmark.cins... (AT) gmail (DOT) com> wrote: var l = a.length ... if (typeof(l) != 'undefined') What this checking is necessary for? The index of an array can be type "undefined"? |
![]() |
| Thread Tools | |
| Display Modes | |
| |