simplify javascript code using regex (getting multiple links to iframes youtube) - javascript

Hi
I have a code which can show youtube videos if there are any links to youtube in the text
like for example the text which has multiple links
http://www.youtube.com/watch?v=-LiPMxFBLZY
testing
http://www.youtube.com/watch?v=Q3-l22b_Qg8&feature=related
example at:- pradyut.dyndns.org
the question has three parts which can be done using regex..
1 > getting the urls one by one for checking
2>checking if they youtube urls
3>converting the urls to youtube objects or iframes...
the second and the third are almost done with regex .. any improvements are welcome...
the most cumbersome is part one of the code which is to be done using regex...
this text i m forwarding to the function...
function to_youtubelink(text)
{
if ( text.indexOf ('<') > 0 || text.indexOf ('"') > 0 || text.indexOf ('>') > 0 )
return text;
else
{
var obj_text = new Array();
var oi = 0;
while(text.indexOf('http://') >=0)
{ //getting the paths
var si = text.indexOf('http://');
var gr = text.indexOf('\n', si);
var sp = text.indexOf(' ', si);
var ei;
if ( gr > 0 || sp > 0 )
{
if ( gr >0 && sp > 0 )
{
if ( gr < sp )
{
ei = gr ;
}
else
{
ei = sp ;
}
}
else if ( gr > 0)
{
ei = gr;
}
else
{
ei = sp;
}
}
else
{
ei = text.length;
}
var it = text.substring(si,ei);
if ( it.indexOf('"') > 0)
{
it.substring(0, it.indexOf('"') );
}
if(ei < 0)
ei = text.length;
else
ei = text.indexOf(' ', si) ;
obj_text[oi] = it;
text = text.replace( it, '[link_service]');
oi++;
}
var ob_text = new Array();
var ob =0;
for (oi=0; oi<obj_text.length; oi++)
{
if ( is_youtubelink( obj_text[oi] ) )
{
ob_text[ob] = to_utubelink(obj_text[oi]);
ob++;
}
}
oi = 0;
while ( text.indexOf('[link_service]') >=0 )
{
text = text.replace( '[link_service]', obj_text[oi]);
oi ++;
}
for (ob=0; ob<ob_text.length; ob++)
{
text = text +"\n\n" + ob_text[ob];
}
return text;
}
}
function is_youtubelink(text)
{
var matches = text.match(/http:\/\/(?:www\.)?youtube.*watch\?v=([a-zA-Z0-9\-_]+)/);
if (matches) {
return true;
} else {
return false;
}
}
function to_utubelink(text)
{
var video_id = text.split('v=')[1];
var ampersandPosition = video_id.indexOf('&');
if(ampersandPosition != -1)
{
video_id = video_id.substring(0, ampersandPosition);
}
text = "<iframe title=\"YouTube video player\" class=\"youtube-player\" type=\"text/html\" width=\"425\" height=\"350\" src=\"http://www.youtube.com/embed/" + video_id + "\" frameborder=\"0\"></iframe>"
return text;
}
now i m getting the output properly...
but i was thinking if the code could be done better and simplified using regex
...especially getting the urls part...
thanks

