Un ejemplo (muy poco optimizado) para las colecciones:
Código PHP:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Documento sin título</title>
<script type="text/javascript">
if (!Array.prototype.forEach){
Array.prototype.forEach = function(fun){
if (typeof fun != "function") throw new TypeError();
for (var i = 0,l=this.length; i < l; i++) {
if (i in this) fun.call(arguments[1], this[i], i)
}
return this;
}
}
var pp=(function(){
/* ---- métodos privados ---- */
var metodosColeccion={
css:function(){
var args=[].slice.call(arguments);
this.forEach(function(el){metodosPrivados.css.apply(el,args)});
return this;
},
addEvent:function(){
var args=[].slice.call(arguments);
this.forEach(function(el){metodosPrivados.addEvent.apply(el,args)});
return this;
}
};
var metodosPrivados={
css:function(propiedad,valor){
if(!valor)
return this.style[propiedad];
this.style[propiedad]=valor;
return this;
},
addEvent: function(type, fn ) {
if ( this.addEventListener ) {
this.addEventListener( type, fn, false );
} else if(this.attachEvent){
var _this=this;
var f= function(){fn.call(_this,window.event);}
this.attachEvent( 'on'+type, f);
this[fn.toString()+type]=f;
}else{
this['on'+type]=fn;
}
var ev={_obj:this,_evType:type,_fn:fn};
window.EvRegister=window.EvRegister || [];
window.EvRegister.push(ev);
return this;
},
extendido:true
};
/* ---- métodos públicos ---- */
return{
extend:function(el,obj){
if(el.extendido && el!=metodosPrivados)return el;
for(var i in obj)
el[i]=obj[i];
return el;
},
get:function(id){
if(!document.getElementById(id))return false;
return pp.extend(document.getElementById(id),metodosPrivados);
},
getO:function(obj){
return pp.extend(obj,metodosPrivados);
},
add:function(obj){
pp.extend(metodosPrivados,obj);
},
getByTag:function(tag,ctx){
var d=ctx || document,col=d.getElementsByTagName(tag),ret=[],i,l=col.length;
for(i=0;i<l;i++){
ret.push(col[i]);
}
ret.forEach(function(el){pp.extend(el,metodosPrivados);});
return pp.extend(ret,metodosColeccion);
}
}
})();
onload=function(){
pp.getByTag('li').css('color','red').addEvent('click',function(){alert(this.css('color'));});
}
</script>
</head>
<body>
<ul><li>uno</li><li>dos</li><li>tres</li></ul>
</body>
</html>
Para no hacer un motor de selectores (para los navegadores que no soportan la api Selector), que es muy complejo (uno de los que más me gusta es el de Simon Willison:
http://simonwillison.net/2003/Mar/25...ntsBySelector/), agregué como ejemplo el método getByTag. Fijate que agregué también un objeto metodosColeccion
para extender el nodeList. Esa parte se puede simplificar, ya que si observás los métodos css y addEvent de ese objeto son casi iguales entre sí, así que lo mejor sería recorrer el objeto métodosPrivados y aplicar para cada método de ese objeto una función semejante a esas que digo que son redundantes para extender la colección. Lo que quiero decir es que ni siquiera hace falta crear el objeto metodosColeccion para extender la funcionalidad del nodeList, pero así es más didáctico y ya teniendo la idea seguro que la mejorás, como venís haciendo hasta ahora ;)
Edito:
Lo que decía de evitar redundancias era algo así:
Código PHP:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Documento sin título</title>
<script type="text/javascript">
if (!Array.prototype.forEach){
Array.prototype.forEach = function(fun){
if (typeof fun != "function") throw new TypeError();
for (var i = 0,l=this.length; i < l; i++) {
if (i in this) fun.call(arguments[1], this[i], i)
}
return this;
}
}
var pp=(function(){
/* ---- métodos privados ---- */
var metodosPrivados={
css:function(propiedad,valor){
if(!valor)
return this.style[propiedad];
this.style[propiedad]=valor;
return this;
},
addEvent: function(type, fn ) {
if ( this.addEventListener ) {
this.addEventListener( type, fn, false );
} else if(this.attachEvent){
var _this=this;
var f= function(){fn.call(_this,window.event);}
this.attachEvent( 'on'+type, f);
this[fn.toString()+type]=f;
}else{
this['on'+type]=fn;
}
var ev={_obj:this,_evType:type,_fn:fn};
window.EvRegister=window.EvRegister || [];
window.EvRegister.push(ev);
return this;
},
extendido:true
};
/* ---- métodos públicos ---- */
return{
extend:function(el,obj){
if(el.extendido && el!=metodosPrivados)return el;
for(var i in obj)
el[i]=obj[i];
return el;
},
get:function(id){
if(!document.getElementById(id))return false;
return pp.extend(document.getElementById(id),metodosPrivados);
},
getO:function(obj){
return pp.extend(obj,metodosPrivados);
},
add:function(obj){
pp.extend(metodosPrivados,obj);
},
getByTag:function(tag,ctx){
var d=ctx || document,col=d.getElementsByTagName(tag),ret=[],i,l=col.length;
for(i=0;i<l;i++){
ret.push(col[i]);
}
ret.forEach(function(el){pp.extend(el,metodosPrivados);});
if(ret.extendido)return ret;
for(var n in metodosPrivados){
if(typeof metodosPrivados[n]=='function'){
(function(){
var mp=metodosPrivados[n];
ret[n]=function(){
var args=[].slice.call(arguments);
ret.forEach(function(el){mp.apply(el,args)});
return ret;
}
})();
}else{
(function(){
ret[n]=metodosPrivados[n];
})();
}
}
return ret;
}
}
})();
onload=function(){
pp.getByTag('li').css('color','red').addEvent('click',function(){alert(this.css('color'));});
}
</script>
</head>
<body>
<ul><li>uno</li><li>dos</li><li>tres</li></ul>
</body>
</html>