Ver Mensaje Individual
  #7 (permalink)  
Antiguo 01/05/2007, 17:57
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: SELECTS dependientes con inteligencia hacia atrás

Bueno yo diría que ya está:

Código PHP:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<
html>
<
head>
<
title>SELECTs depedientes con inteligencia hacia atrás</title>
<
meta name="Author" content="derkeNuke">
</
head>

<
body>



<
script>

/****************************************************************
    ESTRUCTURA BÁSICA
****************************************************************/
var paises=["PAIS1","PAIS2","PAIS3"];
var 
provincias=[
    [
"PROVINCIA1 (p1)","PROVINCIA2 (p1)",  "PROVINCIA3 (p1)""PROVINCIA4 (p1)"], 
    [
"PROVINCIA1 (p2)""PROVINCIA2 (p2)""PROVINCIA3 (p2)""PROVINCIA4 (p2)""PROVINCIA5 (p2)""PROVINCIA6 (p2)"], 
    [
"PROVINCIA1 (p3)""PROVINCIA2 (p3)""PROVINCIA3 (p3)" ]
];
var 
ciudades=[
    [
        [
"ciud1-1-1""ciud1-1-2""ciud1-1-3""ciud1-1-4""ciud1-1-5" ],
        [
"ciud1-2-1""ciud1-2-2""ciud1-2-3""ciud1-2-4" ],
        [
"ciud1-3-1""ciud1-3-2""ciud1-3-3""ciud1-3-4" ],
        [
"ciud1-4-1""ciud1-4-2""ciud1-4-3" ]
    ],
    
    [
        [
"ciud2-1-1""ciud2-1-2""ciud2-1-3""ciud2-1-4""ciud2-1-5""ciud2-1-6""ciud2-1-7""ciud2-1-8" ],
        [
"ciud2-2-1""ciud2-2-2""ciud2-2-3""ciud2-2-4""ciud2-2-5""ciud2-2-6" ],
        [
"ciud2-3-1""ciud2-3-2""ciud2-3-3""ciud2-3-4""ciud2-3-5""ciud2-3-6" ],
        [
"ciud2-4-1""ciud2-4-2""ciud2-4-3""ciud2-4-4""ciud2-4-5""ciud2-4-6""ciud2-4-7" ],
        [
"ciud2-5-1""ciud2-5-2""ciud2-5-3""ciud2-5-4""ciud2-5-5" ],
        [
"ciud2-6-1""ciud2-6-2""ciud2-6-3""ciud2-6-4""ciud2-6-5" ]
    ],
    
    [
        [
"ciud3-1-1""ciud3-1-2""ciud3-1-3""ciud3-1-4""ciud3-1-5""ciud3-1-6""ciud3-1-7""ciud3-1-8" ],
        [
"ciud3-2-1""ciud3-2-2""ciud3-2-3" ],
        [
"ciud3-3-1""ciud3-3-2""ciud3-3-3""ciud3-3-4" ]
    ]
];


/****************************************************************
    FUNCIONES ÚTILES PARA ARRAYS Y SELECTS
****************************************************************/

//agrega un option a un select, con un par de atributos extra que nos serán útiles
function agregarOpt(elSel,txt,valor,suPais,suProvincia,contieneProvincias,contieneCiudades) {
    var 
indice=elSel.options.length;
    
elSel.optionsindice ] = new Option(txt,valor);
    
elSel.optionsindice ].suPais=suPais;
    
elSel.optionsindice ].suProvincia=suProvincia;
    
elSel.optionsindice ].contieneProvincias=contieneProvincias;
    
elSel.optionsindice ].contieneCiudades=contieneCiudades;
}

//selecciona la opción iPos en el select elSelect
function selecciona(elSelect,iPos) { 
    
elSelect.options[iPos].selected="selected";        // para los estándares
    
elSelect.options.selectedIndex=iPos;            // a la manera IE
}

//devuelve true si el elemento elem se encuentra entre los elementos del array
Array.prototype.existe=function(elem) {
    for(var 
i=0;i<this.length;i++)
        if( 
this[i] == elem ) return true;
    return 
false;
}

//borra todas las opciones de un select cuyo valor no se encuentre entre los elementos de elArray
function dejarOpcionesExistentes(elSelect,elArray) {
    for(var 
i=0i<elSelect.options.lengthi++) {
        if( !
elArray.existeelSelect.options[i].value ) ) {
            
//borramos la opcion
            
elSelect.options[i]=null;
            
i--;    //reducimos i porque tenemos que iterar más veces (el length de las options es uno menos)
        
}
    }
}

/****************************************************************
    CREACIÓN Y RELLENADO DE LOS SELECTS
****************************************************************/

//Creamos los SELECTS
var selPais=document.createElement("SELECT");
var 
selProv=document.createElement("SELECT");
var 
selCiud=document.createElement("SELECT");

