English

How To: Use Javascript to Sort Attribute Data in the ArcIMS 4.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, most offen 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 it has not already been created. 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.
//Field Sorting Functions
// start added code for data sorting
//
function sortorder(a){
	ascdesc = a;
}

function compareIt(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(compareIt);
	} 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;
	lastXMLResponse = sendstring;
	displayAttributeData(sendstring);
	sendstring = null;
}

var ascdesc = "ascending";
// end added code for data sorting
 
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.
  1. In the same website folder for the HTML Viewer, open the displayAttributeData.htm file in a text editor.
  1. For ArcIMS 4.0, change the code as shown below.
From:
if (featureCount > 0) {
		t.newSelectCount += 1;

			document.writeln('<title>' + t.titleList[7] + '</title></head>');
			document.writeln('<body bgcolor="' + t.textFrameBackColor + '" text="Black" link="Blue" vlink="Gray" LEFTMARGIN=0 onload="window.focus()">');
			document.writeln('<center>');
			document.writeln('<FONT FACE="Arial" SIZE="-1"><b>' + t.LayerName[t.ActiveLayerIndex] + '</b></FONT>');
			document.writeln('<table border="1" cellspacing="0" cellpadding="2" nowrap bgcolor="' + t.tableBackColor + '">');

		endpos = 1;

To:
if (featureCount > 0) {
		t.newSelectCount += 1;
		
		// modified code for sorting by field - begin
			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;
		// modified code for sorting by field - end
		
			document.writeln('<title>' + t.titleList[7] + '</title></head>');
			document.writeln('<body bgcolor="' + t.textFrameBackColor + '" text="Black" link="Blue" vlink="Gray" LEFTMARGIN=0 onload="window.focus()">');
		
		// modified code for sorting by field - begin
			document.writeln('<form><center>');
			document.writeln('<FONT FACE="Arial" SIZE="-2">');
			if (sorta) {
				var ascdesc = "ascending";
				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</FONT></center><center><FONT FACE="Arial" SIZE="-1" ><b>' + t.LayerName[t.ActiveLayerIndex] + '</b>');
			} else if (sortd) {
				var ascdesc = "descending";
				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</FONT></center><center><FONT FACE="Arial" SIZE="-1" ><b>' + t.LayerName[t.ActiveLayerIndex] + '</b>');
			} else {
				var ascdesc = "ascending";
				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</FONT></center><center><FONT FACE="Arial" SIZE="-1" ><b>' + t.LayerName[t.ActiveLayerIndex] + '</b>');
			}
		// modified code for sorting by field - end
		
			document.writeln('<table border="1" cellspacing="0" cellpadding="2" nowrap bgcolor="' + t.tableBackColor + '">');

		endpos = 1;
 
  1. For ArcIMS 4.0.1, change the code as shown below.
From:
if (featureCount > 0) {
		t_id.newSelectCount += 1;

			document_id.writeln('<title>' + t_id.titleList[7] + '</title></head>');
			document.writeln('<body bgcolor="' + t_id.textFrameBackColor + '" text="Black" link="Blue" vlink="Gray" LEFTMARGIN=0 onload="window.focus()">');
			document.writeln('<center>');
			document.writeln('<FONT FACE="Arial" SIZE="-1"><b>' + t_id.LayerName[t_id.ActiveLayerIndex] + '</b></FONT>');
			document.writeln('<table border="1" cellspacing="0" cellpadding="2" nowrap bgcolor="' + t_id.tableBackColor + '">');

		endpos = 1;

To:
if (featureCount > 0) {
		t_id.newSelectCount += 1;
		
		// modified code for sorting by field - begin
			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;
		// modified code for sorting by field - end
		
			document.writeln('<title>' + t_id.titleList[7] + '</title></head>');
			document.writeln('<body bgcolor="' + t_id.textFrameBackColor + '" text="Black" link="Blue" vlink="Gray" LEFTMARGIN=0 onload="window.focus()">');
		
		// modified code for sorting by field - begin
			document.writeln('<form><center>');
			document.writeln('<FONT FACE="Arial" SIZE="-2">');
			if (sorta) {
				var ascdesc = "ascending";
				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</FONT></center><center><FONT FACE="Arial" SIZE="-1" ><b>' + t_id.LayerName[t_id.ActiveLayerIndex] + '</b>');
			} else if (sortd) {
				var ascdesc = "descending";
				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</FONT></center><center><FONT FACE="Arial" SIZE="-1" ><b>' + t_id.LayerName[t_id.ActiveLayerIndex] + '</b>');
			} else {
				var ascdesc = "ascending";
				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</FONT></center><center><FONT FACE="Arial" SIZE="-1" ><b>' + t_id.LayerName[t_id.ActiveLayerIndex] + '</b>');
			}
		// modified code for sorting by field - end
		
			document.writeln('<table border="1" cellspacing="0" cellpadding="2" nowrap bgcolor="' + t_id.tableBackColor + '">');

		endpos = 1;
This code determines whether the ArcXML response has been sorted and adds the sort method radio buttons to the destination frame. It also adds a form tag necessary for Netscape 4.x.
  1. Change the code as shown below.
  1. For ArcIMS 4.0, change the following code:
From:
				var fName1 = t.getFieldNames(selectedData);
				var fValue1 = t.getFieldValues(selectedData);
				t.selectPoints[t.selectCount] = t.getIdValue(fName1, fValue1);
				
				var idFieldNum = -1;
				var shapeFieldNum = -1;
				if (t.hideIDFieldData) {
					// hide ID column header
					for (var f=0;f<fName1.length;f++) {
						if (fName1[f]==t.LayerIDField[t.ActiveLayerIndex]) idFieldNum = f;
					}
				}
				if (t.hideShapeFieldData) {
					// hide Shape column header
					for (var f=0;f<fName1.length;f++) {
						if (fName1[f]==t.LayerShapeField[t.ActiveLayerIndex]) shapeFieldNum = f;
					}
				}
				
				if (t.selectCount==0) {
					document.write('<tr><th><FONT FACE="Arial" SIZE="-2">' + t.msgList[86] + '</FONT></a></th>');
					for (var f=0;f<fName1.length;f++) {
						if ((f!=idFieldNum) && (f!=shapeFieldNum)) {
							var f2 = -1;
							if (t.useFieldAlias) {
								for (var f3=0;f3<t.AliasFieldName.length;f3++) {
									if (t.AliasFieldName[f3]==fName1[f]) f2 = f3;
								}
							}
							if (f2!=-1) {
								document.write('<th><FONT FACE="Arial" SIZE="-2">' + t.AliasFieldAlias[f2] + '</FONT></a></th>');
							} else {
								document.write('<th><FONT FACE="Arial" SIZE="-2">' + fName1[f] + '</FONT></a></th>');
							}
						}
					}
					document.writeln('</tr>');
				}

To:
				var fName1 = t.getFieldNames(selectedData);
				var fValue1 = t.getFieldValues(selectedData);
				
			// added code for sorting by field - begin
				if (i == 0) {
					t.rexlist = new Array(fCount);
					for(ii = 0;ii < fCount;ii++){
						t.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;
					}
					t.rexlist[xx][jj] = theval1;
				}
				xx = xx + 1;
				t.fldlist = fName1;
				t.therep = theReply;
			// added code for sorting by field - end
			
				t.selectPoints[t.selectCount] = t.getIdValue(fName1, fValue1);
				
				var idFieldNum = -1;
				var shapeFieldNum = -1;
				if (t.hideIDFieldData) {
					// hide ID column header
					for (var f=0;f<fName1.length;f++) {
						if (fName1[f]==t.LayerIDField[t.ActiveLayerIndex]) idFieldNum = f;
					}
				}
				if (t.hideShapeFieldData) {
					// hide Shape column header
					for (var f=0;f<fName1.length;f++) {
						if (fName1[f]==t.LayerShapeField[t.ActiveLayerIndex]) shapeFieldNum = f;
					}
				}
				
				if (t.selectCount==0) {
					document.write('<tr><th><FONT FACE="Arial" SIZE="-2">' + t.msgList[86] + '</FONT></a></th>');
					for (var f=0;f<fName1.length;f++) {
						if ((f!=idFieldNum) && (f!=shapeFieldNum)) {
							var f2 = -1;
							if (t.useFieldAlias) {
								for (var f3=0;f3<t.AliasFieldName.length;f3++) {
									if (t.AliasFieldName[f3]==fName1[f]) f2 = f3;
								}
							}
							
						// added code for sorting by field - begin
							if (f2!=-1) {
								document.write('<th><a href="javascript:parent.MapFrame.sort(' + f + ',' + fCount + ',' + fName1.length + ')"><FONT FACE="Arial" SIZE="-2">' + t.AliasFieldAlias[f2] + '</FONT></a></th>');
							} else {
								document.write('<th><a href="javascript:parent.MapFrame.sort(' + f + ',' + fCount + ',' + fName1.length + ')"><FONT FACE="Arial" SIZE="-2">' + fName1[f] + '</FONT></a></th>');
							}
						// added code for sorting by field - end
							
						}
					}
					document.writeln('</tr>');
				}
  1. For ArcIMS 4.0.1, change the following:
From:
				var fName1 = t_id.getFieldNames(selectedData);
				var fValue1 = t_id.getFieldValues(selectedData);
				t_id.selectPoints[t_id.selectCount] = t_id.getIdValue(fName1, fValue1);
				
				var idFieldNum = -1;
				var shapeFieldNum = -1;
				if (t_id.hideIDFieldData) {
					// hide ID column header
					for (var f=0;f<fName1.length;f++) {
						if (fName1[f]==t_id.LayerIDField[t_id.ActiveLayerIndex]) idFieldNum = f;
					}
				}
				if (t_id.hideShapeFieldData) {
					// hide Shape column header
					for (var f=0;f<fName1.length;f++) {
						if (fName1[f]==t_id.LayerShapeField[t_id.ActiveLayerIndex]) shapeFieldNum = f;
					}
				}
				
				if (t_id.selectCount==0) {
					document.write('<tr><th><FONT FACE="Arial" SIZE="-2">' + t_id.msgList[86] + '</FONT></a></th>');
					for (var f=0;f<fName1.length;f++) {
						if ((f!=idFieldNum) && (f!=shapeFieldNum)) {
							var f2 = -1;
							if (t_id.useFieldAlias) {
								for (var f3=0;f3<t_id.AliasFieldName.length;f3++) {
									if (t_id.AliasFieldName[f3]==fName1[f]) f2 = f3;
								}
							}
							if (f2!=-1) {
								document.write('<th><FONT FACE="Arial" SIZE="-2">' + t_id.AliasFieldAlias[f2] + '</FONT></a></th>');
							} else {
								document_id.write('<th><FONT FACE="Arial" SIZE="-2">' + fName1[f] + '</FONT></a></th>');
							}
						}
					}
					document.writeln('</tr>');
				}

To:
				var fName1 = t_id.getFieldNames(selectedData);
				var fValue1 = t_id.getFieldValues(selectedData);
				
			// added code for sorting by field - begin
				if (i == 0) {
					t_id.rexlist = new Array(fCount);
					for(ii = 0;ii < fCount;ii++){
						t_id.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;
					}
					t_id.rexlist[xx][jj] = theval1;
				}
				xx = xx + 1;
				t_id.fldlist = fName1;
				t_id.therep = theReply;
			// added code for sorting by field - end
			
				t_id.selectPoints[t_id.selectCount] = t_id.getIdValue(fName1, fValue1);
				
				var idFieldNum = -1;
				var shapeFieldNum = -1;
				if (t_id.hideIDFieldData) {
					// hide ID column header
					for (var f=0;f<fName1.length;f++) {
						if (fName1[f]==t_id.LayerIDField[t_id.ActiveLayerIndex]) idFieldNum = f;
					}
				}
				if (t_id.hideShapeFieldData) {
					// hide Shape column header
					for (var f=0;f<fName1.length;f++) {
						if (fName1[f]==t_id.LayerShapeField[t_id.ActiveLayerIndex]) shapeFieldNum = f;
					}
				}
				
				if (t_id.selectCount==0) {
					document.write('<tr><th><FONT FACE="Arial" SIZE="-2">' + t_id.msgList[86] + '</FONT></a></th>');
					for (var f=0;f<fName1.length;f++) {
						if ((f!=idFieldNum) && (f!=shapeFieldNum)) {
							var f2 = -1;
							if (t_id.useFieldAlias) {
								for (var f3=0;f3<t_id.AliasFieldName.length;f3++) {
									if (t_id.AliasFieldName[f3]==fName1[f]) f2 = f3;
								}
							}
							
						// added code for sorting by field - begin
							if (f2!=-1) {
								document.write('<th><a href="javascript:parent.MapFrame.sort(' + f + ',' + fCount + ',' + fName1.length + ')"><FONT FACE="Arial" SIZE="-2">' + t_id.AliasFieldAlias[f2] + '</FONT></a></th>');
							} else {
								document.write('<th><a href="javascript:parent.MapFrame.sort(' + f + ',' + fCount + ',' + fName1.length + ')"><FONT FACE="Arial" SIZE="-2">' + fName1[f] + '</FONT></a></th>');
							}
						// added code for sorting by field - end
							
						}
					}
					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.
  1. For both ArcIMS 4.0 and 4.0.1, change:
From:
document.writeln('</font></center></body>');
To:
// modified code for sorting by field - begin
	document.writeln('</font></form></center></body>');
// modified code for sorting by field - end
This code inserts the closing form tag.
  1. Change the code as shown below.
  1. For ArcIMS 4.0, change:
From:
t.sendMapXML();
To:
// modified code for sorting by field - begin
	if ((!sorta) && (!sortd)) {
	     t.sendMapXML();
	}
// modified code for sorting by field - end
  1. For ArcIMS 4.0.1, change:
From:
t_id.sendMapXML();
To:
// modified code for sorting by field - begin
	if ((!sorta) && (!sortd)) {
	     t_id.sendMapXML();
	}
// modified code for sorting by field - end
This code ensures that the map does not reload when a client sorts an attribute table that was the result of a feature selection.
  1. Save the edits to both the aimsCustom.js and displayAttributeData.htm files. This is an important step. 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