2008-10-07 19 views
23

Utilizando las respuestas a this question, he podido completar un cuadro de selección según la selección de otro cuadro de selección. (I posted my answer here) Extracción de los datos de una estructura de matriz integrada en el servidor, almacenada en un archivo .js y referenciada en la página html.Uso de javascript y jquery, para rellenar cuadros de selección relacionados con estructura de matriz

Ahora me gustaría agregar un tercer cuadro de selección. Si tuviera 3 series de datos (modelo, marca, opciones) algo como esto (pseudo código):

cars : [Honda[Accord[Lx, Dx]], [Civic[2dr, Hatchback]], 
    [Toyota[Camry[Blk, Red]], [Prius[2dr,4dr]] 

Ej: Si se selecciona Honda, el siguiente cuadro de selección tendría [Acuerdo Cívico] y si Acuerdo eran seleccionado el siguiente cuadro de selección tendría [Lx Dx]

¿Cómo puedo

1) crear una estructura de matriz para contener los datos? de tal manera que

2) I puede utilizar el valor de un cuadro de selección para hacer referencia a los valores necesarios para el siguiente cuadro de selección

Gracias

EDITAR

I pueden crear los siguientes, pero no puede encontrar las referencias de una manera que ayudaría a llenar un cuadro de selección

var cars = [ 
{"makes" : "Honda", 
    "models" : [ 
    {'Accord' : ["2dr","4dr"]} , 
    {'CRV' : ["2dr","Hatchback"]} , 
    {'Pilot': ["base","superDuper"] } ] 
}, 
{"makes" :"Toyota", 
    "models" : [ 
    {'Prius' : ["green","reallyGreen"]} , 
    {'Camry' : ["sporty","square"]} , 
    {'Corolla' : ["cheap","superFly"] } ] 
} ] ;    

alert(cars[0].models[0].Accord[0]); ---> 2dr 

Respuesta

45

prefiero estructura de datos como esto:

var carMakers = [ 
    { name: 'Honda', models: [ 
      { name: 'Accord', features: ['2dr', '4dr'] }, 
      { name: 'CRV', features: ['2dr', 'Hatchback'] }, 
      { name: 'Pilot', features: ['base', 'superDuper'] } 
     ]}, 

    { name: 'Toyota', models: [ 
      { name: 'Prius', features: ['green', 'superGreen'] }, 
      { name: 'Camry', features: ['sporty', 'square'] }, 
      { name: 'Corolla', features: ['cheap', 'superFly'] } 
     ]} 
]; 

Teniendo en cuenta las tres listas de selección por los identificadores: 'fabricante', 'modelo' y 'características' se pueden manipular con este (creo que esto es bastante auto explicativo):

// returns array of elements whose 'prop' property is 'value' 
function filterByProperty(arr, prop, value) { 
    return $.grep(arr, function (item) { return item[prop] == value }); 
} 

// populates select list from array of items given as objects: { name: 'text', value: 'value' } 
function populateSelect(el, items) { 
    el.options.length = 0; 
    if (items.length > 0) 
     el.options[0] = new Option('please select', ''); 

    $.each(items, function() { 
     el.options[el.options.length] = new Option(this.name, this.value); 
    }); 
} 

// initialization 
$(document).ready(function() { 
    // populating 1st select list 
    populateSelect($('#maker').get(0), $.map(carMakers, function(maker) { return { name: maker.name, value: maker.name} })); 

    // populating 2nd select list 
    $('#maker').bind('change', function() { 
     var makerName = this.value, 
      carMaker = filterByProperty(carMakers, 'name', makerName), 
      models = []; 

     if (carMaker.length > 0) 
      models = $.map(carMaker[0].models, function(model) { return { name: model.name, value: makerName + '.' + model.name} }); 

     populateSelect($('#model').get(0), models); 
     $('#model').trigger('change'); 
    }); 

    // populating 3rd select list 
    $('#model').bind('change', function() { 
     var nameAndModel = this.value.split('.'), 
      features = []; 

     if (2 == nameAndModel.length) { 
      var makerName = nameAndModel[0], 
       carModel = nameAndModel[1], 
       carMaker = filterByProperty(carMakers, 'name', makerName); 

      if (carMaker.length > 0) { 
       var model = filterByProperty(carMaker[0].models, 'name', carModel) 

       if (model.length > 0) 
        features = $.map(model[0].features, function(feature) { return { name: feature, value: makerName + '.' + carModel + '.' + feature} }) 
      } 
     } 

     populateSelect($('#feature').get(0), features); 
    }) 

    // alerting value on 3rd select list change 
    $('#feature').bind('change', function() { 
     if (this.value.length > 0) 
      alert(this.value); 
    }) 
}); 
+0

gracias por el esfuerzo que puso en su respuesta. Probé tu código y funcionó, pero no tengo tiempo ahora mismo para saber exactamente cómo funciona ... volveré más tarde ... pero estoy usando la estructura de matriz ... y creo que ahora entender cómo crear estas matrices. Gracias de nuevo –

+0