//la función coloca en los selects creados todos los valores de los arrays, pudiendo salvar el select que se indique en los argumentos
function reiniciar_selects(conPaises,conProvincias,ConCiudades) {
    if (
conPaises==undefined || conPaises)
        
haCambiadoPais=false;
    
//eliminamos las option de los selects que procedan
    
while( (conPaises==undefined || conPaises) && selPais.options.length>)
        
selPais.options[0]=null;
    while( (
conProvincias==undefined || conProvincias) && selProv.options.length>)
        
selProv.options[0]=null;
    while( (
ConCiudades==undefined || ConCiudades) && selCiud.options.length>)
        
selCiud.options[0]=null;
    
//colocamos las opciones nuevas si procede
    
for(var i=0i<paises.lengthi++) {
        if(
conPaises==undefined || conPaises 
            
agregarOpt(selPaispaises[i], paises[i], nullnullprovincias[i].toString().split(","), ciudades[i].toString().split(",") );
        for(var 
j=0j<provincias[i].lengthj++) {
            if(
conProvincias==undefined || conProvincias )  
                
agregarOpt(selProvprovincias[i][j], provincias[i][j], inullnullciudades[i][j].toString().split(",") );
            for(
k=0k<ciudades[i][j].lengthk++) {
                if(
ConCiudades==undefined || ConCiudades ) {
                    
//cuenta regresiva para contar todas las provincias anteriores (cuantas provincias habia en los paises anteriores)
                    
var aux=i-1provinciasAnteriores=0;
                    while(
aux>=0)
                        
provinciasAnteriores+=provincias[aux--].length;
                    
agregarOpt(selCiudciudades[i][j][k], ciudades[i][j][k], iprovinciasAnteriores+";"+jnullnull);
                }
            }
        }
    }
}

var 
haCambiadoPais=false;        //elemento de control para contar las provincias al cambiar de ciudad
reiniciar_selects(true,true,true);        //todos los valores en todos los selects

//adjuntamos al documento
document.body.appendChild(selPais);
document.body.appendChild(selProv);
document.body.appendChild(selCiud);



/****************************************************************
    EVENTOS ONCHANGE PARA CADA UNO DE LOS SELECTS
****************************************************************/
selPais.onchange=function() {
    
//restablecemos provincias, ciudades
    
reiniciar_selects(false,true,true);
    
//cambiar provincias para que sólo contengan .contieneProvincias
    
var contieneProvincias=this.options[this.options.selectedIndex].contieneProvincias;
    
dejarOpcionesExistentes(selProv,contieneProvincias);
    
//cambiar ciudades para que sólo contengan .contieneCiudades
    
var contieneCiudades=this.options[this.options.selectedIndex].contieneCiudades;
    
dejarOpcionesExistentes(selCiud,contieneCiudades);
    
haCambiadoPais=true;
}
selProv.onchange=function() {
    
//restablecemos sólo ciudades
    
reiniciar_selects(false,false,true);
    
//seleccionar el pais al que pertenece la provincia
    
var suPais=this.options[this.options.selectedIndex].suPais;
    
selecciona(selPais,suPais);
    
//cambiar ciudades para que sólo contengan .contieneCiudades
    
var contieneCiudades=this.options[this.options.selectedIndex].contieneCiudades;
    
dejarOpcionesExistentes(selCiud,contieneCiudades);
}
selCiud.onchange=function() {
    
//seleccionar el pais al que pertenece la ciudad
    
var suPais=this.options[this.options.selectedIndex].suPais;
    
selecciona(selPais,suPais);
    
//seleccionar la provincia a la que pertenece la ciudad
    
var suProvincia=this.options[this.options.selectedIndex].suProvincia;
    if(!
haCambiadoPaissuProvincia=eval( suProvincia.replace(";","+") );        //suma de las provincias de los anteriores paises más la suya
    
else suProvincia=suProvincia.split(";")[1];                                    //sólo la suya
    
selecciona(selProv,suProvincia);
}



//creamos un botón por si acaso se necesita restablecer todo:
var boton=document.createElement("INPUT");
with(boton) {
    
type="button"value="Restablecer";
    
setAttribute("onclick","reiniciar_selects(true,true,true)");        // estándar
    
boton.onclick=reiniciar_selects;                                    // IE
}
document.body.appendChild(boton);


</script>

</body>
</html> 
Para solventarlo con los mínimos cambios posibles he añadido la variable de control haCambiadoPais que es un boolean que indica lo que dice su nombre.

En la propiedad suProvincia de cada option del select ciudad en vez de guardar un único valor numérico para el caso haCambiadoPais=false como tenía antes, ahora es un string con formato "X;Y". X se encarga de contar las provincias de los paises anteriores a los que no pertenece la ciudad, Y es el número de provincia dentro del país al que pertenece la ciudad.

De manera que si haCambiadoPais=false la provincia a seleccionar será todas las de los paises anteriores (X) más las provincias de nuestro país (Y).
Si haCambiadoPais=true en el select de provincias sólo habrá las de nuestro país, luego a la provincia que hay que cambiar es únicamente Y:

Código PHP:
    if(!haCambiadoPaissuProvincia=eval( suProvincia.replace(";","+") );        //suma de las provincias de los anteriores paises más la suya
else suProvincia=suProvincia.split(";")[1];                                    //sólo la suya 
Para el botón he simplificado código y he metido las dos maneras, no sé lo correcto que será esto, pero no me da errores ni en uno ni en otro:
Código PHP:
    setAttribute("onclick","reiniciar_selects(true,true,true)");        // estándar
boton.onclick=reiniciar_selects;                                    // IE 


Bueno, me gustaría que alguien lo testeara en otros navegadores como Opera o Safari, especialmente Opera, yo no lo tengo instalado en esta máquina.


Un saludo.


PD: Que nadie intente entender el código sin estas explicaciones
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.