WIP webmap cleanup

This commit is contained in:
Oliver Jowett 2015-01-05 23:20:03 +00:00
parent 99bca13844
commit 1f06abf67d
4 changed files with 242 additions and 288 deletions

6
debian/changelog vendored
View file

@ -1,3 +1,9 @@
dump1090-mutability (1.10.3010.14mu-10) UNRELEASED; urgency=medium
* JSON / webmap cleanups.
-- Oliver Jowett <oliver@mutability.co.uk> Mon, 05 Jan 2015 21:43:58 +0000
dump1090-mutability (1.10.3010.14mu-9) unstable; urgency=medium dump1090-mutability (1.10.3010.14mu-9) unstable; urgency=medium
* Fix warnings. Add -Werror so they break the build in future. * Fix warnings. Add -Werror so they break the build in future.

View file

@ -671,58 +671,59 @@ char *generateAircraftJson(int *len) {
time_t now = time(NULL); time_t now = time(NULL);
struct aircraft *a = Modes.aircrafts; struct aircraft *a = Modes.aircrafts;
int buflen = 1024; // The initial buffer is incremented as needed int buflen = 1024; // The initial buffer is incremented as needed
char *buf = (char *) malloc(buflen), *p = buf; char *buf = (char *) malloc(buflen), *p = buf, *end = buf+buflen;
int l; int first = 1;
p += snprintf(p, end-p,
"{ \"now\" : %d,\n"
" \"aircraft\" : [",
(int)now);
l = snprintf(p,buflen,"[\n");
p += l; buflen -= l;
while(a) { while(a) {
int position = 0;
int track = 0;
if (a->modeACflags & MODEAC_MSG_FLAG) { // skip any fudged ICAO records Mode A/C if (a->modeACflags & MODEAC_MSG_FLAG) { // skip any fudged ICAO records Mode A/C
a = a->next; a = a->next;
continue; continue;
} }
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { if (first)
position = 1; first = 0;
} else
*p++ = ',';
p += snprintf(p, end-p, "\n {\"hex\":\"%06x\"", a->addr);
if (a->bFlags & MODES_ACFLAGS_SQUAWK_VALID)
p += snprintf(p, end-p, ",\"squawk\":\"%04x\"", a->modeA);
if (a->bFlags & MODES_ACFLAGS_CALLSIGN_VALID)
p += snprintf(p, end-p, ",\"flight\":\"%s\"", a->flight);
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID)
p += snprintf(p, end-p, ",\"lat\":%f,\"lon\":%f", a->lat, a->lon);
if ((a->bFlags & MODES_ACFLAGS_AOG_VALID) && (a->bFlags & MODES_ACFLAGS_AOG))
p += snprintf(p, end-p, ",\"altitude\":\"ground\"");
else if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID)
p += snprintf(p, end-p, ",\"altitude\":%d", a->altitude);
if (a->bFlags & MODES_ACFLAGS_VERTRATE_VALID)
p += snprintf(p, end-p, ",\"vert_rate\":%d", a->vert_rate);
if (a->bFlags & MODES_ACFLAGS_HEADING_VALID)
p += snprintf(p, end-p, ",\"track\":%d", a->track);
if (a->bFlags & MODES_ACFLAGS_SPEED_VALID)
p += snprintf(p, end-p, ",\"speed\":%d", a->speed);
p += snprintf(p, end-p, ",\"messages\":%ld, \"seen\":%d}",
a->messages, (int)(now - a->seen));
if (a->bFlags & MODES_ACFLAGS_HEADING_VALID) { // If we're getting near the end of the buffer, expand it.
track = 1; if ((end - p) < 256) {
} int used = p - buf;
buflen *= 2;
// No metric conversion buf = (char *) realloc(buf, buflen);
l = snprintf(p,buflen,
"{\"hex\":\"%06x\", \"squawk\":\"%04x\", \"flight\":\"%s\", \"lat\":%f, "
"\"lon\":%f, \"validposition\":%d, \"altitude\":%d, \"vert_rate\":%d,\"track\":%d, \"validtrack\":%d,"
"\"speed\":%d, \"messages\":%ld, \"seen\":%d},\n",
a->addr, a->modeA, a->flight, a->lat, a->lon, position, a->altitude, a->vert_rate, a->track, track,
a->speed, a->messages, (int)(now - a->seen));
p += l; buflen -= l;
//Resize if needed
if (buflen < 256) {
int used = p-buf;
buflen += 1024; // Our increment.
buf = (char *) realloc(buf,used+buflen);
p = buf+used; p = buf+used;
end = buf + buflen;
} }
a = a->next; a = a->next;
} }
//Remove the final comma if any, and closes the json array. p += snprintf(p, end-p, "\n ]\n}\n");
if (*(p-2) == ',') {
*(p-2) = '\n';
p--;
buflen++;
}
l = snprintf(p,buflen,"]\n");
p += l; buflen -= l;
*len = p-buf; *len = p-buf;
return buf; return buf;
} }

