2008-10-07 13 views
23

Utilizzando le risposte a this question, sono riuscito a compilare una casella di selezione in base alla selezione di un'altra casella di selezione. (I posted my answer here) Estrazione dei dati da una struttura di array creata lato server, archiviata in un file .js e referenziata nella pagina html.Utilizzo di javascript e jquery per popolare caselle di selezione correlate con struttura di matrice

Ora desidero aggiungere una terza casella di selezione. Se avessi 3 set di dati (modello, marca, opzioni) qualcosa di simile (pseudo codice):

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

Es: Se sono stati selezionati Honda, la prossima casella di selezione avrebbe [Accord Civic] e se Accord erano selezionato la prossima casella di selezione avrebbe [Lx Dx]

Come

1) in grado di creare una struttura a matrice per contenere i dati? tale che

2) posso utilizzare il valore da una casella di selezione per fare riferimento ai valori necessari per la successiva casella di selezione

Grazie

EDIT

posso creare quanto segue, ma non riesco a capire i riferimenti in un modo che possa aiutare a popolare una casella di selezione

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 

risposta

45

preferisco struttura di dati in questo modo:

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'] } 
     ]} 
]; 

Dato i tre elenchi di selezione con id: 'maker', 'modello' e 'caratteristiche' li si può manipolare con questo (credo che questo è abbastanza auto esplicativo):

// 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

grazie per l'impegno che mettete nel vostro risposta. Ho provato il tuo codice e ha funzionato, ma non ho il tempo adesso per imparare esattamente come funziona ... ci tornerò più tardi .. ma sto usando la struttura dell'array ... e ora penso di capire come creare questi array. Grazie ancora –

+0

La struttura dati è in realtà un oggetto Javascript. Puoi trovare qui un discreto tutorial JSON: http://www.hunlock.com/blogs/Mastering_JSON_%28_JavaScript_Object_Notation_%29 – BalusC

+1

L'utilizzo di $ .grep e $ .map per questo è solo il colpo dei maestri. Soluzione fantastica, l'ho usato come base per qualcosa di simile e mi sento come un programmatore migliore per questo. Soluzione eccezionale. – hendrixski

1

Potresti dare un'occhiata a here per la selezione della casella. Per quello che vuoi, penso che lo JSON farà il lavoro giusto per te. In ogni caso, se fossi in te, farò in questo modo: Quando cambio prima selezionare, faccio una richiesta Ajax. Con una risposta ajax, popolerò la seconda casella. Lo stesso per la seconda scatola e lì hai la terza casella popolata con i dati giusti.

3

Grazie alla risposta da @Marko Dunic, sono stato in grado di costruire una struttura a matrice (dati) che può essere referenziato per popolare 3 caselle di selezione. Non ho usato il codice di implementazione solo perché non l'ho capito completamente ... funziona come pubblicato. Tornerò su questo codice più tardi mentre imparo jQuery. Il mio codice è pubblicato sotto (ovviamente, il vostro riferimento a jQuery può essere diversa)

<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 per riempire un buco nella mia conoscenza jQuery + JSON. Grazie :) – Zoe

2

Mi è piaciuto molto la soluzione @Marko Dunic, ma non ha soddisfatto le mie esigenze per il fissaggio ID alle opzioni. Una volta collegato gli ID, mi sono reso conto che avrei potuto rendere il codice JS ancora più piccolo e semplice. La mia soluzione è progettata per quando i dati provengono da un database relazionale e i dati di input JSON mantengono la struttura relazionale con chiavi primarie/esterne. Ecco i dati 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> 

Si noti che la mia soluzione sposta la funzionalità in modo che Make-modello sono il 2 ° e 3 ° caselle di testo, e il tipo (interno, l'importazione, barca, ecc) sono il 1 ° livello.Ho ottenuto il boilerplate JS a 23 righe (meno commenti) pur mantenendo una buona formattazione.

I dati JSON sono molto facili da eseguire da query SQL, che vengono memorizzate nella cache in java Lists su init perché il Type-Make-Model raramente cambia. Non uso alcun AJAX dinamico perché questo complica l'architettura e ho una lista relativamente piccola di valori disponibili, quindi la invio alla richiesta della pagina.

"Soluzioni dovrebbe essere una semplice possibile, ma non più semplice" - A. Einstein

Problemi correlati