I have several selects that I populate using JQuery Ajax. Most load fine. There are one or two of these queries however, that in a few rare cases return a LOT of records to the select. I was wondering if the way that I am populating the selects is the most efficient way to do so from client side code.
I omitted some stuff to make the code a litle shorter.
$(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+/)]; });
}
So this just loops around and fills the selects. Is there a better way to do this? Note the alert("success") line fire almost immediately, so the data is coming back fast, but then after that it hangs trying to fill the select.
UPDATE: (3) this is working really well. Although there is some issue. I have onBlur(call function to reload selects) and when the onBlur is activated and the selects re-load, the page just takes FOREVER to load, so long I has to stop it... not sure why?
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);
}
Have you tried creating a jquery object in memory and populating that, and at the end putting it in the DOM?
like this
var vSelect = $('<select/>'); // our virtual select element
and in the each
method use that to append the options
vSelect.append('<option>..</option>');
and at the end append in the DOM the virtual object's html
$(selectId).html( vSelect.html() );
something else that would speed your current code is to keep a reference to the select
element (instead of its id) and append to it directly instead of having jquery find the element in each appending (as you do now)
Update with full code
replace the part inside FilLSelect
ServiceCall(service,
param,
<SNIP>...<SNIP>,
FailedServiceCall);
}
with
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);
}
if you page can bring back the whole data as a string in the format of
option_value:option_text<TAB>option_value:option_text<TAB>option_value:option_text...
then you could do a replace with a regular expression and just put it in the select element.
var options = data.replace( /([\S ]+)(?=:)(:)([\S ]+)/gi, '<option value="$1">$3</option>');
$(selectID).empty().append(options);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With