2009-03-30 15 views
14

Tengo dos < seleccionar> cuadros en un formulario. Al seleccionar un elemento en el primer < seleccione> cuadro se determinará qué debería aparecer en el segundo < seleccione> (Usando Ajax http_request).Forma más rápida de poblar <select> con Javascript

En algunos casos, puede haber un gran número de 500 (adivinar) elementos en la segunda selección y tarda de 5 a 10 segundos en actualizarse en IE. Firefox parece funcionar perfectamente.

Me pregunto si hay una manera más rápida de lograr esto. Actualmente, el servidor crea una cadena que lo pasa al cliente que luego se divide y agrega cada elemento a la selección creando un elemento de opción y luego agregándolo al < select>.

Yo trato de crear todo el elemento seleccionado como una cadena en el servidor y añadir que a la forma, pero por alguna razón no iba a funcionar en Firefox (perdido algo?)

Gracias

Respuesta

2

Configurarlo usando SelectElement.innerHTML sería el más rápido ... pero that FAILS in IE.

yo sepa, usted puede hacer esto en IE, si usted envuelve todas las opciones en un falso <div> una etiqueta o un sistema entero de la .outerHTML de la lista de selección en el IE.

0

Sería de gran ayuda ver su código.

si está creando un elemento <option> y añadiendo que cada iteración, se debe considerar la creación de todos los <option> elementos a la vez, y luego añadiendo todos a la vez.

Por lo tanto (en psuedocode):

// Don't do this: 
for choice in choices: 
    option = new Options(choice) 
    select.append(option) 


// Do this instead 
var options = array() 

for choice in choices: 
    options.append(new Options(choice)) 

for option in options: 
    select.append(option) 

// Or you might try building the select element off-screen and then appending to the DOM 
var options = array() 
var select = new SelectElement() 

for choice in choices: 
    select.append(new Options(choice)) 

dom_element.append(select) 
+0

¿cómo utilizar la matriz de ayuda? aún necesita llamar {n} para agregar a la lista de selección (que es lo que causa el problema de velocidad, ya que el navegador necesita determinar después de cada anexión si el tamaño de la lista necesita actualización) – scunliffe

+0

@scunliffe - la optimización del navegador rara vez se presenta hasta el análisis de complejidad Big-O. Supongo que IE podría retrasar el renderizado de los nuevos elementos de Opción a la pantalla si estuvieran todos conectados al DOM a la vez, lo que debería acelerar las cosas. Solo algo para probar. – Triptych

1

me gustaría crear el conjunto seleccione en el servidor y lo inyecta en la página. Ese enfoque evita las molestas discrepancias del navegador y reduce la complejidad del código del lado del cliente.

Mencionaste que lo intentaste, pero falló en Firefox. Sugeriría perseverar para que funcione, publicando otra pregunta pidiendo ayuda sobre ese tema o editando tu pregunta para mostrarnos lo que hiciste que no funcionó en Firefox.

19

500 elementos no es mucho, incluso para IE. Debes estar haciendo otra cosa para causar el retraso.

Acabo de probar con más de 500 opciones en IE6, IE7, FF2 y FF3 y todas fueron instantáneas. He utilizado este código:

var data = [ 
    { text: 'foo', value: 'bar' }, 
    // ... 
    { text: 'foo', value: 'bar' } 
]; 

var select = document.getElementsByTagName('select')[0]; 
select.options.length = 0; // clear out existing items 
for(var i=0; i < data.length; i++) { 
    var d = data[i]; 
    select.options.add(new Option(d.text, i)) 
} 

Yo sugeriría perfilar el bit de código que es ir a buscar los datos y llenar el menú desplegable. Algo más podría estar ocupando el tiempo. Por ejemplo, compruebe que el código que "divide" el valor de cadena devuelto por el servidor sea nítido (parece que está haciendo su propio análisis personalizado allí).

+5

Um ... ¿no debería ser 'select.options.add (new Option (d.text, d.value))'? – tzot

0

