Ideal implementation of document. getelementsbyclassname

Source: Internet
Author: User
Various implementation methods: Pure dom

Generally, getelementsbytagname ("*") is used to retrieve all elements in the document, traverse them, and use regular expressions to find matching elements and put them in an array to return the results. Because ie5 does not support document. getelementsbytagname ("*"), use the branch document. All to prevent errors.

The ultimate getelementsbyclassname SolutionThe author is Robert Nyman, which has been realized in. It can be seen that many foreigners have gone far before.

// All three parameters are required. Search for the 5007 elements of a webpage class named "cell". IE8 lasts for 1828 ~ 1844 ms, // IE6 is 4610 ~ 6109 ms, ff3.5 is 46 ~ 48 ms, opera10 is 31 ~ 32 ms, Chrome is 23 ~ 26 Ms, // safari4 is 19 ~ 20 ms function getelementsbyclassname (oelm, strtagname, strclassname) {var arrelements = (strtagname = "*" & oelm. All )? Oelm. ALL: oelm. getelementsbytagname (strtagname); var arrreturnelements = new array (); strclassname = strclassname. replace (/\-/g, "\-"); var oregexp = new Regexp ("(^ | \ s) "+ strclassname +" (\ s | $) "); var oelement; For (VAR I = 0; I <arrelements. length; I ++) {oelement = arrelements [I]; If (oregexp. test (oelement. classname) {arrreturnelements. push (oelement) ;}} return (arrreturnelements )}

Another implementation is provided by Dustin DIAZ (author of JavaScript design patterns), but it is not compatible with ie5.

// The last two parameters are reliable. Find the 5007 elements of the class "cell" on a webpage. IE8 lasts for 78 milliseconds, and IE6 lasts for 125 to milliseconds ~ 171 Ms // ff3.5 is 42 ~ 48 ms, opera10 is 31 ms, Chrome is 22 ~ 25 ms, safari4 is 18 ~ 19 Ms var getelementsbyclass = function (searchclass, node, tag) {var classelements = new array (); If (node = NULL) node = document; if (TAG = NULL) tag = '*'; var els = node. getelementsbytagname (TAG); var elslen = els. length; var pattern = new Regexp ("(^ | \ s)" + searchclass + "(\ s | $)"); for (I = 0, j = 0; I <elslen; I ++) {If (pattern. test (ELS [I]. classname) {classelements [J] = els [I]; j ++;} return classelements ;}

There is also an older version, which I found in prototype. js1.01. It supports searching for multiple class names (not for the two above ). It does not support ie5, which is very efficient, but as one of the earliest frameworks, it has done a good job. Other frameworks haven't thought of this yet!

// Because this is added later, the test page has been deleted and has not been tested ...... Function getelementsbyclassname (classname, element) {var children = (element | document ). getelementsbytagname ('*'); var elements = new array (); For (VAR I = 0; I DOM tree Walker

Use document. createtreewalker, which is an uncommon level-2 DOM method. Unfortunately, the entire series of IE dishes are closed.

// Search for 5007 elements in a webpage with the class "cell", and ff3.5 is 104 ~ 119 ms, opera10 is 230 ~ 265 ms, // Chrome is 119 ~ 128 ms, Safari is 28 ~ 32 millisecond var getelementsbyclassname = function (searchclass) {function acceptnode (node) {If (node. hasattribute ("class") {var c = "" + node. classname + ""; if (C. indexof ("" + searchclass + "")! =-1) return nodefilter. filter_accept;} return nodefilter. filter_skip;} var treewalker = document.createtreewalker(document.doc umentelement, nodefilter. show_element, acceptnode, true); var returnelements = []; If (treewalker) {var node = treewalker. nextnode (); While (node) {returnelements. push (node); node = treewalker. nextnode () ;}} return returnelements ;}
Xpath

More modern and fashionable technologies.

The following is taken from the prototype. js framework.

