English

How To: Use Javascript to Sort Attribute Data in the ArcIMS 3.x HTML Viewer

Summary

The Identify and Select functionality in the HTML Viewer return attribute data for features in a selected
layer. The attribute data is usually returned in the form of an HTML table (usually in the TextFrame).
This document provides a method for sorting (ascending and descending) the records in the returned
attributes based on the values in a selected field.

Procedure

  1. Create an HTML Viewer website if one has not already been created.
  2. In the website folder for the HTML Viewer, open the /javascript/aimsCustom.js file in a text editor.
    ADD the following code to the end of the aimsCustom.js file:

    Code:

    //Field Sorting Functions
    //
    function sortorder(a){
    ascdesc = a;
    }

    function compare(a,b) {
    return a - b
    }

    function sort(fldnum,fnum,flds) {
    endlist = new Array();
    newlist = new Array();

    sortmethod = 0;
    for(i = 0;i < fnum;i++){
    newlist[i] = rexlist[i][fldnum];
    var testval1 = parseFloat(newlist[i]);
    if (isNaN(testval1)) {
    sortmethod = 1;
    } else if (testval1.toString().length != newlist[i].toString().length) {
    var st1 = testval1.toString();
    var fval = newlist[i];
    var char1 = st1.length;
    var st2 = fval.charAt(char1);
    var st3 = parseFloat(st2);
    if (isNaN(st3)) {
    sortmethod = 1;
    }
    }

    }

    if (sortmethod == 0) {
    newlist.sort(compare);
    } else if(sortmethod == 1) {
    newlist.sort()
    }

    if (ascdesc == "descending") {
    newlist.reverse();
    }


    env = false;
    if (toolMode!=4) {
    env = true;
    for (var k=0;k < fnum;k++) {
    lft = selectLeft[k];
    bot = selectBottom[k];
    rgt = selectRight[k];
    tp = selectTop[k];
    theenv = '<ENVELOPE minx="' + lft + '" miny="' + bot + '" maxx="' + rgt + '" maxy="' + tp + '" />\n';
    rexlist[k][flds] = theenv;
    }
    flds = flds + 1;
    }

    var x = 0;
    for (t = 0;t < fnum;t++){
    //alert(newlist[t] + 'newlist t' );
    for (j = 0;j < (fnum - x);j++){
    if (rexlist[j][fldnum] == newlist[t]){
    endlist[x] = new Array();
    for (k = 0;k < flds;k++){
    endlist[x][k] = rexlist[j][k];

    }
    rexlist.splice(j,1);
    x = x + 1;
    j = fnum;
    }

    }
    }

    numfeats = newlist.length;
    numfields = fldlist.length;
    morefeats = 'false';
    var endpos = xmlEndPos;
    pos = therep.indexOf('hasmore="true"',endpos);
    if (pos!=-1) morefeats = 'true';
    pos=0;
    endpos = 1;

    if (ascdesc == "ascending") {
    sendstring = '<SORTED ASCENDING><RESPONSE>\n<FEATURES>\n';
    } else if (ascdesc == "descending") {
    sendstring = '<SORTED DESCENDING><RESPONSE>\n<FEATURES>\n';
    }
    for (var k=0;k<numfeats;k++) {
    sendstring = sendstring + '<FEATURE>\n ';
    if (env) {
    sendstring = sendstring + endlist[k][numfields];
    }
    sendstring = sendstring + '<FIELDS ';
    for (var d=0;d<numfields;d++) {

    sendstring = sendstring + fldlist[d] +'="'+ endlist[k][d] +'" ';
    }
    sendstring = sendstring + '/>\n </FEATURE>\n';
    }

    sendstring = sendstring + '<FEATURECOUNT count="'+ numfeats + '" hasmore="' + morefeats +'" />\n </FEATURES>\n </RESPONSE>\n ';

    fldlist = null;
    rexlist = null;
    newlist = null;
    therep = null;
    displayAttributeData(sendstring);
    sendstring = null;

    }

    This code specifies the sorting method and sends the sorted data (in ArcXML response
    format) to the displayAttributeData function in the aimsIdentify.js file function.
  3. In the same website folder for the HTML Viewer, open the /javascript/aimsIdentify.js file
    in a text editor. ADD the following line above the displayAttributeData function:

    Change:

    Code:

    function displayAttributeData(theReply) {

    -to-

    Code:

    var ascdesc = "ascending";
    function displayAttributeData(theReply) {

    This code initializes the variable to identify the sort order.
  4. In aimsIdentify.js REPLACE the following section in the displayAttributeData function:

    Change:

    Code:

    if (featureCount > 0) {
    newSelectCount += 1;
    if (showSelectedData) {
    //alert("displayAttributeData()[opening html page]");
    if ((useExternalWindow) || (!useTextFrame)) {
    Win1 = window.open("","QueryWindow","width=575,height=120,scrollbars=yes,resizable=yes");
    theFrame = "opener";
    if (parent.MapFrame!=null) theFrame = "opener.parent.MapFrame";
    } else {
    Win1 = parent.TextFrame;
    Win1.document.open();
    }
    Win1.document.open();
    Win1.document.writeln('<html><head><title>Query/Selection Results</title></head>');
    Win1.document.writeln('<body bgcolor="' + textFrameBackColor + '" text="Black" link="Blue" vlink="Gray" LEFTMARGIN=0 onload="window.focus()">');
    Win1.document.writeln('<center><FONT FACE="Arial" SIZE="-1"><b>' + LayerName[ActiveLayerIndex] + '</b>');
    Win1.document.writeln('<table border="1" cellspacing="0" cellpadding="2" nowrap bgcolor="' + tableBackColor + '">');
    }
    endpos = 1;

    -to-

    Code:

    if (featureCount > 0) {
    newSelectCount += 1;
    var sorta = false;
    sora = theReply.indexOf('SORTED ASCENDING',0);
    if (sora!=-1) sorta = true;
    var sortd = false;
    sord = theReply.indexOf('SORTED DESCENDING',0);
    if (sord!=-1) sortd = true;


    if (showSelectedData) {
    if ((useExternalWindow) || (!useTextFrame)) {
    Win1 = window.open("","QueryWindow","width=575,height=120,scrollbars=yes,resizable=yes");
    theFrame = "opener";
    if (parent.MapFrame!=null) theFrame = "opener.parent.MapFrame";
    } else {
    Win1 = parent.TextFrame;
    Win1.document.open();
    }
    Win1.document.open();
    Win1.document.writeln('<html><head><title>Query/Selection Results</title></head>');
    Win1.document.writeln('<body bgcolor="' + textFrameBackColor + '" text="Black" link="Blue" vlink="Gray" LEFTMARGIN=0 onload="window.focus()">');
    if (sorta) {
    var ascdesc = "ascending";
    Win1.document.writeln('Sort Method: <INPUT TYPE="radio" NAME="sortorder" VALUE="ascending" onClick="javascript:parent.MapFrame.sortorder(this.value)" CHECKED>Ascending<INPUT TYPE="radio" NAME="sortorder" VALUE="descending" onClick="javascript:parent.MapFrame.sortorder(this.value)">Descending<center><FONT FACE="Arial" SIZE="-1" ><b>' + LayerName[ActiveLayerIndex] + '</b>');
    } else if (sortd) {
    var ascdesc = "descending";
    Win1.document.writeln('Sort Method: <INPUT TYPE="radio" NAME="sortorder" VALUE="ascending" onClick="javascript:parent.MapFrame.sortorder(this.value)" >Ascending<INPUT TYPE="radio" NAME="sortorder" VALUE="descending" onClick="javascript:parent.MapFrame.sortorder(this.value)" CHECKED>Descending<center><FONT FACE="Arial" SIZE="-1" ><b>' + LayerName[ActiveLayerIndex] + '</b>');
    } else {
    var ascdesc = "ascending";
    Win1.document.writeln('Sort Method: <INPUT TYPE="radio" NAME="sortorder" VALUE="ascending" onClick="javascript:parent.MapFrame.sortorder(this.value)" CHECKED>Ascending<INPUT TYPE="radio" NAME="sortorder" VALUE="descending" onClick="javascript:parent.MapFrame.sortorder(this.value)">Descending<center><FONT FACE="Arial" SIZE="-1" ><b>' + LayerName[ActiveLayerIndex] + '</b>');
    }
    Win1.document.writeln('<table border="1" cellspacing="0" cellpadding="2" nowrap bgcolor="' + tableBackColor + '">');
    }
    endpos = 1;

    This code determines whether the ArcXML response has been sorted
    and adds the sort method radio buttons to the destination frame.
  5. In aimsIdentify.js REPLACE the following section in the displayAttributeData function:

    Change:

    Code:

    var fName1 = getFieldNames(selectedData);
    var fValue1 = getFieldValues(selectedData);
    selectPoints[selectCount] = getIdValue(fName1, fValue1);

    if (selectCount==0) {
    Win1.document.write('<tr><th><FONT FACE="Arial" SIZE="-2">Rec</FONT></a></th>');
    for (var f=0;f<fName1.length;f++) {
    var f2 = -1;
    if (useFieldAlias) {
    for (var f3=0;f3<AliasFieldName.length;f3++) {
    if (AliasFieldName[f3]==fName1[f]) f2 = f3;
    }
    }
    if (f2!=-1) {
    Win1.document.write('<th><FONT FACE="Arial" SIZE="-2">' + AliasFieldAlias[f2] + '</FONT></a></th>');
    } else {
    Win1.document.write('<th><FONT FACE="Arial" SIZE="-2">' + fName1[f] + '</FONT></a></th>');
    }
    }
    Win1.document.writeln('</tr>');
    }

    -to-

    Code:

    var fName1 = getFieldNames(selectedData);
    var fValue1 = getFieldValues(selectedData);
    if (i == 0) {
    rexlist = new Array(fCount);
    for(ii = 0;ii < fCount;ii++){
    rexlist[ii] = new Array(fName1.length + 1);
    var xx = 0;
    }
    }

    for (jj = 0;jj < fName1.length;jj++){

    var theval = parseFloat(fValue1[jj]);

    if (isNaN(theval)) {
    theval1 = fValue1[jj];
    }
    else if (theval.toString().length != fValue1[jj].length) {
    var st1 = theval.toString();
    var fval = fValue1[jj];
    var char1 = st1.length;
    var st2 = fval.charAt(char1);
    var st3 = parseFloat(st2);
    if (isNaN(st3)) {
    theval1 = fValue1[jj];
    } else {
    theval1 = theval;
    }
    } else {
    theval1 = theval;
    }

    rexlist[xx][jj] = theval1;

    }
    xx = xx + 1;
    fldlist = fName1;
    therep = theReply;

    selectPoints[selectCount] = getIdValue(fName1, fValue1);

    if (selectCount==0) {
    Win1.document.write('<tr><th><FONT FACE="Arial" SIZE="-2">Rec</FONT></a></th>');
    for (var f=0;f<fName1.length;f++) {
    var f2 = -1;
    if (useFieldAlias) {
    for (var f3=0;f3<AliasFieldName.length;f3++) {
    if (AliasFieldName[f3]==fName1[f]) f2 = f3;
    }
    }
    if (f2!=-1) {
    Win1.document.write('<th><a href="javascript:parent.MapFrame.sort(nothere)"><FONT FACE="Arial" SIZE="-2">' + AliasFieldAlias[f2] + '</FONT></a></th>');
    } else {
    Win1.document.write('<th><a href="javascript:parent.MapFrame.sort(' + f + ',' + fCount + ',' + fName1.length + ')"><FONT FACE="Arial" SIZE="-2">' + fName1[f] + '</FONT></a></th>');
    }
    }
    Win1.document.writeln('</tr>');
    }

    This code creates a multi-dimensional array from the attributes of the selected
    features, determines the data type for each value, and creates hyperlinks from
    each field in the selected features attribute table.
  6. In aimsIdentify.js REPLACE the following section in the displayAttributeData function:

    Change:

    Code:

    sendMapXML();

    -to-

    Code:

    if ((!sorta) && (!sortd)) {
    sendMapXML();
    }

    This code ensures that the map does not reload when a client sorts an attribute
    table that was the result of a feature selection.
  7. BE SURE TO SAVE the edits to both the aimsCustom.js and aimsIdentify.js files. To test,
    load or reload the website in a browser and use the identify or select tool on a set of
    features. The TextFrame will contain two radio buttons indicating the type of sort (ascending
    or descending). Select the type of sort and click on a field name to sort the visible
    records based on the values in that field.

Related Information