2010-11-04 12 views
5

Tengo varias selecciones que llene con JQuery Ajax. La mayoría carga bien Sin embargo, hay una o dos de estas consultas que, en unos pocos casos excepcionales, devuelven MUCHOS registros a la selección. Me preguntaba si la forma en que estoy completando los seleccionados es la forma más eficiente de hacerlo desde el código del lado del cliente.most * efficient * manera de poblar seleccionar con Jquery ajax

He omitido algunas cosas para hacer que el código sea un poco más corto.

$(function() { 
    FillAwcDll() 
}); 
function FillAwcDll() { 
FillSelect('poleDdl', 'WebService.asmx/Pole', params, false, null, false); 
} 

function ServiceCall(method, parameters, onSucess, onFailure) { 
    var parms = "{" + (($.isArray(parameters)) ? parameters.join(',') : parameters) + "}"; // to json 
    var timer = setTimeout(tooLong, 100000); 
    $.ajax({ 
     type: "POST", 
     url: appRoot + "/services/" + method, 
     data: parms, 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     success: function (msg) { 
      clearTimeout(timer); 
      alert("success"); 
      if (typeof onSucess == 'function' || typeof onSucess == 'object') 
       onSucess(msg.d); 
     }, 
     error: function (msg, err) { 

      } 
     } 
    }); 

function FillSelect(sel, service, param, hasValue, prompt, propCase) { 
    var selectId = 'select#{0}'.format(sel); 
    if ($(selectId) == null) { 
     alert('Invalid FillSelect ID'); 
     return; 
    } 
    $(selectId + ' option').remove(); 
    $('<option class=\'loading\' value=\'\'>loading...</option>').appendTo(selectId); 
    ServiceCall(service, 
       param, 
       function (data, args) { 
        $(selectId + ' option').remove(); 

        if (prompt != null && prompt.length > 0) { 
         $('<option class=\'selectPrompt\' value=\'\' selected>{0}</option>'.format(prompt)).appendTo(selectId); 
        } 
        $.each(data, (hasValue) 
         ? function (i, v) { 
          $('<option value=\'{0}\'>{1}</option>'.format(v.Key, (propCase) ? v.Value.toProperCase() : v.Value)).appendTo(selectId); 
         } 
         : function (i, v) { 
          $('<option value=\'{0}\'>{1}</option>'.format(v, (propCase) ? v.toProperCase() : v)).appendTo(selectId); 
         }) 

       }, 
       FailedServiceCall); 
       } 

String.prototype.format = function() { 
    var pattern = /\{\d+\}/g; 
    var args = arguments; 
    return this.replace(pattern, function (capture) { return args[capture.match(/\d+/)]; }); 
} 

Así que esto simplemente gira y llena las selecciones. ¿Hay una mejor manera de hacer esto? Tenga en cuenta que la línea de alerta ("éxito") se dispara casi de inmediato, por lo que los datos vuelven rápidamente, pero luego se bloquea al intentar completar la selección.

ACTUALIZACIÓN: (3) esto está funcionando realmente bien. Aunque hay algún problema. Tengo onBlur (función de llamada para volver a cargar selecciones) y cuando el onBlur está activado y las selecciones se vuelven a cargar, la página solo necesita FOREVER para cargar, por lo que tengo que detenerlo ... ¿no estoy seguro de por qué?

ServiceCall(service, 
      param, 
      function (data, args) { 
       var $select = $(selectId); 
       var vSelect = ''; 
       if (prompt != null && prompt.length > 0) { 
        vSelect += '<option class=\'selectPrompt\' value=\'\' selected>{0}</option>'.format(prompt); 
       } 
       if (hasValue) { 
        $.each(data, function (i, v) { 
         vSelect += '<option value=\'{0}\'>{1}</option>'.format(v.Key, (propCase) ? v.Value.toProperCase() : v.Value); 
        }); 
       } 
       else { 
        $.each(data, function (i, v) { 
         vSelect += '<option value=\'{0}\'>{1}</option>'.format(v, (propCase) ? v.toProperCase() : v); 
        }); 
       } 
       $select.html(vSelect); 
       delete vSelect; 
       delete data; 
      }, 
      FailedServiceCall); 
} 
+0

@kralco, es una opción para que los datos devueltos con formato de 'val: Text' uno por línea? –