Try something like this:
/**
* Extracts a youtube id from a string
*
* #param string
*
* #return mixed
*/
function youtubeIDextract(text) {
var replace = "$1";
if (!text.match(/http:\/\/www\.youtube[^"]+/))
return false;
if (text.match(/^[^v]+v.([^&^=^\/]{11}).*/))
return text.replace(/^[^v]+v.([^&^=^\/]{11}).*/,replace);
else if (text.match(/^[^v]+\?v=([^&^=^\/]{11}).*/))
return text.replace(/^[^v]+\?v=([^&^=^\/]{11}).*/,replace);
else
return false;
}
A working example can be seen here: http://jsfiddle.net/6PRVp/2/
If you want to simply check if there is a youtube link in there somewhere, do this:
if (youtubeIDextract(text)) {...}
Notice that this also checks if there are 11 characters in the video id (without that, it would be a malformed youtube link).

Try this one:
function to_youtubelink(a) {
if (a.indexOf("<") > 0 || a.indexOf('"') > 0 || a.indexOf(">") > 0) return a;
var b = Array(),
c = 0;
while (a.indexOf("http://") >= 0) {
var g, d = a.indexOf("http://"),
e = a.indexOf("\n", d),
f = a.indexOf(" ", d);
g = e > 0 || f > 0 ? e > 0 && f > 0 ? f > e ? e : f : e > 0 ? e : f : a.length;
var h = a.substring(d, g);
h.indexOf('"') > 0 && h.substring(0, h.indexOf('"')), g = 0 > g ? a.length : a.indexOf(" ", d), b[c] = h, a = a.replace(h, "[link_service]"), c++
}
var i = Array(),
j = 0;
for (c = 0; b.length > c; c++) is_youtubelink(b[c]) && (i[j] = to_utubelink(b[c]), j++);
c = 0;
while (a.indexOf("[link_service]") >= 0) a = a.replace("[link_service]", b[c]), c++;
for (j = 0; i.length > j; j++) a = a + "\n\n" + i[j];
return a
}
function is_youtubelink(a) {
var b = a.match(/http:\/\/(?:www\.)?youtube.*watch\?v=([a-zA-Z0-9\-_]+)/);
return b ? !0 : !1
}
function to_utubelink(a) {
var b = a.split("v=")[1],
c = b.indexOf("&");
return c != -1 && (b = b.substring(0, c)), a = '<iframe title="YouTube video player" class="youtube-player" type="text/html" width="425" height="350" src="http://www.youtube.com/embed/' + b + '" frameborder="0"></iframe>'
}

Related

HTML input event called twice

I have a problem with html/javascript code, the code should format numbers taken from keyboard (1 -> 0.01, 2-> 0.12, 3->1.23 ... 6->1,234.56).
It seems that the result of substring and substr is appended twice. In debug it works fine but without debug it doesn't. (1 -> 0.011, 2->1.122, 3->112.233)
It works the same for delete or backspace.
Here is the code:
formatElementAmount = function(f, d) {
d = d.replace(/\./g, '');
d = d.replace(/\,/g, '');
d = parseFloat(d);
d = d + '';
var c = document.getElementById((f.target || f.srcElement).id);
var b = '0123456789';
var a = f.which || f.keyCode;
if (a == 13) { // keycode 13 = enter >
return false;
}
if (a == 9) { // keycode 9 == tab
return true;
}
if (a == 8 || a == 46) { // keyCode 8 == backspace, 46 == delete
if (d.length > 0) {
d = d.substring(0, d.length - 1);
c.value = '';
}
c.value = format(d);
return false;
}
if (c.value.length > 12) {
c.value = '';
c.value = format(d);
return false;
}
if (a >= 96 && a <= 105) { // 96 = numbpad 0, 105 = numpad 9
a = a - 48;
}
key = String.fromCharCode(a);
if (b.indexOf(key) == -1) {
return false;
}
if ((d.length == 0) && (key == '0')) {} else {
d = d + key;
}
c.value = '';
c.value = format(d);
return false;
};
format = function(f) {
if (f.length == 0) {
return '0.00';
}
if (f.length == 1) {
return '0.0' + f;
}
if (f.length == 2) {
return '0.' + f;
}
var a, b, c, d, e;
if (f.length > 2) {
a = '';
for (c = 0, d = f.length - 3; d >= 0; d--) {
if (c == 3) {
a += ',';
c = 0;
}
a += f.charAt(d);
c++;
}
b = '';
len2 = a.length;
for (d = len2 - 1; d >= 0; d--) {
b += a.charAt(d);
}
e = f.substr(f.length - 2);
b += '.' + e;
}
return b;
};
<input id="paymentForm" name="paymentForm" type="text" value="0.00" onkeydown="if(this.value =='') this.value ='0.00';
if (!formatElementAmount(event, this.value)) {
event.stopPropagation();
}"></input>
The problem with your current code is it doesn't prevent the default action of the keyDown event:
if (!formatElementAmount(event, this.value)) {
event.stopPropagation();
event.preventDefault();
}
First of all your should stop using event.stopPropagation() - it doesn't stop default event. Also don't use event.preventDefault() which is not recommended. Instead use return false which disable default event effect and stop insert chars from keyboard.
Also use keypress event instead of keydown (I can't explain why it works because I don't know).
<input id="paymentForm" name="paymentForm" type="text" value="0.00" onkeypress="if(this.value =='') this.value ='0.00';
if (!formatElementAmount(event, this.value)) {
return false;
}"></input>
I tested this fix in Firefox, IE10 & Edge which i actually have on my computer.

Canvas not graphing exponents or multiple lines correctly

I have a program that graphs a line on an HTML canvas with JavaScript. The HTML contains a 500px by 500px canvas and a div with the id "LineBoxHolder" that has a certain number of items inside, which are from zero to infinity select elements of the class .equation, and for each one, depending on the selected value, a number of inputs of the type number and the class .eqNum. Here's a chart to clarify that part:
selected value | number of "number" inputs added
------------------------------------------------
number | 1
linear | 2
quadratic | 3
power | 2
exponential | 2
For example, if you have 3 select boxes, 1 with "linear" selected and 2 with "quadratic" selected, you get a total of 8 ".eqNum" inputs. Sorry if I'm not making much sense, I'ts midnight and I've had lots of homework lately (8th grade), but if this is too confusing I'll clean it up and add a bounty tomorrow. Anyways, here's the JavaScript code simplified down to what I think is the most important part. My problem, by the way, is that I can't graph multiple lines, and all types of lines except "number" and "linear" show up oddly.
function DrawCurrent()
{
//Set up environment
var cnvs = document.getElementById("cnvs");
cnvs.height = 500;
cnvs.width = 500;
var cont = cnvs.getContext("2d");
var imdt = cont.getImageData(0,0,500,500);
//Get the rest of the dimension and color values that need to be tested
var canvasXmin = document.getElementById("CanvasX-min").value;
var canvasYmin = document.getElementById("CanvasY-min").value;
var canvasXmax = document.getElementById("CanvasX-max").value;
var canvasYmax = document.getElementById("CanvasY-max").value;
var x_minList = document.querySelectorAll("#LineBoxHolder .x-min");
var y_minList = document.querySelectorAll("#LineBoxHolder .y-min");
var x_maxList = document.querySelectorAll("#LineBoxHolder .x-max");
var y_maxList = document.querySelectorAll("#LineBoxHolder .y-max");
var rgbaValue = document.querySelectorAll("#LineBoxHolder .lineColor");
var xyList = document.querySelectorAll("#LineBoxHolder .xOry");
var eqList = document.querySelectorAll("#LineBoxHolder .equation");
var numList = document.querySelectorAll("#LineBoxHolder .eqNum");
//Create variables to be used in graphing (Not all are nessecary, but they make for less repetitive and pointless coding)
var pseudoBase = 0;
var baseList = [];
var pseudoDependent = 0;
var pseudoDependentList = [];
var actualDependentList = [];
var dependentActual = 0;
var xMin = 0;
var xMax = 0;
var yMin = 0;
var yMax = 0;
var eqtn = "";
var numListNum = 0;
var a = 0;
var b = 0;
var c = 0;
var index = 0;
//Graph the lines
for (var z9 = 0 ; z9 < eqList.length/*Eqlist has 1 value for each line, so its length is equal to the number of lines*/ ; z9++ )
{
//Set values
xMin = x_minList[z9].value*1;
xMax = x_maxList[z9].value*1;
yMin = y_minList[z9].value*1;
yMax = y_maxList[z9].value*1;
eqtn = eqList[z9].value;
for ( var z10 = 0 ; z10 < 500 ; z10++ )
{
pseudoBase = canvasXmin*1 + (((Math.abs( canvasXmax - canvasXmin )) * z10)/500);
if ( pseudoBase >= xMin && pseudoBase <= xMax )
{
baseList.push( pseudoBase );
}
else
{
baseList.push( NaN );
};
}
if ( eqtn == "number" )
{
a = numList[numListNum].value;
numListNum++;
for ( var z12 = 0 ; z12 < 500 ; z12++)
{
pseudoDependent = a;
if ( pseudoDependent >= yMin && pseudoDependent <= yMax)
{
pseudoDependentList.push(pseudoDependent);
}
else
{
pseudoDependentList.push( NaN);
};
}
}
if ( eqtn == "linear" )
{
a = numList[numListNum].value;
numListNum++;
b = numList[numListNum].value;
numListNum++;
for ( var z12 = 0 ; z12 < 500 ; z12++)
{
pseudoDependent = (a*baseList[z12])*1 + b*1;
if ( pseudoDependent >= yMin && pseudoDependent <= yMax )
{
pseudoDependentList.push(pseudoDependent);
}
else
{
pseudoDependentList.push(NaN);
};
}
}
if ( eqtn == "quadratic" )
{
a = numList[numListNum].value;
numListNum++;
b = numList[numListNum].value;
numListNum++;
c = numList[numListNum].value;
numListNum++;
for ( var z12 = 0 ; z12 < 500 ; z12++)
{
pseudoDependent = (a* Math.pow(baseList[z12],2))+(b*1*baseList[z12])+c*1;
if ( pseudoDependent >= yMin && pseudoDependent <= yMax )
{
pseudoDependentList.push(pseudoDependent);
}
else
{
pseudoDependentList.push(NaN);
};
}
}
if ( eqtn == "power" )
{
a = numList[numListNum].value;
numListNum++;
b = numList[numListNum].value;
numListNum++;
for ( var z12 = 0 ; z12 < 500 ; z12++)
{
pseudoDependent = (a* Math.pow(baseList[z12],b));
if ( pseudoDependent >= yMin && pseudoDependent <= yMax )
{
pseudoDependentList.push(pseudoDependent);
}
else
{
pseudoDependentList.push(NaN);
};
}
}
if ( eqtn == "exponential" )
{
a = numList[numListNum].value;
numListNum++;
b = numList[numListNum].value;
numListNum++;
for ( var z12 = 0 ; z12 < 500 ; z12++)
{
pseudoDependent = (a* Math.pow(b,baseList[z12]));
if ( pseudoDependent >= yMin && pseudoDependent <= yMax )
{
pseudoDependentList.push(pseudoDependent);
}
else
{
pseudoDependentList.push(NaN);
};
}
}
for ( var z13 = 0 ; z13 < 500 ; z13++ )
{
dependentActual = 500-(((pseudoDependentList[z13]*1 + (0 - canvasYmin*1))*500)/Math.abs(canvasYmax-canvasYmin));
actualDependentList.push(dependentActual);
}
var storedindex = 0;
var currentIndex = 0;
for ( var z14 = 0 ; z14 < 500 ; z14++)
{
currentIndex = parseInt(Math.round((actualDependentList[z14]*2000) + (4*z14)));
console.log(currentIndex + " " + actualDependentList[z14] + " " + z14);
if (currentIndex >= 0 && currentIndex <= 999997 && pseudoDependentList[z14] != NaN && baseList[z14] != NaN)
{
environment.data[currentIndex] = newColorList[z9];
environment.data[currentIndex + 1] = newColorList[z9+1];
environment.data[currentIndex + 2] = newColorList[z9+2];
environment.data[currentIndex + 3] = 255;
}
if ( z14 > 0 && currentIndex < storedY && pseudoDependentList[z14] != NaN && baseList[z14] != NaN)
{
for ( var z20 = 1 ; z20 < Math.floor((storedY-currentIndex)/2000) ; z20++ )
{
index = currentIndex + (z20*2000);
if ( index < 999997 && index > 0 )
{
environment.data[index] = newColorList[z9];
environment.data[index + 1 ] = newColorList[z9+1];
environment.data[index + 2 ] = newColorList[z9+2];
environment.data[index + 3 ] = 255;
}
}
}
if ( z14 > 0 && currentIndex > storedY && pseudoDependentList[z14] != NaN && baseList[z14] != NaN )
{
for ( var z15 = 0 ; z15 < Math.floor((currentIndex-storedY)/2000) ; z15++ )
{
index = currentIndex + (z15*2000);
if ( index < 999997 && index > 0 )
{
environment.data[index] = newColorList[z9];
environment.data[index + 1 ] = newColorList[z9+1];
environment.data[index + 2 ] = newColorList[z9+2];
environment.data[index + 3 ] = 255;
}
}
}
storedY = currentIndex;
}
}
pixelDotter.putImageData( environment , 0 , 0 );
}
Also here's some sample HTML in case I was confusing:
<body onload = drawCurrent()>
<canvas id = "cnvs" height = "500px" width = "500px">
</canvas>
<div id = 'LineBoxHolder'>
<select class = "equation">
<option value = 'number'>A</option>
<option value = 'linear' selected = 'selected'>B</option>
<option value = 'quadratic'>C</option>
<option value = 'power'>D</option>
<option value = 'exponential'>E</option>
</select>
<!--Linear is selected so there are 2 number inputs-->
<input type = 'number' class = "eqNum">
<input type = 'number' class = "eqNum">
<select class = "equation">
<option value = 'number'>A</option>
<option value = 'linear' >B</option>
<option value = 'quadratic' selected = 'selected'>C</option>
<option value = 'power'>D</option>
<option value = 'exponential'>E</option>
</select>
<!-- Quadratic is selected so there are 23 number inputs-->
<input type = 'number' class = "eqNum">
<input type = 'number' class = "eqNum">
<input type = 'number' class = "eqNum">
</div>
Last quick note, JavaScript code assumes theres at least 1 line and that all the values it tries to get from html exist somewhere and are valid.

Sorting elements with the same class but different content inside [duplicate]

is there a quick way to sort the items of a select element?
Or I have to resort to writing javascript?
Please any ideas.
<select size="4" name="lstALL" multiple="multiple" id="lstALL" tabindex="12" style="font-size:XX-Small;height:95%;width:100%;">
<option value="0"> XXX</option>
<option value="1203">ABC</option>
<option value="1013">MMM</option>
</select>
This will do the trick. Just pass it your select element a la: document.getElementById('lstALL') when you need your list sorted.
function sortSelect(selElem) {
var tmpAry = new Array();
for (var i=0;i<selElem.options.length;i++) {
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
tmpAry.sort();
while (selElem.options.length > 0) {
selElem.options[0] = null;
}
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
}
return;
}
This solution worked very nicely for me using jquery, thought I'd cross reference it here as I found this page before the other one. Someone else might do the same.
$("#id").html($("#id option").sort(function (a, b) {
return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
}))
from Sorting dropdown list using Javascript
Vanilla JS es6 Localization Options Sorting Example
const optionNodes = Array.from(selectNode.children);
const comparator = new Intl.Collator(lang.slice(0, 2)).compare;
optionNodes.sort((a, b) => comparator(a.textContent, b.textContent));
optionNodes.forEach((option) => selectNode.appendChild(option));
My use case was to localize a country select dropdown with locale aware sorting. This was used on 250 + options and was very performant ~10ms on my machine.
Working with the answers provided by Marco Lazzeri and Terre Porter (vote them up if this answer is useful), I came up with a slightly different solution that preserves the selected value (probably doesn't preserve event handlers or attached data, though) using jQuery.
// save the selected value for sorting
var v = jQuery("#id").val();
// sort the options and select the value that was saved
j$("#id")
.html(j$("#id option").sort(function(a,b){
return a.text == b.text ? 0 : a.text < b.text ? -1 : 1;}))
.val(v);
From the W3C FAQ:
Although many programming languages have devices like drop-down boxes that have the capability of sorting a list of items before displaying them as part of their functionality, the HTML <select> function has no such capabilities. It lists the <options> in the order received.
You'd have to sort them by hand for a static HTML document, or resort to Javascript or some other programmatic sort for a dynamic document.
Another option:
function sortSelect(elem) {
var tmpAry = [];
// Retain selected value before sorting
var selectedValue = elem[elem.selectedIndex].value;
// Grab all existing entries
for (var i=0;i<elem.options.length;i++) tmpAry.push(elem.options[i]);
// Sort array by text attribute
tmpAry.sort(function(a,b){ return (a.text < b.text)?-1:1; });
// Wipe out existing elements
while (elem.options.length > 0) elem.options[0] = null;
// Restore sorted elements
var newSelectedIndex = 0;
for (var i=0;i<tmpAry.length;i++) {
elem.options[i] = tmpAry[i];
if(elem.options[i].value == selectedValue) newSelectedIndex = i;
}
elem.selectedIndex = newSelectedIndex; // Set new selected index after sorting
return;
}
This is a a recompilation of my 3 favorite answers on this board:
jOk's best and simplest answer.
Terry Porter's easy jQuery method.
SmokeyPHP's configurable function.
The results are an easy to use, and easily configurable function.
First argument can be a select object, the ID of a select object, or an array with at least 2 dimensions.
Second argument is optional. Defaults to sorting by option text, index 0. Can be passed any other index so sort on that. Can be passed 1, or the text "value", to sort by value.
Sort by text examples (all would sort by text):
sortSelect('select_object_id');
sortSelect('select_object_id', 0);
sortSelect(selectObject);
sortSelect(selectObject, 0);
Sort by value (all would sort by value):
sortSelect('select_object_id', 'value');
sortSelect('select_object_id', 1);
sortSelect(selectObject, 1);
Sort any array by another index:
var myArray = [
['ignored0', 'ignored1', 'Z-sortme2'],
['ignored0', 'ignored1', 'A-sortme2'],
['ignored0', 'ignored1', 'C-sortme2'],
];
sortSelect(myArray,2);
This last one will sort the array by index-2, the sortme's.
Main sort function
function sortSelect(selElem, sortVal) {
// Checks for an object or string. Uses string as ID.
switch(typeof selElem) {
case "string":
selElem = document.getElementById(selElem);
break;
case "object":
if(selElem==null) return false;
break;
default:
return false;
}
// Builds the options list.
var tmpAry = new Array();
for (var i=0;i<selElem.options.length;i++) {
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
// allows sortVal to be optional, defaults to text.
switch(sortVal) {
case "value": // sort by value
sortVal = 1;
break;
default: // sort by text
sortVal = 0;
}
tmpAry.sort(function(a, b) {
return a[sortVal] == b[sortVal] ? 0 : a[sortVal] < b[sortVal] ? -1 : 1;
});
// removes all options from the select.
while (selElem.options.length > 0) {
selElem.options[0] = null;
}
// recreates all options with the new order.
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
}
return true;
}
I had the same problem. Here's the jQuery solution I came up with:
var options = jQuery.makeArray(optionElements).
sort(function(a,b) {
return (a.innerHTML > b.innerHTML) ? 1 : -1;
});
selectElement.html(options);
I had a similar problem, except I wanted the selected items to show up on top, and I didn't want to clear which items were selected (multi-select list). Mine is jQuery based...
function SortMultiSelect_SelectedTop(slt) {
var options =
$(slt).find("option").sort(function (a, b) {
if (a.selected && !b.selected) return -1;
if (!a.selected && b.selected) return 1;
if (a.text < b.text) return -1;
if (a.text > b.text) return 1;
return 0;
});
$(slt).empty().append(options).scrollTop(0);
}
Without selected on top, it would look like this.
function SortMultiSelect(slt) {
var options =
$(slt).find("option").sort(function (a, b) {
if (a.text < b.text) return -1;
if (a.text > b.text) return 1;
return 0;
});
$(slt).empty().append(options).scrollTop(0);
}
Yes DOK has the right answer ... either pre-sort the results before you write the HTML (assuming it's dynamic and you are responsible for the output), or you write javascript.
The Javascript Sort method will be your friend here. Simply pull the values out of the select list, then sort it, and put them back :-)
Í think this is a better option (I use #Matty's code and improved!):
function sortSelect(selElem, bCase) {
var tmpAry = new Array();
bCase = (bCase ? true : false);
for (var i=0;i<selElem.options.length;i++) {
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
if (bCase)
tmpAry.sort(function (a, b) {
var ret = 0;
var iPos = 0;
while (ret == 0 && iPos < a.length && iPos < b.length)
{
ret = (String(a).toLowerCase().charCodeAt(iPos) - String(b).toLowerCase().charCodeAt(iPos));
iPos ++;
}
if (ret == 0)
{
ret = (String(a).length - String(b).length);
}
return ret;
});
else
tmpAry.sort();
while (selElem.options.length > 0) {
selElem.options[0] = null;
}
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
}
return;
}
I used this bubble sort because I wasnt able to order them by the .value in the options array and it was a number. This way I got them properly ordered. I hope it's useful to you too.
function sortSelect(selElem) {
for (var i=0; i<(selElem.options.length-1); i++)
for (var j=i+1; j<selElem.options.length; j++)
if (parseInt(selElem.options[j].value) < parseInt(selElem.options[i].value)) {
var dummy = new Option(selElem.options[i].text, selElem.options[i].value);
selElem.options[i] = new Option(selElem.options[j].text, selElem.options[j].value);
selElem.options[j] = dummy;
}
}
I've quickly thrown together one that allows choice of direction ("asc" or "desc"), whether the comparison should be done on the option value (true or false) and whether or not leading and trailing whitespace should be trimmed before comparison (boolean).
The benefit of this method, is that the selected choice is kept, and all other special properties/triggers should also be kept.
function sortOpts(select,dir,value,trim)
{
value = typeof value == 'boolean' ? value : false;
dir = ['asc','desc'].indexOf(dir) > -1 ? dir : 'asc';
trim = typeof trim == 'boolean' ? trim : true;
if(!select) return false;
var opts = select.getElementsByTagName('option');
var options = [];
for(var i in opts)
{
if(parseInt(i)==i)
{
if(trim)
{
opts[i].innerHTML = opts[i].innerHTML.replace(/^\s*(.*)\s*$/,'$1');
opts[i].value = opts[i].value.replace(/^\s*(.*)\s*$/,'$1');
}
options.push(opts[i]);
}
}
options.sort(value ? sortOpts.sortVals : sortOpts.sortText);
if(dir == 'desc') options.reverse();
options.reverse();
for(var i in options)
{
select.insertBefore(options[i],select.getElementsByTagName('option')[0]);
}
}
sortOpts.sortText = function(a,b) {
return a.innerHTML > b.innerHTML ? 1 : -1;
}
sortOpts.sortVals = function(a,b) {
return a.value > b.value ? 1 : -1;
}
Inspired by #Terre Porter's answer, I think this one is very simple to implement (using jQuery)
var $options = jQuery("#my-dropdownlist-id > option");
// or jQuery("#my-dropdownlist-id").find("option")
$options.sort(function(a, b) {
return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
})
But, for Alpha/Numeric dropdown lists :
Inspired by : https://stackoverflow.com/a/4340339/1598891
var $options = jQuery(dropDownList).find("option");
var reAlpha = /[^a-zA-Z]/g;
var reNumeric = /[^0-9]/g;
$options.sort(function AlphaNumericSort($a,$b) {
var a = $a.text;
var b = $b.text;
var aAlpha = a.replace(reAlpha, "");
var bAlpha = b.replace(reAlpha, "");
if(aAlpha === bAlpha) {
var aNumeric = parseInt(a.replace(reNumeric, ""), 10);
var bNumeric = parseInt(b.replace(reNumeric, ""), 10);
return aNumeric === bNumeric ? 0 : aNumeric > bNumeric ? 1 : -1;
} else {
return aAlpha > bAlpha ? 1 : -1;
}
})
Hope it will help
function call() {
var x = document.getElementById("mySelect");
var optionVal = new Array();
for (i = 0; i < x.length; i++) {
optionVal.push(x.options[i].text);
}
for (i = x.length; i >= 0; i--) {
x.remove(i);
}
optionVal.sort();
for (var i = 0; i < optionVal.length; i++) {
var opt = optionVal[i];
var el = document.createElement("option");
el.textContent = opt;
el.value = opt;
x.appendChild(el);
}
}
The idea is to pullout all the elements of the selectbox into an array , delete the selectbox values to avoid overriding, sort the array and then push back the sorted array into the select box
Not quite as pretty as the JQuery example by Marco but with prototype (i may be missing a more elegant solution) it would be:
function sort_select(select) {
var options = $A(select.options).sortBy(function(o) { return o.innerHTML });
select.innerHTML = "";
options.each(function(o) { select.insert(o); } );
}
And then just pass it a select element:
sort_select( $('category-select') );
Just another way to do it with jQuery:
// sorting;
var selectElm = $("select"),
selectSorted = selectElm.find("option").toArray().sort(function (a, b) {
return (a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase()) ? 1 : -1;
});
selectElm.empty();
$.each(selectSorted, function (key, value) {
selectElm.append(value);
});
Try this...hopefully it will offer you a solution:
function sortlist_name()
{
var lb = document.getElementById('mylist');
arrTexts = new Array();
newTexts = new Array();
txt = new Array();
newArray =new Array();
for(i=0; i<lb.length; i++)
{
arrTexts[i] = lb.options[i].text;
}
for(i=0;i<arrTexts.length; i++)
{
str = arrTexts[i].split(" -> ");
newTexts[i] = str[1]+' -> '+str[0];
}
newTexts.sort();
for(i=0;i<newTexts.length; i++)
{
txt = newTexts[i].split(' -> ');
newArray[i] = txt[1]+' -> '+txt[0];
}
for(i=0; i<lb.length; i++)
{
lb.options[i].text = newArray[i];
lb.options[i].value = newArray[i];
}
}
/***********revrse by name******/
function sortreverse_name()
{
var lb = document.getElementById('mylist');
arrTexts = new Array();
newTexts = new Array();
txt = new Array();
newArray =new Array();
for(i=0; i<lb.length; i++)
{
arrTexts[i] = lb.options[i].text;
}
for(i=0;i<arrTexts.length; i++)
{
str = arrTexts[i].split(" -> ");
newTexts[i] = str[1]+' -> '+str[0];
}
newTexts.reverse();
for(i=0;i<newTexts.length; i++)
{
txt = newTexts[i].split(' -> ');
newArray[i] = txt[1]+' -> '+txt[0];
}
for(i=0; i<lb.length; i++)
{
lb.options[i].text = newArray[i];
lb.options[i].value = newArray[i];
}
}
function sortlist_id() {
var lb = document.getElementById('mylist');
arrTexts = new Array();
for(i=0; i<lb.length; i++) {
arrTexts[i] = lb.options[i].text;
}
arrTexts.sort();
for(i=0; i<lb.length; i++) {
lb.options[i].text = arrTexts[i];
lb.options[i].value = arrTexts[i];
}
}
/***********revrse by id******/
function sortreverse_id() {
var lb = document.getElementById('mylist');
arrTexts = new Array();
for(i=0; i<lb.length; i++) {
arrTexts[i] = lb.options[i].text;
}
arrTexts.reverse();
for(i=0; i<lb.length; i++) {
lb.options[i].text = arrTexts[i];
lb.options[i].value = arrTexts[i];
}
}
</script>
ID ▲ ▼ | Name ▲ ▼<br/>
<select name=mylist id=mylist size=8 style='width:150px'>
<option value="bill">4 -> Bill</option>
<option value="carl">5 -> Carl</option>
<option value="Anton">1 -> Anton</option>
<option value="mike">2 -> Mike</option>
<option value="peter">3 -> Peter</option>
</select>
<br>
function sortItems(c) {
var options = c.options;
Array.prototype.sort.call(options, function (a, b) {
var aText = a.text.toLowerCase();
var bText = b.text.toLowerCase();
if (aText < bText) {
return -1;
} else if (aText > bText) {
return 1;
} else {
return 0;
}
});
}
sortItems(document.getElementById('lstALL'));
For those who are looking to sort whether or not there are optgroup :
/**
* Sorting options
* and optgroups
*
* #param selElem select element
* #param optionBeforeGroup ?bool if null ignores, if true option appear before group else option appear after group
*/
function sortSelect(selElem, optionBeforeGroup = null) {
let initialValue = selElem.tagName === "SELECT" ? selElem.value : null;
let allChildrens = Array.prototype.slice.call(selElem.childNodes);
let childrens = [];
for (let i = 0; i < allChildrens.length; i++) {
if (allChildrens[i].parentNode === selElem && ["OPTGROUP", "OPTION"].includes(allChildrens[i].tagName||"")) {
if (allChildrens[i].tagName == "OPTGROUP") {
sortSelect(allChildrens[i]);
}
childrens.push(allChildrens[i]);
}
}
childrens.sort(function(a, b){
let x = a.tagName == "OPTGROUP" ? a.getAttribute("label") : a.innerHTML;
let y = b.tagName == "OPTGROUP" ? b.getAttribute("label") : b.innerHTML;
x = typeof x === "undefined" || x === null ? "" : (x+"");
y = typeof y === "undefined" || y === null ? "" : (y+"");
if (optionBeforeGroup === null) {
if (x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
if (x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
} else if (optionBeforeGroup === true) {
if ((a.tagName == "OPTION" && b.tagName == "OPTGROUP") || x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
if ((a.tagName == "OPTGROUP" && b.tagName == "OPTION") || x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
} else if (optionBeforeGroup === false) {
if ((a.tagName == "OPTGROUP" && b.tagName == "OPTION") || x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
if ((a.tagName == "OPTION" && b.tagName == "OPTGROUP") || x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
}
return 0;
});
if (optionBeforeGroup !== null) {
childrens.sort(function(a, b){
if (optionBeforeGroup === true) {
if (a.tagName == "OPTION" && b.tagName == "OPTGROUP") {return -1;}
if (a.tagName == "OPTGROUP" && b.tagName == "OPTION") {return 1;}
} else {
if (a.tagName == "OPTGROUP" && b.tagName == "OPTION") {return -1;}
if (a.tagName == "OPTION" && b.tagName == "OPTGROUP") {return 1;}
}
return 0;
});
}
selElem.innerHTML = "";
for (let i = 0; i < childrens.length; i++) {
selElem.appendChild(childrens[i]);
}
if (selElem.tagName === "SELECT") {
selElem.value = initialValue;
}
}
I think my function is more general for strings or numbers and does not sort the first element if it could mean All.
/** Check if a string can be parsed as a number. */
function isNumber(n) { return !isNaN(parseFloat(n)) && !isNaN(n - 0) };
/** Sort options of HTML elements. */
function sortOptions(selectElement, exceptFirstOpt=false) {
// List of options.
var options = selectElement.options;
// If empty list, do nothing.
if(!options || options.length==0) return;
// Array.
var optionsArray = [];
for (var i = (exceptFirstOpt ? 1 : 0); i < options.length; i++)
optionsArray.push(options[i]);
// Sort.
optionsArray = optionsArray.sort(function (a, b) {
let v1 = a.innerHTML.toLowerCase();
let v2 = b.innerHTML.toLowerCase();
if((v1==undefined || v1 == '') && (v2==undefined || v2 == ''))
return 0;
else if(v1==undefined || v1.trim() == '') return 1;
else if(v2==undefined || v2.trim() == '') return -1;
// If number.
if(isNumber(v1) && isNumber(v2))
return parseFloat(v1)>parseFloat(v2);
return v1.localeCompare(v2);
});
// Update options.
for (var i = 0; i <= optionsArray.length; i++)
options[i + (exceptFirstOpt ? 1 : 0)] = optionsArray[i];
// First option selected by default.
options[0].selected = true;
}
let selectOrDatalist = document.querySelector('#sdl');
/* optional added option
selectOrDatalist.insertAdjacentHTML('afterbegin', `<option id="${id}" value="${foo}">${bar}</option>` );
*/
selectOrDatalist.append(...[...selectOrDatalist.options].sort((a,b) => a.value.localeCompare(b.value)));

JavaScript function to transform a currency field in words

i found several scripts to do this with ENG/US currency, but I need it in Portuguese language, and its getting hard to find.
I've tried to modify a script to my needs but it is hard.
So, I found this script on web but it dont work too. What is wrong? Uncaught SyntaxError: Unexpected identifier : lin23
<script>
function number_format(a, b, c, d) {
a = Math.round(a * Math.pow(10, b)) / Math.pow(10, b);
e = a + '';
f = e.split('.');
if (!f[0]) {
f[0] = '0';
}
if (!f[1]) {
f[1] = '';
}
if (f[1].length < b) {
g = f[1];
for (i=f[1].length + 1; i <= b; i++) {
g += '0';
}
f[1] = g;
}
if(d != '' && f[0].length > 3) {
h = f[0];
f[0] = '';
for(j = 3; j < h.length; j+=3) {
i = h.slice(h.length – j, h.length – j + 3);
f[0] = d + i + f[0] + '';
}
j = h.substr(0, (h.length % 3 == 0) ? 3 : (h.length % 3));
f[0] = j + f[0];
}
c = (b <= 0) ? '' : c;
return f[0] + c + f[1];
}
function ValorPorExtenso(valor) {
if (!valor) return 'Zero';
var singular = ["centavo", "real", "mil", "milhão", "bilhão", "trilhão", "quatrilhão"];
var plural = ["centavos", "reais", "mil", "milhões", "bilhões", "trilhões", "quatrilhões"];
var c = ["", "cento", "duzentos", "trezentos", "quatrocentos", "quinhentos", "seiscentos", "setecentos", "oitocentos", "novecentos"];
var d = ["", "dez", "vinte", "trinta", "quarenta", "cinquenta", "sessenta", "setenta", "oitenta", "noventa"];
var d10 = ["dez", "onze", "doze", "treze", "quatorze", "quinze", "dezesseis", "dezesete", "dezoito", "dezenove"];
var u = ["", "um", "dois", "três", "quatro", "cinco", "seis", "sete", "oito", "nove"];
var z = 0;
valor = valor.toString();
valor = number_format(valor, 2, '.', '.');
alert(valor);
var inteiro = valor.split(/\./);
for (var i = 0; i < inteiro.length; i++) {
inteiro[i] = inteiro[i].toString();
for (var ii = inteiro[i].length; ii < 3; ii++) {
inteiro[i] = '0' + inteiro[i];
}
}
var fim = inteiro.length – ( inteiro[inteiro.length-1] > 0 ? 1 : 2 );
var rc, rd, ru;
var r, t;
var rt = '';
var valor_split;
for (var i = 0; i < inteiro.length; i++) {
valor = inteiro[i];
valor_split = valor.match(/./g);
rc = ((valor > 100) && (valor < 200)) ? 'cento' : c[valor_split[0]];
rd = (valor_split[1] < 2) ? '' : d[valor_split[1]];
ru = (valor > 0) ? ((valor_split[1] == 1) ? d10[valor_split[2]] : u[valor_split[2]]) : '';
r = rc + ((rc && (rd || ru)) ? ' e ' : '') + rd + ((rd && ru) ? ' e ' : '') + ru;
t = inteiro.length – 1 – i;
r = r + (r ? ' ' + (valor > 1 ? plural[t] : singular[t]) : '');
if (valor == '000') z++;
else if (z > 0) z–;
if ((t==1) && (z>0) && (inteiro[0] > 0)) {
r = r + ((z>1) ? ' de ' : '') + plural[t];
}
if (r) {
rt = rt + (((i > 0) && (i <= fim) && (inteiro[0] > 0) && (z < 1)) ? ( (i < fim) ? ', ' : ' e ') : ' ') + r;
}
}
return (rt ? rt : 'zero');
}
alert(ValorPorExtenso(8916165));
</script>
I realize that you copied the code as is and pasted into a seperate file. There is a problem with the encoding of some characters. For example, so '-' are incorrectly encoded; so just replace them
i = h.slice(h.length – j, h.length – j + 3)
should be
i = h.slice(h.length - j, h.length – j + 3)
I know you can't see the difference, but the two characters are different.
Have a look at the modified code: http://jsfiddle.net/7P3Vy/

Javascript to sort contents of select element

is there a quick way to sort the items of a select element?
Or I have to resort to writing javascript?
Please any ideas.
<select size="4" name="lstALL" multiple="multiple" id="lstALL" tabindex="12" style="font-size:XX-Small;height:95%;width:100%;">
<option value="0"> XXX</option>
<option value="1203">ABC</option>
<option value="1013">MMM</option>
</select>
This will do the trick. Just pass it your select element a la: document.getElementById('lstALL') when you need your list sorted.
function sortSelect(selElem) {
var tmpAry = new Array();
for (var i=0;i<selElem.options.length;i++) {
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
tmpAry.sort();
while (selElem.options.length > 0) {
selElem.options[0] = null;
}
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
}
return;
}
This solution worked very nicely for me using jquery, thought I'd cross reference it here as I found this page before the other one. Someone else might do the same.
$("#id").html($("#id option").sort(function (a, b) {
return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
}))
from Sorting dropdown list using Javascript
Vanilla JS es6 Localization Options Sorting Example
const optionNodes = Array.from(selectNode.children);
const comparator = new Intl.Collator(lang.slice(0, 2)).compare;
optionNodes.sort((a, b) => comparator(a.textContent, b.textContent));
optionNodes.forEach((option) => selectNode.appendChild(option));
My use case was to localize a country select dropdown with locale aware sorting. This was used on 250 + options and was very performant ~10ms on my machine.
Working with the answers provided by Marco Lazzeri and Terre Porter (vote them up if this answer is useful), I came up with a slightly different solution that preserves the selected value (probably doesn't preserve event handlers or attached data, though) using jQuery.
// save the selected value for sorting
var v = jQuery("#id").val();
// sort the options and select the value that was saved
j$("#id")
.html(j$("#id option").sort(function(a,b){
return a.text == b.text ? 0 : a.text < b.text ? -1 : 1;}))
.val(v);
From the W3C FAQ:
Although many programming languages have devices like drop-down boxes that have the capability of sorting a list of items before displaying them as part of their functionality, the HTML <select> function has no such capabilities. It lists the <options> in the order received.
You'd have to sort them by hand for a static HTML document, or resort to Javascript or some other programmatic sort for a dynamic document.
Another option:
function sortSelect(elem) {
var tmpAry = [];
// Retain selected value before sorting
var selectedValue = elem[elem.selectedIndex].value;
// Grab all existing entries
for (var i=0;i<elem.options.length;i++) tmpAry.push(elem.options[i]);
// Sort array by text attribute
tmpAry.sort(function(a,b){ return (a.text < b.text)?-1:1; });
// Wipe out existing elements
while (elem.options.length > 0) elem.options[0] = null;
// Restore sorted elements
var newSelectedIndex = 0;
for (var i=0;i<tmpAry.length;i++) {
elem.options[i] = tmpAry[i];
if(elem.options[i].value == selectedValue) newSelectedIndex = i;
}
elem.selectedIndex = newSelectedIndex; // Set new selected index after sorting
return;
}
This is a a recompilation of my 3 favorite answers on this board:
jOk's best and simplest answer.
Terry Porter's easy jQuery method.
SmokeyPHP's configurable function.
The results are an easy to use, and easily configurable function.
First argument can be a select object, the ID of a select object, or an array with at least 2 dimensions.
Second argument is optional. Defaults to sorting by option text, index 0. Can be passed any other index so sort on that. Can be passed 1, or the text "value", to sort by value.
Sort by text examples (all would sort by text):
sortSelect('select_object_id');
sortSelect('select_object_id', 0);
sortSelect(selectObject);
sortSelect(selectObject, 0);
Sort by value (all would sort by value):
sortSelect('select_object_id', 'value');
sortSelect('select_object_id', 1);
sortSelect(selectObject, 1);
Sort any array by another index:
var myArray = [
['ignored0', 'ignored1', 'Z-sortme2'],
['ignored0', 'ignored1', 'A-sortme2'],
['ignored0', 'ignored1', 'C-sortme2'],
];
sortSelect(myArray,2);
This last one will sort the array by index-2, the sortme's.
Main sort function
function sortSelect(selElem, sortVal) {
// Checks for an object or string. Uses string as ID.
switch(typeof selElem) {
case "string":
selElem = document.getElementById(selElem);
break;
case "object":
if(selElem==null) return false;
break;
default:
return false;
}
// Builds the options list.
var tmpAry = new Array();
for (var i=0;i<selElem.options.length;i++) {
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
// allows sortVal to be optional, defaults to text.
switch(sortVal) {
case "value": // sort by value
sortVal = 1;
break;
default: // sort by text
sortVal = 0;
}
tmpAry.sort(function(a, b) {
return a[sortVal] == b[sortVal] ? 0 : a[sortVal] < b[sortVal] ? -1 : 1;
});
// removes all options from the select.
while (selElem.options.length > 0) {
selElem.options[0] = null;
}
// recreates all options with the new order.
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
}
return true;
}
I had the same problem. Here's the jQuery solution I came up with:
var options = jQuery.makeArray(optionElements).
sort(function(a,b) {
return (a.innerHTML > b.innerHTML) ? 1 : -1;
});
selectElement.html(options);
I had a similar problem, except I wanted the selected items to show up on top, and I didn't want to clear which items were selected (multi-select list). Mine is jQuery based...
function SortMultiSelect_SelectedTop(slt) {
var options =
$(slt).find("option").sort(function (a, b) {
if (a.selected && !b.selected) return -1;
if (!a.selected && b.selected) return 1;
if (a.text < b.text) return -1;
if (a.text > b.text) return 1;
return 0;
});
$(slt).empty().append(options).scrollTop(0);
}
Without selected on top, it would look like this.
function SortMultiSelect(slt) {
var options =
$(slt).find("option").sort(function (a, b) {
if (a.text < b.text) return -1;
if (a.text > b.text) return 1;
return 0;
});
$(slt).empty().append(options).scrollTop(0);
}
Yes DOK has the right answer ... either pre-sort the results before you write the HTML (assuming it's dynamic and you are responsible for the output), or you write javascript.
The Javascript Sort method will be your friend here. Simply pull the values out of the select list, then sort it, and put them back :-)
Í think this is a better option (I use #Matty's code and improved!):
function sortSelect(selElem, bCase) {
var tmpAry = new Array();
bCase = (bCase ? true : false);
for (var i=0;i<selElem.options.length;i++) {
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
if (bCase)
tmpAry.sort(function (a, b) {
var ret = 0;
var iPos = 0;
while (ret == 0 && iPos < a.length && iPos < b.length)
{
ret = (String(a).toLowerCase().charCodeAt(iPos) - String(b).toLowerCase().charCodeAt(iPos));
iPos ++;
}
if (ret == 0)
{
ret = (String(a).length - String(b).length);
}
return ret;
});
else
tmpAry.sort();
while (selElem.options.length > 0) {
selElem.options[0] = null;
}
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
}
return;
}
I used this bubble sort because I wasnt able to order them by the .value in the options array and it was a number. This way I got them properly ordered. I hope it's useful to you too.
function sortSelect(selElem) {
for (var i=0; i<(selElem.options.length-1); i++)
for (var j=i+1; j<selElem.options.length; j++)
if (parseInt(selElem.options[j].value) < parseInt(selElem.options[i].value)) {
var dummy = new Option(selElem.options[i].text, selElem.options[i].value);
selElem.options[i] = new Option(selElem.options[j].text, selElem.options[j].value);
selElem.options[j] = dummy;
}
}
I've quickly thrown together one that allows choice of direction ("asc" or "desc"), whether the comparison should be done on the option value (true or false) and whether or not leading and trailing whitespace should be trimmed before comparison (boolean).
The benefit of this method, is that the selected choice is kept, and all other special properties/triggers should also be kept.
function sortOpts(select,dir,value,trim)
{
value = typeof value == 'boolean' ? value : false;
dir = ['asc','desc'].indexOf(dir) > -1 ? dir : 'asc';
trim = typeof trim == 'boolean' ? trim : true;
if(!select) return false;
var opts = select.getElementsByTagName('option');
var options = [];
for(var i in opts)
{
if(parseInt(i)==i)
{
if(trim)
{
opts[i].innerHTML = opts[i].innerHTML.replace(/^\s*(.*)\s*$/,'$1');
opts[i].value = opts[i].value.replace(/^\s*(.*)\s*$/,'$1');
}
options.push(opts[i]);
}
}
options.sort(value ? sortOpts.sortVals : sortOpts.sortText);
if(dir == 'desc') options.reverse();
options.reverse();
for(var i in options)
{
select.insertBefore(options[i],select.getElementsByTagName('option')[0]);
}
}
sortOpts.sortText = function(a,b) {
return a.innerHTML > b.innerHTML ? 1 : -1;
}
sortOpts.sortVals = function(a,b) {
return a.value > b.value ? 1 : -1;
}
Inspired by #Terre Porter's answer, I think this one is very simple to implement (using jQuery)
var $options = jQuery("#my-dropdownlist-id > option");
// or jQuery("#my-dropdownlist-id").find("option")
$options.sort(function(a, b) {
return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
})
But, for Alpha/Numeric dropdown lists :
Inspired by : https://stackoverflow.com/a/4340339/1598891
var $options = jQuery(dropDownList).find("option");
var reAlpha = /[^a-zA-Z]/g;
var reNumeric = /[^0-9]/g;
$options.sort(function AlphaNumericSort($a,$b) {
var a = $a.text;
var b = $b.text;
var aAlpha = a.replace(reAlpha, "");
var bAlpha = b.replace(reAlpha, "");
if(aAlpha === bAlpha) {
var aNumeric = parseInt(a.replace(reNumeric, ""), 10);
var bNumeric = parseInt(b.replace(reNumeric, ""), 10);
return aNumeric === bNumeric ? 0 : aNumeric > bNumeric ? 1 : -1;
} else {
return aAlpha > bAlpha ? 1 : -1;
}
})
Hope it will help
function call() {
var x = document.getElementById("mySelect");
var optionVal = new Array();
for (i = 0; i < x.length; i++) {
optionVal.push(x.options[i].text);
}
for (i = x.length; i >= 0; i--) {
x.remove(i);
}
optionVal.sort();
for (var i = 0; i < optionVal.length; i++) {
var opt = optionVal[i];
var el = document.createElement("option");
el.textContent = opt;
el.value = opt;
x.appendChild(el);
}
}
The idea is to pullout all the elements of the selectbox into an array , delete the selectbox values to avoid overriding, sort the array and then push back the sorted array into the select box
Not quite as pretty as the JQuery example by Marco but with prototype (i may be missing a more elegant solution) it would be:
function sort_select(select) {
var options = $A(select.options).sortBy(function(o) { return o.innerHTML });
select.innerHTML = "";
options.each(function(o) { select.insert(o); } );
}
And then just pass it a select element:
sort_select( $('category-select') );
Just another way to do it with jQuery:
// sorting;
var selectElm = $("select"),
selectSorted = selectElm.find("option").toArray().sort(function (a, b) {
return (a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase()) ? 1 : -1;
});
selectElm.empty();
$.each(selectSorted, function (key, value) {
selectElm.append(value);
});
Try this...hopefully it will offer you a solution:
function sortlist_name()
{
var lb = document.getElementById('mylist');
arrTexts = new Array();
newTexts = new Array();
txt = new Array();
newArray =new Array();
for(i=0; i<lb.length; i++)
{
arrTexts[i] = lb.options[i].text;
}
for(i=0;i<arrTexts.length; i++)
{
str = arrTexts[i].split(" -> ");
newTexts[i] = str[1]+' -> '+str[0];
}
newTexts.sort();
for(i=0;i<newTexts.length; i++)
{
txt = newTexts[i].split(' -> ');
newArray[i] = txt[1]+' -> '+txt[0];
}
for(i=0; i<lb.length; i++)
{
lb.options[i].text = newArray[i];
lb.options[i].value = newArray[i];
}
}
/***********revrse by name******/
function sortreverse_name()
{
var lb = document.getElementById('mylist');
arrTexts = new Array();
newTexts = new Array();
txt = new Array();
newArray =new Array();
for(i=0; i<lb.length; i++)
{
arrTexts[i] = lb.options[i].text;
}
for(i=0;i<arrTexts.length; i++)
{
str = arrTexts[i].split(" -> ");
newTexts[i] = str[1]+' -> '+str[0];
}
newTexts.reverse();
for(i=0;i<newTexts.length; i++)
{
txt = newTexts[i].split(' -> ');
newArray[i] = txt[1]+' -> '+txt[0];
}
for(i=0; i<lb.length; i++)
{
lb.options[i].text = newArray[i];
lb.options[i].value = newArray[i];
}
}
function sortlist_id() {
var lb = document.getElementById('mylist');
arrTexts = new Array();
for(i=0; i<lb.length; i++) {
arrTexts[i] = lb.options[i].text;
}
arrTexts.sort();
for(i=0; i<lb.length; i++) {
lb.options[i].text = arrTexts[i];
lb.options[i].value = arrTexts[i];
}
}
/***********revrse by id******/
function sortreverse_id() {
var lb = document.getElementById('mylist');
arrTexts = new Array();
for(i=0; i<lb.length; i++) {
arrTexts[i] = lb.options[i].text;
}
arrTexts.reverse();
for(i=0; i<lb.length; i++) {
lb.options[i].text = arrTexts[i];
lb.options[i].value = arrTexts[i];
}
}
</script>
ID ▲ ▼ | Name ▲ ▼<br/>
<select name=mylist id=mylist size=8 style='width:150px'>
<option value="bill">4 -> Bill</option>
<option value="carl">5 -> Carl</option>
<option value="Anton">1 -> Anton</option>
<option value="mike">2 -> Mike</option>
<option value="peter">3 -> Peter</option>
</select>
<br>
function sortItems(c) {
var options = c.options;
Array.prototype.sort.call(options, function (a, b) {
var aText = a.text.toLowerCase();
var bText = b.text.toLowerCase();
if (aText < bText) {
return -1;
} else if (aText > bText) {
return 1;
} else {
return 0;
}
});
}
sortItems(document.getElementById('lstALL'));
For those who are looking to sort whether or not there are optgroup :
/**
* Sorting options
* and optgroups
*
* #param selElem select element
* #param optionBeforeGroup ?bool if null ignores, if true option appear before group else option appear after group
*/
function sortSelect(selElem, optionBeforeGroup = null) {
let initialValue = selElem.tagName === "SELECT" ? selElem.value : null;
let allChildrens = Array.prototype.slice.call(selElem.childNodes);
let childrens = [];
for (let i = 0; i < allChildrens.length; i++) {
if (allChildrens[i].parentNode === selElem && ["OPTGROUP", "OPTION"].includes(allChildrens[i].tagName||"")) {
if (allChildrens[i].tagName == "OPTGROUP") {
sortSelect(allChildrens[i]);
}
childrens.push(allChildrens[i]);
}
}
childrens.sort(function(a, b){
let x = a.tagName == "OPTGROUP" ? a.getAttribute("label") : a.innerHTML;
let y = b.tagName == "OPTGROUP" ? b.getAttribute("label") : b.innerHTML;
x = typeof x === "undefined" || x === null ? "" : (x+"");
y = typeof y === "undefined" || y === null ? "" : (y+"");
if (optionBeforeGroup === null) {
if (x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
if (x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
} else if (optionBeforeGroup === true) {
if ((a.tagName == "OPTION" && b.tagName == "OPTGROUP") || x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
if ((a.tagName == "OPTGROUP" && b.tagName == "OPTION") || x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
} else if (optionBeforeGroup === false) {
if ((a.tagName == "OPTGROUP" && b.tagName == "OPTION") || x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
if ((a.tagName == "OPTION" && b.tagName == "OPTGROUP") || x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
}
return 0;
});
if (optionBeforeGroup !== null) {
childrens.sort(function(a, b){
if (optionBeforeGroup === true) {
if (a.tagName == "OPTION" && b.tagName == "OPTGROUP") {return -1;}
if (a.tagName == "OPTGROUP" && b.tagName == "OPTION") {return 1;}
} else {
if (a.tagName == "OPTGROUP" && b.tagName == "OPTION") {return -1;}
if (a.tagName == "OPTION" && b.tagName == "OPTGROUP") {return 1;}
}
return 0;
});
}
selElem.innerHTML = "";
for (let i = 0; i < childrens.length; i++) {
selElem.appendChild(childrens[i]);
}
if (selElem.tagName === "SELECT") {
selElem.value = initialValue;
}
}
I think my function is more general for strings or numbers and does not sort the first element if it could mean All.
/** Check if a string can be parsed as a number. */
function isNumber(n) { return !isNaN(parseFloat(n)) && !isNaN(n - 0) };
/** Sort options of HTML elements. */
function sortOptions(selectElement, exceptFirstOpt=false) {
// List of options.
var options = selectElement.options;
// If empty list, do nothing.
if(!options || options.length==0) return;
// Array.
var optionsArray = [];
for (var i = (exceptFirstOpt ? 1 : 0); i < options.length; i++)
optionsArray.push(options[i]);
// Sort.
optionsArray = optionsArray.sort(function (a, b) {
let v1 = a.innerHTML.toLowerCase();
let v2 = b.innerHTML.toLowerCase();
if((v1==undefined || v1 == '') && (v2==undefined || v2 == ''))
return 0;
else if(v1==undefined || v1.trim() == '') return 1;
else if(v2==undefined || v2.trim() == '') return -1;
// If number.
if(isNumber(v1) && isNumber(v2))
return parseFloat(v1)>parseFloat(v2);
return v1.localeCompare(v2);
});
// Update options.
for (var i = 0; i <= optionsArray.length; i++)
options[i + (exceptFirstOpt ? 1 : 0)] = optionsArray[i];
// First option selected by default.
options[0].selected = true;
}
let selectOrDatalist = document.querySelector('#sdl');
/* optional added option
selectOrDatalist.insertAdjacentHTML('afterbegin', `<option id="${id}" value="${foo}">${bar}</option>` );
*/
selectOrDatalist.append(...[...selectOrDatalist.options].sort((a,b) => a.value.localeCompare(b.value)));

Categories

Resources