La estructura de datos es en realidad un objeto Javascript. Puede encontrar aquí un tutorial JSON decente: http://www.hunlock.com/blogs/Mastering_JSON_%28_JavaScript_Object_Notation_%29 – BalusC

+1

El uso de $ .grep y $ .map para esto es solo el trazo maestro. Fantástica solución, acabo de usarlo como base para algo similar y me siento mejor programador para eso. Impresionante solución. – hendrixski

1

Usted sh debería echar un vistazo here para seleccionar la manipulación de la caja. Para lo que quiera, creo que JSON hará el trabajo adecuado para usted. De todos modos, si yo fuera usted, lo haré de esta manera: Cuando cambio primero seleccione, hago una solicitud de ajax. Con la respuesta ajax, poblaré la segunda casilla. Lo mismo para el segundo cuadro y allí tiene el tercer cuadro poblado con datos correctos.

3

Gracias a la respuesta de @Marko Dunic, yo era capaz de construir una estructura de matriz (datos) que se puede hacer referencia a poblar 3 cajas de selección. No utilicé el código de implementación solo porque no lo entendí del todo ... funciona según lo publicado. Volveré a este código más adelante cuando aprendo jQuery. Mi código se publica a continuación (obviamente, su referencia a jQuery puede ser diferente)

<html><head> 
<script language="Javascript" src="javascript/jquery-1.2.6.min.js"></script> 
<script type="text/JavaScript"> 
var cars = [ 
{ name: 'Honda', models: [ 
{ name: 'Accord', features: ['2dr', '4dr'] }, 
{ name: 'CRV', features: ['2dr', 'Hatchback'] }, 
{ name: 'Pilot', features: ['base', 'superDuper'] } 
    ]}, 
{ name: 'Toyota', models: [ 
{ name: 'Prius', features: ['green', 'superGreen'] }, 
{ name: 'Camry', features: ['sporty', 'square'] }, 
{ name: 'Corolla', features: ['cheap', 'superFly'] } 
    ] 
} 
]; 
$(function() { 
var options = '' ; 
for (var i = 0; i < cars.length; i++) { 
    var opt = cars[i].name ; 
    if (i == 0){ options += '<option selected value="' + opt + '">' + opt + '</option>'; } 
    else {options += '<option value="' + opt + '">' + opt + '</option>'; } 
} 
$("#maker").html(options); // populate select box with array 

var options = '' ; 
for (var i=0; i < cars[0].models.length; i++) { 
    var opt = cars[0].models[0].name ; 
    if (i==0){options += '<option selected value="' + opt + '">' + opt + '</option>';} 
    else {options += '<option value="' + opt + '">' + opt + '</option>';} 
} 
$("#model").html(options); // populate select box with array 

var options = '' ; 
for (var i=0; i < cars[0].models[0].features.length; i++) { 
    var opt = cars[0].models[0].features[i] ; 
    if (i==0){options += '<option selected value="' + opt + '">' + opt + '</option>';} 
    else {options += '<option value="' + opt + '">' + opt + '</option>';} 
} 
$("#feature").html(options); // populate select box with array 

$("#maker").bind("click", 
    function() { 
     $("#model").children().remove() ;  // clear select box 
     for(var i=0; i<cars.length; i++) { 
      if (cars[i].name == this.value) { 
       var options = '' ; 
       for (var j=0; j < cars[i].models.length; j++) { 
        var opt= cars[i].models[j].name ; 
        if (j==0) {options += '<option selected value="' + opt + '">' + opt + '</option>';} 
        else {options += '<option value="' + opt + '">' + opt + '</option>';} 
       } 
       break; 
      } 
     } 
     $("#model").html(options); // populate select box with array 

     $("#feature").children().remove() ;  // clear select box 
     for(var i=0; i<cars.length; i++) { 
      for(var j=0; j<cars[i].models.length; j++) { 
       if(cars[i].models[j].name == $("#model").val()) { 
        var options = '' ; 
        for (var k=0; k < cars[i].models[j].features.length; k++) { 
         var opt = cars[i].models[j].features[k] ; 
         if (k==0){options += '<option selected value="' + opt + '">' + opt + '</option>';} 
         else {options += '<option value="' + opt + '">' + opt + '</option>';} 
        } 
        break; 
       } 
      } 
     } 
     $("#feature").html(options); // populate select box with array 
    }); 

    $("#model").bind("click", 
     function() { 
      $("#feature").children().remove() ;  // clear select box 
      for(var i=0; i<cars.length; i++) { 
       for(var j=0; j<cars[i].models.length; j++) { 
        if(cars[i].models[j].name == this.value) { 
         var options = '' ; 
         for (var k=0; k < cars[i].models[j].features.length; k++) { 
          var opt = cars[i].models[j].features[k] ; 
          if (k==0){options += '<option selected value="' + opt + '">' + opt + '</option>';} 
          else {options += '<option value="' + opt + '">' + opt + '</option>';} 
         } 
         break ; 
        } 
       } 
      } 
      $("#feature").html(options); // populate select box with array 
    }); 
}); 
</script> 
</head> <body> 
<div id="selection"> 
<select id="maker"size="10" style="{width=75px}"></select> 
<select id="model" size="10" style="{width=75px}"></select> 
<select id="feature" size="10"style="{width=75px}"></select> 
</div></body></html> 
+0

