var spaces = "                        "; // string of 24 spaces
Selector.prototype.loadRange = loadRange;
Selector.prototype.loadContaining = loadContaining;
Selector.prototype.printHTML = printHTML;
Selector.prototype.loadRA = loadRA;
Selector.prototype.clearLists = clearLists;
Selector.prototype.doStuff = doStuff;

// Selector class
// The contsructor should be passed the index of the form array the printHTML function is called
function Selector( num ) {
	this.tempNames = new Array();
	this.tempValues = new Array();
	this.thisForm = num;
}


// Selector method
// Sets the array fields in this object and clears the lists in the form
function loadRA( newNames, newValues ) {
	this.tempNames = newNames;
	this.tempValues = newValues;
};


// Selector method
// Moves selected items in array fields that match expression to the running list of the form
function loadContaining( target, list ) {
	list.length = 0;
	var listNames = new Array();
	var listValues = new Array();
	var newi = 0;
	var re = new RegExp( target, "i" );
	for( var i = 0; i < this.tempNames.length; i++ ) {
		if( this.tempNames[i].search(re) != -1 ) {
			listNames[newi] = this.tempNames[i];
			listValues[newi] = this.tempValues[i];
			newi++;
		} //end if
	} //end for

	quickSortNR( listNames, listValues );

	for( var i = 0; i < listNames.length; i++){
		list.options[list.options.length] = new Option( listNames[i], listValues[i] );
	} //end for

	if( list.options.length == 0 ) {
		list.options[0] = new Option( spaces );
	} else if( list.options[0].text.length < 24 ) {
		for(var i = 24 - list.options[0].text.length; i > 0; i-- )
			list.options[0].text += " ";
	}
};


// Selector method
// Empties the lists in the form of this object
// Pass in appropriate boolen for each list you want cleared ie clearLists( false, true ) clears the running list
function clearLists( bRange, bRunning ) {
	if( bRange ) {
		document.forms[this.thisForm].rangeList.options.length = 0;
		document.forms[this.thisForm].rangeList.options[0] = new Option( spaces );
	}
	if( bRunning ) {
		document.forms[this.thisForm].runningList.options.length = 0;
		document.forms[this.thisForm].runningList.options[0] = new Option( spaces );
	}
};


// Selector method
// Moves selected items in array fields that fall in the range to the running list of the form
function loadRange( newFirst, newLast, list ) {
	list.length = 0;
	var listNames = new Array();
	var listValues = new Array();
	var newi = 0;
	var re = new RegExp( "^[" + newFirst.toUpperCase() + "-" + newLast.toUpperCase() + newFirst.toLowerCase() + "-" + newLast.toLowerCase() + "]", "i" );
	for( var i = 0; i < this.tempNames.length; i++ ) {
		if( this.tempNames[i].search(re) != -1 ) {
			listNames[newi] = this.tempNames[i];
			listValues[newi] = this.tempValues[i];
			newi++;
		} //end if
	} //end for

	quickSortNR( listNames, listValues );

	for( var i = 0; i < listNames.length; i++){
		list.options[list.options.length] = new Option( listNames[i], listValues[i] );
	} //end for

	if( list.options.length == 0 ) {
		list.options[0] = new Option(spaces);
	} else if( list.options[0].text.length < 24 ) {
		for(var i = 24 - list.options[0].text.length; i > 0; i-- )
			list.options[0].text += " ";
	}
};


// Selector method
// Returns a pointer to the running list object
function doStuff(  ) {
	return document.forms[this.thisForm].elements[35];
};


