Due to the number of dropdown boxes I have in the sites that I maintain, I have written a jquery extension that will take a specified URL, make an ajax call to it and use the result to populate the dropdown box. The code had been working, but now when I have multiple dropdown boxes on a page, most, if not all, fail. When examining them in Chrome developer tools, the error is 500 Internal Server Error. However, if I step through the code rather than running it, everything works just as it should. The Javascript is as follows:
(function() {
(function($, window) {
$.extend($.fn, {
loadDropdown: function(selectControl, data) {
var currentOptions, d, i, id, idField, initialBlank, initialText, initialVal, len, objData, opt, text, textField;
if (data) {
objData = data.$values || data;
} else {
return;
}
idField = selectControl.attr('data-id') || selectControl.attr('dd-id') || 'id';
textField = selectControl.attr('data-text') || selectControl.attr('dd-text') || 'name';
initialBlank = selectControl.attr('data-placeholder') || selectControl.attr('dd-placeholder') ? true : false;
initialText = selectControl.attr('data-initial-text') || selectControl.attr('dd-initial-text');
initialVal = selectControl.attr('data-initial-val') || selectControl.attr('dd-initial-val');
currentOptions = [];
if (initialVal) {
currentOptions = initialVal.split(',');
}
selectControl.find('option :selected').each(function() {
return currentOptions.push($(this).val());
});
selectControl.empty();
if (initialBlank) {
opt = $('<option>').text('');
selectControl.append(opt);
}
for (i = 0, len = objData.length; i < len; i++) {
d = objData[i];
id = d[idField];
text = d[textField];
opt = $('<option>', {
value: id
}).text(text);
if ((currentOptions && currentOptions.length > 0) && $.inArray(id.toString(), currentOptions) !== -1) {
opt.attr('selected', 'selected');
}
if (initialText && initialText === text) {
opt.attr('selected', 'selected');
}
selectControl.append(opt);
}
selectControl.trigger('chosen:updated');
selectControl.trigger('dd:loaded');
},
ddbox: function(args) {
var _this, defaults, opts;
_this = $(this);
defaults = $.extend({
url: _this.attr('data-url') || _this.attr('qf-url') || _this.attr('dd-url'),
width: _this.attr('data-width') || _this.attr('qf-width') || _this.attr('dd-width') || '100%',
allow_single_deselect: _this.hasAttr('data-placeholder') || _this.hasAttr('qf-placeholder') || _this.hasAttr('dd-placeholder') || false,
dropdownLoad: function(event, data) {
return $.fn.loadDropdown($(event.currentTarget), data);
},
dropdownLoaded: function(event) {}
}, args);
opts = {
width: defaults.width,
allow_single_deselect: defaults.allow_single_deselect
};
_this.on('dd:load', function(event, data) {
return defaults.dropdownLoad.apply(_this, [event, data]);
});
_this.on('dd:loaded', function(event) {
return defaults.dropdownLoaded.apply(_this, [event]);
});
_this.chosen(opts);
$('#overlay').removeClass('overlay-off').addClass('overlay');
return $.ajax({
method: 'GET',
url: defaults.url,
success: function(html) {
$('#overlay').removeClass('overlay').addClass('overlay-off');
return _this.trigger('dd:load', [html]);
}
});
}
});
return $(document).ready(function() {
return $('select[data-url], select[qf-url], select[dd-url]').each(function() {
return $(this).ddbox();
});
});
})(window.jQuery, window);
}).call(this);
The URLs that it queries are all web APIs that return an id/name pair in JSON format as such:
{"$id":"1","$values":[{"$id":"2","id":1,"name":"None"},{"$id":"3","id":3,"name":"Safety and Hazard Analysis Software and Design Software"},{"$id":"4","id":4,"name":"Safety Management and Administrative Controls Software"},{"$id":"5","id":2,"name":"Safety System Software"}]}
Can someone please tell me what's going on here?
Edit: After the comments below, I changed the ajax calls to synchronous and everything started working correctly. I can't help but think that there's some other way to do this, though.