+1 para llenar un vacío en mi conocimiento jQuery + JSON. Gracias :) – Zoe

2

Me gustó mucho la solución por @Marko Dunic, pero no cumplió con mis necesidades para la fijación de los ID de las opciones. Una vez que adjunté las ID, me di cuenta de que podía hacer que el código JS fuera aún más pequeño y simple. Mi solución está diseñada para cuando los datos provienen de una base de datos relacional y los datos de entrada de JSON conservan la estructura relacional con claves primarias/externas. Estos son los datos JSON:

<html lang="en"> 
    <head> 
    <title>Populate a select dropdown list with jQuery - WebDev Ingredients</title> 
    <script type="text/javascript" src="js/jquery-1.4.2.js"></script> 
    <script type="text/javascript"> 
     var types = [ 
      { typeID: 1, name: 'Domestic'}, 
      { typeID: 2, name: 'Import'}, 
      { typeID: 3, name: 'Boat'} 
     ] 
     var makes = [ 
      { typeID: 1, makeID: 1, name: 'Chevy'}, 
      { typeID: 1, makeID: 2, name: 'Ford'}, 
      { typeID: 1, makeID: 3, name: 'Delorean'}, 
      { typeID: 2, makeID: 4, name: 'Honda'}, 
      { typeID: 2, makeID: 5, name: 'Toyota'}, 
      { typeID: 2, makeID: 6, name: 'Saab'} 
     ]  
     var model = [ 
      { makeID: 1, modelID: 1, name: 'Camaro'}, 
      { makeID: 1, modelID: 2, name: 'Chevelle'}, 
      { makeID: 1, modelID: 3, name: 'Nova'}, 
      { makeID: 2, modelID: 4, name: 'Focus'}, 
      { makeID: 2, modelID: 5, name: 'Galaxie'}, 
      { makeID: 2, modelID: 6, name: 'Mustang'}, 
      { makeID: 4, modelID: 7, name: 'Accord'}, 
      { makeID: 4, modelID: 8, name: 'Civic'}, 
      { makeID: 4, modelID: 9, name: 'Odyssey'}, 
      { makeID: 5, modelID: 10, name: 'Camry'}, 
      { makeID: 5, modelID: 11, name: 'Corolla'} 
     ] 
     // 
     // Put this in a stand alone .js file 
     // 
     // returns array of elements whose 'prop' property is 'value' 
     function filterByProperty(arr, prop, value) { 
      return $.grep(arr, function (item) { return item[prop] == value }); 
     } 
     // populates select list from array of items given as objects: { name: 'text', value: 'value' } 
     function populateSelect(el, items) { 
      el.options.length = 0; 
      if (items.length > 0) 
       el.options[0] = new Option('please select', ''); 
      $.each(items, function() { 
       el.options[el.options.length] = new Option(this.name, this.value); 
      }); 
     } 
     // initialization 
     $(document).ready(function() { 
      // populating 1st select list 
      populateSelect($('#sType').get(0), $.map(types, function(type) { return { name: type.name, value: type.typeID} }));  
      // populating 2nd select list 
      $('#sType').bind('change', function() { 
       var theModels = filterByProperty(makes, 'typeID', this.value); 
       populateSelect($('#sMake').get(0), $.map(theModels, function(make) { return { name: make.name, value: make.makeID} })); 
       $('#sMake').trigger('change'); 
      }); 
      // populating 3nd select list 
      $('#sMake').bind('change', function() { 
       var theSeries = filterByProperty(model, 'makeID', this.value); 
       populateSelect($('#sModel').get(0), $.map(theSeries, function(model) { return { name: model.name, value: model.modelID} })); 
      }); 
     }); 
    </script> 
    </head> 
    <body> 
    Enter values, click submit, and look at the post parameters 
    <form method="get" action="index.php"> 
      <div id="selection"> 
       <select id="sType" name="type_id" style="{width=75px}"></select> 
       <select id="sMake" name="make_id" style="{width=75px}"></select> 
       <select id="sModel" name="model_id" style="{width=75px}"></select> 
      </div> 
      <input type="submit"> 
    </form> 
    </body> 
</html> 

en cuenta que mi solución desplaza la funcionalidad para que Maquillaje Modelo son la segunda y cuadros de texto 3º, y el tipo (nacional, importación, barco, etc.) son el 1er nivel.Obtuve el texto estándar JS en 23 líneas (menos comentarios) conservando un buen formato.

Los datos JSON son muy fáciles de representar a partir de las consultas SQL, que se almacenan en caché en las listas java en init porque el Type-Make-Model rara vez cambia. No uso ningún AJAX dinámico porque eso complica la arquitectura, y tengo una lista relativamente pequeña de valores disponibles, así que simplemente la envío a la solicitud de la página.

"Las soluciones deben ser una simple posible, pero no más simple" - A. Einstein

Cuestiones relacionadas