+0

o 'val: text' ' val: text' .. –

+0

@kralco, en su ejemplo actualizado está agregando toda la información en cada 'option + =' no solo el elemento relevante del bucle .. –

Respuesta

7

¿Has intentado crear un objeto jquery en memoria y poblar eso, y al final ponerlo en el DOM?

como este

var vSelect = $('<select/>'); // our virtual select element 

y en el uso each método que para anexar los options

vSelect.append('<option>..</option>'); 

y al final anexar en el DOM html del objeto virtual

$(selectId).html(vSelect.html()); 

algo más que acelerar su código actual es mantener una referencia al elemento select (en lugar de su ID) y anexar a ella directamente en lugar de tener jQuery encontrar el elemento en cada anexar (como lo hace ahora)


de actualización con código completo

reemplazar la parte interior FilLSelect

ServiceCall(service, 
      param, 
      <SNIP>...<SNIP>, 
      FailedServiceCall); 
      } 

con

ServiceCall(service, 
      param, 
      function (data, args) { 
       var $select = $(selectId); 
       var vSelect = ''; 
       if (prompt != null && prompt.length > 0) { 
        vSelect += '<option class=\'selectPrompt\' value=\'\' selected>{0}</option>'.format(prompt); 
       } 
       if (hasValue) 
       { 
        $.each(data, function (i, v) { 
         vSelect += '<option value=\'{0}\'>{1}</option>'.format(v.Key, (propCase) ? v.Value.toProperCase() : v.Value); 
        }); 
       } 
       else 
       { 
        $.each(data,function (i, v) { 
         vSelect += '<option value=\'{0}\'>{1}</option>'.format(v, (propCase) ? v.toProperCase() : v); 
        }); 
       } 
       $select.html(vSelect); 

      }, 
      FailedServiceCall); 
      } 

si la página puede traer de vuelta los datos enteros como una cadena en el formato de

option_value:option_text<TAB>option_value:option_text<TAB>option_value:option_text... entonces usted podría hacer un reemplazo con una expresión regular y sólo hay que poner en el elemento select.

var options = data.replace(/([\S ]+)(?=:)(:)([\S ]+)/gi, '<option value="$1">$3</option>'); 
$(selectID).empty().append(options); 
+0

Estoy un poco confundido sobre cómo pondría este código en el código actual que tengo. No estoy muy familiarizado con el funcionamiento del código original. – kralco626

+0

@kralco, actualizado con el ejemplo completo de código ... –

+0

¡es increíble!esto funciona en unos 10 segundos, lo cual es mucho mejor que, bueno, lo dejé funcionar durante unos 20 minutos en mi solución original y ¡estaba a mitad de camino de los valores! ¡Muchas gracias! Supongamos que sería codicioso preguntar si había alguna manera de hacerlo aún más eficiente. ¿Algo más que esté pasando que pueda modificarse? – kralco626

1

Aquí está uno genérico donde msg es el objeto de datos JSON devuelto por el servidor.

var options = ""; 

$(msg).each(function() { 
    options += $('<option />').val(yourValue).text(yourDisplayValue); 
}); 


$(selectID).empty().append(options); 

Personalmente, prefiero usar un sistema de plantillas para insertar html desde javascript. Yo uso Microsoft's jQuery Templates. La sintaxis para eso sería simple:

var options = $.tmpl("<option value="${yourValue}">${yourDisplayValue}</option>", msg); 

$(selectID).empty().append(options); 

La elección es suya. :)

+0

ok. Me lo imaginé. Es desafiantemente mejor. (ver editar para preguntar) pero aún demasiado lento. Alguna idea para hacerlo mas rapido? No estoy seguro de lo que está pasando, pero tardó 3.5 minutos en completarse, y no había nada en el cuadro de selección cuando estaba listo. – kralco626

1

Crear un contenedor temporal que no esté unido al dom. Después de llenar el contenedor con las opciones, conecte todos los elementos secundarios a la selección.

var temp = $('<select></select>'); 
$('<option></option>').attr('value', 1).text('First').appendTo(temp); 
$(selectId).children().remove(); 
temp.children().detach().appendTo($(selectId)); 

Tal vez esto también funcionará:

$(selectId).html(temp.html());