Foros del Web » Programando para Internet » Javascript »

Selectores múltiples

Estas en el tema de Selectores múltiples en el foro de Javascript en Foros del Web. Buenas gente, hasta ahora la función P de mi intento librería (XD) sólo manejaba un elemento. Es decir: @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); Código Javascript : Ver original ...
  #1 (permalink)  
Antiguo 02/04/2011, 15:03
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 14 años, 1 mes
Puntos: 310
Selectores múltiples

Buenas gente, hasta ahora la función P de mi intento librería (XD) sólo manejaba un elemento. Es decir:
Código Javascript:
Ver original
  1. var foo = P('.bar');
Sólo devolvía el primer .bar porque usaba document.querySelector . Ahora estoy intentando poder usar todas las coincidencias con document.querySelectorAll, pero me veo en problemas. Por ejemplo:
Código Javascript:
Ver original
  1. opacity : function(opct){
  2.    if(this[0]){
  3.     for(var i = 0; act = this[i]; i++){ act.opacity(opct); }
  4.    }
  5.    if(opct){
  6.     this.style.opacity = opct;
  7.     this.style.MozOpacity = opct;
  8.     this.style.KhtmlOpacity = opct;
  9.     this.style.zoom = 1;
  10.     this.style.filter = 'alpha(opacity=' + opct * 100 + ')';
  11.    }else{ return P(this).getStyle('opacity'); }
  12.    return P(this);
  13.   }
Pero claro, opacity se añade como método de un elemento, no de un array de elementos que es lo que devuelve document.querySelectorAll. ¿Qué puedo hacer para solucionar este problema?
Saludos (:
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red
  #2 (permalink)  
Antiguo 02/04/2011, 15:42
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años, 2 meses
Puntos: 1485
Respuesta: Selectores múltiples

buenas...

asi a la ligera, lo que se me ocurre es crear un array y recorrer la lista de nodos devuelta por querySelectorAll aplicandole la extension. es decir, creando el objeto que contiene los metodos de tu libreria. luego ese objeto lo almacenas en el array y finalmente devuelves el array en lugar del NodeList. esto porque los elementos de un NodeList no puedes alterarlo.

__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.
  #3 (permalink)  
Antiguo 02/04/2011, 15:54
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 14 años, 1 mes
Puntos: 310
Respuesta: Selectores múltiples

Si te fijas lo tengo así:
Código Javascript:
Ver original
  1. extender : function(elem, obj){
  2.    if(elem[0]){
  3.     for(var i = 0; act = elem[i]; i++){ JSPlus.extender(act, privado); }
  4.     return elem;
  5.    }
  6.    if(elem.extendido && elem != privado) return elem;
  7.    for(var i in obj){
  8.     elem[i] = obj[i];
  9.    }
  10.    return elem;
  11.   }
¿Cambiaría si en vez de devolver así a pelo devuelvo un verdadero aray?
Saludos (:
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red
  #4 (permalink)  
Antiguo 02/04/2011, 16:26
Avatar de zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años, 2 meses
Puntos: 1485
Respuesta: Selectores múltiples

creo que ya entendi la situacion inicial. ¿tu quieres que el NodeList devuelto por querySelectorAll sea extendido de modo que al invocar los metodos estos se apliquen a todos los elementos del NodeList? por decir un ejemplo...
Código:
P("li").salida("lento");
// todos los elementos <li> encontrados deberian desaparecer ;
yo lo estaba viendo mas desde el punto de vista donde todos los elementos del NodeList sean extendidos. de modo que luego invocas los metodos por cada elemento por separado. de hecho, asi es como lo tienes ahora mismo.

__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.
  #5 (permalink)  
Antiguo 02/04/2011, 16:57
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 14 años, 1 mes
Puntos: 310
Respuesta: Selectores múltiples

Exactamente, lo que quiero es que el método se aplique a todo el NodeList como si estuviera siendo invocado para un sólo elemento. Y como es la única manera que se me ocurrió, lo que pretendía hacer para que funcionara es comprobar en cada método si this era un array y dado el caso invocarlo por cada elemento del array. Espero que se me haya entendido
Saludos (:
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red
  #6 (permalink)  
Antiguo 02/04/2011, 20:03
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 6 meses
Puntos: 845
Respuesta: Selectores múltiples

Que tal _cronos2,

no seria mejor que crearas una clase para manejar las colecciones de elements(JSPLus.NodeList), y utilizarla de proxy a los métodos de los elements en vez de estar en cada método comprobando que es un array ?
__________________
http://es.phptherightway.com/
thats us riders :)
  #7 (permalink)  
Antiguo 03/04/2011, 01:40
Avatar de Panino5001
Me alejo de Omelas
 
Fecha de Ingreso: mayo-2004
Ubicación: -34.637167,-58.462984
Mensajes: 5.148
Antigüedad: 20 años, 1 mes
Puntos: 834
Respuesta: Selectores múltiples

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&#237;tulo</title>
<script type="text/javascript">
if (!Array.
prototype.forEach){
    Array.
prototype.forEach = function(fun){
        if (
typeof fun != "function") throw new TypeError();
          for (var 
0,l=this.lengthli++) {
               if (
i in thisfun.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(typefn ) {
            if ( 
this.addEventListener ) {
                
this.addEventListenertypefnfalse );
            } else if(
this.attachEvent){
                var 
_this=this;
                var 
f= function(){fn.call(_this,window.event);}
                
this.attachEvent'on'+typef);
                
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&#237;tulo</title>
<script type="text/javascript">
if (!Array.
prototype.forEach){
    Array.
prototype.forEach = function(fun){
        if (
typeof fun != "function") throw new TypeError();
          for (var 
0,l=this.lengthli++) {
               if (
i in thisfun.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(typefn ) {
            if ( 
this.addEventListener ) {
                
this.addEventListenertypefnfalse );
            } else if(
this.attachEvent){
                var 
_this=this;
                var 
f= function(){fn.call(_this,window.event);}
                
this.attachEvent'on'+typef);
                
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> 

Última edición por Panino5001; 03/04/2011 a las 04:42
  #8 (permalink)  
Antiguo 03/04/2011, 08:51
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 14 años, 1 mes
Puntos: 310
Respuesta: Selectores múltiples

Cita:
Iniciado por masterpuppet Ver Mensaje
Que tal _cronos2,

no seria mejor que crearas una clase para manejar las colecciones de elements(JSPLus.NodeList), y utilizarla de proxy a los métodos de los elements en vez de estar en cada método comprobando que es un array ?
Me perdí a partir de proxy

Cita:
Iniciado por Panino5001 Ver Mensaje
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 ;)
Muchas gracias por el piropo ¡Funciona perfectamente hasta en IE!
Así queda el código de momento, muchas gracias a todos, os debo un montón de karma XD
Saludos (:
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red

Etiquetas: selectores
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 2 personas




La zona horaria es GMT -6. Ahora son las 20:36.