
Quickly sort tables with Javascript
In the process of working with tables, for ease of perception, as well as quick analysis, sooner or later the question arises of outputting the sorted contents of these tables. This problem in web programming can be solved in two ways:
The disadvantages of the first option are a reload of the page for every user click on the sort controls. Pros - sorting speed on large samples.
Cons on the client side is the relatively low speed, which directly depends on the browser and the power of the user's computer. The pluses are the absence of a page reload, therefore, sometimes this gives a higher speed of getting sorted content, because in this case, there is no delay between sending the request to the server and receiving the result.
Let's take a table with columns of different types of data: numerical data, time, date and text.
The most suitable method, I believe, is to get the contents of all the cells in the table, according to which you need to sort and write it to an array, and then restore the rows according to their order in the sorted array. For such sorting, it will be possible to use the array.sort () method.
By default, arrays are sorted in ascending order and the contents are treated as text, but you can use your own handler for the array.sort method. Therefore, before using this method, you need to prepare the initial data.
Numeric and text data are written to the array without change.
We convert time to a numerical value, in my example it is minutes.
The date is also converted to a numerical value. I used the Date object and the getTime () method for this, which returns the timestamp in milliseconds.
Thus, we sort the numbers, date and time as numeric data with our own handler, and we sort the text by the usual call to array.sort ().
Now about how to match these arrays with the table object. Before the conversion, we index all the rows of the table and assign them the runiqueID serial number. This is necessary so that when sorting data with duplicate values, our second priority is the line number. The array.sort () method sorts the array according to the weights and, passing it multidimensional arrays, you can sort them by several fields. I use a three-dimensional array, where the zero element is the converted value, the first element is the row ordinal number, and the second is the row node. Handler code is given below.
After casting to the desired type, save the nodes in the array element and call array.sort (), and if you need sorting in the reverse order, then we also call array.reverse ().
When the data is sorted, we can already change the position of the rows in the table tree. We go through the sorted array and call appendChild for all previously saved table row nodes.
This method is very fast because when sorting, table nodes are rearranged only at the end by a sequential call to appendChild.
View a working example and download the source code .
UPD: Added caching of the result and slightly optimized the code. Also, the example now has 500 lines. Optimized version and source code .
- Server-side sorting using SQL or backend;
- Client side sorting.
The disadvantages of the first option are a reload of the page for every user click on the sort controls. Pros - sorting speed on large samples.
Cons on the client side is the relatively low speed, which directly depends on the browser and the power of the user's computer. The pluses are the absence of a page reload, therefore, sometimes this gives a higher speed of getting sorted content, because in this case, there is no delay between sending the request to the server and receiving the result.
In this article, I would like to consider client-side sorting using JavaScript.
Let's take a table with columns of different types of data: numerical data, time, date and text.
The most suitable method, I believe, is to get the contents of all the cells in the table, according to which you need to sort and write it to an array, and then restore the rows according to their order in the sorted array. For such sorting, it will be possible to use the array.sort () method.
By default, arrays are sorted in ascending order and the contents are treated as text, but you can use your own handler for the array.sort method. Therefore, before using this method, you need to prepare the initial data.
Numeric and text data are written to the array without change.
We convert time to a numerical value, in my example it is minutes.
fastSortEngine.prototype.parseTime = function(tvalue) {
var ret = tvalue;
if(!tvalue) {
ret = this.nullValue;
} else {
tvalue = tvalue.split(':');
if(tvalue.length == 2) {
ret = parseInt(tvalue[0],10)*60 + parseInt(tvalue[1],10);
} else {
ret = this.nullValue;
}
}
return ret;
}
The date is also converted to a numerical value. I used the Date object and the getTime () method for this, which returns the timestamp in milliseconds.
fastSortEngine.prototype.parseDate = function(dvalue) {
var ret = dvalue;
if(!dvalue) {
ret = this.nullValue;
} else {
dvalue = dvalue.split(' ');
if(dvalue.length == 3) {
var d = new Date(dvalue[2], this.months[dvalue[1].toLowerCase()], dvalue[0]);
ret = d.getTime();
} else {
ret = this.nullValue;
}
}
return ret;
}
Thus, we sort the numbers, date and time as numeric data with our own handler, and we sort the text by the usual call to array.sort ().
Now about how to match these arrays with the table object. Before the conversion, we index all the rows of the table and assign them the runiqueID serial number. This is necessary so that when sorting data with duplicate values, our second priority is the line number. The array.sort () method sorts the array according to the weights and, passing it multidimensional arrays, you can sort them by several fields. I use a three-dimensional array, where the zero element is the converted value, the first element is the row ordinal number, and the second is the row node. Handler code is given below.
fastSortEngine.prototype.sortNumber = function(a,b) {
var a1 = a[0] == '' ? this.nullValue : parseFloat(a[0]);
var b1 = b[0] == '' ? this.nullValue : parseFloat(b[0]);
if (a1 == b1 && a[1] < b[1] ) return -0.0000000001;
else if(a1 == b1 && a[1] > b[1] ) return 0.0000000001;
return a1 - b1;
}
After casting to the desired type, save the nodes in the array element and call array.sort (), and if you need sorting in the reverse order, then we also call array.reverse ().
var obj = [val,
rowObj.runiqueID,
rowObj];
dataCol.push(obj);
if(this.colType == "text") dataCol.sort();
else dataCol.sort(this.sortNumber);
When the data is sorted, we can already change the position of the rows in the table tree. We go through the sorted array and call appendChild for all previously saved table row nodes.
var l = dataCol.length;
for(var i = 0; i
this.tBody.appendChild(dataCol[i][2]);
}
This method is very fast because when sorting, table nodes are rearranged only at the end by a sequential call to appendChild.
View a working example and download the source code .
UPD: Added caching of the result and slightly optimized the code. Also, the example now has 500 lines. Optimized version and source code .