// Selector method
// Prints out the HTML for this object
// Needs to have the name of the variable of this object passed in as a string
function printHTML( name ) {
	document.write(
'<table width="800">\n' +
'<form onSubmit="0";>\n' +
'<tr>\n' +
'<td width="250" valign="top" bgcolor=#CCCCCC>\n' +
'<b>Load Range:</b><br>\n' +
'Use First Letter of Library Name:<br>\n' +
'<center><font face="monospace" size="3">\n' +
'<input type="button" value="A" onClick="'+name+'.loadContaining(\'^A\', this.form.rangeList);" /> \n' +
'<input type="button" value="B" onClick="'+name+'.loadContaining(\'^B\', this.form.rangeList);" /> \n' +
'<input type="button" value="C" onClick="'+name+'.loadContaining(\'^C\', this.form.rangeList);" /> \n' +
'<input type="button" value="D" onClick="'+name+'.loadContaining(\'^D\', this.form.rangeList);" /> \n' +
'<input type="button" value="E" onClick="'+name+'.loadContaining(\'^E\', this.form.rangeList);" /> \n' +
'<input type="button" value="F" onClick="'+name+'.loadContaining(\'^F\', this.form.rangeList);" /> \n' +
'<input type="button" value="G" onClick="'+name+'.loadContaining(\'^G\', this.form.rangeList);" /><br /><br />\n' +
'<input type="button" value="H" onClick="'+name+'.loadContaining(\'^H\', this.form.rangeList);" /> \n' +
'<input type="button" value="I" onClick="'+name+'.loadContaining(\'^I\', this.form.rangeList);" /> \n' +
'<input type="button" value="J" onClick="'+name+'.loadContaining(\'^J\', this.form.rangeList);" /> \n' +
'<input type="button" value="K" onClick="'+name+'.loadContaining(\'^K\', this.form.rangeList);" /> \n' +
'<input type="button" value="L" onClick="'+name+'.loadContaining(\'^L\', this.form.rangeList);" /> \n' +
'<input type="button" value="M" onClick="'+name+'.loadContaining(\'^M\', this.form.rangeList);" /> \n' +
'<input type="button" value="N" onClick="'+name+'.loadContaining(\'^N\', this.form.rangeList);" /><br /><br />\n' +
'<input type="button" value="O" onClick="'+name+'.loadContaining(\'^O\', this.form.rangeList);" /> \n' +
'<input type="button" value="P" onClick="'+name+'.loadContaining(\'^P\', this.form.rangeList);" /> \n' +
'<input type="button" value="Q" onClick="'+name+'.loadContaining(\'^Q\', this.form.rangeList);" /> \n' +
'<input type="button" value="R" onClick="'+name+'.loadContaining(\'^R\', this.form.rangeList);" /> \n' +
'<input type="button" value="S" onClick="'+name+'.loadContaining(\'^S\', this.form.rangeList);" /> \n' +
'<input type="button" value="T" onClick="'+name+'.loadContaining(\'^T\', this.form.rangeList);" /> \n' +
'<input type="button" value="U" onClick="'+name+'.loadContaining(\'^U\', this.form.rangeList);" /><br /><br />\n' +
'<input type="button" value="V" onClick="'+name+'.loadContaining(\'^V\', this.form.rangeList);" /> \n' +
'<input type="button" value="W" onClick="'+name+'.loadContaining(\'^W\', this.form.rangeList);" /> \n' +
'<input type="button" value="X" onClick="'+name+'.loadContaining(\'^X\', this.form.rangeList);" /> \n' +
'<input type="button" value="Y" onClick="'+name+'.loadContaining(\'^Y\', this.form.rangeList);" /> \n' +
'<input type="button" value="Z" onClick="'+name+'.loadContaining(\'^Z\', this.form.rangeList);"><br /><br />\n' +
'<input type="button" value=" All " onClick="'+name+'.loadContaining(\'\', this.form.rangeList);"></center><br /><br />\n' +
'</font>\n' +
'Use Range of Letters:<br>\n' +
'<input type="text" name="firstLetter" size="1" maxlength="1"> to <input type="text" name="lastLetter" size="1" maxlength="1"><font face="monospace" size="3"><input type="button" value="  Find  " onClick="'+name+'.loadRange(firstLetter.value, lastLetter.value, this.form.rangeList);">\n' +
'</font>\n' +
'<br><br>\n' +
'Search Library Name Using Keyword:<br>\n' +
'<input type="text" name="target"><font face="monospace" size="3"><input type="button" value="  Find  " onClick="'+name+'.loadContaining(target.value, this.form.rangeList);">\n' +
'</font>\n' +
'</td>\n' +
'<td width="275" valign="top" bgcolor=#CCCCCC>\n' +
'<b>Current Range:</b><br>\n' +
'<font face="monospace" size="3"><select name="rangeList" multiple size="15">\n' +
'<option> ------initializing------\n' +
'</select><br>\n' +
'<input type="button" value="  Add-> " onClick="addEm(this.form.rangeList, this.form.runningList); reset();"> <input type="button" value="Select All" onClick="selectAll(rangeList);">\n' +
'</font>\n' +
'</td>\n' +
'<td width="275" valign="top" bgcolor=#CCCCCC>\n' +
'<b>Running List:</b><br>\n' +
'<font face="monospace" size="3"><select name="runningList" multiple size="15">\n' +
'<option> ------initializing------\n' +
'</select><br>\n' +
'<input type="button" value=" Remove " onClick="remove(runningList);"> <input type="button" value="Select All" onClick="selectAll(runningList);">\n' +
'</font>\n' +
'</td>\n' +
'</tr>\n' +
'</form>\n' +
'</table>\n'
);
};




