

/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */



// Fades an element between two colors and returns to the original color when complete
Element_class.prototype.fadeAttention = function(el,args) {

	el = this.get(el);  if (!el) { return; }
	if (el._fadeTimer) { clearTimeout(el._fadeTimer); }
	args = args || {}

	if (args.startColor && args.endColor) {
		args.startColor = args.startColor.replace(/#/g,"");
		args.endColor = args.endColor.replace(/#/g,"");
		args.steps = args.steps || 10;
		args.colors = fadeHex(args.startColor,args.endColor,args.steps);
	}

	var colors = args.colors || ["ccffcc","d1ffd1","d6ffd6","dbffdb","e0ffe0","e5ffe5","ebffeb","f0fff0","f5fff5","fafffa","ffffff"];

	if (args.reverse) {
		colors.reverse();
	}

	var timing = args.timing || 50; // ms between fade steps

	var i = 0;
	fade();

	function fade() {
		if (i < colors.length-1) {
			el.style.backgroundColor = "#"+colors[i]; 
			i++;
			el._fadeTimer = setTimeout(fade,timing);
			return;
		}
		else if (args.callback) {
			args.callback();
		}
		el.style.backgroundColor = ""; // reset to CSS default when done
		el._fadeTimer = null;
	}


	function fadeHex (hex1, hex2, steps){
		hex1 = (parseInt("0x"+hex1,16)); // convert strings to hex
		hex2 = (parseInt("0x"+hex2,16));
	
		var ratio, color, colors = [], r, g, b;
		var pad =["000000","00000","0000","000","00","0",""]
		steps--;
		for (var i=0; i<steps+1; i++) {
			ratio = (i==steps) ? 1 : (1/steps)*i;
			r = hex1 >> 16;
			g = hex1 >> 8 & 0xFF;
			b = hex1 & 0xFF;
			r += ((hex2 >> 16)-r)*ratio;
			g += ((hex2 >> 8 & 0xFF)-g)*ratio;
			b += ((hex2 & 0xFF)-b)*ratio;
			color = (r<<16 | g<<8 | b).toString(16)
			color = pad[color.length] + color;
			colors.push(color);
		}
	
		return colors;
	
	}



}



// Converts a form to an object based on the name/id used for each field
Element_class.prototype.formToObject = function(f,args) {

	args = args || {};
	var obj = {values:args.values||{},elements:{}};
	args.valueMap = args.valueMap || {};
	f = Element.get(f);
	obj = obj || {};
	var els = f.elements;
	var el, tag, type, name, id, elName;
	var val = "";
	elLoop: for (var i=0; i<els.length; i++) {
		val = "";
		el = els[i];
		tag = el.tagName.toLowerCase();
		id = el.id
		name = el.getAttribute("name")
		type = el.getAttribute("type")

		if (tag == "input") {
			if (/text|hidden|password/.test(type)) { val = el.value; }
			else if (type == "radio") {
				for (var x=0; x<f[name].length; x++) {
					if (f[name][x].checked) { val = f[name][x].value; break; }
				}
			}
			else if (type == "checkbox") {
				val = el.checked ? (el.value || 1) : ""; // return either the value or 1 if checked, or "" if not checked
			}

		}
		else if (tag == "textarea") {
			val = el.value;
		}
		else if (tag == "select") {
			var vals = [];
			var options = el.getElementsByTagName("option");

			for (var x=0; x<options.length;x++) {
				if (options[x].selected) {

					vals.push(options[x].value || options[x].text);
				}
			}
			val = vals.join(",");
		}


		// use name then id and assign to mapped value or element's value
		elName = name || id || null; //(tag+i);
		if (!elName) { // don't include elements with out a handle
			continue;
		}
		obj.values[elName] = args.valueMap[val] != undefined ? args.valueMap[val] : val;
		obj.elements[elName] = el;


	}

	return args.elements ? obj : obj.values;

}


// Popuplates a form from an object
Element_class.prototype.objectToForm = function(f,obj) {

	f = Element.get(f);

	obj = obj || {};
	obj.values = obj.values || {};

	for (var name in obj) {
		if (f[name]) {
			// todo - switch on tagname for radio/checkbox support
			f[name].value = obj[name];
		}
	}


}


// Converts an object to a URL parameter string
Element_class.prototype.objectToParams = function(obj) {
	var params = [];
	for (var i in obj) {
		params.push(i + "=" + encodeURIComponent(obj[i]));
	}
	return params.join("&");
}





Element_class.prototype.getXYRelative = function(el) {
    el = this.get(el);
    if(!el){ return; }


	var x = 0, y = 0;

    if(el.offsetParent)  {
	    var x = el.offsetLeft;
	    var y = el.offsetTop;
    }

    return {x:x, y:y};
}



/* -- Loaded:/tdameritrade/common/scripts/Element.3additions.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */





// Builds a HTML Select element based on different data structures and specified data format. 
// Appends to a optionally specified container and returns the DOM element
// args - data, format of data (text/value property names), selected values
// attributes - passed along to Element.create's 2nd parameter
Element_class.prototype.buildSelect = function(args,attributes,parentElement) {

	attributes = attributes || {};

	// get the passed element, by ID, or create it with the specified attributes
	var select = args.element || Element.get(attributes.id || "NoSelectIdSpecified") || Element.create("select",attributes);

	Element.removeChildNodes(select);

	var data = args.data || [];
	var firstOption = args.firstOption || null;
	var firstOptionSelected = args.firstOptionSelected || null;
	var valProperty = args.value || "value";
	var textProperty = args.text || "text";
	var option, optionVal;
	var options = [];
	var selected = args.selected || "";
	if (selected instanceof Array) {
		selected = selected.join("{}"); // join an array of selected options for the RegExp comparison below
	}
	if (firstOption) {
		var attributes = {value:firstOption.value};
		firstOptionSelected ? attributes.selected = "selected" : null;
		Element.create("option", attributes, firstOption.text, select);
	}

	var optionVal, optionText, option, attributes;

	// array structure - ["CO","AR"] or [{"l":"Label","v":"Value"}]
	if (data instanceof Array) { 

		for (var i=0; i<data.length; i++) { 
			optionVal = (data[i][valProperty] || data[i][textProperty] || data[i]);
			optionText = (data[i][textProperty] || data[i][valProperty] || data[i]);
			attributes = {value:optionVal};

			option = Element.create("option", attributes, optionText, select);
			options.push(option);
		} 

	}

	// object structure - {"CO":"Colorado,"AR":"Arizona"} or {1:{text:"Colorado",value:"CO},2:{text:"Arizona",value:"AZ"}}
	else {

		for (var i in data) { 
			optionVal = i;
			optionText = data[i][textProperty] || data[i][valProperty] || data[i];
			attributes = {value:optionVal};

			option = Element.create("option", attributes, optionText,select);
			options.push(option);
		} 
	}


	function updateSelect() {

			for (var i=0; i<options.length; i++) {

				if ( 

					// select option if starts/ends with selected value            // escape reserved RE characters
					selected.match("(({})|^)" + String(options[i].value).replace(/([/.+()])/g,"\\$1") + "(({})|$)")
					||
					(args.selectedMatchText && selected.match("(({})|^)" + String(options[i].text).replace(/([/.+()])/g,"\\$1") + "(({})|$)"))
				) {
					try {
					options[i].selected = true;
					}
					catch(e) { }
				}
				else {

					options[i].selected = false;
				}
			}

	}

	if (selected) {
		// A short delay is needed for IE to respect selecting of multiple=multiple options
		var delay = (document.all && select.getAttribute("multiple")) ? (args.selectedDelay || 5) : 0;
		delay ?	setTimeout(function() { updateSelect(); }, delay) : updateSelect();
	}

	if (args.disabled) {
		Element.setAttribute(select,"disabled","disabled");
	}

	if (parentElement) {
		Element.addChild(parentElement,select);
	}

	return select;

}



/*
Override for parseSelector that supports an array for the "node" parameter
*/
// implemented in library
Element_class.prototype.XXXparseSelector = function() {
	var SEPERATOR = /\s*,\s*/;
	
	function parseSelector(selector, node, num) {

		node = node || document.documentElement;
		node = this.get(node);

		var argSelectors = selector.split(SEPERATOR);
		var result = [];
		
		for(var i = 0; i < argSelectors.length; i++) {

			var stream = toStream(argSelectors[i]), prevToken;

			if (this.isArray(node)) {
				var nodes = node;
				// remove * and " " put in by toStream if it starts with a non alphanumeric 
				if (!argSelectors[i].match(/^[A-Za-z1-9]/)) {
					while (stream[0] && stream[0].match(/[* ]/)) { stream.shift(); }
				}
			}
			else {
				var nodes = [node]
			}


			for(var j = 0;j < stream.length;) {

				var token = stream[j++];

				var args = '';
				if (token == "[") {
					args = stream[j];
					while(stream[j++] != ']' && j < stream.length) { args += stream[j] };
					args = args.slice(0, -1);
					var filter = "";
				}
				else {
					var filter = stream[j++];
				}

				if(stream[j] == '(') {
					while(stream[j++] != ')' && j < stream.length) args += stream[j];
					args = args.slice(0, -1);
				}

				prevToken = token;
				nodes = select(nodes, token, filter, args);
			}
			result = result.concat(nodes);
		}
		
		// simple selection of an individual node
		  if (num != undefined) {

			if (result.length) {
				var REMatch;
	
				if (num == "first") {
					return result[0]
				}
				else if (num == "last") {
					return result[result.length-1]
				}
				else if (REMatch = String(num).match(/nth\((.*)\)/) || num == "even") { // even is the same as nth(2) 
					if (num == "even") num = 2;
					else num = REMatch[1];
		
					var result2 = [];
					for (var i=0,len=result.length; i<len;i++) {
						if (i%num == 0) { result2.push(result[i]); }
					}
					return result2;
				}
				else if (num == "odd") {
					var result2 = [];
					for (var i=0,len=result.length; i<len;i++) {
						if (i%2 != 0) { result2.push(result[i]); }
					}
					return result2;
				}
				else if (!isNaN(num) && result.length >= num) {
					return result[num]
				}
				else {
					return null; // num passed, but no matches or unsupported type
				}
			}
			else {
				return null;
			}
		
		  }

		return result;
	}

	var WHITESPACE = /\s*([\s>+~(),]|^|$)\s*/g;
	var IMPLIED_ALL = /([\s>+~,]|[^(]\+|^)([#.:@])/g;
	var STANDARD_SELECT = /^[^\s>+~]/;
	var STREAM = /[\s#.:>+~[\]()@!]|[^\s#.:>+~[\]()@!]+/g;
		
	function toStream(selector) {
		var stream = selector.replace(WHITESPACE, '$1').replace(IMPLIED_ALL, '$1*$2');
		if(STANDARD_SELECT.test(stream)) stream = ' ' + stream;
    return stream.match(STREAM) || [];
	}
	
	function select(nodes, token, filter, args) {
		return (selectors[token]) ? selectors[token](nodes, filter, args) : [];
	}
	
	var util = {
		toArray: function(enumerable) {
			var a = [];
			for(var i = 0; i < enumerable.length; i++) a.push(enumerable[i]);
			return a;
		},
		
		push: function(arr,val) {
			arr.push(val)
      		//for(var i = 1; i < arguments.length; i++) arr[arr.length] = arguments[i];
      		return arr.length;
    	}
	};
	
	var dom = {
		isTag: function(node, tag) {
			return (tag == '*') || (
				tag.toLowerCase() == node.nodeName.toLowerCase().replace(':html', '')
			);
		},
	
		previousSiblingElement: function(node) {
			do node = node.previousSibling; while(node && node.nodeType != 1);
			return node;
		},
	
		nextSiblingElement: function(node) {
			do node = node.nextSibling; while(node && node.nodeType != 1);
			return node;
		},
	
		hasClass: function(name, node) {
			return (node.className || '').match('(^|\\s)'+name+'(\\s|$)');
		},
	
		getByTag: function(tag, node) {
			/*	IE5.x does not support document.getElementsByTagName("*")
				therefore we're falling back to element.all */
			if(tag == '*') {
			  var nodes = node.getElementsByTagName(tag);
			  if(nodes.length == 0 && node.all != null) return node.all
			  return nodes;
		  }
			return node.getElementsByTagName(tag);
		}
	};

	var selectors = {
		'#': function(nodes, filter) {
			for(var i = 0; i < nodes.length; i++) {
				if(nodes[i].getAttribute('id') == filter) return [nodes[i]];
			}
			return [];
		},

		' ': function(nodes, filter) {
			var result = [];
			for(var i = 0; i < nodes.length; i++) {
				result = result.concat(util.toArray(dom.getByTag(filter, nodes[i])));
			}
			return result;
		},
		
		'>': function(nodes, filter) {
			var result = [];
			for(var i = 0, node; i < nodes.length; i++) {
				node = nodes[i];
				for(var j = 0, child; j < node.childNodes.length; j++) {
					child = node.childNodes[j];
					if(child.nodeType == 1 && dom.isTag(child, filter)) {
						result.push(child);
					}
				}
			}
			return result;
		},

		'.': function(nodes, filter) {
			var result = [];
			for(var i = 0, node; i < nodes.length; i++) {
				node = nodes[i];
				if(dom.hasClass([filter], node)) result.push(node);
			}
			return result;
		}, 

		'!': function(nodes, filter) {
			var result = [];
			for(var i = 0, node; i < nodes.length; i++) {
				node = nodes[i];
				if(!dom.hasClass([filter], node)) result.push(node);
			}
			return result;
		}, 
				
		':': function(nodes, filter, args) {
			return (pseudoClasses[filter]) ? pseudoClasses[filter](nodes, args) : [];
		},


		'+': function(nodes, filter) {
			var result = [];
			for(var i = 0, node; i < nodes.length; i++) {
				node = nodes[i];
				var sibling = parseSelector.dom.nextSiblingElement(node);
				if(sibling && parseSelector.dom.isTag(sibling, filter)) {
					result.push(sibling);
				}
			}
			return result;
		},
		'~': function(nodes, filter) {
			var result = [];
			for(var i = 0, node; i < nodes.length; i++) {
				node = nodes[i];
				var sibling = parseSelector.dom.previousSiblingElement(node);
				if(parseSelector.dom.isTag(sibling, filter)) result.push(sibling);
			}


			return result;
		},
		'[': function(nodes, filter, args) { // CSS Attribute
			args = args.replace(/'/g,'"'); // allow single quotes

			var attributeProps = [];
			if (!/[<>=]/.test(args)) { // has operator test
				attributeProps = ["",args,"",""];
			}
			else {
				var params = args.match(/([^!^$*\/.<>=]*)(!\*=|\*=|\$=|!\$=|\^=|\/=|!\/=|<=|>=|<|>|!=|=)(\.*)(i?)(["'`])([^\5]*)(\5)/); 
									//   (attName)       (operator)                                 (type)   (caseinsenstive)[quote](value)[quote]
				if (params) { attributeProps = params; }
			}	

			//alert(attributeProps )
			attributeProps = {name:attributeProps[1],operator:attributeProps[2],isStyle:attributeProps[3]=="..",isProperty:attributeProps[3]==".",casei:attributeProps[4]?true:false,value:attributeProps[6],isValue:(attributeProps[5]=="`")};

			// Leave this line for debuging purposes
			//alert(args + "\n att: " + attributeProps.name + "\n operator: " + attributeProps.operator + "\n val: "  + attributeProps.value + "\n isStyle: " + attributeProps.isStyle + "\n isProperty: " + attributeProps.isProperty + "\n isValue: " + attributeProps.isValue + "\n casei: "  + attributeProps.casei)

			if (attributeProps.casei) { attributeProps.value = attributeProps.value.toLowerCase(); }

			var result = [];
			for(var i = 0, node, att, val, el; i < nodes.length; i++) {
				node = el = nodes[i];	

			
				if (attributeProps.isStyle) {
					att = Element.getStyle(node,attributeProps.name);
					if (!att) continue;
				}	
				else if (attributeProps.isProperty) {
					if (node[attributeProps.name] != undefined) {
						var att = node[attributeProps.name];
					}
					else {
						continue;
					}
				}
				else {
					att = node.getAttribute(attributeProps.name);
					if (!att) continue;
				}

				if (/[*^$\/]/.test(attributeProps.operator)) { // so .match complies
					att = String(att)				
				}

				if (attributeProps.casei) { att = att.toLowerCase(); }

				val = attributeProps.value;

				//alert("Tag: " + el.tagName + ", ID: " + el.id + " , Att: " + att + ", Operator: " + attributeProps.operator + ", Val: " + val);
				if (attributeProps.isValue) { val = eval(val.replace(/`/g,"'")); }

				if (!attributeProps.operator) {
					result.push(nodes[i])
				}
				else {


					switch(attributeProps.operator){
						case '=': if (att == val) result.push(node); break;
						case '!=': if (att != val) result.push(node); break;
						case '*=': if (att.match(val)) result.push(node); break;
						case '!*=': if (!att.match(val)) result.push(node); break;
						case '^=': if (att.match('^'+val)) result.push(node); break;
						case '!^=': if (!att.match('^'+val)) result.push(node); break;
						case '$=': if (att.match(val+'$')) result.push(node); break;
						case '!$=': if (!att.match(val+'$')) result.push(node); break;
						case '/=': if (att.match(val)) result.push(node); break;
						case '!/=': if (!att.match(val)) result.push(node); break;
						case '>=': if (att >= val) result.push(node); break;
						case '>': if (att > val) result.push(node); break;
						case '<=': if (att <= val) result.push(node); break;
						case '<': if (att < val) result.push(node); break;
					}	
				}
			}
			return result;

		}
		
	};

	parseSelector.selectors			= selectors;
	var pseudoClasses = { };
	parseSelector.pseudoClasses 			= pseudoClasses;
	parseSelector.util 				  = util;
	parseSelector.dom 				  = dom;
	return parseSelector.apply(this,arguments);
};




/* -- Loaded:/tdameritrade/screener/Element.3additions.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */




/* This class along with CSS (below) will create a transparent drop shadow for any element.
var shadowDiv = new DropShadow({element: popupDiv});

Example CSS
.div-dropshadow {opacity:.40; filter: alpha(opacity=40); -moz-opacity: 0.40; border-right: 1px solid #c6c6c; border-bottom: 1px solid #c6c6c6; }
.shadow2 { border-right: 1px solid #a9a9a9; border-bottom: 1px solid #a9a9a9;}
.shadow3 { border-right: 1px solid #848484; border-bottom: 1px solid #848484;}
.shadow4 { border-right:  1px solid #686868; border-bottom:  1px solid #686868;}
.shadow5 { border-right: 1px solid #525252; border-bottom: 1px solid #525252;}

NOTE: popupDiv MUST HAVE z-index set
*/

function DropShadow(params) {
	this.shadow;
	this.element = params.element; // required
	this.element.monitor = params.monitor || false; // boolean to monitor popup visibility
	this.zIndex = Element.getStyle(this.element, "z-index") || 2; // required css declartion for popup div
	this.hOffset = params.offset || params.hOffset || 4; // horizontal offset
	this.vOffset = params.vOffset || this.hOffset || 4; // vertical offset
	this.thickness = params.thickness || 1; // thickness must match border width
	
	// this will cover form elements in IE
	this.initIframe = (document.all) && (params.iframe);
	if ( this.initIframe ) {
		this.iframe;
	}
	
	this.initDropShadow();
}

DropShadow.prototype.initDropShadow = function() {
	this.renderDropShadow();
	this.positionDropShadow();
	this.resizeDropShadow();

	if ( this.element.monitor ) {
		var self = this;
		this.monitorInterval = setInterval(function() { self.monitor(); },20);
	}
}

DropShadow.prototype.monitor = function() {

	if (!this.element || !this.element.parentNode) {

		this.closeDropShadow();
		clearInterval(this.monitorInterval);

	}
	else {

		var elementVisible = Element.isOnScreen(this.element);
	
		if ( !elementVisible ) {
			Element.setVisibility(this.shadow,"hidden");
		} else {
			Element.setVisibility(this.shadow,"visible");
			this.positionDropShadow();
			this.resizeDropShadow();
		}

	}



}

DropShadow.prototype.renderDropShadow = function() {
	this.shadow = Element.create("div", {className:"div-dropshadow"}, [
		Element.create("div", {className:"shadow2"}, [
			Element.create("div", {className:"shadow3"}, [
				Element.create("div", {className:"shadow4"}, [
					Element.create("div", {className:"shadow5"}, "")
				])
			])
		])
	], document.body);

	Element.setStyle(this.shadow, "position:absolute; z-index:"+(this.zIndex - 1));

	if ( this.initIframe ) {
		this.iframe = Element.create("iframe", {scrolling:"no",frameBorder:0,src:"javascript:void(0);", style:"z-index: "+(this.zIndex - 2)+"; position: absolute; border: 0px solid red;"}, "", document.body);
	}
	
	return this.shadow;
}

DropShadow.prototype.positionDropShadow = function() {
	var xy = Element.getXY(this.element);
	Element.setXY(this.shadow, xy.x + this.hOffset, xy.y + this.vOffset);
	
	if ( this.iframe ) {
		Element.setXY(this.iframe, xy.x-1, xy.y-1);
	}
}

DropShadow.prototype.resizeDropShadow = function() {
	var size = Element.getSize(this.element);
	Element.setSize(this.shadow, size.width, size.height);

	var cursor = this.shadow;
	Element.setHeight(cursor = cursor.firstChild, (size.height - 1 * this.thickness));
	Element.setHeight(cursor = cursor.firstChild, (size.height - 2 * this.thickness));
	Element.setHeight(cursor = cursor.firstChild, (size.height - 3 * this.thickness));
	Element.setHeight(cursor = cursor.firstChild, (size.height - 4 * this.thickness));

	if ( this.iframe ) {
		Element.setSize(this.iframe, size.width + this.hOffset+1, size.height + this.vOffset+1);
	}
}
DropShadow.prototype.update = function() {
	this.positionDropShadow();
	this.resizeDropShadow();
}


DropShadow.prototype.closeDropShadow = function() {
	Element.remove(this.shadow);
	this.shadow = null;
	
	if ( this.iframe ) {
		Element.remove(this.iframe);
		this.iframe = null;
	}	
}
DropShadow.prototype.remove = DropShadow.prototype.closeDropShadow;

/* -- Loaded:/tdameritrade/screener/dropshadow.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */


Function.getClassName = function() {
	return "Function";
};


/* Extend from another prototyped Function */
Function.prototype.Extend = function(superClass) {
	this.prototype = new superClass();

	this.prototype.getSuperClass = function() {
		return superClass;
	};
	this.getSuperClass = this.prototype.getSuperClass;
	return this;
};

/*
The Super method allows us to do the constructor (or any super call) chaining more easily.  It looks like this:

var A = function() {
  this.value = ["1"]
}

var B = function() {
  B.Super(this);
  this.value.push("2");
}

Super calls for non constructor methods look like:
Class.Super(this, "methodName", arguments);
*/

Function.prototype.Super = function(context, methodName, args) {
	if (null != methodName) {
		var method = this.getSuperClass().prototype[methodName];
	}
	else {
		var method = this.getSuperClass();
	}

	if (!args) {
		return method.call(context);
	}
	else {
		return method.apply(context, args);
	}
};

/*
Function.Implements
It takes either an instanciated object or a functor, and a list of properties/methods and add
them to the calling functor.  Be careful not to apply methods that call other methods/object in
the passed functor/object that do not exist in the calling functor.
*/
Function.prototype.Implements = function(obj, members) {
	if(typeof obj == "function") {
		obj = obj.prototype;
	}
	var tObj = {}
	for(var i = 0, len = members.length; i < len; ++i) {
		tObj[members[i]] = obj[members[i]] || null;
	}
	var o = WSDOM.Util.copyObject(tObj);
	for(var i in o) {
		this.prototype[i] = o[i];
	}
};

/* Used to be 'hitch'.  Now it works right. */
Function.prototype.Context = function(obj) {
	var fnReference = this;
	return function () {
		return typeof fnReference == "function" ? fnReference.apply(obj, arguments) : obj[fnReference].apply(obj, arguments);
	};
};
Function.prototype.EmptyFunction = function() {};

/* -- Loaded:/includes/jslib/Function/Function.1.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */


var EventSource = function(type) {
	this.listeners = [];
	this.type = type;
};

EventSource.prototype.addListener = function(listener, context) {
	if (listener instanceof Function) {
		listener = {
			handler: listener,
			context: context
		}
	}
	
	if (!listener.context) {
		listener.context = window;
	}
	this.listeners.push(listener);
	return listener;
};

EventSource.prototype.removeListener = function(listener) {
	for (var i=0; i<this.listeners.length; i++) {
		if (listener == this.listeners[i]) {
			this.listeners.splice(i,1);
		}
	}
};

EventSource.prototype.removeAll = function() {
	this.listeners = [];
};

EventSource.prototype.fire = function() {
	Array.prototype.unshift.call(arguments, this.type);
	
	for (var i=0; i<this.listeners.length; i++) {
		this.listeners[i].handler.apply(this.listeners[i].context, arguments);
	}
};

var DOMEventSource = function(type) {
	DOMEventSource.Super(this, null, arguments);
	this.delayTimeouts = [];
	this.typeIE = "on" + this.type;
	this.elements = [];
};
DOMEventSource.Extend(EventSource);

DOMEventSource.prototype._getBrowserEventName = function() {
	switch (this.type) {
		case "load": 	case "change": 	case "reset":
		case "select":	case "submit": 	case "blur":
		case "focus": 	case "resize": 	case "scroll":
		case "abort":	case "error":	case "unload":
			return "HTMLEvents";
					
		case "mouseover": 	case "mouseout": 	case "click":
		case "dblclick":  	case "mouseup": 	case "mousedown":
		case "mouseenter": 	case "mouseleave":	case "mousemove":
		case "contextmenu": case "dragstart":	case "selectstart":
			return "MouseEvents";
		
		case "keypress": case "keydown": case "keyup":
			return "UIEvents";
		
		default:
			return null;
	}
};

DOMEventSource.prototype._validateEvent = function(e, listener){
	if (listener.keyCode && "UIEvents" == this._getBrowserEventName()) {
		return listener.keyCode == e.nativeEvent.keyCode;
	}
	
	return true;
};

DOMEventSource.prototype._createDOMHandlerClosure = function(listener, element) {
	var theDOMEventSource = this;
	for (var i=0, DOMHandler; i<element.length; i++) {
		DOMHandler = function() {
			var el = element[i].node;
			if (listener.delay) {
				return function() {
					var e = window.event || arguments[0];
					
					// because browsers rewrite values after event goes out of scope
					var newEvt = {};
					for (var i in e) {
						newEvt[i] = e[i];
					}
					
					e = new DOMEvent(newEvt);
					
					theDOMEventSource.clearDelayTimeouts();
					theDOMEventSource.delayTimeouts.push(window.setTimeout(
						function() {
							if(theDOMEventSource._validateEvent(e, listener)){
								listener.handler.call(listener.context, e, el, listener.data);
							}
						}
					, listener.delay));
				}
			}
			else {
				return function() {
					var e = new DOMEvent(window.event || arguments[0]);
					if(theDOMEventSource._validateEvent(e, listener)){
						listener.handler.call(listener.context, e, el, listener.data);
					}
				}
			}
		}();
		
		this._addEventListener(element[i].node, DOMHandler);
		element[i].registeredListeners.push({ DOMHandler: DOMHandler, listener: listener });
	}
};

DOMEventSource.prototype.addElement = function(element /* element or array of elements */, removeIfExisting) {
	if (!(element instanceof Array)) {
		element = [element];
	}
	
	if (removeIfExisting) {
		this.removeElement(element);
	}
	
	var elements = [];
	for (var i=0; i<element.length; i++) {
		elements.push({
			node: element[i],
			registeredListeners: []
		});
	}
	
	for (var i=0; i<this.listeners.length; i++) {
		this._createDOMHandlerClosure(this.listeners[i], elements);
	}
	
	this.elements = this.elements.concat(elements);
};

DOMEventSource.prototype.removeElement = function(element) {
	var element = [].concat(element);
	
	for (var i=0, elWrapper; i<this.elements.length; i++) {
		elWrapper = this.elements[i];
		
		if (!element.length) {
			break;
		}
		
		for (var j=0, el; j<element.length; j++) {
			el = element[j];
			
			if (elWrapper.node === el) {
				
				for (var k=0; k<elWrapper.registeredListeners.length; k++) {
					this._removeEventListener(el, elWrapper.registeredListeners[k].DOMHandler);
				}
				
				element.splice(j, 1);
				this.elements.splice(i, 1);
				
				j--;
				i--;
			}
		}
	}

};

DOMEventSource.prototype.removeAll = function() {
	this.removeAllElements();
	this.listeners = [];
};

DOMEventSource.prototype.removeAllElements = function() {
	for (var i=0, el; i<this.elements.length; i++) {
		el = this.elements[i];
		
		for (var j=0; j<el.registeredListeners.length; j++) {
			this._removeEventListener(el.node, el.registeredListeners[j].DOMHandler);
		}
	}
	this.elements = [];
};

DOMEventSource.prototype.addListener = function(listener, context, delay) {
	if (listener instanceof Function) {
		listener = {
			handler: listener,
			context: context,
			delay: delay
		}
	}
	
	if (!listener.context) {
		listener.context = window;
	}
	
	this._createDOMHandlerClosure(listener, this.elements);
	
	this.listeners.push(listener);
	return listener;
};

DOMEventSource.prototype.removeListener = function(listener) {
	for (var i=0, el; i<this.elements.length; i++) {
		el = this.elements[i];
		
		for (var j=0, rl; j<el.registeredListeners.length; j++) {
			rl = el.registeredListeners[j];
			
			if (rl.listener == listener) {
				this._removeEventListener(el.node, rl.DOMHandler);
				el.registeredListeners.splice(j, 1);
				break;
			}
		}
	}
	
	for (var i=0, listener; i<this.listeners.length; i++) {
		if (listener == this.listeners[i]) {
			this.listeners.splice(i, 1);
			break;
		}
	}
};

DOMEventSource.prototype.fire = function(element /* optional element or array of elements */) { 
	if (undefined == element) {
		// fire on all elements
		for (var i=0; i<this.elements.length; i++) {
			this._dispatchEvent(this.elements[i].node);					
		}
	}
	else {
		if (!(element instanceof Array)) {
			element = [element];
		}
		
		for (var i=0; i<element.length; i++) {
			this._dispatchEvent(element[i]);
		}
	}
};

DOMEventSource.prototype._addEventListener = function(el, handler) {
	if (document.attachEvent) {
		DOMEventSource.prototype._addEventListener = function(el, handler) {
			el.attachEvent(this.typeIE, handler);
		};
	}
	else if (document.addEventListener) {
		DOMEventSource.prototype._addEventListener = function(el, handler) {
			el.addEventListener(this.type, handler, false);
		};
	}
	this._addEventListener = DOMEventSource.prototype._addEventListener;
	this._addEventListener(el, handler);
};

DOMEventSource.prototype._removeEventListener = function(el, handler) {
	if (el.detachEvent) {
		DOMEventSource.prototype._removeEventListener = function(el, handler) {
				el.detachEvent(this.typeIE, handler);
		};
	}
	else if (el.removeEventListener) {
		DOMEventSource.prototype._removeEventListener = function(el, handler) {
			el.removeEventListener(this.type, handler, false);
		};
	}
	this._removeEventListener = DOMEventSource.prototype._removeEventListener;
	this._removeEventListener(el, handler);
};

DOMEventSource.prototype._dispatchEvent = function(el) {
	if (document.createEventObject) {
		DOMEventSource.prototype._dispatchEvent  = function(el) {
			var event = document.createEventObject();
				event.srcElement = el;
				event.type = this.type;
				
			el.fireEvent(this.typeIE, event);
		};
	}
	else {
		DOMEventSource.prototype._dispatchEvent = function(el) {
			var event = document.createEvent(this._getBrowserEventName(this.type));
				event.initEvent(this.type, true, true);
				
			el.dispatchEvent(event);
		};	
	}
	this._dispatchEvent = DOMEventSource.prototype._dispatchEvent;
	this._dispatchEvent(el);
};

DOMEventSource.prototype.clearDelayTimeouts = function() {
	for (var i=0; i<this.delayTimeouts.length; i++) {
		window.clearTimeout(this.delayTimeouts[i]);
	}
	this.delayTimeouts = [];
};


var DOMEvent = function(nativeEvent) {
	this.nativeEvent = nativeEvent;
};

DOMEvent.prototype.cancel = function() {
	if (this.nativeEvent.stopPropagation) {
		this.nativeEvent.stopPropagation();
	} 
	else {
		try { this.nativeEvent.cancelBubble = true; } catch(e) {}
	}
	if (this.nativeEvent.preventDefault) {
		this.nativeEvent.preventDefault();
	} 
	else {
		try { this.nativeEvent.returnValue = false; } catch(e) {}
	}
	
	
	return this.nativeEvent;
};

DOMEvent.prototype.getTarget = function() {
	var target = this.nativeEvent.srcElement || this.nativeEvent.target;
	
	this.getTarget = function() {
		return target;
	}
	return this.getTarget();
};

var EventManager = function() {
	this.events = [];
	this.add(window, "unload", this.removeAll, this);
};

EventManager.prototype.KEYCODES = {
	Backspace:8
	,TAB:9
	,ENTER:13
	,SHIFT:16
	,CTRL:17
	,ALT:18
	,CAPS:20
	,ESCAPE:27
	,PAGEUP:33
	,PAGEDOWN:34
	,END:35
	,HOME:36
	,LEFT:37
	,UP:38
	,RIGHT:39
	,DOWN:40
	,INSERT:45
	,DELETE:46
	,SPACE:32
	,COMMAND:224
}

EventManager.prototype.add = function(element /* | or object | or customType */, type, handler, context, data, delay, keyCode) {
	if (arguments.length > 1) {
		var inputs = {
			element: element,
			type: type,
			handler: handler,
			context: context,
			data: data,
			delay: delay,
			keyCode:keyCode
		}
	}
	else if (arguments[0] instanceof Object) {
		var inputs = arguments[0];
	}
	else {
		var inputs = {
			type: arguments[0]
		}
	}
	
	var listener = { handler: inputs.handler, context: inputs.context, delay: inputs.delay, data: inputs.data, keyCode:inputs.keyCode };
	
	if (this._isDomEventType(inputs.type)) {
		var e = this._addDOMEvent(inputs.type, listener, inputs.element);
	}
	else {
		var e = this._addCustomEvent(inputs.type, listener);
	}
	this.events.push(e);
	return e;
};

EventManager.prototype._isDomEventType = function (type) {
	if (null == DOMEventSource.prototype._getBrowserEventName.apply({type: type})) {
		return false;
	}
	return true;
};


EventManager.prototype._addDOMEvent = function(type, listener, element) {
	var e = new DOMEventSource(type);
	if (listener.handler) {
		e.addListener(listener);
	}
	if (element) {
		e.addElement(element);
	}
	return e;
};

EventManager.prototype._addCustomEvent = function(type, listener) {
	var e = new EventSource(type);
	if (listener.handler) {
		e.addListener(listener);
	}
	return e;
};

EventManager.prototype.remove = function(e /*element  or event */, listener /*listener or eventType*/) {
	/* Method refactored, as it supports 'new' mode (remove the event+listener) and 'old' mode (remove the event from the element by eventType)*/
	if (e instanceof EventSource) {
		this._removeEvent(e, listener);
	}
	else if (e.nodeName || e instanceof Array) {
		this._removeElement(e, listener);
	}
};

EventManager.prototype._removeEvent = function(e, listener) {
	if (undefined == listener) {
		e.removeAll();
	} else {
		e.removeListener(listener);
	}
	for (var i=0; i<this.events.length; i++) {
		if (e == this.events[i]) {
			this.events.splice(i, 1);
			break;
		}
	}
};
EventManager.prototype._removeElement = function(el, eventType) {
	for (var i=0, event; i<this.events.length; i++) {
		event = this.events[i];
		if (event instanceof DOMEventSource) {
			if (!eventType || (event.type == eventType)) {
				event.removeElement(el);
			}
		}
	}
};

EventManager.prototype.removeAll = function() {
	for (var i=0; i<this.events.length; i++) {
		this.events[i].removeAll();
	}
	this.events = [];
};

EventManager.prototype.cancel = function(e) {
	if(!e) { return; }
	
	if (e instanceof DOMEvent) {
		e.cancel();
	}
	else if (e.srcElement || e.target) {
		DOMEvent.prototype.cancel.apply({nativeEvent: e});
	}
};

if (window["WSDOM"]) {
	WSDOM.defineClass("Events", null, EventManager);
	WSDOM.loadSingleton("WSDOM.Events.3");
} else {
	var Events = new EventManager(); // backwards compatibility with Events.2
}


/* -- Loaded:/includes/jslib/Events/Events.3.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */



// helper method for Events.  Will only attach the event if the element exists.  Can also accept element id rather than a pointer.
Events.addIf = function(eventArgs) {
	var element = Element.get(eventArgs.element);
	if (element) { eventArgs.element = element; Events.add(eventArgs); }
}

// This if (!e) check isn't in Production yet
EventManager.prototype.cancel = function(e) {
	if(!e) { return; }
	
	if (e instanceof DOMEvent) {
		e.cancel();
	}
	else if (e.srcElement || e.target) {
		DOMEvent.prototype.cancel.apply({nativeEvent: e});
	}
};

/* -- Loaded:/tdameritrade/screener/Events.additions.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */


/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	WCH.js - Windowed Controls Hider v3.10
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	(c) Copyright 2003, Aleksandar Vacic, aleck@sezampro.yu, www.aplus.co.yu
	## This work is licensed under the Creative Commons Attribution-ShareAlike License.
	## To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/1.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Credits: Mike Foster for x functions (cross-browser.com)
	Credits: Tim Connor for short and sweet way of dealing with IE5.0 - dynamic creation of style rule (www.infosauce.com)
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Based on idea presented by Joe King. Works with IE5.0+/Win
	IE 5.5+: place iFrame below the layer to hide windowed controls
	IE 5.0 : hide/show all elements that have "WCHhider" class
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
var WCH_Constructor = function() {
	//	exit point for anything but IE5.0+/Win
	if ( !(document.all && document.getElementById && !window.opera && navigator.userAgent.toLowerCase().indexOf("mac") == -1) ) {
		this.Apply = function() {};
		this.Discard = function() {};
		return;
	}

	//	private properties
	var _bIE55 = false;
	var _bIE6 = false;
	var _oRule = null;
	var _bSetup = true;
	var _oSelf = this;

	//	public: hides windowed controls
	this.Apply = function(vLayer, vContainer, bResize) {

		if (_bSetup) _Setup();

		if ( _bIE55 && (oIframe = _Hider(vLayer, vContainer, bResize)) ) {
			oIframe.style.visibility = "visible";
		} else if(_oRule != null) {
			_oRule.style.visibility = "hidden";
		}

	};

	//	public: shows windowed controls
	this.Discard = function(vLayer, vContainer) {
		if ( _bIE55 && (oIframe = _Hider(vLayer, vContainer, false)) ) {
			oIframe.style.visibility = "hidden";
		} else if(_oRule != null) {
			_oRule.style.visibility = "visible";
		}
	};

	//	private: returns iFrame reference for IE5.5+
	function _Hider(vLayer, vContainer, bResize) {
		var oLayer = _GetObj(vLayer);
		var oContainer = ( (oTmp = _GetObj(vContainer)) ? oTmp : document.getElementsByTagName("body")[0] );
		if (!oLayer || !oContainer) return;
		//	is it there already?
		var oIframe = document.getElementById("WCHhider" + oLayer.id);

		//	if not, create it
		if ( !oIframe ) {
			//	IE 6 has this property, IE 5 not. IE 5.5(even SP2) crashes when filter is applied, hence the check
			var sFilter = (_bIE6) ? "filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0);" : "";
			//	get z-index of the object
			var zIndex = oLayer.style.zIndex;
			if ( zIndex == "" ) zIndex = oLayer.currentStyle.zIndex;
			zIndex = parseInt(zIndex);
			//	if no z-index, do nothing
			if ( isNaN(zIndex) ) return null;
			//	if z-index is below 2, do nothing (no room for Hider)
			if (zIndex < 2) return null;
			//	go one step below for Hider
			zIndex--;
			var sHiderID = "WCHhider" + oLayer.id;
			oContainer.insertAdjacentHTML("afterBegin", '<iframe class="WCHiframe" src="javascript:false;" id="' + sHiderID + '" scroll="no" frameborder="0" style="position:absolute;visibility:hidden;' + sFilter + 'border:0;top:0;left;0;width:0;height:0;background-color:#ccc;z-index:' + zIndex + ';"></iframe>');
			oIframe = document.getElementById(sHiderID);
			//	then do calculation
			_SetPos(oIframe, oLayer);
		} else if (bResize) {
			//	resize the iFrame if asked
			_SetPos(oIframe, oLayer);
		}

		return oIframe;
	};

	//	private: set size and position of the Hider
	function _SetPos(oIframe, oLayer) {
		//	fetch and set size
		oIframe.style.width = oLayer.offsetWidth + "px";
		oIframe.style.height = oLayer.offsetHeight + "px";
		//	move to specified position
		oIframe.style.left = oLayer.offsetLeft + "px";
		oIframe.style.top = oLayer.offsetTop + "px";
	};

	//	private: returns object reference
	function _GetObj(vObj) {
		var oObj = null;
		switch( typeof(vObj) ) {
			case "object":
				oObj = vObj;
				break;
			case "string":
				oObj = document.getElementById(vObj);
				break;
		}
		return oObj;
	};

	//	private: setup properties on first call to Apply
	function _Setup() {
		_bIE55 = (typeof(document.body.contentEditable) != "undefined");
		_bIE6 = (typeof(document.compatMode) != "undefined");

		if (!_bIE55) {
			if (document.styleSheets.length == 0)
				document.createStyleSheet();
			var oSheet = document.styleSheets[0];
			oSheet.addRule(".WCHhider", "visibility:visible");
			_oRule = oSheet.rules(oSheet.rules.length-1);
		}

		_bSetup = false;
	};
};
var WCH = new WCH_Constructor();



/* -- Loaded:/includes/jslib/wch.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */



Screener_class = function() {


	// these are populatated by screener.js.asp

	this.resultViews = {};
	this.criteria = {};
	this.criteriaMap = {};
	this.properties = {};
	this.data = {};


	this.page

	this.errorCode = -32768;

	this.serializer = new Serializer();

	this.clientSide = true; // some methods are used both server and client side


}


// Items that happen on initial load of the screener
Screener_class.prototype.init = function() {

	// add events to categories
	this.categoriesContainer = Element.get("categoryGroupContainer");
	this.categoryGroups = Element.parseSelector("div.categoryGroup",this.categoriesContainer);
	this.categoryGroupLists = Element.parseSelector("div.categoryGroupList",this.categoriesContainer);

	this.categoryGroupLinks = Element.parseSelector("div.categoryGroupLink a",this.categoriesContainer);
	Element.addClass(this.categoryGroupLinks,"expandcontract");
	Events.add({element:this.categoryGroupLinks,type:"click",context:this,handler:this.GUI_switchCategory});

	this.categoryGroupSelectAllLinks = Element.parseSelector("a.categoryGroupSelectAllLink",this.categoriesContainer);
	Events.add({element:this.categoryGroupSelectAllLinks,type:"click",context:this,handler:this.GUI_categorySelectAll});

	this.criteriaCheckboxes = Element.parseSelector('input[type="checkbox"]',this.categoriesContainer);
	this.criteriaLabels = Element.parseSelector('label',this.categoriesContainer);

	var extendedSessionContainer = Element.get("extendedSessionContainer");

	// add events for criteria and extended tooltips
	if (document.all) { // Why does the order of event attachments matter between IE and FF?
		this.labelToolTipEvents = Events.add({element:extendedSessionContainer?this.criteriaLabels.concat(extendedSessionContainer):this.criteriaLabels,type:"mouseover",context:this,handler:this.GUI_criteriaToolTip,data:"over",delay:400});
		Events.add({element:extendedSessionContainer?this.criteriaLabels.concat(extendedSessionContainer):this.criteriaLabels,type:"mouseover",context:this,handler:this.GUI_criteriaToolTipClearTimeouts,data:"over"});
	}
	else {
		Events.add({element:extendedSessionContainer?this.criteriaLabels.concat(extendedSessionContainer):this.criteriaLabels,type:"mouseover",context:this,handler:this.GUI_criteriaToolTipClearTimeouts,data:"over"});
		this.labelToolTipEvents = Events.add({element:extendedSessionContainer?this.criteriaLabels.concat(extendedSessionContainer):this.criteriaLabels,type:"mouseover",context:this,handler:this.GUI_criteriaToolTip,data:"over",delay:400});
	}
	this.labelToolTipEventsOut = Events.add({element:extendedSessionContainer?this.criteriaLabels.concat(extendedSessionContainer):this.criteriaLabels,type:"mouseout",context:this,handler:this.GUI_criteriaToolTip,data:"out",delay:70});

	Events.add({element:this.criteriaCheckboxes,type:"click",context:this,handler:this.GUI_criteriaChecked});

	// add events to result view options
	Events.addIf({element:"resultsViewSelect",type:"change",handler:this.GUI_updateResultsColumnSelect,context:this});
	Events.addIf({element:"resultsColumnSelect",type:"change",handler:this.GUI_updateResultsSortSelect,context:this});
	Events.addIf({element:"viewMatches",type:"click",handler:this.GUI_viewMatches,context:this});
	Events.addIf({element:"extendedSessionCheckbox",type:"click",handler:this.GUI_switchToExtendedSession,context:this});

	if (this.getProperty("categorySuperOptions")) {
		this.categorySuperOptions = Element.parseSelector("a","categorySuperContainer");
		Events.add({element:this.categorySuperOptions,type:"click",handler:this.GUI_categorySuperOptionClick,context:this});
	}

	this.createCommonTopLinks();

	this.criteriaTable = Element.parseSelector("tbody","criteriaTable","first");

	this.renderTDAMButtons();

	this.retrieveCurrentCriteria();

}



Screener_class.prototype.createCommonTopLinks = function(keyword) {
	if (/public/i.test(location.href)) { return; }
	
	Common.addTopLink(Element.create("a",{href:"#",Events:{type:"click",context:this,handler:this.popupGlossary},className:"fleft"},"Screeners Glossary"));
	Common.addTopLink(Element.create("a",{href:"#",Events:{type:"click",context:this,handler:this.popupHelpContent},className:"iconBackground fleft",id:"tdamPageHelp"},"Page Help"));

}


Screener_class.prototype.popupWhatsNew = function(keyword) {
	window.open(buildAbsolutePath("/screener/whatsnew.pdf"),'ScreenersWhatsNew','resizable=yes,scrollbars=yes,width=810,height=755,top=2,left=17');
}


Screener_class.prototype.popupGlossary = function(keyword) {
	window.open(gSessionSeedDomain + '/cgi-bin/apps/u/PLoad?pagename=thirdparty/screener_glossary.html' + (keyword?("#"+keyword):""),'ScreenersGlossary','resizable=yes,scrollbars=yes,width=705,height=537,top=2,left=17');
}


Screener_class.prototype.popupHelpContent = function() {
	window.open(gSessionSeedDomain + '/cgi-bin/apps/u/PLoad?pagename=thirdparty/wsodScreenerHelp.html','ScreenersMainIndex','resizable=yes,scrollbars=yes,width=705,height=537,top=2,left=17');
}

Screener_class.prototype.GUI_criteriaToolTip = function(e,el,mouse) {

	this.GUI_criteriaToolTipClearTimeouts();

	// remove existing description
	if (this.fieldDescription) {
		//WCH.Discard(this.fieldDescription);

		if (this.fieldDescriptionShadow) {
			this.fieldDescriptionShadow.remove();
		}
		Element.remove(this.fieldDescription);
		this.fieldDescription = null;
	}

	if (mouse == "over") {

		var field = el.getAttribute('field');
		var criterion = this.getCriterion(field);

		if (!criterion.description) {
			return;
		}

		this.fieldDescription = Element.create("div",{id:"fieldDescription"},[
			criterion.description
		],document.body);

		var size = Element.getSize(el);
		var pos = Element.getXY(el);

		var x = pos.x+20;
		var y = pos.y+size.height+5;
		var viewPort = getViewport();

		var moduleSize = Element.getSize(this.fieldDescription);

		//console.info(x,moduleSize.width,pageSize.width)
		// move over if too far right

		if (x + moduleSize.width > viewPort.right) {
			x = viewPort.right - moduleSize.width - 30;
		}

		// move over if too far left
		if (x < viewPort.left) {
			x = viewPort.left + 10;
		}

		// move below if won't fit above
		if (y < viewPort.top) {
			y = viewPort.top + 10;
		}

		// move up if cut off on bottom
		if ((y + moduleSize.height) > viewPort.bottom) {
			y -= (y + moduleSize.height) - viewPort.bottom + 10;
		}


		Element.setXY(this.fieldDescription,x,y);

		this.fieldDescriptionShadow = new DropShadow({element:this.fieldDescription,monitor:false,offset:3,iframe:true});

		this.fieldDescriptionEventsOver = Events.add({element:this.fieldDescription,type:"mouseover",context:this,handler:this.GUI_criteriaToolTipClearTimeouts});
		this.fieldDescriptionEventsOut = Events.add({element:this.fieldDescription,type:"mouseout",context:this,handler:this.GUI_criteriaToolTip,data:"out",delay:10});

		// links were causing mouseout triggers
		var innerElements = Element.parseSelector("div,a,span",this.fieldDescription);
		Events.add({element:innerElements,type:"mouseover",context:this,handler:this.GUI_criteriaToolTipClearTimeouts});

		
	}


}

Screener_class.prototype.GUI_criteriaToolTipClearTimeouts = function(e,el,data) {

	this.labelToolTipEvents.clearDelayTimeouts(); 
	this.labelToolTipEventsOut.clearDelayTimeouts(); 

	if (this.fieldDescriptionEventsOut) {
		this.fieldDescriptionEventsOut.clearDelayTimeouts();
	}
}

Screener_class.prototype.GUI_categorySuperOptionClick = function(e,el,data) {
	Events.cancel(e);
	el.blur();

	var categorySuper = el.getAttribute("categorySuper");

	this.setPreference("categorySuper",categorySuper);

	this.GUI_switchCategorySuper(categorySuper,true);

}


Screener_class.prototype.GUI_switchCategorySuper = function(categorySuper,removeCriteria) {

	this.categorySuper = categorySuper;
	this.GUI_updateResultsViewSelect();

	if (this.categorySuperOptions) {
		Element.removeClass(this.categorySuperOptions,"selected");
		Element.addClass(Element.parseSelector('[categorySuper="'+categorySuper+'"]',this.categorySuperOptions),"selected");
	}

	// collapse all categories
	Element.addClass(this.categoryGroups,"none");

	// expand clicked one
	var categoryGroupsInSuper = Element.parseSelector('[categorySuper="'+categorySuper+'"]',this.categoryGroups);
	var firstCategoryGroupLink = Element.parseSelector("div.categoryGroupLink a",categoryGroupsInSuper,"first");

	if (categoryGroupsInSuper.length == 1) {
		Element.removeClass(firstCategoryGroupLink,"expandcontract");

	}

	this.GUI_switchCategory(null,firstCategoryGroupLink,true)


	//Element.addClass(Element.parseSelector("div.categoryGroupList",categoryGroupsInSuper),"none");
	//Element.removeClass(Element.parseSelector("div.categoryGroupList",categoryGroupsInSuper,"first"),"none");
	Element.removeClass(categoryGroupsInSuper,"none");



	if (removeCriteria) {
		var fieldRows = Element.parseSelector('tr[field]',this.criteriaTable);
		Element.remove(fieldRows);

		var categorySuperOptionsByName = this.util.hashTable(Screener.getProperty("categorySuperOptions"),{field:"name",returnNew:true});
		if (categorySuperOptionsByName[categorySuper].criteria) {
			var criteria = categorySuperOptionsByName[categorySuper].criteria;
			for (var i=0; i<criteria.length; i++) {
				this.GUI_addCriteria(criteria[i].field,criteria[i]);
			}
		

		}

		this.getMatches();



	}




}

Screener_class.prototype.GUI_switchCategory = function(e, el, ignoreExpand) {
	Events.cancel(e);
	el.blur();
	var category = el.getAttribute("category");

	var wasExpanded = Element.hasClass(el,"expanded");


	// collapse all categories
	Element.addClass(this.categoryGroupLists,"none");
	Element.removeClass(this.categoryGroupLinks,"expanded");

	if (!wasExpanded || ignoreExpand) {
		// expand clicked one
		Element.removeClass(Element.parseSelector('div.categoryGroupList[category="'+category+'"]',this.categoriesContainer),"none");
		Element.addClass(Element.parseSelector('[category="'+category+'"]',this.categoryGroupLinks),"expanded");
	}

}



Screener_class.prototype.setPreference = function(name,value) {

	this.loadContentBufferSecondary({
		 page:"buffer_utils.asp"
		,action:"setSticky"
		,data:{name:name,value:value}
		,context:this
	});

}




Screener_class.prototype.GUI_switchToExtendedSession = function(e,el,data) {
	this.getMatches();
}

Screener_class.prototype.GUI_viewMatches = function(e,el,data) {

	Events.cancel(e);

	var view = Element.get("resultsViewSelect").value;
	var column = Element.get("resultsColumnSelect").value;
	var sort = Element.get("resultsSortSelect").value;

	var resultsParams = {view:view,sortfield:column,sortdir:sort};

	//recurseObject({o:resultsParams,console:1});
	//return;

	if (this.totalMatches) {
		location.href = "results.asp?params=" + this.serialize(resultsParams);
	}


}


Screener_class.prototype.GUI_criteriaChecked = function(e,el,data) {

	if (el.checked) {
		this.GUI_addCriteria(el.getAttribute("field"),el.getAttribute("interfaceField"));
	}
	else {
		this.GUI_removeCriteria(el.getAttribute("field"),el.getAttribute("interfaceField"));
	}

}


// called from category checkbox uncheck
Screener_class.prototype.GUI_removeCriteria = function(field,interfaceField) {

	// remove any <tr field="FIELD"> from criteriaTable

	var criterion = this.getCriterion(field);
	
	if (!criterion) { return; }

	var selector = 'tr[field="' + criterion.name + '"]';
	if (criterion.interfaceName) {
		selector+=',' + 'tr[interfaceName="' + criterion.interfaceName + '"]'
	}
	//console.info(selector);

	var fieldRows = Element.parseSelector(selector,this.criteriaTable);
	//console.info(fieldRows)

	try { // this is in as the above may select the same element twice - (Element needs a removeDuplicates)
		Element.remove(fieldRows);
	}
	catch(e) { }

	this.getMatches();

}


Screener_class.prototype.GUI_removeCriterion = function(e,el,data) {

	Element.remove(Element.getParent(el,"tr"));

	this.getMatches();

}


// Displays the matches per row in the interface
Screener_class.prototype.GUI_displayMatches = function() {

	if (!this.matches) { return; }

	var criteriaRows = Element.parseSelector("tr",this.criteriaTable);

	var matchesContainer, averageContainer;

	if (this.matches && this.matches.length && this.matches.length == criteriaRows.length) {
		
		for (var i=0; i<criteriaRows.length; i++) {
			matchesContainer = Element.parseSelector('div[matches]',criteriaRows[i]);

			if (this.matches[i].matches == undefined) {
				this.matches[i].matches = "--";
				this.matches[i].matchesTotal = "--"
			}
			Element.setHTML(matchesContainer,this.util.commatize(this.matches[i].matches) + "<div class='smaller lighter'>(" + this.util.commatize(this.matches[i].matchesTotal) + ")</div>");

			averageContainer = Element.parseSelector('div.criterionFieldAverage',criteriaRows[i]);
			if (averageContainer && this.matches[i].fieldAverage) {
				Element.setHTML(averageContainer,this.matches[i].fieldAverage ? ("Average: " + this.matches[i].fieldAverage) : "");

			}

			// no need to retrieve the value again for this row
			criteriaRows[i].retrieveFieldAverage = false;
		}

		this.totalMatches = this.matches[i-1].matches; // the matches of the last criterion will be the total results
		this.GUI_displayTotalMatches(this.totalMatches);

		var criteriaRows = Element.parseSelector("!none",criteriaRows); // any visible rows
		if (criteriaRows.length) {
			// only update the select boxes if there is criteria (also avoids an IE rendering bug when these are hidden)
			this.GUI_updateResultsColumnSelect();
		}

	}
	else {
		this.GUI_displayTotalMatches(0);
	}

	// IE was rendering the selects even though their container was hidden.  Leave in this delay hack for now in case it is needed
	 var self = this; setTimeout(function() { self.updateCategories(); },1);
	

}




// Updates View -- Matches button with matches value
Screener_class.prototype.GUI_displayTotalMatches = function(totalMatches) {

	var plural = !totalMatches || totalMatches > 1;

	// display -- if no matches
	totalMatches = (totalMatches != undefined && totalMatches != false ? totalMatches : "--");

	totalMatches != "--" ? btnOn("viewMatches") : btnOff("viewMatches");

	var label = "View " + this.util.commatize(totalMatches) + " Match" + (plural?"es":"");

	this.GUI_updateTDButton(this.getProperty("totalMatchesElement"),label);
    //Element.get(this.getProperty("totalMatchesElement")).firstChild.nodeValue = 
}


// Updates selected criteria checkboxes and no criteria selected message
Screener_class.prototype.updateCategories = function() {

	// hide/show message and result view options
	var criteriaRows = Element.parseSelector("tr[field]!none",this.criteriaTable); // any visible rows
	Element.switchClass("nocriteriaselected","none",criteriaRows.length?true:false);
	Element.switchClass("criteriaselected","none",criteriaRows.length?false:true);

	var fields = [], interfaceName;
	for (var i=0; i<criteriaRows.length; i++) {
		fields.push(criteriaRows[i].getAttribute("field"));
		interfaceName = criteriaRows[i].getAttribute("interfaceName");
		if (interfaceName) {
			fields.push(interfaceName);
		}
	}


	// Update criteria interface

	// uncheck all criteria boxes
	Element.setProperty(this.criteriaCheckboxes,"checked",false);

	//console.info(fields)

	if (fields.length) {
		// check criteria boxes for selected criteria
		//console.info('[field/="'+fields.join("|")+'"]')
		Element.setProperty(Element.parseSelector('[field/="^('+fields.join("|")+')$"]',this.criteriaCheckboxes),"checked",true);
	}

	// show checkmark indicating checked boxes (add the class if it contains any checked boxes)
	for (var i=0; i<this.categoryGroups.length; i++) {
		var atLeastOneChecked = Element.parseSelector('input[type="checkbox"][checked=.`true`]',this.categoryGroups[i]).length;
		Element.setHTML(this.categoryGroupSelectAllLinks[i],atLeastOneChecked?"Select None":"Select All")
		Element.switchClass(this.categoryGroupSelectAllLinks[i],"selected",atLeastOneChecked)
		Element.switchClass(this.categoryGroups[i],"containsChecked",atLeastOneChecked);
	}

}




Screener_class.prototype.GUI_categorySelectAll = function(e, el, data) {
	Events.cancel(e);

	// allow link to be clicked only once at a time
	function setTimer(el) {
		clearTimeout(el.clickTimer);
		el.clickTimer = setTimeout(function() { el.clickTimer = null;  },500);
	}
	
	if (el.clickTimer) {
		setTimer(el);
		return;
	}

	setTimer(el);


	var category = el.getAttribute("category");

	var unchecked = Element.parseSelector('[category="'+category+'"][checked=.`false`]',this.criteriaCheckboxes)
	var checkboxes = Element.parseSelector('[category="'+category+'"]',this.criteriaCheckboxes)

	if (!Element.hasClass(el, "selected") && unchecked.length) {
		//Element.addClass(el, "selected");
		for (var i=0; i<unchecked.length; i++) {
			this.GUI_addCriteria(unchecked[i].getAttribute("field"));
		}
	}
	else {
		for (var i=0; i<checkboxes.length; i++) {
			this.GUI_removeCriteria(checkboxes[i].getAttribute("field"));
		}
		//Element.removeClass(el, "selected");
	}

}


// Called from storeCriterion and removeCriterion
// Starts a delay to retrieve matches
Screener_class.prototype.getMatches = function(dontGetMatches) {

	var criteria = [];

	// collect criteria through TR.criteria

	//var extendedSessionFields = this.getProperty("extendedSessionFields");
	//var isExtended = extendedSessionFields.length && Element.get("extendedSessionCheckbox").checked;

	var criteriaRows = Element.parseSelector("tr",this.criteriaTable);
	var visibleCriteriaRows = Element.parseSelector("!none",criteriaRows); // any visible rows
	if (visibleCriteriaRows.length) {
		Element.addClass("nocriteriaselected","none");
	}

	var rowCriteria;
	for (var i=0; i<criteriaRows.length; i++) {
		if (criteriaRows[i].rowCriteria){ 
			rowCriteria = criteriaRows[i].rowCriteria;

			if (rowCriteria instanceof Array) {
				criteria = criteria.concat(rowCriteria); // put in to support criteria which contains multiple fields/rowCriteria
				continue;
			}

			rowCriteria.retrieveFieldAverage = criteriaRows[i].retrieveFieldAverage ? true : false;

			/*
			// add Extended if the box is checked and there is an extended field
			if (isExtended && this.util.arrayContains(this.getProperty("extendedSessionFields"),rowCriteria.field)) {
				rowCriteria.field = rowCriteria.field.replace(/Extended$/g,"") + "Extended";
			}

			// remove Extended from the field name
			else {
				//console.info("remove for " + criteriaRows[i].rowCriteria.field)
				rowCriteria.field = rowCriteria.field.replace(/Extended$/g,"");
			}
			*/

			criteria.push(rowCriteria);
		}
	}


	var dontGetMatches = dontGetMatches || this.getProperty("suppressMatches") || false;

	if (this.getMatchesTimer) { clearTimeout(this.getMatchesTimer); this.getMatchesTimer = null; }

	var self = this;
	this.getMatchesTimer = setTimeout(function() { self.getMatchesDelay(criteria,dontGetMatches) },this.getProperty("getMatchesDelay",500));



}


Screener_class.prototype.getMatchesDelay = function(criteria, dontGetMatches) {

	recurseObject({o:criteria,n:"Current Criteria",console:1});

	if (dontGetMatches) {
		// passed through from drawCurrentCriteria or suppressMatches property
		return;
	}

	this.currentCriteria = criteria;

	this.contentBufferAbortRequests();

	var extendedSessionFields = this.getProperty("extendedSessionFields") || [];

	this.loadContentBuffer({
		 page:"buffer_getMatches.asp"
		,action:"getMatches"
		,data:{
			criteria:this.currentCriteria
			,useExtended:(extendedSessionFields.length && Element.get("extendedSessionCheckbox") && Element.get("extendedSessionCheckbox").checked)?"yes":"no"
		}
		,context:this
		,onload:this.GUI_displayMatches
	});



}



Screener_class.prototype.getContentBuffer  = function() {
	if (!this.gContentBuffer) {
		this.gContentBuffer = new ContentBuffer();
	}
	return this.gContentBuffer;
}

Screener_class.prototype.contentBufferAbortRequests  = function() {
	if (!this.gContentBuffer) {
		this.gContentBuffer = new ContentBuffer();
	}
	this.gContentBuffer.abortRequests();
}

Screener_class.prototype.loadContentBuffer = function(argsObj) {
	var cb = this.getContentBuffer();

	//dbgObject(argsObj.data);
	//dbg(DataFunctions.serialize(argsObj.data));

	var conn = cb.load({
		debug: true,
		url: argsObj.page,
		method: "post",
		contentType: argsObj.contentType || "text/javascript",
		context:argsObj.context,
		evalInContext:(argsObj.context)?true:false,
		data:{
			 action:argsObj.action||""
			,data:this.serialize(argsObj.data)
		},
		onload: argsObj.onload,
		onerror: argsObj.onerror
	});
}




Screener_class.prototype.getContentBufferSecondary  = function() {
	if (!this.gContentBufferSecondary) {
		this.gContentBufferSecondary = new ContentBuffer();
	}
	return this.gContentBufferSecondary;
}

Screener_class.prototype.contentBufferSecondaryAbortRequests  = function() {
	if (!this.gContentBufferSecondary) {
		this.gContentBufferSecondary = new ContentBuffer();
	}
	this.gContentBufferSecondary.abortRequests();
}

Screener_class.prototype.loadContentBufferSecondary = function(argsObj) {
	var cb = this.getContentBufferSecondary();

	//dbgObject(argsObj.data);
	//dbg(DataFunctions.serialize(argsObj.data));

	var conn = cb.load({
		debug: true,
		url: argsObj.page,
		method: "post",
		contentType: argsObj.contentType || "text/javascript",
		context:argsObj.context,
		evalInContext:(argsObj.context)?true:false,
		data:{
			 action:argsObj.action||""
			,data:this.serialize(argsObj.data)
		},
		onload: argsObj.onload,
		onerror: argsObj.onerror
	});
}



// content buffer to buffer_getCurrentCriteria.asp
Screener_class.prototype.retrieveCurrentCriteria = function() {


	// check for static criteria to load for testing
	if (this.getProperty("testCriteria")) {
		this.currentCriteria = this.getProperty("testCriteria");
		this.GUI_drawCurrentCriteria();
		Element.removeClass("criteriaselected","none");

		return;
	}


	// retrieve current criteria and matches
	this.loadContentBuffer({
		 page:"buffer_getCurrentCriteria.asp"
		,action:"getCurrentCriteria"
		,data:{}
		,context:this
		,onload:this.GUI_drawCurrentCriteria
	});

}



Screener_class.prototype.GUI_drawCurrentCriteria = function() {

	if (this.currentCriteria && this.currentCriteria.length) { 

	
		this.ignoreFirstGetMatches = true; // don't kick off the getMatches for the initial criteria view as it is retrieved through the same request
	
		recurseObject({o:this.currentCriteria,n:"Session Criteria",console:1});
		
		//var extendedSessionFields = this.getProperty("extendedSessionFields") && this.getProperty("extendedSessionFields").length;

		var criterion;
		for (var i=0; i<this.currentCriteria.length; i++) {

			criterion = this.getCriterion(this.currentCriteria[i].field)
	
			// Check the Extended box if the criteria is an extended field
			//if (criterion && extendedSessionFields && /Extended$/.test(this.currentCriteria[i].field)) {
			//	Element.get("extendedSessionCheckbox").checked = true;
			//}

			// Specific check for stocks so that the Preferred is retained regardless of the current sticky setting
			if (this.getProperty("section") == "stocks" && this.currentCriteria[i].field == "PreferredStock") {
				this.categorySuper = "preferred";
			}

			// add it to the interface
			this.GUI_addCriteria(null,this.currentCriteria[i],null,true /*dontGetMatches*/);
	
		}
	

	}

	if (this.categorySuper) {
		this.GUI_switchCategorySuper(this.categorySuper);
	}

	Element.removeClass("topLevelOptions","none");
	Element.removeClass("criteriaContainer","none");

	this.GUI_updateResultsViewSelect();

	this.GUI_displayMatches();

}

// Update the Column select based on the chosen view
Screener_class.prototype.GUI_updateResultsViewSelect = function() {

	this.categorySuper = this.categorySuper || "all";

	var resultViews = this.getResultViews();

	var views = [];
	for (var i in resultViews) {
		// Only include the view if not preferred or not an exluded view for preferreds
		if (this.categorySuper != "preferred" || !resultViews[i].excludeIfCriteriaUsed) {
			views.push({text:resultViews[i].label,value:i});
		}
	}

	this.resultsParameters = this.resultsParameters || {};
	this.resultsViewSelect = Element.buildSelect({data:views,selected:this.resultsParameters.view||""},{id:"resultsViewSelect"});

}

// Update the Column select based on the chosen view
Screener_class.prototype.GUI_updateResultsColumnSelect = function(e,el,data) {
	var view = Element.get("resultsViewSelect").value || "Criteria";

	var resultViews = this.getResultViews();
	
	var viewColumns = [];

	var defaultColumnNumber = 0;

	if (this.getProperty("commonResultColumnsLeft")) {
		viewColumns = viewColumns.concat(this.getProperty("commonResultColumnsLeft"));
		defaultColumnNumber = this.getProperty("commonResultColumnsLeft").length;
	}

	if (view == "Criteria" && this.currentCriteria) {
		// loop through criteria

		var criterion;
		for (var i=0; i<this.currentCriteria.length; i++) {
			field = this.currentCriteria[i].field;
			criterion = this.getCriterion(this.currentCriteria[i].field);
			if (criterion && !criterion.hideOnInterface) { // don't show hidden criteria (Preferred)
				viewColumns.push(field);
			}
		}
	}
	else {
		// loop through result view columns
		for (var i=0; i<resultViews[view].columns.length; i++) {
			viewColumns.push(resultViews[view].columns[i]);
		}
	}

	viewColumns = this.util.arrayRemoveDuplicates(viewColumns);

	// loop through and only add "datapoint" columns
	var columnOptions = []
	for (var i=0; i<viewColumns.length; i++) {
		criterion = this.getCriterion(viewColumns[i]);
		if (criterion && !criterion.displayOnly) {
			columnOptions.push({text:this.getFieldLabel(viewColumns[i],criterion,null),value:viewColumns[i]});
		}
	}


	var defaultColumn = (columnOptions[defaultColumnNumber] ? columnOptions[defaultColumnNumber].value : "");
	//console.info("defaultColumn " + defaultColumn)

	// current selected option, last result value, or default
	var selected = Element.get("resultsColumnSelect").value || this.resultsParameters.sortfield || "";
	selected = selected.replace(/Extended$/g,"");

	if (view == "Criteria" && (!this.resultsParameters.sortfield || (this.resultsParameters.sortfield && !this.util.arrayContains(viewColumns,this.resultsParameters.sortfield)))) {
		selected = defaultColumn;
	}

	//console.info("defaultColumn " + defaultColumn)

	this.resultsParameters.sortfield = ""; // clear it out so the conditon above works


	Element.buildSelect({data:columnOptions,selected:selected},{id:"resultsColumnSelect"});

	this.GUI_updateResultsSortSelect();

}


// Update the Sort select based on the chosen column
Screener_class.prototype.GUI_updateResultsSortSelect = function(e,el,data) {
	var column = Element.get("resultsColumnSelect").value;
	var criterion = this.getCriterion(column);

	// current selected option, last result value, or default
	var selected = criterion.sortdir || Element.get("resultsSortSelect").value || this.resultsParameters.sortdir || "A";

	Element.buildSelect({data:{"A":"Ascending","D":"Descending"},selected:selected},{id:"resultsSortSelect"});



}

Screener_class.prototype.serialize = function(obj) {
	return this.serializer.serialize(obj);
}

Screener_class.prototype.deserialize = function(str) {
	return this.serializer.deserialize(str);
}



// TDAM has JavaScript which converts links to buttons.  This will take any tdbutton="white|green" stateoff="true|" size="100" and convert and convert
// It additionally converts "#" to "javascript:void(0)" to keep links simple
Screener_class.prototype.AAArenderTDAMButtons = function(container) {
	var self = this; setTimeout(function() { self.renderTDAMButtonsDelay(container); },20);
	
}

Screener_class.prototype.renderTDAMButtons = function(container) {

	container = container || document.body;

	var buttonLinks = Element.parseSelector('a[tdbutton]',container);

	// Create TDAM buttons from links
	for (var i=0; i<buttonLinks.length; i++) {
		if (/#$/.test(buttonLinks[i].getAttribute("href"))) {
			buttonLinks[i].setAttribute("href","javascript:void(0)");
		}
		btnInit(buttonLinks[i].id,buttonLinks[i].getAttribute("tdbutton") == "green",buttonLinks[i].getAttribute("stateoff")?false:true,buttonLinks[i].getAttribute("width")||null);
	}

}

Screener_class.prototype.escapeInput = function (input) {
	input = input.replace(/\</g, "&lt;");
	input = input.replace(/\>/g, "&gt;");
	input = input.replace(/\"/g, "&quot;");
	return input;
}

// nodeValue is needed as the rendered HTML is not valid and innerHTML fails in Firefox
Screener_class.prototype.GUI_updateTDButton = function(id,val) {
	Element.get(id+"Inner").firstChild.nodeValue = val;
}


Screener = new Screener_class();






/* -- Loaded:/tdameritrade/screener/Screener_class.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */


/*

This file contains extra common functionality not specific to screen/results

*/




/* -- Loaded:/tdameritrade/screener/Screener_class.common.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */





// Creates a new criteria row from an existing one using its criteria
Screener_class.prototype.GUI_cloneCriterion = function(e,el,data) {

	var parentTR = Element.getParentBySelector(el,"tr[field]",true);

	// cloning passes along clicked row's criteria and passes itself as the copyOf parameter for placement
	this.GUI_addCriteria(null,parentTR.rowCriteria,parentTR);

}



/*
Gets current criteria from the criterion row and stores it as a property
*/
Screener_class.prototype.GUI_storeCriterion = function(e,el,data,dontGetMatches) {

	var rowCriteria = {field:null,values:[]};

	var parentTR = Element.getParentBySelector(el,"tr[field]",true);
	var criteriaContainer = Element.parseSelector("td.criteriaColumn",parentTR,"first");

	var field = parentTR.getAttribute("field");

	var criterion = this.getCriterion(field);

	field = criterion.field;

	// Get screener field from fieldModifier input if it exists

	if (criterion.fieldModifier && criterion.fieldModifierType == "select") {
		field = Element.parseSelector('select[fieldModifier]',parentTR,"first").value;
	}

	else if (criterion.fieldModifier && criterion.fieldModifierType == "radio") {
		field = this.GUI_getCriterionRadioInputsValue(criteriaContainer,this.getObjectFirstProperty(criterion.fieldModifier));
	}

	if (!criterion) {
		console.info("No criterion for " + field);
		return;
	}

	rowCriteria.field = field;


	// Call the module's store method if it exists.
	if (criterion.module && this["GUI_storeCriterion_"+criterion.module]) {
		var criteriaOverride = this["GUI_storeCriterion_"+criterion.module](criterion,rowCriteria,criteriaContainer);
		if (criteriaOverride) {
			rowCriteria = criteriaOverride;
		}
	}

	// Some criteria do additional things with the rowCriteria
	if (criterion.subModule && this["GUI_storeCriterionSub_"+criterion.subModule]) {
	
		var criteriaOverride = this["GUI_storeCriterionSub_"+criterion.subModule](criterion,rowCriteria,criteriaContainer);
		if (criteriaOverride) {
			rowCriteria = criteriaOverride;
		}
	}

	if (criterion.operatorModifier && criterion.operatorModifierType == "select") { // reverse the criteria if 2nd radio is selected
		var operatorModifierSelect = Element.parseSelector('select[operatorModifierSelect]',parentTR,"first");
		if (operatorModifierSelect.selectedIndex == 1) {
			rowCriteria = this.reverseCriteria(rowCriteria);
		}
	}


	if (criterion.operatorModifier && criterion.operatorModifierType == "radio") { // reverse the criteria if 2nd option is selected
		var operatorModifiers = Element.parseSelector('input[operatorModifier]',parentTR);
		if (operatorModifiers[1].checked) {
			rowCriteria = this.reverseCriteria(rowCriteria);
		}
	}


 	// so the field average is retrieved only once per data point
	parentTR.lastField = parentTR.currentField || "";
	parentTR.currentField = rowCriteria.field+"";
	parentTR.retrieveFieldAverage = (criterion.retrieveAverage && (parentTR.currentField != parentTR.lastField));


	//console.info(rowCriteria)



	//recurseObject({o:rowCriteria,console:1});

	// stores the criteria object as a property of the TR
	parentTR.rowCriteria = rowCriteria;


	this.getMatches(dontGetMatches);

	return rowCriteria;

}


Screener_class.prototype.GUI_storeCriterion_radioInputs = function(criterion,rowCriteria,criteriaContainer) {

	rowCriteria.values = []; 

	rowCriteria.values.push(this.GUI_getCriterionRadioInputsValue(criteriaContainer,this.getObjectFirstProperty(criterion.radioInputs)));

}

Screener_class.prototype.GUI_renderCriterion_radioInputs = function(criterion,rowCriteria,criteriaContainer) {
	this.GUI_setCriterionRadioInputsSelected(criteriaContainer,rowCriteria.values.length?rowCriteria.values[0]:this.getObjectFirstProperty(criterion.radioInputs))
}




// fieldModifier modules always pass EQU=1 as a flag
Screener_class.prototype.GUI_storeCriterion_fieldModifier = function(criterion,rowCriteria,criteriaContainer) {
	rowCriteria.values.push("EQU,1");
}


// returns a select element which changes the screener field used for the criteria row
Screener_class.prototype.GUI_renderFieldModifier = function(fieldModifier,selected) {
	if (selected) {
		selected = selected.replace(/Ptile$/g,"");
	}
	return Element.buildSelect({selected:selected||"",data:fieldModifier},{fieldModifier:"yes"});

}




Screener_class.prototype.GUI_storeCriterion_multiSelect = function(criterion,rowCriteria,criteriaContainer) {
	// get select values
	var select = Element.parseSelector("*[layoutInput]",criteriaContainer,"first")

	var options = select.getElementsByTagName("option");

	for (var x=0; x<options.length;x++) {
		if (options[x].selected) {
			rowCriteria.values.push("LIKE," + (options[x].value || options[x].text));
		}
	}
}


Screener_class.prototype.GUI_renderCriterion_multiSelect = function(criterion,rowCriteria,criteriaContainer,titleContainer) {

	var selectData = this.getDatum(criterion.data);

	// remove LIKE operator from selected values
	var values = rowCriteria.values.join("{}");
	values = values.replace(/LIKE,/g,"");
	values = values.split("{}");

	return Element.buildSelect({selected:values,data:selectData},{layoutInput:"layoutInput",multiple:"multiple",size:criterion.moduleSize||10},criteriaContainer);

}











Screener_class.prototype.GUI_renderCriterionSub_PercentDollar = function(criterion,rowCriteria,criteriaContainer) {
	
	var field = rowCriteria.field.replace(/Ptile|Extended/,""); 

	if (/Ptile/.test(rowCriteria.field)) {
		var ptile=true;
		rowCriteria.field = rowCriteria.field.replace(/Ptile/,"");
	}

	var isDollar = !rowCriteria.values.length || this.util.getObjectPropertyIndex(criterion.fieldModifierAdditional,field) !== null;

	// select the %/$ radio button
	this.GUI_setCriterionRadioInputsSelected(criteriaContainer,isDollar?"dollar":"percent")

	// override the field to the % equivalent so that it is selected
	if (isDollar) {
		var index = this.util.getObjectPropertyIndex(criterion.fieldModifierAdditional,field);
		var pctField = this.util.getObjectIndexProperty(criterion.fieldModifier,index);
		if (pctField) {
			rowCriteria.field = pctField;
		}
	}

	if (ptile) {
		rowCriteria.field = rowCriteria.field + "Ptile";
	}





}


Screener_class.prototype.GUI_storeCriterionSub_PercentDollar = function(criterion,rowCriteria,criteriaContainer) {

	// Price Change for preferreds only supports the default timeframe
	if (criterion.name == "PriceChange" && this.categorySuper && this.categorySuper == "preferred" && !criteriaContainer.fieldModifierRemoved) {
		var fieldModifier = Element.parseSelector('select[fieldModifier]',criteriaContainer,'first');
		Element.insertAfter(Element.create("span",{},"Today's Trading Session"),fieldModifier);
		Element.addClass(fieldModifier,"none");
		criteriaContainer.fieldModifierRemoved = true;
	}

	var radioValue = this.GUI_getCriterionRadioInputsValue(criteriaContainer,this.getObjectFirstProperty(criterion.radioInputs))

	// override the field to the $ equivalent
	if (radioValue == "dollar") {

		// remove and add Ptile back in after the field swap
		if (/Ptile/.test(rowCriteria.field)) {
			var ptile=true;
			rowCriteria.field = rowCriteria.field.replace(/Ptile/,"");
		}

		var index = this.util.getObjectPropertyIndex(criterion.fieldModifier,rowCriteria.field);
		var dlrField = this.util.getObjectIndexProperty(criterion.fieldModifierAdditional,index);

		if (dlrField) {
			rowCriteria.field = dlrField;
		}

		if (ptile) {
			rowCriteria.field = rowCriteria.field + "Ptile";
		}
	}
}






// Use this if we end up combining Mutual Fund Types
Screener_class.prototype.GUI_renderCriterion_multipleFlags = function(criterion,rowCriteria,criteriaContainer,titleContainer) {

	var selectData = this.getDatum(criterion.data);

	// remove LIKE operator from selected values
	var values = rowCriteria.values.join("{}");
	values = values.replace(/LIKE,/g,"");
	values = values.split("{}");

	return Element.buildSelect({selected:values,data:selectData},{layoutInput:"layoutInput",multiple:"multiple",size:criterion.moduleSize||10},criteriaContainer);

}


Screener_class.prototype.GUI_storeCriterion_multipleFlags = function(criterion,rowCriteria,criteriaContainer) {
	// get select values

	var criteria = [];

	var select = Element.parseSelector("*[layoutInput]",criteriaContainer,"first")

	var options = select.getElementsByTagName("option");

	for (var x=0; x<options.length;x++) {
		if (options[x].selected) {
			criteria.push({field:options[x].value,values:["EQU,1"]});
			//rowCriteria.values.push("LIKE," + (options[x].value || options[x].text));
		}
	}

	return criteria;


}



Screener_class.prototype.GUI_renderCriterionSub_Pricevs52w = function(criterion,rowCriteria,criteriaContainer) {

	// NOTE: Above/Below value is stored by _buttons module

	var fieldValues = this.deconstructFieldName(rowCriteria.field,criterion.fieldPattern,criterion.fieldPatternDefaults);
	console.info("Pricevs52w fieldValues",fieldValues)

	this.GUI_setCriteriaInputValues(criteriaContainer,{1:fieldValues[0]});

}


Screener_class.prototype.GUI_storeCriterionSub_Pricevs52w = function(criterion,rowCriteria,criteriaContainer) {

	// NOTE: Above/Below value is retrieved by _buttons module

	var layoutInputs = Element.parseSelector("*[layoutInput]",criteriaContainer);

	var inputValues = [layoutInputs[0].value];
	console.info("Pricevs52w inputValues",inputValues)

	rowCriteria.values = (inputValues[0] == "High") ? ["GTR,0"] : ["LSS,0"];

	rowCriteria.field = this.constructFieldName(criterion.fieldPatternOrder,inputValues);

}


Screener_class.prototype.GUI_storeCriterion_buttons = function(criterion,rowCriteria,criteriaContainer) {

	// populate rowCriteria with values from either selected buttons or inputs
	var criteriaButtons = Element.parseSelector("div.criteriaButtons",criteriaContainer,"first")
	var criteriaInputs = Element.parseSelector("div.criteriaInputs",criteriaContainer,"first")
	var isButtons = Element.hasClass(criteriaInputs,"none");


	// loop through buttons and get values for those selected
	if (isButtons || criterion.showButtonsAndInputs) {

		var buttons = Element.parseSelector("a",criteriaButtons);
		for (var i=0; i<buttons.length; i++) {
			if (Element.hasClass(buttons[i],"selected")) {
				rowCriteria.values.push(buttons[i].getAttribute("value"));
			}
	
		}

		if (criterion.buttonsArePtile) {
			rowCriteria.field = rowCriteria.field + "Ptile";
		}

	}

	// determine values based on chosen operator
	else {

		var operatorSelect = Element.parseSelector("select[operatorSelect]",criteriaContainer,"first");
		var operatorLayouts = Element.parseSelector("span[operator]",criteriaContainer);
		Element.addClass(operatorLayouts,"none");

		var operator = operatorSelect.value;
		var operatorLayout = Element.parseSelector("span[operator='"+operator+"']",criteriaContainer,"first");
		Element.removeClass(operatorLayout,"none");

		// get inputs and values depending on operator selected
		var layoutInputs = Element.parseSelector("*[layoutInput]",operatorLayout);

		var value1;
		var value2;


		switch (operator) {
			case "GEQ": case "GTR": case "LEQ": case "LSS": case "EQU":
				value1 = getInputValue(layoutInputs[0]);
				if (isNumerical(value1)) {
					rowCriteria.values.push(operator + "," + value1);	
				}
			break;
		
			case "RNG1": // one drop down which contains operator(s) and value(s)
				rowCriteria.values.push(layoutInputs[0].value);
			break;

			case "BTW": case "RNG2":
				value1 = getInputValue(layoutInputs[0]);
				value2 = getInputValue(layoutInputs[1]);
				if (isNumerical(value1) && isNumerical(value2)) {

					if (parseInt(value1) > parseInt(value2)) {
						// reverse the two values: A=(A^=B)^(B^=A);
						value1 = (value1 ^= value2) ^ (value2 ^= value1);
					}
					rowCriteria.values.push("GEQ," + value1 + "|LEQ," + value2);
				}
			break;

		}





	}

	// clear non numeric and absolute the value
	function getInputValue(input) {
		var val = input.value;

		val = val.replace(/[^0-9.]/g,""); // remove all non-numeric/period characters

		if (isNaN(val) && val != ".") {
			val = ""
		}
		else if (val < 0) {
			val = Math.abs(input.value)
		}

		input.value = val;

		return input.value;
	}

	function isNumerical(value) {
		return value != "" && !isNaN(value);
	}


	//console.info("buttons rowCriteria",rowCriteria)

}


Screener_class.prototype.GUI_renderCriterion_buttons = function(criterion,rowCriteria,criteriaContainer,titleContainer) {

	// create interface buttons and/or inputs


	var buttonsContainer = Element.create("div",{className:"criteriaButtons"},null,criteriaContainer);
	var inputsContainer = Element.create("div",{className:"criteriaInputs"},null,criteriaContainer);

	var buttonsMatched = false;
	var inputsMatched = false;


	if (criterion.buttons) {

		var buttonLinks = [];
		var ul = Element.create("ul",{},null,buttonsContainer);

		var buttons = criterion.buttons, counter = 0, li, a;
		for (var i in buttons) {
			Element.create("li",{},[
				a = Element.create("a",{href:"javascript:void(0)",value:i},buttons[i])
			],ul);
			
			if (counter==0) {
				Element.addClass(a,"first"); // for CSS styling
			}

			// select button if it matches one of the saved values
			for (var j=0; j<rowCriteria.values.length; j++) {
				if (i == rowCriteria.values[j]) {
					Element.addClass(a,"selected");
					buttonsMatched = true;
				}
			}


			if (!rowCriteria.values.length && criterion.buttonsDefault) {
				// select default buttons
			}

			buttonLinks.push(a);

			counter++;

		}

		// select first button as default
		if (!rowCriteria.values.length && !buttonsMatched && criterion.buttonsSingleSelect) {
			Element.addClass(buttonLinks[0],"selected");
		}


		Element.create("div",{className:"clearNoHeight"},null,buttonsContainer);

	}
	
	if (criterion.inputs) {

		// ,inputs:[{select:"GEQ",layout:"INPUT %"},{select:"LSS",layout:"INPUT %"},{select:"-",layout:""},{select:"BTW",layout:"INPUT % and INPUT %"},{select:"RNG1",layout:"SELECT:DividendYield"}]

		// loop through .inputs and create drop down and spans

		var values = rowCriteria.values;

		var operatorOptions = [];
		var operatorLayouts = [];
		var operatorLabels = this.getProperty("operatorLabels");


		if (criterion.inputsLabel) {
			var operatorSelect = Element.create("span",{inputsLabel:"yes"},criterion.inputsLabel + "&nbsp;",inputsContainer);
		}


		if (criterion.operatorModifier && criterion.operatorModifierType == "select") {

			var isNegative = this.isCriteriaNegative(rowCriteria);
			if (isNegative) {
				rowCriteria = this.reverseCriteria(rowCriteria);
			}

			// this.getObjectFirstProperty(criterion.operatorModifierSelect)

			var operatorModifierSelect = Element.buildSelect({data:criterion.operatorModifier},{operatorModifierSelect:"yes"},inputsContainer);
			if (isNegative) {
				operatorModifierSelect.selectedIndex = 1;
			}
			Element.create("span",{},"&nbsp;&nbsp;",inputsContainer);
		}

		var operatorSelect = Element.create("select",{operatorSelect:"yes"},operatorOptions,inputsContainer);

		// hide ability to select the inputs group if there is only one option or override is set
		var singleInputsGroup = this.getObjectPropertyCount(criterion.inputs) == 1 || criterion.hideInputsOperator;
		if (singleInputsGroup) {
			Element.addClass(operatorSelect,"none");
		}
		else {
			Element.create("span",{},"&nbsp;",inputsContainer);
		}

		var operatorSelectOptions = [];

		var values = [], operators = [], opPairs;
		for (var i=0; i<rowCriteria.values.length; i++) {
			opPairs = rowCriteria.values[i].split("|");
			for (var j=0; j<opPairs.length; j++) {
				operators.push(opPairs[j].match(/(.*),/)[1]);
				values.push(opPairs[j].match(/,(.*)/)[1]);
			}
		}

		// Debugging
		//Element.create("div",{},"criteria values: " + rowCriteria.values,inputsContainer);
		//Element.create("div",{},"operators: " + operators,inputsContainer);
		//Element.create("div",{},"values: " + values,inputsContainer);


		var inputs = criterion.inputs, valueCounter, operatorOption, inputItems, value, selectMatch, span;
		for (var i in inputs) {

			valueCounter = 0
			var operator = i;
			operatorOption = Element.create("option",{value:operator},operatorLabels[operator]);


			if (rowCriteria.values.length == 1 && ((operators[0] == operator) ||  (rowCriteria.values[0].match(/\|/) && operator == "RNG2"))) {
				// one criteria set            AND      is current operator   OR          criteria contains 2 values and is 2 drop downs
				Element.setAttribute(operatorOption,"selected","selected");
			}
			else if (values.length == 2 && operator == "BTW") {
				Element.setAttribute(operatorOption,"selected","selected");
			}
			// TODO - RNG2 (for market cap)
			
			operatorSelectOptions.push(operatorOption);

			// create span with layout based on .layout
			inputItems = inputs[i].split(" ");

			span = Element.create("span",{operator:operator,className:singleInputsGroup?"":"none"},null);


			var inputCounter = 0;

			// loop through the layout pieces and generate the appropriate element type
			for (var j=0; j<inputItems.length; j++) {

				if (j) { // leading space for all but first
					Element.create("span",{},"&nbsp;",span);
				}


				// user interface element
				if (selectMatch = inputItems[j].match(/(INPUT|SELECT|HIDDEN|FIELDMODIFIER):?(.*)/)) {

					var layoutInputType = (selectMatch[1]); // input type
					var layoutInputValue = (selectMatch[2]||"layoutInput"); // set as a handle for parseSelection and defines datum name for SELECTS

					switch (layoutInputType) {
						case "INPUT": 
							Element.create("input",{type:"text",layoutInput:layoutInputValue,size:"5",value:getInputValue(layoutInputValue)},null,span);
						break;

						case "HIDDEN": 
							Element.create("input",{type:"hidden",layoutInput:layoutInputValue,size:"5",value:getInputValue(layoutInputValue)},null,span);
						break;

						case "SELECT": 
							if (operator == "RNG1") {
								value = rowCriteria.values[0] || ""; // get the entire value, including a range
							}
							else {
								value = getInputValue(); // get only a single value
							}
		
							var selectData = this.getDatum(layoutInputValue);
							Element.buildSelect({selected:value,data:selectData},{layoutInput:layoutInputValue},span);

						break;

						case "FIELDMODIFIER": // for inline field modifiers (such as SMA)
							
							var selectData = this.getDatum(layoutInputValue);
							var selectBox = this.GUI_renderFieldModifier(selectData,rowCriteria.field);
							Element.addChild(span,selectBox);
							criteriaContainer.fieldModifierCreated = true;
							criterion.fieldModifierType = "select"; // so it is picked up by "store"
							criterion.fieldModifier = true;

						break;

					}

				}

				// must be display text
				else {
					Element.create("span",{},inputItems[j],span);
				}

			}

			operatorLayouts.push(span);


		}


		Element.addChild(operatorSelect,operatorSelectOptions);
		Element.addChild(inputsContainer,operatorLayouts)

	
	}

	// returns the value, if available, and increments the counter
	// if defined, set inputsMatched to true so they will display initially
	function getInputValue(layoutInputValue) {
		var value = value = values[inputCounter++] || "";
		if (!value && !isNaN(layoutInputValue)) {
			value = layoutInputValue; // use default value passed after colon (ex: INPUT:0.10)
		}
		if (value != "") { inputsMatched = true; }
		return value;
	}

	var displayButtons = !criterion.inputs || buttonsMatched || (!inputsMatched && criterion.defaultView && criterion.defaultView == "buttons");

	// Toggle link to switch between buttons and inputs
	if (criterion.buttons && criterion.inputs && !criterion.showButtonsAndInputs) {
		var buttonsViewLink = Element.create("a",{href:"javascript:void(0)",className:"criteriaButtonsView"},[
			Element.create("span",{className:"viewInputs"},"Enter Specific Values")
			,Element.create("span",{className:"viewButtons"},"Button View")
		],titleContainer);

		Element.addClass(buttonsViewLink,displayButtons?"viewButtons":"viewInputs");

	}


	if (!criterion.showButtonsAndInputs) {
		if (displayButtons) {
			Element.addClass(inputsContainer,"none");
		}
		else {
			Element.addClass(buttonsContainer,"none");
		}
	}
	


}




// buttonsFieldModifier uses "buttons" and adds a select box at the top of the interface that defines the field to screen on
Screener_class.prototype.GUI_renderCriterionSub_buttonsFieldModifier = function(criterion,rowCriteria,criteriaContainer,titleContainer) {

	Element.setHTML(Element.parseSelector("span",titleContainer,"first"),this.getDatum(criterion.interfaceName+"_Label"));

	// build single select Growth type
	var selectData = this.getDatum(criterion.interfaceName);

	var select = Element.buildSelect({selected:rowCriteria.field.replace(/Ptile$/g,""),data:selectData},{layoutInput:"layoutInput",style:"display:block; margin-bottom:5px; width:150px"});
	Element.insertBefore(select,criteriaContainer.firstChild)
	//Events.add({element:select,type:"change",context:this,handler:this.GUI_MorningstarStyleBoxesUpdateSelect});

}



Screener_class.prototype.GUI_storeCriterionSub_buttonsFieldModifier = function(criterion,rowCriteria,criteriaContainer) {

	if (/Ptile/.test(rowCriteria.field)) {
		var ptile=true;
	}
	
	var select = Element.parseSelector("*[layoutInput]",criteriaContainer,"first")

	// set the field based on the selected type
	rowCriteria.field = select.value;

	if (ptile) {
		rowCriteria.field = rowCriteria.field + "Ptile";
	}
}







/*
Adds a criteria <tr> to the criteria table

field: the screener criteria identifier
rowCriteria: criteria to populate interface with
copyOf: criterion item to clone
*/
Screener_class.prototype.GUI_addCriteria = function(field,rowCriteria, copyOf, dontGetMatches) {

	field = field || rowCriteria.field;
	rowCriteria = rowCriteria || {field:field,values:[]}; // criteria to populate with (either from saved or clone)
	copyOf = copyOf || null; // criteria row copied from - used for placement
	
	var criterion = this.getCriterion(field);

	if (!criterion) {
		console.info("No criterion for " + field);
		return;
	}

	if (criterion.interfaceName) {
		//criterion = this.getCriterion(criterion.interfaceName);
	}

	var criteriaRow = Element.create("tr",{field:criterion.name,className:"criteriaRow"});

	if (criterion.interfaceName) {
		Element.setAttribute(criteriaRow,"interfaceName",criterion.interfaceName);
	}

	if (criterion.hideOnInterface) {
		Element.addClass(criteriaRow,"none");
	}

	// first column which contains delete link
	var removeTD = Element.create("td",{},[
			Element.create("a",{className:"delete removeCriterion",href:"javascript:void(0)"},"")
	],criteriaRow);

	// middle column which contains criteria interface
	var titleContainer, criteriaContainer
	Element.create("td",{className:"criteriaColumn"},[
		titleContainer = Element.create("div",{},[
			Element.create("span",{className:"bold"},criterion.label)
		])
		,criteriaContainer = Element.create("div",{className:"criteriaContainer"})
	]
	,criteriaRow);

	var cloneTD = Element.create("td",{},[
			criterion.canClone ? Element.create("a",{title:"Copy this criteria to narrow your results.",className:"cloneCriterion",href:"javascript:void(0)"},"Copy") : ""
	],criteriaRow);

	// right column which contains the mactch count
	var matchesTD = Element.create("td",{className:"matchesColumn"},[
		Element.create("div",{matches:"matches"},"0")
		//,Element.create("div",{},"Matches")

	],criteriaRow);


	// radio buttons to select the sign of the criteria values
	if (criterion.operatorModifier && criterion.operatorModifierType == "radio") { 

		var isNegative = this.isCriteriaNegative(rowCriteria);
		if (isNegative) {
			rowCriteria = this.reverseCriteria(rowCriteria);
		}

		var randName = Math.random();

		var radioButtons = '<label for=OM1'+randName+'><input type=radio operatorModifier=yes name=OM'+randName+' id=OM1'+randName+' '+(!isNegative?'checked=checked':'')+' />'+criterion.operatorModifier[0]+'</label>' +
			'<label for=OM2'+randName+'><input type=radio operatorModifier=yes name=OM'+randName+' id=OM2'+randName+' '+(isNegative?'checked=checked':'')+' />'+criterion.operatorModifier[1]+'</label>'
		Element.addChild(criteriaContainer,radioButtons);
	}




	if (criterion.fieldModifier && criterion.fieldModifierType == "radio") {


		if (criterion.fieldModifierLabel) {
			Element.addChild(criteriaContainer,Element.create("span",{},(criterion.fieldModifierLabel === true ? "Timeframe" : criterion.fieldModifierLabel)+"&nbsp;"));
		}

		var randName = Math.random();

		var radioButtons = [];

		for (var i in criterion.fieldModifier) {
			radioButtons.push('<label for="RI'+i+''+randName+'"><input type=radio radioInputs=yes name=RI'+randName+' id="RI'+i+''+randName+'" value="'+i+'"' +(i == rowCriteria.field?' checked="checked"':'') + ' />'+criterion.fieldModifier[i]+'</label>');
		}

		Element.addChild(criteriaContainer,radioButtons.join(""));

	}


	// radio buttons to select the sign of the criteria values
	if (criterion.radioInputs) { 

		var randName = Math.random();

		var radioButtons = [];
		for (var i in criterion.radioInputs) {
			radioButtons.push('<label for="RI'+i+''+randName+'"><input type=radio radioInputs=yes name=RI'+randName+' id="RI'+i+''+randName+'" value='+i+' />'+criterion.radioInputs[i]+'</label>');
		}

		Element.addChild(criteriaContainer,radioButtons.join(""));
	}


	// Call the mdoule's render method
	if (this["GUI_renderCriterion_"+criterion.module]) {
		this["GUI_renderCriterion_"+criterion.module](criterion,rowCriteria,criteriaContainer,titleContainer)
	}


	// Some criteria have a subModule which makes additional tweaks to the interface
	if (criterion.subModule && this["GUI_renderCriterionSub_"+criterion.subModule]) {
		this["GUI_renderCriterionSub_"+criterion.subModule](criterion,rowCriteria,criteriaContainer,titleContainer)
	}


	if (criterion.fieldModifier && criterion.fieldModifierType == "select" && !criteriaContainer.fieldModifierCreated) {
		if (criterion.fieldModifierLabel) {
			Element.addChild(criteriaContainer,Element.create("span",{},(criterion.fieldModifierLabel === true ? "Timeframe" : criterion.fieldModifierLabel)+"&nbsp;"));
		}

		var selectBox = this.GUI_renderFieldModifier(criterion.fieldModifier,rowCriteria.field);
		Element.addChild(criteriaContainer,selectBox);
	}

	if (criterion.retrieveAverage) {
		Element.addChild(criteriaContainer,Element.create("div",{className:"criterionFieldAverage"},"&nbsp;"));
	}

	if (criterion.footer) {
			Element.addChild(criteriaContainer,Element.create("div",{className:"criterionFooter"},criterion.footer));
	}



	if (copyOf) {
		Element.insertAfter(criteriaRow,copyOf);
		Element.fadeAttention(criteriaRow,{startColor:"ffffcc",endColor:"ffffff"});
	}
	else {
		Element.addChild(this.criteriaTable,criteriaRow);
	}

	this.GUI_attachCriterionEvents(criteriaRow);


	// store the current criteria values
	// Certain interfaces have internal processing/delays (multi-selects for example, have a 5ms delay for IE support)
	var self = this;
	var addStoreDelay = criterion.addStoreDelay ? (criterion.addStoreDelay === true ? 10 : criterion.addStoreDelay) : 0;

	if (criterion.radioInputs || criterion.module == "multiSelect") {
		addStoreDelay = 10;
	}

	var dontGetMatches = dontGetMatches || false;

	(addStoreDelay && document.all) ? setTimeout(function() { self.GUI_storeCriterion(null,criteriaRow,null,dontGetMatches); },addStoreDelay) : this.GUI_storeCriterion(null,criteriaRow,null,dontGetMatches);
	
	//gets a special icon & label
	
	if(criterion.field == "PriceCurrent"){
		var labelDiv = Element.parseSelector('tr[field="PriceCurrent"] div', 'criteriaTable')[0];
		Element.create('span', {'class': 'infoIcon'},
			[
				Element.create('img', {'src': '../../images/icons/info.gif'}), 
				Element.create('label', {'class': 'bold'}, 'Results may not include real-time price information' )
			],
			labelDiv
		);		
	}

}


// Buttons in module:buttons button clickd.  Change its state and store the criteria
Screener_class.prototype.GUI_criteriaButtonClicked = function(e,el,data) {
	Events.cancel(e);

	var parentTR = Element.getParentBySelector(el,"tr[field]",true);
	var field = parentTR.getAttribute("field");
	var criterion = this.getCriterion(field);

	if (criterion.buttonsSingleSelect) { // deselect all buttons if single select
		var criteriaContainer = Element.parseSelector("td.criteriaColumn",parentTR,"first");
		var criteriaButtons = Element.parseSelector("div.criteriaButtons a",criteriaContainer);
		Element.removeClass(criteriaButtons,"selected");
	}

	Element.toggleClass(el,"selected");
	el.blur();

	this.GUI_storeCriterion(null,el,data);

}


// run when "Button/Inputs" link is clicked to toggle view
Screener_class.prototype.GUI_criteriaButtonsViewClicked = function(e,el,data) {
	Events.cancel(e);
	

	var parentTR = Element.getParentBySelector(el,"tr[field]",true); // get parent TR, including itself if a TR is passed

	var criteriaButtons = Element.parseSelector("div.criteriaButtons",parentTR,"first");
	var criteriaInputs = Element.parseSelector("div.criteriaInputs",parentTR,"first");

	var isButtons = Element.hasClass(criteriaInputs,"none");

	el = Element.parseSelector("a.criteriaButtonsView",parentTR,"first");

	Element.replaceClass(el,"view(?:Buttons|Inputs)",isButtons?"viewInputs":"viewButtons"); // remove both buttons and inputs classNames and add the appropriate one
	Element.switchClass(criteriaButtons,"none",isButtons);
	Element.switchClass(criteriaInputs,"none",!isButtons);

	this.GUI_storeCriterion(null,el,data);



}


// Attaches change/click/keyup events to criteria elements so they 
Screener_class.prototype.GUI_attachCriterionEvents = function(criteriaRow) {

	Events.add({element:Element.parseSelector("input[type/=.'radio|checkbox']",criteriaRow),type:"click",context:this,handler:this.GUI_storeCriterion});

	Events.add({element:Element.parseSelector("select",criteriaRow),type:"change",context:this,handler:this.GUI_storeCriterion});

	Events.add({element:Element.parseSelector("a.criteriaButtonsView",criteriaRow),type:"click",context:this,handler:this.GUI_criteriaButtonsViewClicked});

	Events.add({element:Element.parseSelector("div.criteriaButtons a",criteriaRow),type:"click",context:this,handler:this.GUI_criteriaButtonClicked});

	Events.add({element:Element.parseSelector("input[type='text']",criteriaRow),type:"keyup",delay:400,context:this,handler:this.GUI_storeCriterion});

	Events.add({element:Element.parseSelector("a.removeCriterion",criteriaRow),type:"click",context:this,handler:this.GUI_removeCriterion});

	Events.add({element:Element.parseSelector("a.cloneCriterion",criteriaRow),type:"click",context:this,handler:this.GUI_cloneCriterion});
	

}






// Radio Inputs are drawn across the top of a criterion row
// parseSelect and get the one that is checked - called from "store"
Screener_class.prototype.GUI_getCriterionRadioInputsValue = function(criteriaContainer,defaultValue) {
	var radioInput = Element.parseSelector('input[radioInputs][checked=.`true`]',criteriaContainer,"first");
	return radioInput ? radioInput.value : defaultValue;
}

// checks a radio input - called from "render"
Screener_class.prototype.GUI_setCriterionRadioInputsSelected = function(criteriaContainer,value) {

	var radioInputs = Element.parseSelector('input[radioInputs]',criteriaContainer);

	for (var i=0; i<radioInputs.length; i++) {
		if (radioInputs[i].value == value) {

			var radio = radioInputs[i];

			// radio buttons can not be selected immediately after creation.  Add a delay for IE support
			document.all ? setTimeout(function() { radio.checked = true; },5) : radio.checked = true;

			return true;
		}
	}
	return false;
}



// selects a criteria button of a specific value
Screener_class.prototype.GUI_selectCriteriaButton = function(criteriaContainer,value) {

	var criteriaButtons = Element.parseSelector("div.criteriaButtons a",criteriaContainer);
	for (var i=0; i<criteriaButtons.length; i++) {
		if (criteriaButtons[i].getAttribute("value") == value) {
			Element.addClass(criteriaButtons[i],"selected");
		}
	}
}


// selects a criteria button of a specific value
Screener_class.prototype.GUI_getCriteriaButtonValue = function(criteriaContainer,defaultValue) {

	var criteriaButtons = Element.parseSelector("div.criteriaButtons a",criteriaContainer);
	for (var i=0; i<criteriaButtons.length; i++) {
		if (Element.hasClass(criteriaButtons[i],"selected")) {
			return criteriaButtons[i].getAttribute("value");
		}
	}

	return defaultValue || null;
}


// sets values of layoutInput fields from an associative object
// called from render methods to update the interface
Screener_class.prototype.GUI_setCriteriaInputValues = function(criteriaContainer,valuesObj) {
	var layoutInputs = Element.parseSelector("*[layoutInput]",criteriaContainer);

	for (var i in valuesObj) {
		if (layoutInputs[i]) {
			layoutInputs[i].value = valuesObj[i];
		}
	}
}






/* -- Loaded:/tdameritrade/screener/Screener_class.criteria.js*/




/* -- Attempting to load:/tdameritrade/common/scripts/Element.3additions.js */


// client side methods unique to results.asp go in here

Screener_class.prototype.resultsInit = function() {

	// These two commands were moved to the bottom of resultsBody.asp
	//this.renderTDAMButtons();
	//Element.addClass("customViewContainer","none"); // this has to be hidden after renderTDAMButtons

	Events.addIf({element:"saveScreen",type:"click",context:this,handler:this.saveScreenDialogShow});

	Events.addIf({element:"resultViewSelect",type:"change",context:this,handler:this.results_changeView});
	Events.addIf({element:"saveAsWatchlist",type:"click",context:this,handler:this.results_saveAsWatchlist});
	Events.addIf({element:"watchlistSelectGroup",type:"click",context:this,handler:this.results_selectWatchListGroup});
	Events.addIf({element:"watchlistSelectGroupUncheckAll",type:"click",context:this,handler:this.results_selectWatchListGroupUncheckAll});

	var resultsTable = Element.get("resultsTable");
	this.resultSymbolLinks = Element.parseSelector('a[symbollink]!noRollover',resultsTable);

	if (this.results_symbolRolloverContent) {
		Events.add({element:this.resultSymbolLinks,type:"mouseover",context:this,handler:this.results_symbolRollover,data:true});
		Events.add({element:this.resultSymbolLinks,type:"mouseout",context:this,handler:this.results_symbolRollover,data:false});
	}
	
	if(this.results_popOptionReport) {
		Events.add({element:Element.parseSelector('a[reportSymbol]',resultsTable),type:"click",context:this,handler:this.results_popOptionReport});
	}

	// Check if in a popup
	if (window.opener) {
		Events.add({element:this.resultSymbolLinks,type:"click",context:this,handler:this.results_symbolPopupClick});
	}

	//this.createCommonTopLinks();

	this.createResultsTopLinks();

	if (Element.get("resultsTable") && Element.getSize("resultsTable").width > 849) {
		function setWidthOfContainers() {
			var width = Element.getSize("timestampBar").width - 135;
			Element.setWidth("top", width);
			Element.setWidth("criteriaListContainer", width);
		}
		setWidthOfContainers();
		Events.add({element:window, type:"resize", handler:setWidthOfContainers});
		window.scrollTo(0,0);
	}


	// Enable for custom view quick testing
	//this.customView_showInterface()
	//Element.get("customViewLabel").value = "AAA";

}

Screener_class.prototype.createResultsTopLinks = function(e,el,over) {
	
	Common.addTopLink(Element.create("a",{href:"#",Events:{type:"click",context:this,handler:this.popupGlossary},className:"fleft"},"Screeners Glossary"));
	
	var text = /\/stocks\//i.test(location.href) ? "(Basic View Only)" : "(Overview View Only)";
	

	Common.addTopLink(Element.create("a",{href:"#",Events:{type:"click",context:this,handler:this.results_popupExport}},"Export Data"), text);
	if (!window.opener) {
		Common.addTopLink(Element.create("a",{href:"#",Events:{type:"click",context:this,handler:this.results_popupTearaway},id:"tearAway",className:"iconBackground fleft"},"Tear Away"));
	}	
	Common.addTopLink(Element.create("a",{href:"#",Events:{type:"click",context:this,handler:this.popupHelpContent},className:"iconBackground fleft",id:"tdamPageHelp"},"Page Help"));

	
}

Screener_class.prototype.results_symbolPopupClick = function(e,el,over) {
	Events.cancel(e);
	window.opener.location.href = el.getAttribute("href");
}

Screener_class.prototype.results_popupExport = function(e,el,data) {
	// always export first static view
	window.open('resultsExport.asp?resultView='+this.util.getObjectIndexProperty(this.resultViews,1),'');
}


Screener_class.prototype.results_popupTearaway = function(e,el,data) {
	window.open('resultsTearaway.asp?display=popup','_blank','width=800,height=537,scrollbars=1,menubar=1,resizable=1');
}


Screener_class.prototype.results_closeDialog = function(e,el,data) {

	var dialog = Element.getParentBySelector(el,"div.popupDialog");

	if (dialog) {
		dialog.Shadow.remove();
		Element.remove(dialog);
		dialog = null;
	}

}

Screener_class.prototype.results_createDialog = function(params) {


	var dialog = Element.create("div",{id:"saveScreenDialog",className:"popupDialog"},[
		Element.create("img",{id:"saveScreenDialogClose",className:"close hand",src:"/tdameritrade/images/charts/ico-close.gif",Events:{type:"click", context:this, handler:this.results_closeDialog}})
		,Element.create("div",{id:"saveScreenDialogTitle",className:"moduleHeader nocorner"},params.title)
		,Element.create("div",{id:"saveScreenDialogEntry",className:"saveScreenDialogBody pad10  smaller"},params.content)

	],document.body);



	var pos = Element.getXY(params.link);
	Element.setXY(dialog,pos.x,pos.y-150);

	this.renderTDAMButtons(dialog);

	dialog.Shadow = new DropShadow({element:dialog,Amonitor:true,offset:3,iframe:1});

	return dialog;



}

Screener_class.prototype.results_selectWatchListGroup = function(e,el,over) {

	Events.cancel(e);

	var symbolCheckboxes = Element.parseSelector('input[type="checkbox"][symbol]',"resultsTable");
	var thoseChecked = Element.parseSelector('[checked=.`true`]',symbolCheckboxes)

	Element.setProperty(symbolCheckboxes,"checked",false);

	if (thoseChecked.length) {
		Element.setHTML(el,el.getAttribute("originalLabel"));
		return;
	}

	Element.setHTML(el,"Deselect All");

	Element.setProperty(symbolCheckboxes.splice(0,35),"checked",true);

}


Screener_class.prototype.results_selectWatchListGroupUncheckAll = function(e,el,over) {

	Events.cancel(e);

	var symbolCheckboxes = Element.parseSelector('input[type="checkbox"][symbol]',"resultsTable");

	Element.setProperty(symbolCheckboxes,"checked",false);


}


Screener_class.prototype.results_saveAsWatchlist = function(e,el,over) {

	Events.cancel(e)

	var symbolCheckboxes = Element.parseSelector('input[type="checkbox"][symbol][checked=.`true`]',"resultsTable");

	this.watchListSymbols = [];

	for (var i=0; i<symbolCheckboxes.length; i++) {
		this.watchListSymbols.push(symbolCheckboxes[i].getAttribute("symbol"));
	}

	if (!this.watchListSymbols.length) {
		alert("Please select at least one symbol to add to your watch list");
		return;
	}
	else if (this.watchListSymbols.length > 35) {
		this.results_saveAsWatchlistDialogShow(el);
	}
	else {
		this.results_storeWatchlist();
	}

}




Screener_class.prototype.results_saveAsWatchlistDialogShow = function(el) {

	if (this.watchlistDialog && this.watchlistDialog.parentNode) {
		Element.remove(this.watchlistDialog);
	}


	var dialogContent = [
							Element.create("div",{className:"bottomBorder smallest padBot5 margBot5"},"The number of screen results exceed the maximum number of symbols that can be saved to a watch list.  Only the <b>first 35 symbols</b> selected will be saved.<br />Do you wish to continue?")
							,Element.create("div",{className:"fright"},[
								Element.create("a",{id:"a-savebutton",tdbutton:"green",width:100,Events:{type:"click", context:this, handler:this.results_storeWatchlist}},"Continue")
				
							])
							,Element.create("div",{className:"fright margRight5"},[
								Element.create("a",{id:"a-savecancelbutton",tdbutton:"white",Events:{type:"click", context:this, handler:this.results_closeDialog}},"Cancel")
							])		
							,Element.create("div",{className:"clearNoHeight"})		
						];


	this.watchlistDialog = this.results_createDialog({link:el,title:"Save as Watch List",content:dialogContent});


}

Screener_class.prototype.results_storeWatchlist = function() {

	// take only 35
	this.watchListSymbols = this.watchListSymbols.splice(0,35);

	if (gSessionSeedDomain) {
		var watchlistURL = gSessionSeedDomain + "/cgi-bin/apps/u/WatchListCreate?symbols=" + this.watchListSymbols.join(",");
		window.opener ? (window.opener.location.href = watchlistURL) : (location.href = watchlistURL);
	}
	else {
		alert("This would go to the watch list create page for:\n"+this.watchListSymbols.join(", "));
	}


}
Screener_class.prototype.results_symbolRollover = function(e,el,over) {


	if (window.results_symbolRollover_TIMER) {
		clearTimeout(window.results_symbolRollover_TIMER);
		window.results_symbolRollover_TIMER = null;
	}

	if (!over) {
		if (moduleContainer = Element.get("symbolChartModule")) {
			moduleContainer.Shadow.remove();
			Element.remove(moduleContainer);
		}
	}
	else {

		var self = this;
		results_symbolRollover_TIMER = setTimeout(function() { self.results_symbolRolloverDelay(el) },100);
	}

}

Screener_class.prototype.results_symbolRolloverContent = function(symbolData) {
			return Element.create("div",{},recurseObject({o:symbolData,nowrite:1}));
}

Screener_class.prototype.results_symbolRolloverDelay = function(el) {

			var symbol = el.getAttribute("symbollink");

			var resultsDataBySymbol = this.util.hashTable(this.resultsData.data,{field:"ticker",returnNew:true});
			var symbolData = resultsDataBySymbol[symbol]

			//console.info(symbolData)


			var moduleContainer = Element.create("div",{id:"symbolChartModule"},null);
			var size = Element.getSize(el);
			var pos = Element.getXY(el);


			Element.addChild(moduleContainer,this.results_symbolRolloverContent(symbolData));


			Element.addChild(document.body,moduleContainer);
			var x = pos.x+size.width+5;
			var y = pos.y-15;


			var viewPort = getViewport();

			var moduleSize = Element.getSize(moduleContainer);

			//console.info(x,moduleSize.width,pageSize.width)
			// move over if too far right
			if (x + moduleSize.width > viewPort.right) {
				x = pos.x - moduleSize.width - 15;
			}

			// move over if too far left
			if (x < viewPort.left) {
				x = viewPort.left + 10;
			}

			// move below if won't fit above
			if (y < viewPort.top) {
				y = viewPort.top + 10;
			}

			// move up if cut off on bottom
			if ((y + moduleSize.height) > viewPort.bottom) {
				y -= (y + moduleSize.height) - viewPort.bottom + 10;
			}


			Element.setXY(moduleContainer,x,y);


			moduleContainer.Shadow = new DropShadow({element:moduleContainer,Amonitor:true,offset:3});



}


Element_class.prototype.getPageScroll = function() {

		if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict
			return {x:document.documentElement.scrollLeft,y:document.documentElement.scrollTop};
		}
		else if (document.body) { // all other Explorers	
			return {x:document.body.scrollLeft,y:document.body.scrollTop};
		}

}

// Called from buffer_saveScreen.asp when screen already exists
Screener_class.prototype.saveScreenDialogExists = function() {
	this.saveScreenDialogShow(null,null,{exists:true});
}

Screener_class.prototype.saveScreenDialogShow = function(e,el,data) {

	Events.cancel(e);

	var alreadyExists = data && data.exists;

	if (!this.saveScreenDialog) {
	
		var a, img;
		this.saveScreenDialog = Element.create("div",{id:"saveScreenDialog"},[
			Element.create("img",{id:"saveScreenDialogClose",className:"close hand",src:"/tdameritrade/images/charts/ico-close.gif",Events:{type:"click", context:this, handler:this.saveScreenDialogClose}})
			,Element.create("div",{id:"saveScreenDialogTitle",className:"moduleHeader nocorner"},"Save This Screen")
			,Element.create("div",{id:"saveScreenDialogEntry",className:"saveScreenDialogBody pad10  smaller"},[
				Element.create("div",{className:"bottomBorder smallest padBot5 margBot5"},"You can save your current screen results for later use by naming it now. For previously-saved screens, you may re-save with your new changes.")
				,Element.create("div",{className:"bottomBorder padBot5 margBot5"},[
					this.saveStepName = Element.create("div",{className:"bold"},"Name this Screen")
					,this.saveStepNameInUse = Element.create("div",{className:"bold error"},"This name is already in use.  Overwrite or supply another name.")
					,this.saveInput = Element.create("input",{id:"",type:"text",Events:{type:"keypress", context:this, handler:this.saveClearInUse}})
				])
				,Element.create("div",{className:"haslayout"},[
					Element.create("div",{className:"fright margRight5"},[
						Element.create("a",{id:"a-savecancelbutton",tdbutton:"white",Events:{type:"click", context:this, handler:this.saveScreenDialogClose}},"Cancel")
	
					])
					,this.saveButtonOverwrite = Element.create("div",{className:"fright none"},[
						Element.create("a",{id:"a-saveoverwritebutton",tdbutton:"green",width:130,Events:{type:"click", context:this, handler:this.saveScreenDialogSave,data:{overwrite:true}}},"Save & Overwrite")
	
					])
					,this.saveButton = Element.create("div",{className:"fright"},[
						Element.create("a",{id:"a-savebutton",tdbutton:"green",width:100,Events:{type:"click", context:this, handler:this.saveScreenDialogSave}},"Save Screen")
	
					])
				])				
			])
			,Element.create("div",{id:"saveScreenDialogSaving",className:"saveScreenDialogBody pad10  smaller"},[
				Element.create("div",{className:"alignCenter bold margTop25"},"Saving Screen...")
				,Element.create("div",{id:"saveScreenDialogSavingName1",className:"light small alignCenter margBot25"},"")
				,Element.create("div",{className:"clearNoHeight"})
			])
			,Element.create("div",{id:"saveScreenDialogSuccess",className:"saveScreenDialogBody pad10  smaller"},[
				Element.create("div",{className:"alignCenter bold tdGreen margTop25"},"Saved Successfully!")
				,Element.create("div",{id:"saveScreenDialogSavingName2",className:"light small alignCenter margBot25"},"")
				,Element.create("div",{className:"haslayout"},[
					Element.create("div",{className:"fright"},[
						aclose = Element.create("a",{id:"a-saveclosebutton",tdbutton:"green",Events:{type:"click", context:this, handler:this.saveScreenDialogClose}},"Close")
					])
				])
			])
		],document.body);
	
		var selects = Element.parseSelector("div.screenerResultsOptions select", "screenerContainer");
		
		Element.addClass( selects, "hide" )
		
	
		this.renderTDAMButtons(this.saveScreenDialog);
	
		this.saveScreenDialog.Shadow = new DropShadow({element:this.saveScreenDialog,monitor:false,offset:3});

		//this.saveInput.focus();


	}
	else {
		// hide if already shown
		
		if (!alreadyExists && this.saveScreenDialog.style.visibility == "visible") {
			this.saveScreenDialogClose();
			return;
		}
	}

	//Element.setHTML("saveScreenDialogSavingName1","AAAA");
	//Element.setHTML("saveScreenDialogSavingName2","BBBB");



	if (alreadyExists) {
		Element.setDisplay("saveScreenDialogEntry","block");
		Element.setDisplay("saveScreenDialogSaving","none");
		Element.setDisplay("saveScreenDialogSuccess","none");
		Element.setDisplay(this.saveStepName,"none");
		Element.setDisplay(this.saveStepNameInUse,"block");
		Element.setDisplay(this.saveButton,"none");
		Element.setDisplay(this.saveButtonOverwrite,"block");
		Element.setVisibility(this.saveScreenDialog,"visible");

		this.saveInput.focus();


	}
	else {


		Element.setDisplay("saveScreenDialogEntry","block");
		Element.setDisplay("saveScreenDialogSaving","none");
		Element.setDisplay("saveScreenDialogSuccess","none");
		Element.setDisplay(this.saveStepName,"block");
		Element.setDisplay(this.saveStepNameInUse,"none");
		Element.setDisplay(this.saveButton,"block");
		Element.setDisplay(this.saveButtonOverwrite,"none");
		Element.setVisibility(this.saveScreenDialog,"visible");
	
		//this.saveInput.value = (screenerData.screenName != "custom")?screenerData.screenName:"";

	}
	
	Element.switchClass(this.saveInput,"error",alreadyExists);



	if (el) {
		var pos = Element.getXY(el);
		Element.setXY(this.saveScreenDialog,pos.x,pos.y-200);
	}

	this.saveScreenDialog.Shadow.update();

	WCH.Apply(this.saveScreenDialog, null, false);
}




Screener_class.prototype.saveScreenDialogSave = function(e,el,data) {

	data = data || {};

	var name = this.saveInput.value;
	if(!/\s/g.test( name ) || /\S{40,}/g.test( name )) name = name.substring(0, 40);
	
	var displayName = this.escapeInput(name);
	 displayName = name.replace(/(.{25})/g,"$1<br />");
	
	Element.setHTML("saveScreenDialogSavingName1",'"' + displayName + '"');
	Element.setHTML("saveScreenDialogSavingName2",'"' + displayName + '"');
	Element.setDisplay("saveScreenDialogEntry","none");
	Element.setDisplay("saveScreenDialogSaving","block");
	Element.setDisplay("saveScreenDialogSuccess","none");

	this.saveScreenDialog.Shadow.update();

	this.loadContentBuffer({
		 page:"buffer_saveScreen.asp"
		,action:"saveScreen"
		,data:{name:name,overwrite:data.overwrite||false}
		,context:this
		//,onload:this.GUI_displayMatches
	});

}


Screener_class.prototype.saveClearInUse = function() {

	Element.setDisplay(this.saveStepName,"block");
	Element.setDisplay(this.saveStepNameInUse,"none");
	Element.removeClass(this.saveInput,"error");
	Element.setDisplay(this.saveButton,"block");
	Element.setDisplay(this.saveButtonOverwrite,"none");

	this.saveScreenDialog.Shadow.update();

}


// Called from buffer_saveScreen.asp when saved successfully
Screener_class.prototype.saveScreenSuccess = function(e,el,data) {
	this.saveScreenDialogClose(null,null,{success:true});
}

// Called from either close buttons or saveScreenSuccess
Screener_class.prototype.saveScreenDialogClose = function(e,el,data) {
	if (this.saveScreenDialog) {
	
		WCH.Discard(this.saveScreenDialog);

		if (data && data.success) {
			Element.setDisplay("saveScreenDialogEntry","none");
			Element.setDisplay("saveScreenDialogSaving","none");
			Element.setDisplay("saveScreenDialogSuccess","block");

			this.saveScreenDialog.Shadow.update();

		}
		else {
			this.saveScreenDialog.Shadow.remove();
			Element.remove(this.saveScreenDialog);
			this.saveScreenDialog = null;
			
			var selects = Element.parseSelector("div.screenerResultsOptions select", "screenerContainer");
			Element.removeClass( selects, "hide" )
		}
		
	}
}



// populated for modules such as the chart rollover
Screener_class.prototype.setResultsData = function(data) {
	this.resultsData = data;
}


Screener_class.prototype.results_changeView = function(e,el,data) {

	var view = typeof el == "string" ? el : el.value; 
	if (!view) { return; }

	if (view == "edit") {
		this.customView_retrieveCustomViews();
	}
	else {

		location.href='?params='+view;

	}



}

Screener_class.prototype.customView_retrieveCustomViews = function(e,el,data) {
	
	this.customView_showInterface(); // the JS file or utils now populates .customViews
	return;

	// no need for this, but leave in just in case
	this.loadContentBuffer({
		 page:"buffer_utils.asp"
		,action:"retrieveCustomViews"
		,data:{}
		,context:this
		,onload:this.customView_showInterface
	});


}

Screener_class.prototype.customView_showInterface = function(e,el,data) {

	this.customView_init();

	Element.get("resultViewSelect").selectedIndex = 0;

	Element.removeClass("customViewContainer","none");

	// populate custom view select with view options
	var select = Element.buildSelect({firstOption:{text:"New Custom View...",value:"new"},data:this.customViews,text:"label"},{id:"customViewSelect"});

	this.customView_populateAvailableSelected(null,select,null);

	this.customView_updateInterface();


}


Screener_class.prototype.customView_init = function(customViews) {

	if (this._customView_initialized) { return; }
	this._customView_initialized = true;
	
	Element.get( "symbol" ).focus(); /* Safari keeps focus on the dropBox making the page reload over and over again */


	Events.addIf({element:"customViewAvailable",type:"dblclick",context:this,handler:this.customView_moveToSelected});
	Events.addIf({element:"customViewAvailable",type:"mouseup",context:this,handler:this.customView_updateInterface});
	Events.addIf({element:"customViewAvailable",type:"keyup",context:this,handler:this.customView_updateInterface});
	Events.addIf({element:"customViewAvailable",type:"keydown",context:this,handler:this.customView_moveToSelected,data:{keypress:true}});
	Events.addIf({element:"customViewSelected",type:"dblclick",context:this,handler:this.customView_moveToAvailable});
	Events.addIf({element:"customViewSelected",type:"mouseup",context:this,handler:this.customView_updateInterface});
	Events.addIf({element:"customViewSelected",type:"keyup",context:this,handler:this.customView_updateInterface});
	Events.addIf({element:"customViewSelected",type:"keydown",context:this,handler:this.customView_moveToAvailable,data:{keypress:true}});

	Events.addIf({element:"customViewAdd",type:"click",context:this,handler:this.customView_moveToSelected});
	Events.addIf({element:"customViewRemove",type:"click",context:this,handler:this.customView_moveToAvailable});

	Events.addIf({element:"customViewUp",type:"click",context:this,handler:this.customView_moveDirection,data:"up"});
	Events.addIf({element:"customViewDown",type:"click",context:this,handler:this.customView_moveDirection,data:"down"});


	Events.addIf({element:"customViewSave",type:"click",context:this,handler:this.customView_save});
	Events.addIf({element:"customViewSaveOverwrite",type:"click",context:this,handler:this.customView_save,data:{overwrite:true}});
	Events.addIf({element:"customViewCancel",type:"click",context:this,handler:this.customView_cancel});
	Events.addIf({element:"customViewDelete",type:"click",context:this,handler:this.customView_delete});
	Events.addIf({element:"customViewNewOption",type:"click",context:this,handler:this.customView_clearLabel});

	Events.addIf({element:"customViewLabel",type:"keypress", context:this, handler:this.customView_resetSaveInputs});
	Events.addIf({element:"customViewSelect",type:"change",context:this,handler:this.customView_populateAvailableSelected});

}


Screener_class.prototype.customView_clearLabel = function(e,el,data) {

	Element.get("customViewLabel").value = "";
	Element.get("customViewLabel").focus();

}

Screener_class.prototype.customView_save = function(e,el,data) {

	data = data || {};

	Events.cancel(e);

	var name = Element.get("customViewName").value;
	var label = Element.get("customViewLabel").value;

	var fields = [];

	var select = Element.get("customViewSelected");
	var options = Element.parseSelector("option",select);

	if (options.length > 21) {
		alert("Please select a maximum of 21 columns.");
		return;
	}

	for (var x=0; x<options.length;x++) {
			fields.push(options[x].value);
	}

	var method = Element.get("customViewSelect").value == "new" || Element.get("customViewNewOption").checked ? "new" : "update";

	if (method == "new") {
		name = "CV" + (new Date()).getTime(); // create a new, unique name

		var savedViewsCount = this.util.getObjectLength(this.customViews);
		if (savedViewsCount >= 42) {
			alert('You are limited to a maximum of 42 custom views.  Please choose "Update View" or delete a current view.');
			return;
		}


		var select = Element.get("customViewSelect");
		var previousNameOption = Element.parseSelector('option[text=."'+label+'"]',select,"first");

		if (previousNameOption && !data.overwrite) {
			//alert("Please specify a unique name.");

			Element.removeClass("customViewSaveOverwrite","none");
			Element.addClass("customViewSave","none");
			Element.removeClass("customViewNameInUse","none");
			Element.addClass("customViewLabel","error");

			return;
		}
		else if (previousNameOption) {
			name = previousNameOption.value;
		}

	}

	if (!label || label.match("^My Custom View")) {
		alert("Please specify a name.");
		return;
	}

	if (!fields.length) {
		alert("Please add at least one field.");
		return;
	}

	// post to utils.asp and reload page with new view
	this.loadContentBuffer({
		 page:"buffer_utils.asp"
		,action:"saveCustomView"
		,data:{name:name,label:label,fields:fields.join("|"),method:method}
		,context:this
		,onload:function() { location.href = "?resultView="+name; }
		//,onload:this.customView_showInterface
	});





}

Screener_class.prototype.customView_cancel = function(e,el,data) {
	Element.addClass("customViewContainer","none");
}


Screener_class.prototype.customView_delete = function(e,el,data) {
	Events.cancel(e);

	var name = Element.get("customViewSelect").value;

	if (!confirm("Delete this custom view?")) {
		return;
	}

	this.loadContentBuffer({
		 page:"buffer_utils.asp"
		,action:"deleteCustomView"
		,data:{name:name}
		,context:this
		,onload:this.customView_showInterface
	});



}

Screener_class.prototype.customView_populateAvailableSelected = function(e,el,data) {

	var name = el.value;

	Element.switchClass("customViewUpdateOptions","none",name == "new");
	Element.switchClass("customViewNewOptions","none",name != "new");
	Element.switchClass("customViewDelete","none",name == "new");

	var view = (name == "new" || !this.customViews[name]) ? {label:"",fields:""} : this.customViews[name];

	Element.get("customViewLabel").value = view.label || "My Custom View";
	Element.get("customViewName").value = name;


	var fieldsAvailable = this.getProperty("customViewFields").split("|");
	var fieldsSelected = view.fields.split("|");


	var fieldsAvailableData = [];
	var fieldsSelectedData = [];

	var field, criterion;
	for (var i=0; i<fieldsAvailable.length; i++) {
		field = fieldsAvailable[i];
		criterion = this.getCriterion(field);

		if (criterion) {

			if (this.util.arrayContains(fieldsSelected,field)) {
				fieldsSelectedData.push({text:this.getFieldLabel(field,criterion),value:field});
			}
			else {
				fieldsAvailableData.push({text:this.getFieldLabel(field,criterion),value:field});
			}
		}
	}

	Element.buildSelect({data:fieldsAvailableData},{id:"customViewAvailable"});
	Element.buildSelect({data:fieldsSelectedData},{id:"customViewSelected"});

	this.customView_updateInterface();

}




Screener_class.prototype.customView_moveDirection = function(e,el,direction) {

	var selectedOptions = Element.parseSelector('option[selected=.`true`]',"customViewSelected");

	if (selectedOptions.length != 1) { return; } // only one works well for now

	for (var i=0; i<selectedOptions.length; i++) {
		if (direction == "up") {
			if (selectedOptions[i].previousSibling) {
				Element.insertBefore(selectedOptions[i],selectedOptions[i].previousSibling);
			}
		}
		else if (direction == "down") {
			if (selectedOptions[i].nextSibling) {
				Element.insertAfter(selectedOptions[i],selectedOptions[i].nextSibling);
			}
		}
	}

	this.customView_updateInterface();

}


Screener_class.prototype.customView_moveToAvailable = function(e,el,data) {
	
	data = data || {};

	if (data.keypress) {
		var keyCode = e.nativeEvent.which || e.nativeEvent.keyCode;
		if (keyCode != 13) { return; };
	}

	var selectedOptions = Element.parseSelector('option[selected=.`true`]',"customViewSelected");
	Element.setProperty(selectedOptions,"selected",false);
	Element.addChild("customViewAvailable",selectedOptions);

	this.customView_updateInterface();

}


Screener_class.prototype.customView_moveToSelected = function(e,el,data) {

	data = data || {};

	if (data.keypress) {
		var keyCode = e.nativeEvent.which || e.nativeEvent.keyCode;
		if (keyCode != 13) { return; };
	}

	var moveToSelectedOptions = Element.parseSelector('option[selected=.`true`]',"customViewAvailable");

	Element.setProperty(moveToSelectedOptions,"selected",false);
	Element.addChild("customViewSelected",moveToSelectedOptions);

	this.customView_updateInterface();

}




Screener_class.prototype.customView_resetSaveInputs = function(e,el,data) {

	Element.addClass("customViewSaveOverwrite","none");
	Element.removeClass("customViewSave","none");
	Element.addClass("customViewNameInUse","none");
	Element.removeClass("customViewLabel","error");

}

Screener_class.prototype.customView_updateInterface = function(e,el,data) {
	var self = this;
	setTimeout(function() { self.customView_updateInterfaceDelay(); },1);
}

Screener_class.prototype.customView_updateInterfaceDelay = function(e,el,data) {

	var availableOptionsHighlighted = Element.parseSelector('option[selected=.`true`]',"customViewAvailable");
	availableOptionsHighlighted.length ? btnOn("customViewAdd") : btnOff("customViewAdd");

	var selectedOptionsHighlighted = Element.parseSelector('option[selected=.`true`]',"customViewSelected");
	selectedOptionsHighlighted.length ? btnOn("customViewRemove") : btnOff("customViewRemove");

	var selectedOptionsChosen = Element.parseSelector('option',"customViewSelected");
	selectedOptionsChosen.length ? btnOn("customViewSave") : btnOff("customViewSave");
	selectedOptionsChosen.length ? btnOn("customViewSaveOverwrite") : btnOff("customViewSaveOverwrite");

	this.customView_resetSaveInputs();
}





/* -- Loaded:/tdameritrade/screener/Screener_class.results.js*/