Document. getelementsbyclassname = function (classname, parentelement) {If (prototype. browserfeatures. XPath) {var q = ". // * [contains (Concat ('', @ class,''), '"+ classname +"')] "; return document. _ getelementsbyxpath (Q, parentelement);} else {var children = ($ (parentelement) | document. body ). getelementsbytagname ('*'); var elements = [], child; for (VAR I = 0, length = children. length; I <length; I ++) {Child = children [I]; If (element. hasclassname (child, classname) elements. push (element. extend (child);} return elements ;}};

Since this cannot be run, we modify it as follows:

 // search for the elements of the first class named "cell" on a webpage. The value of ff3.5 is 33 ~ 48 ms, opera10 is 31 ~ 32 ms, // Chrome is 104 ~ 107 Ms, Safari is 18 ~ 21 Ms var getelementsbyclassname = function (searchclass, node, tag) {node = node | document; tag = tag | '*'; var classes = searchclass. split (""), patterns = "", xhtmlnamespace = "http://www.w3.org/1999/xhtml", namespaceresolver = (document.doc umentelement. namespaceuri === xhtmlnamespace )? Xhtmlnamespace: NULL, returnelements = [], elements, _ node; For (var j = 0, JL = classes. length; j 
   

Of course, if the browser supports native, it will use native.

Support for mainstream browsers
IE8 IE7 IE6 Ff3 Ff2 Saf3 OP9 OP10 Chrome
N N N Y N Y Y Y Y
Speed comparison Overview

Speed-based solution for the entire platform

Provided by Robert Nyman.

VaR getelementsbyclassname = function (classname, Tag, elm) {If (document. getelementsbyclassname) {getelementsbyclassname = function (classname, Tag, elm) {elm = elm | document; var elements = Elm. getelementsbyclassname (classname), nodename = (TAG )? New Regexp ("\ B" + tag + "\ B", "I"): NULL, returnelements = [], current; For (VAR I = 0, IL = elements. length; I <il; I + = 1) {current = elements [I]; If (! Nodename | nodename. test (current. nodename) {returnelements. push (current) ;}} return returnelements ;};} else if (document. evaluate) {getelementsbyclassname = function (classname, Tag, elm) {tag = tag | "*"; elm = elm | document; var classes = classname. split (""), classestocheck = "", xhtmlnamespace = "http://www.w3.org/1999/xhtml", namespaceresolver = (document.doc umentelement. namespaceur I === xhtmlnamespace )? Xhtmlnamespace: NULL, returnelements = [], elements, node; For (var j = 0, JL = classes. length; j <JL; j + = 1) {classestocheck + = "[contains (Concat ('', @ class ,''), '"+ classes [J] +"')] ";} Try {elements = document. evaluate (". // "+ tag + classestocheck, elm, namespaceresolver, 0, null);} catch (e) {elements = document. evaluate (". // "+ tag + classestocheck, elm, null, 0, null);} while (node = E Lements. iteratenext () {returnelements. push (node) ;}return returnelements ;};} else {getelementsbyclassname = function (classname, Tag, elm) {tag = tag | "*"; elm = elm | document; var classes = classname. split (""), classestocheck = [], elements = (TAG = "*" & Elm. all )? Elm. ALL: Elm. getelementsbytagname (TAG), current, returnelements = [], match; For (var k = 0, KL = classes. length; k <kl; k + = 1) {classestocheck. push (New Regexp ("(^ | \ s)" + classes [k] + "(\ s | $)");} For (var l = 0, LL = elements. length; L <ll; L + = 1) {current = elements [l]; match = false; For (VAR m = 0, ML = classestocheck. length; m <ml; m + = 1) {match = classestocheck [M]. test (current. classname); If (! Match) {break ;}}if (MATCH) {returnelements. Push (current) ;}} return returnelements ;};} return getelementsbyclassname (classname, Tag, elm );};

Based on the above scheme, I have come up with the most ideal implementation-compatible with ie5, so that the next two parameters are optional, native, and efficiency can be improved using literal and reverse loops ......

 
// Search for the 5007 elements in a webpage with the class "cell". IE8 lasts 1828 ~ 1844 ms, // IE6 is 125 ~ 172 ms, IE8 is 93 ~ 94 Ms, ff3.5 is 0 ~ 1 ms, opera10 is 0 ms, Chrome is 1 ms, // safari4 is 0 Ms var getelementsbyclassname = function (searchclass, node, tag) {If (document. getelementsbyclassname) {return document. getelementsbyclassname (searchclass)} else {node = node | document; tag = tag | '*'; vaR returnelements = [] var els = (TAG = "*" & node. all )? Node. ALL: node. getelementsbytagname (TAG); var I = els. length; searchclass = searchclass. replace (/\-/g, "\-"); var pattern = new Regexp ("(^ | \ s) "+ searchclass +" (\ s | $) "); While (-- I> = 0) {If (pattern. test (ELS [I]. classname) {returnelements. push (ELS [I]) ;}} return returnelements ;}}

Usage:

VaR collections = getelementsbyclassname ("red ");

However, it is inferior to the native getelementsbyclassname, and cannot retrieve multiple classes at the same time.

 
<H2 class = "Red Cell title"> installation support </H2> <SPAN class = "cell red"> jjj </span> <Div class = "filament_table Red Cell"> this is Div </div> # use VaR dd = getelementsbyclassname ("cell red "), all three elements should be retrieved!
Therefore, the final solution is:
VaR getelementsbyclassname = function (searchclass, node, tag) {If (document. getelementsbyclassname) {var nodes = (node | document ). getelementsbyclassname (searchclass), result = []; for (VAR I = 0; node = nodes [I ++];) {If (tag! = "*" & Node. tagname = tag. touppercase () {result. push (node) }} return result} else {node = node | document; tag = tag | "*"; var classes = searchclass. split (""), elements = (TAG = "*" & node. all )? Node. ALL: node. getelementsbytagname (TAG), patterns = [], current, match; var I = classes. length; while (-- I> = 0) {patterns. push (New Regexp ("(^ | \ s)" + classes [I] + "(\ s | $)");} var J = elements. length; while (-- j> = 0) {current = elements [J]; match = false; For (var k = 0, KL = patterns. length; k <kl; k ++) {match = patterns [K]. test (current. classname); If (! Match) break;} If (MATCH) result. Push (current) ;}return result ;}}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.