I am trying to resort a list of dynamically created SELECT OPTIONS in javascript.
I have no access to the source, otherwise I would change this from the server code.
This is the select:
<select class="text12 width_constrained" name="/web/personalisation/request/DesignConsultationRequestFormHandler.addressItem">
<option value="1|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">1 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="3|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">3 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="5|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">5 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="7|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">7 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="9|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">9 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="11|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">11 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="13|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">13 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="15|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">15 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="17|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">17 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="19|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">19 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="21|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">21 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="23|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">23 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="25|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">25 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="27|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">27 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="2|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">2 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="4|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">4 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="6|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">6 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="8|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">8 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="10|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">10 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="12|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">12 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="14|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">14 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="16|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">16 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="18|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">18 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="20|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">20 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="22|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">22 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="24|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">24 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="26|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">26 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="28|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">28 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
I am currently using the following, but it only sorts by the first character using the natural sort, which does not support alphanumeric...
jQuery('document').ready(function() {
var opts = jQuery('form[name=consultationForm] select option');
console.log("options");
console.log(opts);
var arr = opts.map(function(_, o) {
return {
t: jQuery(o).text(),
v: o.value
};
}).get();
console.log("options post sort");
//arr.sort();
arr.sort(function(o1, o2) {
return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0;
});
console.log(arr);
});
The obvious desired output is to have all the options ordered in numeric value, but also allowing for subsets e.g. 2a, 2b, 2c.
Can anyone help further?
It sounds like what you want is Natural Sort, i found this code sample here: Javascript : natural sort of alphanumerical strings This will give proper sorting for values like 2a, 2b, 2c, as well as values without a street number.
function naturalSorter(as, bs){
var a, b, a1, b1, i= 0, n, L,
rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
if(as=== bs) return 0;
a= as.toLowerCase().match(rx);
b= bs.toLowerCase().match(rx);
L= a.length;
while(i<L){
if(!b[i]) return 1;
a1= a[i],
b1= b[i++];
if(a1!== b1){
n= a1-b1;
if(!isNaN(n)) return n;
return a1>b1? 1:-1;
}
}
return b[i]? -1:0;
}
Then
arr.sort(function(o1, o2) {
return naturalSorter(o1.t, o2.t);
});
I edited TJ's fiddle slightly to give an example: JSFiddle
I believe localeSort
should do what you want if used properly. If, for some reason, you need to implement your own sort comparison, try this:
arr.sort(function(o1, o2) {
return o1.t.split(/(\d+|\D+)/)[1] - o2.t.split(/(\d+|\D+)/)[1]
} );
The split
creates an array of alternating numeric and non-numeric strings (with empty strings between them that we can ignore for this purpose). Element 0 of the array is empty, so element 1 is the first component - the house number, with no extraneous characters that will make the numeric converter treat it as NaN
. The subtraction forces the conversion from string to number, and you're good to go.
That idea generalizes to a full natural sort by examining as much of each string as necessary:
arr.sort(function(o1, o2) {
var a = o1.t.split(/(\d+|\D+)/).filter(function(s){return s!=""});
var b = o2.t.split(/(\d+|\D+)/).filter(function(s){return s!=""});
for (var cmp = 0, i = 0; 0 == cmp && i < a.length && i < b.length; i++) {
var n1 = a[i] - 0, n2 = b[i] - 0;
if (!isNaN(n1) && !isNaN(n2))
cmp = n1 - n2;
else if (a[i] < b[i])
cmp = -1;
else if (a[i] > b[i])
cmp = 1;
}
return cmp;
})
Your strings are probably converted to numbers because they start with a digit. You can try the following sort function:
arr.sort(function(o1, o2) {
return o1.t.localeCompare(o2.t);
});
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare for more information.
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