View file

@ -20,10 +20,6 @@ var planeObject = {
messages : null, messages : null,
seen : null, seen : null,
// Vaild...
vPosition : false,
vTrack : false,
// GMap Details // GMap Details
marker : null, marker : null,
markerColor : MarkerColor, markerColor : MarkerColor,
@ -130,85 +126,69 @@ var planeObject = {
}, },
// Update our data // Update our data
funcUpdateData : function(data){ funcUpdateData : function(receiver_now,data){
// So we can find out if we moved // So we can find out if we moved
var oldlat = this.latitude; var oldlat = this.latitude;
var oldlon = this.longitude; var oldlon = this.longitude;
var oldalt = this.altitude; var oldalt = this.altitude;
// Update all of our data // Update all of our data
this.updated = new Date().getTime(); this.updated = new Date().getTime();
this.icao = data.hex;
this.messages = data.messages;
this.seen = data.seen;
if (typeof data.altitude !== "undefined")
this.altitude = data.altitude; this.altitude = data.altitude;
this.speed = data.speed; if (typeof data.speed !== "undefined")
this.track = data.track; this.speed = data.speed;
if (typeof data.track !== "undefined")
this.track = data.track;
if (typeof data.lat !== "undefined") {
this.latitude = data.lat; this.latitude = data.lat;
this.longitude = data.lon; this.longitude = data.lon;
}
if (typeof data.flight !== "undefined")
this.flight = data.flight; this.flight = data.flight;
if (typeof data.squawk !== "undefined")
this.squawk = data.squawk; this.squawk = data.squawk;
this.icao = data.hex;
this.messages = data.messages;
this.seen = data.seen;
// If no packet in over 58 seconds, consider the plane reapable // If no packet in over 58 seconds, consider the plane reapable
// This way we can hold it, but not show it just in case the plane comes back // This way we can hold it, but not show it just in case the plane comes back
if (this.seen > 58) { if (this.seen > 58) {
this.reapable = true; this.reapable = true;
if (this.marker) { if (this.marker) {
this.marker.setMap(null); this.marker.setMap(null);
this.marker = null; this.marker = null;
}
if (this.line) {
this.line.setMap(null);
this.line = null;
}
if (SelectedPlane == this.icao) {
if (this.is_selected) {
this.is_selected = false;
} }
if (this.line) { SelectedPlane = null;
this.line.setMap(null); }
this.line = null; } else {
this.reapable = false;
}
// Is the position valid?
if (!this.reapable && typeof data.lat !== "undefined") {
// Detech if the plane has moved
if (oldlat != this.latitude || oldlon != this.longitude) {
this.funcAddToTrack();
if (this.is_selected) {
this.line = this.funcUpdateLines();
} }
if (SelectedPlane == this.icao) {
if (this.is_selected) {
this.is_selected = false;
}
SelectedPlane = null;
}
} else {
if (this.reapable == true) {
}
this.reapable = false;
} }
// Is the position valid? this.marker = this.funcUpdateMarker();
if ((data.validposition == 1) && (this.reapable == false)) { PlanesOnMap++;
this.vPosition = true; }
},
// Detech if the plane has moved
changeLat = false;
changeLon = false;
changeAlt = false;
if (oldlat != this.latitude) {
changeLat = true;
}
if (oldlon != this.longitude) {
changeLon = true;
}
if (oldalt != this.altitude) {
changeAlt = true;
}
// Right now we only care about lat/long, if alt is updated only, oh well
if ((changeLat == true) || (changeLon == true)) {
this.funcAddToTrack();
if (this.is_selected) {
this.line = this.funcUpdateLines();
}
}
this.marker = this.funcUpdateMarker();
PlanesOnMap++;
} else {
this.vPosition = false;
}
// Do we have a valid track for the plane?
if (data.validtrack == 1)
this.vTrack = true;
else
this.vTrack = false;
},
// Update our marker on the map // Update our marker on the map
funcUpdateMarker: function() { funcUpdateMarker: function() {
@ -231,7 +211,7 @@ var planeObject = {
} }
// Setting the marker title // Setting the marker title
if (this.flight.length == 0) { if (this.flight === null || this.flight.length == 0) {
this.marker.setTitle(this.hex); this.marker.setTitle(this.hex);
} else { } else {
this.marker.setTitle(this.flight+' ('+this.icao+')'); this.marker.setTitle(this.flight+' ('+this.icao+')');

View file

@ -7,10 +7,9 @@ var PlanesToReap = 0;
var SelectedPlane = null; var SelectedPlane = null;
var SpecialSquawk = false; var SpecialSquawk = false;
var iSortCol=-1; var sortColumn = 3;
var bSortASC=true; var sortAscending = true;
var bDefaultSortASC=true; var sortNumeric = true;
var iDefaultSortCol=3;
// Get current map settings // Get current map settings
CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT; CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT;
@ -22,32 +21,34 @@ RefreshInterval = 1000;
function fetchData() { function fetchData() {
$.getJSON('data/aircraft.json', function(data) { $.getJSON('data/aircraft.json', function(data) {
PlanesOnMap = 0 PlanesOnMap = 0;
SpecialSquawk = false; SpecialSquawk = false;
// Loop through all the planes in the data packet // Loop through all the planes in the data packet
for (var j=0; j < data.length; j++) { console.log("I was called\n");
var now = data.now;
var acs = data.aircraft;
for (var j=0; j < acs.length; j++) {
var ac = acs[j];
// Do we already have this plane object in Planes? // Do we already have this plane object in Planes?
// If not make it. // If not make it.
if (Planes[data[j].hex]) { if (Planes[ac.hex]) {
var plane = Planes[data[j].hex]; var plane = Planes[ac.hex];
} else { } else {
var plane = jQuery.extend(true, {}, planeObject); var plane = jQuery.extend(true, {}, planeObject);
Planes[ac.hex] = plane;
} }
// Set SpecialSquawk-value // Set SpecialSquawk-value
if (data[j].squawk == '7500' || data[j].squawk == '7600' || data[j].squawk == '7700') { if (ac.squawk == '7500' || ac.squawk == '7600' || ac.squawk == '7700') {
SpecialSquawk = true; SpecialSquawk = true;
} }
// Call the function update // Call the function update
plane.funcUpdateData(data[j]); plane.funcUpdateData(now, ac);
// Copy the plane into Planes
Planes[plane.icao] = plane;
} }
PlanesOnTable = data.length; PlanesOnTable = acs.length;
}); });
} }
@ -291,15 +292,17 @@ function refreshSelected() {
} }
html += '<td></tr>'; html += '<td></tr>';
if (selected) { if (selected && selected.altitude !== null) {
if (Metric) { if (selected.altitude === "ground")
html += '<tr><td>Altitude: ' + Math.round(selected.altitude / 3.2828) + ' m</td>'; html += '<tr><td>Altitude: on ground</td>';
else if (Metric) {
html += '<tr><td>Altitude: ' + Math.round(selected.altitude / 3.2828) + ' m</td>';
} else {
html += '<tr><td>Altitude: ' + selected.altitude + ' ft</td>';
}
} else { } else {
html += '<tr><td>Altitude: ' + selected.altitude + ' ft</td>'; html += '<tr><td>Altitude: n/a</td>';
} }
} else {
html += '<tr><td>Altitude: n/a</td>';
}
if (selected && selected.squawk != '0000') { if (selected && selected.squawk != '0000') {
html += '<td>Squawk: ' + selected.squawk + '</td></tr>'; html += '<td>Squawk: ' + selected.squawk + '</td></tr>';
@ -326,15 +329,15 @@ function refreshSelected() {
} }
html += '<tr><td>Track: ' html += '<tr><td>Track: '
if (selected && selected.vTrack) { if (selected && selected.track !== null) {
html += selected.track + '&deg;' + ' (' + normalizeTrack(selected.track, selected.vTrack)[1] +')'; html += selected.track + '&deg;' + ' (' + trackLongName(selected.track) +')';
} else { } else {
html += 'n/a'; html += 'n/a';
} }
html += '</td><td>&nbsp;</td></tr>'; html += '</td><td>&nbsp;</td></tr>';
html += '<tr><td colspan="' + columns + '" align="center">Lat/Long: '; html += '<tr><td colspan="' + columns + '" align="center">Lat/Long: ';
if (selected && selected.vPosition) { if (selected && selected.latitude !== null) {
html += selected.latitude + ', ' + selected.longitude + '</td></tr>'; html += selected.latitude + ', ' + selected.longitude + '</td></tr>';
// Let's show some extra data if we have site coordinates // Let's show some extra data if we have site coordinates
@ -366,73 +369,38 @@ function refreshSelected() {
document.getElementById('plane_detail').innerHTML = html; document.getElementById('plane_detail').innerHTML = html;
} }
// Right now we have no means to validate the speed is good function trackShortName(track) {
// Want to return (n/a) when we dont have it var trackIndex = Math.floor((track+22.5) / 45);
// TODO: Edit C code to add a valid speed flag if ((trackIndex < 0) || (trackIndex >= 8))
// TODO: Edit js code to use said flag return "n/a";
function normalizeSpeed(speed, valid) { return ["N","NE","E","SE","S","SW","W","NW"][trackIndex];
return speed
} }
// Returns back a long string, short string, and the track if we have a vaild track path function trackLongName(track) {
function normalizeTrack(track, valid){ var trackIndex = Math.floor((track+22.5) / 45);
x = [] if ((trackIndex < 0) || (trackIndex >= 8))
if ((track > -1) && (track < 22.5)) { return "n/a";
x = ["North", "N", track] return ["North","Northeast","East","Southeast","South","Southwest","West","Northwest"][trackIndex];
}
if ((track > 22.5) && (track < 67.5)) {
x = ["North East", "NE", track]
}
if ((track > 67.5) && (track < 112.5)) {
x = ["East", "E", track]
}
if ((track > 112.5) && (track < 157.5)) {
x = ["South East", "SE", track]
}
if ((track > 157.5) && (track < 202.5)) {
x = ["South", "S", track]
}
if ((track > 202.5) && (track < 247.5)) {
x = ["South West", "SW", track]
}
if ((track > 247.5) && (track < 292.5)) {
x = ["West", "W", track]
}
if ((track > 292.5) && (track < 337.5)) {
x = ["North West", "NW", track]
}
if ((track > 337.5) && (track < 361)) {
x = ["North", "N", track]
}
if (!valid) {
x = [" ", "n/a", ""]
}
return x
} }
// Refeshes the larger table of all the planes // Refeshes the larger table of all the planes
function refreshTableInfo() { function refreshTableInfo() {
var html = '<table id="tableinfo" width="100%">'; var html = '<table id="tableinfo" width="100%">';
html += '<thead style="background-color: #BBBBBB; cursor: pointer;">'; html += '<thead style="background-color: #BBBBBB; cursor: pointer;">';
html += '<td onclick="setASC_DESC(\'0\');sortTable(\'tableinfo\',\'0\');">ICAO</td>'; html += '<td id="icao" onclick="sortBy(\'icao\',false);">ICAO</td>';
html += '<td onclick="setASC_DESC(\'1\');sortTable(\'tableinfo\',\'1\');">Flight</td>'; html += '<td id="flight" onclick="sortBy(\'flight\',false);">Flight</td>';
html += '<td onclick="setASC_DESC(\'2\');sortTable(\'tableinfo\',\'2\');" ' + html += '<td id="squawk" onclick="sortBy(\'squawk\',false);" align="right">Squawk</td>';
'align="right">Squawk</td>'; html += '<td id="altitude" onclick="sortBy(\'altitude\',true);" align="right">Altitude</td>';
html += '<td onclick="setASC_DESC(\'3\');sortTable(\'tableinfo\',\'3\');" ' + html += '<td id="speed" onclick="sortBy(\'speed\',true);" align="right">Speed</td>';
'align="right">Altitude</td>'; // Add distance column header to table if site coordinates are provided
html += '<td onclick="setASC_DESC(\'4\');sortTable(\'tableinfo\',\'4\');" ' +
'align="right">Speed</td>';
// Add distance column header to table if site coordinates are provided
if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) { if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) {
html += '<td onclick="setASC_DESC(\'5\');sortTable(\'tableinfo\',\'5\');" ' + html += '<td id="distance" onclick="sortBy(\'distance\',true);" align="right">Distance</td>';
'align="right">Distance</td>';
} }
html += '<td onclick="setASC_DESC(\'5\');sortTable(\'tableinfo\',\'6\');" ' + html += '<td id="track" onclick="sortBy(\'track\',true);" align="right">Track</td>';
'align="right">Track</td>'; html += '<td id="msgs" onclick="sortBy(\'msgs\',true);" align="right">Msgs</td>';
html += '<td onclick="setASC_DESC(\'6\');sortTable(\'tableinfo\',\'7\');" ' + html += '<td id="seen" onclick="sortBy(\'seen\',true);" align="right">Seen</td></thead><tbody>';
'align="right">Msgs</td>';
html += '<td onclick="setASC_DESC(\'7\');sortTable(\'tableinfo\',\'8\');" ' +
'align="right">Seen</td></thead><tbody>';
for (var tablep in Planes) { for (var tablep in Planes) {
var tableplane = Planes[tablep] var tableplane = Planes[tablep]
if (!tableplane.reapable) { if (!tableplane.reapable) {
@ -454,70 +422,76 @@ function refreshTableInfo() {
specialStyle += " squawk7700"; specialStyle += " squawk7700";
} }
if (tableplane.vPosition == true) { if (tableplane.latitude !== null)
html += '<tr class="plane_table_row vPosition' + specialStyle + '">'; html += '<tr class="plane_table_row vPosition' + specialStyle + '">';
} else { else
html += '<tr class="plane_table_row ' + specialStyle + '">'; html += '<tr class="plane_table_row ' + specialStyle + '">';
}
html += '<td>' + tableplane.icao + '</td>'; html += '<td>' + tableplane.icao + '</td>';
html += '<td>' + tableplane.flight + '</td>';
if (tableplane.squawk != '0000' ) { if (tableplane.flight !== null)
html += '<td align="right">' + tableplane.squawk + '</td>'; html += '<td>' + tableplane.flight + '</td>';
} else { else
html += '<td align="right">&nbsp;</td>'; html += '<td></td>';
}
if (tableplane.squawk !== null)
if (Metric) { html += '<td align="right">' + tableplane.squawk + '</td>';
html += '<td align="right">' + Math.round(tableplane.altitude / 3.2828) + '</td>'; else
html += '<td align="right">' + Math.round(tableplane.speed * 1.852) + '</td>'; html += '<td align="right"></td>';
} else {
html += '<td align="right">' + tableplane.altitude + '</td>'; if (tableplane.altitude === null)
html += '<td align="right">' + tableplane.speed + '</td>'; html += '<td align="right">&nbsp;</td>';
} else if (tableplane.altitude === "ground")
html += '<td align="right">ground</td>';
else if (Metric)
html += '<td align="right">' + Math.round(tableplane.altitude / 3.2828) + '</td>';
else
html += '<td align="right">' + tableplane.altitude + '</td>';
if (tableplane.speed === null)
html += '<td align="right">&nbsp;</td>';
else if (Metric)
html += '<td align="right">' + Math.round(tableplane.speed * 1.852) + '</td>';
else
html += '<td align="right">' + tableplane.speed + '</td>';
// Add distance column to table if site coordinates are provided // Add distance column to table if site coordinates are provided
if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) { if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) {
html += '<td align="right">'; html += '<td align="right">';
if (tableplane.vPosition) { if (tableplane.latitude !== null) {
var siteLatLon = new google.maps.LatLng(SiteLat, SiteLon); var siteLatLon = new google.maps.LatLng(SiteLat, SiteLon);
var planeLatLon = new google.maps.LatLng(tableplane.latitude, tableplane.longitude); var planeLatLon = new google.maps.LatLng(tableplane.latitude, tableplane.longitude);
var dist = google.maps.geometry.spherical.computeDistanceBetween (siteLatLon, planeLatLon); var dist = google.maps.geometry.spherical.computeDistanceBetween (siteLatLon, planeLatLon);
if (Metric) { if (Metric) {
dist /= 1000; dist /= 1000;
} else { } else {
dist /= 1852; dist /= 1852;
} }
dist = (Math.round((dist)*10)/10).toFixed(1); dist = (Math.round((dist)*10)/10).toFixed(1);
html += dist; html += dist;
} else { }
html += '0'; html += '</td>';
}
html += '</td>';
} }
html += '<td align="right">'; html += '<td align="right">';
if (tableplane.vTrack) { if (tableplane.track !== null)
html += normalizeTrack(tableplane.track, tableplane.vTrack)[2]; html += tableplane.track;
// html += ' (' + normalizeTrack(tableplane.track, tableplane.vTrack)[1] + ')'; html += '</td>';
} else {
html += '&nbsp;';
}
html += '</td>';
html += '<td align="right">' + tableplane.messages + '</td>'; html += '<td align="right">' + tableplane.messages + '</td>';
html += '<td align="right">' + tableplane.seen + '</td>'; html += '<td align="right">' + tableplane.seen + '</td>';
html += '</tr>'; html += '</tr>';
} }
} }
html += '</tbody></table>'; html += '</tbody></table>';
document.getElementById('planes_table').innerHTML = html; document.getElementById('planes_table').innerHTML = html;
if (SpecialSquawk) { if (SpecialSquawk) {
$('#SpecialSquawkWarning').css('display', 'inline'); $('#SpecialSquawkWarning').css('display', 'inline');
} else { } else {
$('#SpecialSquawkWarning').css('display', 'none'); $('#SpecialSquawkWarning').css('display', 'none');
} }
// Click event for table // Click event for table
$('#planes_table').find('tr').click( function(){ $('#planes_table').find('tr').click( function(){
var hex = $(this).find('td:first').text(); var hex = $(this).find('td:first').text();
@ -527,65 +501,59 @@ function refreshTableInfo() {
refreshSelected(); refreshSelected();
} }
}); });
sortTable("tableinfo"); resortTable();
} }
// Credit goes to a co-worker that needed a similar functions for something else function sortBy(colName,numeric) {
// we get a copy of it free ;) var header_cells = document.getElementById('tableinfo').tHead.rows[0].cells;
function setASC_DESC(iCol) { for (var i = 0; i < header_cells.length; ++i) {
if(iSortCol==iCol) { if (header_cells[i].id === colName) {
bSortASC=!bSortASC; if (i == sortColumn)
} else { sortAscending = !sortAscending;
bSortASC=bDefaultSortASC; else {
} sortColumn = i;
sortNumeric = numeric;
sortAscending = true;
}
resortTable();
return;
}
}
console.warn("column not found: " + colName);
} }
function sortTable(szTableID,iCol) { function resortTable() {
//if iCol was not provided, and iSortCol is not set, assign default value sortTable('tableinfo', sortColumn, sortAscending, sortNumeric);
if (typeof iCol==='undefined'){ }
if(iSortCol!=-1){
var iCol=iSortCol;
} else if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) {
var iCol=5;
} else {
var iCol=iDefaultSortCol;
}
}
function sortTable(tableId, col, asc, numeric) {
//retrieve passed table element //retrieve passed table element
var oTbl=document.getElementById(szTableID).tBodies[0]; var oTbl=document.getElementById(tableId).tBodies[0];
var aStore=[]; var aStore=[];
//If supplied col # is greater than the actual number of cols, set sel col = to last col
if (typeof oTbl.rows[0] !== 'undefined' && oTbl.rows[0].cells.length <= iCol) {
iCol=(oTbl.rows[0].cells.length-1);
}
//store the col #
iSortCol=iCol;
//determine if we are delaing with numerical, or alphanumeric content
var bNumeric = false;
if ((typeof oTbl.rows[0] !== 'undefined') &&
(!isNaN(parseFloat(oTbl.rows[0].cells[iSortCol].textContent ||
oTbl.rows[0].cells[iSortCol].innerText)))) {
bNumeric = true;
}
//loop through the rows, storing each one inro aStore //loop through the rows, storing each one inro aStore
for (var i=0,iLen=oTbl.rows.length;i<iLen;i++){ for (var i=0; i < oTbl.rows.length; ++i){
var oRow=oTbl.rows[i]; var oRow=oTbl.rows[i];
vColData=bNumeric?parseFloat(oRow.cells[iSortCol].textContent||oRow.cells[iSortCol].innerText):String(oRow.cells[iSortCol].textContent||oRow.cells[iSortCol].innerText); var sortKey;
aStore.push([vColData,oRow]); if (numeric) {
sortKey = parseFloat(oRow.cells[col].textContent||oRow.cells[col].innerText);
if (isNaN(sortKey)) {
sortKey = -999999;
}
} else {
sortKey = String(oRow.cells[col].textContent||oRow.cells[col].innerText);
}
aStore.push([sortKey,oRow]);
} }
//sort aStore ASC/DESC based on value of bSortASC if (numeric) { //numerical sort
if (bNumeric) { //numerical sort aStore.sort(function(x,y){ return sortAscending ? x[0]-y[0] : y[0]-x[0]; });
aStore.sort(function(x,y){return bSortASC?x[0]-y[0]:y[0]-x[0];});
} else { //alpha sort } else { //alpha sort
aStore.sort(); aStore.sort();
if(!bSortASC) { if (!sortAscending) {
aStore.reverse(); aStore.reverse();
} }
} }
@ -594,7 +562,6 @@ function sortTable(szTableID,iCol) {
for(var i=0,iLen=aStore.length;i<iLen;i++){ for(var i=0,iLen=aStore.length;i<iLen;i++){
oTbl.appendChild(aStore[i][1]); oTbl.appendChild(aStore[i][1]);
} }
aStore=null;
} }
function selectPlaneByHex(hex) { function selectPlaneByHex(hex) {