The Cause
The root of the problem isn't in jEditable, it's in the fact that the JSON that it's using to create the select dropdown is a single object. JavaScript treats object properties as unsorted. This is the key code in jEditable 1.7.1 (starting at line 492):
/* If it is string assume it is json. */
if (String == data.constructor) {
eval ('var json = ' + data);
} else {
/* Otherwise assume it is a hash already. */
var json = data;
}
for (var key in json) {
// starts looping through the object properties
Normally, that for (var key in json)
should loop through the JSON properties in the order that they're created. Instead, they're looped in numerical ("alphabetical") order.
The Fix
There are many ways to solve this, but the simplest is through an anonymously-authored jEditable plug-in I found on Pastebin through a Google search. Paste this into a new JavaScript file, and load it in your HTML file after jEditable:
<script src="/js/jquery.jeditable.min.js"></script>
<script src="/js/jquery.jeditable.plugins.js"></script>
In addition, the json.php
file must be altered. Instead of returning JSON as an object, like this:
{"0":"Select driver...", "48":"Ashley Solis", "43":"Casey Segal", // etc.
It should return JSON as a linear array that looks like this:
[" Select driver...||0","Ashley Solis||48","Casey Segal||43", // etc.
Note the use of whitespace at the start of the string "Select driver...", which ensures that it will be sorted to the first position. No other JavaScript needs to be changed, provided that json.php
isn't being used anywhere else.
The Plugin
Here's the complete jEditable plugin I found on Pastebin:
// type: select (based on 1.7.1, added feature: sorted options)
$.editable.addInputType("select", {
element: function (settings, original) {
var select = $('<select />');
$(this).append(select);
return (select);
},
content: function (data, settings, original) {
/* If it is string assume it is json. */
if (String == data.constructor) {
eval('var json = ' + data);
} else {
/* Otherwise assume it is a hash already. */
var json = data;
}
var aData = [];
for (var key in json) {
if (!json.hasOwnProperty(key)) {
continue;
}
if ('selected' == key) {
continue;
}
aData.push(json[key] + "||" + key);
}
// Sort
aData.sort();
// Create
for (var key in aData) {
var aDataSplit = aData[key].split("||");
var option = $('<option />').val(aDataSplit[1]).append(aDataSplit[0]);
$('select', this).append(option);
}
/* Loop option again to set selected. IE needed this... */
$('select', this).children().each(function () {
if ($(this).val() == json['selected'] || $(this).text() == $.trim(original.revert)) {
$(this).attr('selected', 'selected');
}
});
}
});