Cuando uso la primera versión de este funciona, pero puede ser muy lento en la actualización de la segunda seleccionar

 
<html> 
<form id='myform' method='post' action='$_SERVER[PHP_SELF]'> 
<table> 
<tr><td><select onselect='CALL_AJAX_AND_UPDATE();'></select></td></tr> 
<tr><td><select id='selectid'></select></td></tr> 
</table> 
</form> 
</html> 

<script type=\"text/javascript\"> 
function UPDATE(updatedata) 
{     
    var itemid = document.getElementById('selectid');    

    var data = updatedata.split('|'); 
    var len = data.length;               

    for(i=0; i < len; i ++) 
    { 
     var opt = document.createElement('option'); 
     opt.text = data[i]; 

     try 
     { 
      itemid.add(opt, null);       
     } 
     catch(ex) 
     { 
      itemid.add(opt);  
     }  
    }           
} 
</script> 

Esta versión funciona en IE, Firefox, pero no parece para publicar los datos del segundo selecciones. ¿Me he perdido algo con esto?

 
<html> 
<form id='myform' method='post' action='$_SERVER[PHP_SELF]'> 
<table> 
<tr><td><select onselect='CALL_AJAX_AND_UPDATE();'></select></td></tr> 
<tr><td><div id='addselect'></div></td></tr> 
</table> 
</form> 
</html> 

<script type=\"text/javascript\"> 
function UPDATE(updatedata) 
{    
    // update data is full select html 
    var itemid = document.getElementById('addselect');    
    itemid.innerHTML = updatedata;               
} 
</script> 
2

El problema con todas estas respuestas con SelectElement.innerHTML es que no se puede hacer este truco con las selecciones. La solución es usar innerHTML en el elemento PARENT del elemento SELECT. Entonces en su código ajax/jquery/whatever cree una cadena que contenga TODO el HTML SELECT, y luego obtenga el titular (un div o span o lo que sea) y configure el innerHTML como la cadena que ha construido.

Deberá aislar el SELECT de la página y darle un elemento padre explícito (span o div) para evitar que otros elementos html sean víctimas cuando destruya/reconstruya el elemento SELECT.

Respuesta corta:

parentselectelement.removeChild(selectelement); 
parentselectelement.innerHTML = "<select ...><options...></select>"; 
1

No se olvide de añadir a document.createDocumentFragment() en primer lugar, antes de añadir que a la instrucción SELECT.

4

El primer código está bien, pero esto funciona mejor para mí:

var data = [ 
    { text: 'uno', value: '1' }, 
    {text: 'dos', value: '2' } 
]; 

var select = document.getElementById('select-choice-1'); 
select.options.length = 0; // clear out existing items 
for (var i = 0; i < data.length; i++) { 
    var d = data[i]; 
    select.options.add(new Option(d.text, d.value)) 
} 
0

me gusta respuestas Kemal Fadillah de la Media Luna frescas y del puesto que tanto su uso:

select.options.add(new Options(name, value)) 

En cuanto al objeto de datos que recomiendan una pequeño pellizco de la siguiente manera:

var data = { 
    'uno': 1, 
    'dos': 2 
}; 

var select = document.getElementById('select-choice-1'); 
select.options.length = 0; // clear out existing items 
for (var i in data) { 
     select.options.add(new Option(i, data[i])); 
} 
0

Si no les importa usar CoffeeScript entonces la siguiente bacalao e llena una lista de selección con datos JSON en un par de líneas.

HTML

<select id="clients"></select> 

CoffeeScript

fillList=($list, url)=> 
    $.getJSON(url) 
    .success((data)-> 
     $list 
     .empty() 
     .append("<option value=\"#{item.Id}\">#{item.Name}</option>" for item in data) 
    ) 

$ -> 
    fillList($('#clients'), '/clients/all') 

Nota: El bucle dentro de la append genera toda la cadena HTML antes de llamar al método append vez. Esto es agradable y eficiente.

Ejemplo JSON

[ 
    {"Id":"1","Name":"Client-1"}, 
    {"Id":"2","Name":"Client-2"} 
] 
Cuestiones relacionadas