//////
// Non-recursive quicksort
// stolen from http://resources.inw.com/irt/script/501.htm
// modified to take two parralel arrays and sort them by the first one
// non-recursive was chosen because IE can't handle deep recursion
function quickSortNR( names, values ) {
  var Left  = 0, Right = names.length-1, top = 1;
   var lStack = new Array(), rStack = new Array();
       lStack[top] = Left; rStack[top] = Right;
   while (top!=0) {
     Left  =  lStack[top]; Right =  rStack[top]; top--;
     while (Left < Right) {
       var i = Left, j = Right, n = Left+Right;
       var k = Math.floor(n / 2);
       var x = names[k];
       while (i <= j) {
         while (names[i] < x) { i++; }
         while (names[j] > x) { j--; }
         if (i <= j) {
           var q1 = names[j];
           var q2 = values[j];
           names[j]  = names[i];
           values[j] = values[i];
           names[i]  = q1;
           values[i] = q2;
           i++; j--;
         }
       }
       if ((j - Left) < (Right - i)) {
         if (i < Right) { top++; lStack[top] = i; rStack[top] = Right; }
         Right = j;
       }
       else {
         if (Left < j) { top++; lStack[top] = Left; rStack[top] = j; }
         Left = i;
       }
     }
   }
   return true
}
//
// end Non-recursive quicksort
//////




// Generic function adds selected items from fromList to toList
// Pass in the lists, ie document.forms[0].element[0]
function addEm( fromList, toList ) {
	var j = 0;
	var listNames = new Array();
	var listValues = new Array();
	for( var i = 0; i < toList.length; i++ ) {
	   // Added the test section because for some reason, Firefox compresses
       // the "spaces" variable to an empty string.
       if( toList.options[i].text != spaces && /\S/.test( toList.options[i].text ) ) {
			listNames[j] = toList.options[j].text;
			listValues[j] = toList.options[j].value;
			j++;
		}
	}

	for( var i = 0; i < fromList.options.length; i++ ) {
		if( fromList.options[i].selected && fromList.options[i].text != spaces ) {
			listNames[j] = fromList.options[i].text;
			listValues[j] = fromList.options[i].value;
			j++;
		} //end if
	} //end for

	quickSortNR( listNames, listValues );

	toList.options.length = 0;
	for( var i = 0; i < listNames.length; i++){
		if( listNames[i] != listNames[i+1] && listValues[i] != listValues[i+1] ){
			toList.options[toList.options.length] = new Option( listNames[i], listValues[i] );
		}
	} //end for

	if( toList.options.length == 0 ) {
		toList.options[0] = new Option( spaces );
	} else if( toList.options[0].text.length < 24 ) {
		for(var i = 24 - toList.options[0].text.length; i > 0; i-- )
			toList.options[0].text += " ";
	}
}




// Generic function removes all the selected options in a list
// Pass in a list ie document.forms[0].elements[0]
function remove( list ) {
	var j = 0;
	var listNames = new Array();
	var listValues = new Array();
	for( var i = 0; i < list.options.length; i++ ) {
		if( !list.options[i].selected ) {
			listNames[j] = list.options[i].text;
			listValues[j] = list.options[i].value;
			j++;
		} //end if
	} //end for

	list.options.length = 0;
	for( var i = 0; i < listNames.length; i++){
		if( listNames[i] != listNames[i+1] && listValues[i] != listValues[i+1] ){
			list.options[list.options.length] = new Option( listNames[i], listValues[i] );
		}
	} //end for

	if( list.options.length == 0 ) {
		list.options[0] = new Option( spaces );
	} else if( list.options[0].text.length < 24 ) {
		for(var i = 24 - list.options[0].text.length; i > 0; i-- )
			list.options[0].text += " ";
	}
}




// Generic function selects all of the options in the list
// Pass in a list ie document.forms[0].elements[0]
function selectAll( list ) {
	for( var i = 0; i < list.options.length; i++){
		list.options[i].selected = true;
	} //end for
}

