I think we're both wrong, mine failed on a single class name with no spaces, yours (if I understand it correctly) erroneously reports 2 matches here:
Code:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
function bycls(nme,el){
el = el || document;
for (var reg=new RegExp('\\W'+nme+'\\W'),els=el.getElementsByTagName('*'),ary=[],z0=0; z0<els.length;z0++){
if(reg.test(' '+els[z0].className+' ')){
ary.push(els[z0]);
}
}
return ary;
}
</script>
</head>
<body>
<div class="title-span"></div>
<div class="title"></div>
<script type="text/javascript">
alert(bycls('title').length);
</script>
</body>
</html>
The regex finally adopted by most respondents in the thread I referred to is perhaps the solution (substitute nme for className to make it a drop in replacement):
Code:
new RegExp("(?:^|\\s)" + className + "(?:$|\\s)")
works with the above example. Potentially the best solution in that thread was:
http://www.webdeveloper.com/forum/sh...4&postcount=35
It might still benefit from one or more of the efficiencies mentioned in the earlier posts that it left out, like testing for the equality of a single class name first before applying the regex test. But that might make it less faithful to the specification.
And its author says right out it's not fully tested.
It also assumes an array is what's wanted and when falling forward converts the nodelist to an array. This can actually be good. Nodelists behave erratically cross browser. Some browsers add to/subtract from them if the DOM changes, others do not. With an array, neither of those will happen, so you know what to expect.
In my mind it's best feature is the callback which prevents having to iterate over the array again to perform whatever action is desired.
Added Later:
I tried out that function from that post that had impressed me. It had several problems. Here's a corrected version with my other additions (push for non-push browsers, document.all for those that support it that might not support getElementsByTagName in some or all of its forms) included:
Code:
/**
* @param string required Class name or names to find
* @param string optional Tag name to search for
* @param object optional DOM node to search from
* @param func optional Callback function executed on each iteration.
* Receives two arguments, index and DOM node
* @return array Array of matching DOM nodes
*/
function getElementsByClassNameCustom(cname, tagName, parent, callback) {
tagName = tagName || "*";
parent = parent || document;
callback = callback || function(){};
var el = null;
var matches = [];
var i = 0, j = 0;
var els = document.all && !window.opera? (tagName === '*'? parent.all : parent.all.tags(tagName)) : parent.getElementsByTagName(tagName);
var cnames = cname.split(' ');
function testallnames(name){
var cname, reg;
while (cname = cnames[j++]){
reg = new RegExp("(?:^|\\s)" + cname + "(?:$|\\s)");
if(!reg.test(name)){return false;}
}
return true;
}
while (el = els[i++]) {
j = 0;
if ( testallnames(el.className) ) {
callback( matches.push(el)-1, el);
}
}
return matches;
}
function getElementsByClassNameNative(cname, tagName, parent, callback) {
parent = parent || document;
callback = callback || function(){};
var els = parent.getElementsByClassName(cname, tagName);
var el;
var i = els.length;
var matches = [];
// Wrap the element collection in an Array
while (el = els[--i]) {
callback( matches.push(el)-1, el);
}
return matches.reverse();
}
window.getElementsByClassName = getElementsByClassNameCustom;//!document.getElementsByClassName ? : getElementsByClassNameNative;
if (![].push){
Array.prototype.push = function(){
var a = arguments;
for(var i = 0; i < a.length; ++i){
this[this.length] = a[i];
}
return this.length;
};
}
Example usage, utilizing all of the available parameters on two class names:
Code:
getElementsByClassName('title title-span', 'div', document.body, function(i, el){el.style.display = 'none';})
Using only the required on a single class name:
Code:
getElementsByClassName('title')
Note: The specification requires that, in the case of two or more class names, only those elements with all of the classes should be returned.
Usage for the original question:
Code:
<div id="tileM" onclick="getElementsByClassName('switchM', '', '', function(i, el){el.classname='Tname'});"
Bookmarks