Ver Mensaje Individual
  #6 (permalink)  
Antiguo 02/05/2007, 08:21
Avatar de derkenuke
derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Re: Problema al seleccionar checkboxes y pintar celdas.

Bueno, pues ya he modificado mi script para tablas anidadas. Si antes era complicado de entender, ahora no te imaginas...

El script es corto, pero rebuscado, como me suelen gustar últimamente
Código:
/******************
	FUNCION PARA COLOREAR CELDAS, FILAS O TABLAS (según tagPadre)
******************/
function colorea(obj,tagPadre,niveles) {
	var col= obj.checked ? "#aaf" : "transparent";
	// encontrar con parentNode un obj con tag tagPadre tantas veces como niveles se nos pasen por argumento
	for(var nivelActual=0; nivelActual<niveles; nivelActual++) {
		obj=obj.parentNode;	
		while( obj.nodeType==1 && obj.tagName.toUpperCase()!=tagPadre.toUpperCase() )
			obj=obj.parentNode;
	}
	obj.style.backgroundColor=col;
}

/******************
	FUNCION PARA MARCAR TODOS LOS CHECKBOXES CONTENIDOS EN UNA TABLA QUE SEAN PARA COLOREAR
******************/
function todosChkDeTabla(obj,check) {
	while( obj.nodeType==1 && obj.tagName.toUpperCase()!="TABLE" )
		obj=obj.parentNode;
	//obj ahra es la TABLE sobre la que trabajamos
	function recorrerHijos(elem) {
		if( elem.nodeType==1 && elem.tagName.toUpperCase()=="INPUT" && elem.type=="checkbox" && elem.onclick && /colorea\(/.test(elem.onclick) ) {	// tipo ELEMENT_NODE y encima es checkbox y sirve para colorear
			elem.checked=check;
			// extraemos la funcion que salta al onclick para forzar a ejecutarla (siempre que no sea todosChkDeTabla, entraríamos en recursión)
			var saltaEnOnclick=elem.onclick.toString().match(/^[^\{]+\{([^\}]+)}$/)[1].replace(/this/g,"elem");
			eval(saltaEnOnclick);
		}
		else if (elem.nodeType==1 && elem.hasChildNodes() ) {		//ELEMENT_NODE y encima con hijos
			for(var hijo=0; hijo<elem.childNodes.length; hijo++)		//recorremos cada hijo con la función, recursivamente
				recorrerHijos( elem.childNodes[hijo] );
		}
	}
	recorrerHijos(obj);		//recorremos sus hijos y encontramos checkboxes para marcarlos
}
La estructura HTML es todo lo complicada que se quiera (he anidado varios tipos de tabla). Además he incluído el soporte para checkboxes que no tienen nada que ver con colorear, que antes no tenía esa capacidad la función todosChkDeTabla:
Código PHP:
<table border="1">
    <
tr>
        <
td colspan="3"><input type="checkbox" onclick="todosChkDeTabla(this,this.checked);" /></td>
    </
tr>
    <
tr>
        <
td>
            <
table border="1">
                <
tr>
                    <
td>
                        <
input type="checkbox" onclick="colorea(this,'TR',1);" />
                        <
input type="checkbox" onclick="colorea(this,'TR',2);" />
                    </
td>
                    <
td>AA</td>
                    <
td>BB</td>
                </
tr>
            </
table>
        </
td>
        <
td>loren</td>
        <
td>ipsum</td>
    </
tr>
    <
tr>
        <
td><input type="checkbox" onclick="colorea(this,'TR',1);" /></td>
        <
td>dolor</td>
        <
td>sit</td>
    </
tr>
    <
tr>
        <
td><input type="checkbox" onclick="colorea(this,'TR',1);" /></td>
        <
td>amet</td>
        <
td>loren</td>
    </
tr>
    <
tr>
        <
td><input type="checkbox" onclick="colorea(this,'TR',1);" /></td>
        <
td>
            <
table border="1">
                <
tr>
                    <
td>¿Tienes coche? <input type="checkbox" /></td>
                </
tr>
                <
tr>
                    <
td>¿Moto? <input type="checkbox" /></td>
                </
tr>
                <
tr>
                    <
td>¿Camión? <input type="checkbox" /></td>
                </
tr>
            </
table>
        </
td>
        <
td>dolor</td>
    </
tr>
    <
tr>
        <
td colspan="3">
            <
table border="1">
                <
tr>
                    <
td>Minifila A</td>
                    <
td><input type="checkbox" onclick="colorea(this,'TR',1);" /></td>
                </
tr>
                <
tr>
                    <
td>Minifila B</td>
                    <
td><input type="checkbox" onclick="colorea(this,'TR',1);" /></td>
                </
tr>
                <
tr>
                    <
td>Minifila C</td>
                    <
td><input type="checkbox" onclick="colorea(this,'TR',1);" /></td>
                </
tr>
            </
table>
        </
td>
    </
tr>
</
table
Lo he intentado identar todo muy bien para que no haya confusiones y pueda ser lo más legible posible. He tenido que utilizar los bbcode [ code ] en vez de [ php ] porque utilizo expresiones regulares y las contrabarras se me eliminan si no, lo siento.


La función colorea ahora selecciona el color ella misma, no hace falta pasárselo por argumento (me parece más cómodo). Además busca un padre con la etiqueta tagPadre, pero lo busca tantas veces como niveles. Así si tienemos dos tablas anidadas y desde la de dentro le decimos que coloree "TR" con nivel=2, coloreará el segundo TR que se encuentre haciendo parentNode, es decir, el de la tabla padre. Para "TR" con nivel=1 coloreara la fila de la misma tabla hija.


Para la función todosChkDeTabla lo que he hecho es restringir que se checken todos los checkboxes que en su onclick esté la función colorea; para ello necesito todo el condicional bestia este
Código:
elem.nodeType==1 && elem.tagName.toUpperCase()=="INPUT" && elem.type=="checkbox" && elem.onclick && /colorea\(/.test(elem.onclick)
Aquí ojo que he pensado que si se llama en un onclick a colorea y a todosChkDeTabla a la vez, habría que meter un condicional así para ejecutar el eval:
Código:
if( !/todosChkDeTabla/.test(saltaEnOnclick) )
Pero bueno... son detalles.



Al final me ha gustado mucho cómo me ha quedado el script, pequeño pero matón jeje. Además sirve tanto como para colorear TD como TR como TBODY y TABLE y BODY entero..., lo que se quiera mientras ese elemento sea padre del checkbox



Bueno, ya está bien de parrafada
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.