if (window.HTMLElement) {	
	HTMLElement.prototype.__defineGetter__("innerText", function() {
		return this.textContent;
	});
	
	HTMLElement.prototype.__defineSetter__("innerText", function (str) {
		this.textContent = str;
	});
}
// Version info
var APP_VERSION = '1.1.51.1';
// Urls
var PID_HM = "hm";
var U_HM = "/schools.aspx/q/page=hm";
var PID_FND = "fnd";
var U_FND = "/schools.aspx/q/page=fnd";
var PID_CMP = "cmp";
var U_CMP = "/schools.aspx/q/page=cmp";
var PID_SU = "su";
var U_SU = "/schools.aspx/q/page=su";
var PID_AB = "ab";
var U_AB = "/schools.aspx/q/page=ab";
var PID_PP = "pp";
var U_PP = "/popup.aspx/q/page=pp";
var PID_TMS = "tms";
var U_TMS = "/popup.aspx/q/page=tms";
var PID_MP = "mp";
var U_MP = "/schools.aspx/q/page=mp";
var PID_CU = "cu";
var U_CU = "/schools.aspx/q/page=cu";
var PID_NWS = "nws";
var U_NWS = "/schools.aspx/q/page=nws";
var PID_SR = "sr";
var U_SR = "/schools.aspx/q/page=sr";
var PID_PR = "pr";
var U_PR = "/schools.aspx/q/page=pr";
var PID_SP = "sp";
var U_SP = "/schools.aspx/q/page=sp";
var PID_SC = "sc";
var U_SC = "/schools.aspx/q/page=sc";
var PID_CCP = "ccp";
var U_CCP = "/schools.aspx/q/page=ccp";
var PID_DP = "dp";
var U_DP = "/schools.aspx/q/page=dp";
var PID_SL = "sl";
var U_SL = "/schools.aspx/q/page=sl";
var PID_EMLP = "emlp";
var PID_PRVS = "prvs";
var PID_PRVC = "prvc";
var U_PRVC = "/schools.aspx/q/page=prvc";
var PID_PEM = "pem";
var U_PEM = "/popup.aspx/q/page=pem";
var PID_PPR = "ppr";
var U_PPR = "/popup.aspx/q/page=ppr";
var PID_SCL = "scl";
var PID_PDD = "pdd";
var U_PDD = "/popup.aspx/q/page=pdd";
var PID_PIU = "piu";
var PID_DL = "dl";
var U_DL = "/schools.aspx/q/page=dl";
var PID_PGL = "pgl";
var U_PGL = "/popup.aspx/q/page=pgl";
var PID_PLM = "plm";
var U_PLM = "/popup.aspx/q/page=plm";
var PID_PRR = "prr";
var PID_US = "us";
var U_US = "/schools.aspx/q/page=us";
var PID_USR = "usr";
var U_USR = "/schools.aspx/q/page=usr";
var PID_SUR = "sur";
var U_SUR = "/schools.aspx/q/page=sur";
var PID_MPS = "mps";
var U_MPS = "/schools.aspx/q/page=mps";
var PID_PCP = "pcp";
var U_PCP = "/popup.aspx/q/page=pcp";
var PID_PCW = "pcw";
var U_PCW = "/popup.aspx/q/page=pcw";
var PID_DSC = "dsc";
var U_DSC = "/popup.aspx/q/page=dsc";
var PID_UEP = "uep";
var U_UEP = "/schools.aspx/q/page=uep";
var PID_UER = "uer";
var U_UER = "/schools.aspx/q/page=uer";
var PID_AMBI = "ambi";
var U_AMBI = "/schools.aspx/q/page=ambi";
var PID_AMBG = "ambg";
var U_AMBG = "/schools.aspx/q/page=ambg";
var PID_AMBGS = "ambgs";
var U_AMBGS = "/schools.aspx/q/page=ambgs";
var PID_AMBR = "ambr";
var U_AMBR = "/schools.aspx/q/page=ambr";
var PID_AMHM = "amhm";
var U_AMHM = "/schools.aspx/q/page=amhm";
var PID_NRW = "nrw";
var U_NRW = "/schools.aspx/q/page=nrw";
var PID_JN = "jn";
var U_JN = "/schools.aspx/q/page=jn";
var PID_JND = "jnd";
var U_JND = "/schools.aspx/q/page=jnd";
var PID_JNF = "jnf";
var U_JNF = "/schools.aspx/q/page=jnf";

// Parameters 
var P_PAGE_ID = "page";
var P_SEARCH_TERM = "txt";
var P_US_STATE = "ust";
var P_SEARCH_RADIUS = "mr";
var P_ZIP_CODE = "zc";
var P_SCHOOL_ID = "sid";
var P_DISTRICT_ID = "did";
var P_PAGE_NUMBER = "p";
var P_SORT_ORDER = "so";
var P_SORT_CRITERIA = "sc";
var P_FIRST_PAGE = "fp";
var P_SELECTED_SCHOOLS = "ssid";
var P_CHECKED_SEARCHED_SCHOOLS = "csds";
var P_START_SCHOOL_SELECTION = "ss";
var P_SAVE_SELECTED_SCHOOLS_STATE = "st";
var P_SCHOOLS_TO_COMPARE = "scid";
var P_METRIC_SUBGROUPS = "mcsb";
var P_MAP_MODE = "mm";
var P_MENU_NAVIGATION_INDEX = "midx";
var P_MENU_SELECTED_INDEX = "msidx";
var P_REVIEW_ID = "rvid";
var P_CURRENT_PAGE_URL = "purl";
var P_PAGE_NUMBERS = "pn";
var P_SCHOOL_TERM_1 = "fst";
var P_SCHOOL_TERM_2 = "sst";
var P_SCHOOL_TERM_3 = "tst";
var P_START_ADDRESS = "sad";
var P_REVIEW_STATUS = "rviv";
var P_HELPFUL_REVIEW_ID = "hri";
var P_REVIEWED_SCHOOL_ID = "rsi";
var P_SEARCHED_SCHOOL_ID = "ssi";
var P_SCHOOL_LINKS_SHOW_ALL = "sla";
var P_FILTER_NARROW_BY = "fltr_nb";
var P_COMMAND = "cmd";
var P_EMAILTEXT = "eml";
var P_CONTEXT_ID = "ctxt";
var P_ALTERNATE_DISTANCE = "ad";
var P_ALTERNATE_DISTANCE_STATE = "adss";
var P_ALTERNATE_LONGITUDE = "alg";
var P_ALTERNATE_LATITUDE = "alt";
var P_ALTERNATE_CITY = "ac";
var P_ALTERNATE_CITY_STATE = "acs";
var P_ALTERNATE_DISTRICT = "adt";
var P_ALTERNATE_DISTRICT_STATE = "adts";
var P_RETURN_URL = "rurl";
var P_BLOCK_REDIRECT = "rb";
var P_URL_PAGE_ID = "pid";
var P_COMPARE_SEARCH_ACTION = "csa";
var P_COMPARE_SEARCH_SOURCE = "css";
var P_CONFIRM_PAGE = "cp";
var P_DESCRIPTION = "dsc";
var P_ALTERNATE_CITY_PAGE_NUMBER = "acpn";
var P_ALTERNATE_DISTRICT_PAGE_NUMBER = "adpn";
var P_EMAIL_ADDRESS = "ema";
var P_SUBSCRIPTION_TYPE = "sut";
var P_NEARBY_OF_SCHOOL_ID = "nbsid";
var P_LONGITUDE = "lng";
var P_LATITUDE = "lat";
var P_CLIENT_IP = "ClientIP";
var P_VISITED_DISTRICT_ID = "vdi";
var P_PREVIEWED_PAGES = "prpg";
var P_PREVIEW_PAGE_ID = "prpi";
var P_PAGE_TYPE = "pgtp";
var P_CONFIG_ELEMENT_ID = "elid";
var P_CONFIG_DOCUMENT_NAME = "cdn";
var P_LEVEL = "lv";
var P_FIND_A_SCHOOL_TIP = "fndtip";

// Enum SchoolSortOrder
var SchoolSortOrder = {
Descending: 0,
Ascending: 1
}

// Enum SchoolSortCriteria
var SchoolSortCriteria = {
Default: 0,
GradeLevels: 1,
Reading: 2,
Math: 3,
StudentsPerTeacher: 4,
StateCode: 5,
Enrollment: 6
}

// Enum K12SortCriteria
var K12SortCriteria = {
Default: 0,
district_name: 1,
county_name: 2,
median_price_homes: 3,
average_tax: 4,
POST_3_4: 5,
POST_4: 6,
total_revenue_per_student: 7,
low_income_enrollment: 8
}

// Enum K12SortOrder
var K12SortOrder = {
Descending: 0,
Ascending: 1
}

// Enum StateSign
var StateSign = {
Undefined: 0,
Selected: 1,
Unselected: 2
}

// Enum Command
var Command = {
Undefined: 0,
IsSearchStateDefined: 1,
IsZipCodeValid: 2,
IsCompareStateDefined: 3,
SetReviewStatus: 4
}

// Enum SearchControlType
var SearchControlType = {
Undefined: 0,
Term: 1,
Compare: 2,
ZipCode: 3
}

// Enum CompareSearchAction
var CompareSearchAction = {
None: 0,
PageNavigate: 1,
Compare: 2,
AddSchool: 3
}

// Query string parameters
var QueryParams = ["fst","sst","tst","ssid","csds","adt","ctxt"];
// Persistent parameters
var PersistentParams = ["ssid"];
// Constants
var Constants ={"ClientResponseDataObjectName":"RESPONSE_DATA","IDSeparator":",","StatusSeparator":":"};var UrlContext = { "ParameterDelimiter":"/", "QueryStringDelimiter":"/q/", "ParameterDelimiterEscaped":"/", "QueryStringDelimiterEscaped":"/q/", "NameValueDelimiter":"=", "UrlParameterPrefix":"up_"};
var PageInfo = [{ "PageId":"hm", "Popup":false, "ClientVariable":"PID_HM"},{ "PageId":"fnd", "Popup":false, "ClientVariable":"PID_FND"},{ "PageId":"cmp", "Popup":false, "ClientVariable":"PID_CMP"},{ "PageId":"su", "Popup":false, "ClientVariable":"PID_SU"},{ "PageId":"ab", "Popup":false, "ClientVariable":"PID_AB"},{ "PageId":"pp", "Popup":true, "ClientVariable":"PID_PP"},{ "PageId":"tms", "Popup":true, "ClientVariable":"PID_TMS"},{ "PageId":"mp", "Popup":false, "ClientVariable":"PID_MP"},{ "PageId":"cu", "Popup":false, "ClientVariable":"PID_CU"},{ "PageId":"nws", "Popup":false, "ClientVariable":"PID_NWS"},{ "PageId":"sr", "Popup":false, "ClientVariable":"PID_SR"},{ "PageId":"pr", "Popup":false, "ClientVariable":"PID_PR"},{ "PageId":"sp", "Popup":false, "ClientVariable":"PID_SP"},{ "PageId":"sc", "Popup":false, "ClientVariable":"PID_SC"},{ "PageId":"ccp", "Popup":false, "ClientVariable":"PID_CCP"},{ "PageId":"dp", "Popup":false, "ClientVariable":"PID_DP"},{ "PageId":"sl", "Popup":false, "ClientVariable":"PID_SL"},{ "PageId":"prvc", "Popup":false, "ClientVariable":"PID_PRVC"},{ "PageId":"pem", "Popup":true, "ClientVariable":"PID_PEM"},{ "PageId":"ppr", "Popup":true, "ClientVariable":"PID_PPR"},{ "PageId":"pdd", "Popup":true, "ClientVariable":"PID_PDD"},{ "PageId":"dl", "Popup":false, "ClientVariable":"PID_DL"},{ "PageId":"pgl", "Popup":true, "ClientVariable":"PID_PGL"},{ "PageId":"plm", "Popup":true, "ClientVariable":"PID_PLM"},{ "PageId":"us", "Popup":false, "ClientVariable":"PID_US"},{ "PageId":"usr", "Popup":false, "ClientVariable":"PID_USR"},{ "PageId":"sur", "Popup":false, "ClientVariable":"PID_SUR"},{ "PageId":"mps", "Popup":false, "ClientVariable":"PID_MPS"},{ "PageId":"pcp", "Popup":true, "ClientVariable":"PID_PCP"},{ "PageId":"pcw", "Popup":true, "ClientVariable":"PID_PCW"},{ "PageId":"dsc", "Popup":true, "ClientVariable":"PID_DSC"},{ "PageId":"uep", "Popup":false, "ClientVariable":"PID_UEP"},{ "PageId":"uer", "Popup":false, "ClientVariable":"PID_UER"},{ "PageId":"ambi", "Popup":false, "ClientVariable":"PID_AMBI"},{ "PageId":"ambg", "Popup":false, "ClientVariable":"PID_AMBG"},{ "PageId":"ambgs", "Popup":false, "ClientVariable":"PID_AMBGS"},{ "PageId":"ambr", "Popup":false, "ClientVariable":"PID_AMBR"},{ "PageId":"amhm", "Popup":false, "ClientVariable":"PID_AMHM"},{ "PageId":"nrw", "Popup":false, "ClientVariable":"PID_NRW"},{ "PageId":"jn", "Popup":false, "ClientVariable":"PID_JN"},{ "PageId":"jnd", "Popup":false, "ClientVariable":"PID_JND"},{ "PageId":"jnf", "Popup":false, "ClientVariable":"PID_JNF"}];
var SchoolMattersConfig ={"MaxSchoolsToCompare":3,"MinSchoolsToCompare":2,"CompareSchoolsRowCount":5,"SearchResultsRowCount":25,"RowsPerPage":50,"NearbySchoolsCount":20,"MaxSelectedSchoolsCount":30,"BreadCreambSchoolNameLimit":23,"BreadCreambDistrictNameLimit":23};
var WebFrameworkConfig ={"XmlPath":"/xml/","LayoutControlsPath":"/ui/controls/layout/","RootUrl":"/","SiteUrl":"http://www.schoolmatters.com","LoginUrl":"","PopupUrl":"/popup.aspx","CssPath":"/css","ImagesPath":"/images","JavaScriptPath":"/js","WidgetScriptPath":"/widget","JavaScriptPathMaster":"/js/master","CssPathMaster":"/css/master","UseCssDebugFiles":false,"UseJavaScriptDebugFiles":false,"DefaultPageUrl":"/schools.aspx","ApplicationShortTitle":"SchoolMatters","ResourceHandlerUrl":"http://admin.schoolmatters.com/SMResourceHandler/resourcehandler.res","RequestHandler":"/requestHandler.aspx"};

// System functions
var $get = function(id) { return document.getElementById(id); };
var $exist = function(value) { return typeof(value) != "undefined"; };
var $notExistOrNull = function(value) { return typeof(value) == "undefined" || value === null; };
var $ensure = function(obj, value) { return $notExistOrNull(obj) ? value : obj; }

var isIE = /*@cc_on!@*/false;

function extend(dst, src) {
	for (prop in src) {
		if (src.hasOwnProperty(prop)) {
			dst[prop] = src[prop];
		}
	}
}

// String extensions
String.isEmpty = function(text) {
	return text === null || text.length === 0;
};

String.prototype.trim = function() {
   var m = this.match(/^\s*(\S+(\s+\S+)*)\s*$/);
	return (m === null) ? "" : m[1];
};

String.prototype.format = function() {
	var result = this.valueOf();
	if (typeof(arguments[0]) != 'undefined') {
		reParam = new RegExp("~(\\d+)","igm");
		var paramsMatches = result.match(reParam);		
		for (var i=0; i < paramsMatches.length; i++) {
			var paramIndex = parseInt(paramsMatches[i].substring(1));
			result = result.replace(paramsMatches[i], arguments[paramIndex]);
		}
	}
	return result;
};

String.prototype.contextFormat = function(dataContext) {
	var result = this.valueOf();
	paramRx = /\$.+?\$/igm;
	var matches = result.match(paramRx);	
	for (var i=0; i < matches.length; i++)	{
		var match = matches[i];
		var prop = match.substring(1, match.length-1);
		if (dataContext.hasOwnProperty(prop)) {
			result = result.replace(match, dataContext[prop]);
		}
	}
	return result;
};


//====================
// Array extensions
//====================
Array.prototype.indexOf = function(element){
	var result = -1;
	if (typeof(element) != "undefined"){
		for (var i=0; i<this.length; i++){
			if (typeof(this[i] != "undefined") && this[i] === element){
				result = i;
				break;
			}
		}
	}
	return result;
};

Array.prototype.remove = function(item){
   var index = this.indexOf(item);
   if (index != -1) {
		this.removeAt(index);
   }
};

Array.prototype.removeAt = function(index) {
	var items = this.splice(index, 1);
	return items.length == 1 ? items[0] : null;
};

Array.prototype.map = function(callback, context){
	var result = [];	
	for (var i=0, iLen=this.length; i<iLen; i++) {
		result.push(context ? callback.call(context, this[i], i, this) : callback(this[i], i, this));
	}
	return result;
};

Array.prototype.filter = function(callback, context){
	var result = [];	
	for (var i=0; i< this.length; i++){
		var matches = context ? callback.call(context, this[i], i, this) : callback(this[i], i, this);
		if (matches) {
			result.push(this[i]);
		}
	}
	return result;
};

Array.prototype.forEach = function(callback, context){
	for (var i=0; i<this.length; i++) {
		(!!context) ? callback.call(context, this[i], i, this) : callback(this[i], i, this);
	}
};

Array.getFrom = function(src){
    if (!src) return [];
    var result = [];    
    for (var i = 0, ic = src.length; i < ic; i++) 
        result.push(src[i]);
    return result;    
}

Array.getHash = function Array_getHash(array) {
	var result = {};
	if (array) {
		for (var i=0; i < array.length; i++) {
			var key = array[i];
			if (typeof(key) == "string") {
				key = key.trim();
			}
			result[key] = key;
		}
	}
	return result;
}

function $attachEvent(obj, eventName, func)
{			
	var handler = null;
	if (obj.addEventListener != null)
	{
		// get listeners cache
		var cache = obj.__eventsCache || (obj.__eventsCache = {});
		
		// get listeners for the given event type
		var eventHandlers = cache[eventName] || (cache[eventName] = []);
		
		// create intermediate function to save DOM Event object into global variable window.event
		handler = function attachEvent_Handler(e) {
			window.event = e;
			return func.call(obj, e);
		}		
		// bind created handler 
		obj.addEventListener(eventName, handler, false);			
		
		// save event handler to remove it later
		eventHandlers[eventHandlers.length] = { listener: func, handler: handler };	
	}
	else if (obj.attachEvent != null) {
		obj.attachEvent("on" + eventName, func);
	}
}

function $detachEvent(obj, eventName, func)
{
	var handler = null;
	
	if (obj.removeEventListener  != null)
	{
		var cache = obj.__eventsCache;
		
		if (cache) {
			// get handlers for the given event type
			var eventHandlers = cache[eventName];
			if (eventHandlers) {
				// locate listener to remove respective handler
				for (var i=0, length = eventHandlers.length; i<length; i++) {					
					if (eventHandlers[i].listener === func) {
						handler = eventHandlers[i].handler;
						break;
					}
				}
			}			
			// detach event handler and remove it from cache
			if (handler && typeof(handler) == 'function') {
				obj.removeEventListener(eventName, handler, false);	
				eventHandlers.splice(i, 1);
			}
		}		
	}
	else if (obj.detachEvent != null) {
		obj.detachEvent("on" + eventName, func);
	}
}

function $fireEvent(obj, name)
{
	if (obj.addEventListener != null) {
		var evt = document.createEvent("Event");
		evt.initEvent(name, true, true); 
		obj.dispatchEvent(evt);
	}
	else if (obj.attachEvent != null) {
		obj.fireEvent("on" + name, document.createEventObject());
	}

}


//===========================
//      Type extensions 
//===========================
Function.registerNamespace = function Function_registerNamespace(name) {
	var parts = name.split(".");
	var root = window;
	for (var i=0; i<parts.length; i++) {
		var part = parts[i];
		var ns = root[part];
		if (ns && !ns.isNamespace) {
			throw new Error(SystemMessages.NamespaceDeclarationError.format(name));			
		}
		if (!ns) {
			ns = root[part] = {};			
			ns.isNamespace = true;
		}
		root = ns;		
	}	
}

Function.prototype.register = function Function_register(superClass) {
	this.isClass = true;
  this.prototype.constructor = this;
	if (superClass) {
		this.superClass = superClass;
		this.toBeResolved = true;
  }
};

Function.prototype.resolve = function Function_resolve() {
	if (this.toBeResolved) {
		var superClass = this.superClass;		
		superClass.resolve();
		for (prop in superClass.prototype) {
			var member = superClass.prototype[prop];
			if (!this.prototype[prop]) {
				this.prototype[prop] = member;
			}
		}
		delete this.toBeResolved;
	}	
};

Function.prototype.base = function Function_base(instance, args) {
	this.resolve();
	if (this.superClass) {
		this.superClass.apply(instance, args);
	}
};

Function.prototype.callBase = function Function_callBase(instance, name, args) {
    var method = this.getBase(name);
    if (!method) return false;
    return method.apply(instance, args);
};

Function.prototype.getBase = function Function_getBase(name) {
    var superClass = this.getSuperClass();
    if (superClass) {
        var method = superClass.prototype[name];
        return (method instanceof Function) ? method : null;
    }
    return null;
};

Function.prototype.getSuperClass = function Function_getSuperClass() {
    return !$exist(this.superClass) ? null : this.superClass;
};


Function.prototype.bind = function() {
    var method = this;
    var args = Array.getFrom(arguments);
    var obj = args.shift();
    return function() {
        return method.apply(obj, args.concat(Array.getFrom(arguments)));
    }
}
// ----------
// EventList
EventList = function EventList() {
    this.list = {};
}

EventList.prototype = {
    getEvent : EventHandlerList_getEvent,
    add : EventList_add,
    remove : EventList_remove,
	getHandler : EventList_getHandler
}

function EventHandlerList_getEvent(id) {
	if (!this.list[id]) 
		this.list[id] = [];
    return this.list[id];
}

function EventList_add(id, handler) {
	this.getEvent(id).push(handler);
}

function EventList_remove(id, handler) {
	var e = this.getEvent(id);
	if (!e) return;
	e.remove(handler);	
}

function EventList_getHandler(id) {
	var e = this.getEvent(id);
	if (!e) return;
	return function(source, args) {
		for (var i=0, ic=e.length; i<ic; ++i) {
			e[i](source, args);
		}
	};		
}
// ----------
// SystemMessages
var SystemMessages = {
	ClassDeclarationError : "Couldn't register class ~0",
	NamespaceDeclarationError : "Couldn't register namespace ~0",
	RendererInitializationError : "Couldn't initialize renderer",
	NotImplemented : "Functionality is not implemented yet"
}
// ----------
// Event
Event = {
	cancel : Event_cancel
}

function Event_cancel(e) {
	if (e.preventDefault) {
		e.preventDefault();
		e.stopPropagation();
	} else {
		e.returnValue = false;
		e.cancelBubble = true;
	}
}
// ----------
// Cookie
Cookie = {
	Set : Cookie_Set,
	SetSession : Cookie_SetSession,
	setCommon : Cookie_Set_Common,
    Get : Cookie_Get,
    IsEnabled: Cookie_IsEnabled
}

function Cookie_Set(name, value) {
	// one year cookie
	this.setCommon(name,value,1);
}

function Cookie_SetSession(name, value) {
	this.setCommon(name,value);
}

function Cookie_Set_Common(name,value,time) {
	var cookieData;
	var cookieString;
	
	if (time) {
		var expires = new Date();
		expires.setFullYear(expires.getFullYear() + time);
		cookieData = {
			name: name,
			value: encodeURIComponent(value),
			expires: expires.toGMTString()
		};
		cookieString = "$name$=$value$;path=/;expires=$expires$".contextFormat(cookieData);
	}
	else {
		cookieData = {
			name: name,
			value: encodeURIComponent(value)
		};
		cookieString = "$name$=$value$;path=/;".contextFormat(cookieData);
	}
	document.cookie = cookieString;
}

function Cookie_Get(name) {
	var cookieValue = "";
    var nameRx = new RegExp("~0=([^;]*)".format(name));
    var result = nameRx.exec(document.cookie);
    
    if (result != null) { 
		// get first group
		cookieValue = decodeURIComponent(result[1]);
    }
    return cookieValue;
}

function Cookie_IsEnabled() {
	if(document.cookie.indexOf("TemporaryTestCookie=") == -1) {
		document.cookie = "TemporaryTestCookie=yes;" + document.cookie;
		if(document.cookie.indexOf("TemporaryTestCookie=") == -1)
			return false;
		else
			return true;
	}
	return true;
}
// ----------
// Exception
Exception = {
   alertNotImplemented: Exception_alertNotImplemented
}

function Exception_alertNotImplemented() {
	alert(SystemMessages.NotImplemented);
}
// ----------
// DomElement
DomElement = {
	addCssClass : DomElement_addCssClass,
	removeCssClass : DomElement_removeCssClass,
	getParent : DomElement_getParent,
	getElementsByClassName : DomElement_getElementsByClassName,
	getLocation: DomElement_getLocation
}

function DomElement_addCssClass(element, cssClass) {
	if (element != null) {
		var className = element.className;
		if (className != null) {
			classes = className.split(' ');
			for (var i = 0; i < classes.length; ++i) {
				if (classes[i] == cssClass)
					return;
			}
			element.className = element.className + " " + cssClass;
		}
		else
			element.className = cssClass;			
	}
}

function DomElement_removeCssClass(element, cssClass) {
	if (element != null) {
		var className = element.className;
		if (className != null) {
			classes = className.split(' ');
			res = [];
			for (var i = 0; i < classes.length; ++i) {
				if (classes[i] == cssClass) {
					continue;
				}
				res.push(classes[i]);
			}
			element.className = res.join(' ');
		}
	}
}

function DomElement_getParent(element) { 
	if ($notExistOrNull(element)) 
		return null;
	if (element.parentNode) 
		return element.parentNode;
	else if (element.parentElement) 
		return element.parentElement;
	else
		return null;
}

function DomElement_getLocation(element) {
    var offsetX = 0;
	var offsetY = 0;

    var previous = null;
    for (var parent = element; parent; parent = parent.offsetParent) {
		offsetX +=  parent.offsetLeft;
		offsetY += parent.offsetTop;
	}
	return { x: offsetX, y: offsetY };
}

function DomElement_getElementsByClassName(elm, tagName, className) {
	if (arguments.length == 1) {
		className = arguments[0];		
		elm = document.body;
		tagName = "*";
	}
	var elements = (tagName == "*" && elm.all) ? elm.all :
		elm.getElementsByTagName(tagName);

	var result = [];
	className = className.replace(/\-/g, "\\-");
	var classRx = new RegExp("(^|\\s)" + className + "(\\s|$)");
	var element;
	for (var i=0, length=elements.length; i<length; i++){
		element = elements[i];     
		if(classRx.test(element.className)){
		   result.push(element);
		}   
	}
	return result;
}

$$ = DomElement.getElementsByClassName;

Function.registerNamespace("SM");

// ----------
// SM.SavedSchoolInfo
SM.SavedSchoolInfo = function SM_SavedSchoolInfo(schoolID, checked) {
	this.schoolID = schoolID;
	this.checked = checked;
}

SM.SavedSchoolInfo.prototype = {
	GetID : SM_SavedSchoolInfo_GetID,
	IsChecked : SM_SavedSchoolInfo_IsChecked
}

function SM_SavedSchoolInfo_GetID() {
	return this.schoolID;
}

function SM_SavedSchoolInfo_IsChecked() {
	return this.checked;
}

SM.SavedSchoolInfo.register();

// SM.SavedSchoolsManager
SM.SavedSchoolsManager = function SM_SavedSchoolsManager() {
}

SM.SavedSchoolsManager.prototype = {
	Get : SM_SavedSchoolsManager_Get,
	Set : SM_SavedSchoolsManager_Set,
	AddToUrl : SM_SavedSchoolsManager_AddToUrl,
	GetFromUrl : SM_SavedSchoolsManager_GetFromUrl,
	SetCheckedSearchResultSchools : SM_SavedSchoolsManager_SetCheckedSearchResultSchools,
	GetCheckedSearchResultSchools : SM_SavedSchoolsManager_GetCheckedSearchResultSchools,
	ResetSchoolsSelection : SM_SavedSchoolsManager_ResetSchoolsSelection,
	SetStartSelection : SM_SavedSchoolsManager_SetStartSelection,
	GetStartSelection : SM_SavedSchoolsManager_GetStartSelection,
	SetSaveSelectedSchoolsState : SM_SavedSchoolsManager_SetSaveSelectedSchoolsState,
	GetSaveSelectedSchoolsState : SM_SavedSchoolsManager_GetSaveSelectedSchoolsState
}

function SM_SavedSchoolsManager_Get() { 
	return null; 
}

function SM_SavedSchoolsManager_Set(pairs) {
}

function SM_SavedSchoolsManager_AddToUrl(url) { 
	return url; 
}

function SM_SavedSchoolsManager_GetFromUrl(url) {
}

function SM_SavedSchoolsManager_SetCheckedSearchResultSchools() {
}

function SM_SavedSchoolsManager_GetCheckedSearchResultSchools() {
}

function SM_SavedSchoolsManager_ResetSchoolsSelection() {
}

function SM_SavedSchoolsManager_SetStartSelection(isStartSelection) {
}

function SM_SavedSchoolsManager_GetStartSelection() { 
	return false; 
}

function SM_SavedSchoolsManager_SetSaveSelectedSchoolsState(saveState) {
}

function SM_SavedSchoolsManager_GetSaveSelectedSchoolsState() { 
	return false;
}

SM.SavedSchoolsManager.register();

// SM.CookieSavedSchoolsManager
SM.CookieSavedSchoolsManager = function SM_CookieSavedSchoolsManager() {
	SM.SavedSchoolsManager.base(this);
}

SM.CookieSavedSchoolsManager.prototype = {
	Get : SM_CookieSavedSchoolsManager_Get,
	Set : SM_CookieSavedSchoolsManager_Set,
	AddToUrl : SM_CookieSavedSchoolsManager_AddToUrl,
	GetFromUrl : SM_CookieSavedSchoolsManager_GetFromUrl,
	SetCheckedSearchResultSchools : SM_CookieSavedSchoolsManager_SetCheckedSearchResultSchools,
	GetCheckedSearchResultSchools : SM_CookieSavedSchoolsManager_GetCheckedSearchResultSchools,
	ResetSchoolsSelection : SM_CookieSavedSchoolsManager_ResetSchoolsSelection,
	SetStartSelection : SM_CookieSavedSchoolsManager_SetStartSelection,
	GetStartSelection : SM_CookieSavedSchoolsManager_GetStartSelection,
	SetSaveSelectedSchoolsState : SM_CookieSavedSchoolsManager_SetSaveSelectedSchoolsState,
	GetSaveSelectedSchoolsState : SM_CookieSavedSchoolsManager_GetSaveSelectedSchoolsState
}

function SM_CookieSavedSchoolsManager_GetStartSelection() {
	return Cookie.Get(P_START_SCHOOL_SELECTION) == "true" ? true : false;
}

function SM_CookieSavedSchoolsManager_SetStartSelection(isStartSelection) {
	Cookie.SetSession(P_START_SCHOOL_SELECTION, isStartSelection ? "true" : "false");
}

function SM_CookieSavedSchoolsManager_SetSaveSelectedSchoolsState(saveState) {
	Cookie.SetSession(P_SAVE_SELECTED_SCHOOLS_STATE, saveState ? "true" : "false");	
}

function SM_CookieSavedSchoolsManager_GetSaveSelectedSchoolsState() {
	return Cookie.Get(P_SAVE_SELECTED_SCHOOLS_STATE) == "true" ? true : false;
}

function SM_CookieSavedSchoolsManager_Get() {
	SM.CookieSavedSchoolsManager.callBase(this, "Get", []);
	
	var cookieValue = Cookie.Get(P_SELECTED_SCHOOLS);
	var pairs = cookieValue.split(Constants.IDSeparator);
	
	var res = pairs.map(function(pair) {
		var parts = pair.split(Constants.StatusSeparator);
		if (parts.length == 2) 
			return new SM.SavedSchoolInfo(parseInt(parts[0]), parts[1] == "1");
		return null;
	}, this);      
	
	res = res.filter(function(item) { return item != null; });
	
	return res;
}

function SM_CookieSavedSchoolsManager_GetCheckedSearchResultSchools() {
	SM.CookieSavedSchoolsManager.callBase(this, "GetCheckedSearchResultSchools", []);
	
	var cookieValue = Cookie.Get(P_CHECKED_SEARCHED_SCHOOLS);
	var res = [];
	if (cookieValue && !String.isEmpty(cookieValue))
		res = cookieValue.split(Constants.IDSeparator);
	
	return res;
}

function SM_CookieSavedSchoolsManager_Set(pairs) {
	SM.CookieSavedSchoolsManager.callBase(this, "Set", [pairs]);
	
	var res = [];
	for (var i = 0, ic = pairs.length; i < ic; ++i) {
		var savedSchoolInfo = pairs[i];
		res.push([savedSchoolInfo.GetID(), Constants.StatusSeparator, (savedSchoolInfo.IsChecked() == true) ? "1" : "0"].join(''));
	}
		
	var cookieValue = res.join(Constants.IDSeparator);
	Cookie.SetSession(P_SELECTED_SCHOOLS, cookieValue);		
}

function SM_CookieSavedSchoolsManager_SetCheckedSearchResultSchools(ids) {

	SM.CookieSavedSchoolsManager.callBase(this, "SetCheckedSearchResultSchools", [ids]);
	
	var res = [];
	for (var i = 0, ic = ids.length; i < ic; ++i)
		res.push("~0".format(ids[i]));
		
	var cookieValue = res.join(Constants.IDSeparator);
	Cookie.SetSession(P_CHECKED_SEARCHED_SCHOOLS, cookieValue);	
}

function SM_CookieSavedSchoolsManager_AddToUrl(url) {
	return SM.CookieSavedSchoolsManager.callBase(this, "AddToUrl", [url]);
}

function SM_CookieSavedSchoolsManager_GetFromUrl(url) {
	SM.CookieSavedSchoolsManager.callBase(this, "GetFromUrl", [url]);	
}

function SM_CookieSavedSchoolsManager_ResetSchoolsSelection() {
	SM.CookieSavedSchoolsManager.callBase(this, "ResetSchoolsSelection", []);
	Cookie.SetSession(P_CHECKED_SEARCHED_SCHOOLS, "");
	SavedSchoolsManager.SetStartSelection(false);
}

SM.CookieSavedSchoolsManager.register(SM.SavedSchoolsManager);

// SM.QueryStringSavedSchoolManager
SM.QueryStringSavedSchoolsManager = function() {
	SM.SavedSchoolsManager.base(this);
	
	this.selectedSchools = null;
	this.CheckedSearchedSchools = "";
	this.StartSelection = false;
	this.SaveSelectedSchoolState = false;
}

SM.QueryStringSavedSchoolsManager.prototype = {
	Get : SM_QueryStringSavedSchoolsManager_Get,
	Set : SM_QueryStringSavedSchoolsManager_Set,
	AddToUrl : SM_QueryStringSavedSchoolsManager_AddToUrl,
	GetFromUrl : SM_QueryStringSavedSchoolsManager_GetFromUrl,
	SetCheckedSearchResultSchools : SM_QueryStringSavedSchoolsManager_SetCheckedSearchResultSchools,
	GetCheckedSearchResultSchools : SM_QueryStringSavedSchoolsManager_GetCheckedSearchResultSchools,
	ResetSchoolsSelection : SM_QueryStringSavedSchoolsManager_ResetSchoolsSelection,
	SetStartSelection : SM_QueryStringSavedSchoolsManager_SetStartSelection,
	GetStartSelection : SM_QueryStringSavedSchoolsManager_GetStartSelection,
	SetSaveSelectedSchoolsState : SM_QueryStringSavedSchoolsManager_SetSaveSelectedSchoolsState,
	GetSaveSelectedSchoolsState : SM_QueryStringSavedSchoolsManager_GetSaveSelectedSchoolsState
}

function SM_QueryStringSavedSchoolsManager_GetStartSelection() {
	return this.StartSelection;
}

function SM_QueryStringSavedSchoolsManager_SetStartSelection(isStartSelection) {
	this.StartSelection = isStartSelection;
}

function SM_QueryStringSavedSchoolsManager_SetSaveSelectedSchoolsState(saveState) {
	this.SaveSelectedSchoolState = saveState;
}

function SM_QueryStringSavedSchoolsManager_GetSaveSelectedSchoolsState() {
	return this.SaveSelectedSchoolState;
}

function SM_QueryStringSavedSchoolsManager_Get() {
	SM.QueryStringSavedSchoolsManager.callBase(this, "Get", []);
	
	return this.selectedSchools;
}

function SM_QueryStringSavedSchoolsManager_Set(pairs) {
	SM.QueryStringSavedSchoolsManager.callBase(this, "Set", [pairs]);
	
	this.selectedSchools = pairs;
}

function SM_QueryStringSavedSchoolsManager_AddToUrl(url) {
	if (this.selectedSchools) {
	
		var res = [];
		for (var i = 0, ic = this.selectedSchools.length; i < ic; ++i) {
			var savedSchoolInfo = this.selectedSchools[i];
			res.push("~0~1~2".format(savedSchoolInfo.GetID(), Constants.StatusSeparator, (savedSchoolInfo.IsChecked() == true) ? "1" : "0"));
		}
		
		var value = res.join(Constants.IDSeparator);
		url = Url.setParameter(url, P_SELECTED_SCHOOLS, value);
	}
	
	if (!String.isEmpty(this.CheckedSearchedSchools))
		url = Url.setParameter(url, P_CHECKED_SEARCHED_SCHOOLS, this.CheckedSearchedSchools);
		
	if (this.StartSelection == true)
		url = Url.setParameter(url, P_START_SCHOOL_SELECTION, "true");
		
	if (this.SaveSelectedSchoolState == true)
		url = Url.setParameter(url, P_SAVE_SELECTED_SCHOOLS_STATE, "true");
	
	return url;
}

function SM_QueryStringSavedSchoolsManager_GetFromUrl(url) {
	
	var value = Url.getParameter(url, P_SELECTED_SCHOOLS);
	if (value) {
		var pairs = value.split(Constants.IDSeparator);
		
		var res = pairs.map(function(pair) {
			var parts = pair.split(Constants.StatusSeparator);
			if (parts.length == 2) 
				return new SM.SavedSchoolInfo(parseInt(parts[0]), parts[1] == "1");
			return null;
		}, this);      
		
		res = res.filter(function(item) { return item != null; });
		
		this.selectedSchools = res;
	}
	
	this.CheckedSearchedSchools = Url.getParameter(url, P_CHECKED_SEARCHED_SCHOOLS);
	
	var startSelection = Url.getParameter(url, P_START_SCHOOL_SELECTION);
	if (!startSelection || String.isEmpty(startSelection))
		this.StartSelection = false;
	else 
		this.StartSelection = startSelection == "true" ? true : false;
	
	var saveState = Url.getParameter(url, P_SAVE_SELECTED_SCHOOLS_STATE);
	if (!saveState || String.isEmpty(saveState))
		this.SaveSelectedSchoolState = false;
	else 
		this.SaveSelectedSchoolState = saveState == "true" ? true : false;
}

function SM_QueryStringSavedSchoolsManager_SetCheckedSearchResultSchools(ids) {

	SM.QueryStringSavedSchoolsManager.callBase(this, "SetCheckedSearchResultSchools", [ids]);
	
	var res = [];
	for (var i = 0, ic = ids.length; i < ic; ++i)
		res.push("~0".format(ids[i]));
		
	this.CheckedSearchedSchools = res.join(Constants.IDSeparator);
}

function SM_QueryStringSavedSchoolsManager_GetCheckedSearchResultSchools() {
	SM.QueryStringSavedSchoolsManager.callBase(this, "GetCheckedSearchResultSchools", []);
		
	var value = this.CheckedSearchedSchools;
	var res = [];
	if (value && !String.isEmpty(value))
		res = value.split(Constants.IDSeparator);
	
	return res;
}

function SM_QueryStringSavedSchoolsManager_ResetSchoolsSelection() {
	SM.QueryStringSavedSchoolsManager.callBase(this, "ResetSchoolsSelection", []);
	
	this.CheckedSearchedSchools = "";
	SavedSchoolsManager.SetStartSelection(false);
}

SM.QueryStringSavedSchoolsManager.register(SM.SavedSchoolsManager);

var SavedSchoolsManager = (Cookie.IsEnabled() == true) ? 
	new SM.CookieSavedSchoolsManager() : 
	new SM.QueryStringSavedSchoolsManager();

// ----------
// UrlParameter
function UrlParameter(name, value) {
	 this.name = name;
	 this.value = value;
}

UrlParameter.prototype = {
	toString : UrlParameter_toString,
	get_Value : UrlParameter_Value,
	get_Name : UrlParameter_Name
}

function UrlParameter_toString() {
	return Url.createParameter(this.name, this.value);
}

function UrlParameter_Value() {
	return this.value;
}

function UrlParameter_Name() {
	return this.name;
}

UrlParameter.register();

// URL helper functions
var Url = {
	getQueryParams : Url_getQueryParams,
	getPersistentParams: Url_getPersistentParams,
	symbolsToEncode : [
		["$", "$dl;"],
		["=", "$eq;"],
		["/", "$sl;"],
		["?", "$qt;"],
		["%", "$pc;"],
		["*", "$st;"],
		[":", "$cl;"],
		["<", "$lt;"],
		[">", "$gt;"],
		[" ", "$sp;"],
		["\t", "$tb;"],
		["\\", "$bsl;"],
		[".", "$dot;"],
		["#", "$anc;"],
		["\"", "$quot;"],
		["`", "$bps;"],
		["|", "$vl;"],
		["^", "$ua;"],
		["&", "$amp;"],
		["+", "%2b"]
	],
	dirUriComponentEncode : Url_dirUriComponentEncode,
	dirUriComponentDecode : Url_dirUriComponentDecode,
	navigate : Url_navigate,
	addParameters : Url_addParameters,
	addParameter : Url_addParameter,
	addInnerUrl: Url_addInnerUrl,
	addInnerUrlParameter: Url_addInnerUrlParameter,
	addUrlParameters : Url_addUrlParameters,
	setParameter : Url_setParameter,	
	removeParameter : Url_removeParameter,
	createParameter : Url_createParameter,
	getParameters : Url_getParameters,
	getParameter : Url_getParameter,
	isQueryParameter: Url_isQueryParameter,
	parseParameters: Url_parseParameters,
	getPath: Url_getPath
}

function Url_getQueryParams() {
	if (!Url.queryParams) {
		Url.queryParams = Array.getHash(QueryParams);
	}
	return Url.queryParams;
}

function Url_getPersistentParams() {
	if (!Url.persistentParams) {
		Url.persistentParams = Array.getHash(PersistentParams);
	}
	return Url.persistentParams;
}

function Url_isQueryParameter(parameterText) {
	var queryParams = Url.getQueryParams();
	if (queryParams) {
		var name = parameterText.split(UrlContext.NameValueDelimiter)[0];
		return !!queryParams[name];
	}
	return false;
}

function Url_dirUriComponentEncode(s) {
	var res = s+'';
	for (var i =0; i < Url.symbolsToEncode.length; i++)
		res = res.replace(new RegExp("\\" +Url.symbolsToEncode[i][0],"gi"), Url.symbolsToEncode[i][1]);
	return res;
}

function Url_dirUriComponentDecode(s) {
	var res = s+'';
	for (var i = Url.symbolsToEncode.length -1; i >= 0; i--)
		res = res.replace(new RegExp("\\" +Url.symbolsToEncode[i][1],"gi"), Url.symbolsToEncode[i][0]);
	return res;
}

function Url_navigate(url, frame) {

	url = SavedSchoolsManager.AddToUrl(url);

	frame = frame || window;
	frame.location.href = url;
}

function Url_addUrlParameters(url, params) {	
	var aParams = [];

	for(name in params) {
		if (params.hasOwnProperty(name)) {
			aParams.push(params[name].toString());
		}
	}
	return Url.addParameters(url, aParams);
}

function Url_addParameters(url, params){
	if (String.isEmpty(url) || !params) return url;
	
	// separate query string parameters
	var p = [], queryParams = [];
	for(var i = 0, ic=params.length; i < ic; ++i) {
		var param = params[i];
		if (!String.isEmpty(param)) {
			var target = Url.isQueryParameter(param) ? queryParams : p;
			target.push(params[i]);
		}
	}			
	// form parameter strings
	var paramsString = p.join(UrlContext.ParameterDelimiter);
	var queryParamsString = queryParams.join("&");
	
	// parse original URL
	var urlParts = url.split("?");
	var dirPart = urlParts[0];
	
	// combine query string
	var query = "";
	if (urlParts.length > 1) {
		query = String.isEmpty(queryParamsString) ? urlParts[1] 
						: [urlParts[1], queryParamsString].join("&");
	}
	else {
		query = queryParamsString;
	}
		
	var delimiter = "";

	if (!String.isEmpty(paramsString)) {
		delimiter = dirPart.indexOf(UrlContext.QueryStringDelimiter) == -1 ?
				UrlContext.QueryStringDelimiter : UrlContext.ParameterDelimiter;
	}
	
	var queryStringDelimiter = String.isEmpty(query) ? "" : "?";
	
	var result = [dirPart, delimiter, paramsString, queryStringDelimiter, query].join("");

	return result;
}

function Url_addParameter(url, name, value){
	return Url.addParameters(url, [Url.createParameter(name, value)]);
}

// add another URL as a separate parameters to query string
function Url_addInnerUrl(urlDst, urlSrc) {
	// only one inner URL parameter is allowed so far
	var pid = Url.getParameter(urlDst, P_URL_PAGE_ID);
	if ($notExistOrNull(pid)) {
		 var params = Url.getParameters(urlSrc);
		 // page identifier should be specified explicitly for the inner URL
		 var pidParam = params[P_PAGE_ID];
		 if ($exist(pidParam)) {
			// add page identifier parameter
			urlDst = Url.addParameter(urlDst, P_URL_PAGE_ID, pidParam.get_Value());
			delete(params[P_PAGE_ID]);
			
			for (var param in params) {
				 if (params.hasOwnProperty(param) && !Url.getPersistentParams()[param]) {
					urlDst = Url.addInnerUrlParameter(urlDst, params[param]);
				 }
			}						
		 }
	}
	return urlDst;
}

function Url_addInnerUrlParameter(url, urlParam) {
	if (url && urlParam) {
 		var prefix = UrlContext.UrlParameterPrefix;		
		var name =  prefix + urlParam.get_Name();
		var value = urlParam.get_Value();
		
		if (Url.getParameter(url, name) === null) {
			url = Url.addParameter(url, name, value);
		}
		else {
			url = Url.setParameter(url, name, value);
		}
	}
	return url;
}

function Url_setParameter(url, name, value){		
	if (String.isEmpty(url) || !name || (value == null)) return url;
	url = this.removeParameter(url, name);
	return Url.addParameter(url, name, value);
}

function Url_getPath(url) {
	var urlParts = url.split("?");
	var dirParts = urlParts[0].split(UrlContext.QueryStringDelimiter);
	return dirParts[0];
}

function Url_removeParameter(url, name) {
	var params = Url.getParameters(url);
	delete(params[name]);
	var path = Url.getPath(url);	
	return Url.addUrlParameters(path, params);
}

function Url_createParameter(name, value) {
	var result = "";
	if (!String.isEmpty(name)) {
		if (Url.isQueryParameter(name)) {
			result = [encodeURIComponent(name), UrlContext.NameValueDelimiter, encodeURIComponent(value)].join('');
		}
		else {
			result = [Url.dirUriComponentEncode(name), UrlContext.NameValueDelimiter, Url.dirUriComponentEncode(value)].join('');
		}
	}
	return result;
}

function Url_getParameters(url) {
	var params = {};
	if (!String.isEmpty(url)) {
		// parse original URL
		var urlParts = url.split("?");
		var dirParts = urlParts[0].split(UrlContext.QueryStringDelimiter);
		
		var params = {};	
		
		if (dirParts.length > 1) {
			Url.parseParameters(params, dirParts[1], UrlContext.ParameterDelimiter, Url.dirUriComponentDecode);
		}	
		if (urlParts.length > 1) {
			Url.parseParameters(params, urlParts[1], "&", decodeURIComponent);
		}
	}
	return params;
}

function Url_parseParameters(collection, text, delimiter, decodeMethod) {
	var pairs = text.split(delimiter);
	for (var i=0, length = pairs.length; i<length; i++) {
		 var pair = pairs[i].split(UrlContext.NameValueDelimiter);
		 if (pair.length != 2) continue;
		 var name = decodeMethod(pair[0]);
		 var value = decodeMethod(pair[1]);		 
		 collection[name] = new UrlParameter(name, value);
	}	
}

function Url_getParameter(url, name) {
	var result = null;
	var params = Url.getParameters(url);
	var parameter = params[name];
	if ($exist(parameter)) {
		result =  parameter.get_Value();
	}
	return result;
}

// -----------------------------------------
function isEmailValid(email, showError) {
	if (!$exist(email) || String.isEmpty(email)) {
		if (showError) {
			alert("E-mail address is empty!");
		}
		return false;
	}
	if (email.match(/(^[a-zA-Z0-9]+[a-zA-Z0-9._-]*@([a-zA-Z0-9-]+)(\.[a-zA-Z0-9-]+)+$)/) == null)	{
		if (showError)	{
			alert("\""+email+"\" is not a valid e-mail address!");
		}
		return false;
	}
	return true;
}
// SearchTerms
function SearchTerms(terms) {
	if (terms) {
		this.text = terms.searchTerm || "";
		this.stateCode = terms.stateCode || "";
		this.searchRadius = terms.searchRadius || 0;
		this.zipCode = terms.zipCode || 0;
		this.sortOrder = $exist(terms.sortOrder) ? terms.sortOrder : null; 	
		this.sortCriteria = $exist(terms.sortCriteria) ? terms.sortCriteria : null; 	
		this.pageNumber = $exist(terms.pageNumber) ? terms.pageNumber : 1;
		this.narrowBy = terms.narrowBy || "";
		this.contextID = terms.contextID || "";
		this.alternateLongitude = $exist(terms.alternateLongitude) ? terms.alternateLongitude : null;   
		this.alternateLatitude = $exist(terms.alternateLatitude) ? terms.alternateLatitude : null;
		this.alternateDistance = $exist(terms.alternateDistance) ? terms.alternateDistance : null;
		this.alternateCity =  terms.alternateCity || "";
		this.alternateCityState = terms.alternateCityState || "";
		this.alternateDistrict = terms.alternateDistrict || "";
		this.alternateDistrictState = terms.alternateDistrictState || "";
		this.alternateDistanceState = terms.alternateDistanceState || "";
		this.alternateCityPageNumber = $exist(terms.alternateCityPageNumber) ? terms.alternateCityPageNumber : null;
		this.alternateDistrictPageNumber = $exist(terms.alternateDistrictPageNumber) ? terms.alternateDistrictPageNumber : null;
		this.nearbyOfSchoolID = terms.nearbyOfSchoolID || "";
	}
}

SearchTerms.prototype = {
	serialize : SearchTerms_serialize 
}

function SearchTerms_serialize() {			
	var params = [];
	// create parameters
	params.push(!String.isEmpty(this.text) ? Url.createParameter(P_SEARCH_TERM, this.text) : "");
	params.push(!String.isEmpty(this.stateCode) ? Url.createParameter(P_US_STATE, this.stateCode) : "");
	params.push(!this.searchRadius ? "" : Url.createParameter(P_SEARCH_RADIUS, this.searchRadius));
	params.push(!this.zipCode ? "" : Url.createParameter(P_ZIP_CODE, this.zipCode));
		
	params.push($notExistOrNull(this.sortOrder) ? "" : Url.createParameter(P_SORT_ORDER, this.sortOrder));
	params.push($notExistOrNull(this.sortCriteria) ? "" : Url.createParameter(P_SORT_CRITERIA, this.sortCriteria));
		
	params.push(!String.isEmpty(this.contextID) ? Url.createParameter(P_CONTEXT_ID, this.contextID) : "");

	if ($exist(this.pageNumber)) {
		params.push(Url.createParameter(P_PAGE_NUMBER, this.pageNumber));
		params.push(Url.createParameter(P_FIRST_PAGE, Paging.FirstPage));
	}				
	// filter out empty parameters values
	params = params.filter(function(item) { return item !=""; });
		
	params.push(!String.isEmpty(this.narrowBy) ? Url.createParameter(P_FILTER_NARROW_BY, this.narrowBy) : "");
		
	params.push(!this.alternateLatitude ? "" : Url.createParameter(P_ALTERNATE_LATITUDE, this.alternateLatitude));
	params.push(!this.alternateLongitude ? "" : Url.createParameter(P_ALTERNATE_LONGITUDE, this.alternateLongitude));
	params.push(!this.alternateDistance ? "" : Url.createParameter(P_ALTERNATE_DISTANCE, this.alternateDistance));
		
	params.push(!String.isEmpty(this.alternateCity) ? Url.createParameter(P_ALTERNATE_CITY, this.alternateCity) : "");
	params.push(!String.isEmpty(this.alternateCityState) ? Url.createParameter(P_ALTERNATE_CITY_STATE, this.alternateCityState) : "");
		
	params.push(!String.isEmpty(this.alternateDistrict) ? Url.createParameter(P_ALTERNATE_DISTRICT, this.alternateDistrict) : "");
	params.push(!String.isEmpty(this.alternateDistrictState) ? Url.createParameter(P_ALTERNATE_DISTRICT_STATE, this.alternateDistrictState) : "");
	params.push(!String.isEmpty(this.alternateDistanceState) ? Url.createParameter(P_ALTERNATE_DISTANCE_STATE, this.alternateDistanceState) : "");
		
	params.push($notExistOrNull(this.alternateCityPageNumber) ? "" : Url.createParameter(P_ALTERNATE_CITY_PAGE_NUMBER, this.alternateCityPageNumber));
	params.push($notExistOrNull(this.alternateDistrictPageNumber) ? "" : Url.createParameter(P_ALTERNATE_DISTRICT_PAGE_NUMBER, this.alternateDistrictPageNumber));
		
	params.push(!String.isEmpty(this.nearbyOfSchoolID) ? Url.createParameter(P_NEARBY_OF_SCHOOL_ID, this.nearbyOfSchoolID) : "");

	return params;
}
// ----------
// Outline
var Outline = function(control) {
	this.__control = $notExistOrNull(control) ? null : control;
}

Outline.ClearOutlines = function(outlines) {
	if (outlines) {
		for (var i = 0, ic = outlines.length; i < ic; ++i) {
			if (outlines[i])
				outlines[i].Hide();
		}
	}
}

Outline.prototype = {
	SetOutlining : Outline_SetOutlining,
	Show : Outline_Show,
	Hide : Outline_Hide
}

function Outline_SetOutlining(visibility) {
	var visible = $notExistOrNull(visibility) ? false : visibility;
	if (visible == true) 
		this.Show();
	else
		this.Hide();
}

function Outline_Show() {
	DomElement.addCssClass(DomElement.getParent(this.__control.Control), "errorOutline");	
}

function Outline_Hide() {
	DomElement.removeCssClass(DomElement.getParent(this.__control.Control), "errorOutline");	
}
// ----------
// Message
var Message = function(message, messageControl) {
	this.__message = $notExistOrNull(message) ? null : message;
	this.__messageControl = $notExistOrNull(messageControl) ? null : messageControl;
}

Message.ClearMessages = function(messages) {
	if (messages) {
		for (var i = 0, ic = messages.length; i < ic; ++i) {
			if (messages[i]) 
				messages[i].Hide();
		}	
	}
}

Message.prototype = {
	Show : Message_Show,
	Hide : Message_Hide,
	SetVisible : Message_SetVisible
}

function Message_Show() {
	if (this.__messageControl != null) {
		if (this.__message != null)
			this.__messageControl.innerText = this.__message;
		DomElement.removeCssClass(this.__messageControl, "hide");
		$fireEvent(this.__messageControl, "resize");

	} else {
		if (this.__message != null)
			alert(this.__message);
	}
}

function Message_Hide() {
	if (this.__messageControl != null) {
		DomElement.addCssClass(this.__messageControl, "hide");
		$fireEvent(this.__messageControl, "resize");
	}
}

function Message_SetVisible(visibility) {
	var visible = $notExistOrNull(visibility) ? false : visibility;
			
	if (visible == true) 
		this.Show();
	else
		this.Hide();
}
// ----------
// Validity
var Validity = { 
	NoValidate: 0, 
	Valid: 1, 
	Invalid: 2 
}
// ----------
// Validation
var Validation = function(validity) {
	this.__validity = $notExistOrNull(validity) ? Validity.NoValidate : validity;
	this.__breakOnInvalid = true;
	
	this.__messages = [];
	this.__outlines = [];
	this.__activeControl = null;
}

Validation.prototype = {
	SetValidity : Validation_SetValidity,
	GetValidity : Validation_GetValidity,
	ShowValidityMessage : Validation_ShowValidityMessage,
	Outline : Validation_Outline,
	SetFocus : Validation_SetFocus,
	BreakOnInvalid : Validation_BreakOnInvalid,
	AddMessage : Validation_AddMessage,
	AddOutline : Validation_AddOutline,
	GetMessages : Validation_GetMessages,
	GetOutlines : Validation_GetOutlines,
	SetActiveControl : Validation_SetActiveControl,
	GetActiveControl : Validation_GetActiveControl
}

function Validation_SetValidity(validity) {
	if (this.__validity != Validity.Invalid) 
		this.__validity = validity;
}

function Validation_GetValidity() { 
	return this.__validity; 
}

function Validation_ShowValidityMessage() {
	for (var i = 0, ic = this.__messages.length; i < ic; ++i) {
		this.__messages[i].SetVisible(this.__validity == Validity.Invalid);
	}
}

function Validation_Outline() {
	for (var i = 0, ic = this.__outlines.length; i < ic; ++i) {
		this.__outlines[i].SetOutlining(this.__validity == Validity.Invalid);
	}
}

function Validation_SetFocus() {
	if (this.__activeControl && this.__activeControl.disabled == false) {
		try { this.__activeControl.focus(); } catch(e) {} 
	}
}

function Validation_BreakOnInvalid() { 
	return this.__breakOnInvalid; 
}

function Validation_AddMessage(message) { 
	this.__messages.push(message); 
}

function Validation_AddOutline(outline) { 
	this.__outlines.push(outline); 
}

function Validation_GetMessages() { 
	return this.__messages; 
}

function Validation_GetOutlines() { 
	return this.__outlines; 
}

function Validation_SetActiveControl(control) { 
	this.__activeControl = control; 
}

function Validation_GetActiveControl() { 
	return this.__activeControl; 
}

Validation.register();
// ----------
// Search
var Search = function() {
	this.messages = null;
	this.outlines = null;
}

Search.ZipCode = { 
	Type : "ZipCode",
	Message : {
		IsEmpty: "IsEmpty",
		ContainsAlpha: "ContainsAlpha",
		IsFewerThan5: "IsFewerThan5",
		IsInvalidZip: "IsInvalidZip",
		IsFewerThan5AndContainsAlpha: "IsFewerThan5AndContainsAlpha"
	}
}
	
Search.SearchRadius = { 
	Type: "Miles" 
}
		
Search.SearchTerm = { 
	Type: "Input", 
	Message : {
		IsInvalidZip: "IsInvalidZip"
	}
}
		
Search.StateCode = {
	Type: "State",
	Message : {
		StateNotSelected: "StateNotSelected"
	}	
}

Search.prototype = {
	GetIFrame : Search_GetIFrame,
	GetControls : Search_GetControls,
	GetControl : Search_GetControl,
	GetControlElement : Search_GetControlElement,
	GetControlValue : Search_GetControlValue,
	GetMessages : Search_GetMessages,
	GetMessage : Search_GetMessage, 
	GetMessageText : Search_GetMessageText,
	GetMessageControl : Search_GetMessageControl,
	ZipCodeValidate : Search_ZipCodeValidate,
	TermValidate : Search_TermValidate,
	Validate : Search_Validate,
	DefaultExecute : Search_DefaultExecute,
	ZipCodeExecute : Search_ZipCodeExecute,
	TermExecute : Search_TermExecute,
	Execute : Search_Execute,
	Outline : Search_Outline,
	GetResponseData : Search_GetResponseData,
	OnFrameLoad : Search_OnFrameLoad,
	getSearchTerms : Search_getSearchTerms,
	SearchBySuggestion : Search_SearchBySuggestion,
	CheckKey : Search_CheckKey,
	SetActiveControl : Search_SetActiveControl,
	SetFocus : Search_SetFocus
}

function Search_SetActiveControl(control) {
	this.activeControl = control;
}
		
function Search_SetFocus() {
	if (this.activeControl)
		this.activeControl.focus();
}

function Search_GetIFrame(params) {
	return (!$notExistOrNull(params) && !$notExistOrNull(params.Controls) && !$notExistOrNull(params.Controls.IFrame)) ? params.Controls.IFrame : null;
}

function Search_GetControls(params) {
	return (!$notExistOrNull(params) && !$notExistOrNull(params.Controls)) ? params.Controls : null;
}

function Search_GetControl(params, type) {
	var controls = this.GetControls(params);
	if (!$notExistOrNull(controls) && !$notExistOrNull(type) && !String.isEmpty(type)) {
		return $exist(controls[type]) ? controls[type] : null;
	}
	return null;
}

function Search_GetControlElement(params, type) {
	var control = this.GetControl(params, type);
	return (control != null && $exist(control.Control)) ? control.Control : null;
}

function Search_GetControlValue(params, type, property/*="value"*/, trim/*=true*/) {
	var control = this.GetControlElement(params, type);
	if (control) {
		var prop = $notExistOrNull(property) ? "value" : property;
		var doTrim = $notExistOrNull(trim) ? true : trim;
		return $exist(control[prop]) ? (control[prop]+'').trim() : null;
	}
	return null;
}

function Search_GetMessages(params, type) {
	var control = this.GetControl(params, type);
	return (control != null && $exist(control.Messages)) ? control.Messages : null;
}

function Search_GetMessage(params, type, messageType) {
	var messages = this.GetMessages(params, type);
	return (messages != null && $exist(messages[messageType])) ? messages[messageType] : null;
}

function Search_GetMessageText(params, type, messageType) {
	var message = this.GetMessage(params, type, messageType);
	return (message != null && $exist(message.Text)) ? message.Text : null;
}

function Search_GetMessageControl(params, type, messageType) {
	var message = this.GetMessage(params, type, messageType);
	return (message != null && $exist(message.Control)) ? message.Control : null;
}

function Search_ZipCodeValidate(params) {
	var validation = new Validation(Validity.Valid);
			
	// check zip code
	var zipCode = this.GetControlValue(params, Search.ZipCode.Type);
	if (zipCode == null || String.isEmpty(zipCode)) {
		validation.SetValidity(Validity.Invalid);
				
		var msgText = this.GetMessageText(params, Search.ZipCode.Type, Search.ZipCode.Message.IsEmpty);
		var msgControl = this.GetMessageControl(params, Search.ZipCode.Type, Search.ZipCode.Message.IsEmpty);
				
		validation.AddMessage(new Message(msgText, msgControl));
		validation.AddOutline(new Outline(this.GetControl(params, Search.ZipCode.Type)));
		
		validation.SetActiveControl(this.GetControlElement(params, Search.ZipCode.Type));
	}
	else {
		var zipCodeLength = zipCode.length;
		if (zipCodeLength < 5) {
			validation.SetValidity(Validity.Invalid);
					
			var msgText = this.GetMessageText(params, Search.ZipCode.Type, Search.ZipCode.Message.IsFewerThan5);
			var msgControl = this.GetMessageControl(params, Search.ZipCode.Type, Search.ZipCode.Message.IsEmpty);
				
			validation.AddMessage(new Message(msgText, msgControl));
			validation.AddOutline(new Outline(this.GetControl(params, Search.ZipCode.Type)));
			
			validation.SetActiveControl(this.GetControlElement(params, Search.ZipCode.Type));
		}
		
		var zc = zipCode.substr(0, 5);
		var m = zc.match(/^\d+$/);
		if (m == null) {
			validation.SetValidity(Validity.Invalid);
			
			var msgText;
			var msgControl;
			
			if (zipCodeLength >= 5) {
				var msgText = this.GetMessageText(params, Search.ZipCode.Type, Search.ZipCode.Message.ContainsAlpha);
				var msgControl = this.GetMessageControl(params, Search.ZipCode.Type, Search.ZipCode.Message.ContainsAlpha);
			}
			else {
				var msgText = this.GetMessageText(params, Search.ZipCode.Type, Search.ZipCode.Message.IsFewerThan5AndContainsAlpha);
				var msgControl = this.GetMessageControl(params, Search.ZipCode.Type, Search.ZipCode.Message.IsFewerThan5AndContainsAlpha);
			}
			
			validation.AddMessage(new Message(msgText, msgControl));
			validation.AddOutline(new Outline(this.GetControl(params, Search.ZipCode.Type)));
			
			validation.SetActiveControl(this.GetControlElement(params, Search.ZipCode.Type));
		} else {
			if (zipCodeLength >= 5) {
				m = zipCode.match(/^\d{5}\s*-\s*\d*|\d{5}$/);
				if (m == null) {
					validation.SetValidity(Validity.Invalid);
						
					var msgText = this.GetMessageText(params, Search.ZipCode.Type, Search.ZipCode.Message.IsInvalidZip);
					var msgControl = this.GetMessageControl(params, Search.ZipCode.Type, Search.ZipCode.Message.IsInvalidZip);
					
					validation.AddMessage(new Message(msgText, msgControl));
					validation.AddOutline(new Outline(this.GetControl(params, Search.ZipCode.Type)));
					validation.SetActiveControl(this.GetControlElement(params, Search.ZipCode.Type));
				}
			}
		}
	}
	return validation;
}

function Search_TermValidate(params) {
	var validation = new Validation(Validity.Valid);
			
	var inputText = this.GetControlValue(params, Search.SearchTerm.Type);
	if (inputText != null && String.isEmpty(inputText)) {
		var stateCode = this.GetControlValue(params, Search.StateCode.Type);
		if (stateCode != null && (String.isEmpty(stateCode) || stateCode == "Select" )) {
				
			validation.SetValidity(Validity.Invalid);
				
			var msgText = this.GetMessageText(params, Search.StateCode.Type, Search.StateCode.Message.StateNotSelected);
			var msgControl = this.GetMessageControl(params, Search.StateCode.Type, Search.StateCode.Message.StateNotSelected);
				
			validation.AddMessage(new Message(msgText, msgControl));
			validation.AddOutline(new Outline(this.GetControl(params, Search.StateCode.Type)));
			
			validation.SetActiveControl(this.GetControlElement(params, Search.StateCode.Type));
		}				
	}
	return validation;
}

function Search_Validate(params) {
	if (!$notExistOrNull(params) && 
		!$notExistOrNull(params.SearchControlType)) {
				
		switch(params.SearchControlType) {
			case SearchControlType.ZipCode: return this.ZipCodeValidate(params);
			case SearchControlType.Term: return this.TermValidate(params);
		}
	}
			
	return new Validation();
}

function Search_DefaultExecute(searchParams, resetSelection) {
	resetSelection = $ensure(resetSelection, true);
	var url = U_SR; 
	var searchTerms = this.getSearchTerms(searchParams);		 		
	var params = searchTerms.serialize();
	url = Url.addParameters(url, params);
	
	if (resetSelection)
		SavedSchoolsManager.ResetSchoolsSelection();
		
	Url.navigate(url);
}

function Search_ZipCodeExecute(searchParams, resetSelection) {
	
	var searchTerms = this.getSearchTerms(searchParams);		 		
	var params = searchTerms.serialize();
			
	if (WebFrameworkConfig && WebFrameworkConfig.RequestHandler) {
		var url = WebFrameworkConfig.RequestHandler;
		url = Url.addParameters(url, params);
		url = Url.addParameter(url, P_COMMAND, Command.IsZipCodeValid);
		var iframe = this.GetIFrame(searchParams);
		if (!this.handlerAttached) {
			$attachEvent(iframe, 'load', this.OnFrameLoad.bind(iframe, searchParams, this, Command.IsZipCodeValid, resetSelection));
			this.handlerAttached = true;
		}
		iframe.src = url;
	}
}

function Search_TermExecute(searchParams, resetSelection) {
	var stateCode = this.GetControlValue(searchParams, Search.StateCode.Type);
	var isStateDef = (stateCode != null && !String.isEmpty(stateCode) && stateCode != "Select");
			
	if (this.GetIFrame(searchParams) == null || isStateDef)
		this.DefaultExecute(searchParams);
	else {
		var searchTerms = this.getSearchTerms(searchParams);		 		
		var params = searchTerms.serialize();
				
		if (WebFrameworkConfig && WebFrameworkConfig.RequestHandler) {
			var url = WebFrameworkConfig.RequestHandler;
			url = Url.addParameters(url, params);
			url = Url.addParameter(url, P_COMMAND, Command.IsSearchStateDefined);
			var iframe = this.GetIFrame(searchParams);
			if (!this.handlerAttached) {
				$attachEvent(iframe, 'load', this.OnFrameLoad.bind(iframe, searchParams, this, Command.IsSearchStateDefined, resetSelection));
				this.handlerAttached = true;
			}

			iframe.src = url;
		}
	}
}

function Search_Execute(searchParams, resetSelection) {
	resetSelection = $ensure(resetSelection, true);
		
	if ($notExistOrNull(searchParams) || 
		$notExistOrNull(searchParams.SearchControlType)) {
		this.DefaultExecute(searchParams, resetSelection);
		return;
	}
		
	var validation = this.Validate(searchParams);
			
	if (this.messages)
		this.messages.forEach(function(message, index, array) { message.Hide(); }, this);
	if (this.outlines)
		this.outlines.forEach(function(outline, index, array) {	outline.Hide();	}, this);
			
	validation.ShowValidityMessage();
	validation.Outline();
	validation.SetFocus();
			
	this.messages = validation.GetMessages();
	this.outlines = validation.GetOutlines();
			
	if (validation.GetValidity() == Validity.Invalid) {
		if (validation.BreakOnInvalid())
			return;
	} 
			
	switch(searchParams.SearchControlType) {
		case SearchControlType.ZipCode: this.ZipCodeExecute(searchParams, resetSelection); break
		case SearchControlType.Term: this.TermExecute(searchParams, resetSelection); break;
		default: this.DefaultExecute(searchParams, resetSelection); break;
	}
}

function Search_Outline(searchParams, type, messageType, visibility) {
	var outline = new Outline(this.GetControl(searchParams, type));
	outline.SetOutlining(visibility);
			
	if (visibility)
		this.outlines[this.outlines.length] = outline;
			
	var msgText = this.GetMessageText(searchParams, type, messageType);
	var msgControl = this.GetMessageControl(searchParams, type, messageType);
			
	var message = new Message(msgText, msgControl);
			
	message.SetVisible(visibility);
			
	if (visibility)
		this.messages[this.messages.length] = message;
}

function Search_GetResponseData(iframe) {
	var responseDataObjectName = Constants.ClientResponseDataObjectName;
			
	return (iframe && iframe.contentWindow && iframe.contentWindow[responseDataObjectName]) ? 
		iframe.contentWindow[responseDataObjectName] : null;
}

function Search_OnFrameLoad(searchParams, searchObj, command, resetSelection) {
	resetSelection = $ensure(resetSelection, true);

	searchObj.SetActiveControl(null);
	
	if (Command.IsSearchStateDefined == command) {
		var iframe = searchObj.GetIFrame(searchParams);
				
		var res = searchObj.GetResponseData(iframe);
				
		if (res == null) {
			searchObj.Outline(searchParams, Search.StateCode.Type, Search.StateCode.Message.StateNotSelected, false);
			searchObj.Outline(searchParams, Search.SearchTerm.Type, Search.StateCode.Message.IsInvalidZip, false);
			return;
		}
				
		var sign = new Number(res.Sign);
				
		if (res.ValidZipCode == false) {
			searchObj.Outline(searchParams, Search.SearchTerm.Type, Search.SearchTerm.Message.IsInvalidZip, true);
			searchObj.SetActiveControl(searchObj.GetControlElement(searchParams, Search.SearchTerm.Type));
		}
		else if (sign == StateSign.Selected || sign == StateSign.Undefined) {
				
			searchObj.Outline(searchParams, Search.StateCode.Type, Search.StateCode.Message.StateNotSelected, false);
			searchObj.Outline(searchParams, Search.SearchTerm.Type, Search.StateCode.Message.IsInvalidZip, false);
					
			var url = U_SR; 
					
			var searchTerms = searchObj.getSearchTerms(searchParams);		 		
			var params = searchTerms.serialize();	
					
			url = Url.addParameters(url, params);
			if (res.StateCode) 
				url = Url.setParameter(url, P_US_STATE, res.StateCode);
						
			if (res.SearchTerm)
				url = Url.setParameter(url, P_SEARCH_TERM, res.SearchTerm);
						
			url = Url.removeParameter(url, P_CONTEXT_ID);
			
			if (resetSelection)
				SavedSchoolsManager.ResetSchoolsSelection();
						
			Url.navigate(url);	
		} 
		else if (sign == StateSign.Unselected) { 
			searchObj.Outline(searchParams, Search.SearchTerm.Type, Search.SearchTerm.Message.IsInvalidZip, false);
			searchObj.Outline(searchParams, Search.StateCode.Type, Search.StateCode.Message.StateNotSelected, true);
			
			searchObj.SetActiveControl(searchObj.GetControlElement(searchParams, Search.StateCode.Type));
		}
		else {
			searchObj.Outline(searchParams, Search.StateCode.Type, Search.StateCode.Message.StateNotSelected, false);
			searchObj.Outline(searchParams, Search.SearchTerm.Type, Search.SearchTerm.Message.IsInvalidZip, false);
		}
	} else if (Command.IsZipCodeValid == command) {
			
		var iframe = searchObj.GetIFrame(searchParams);
		var res = searchObj.GetResponseData(iframe);
				
		if (res == null) {
			searchObj.Outline(searchParams, Search.ZipCode.Type, Search.ZipCode.Message.IsEmpty, false);
			searchObj.Outline(searchParams, Search.ZipCode.Type, Search.ZipCode.Message.ContainsAlpha, false);
			searchObj.Outline(searchParams, Search.ZipCode.Type, Search.ZipCode.Message.IsFiewerThan5, false);
			return;
		}
				
		if (res.Valid == true) {
			var url = U_SR; 
					
			var searchTerms = searchObj.getSearchTerms(searchParams);		 		
			var params = searchTerms.serialize();	
					
			url = Url.addParameters(url, params);
			url = Url.removeParameter(url, P_CONTEXT_ID);
			
			if (resetSelection)
				SavedSchoolsManager.ResetSchoolsSelection();
						
			Url.navigate(url);	
		}
		else {
			searchObj.Outline(searchParams, Search.ZipCode.Type, Search.ZipCode.Message.IsInvalidZip, true);
			searchObj.SetActiveControl(searchObj.GetControlElement(searchParams, Search.ZipCode.Type));
		}
	}
	
	searchObj.SetFocus();
}

function Search_getSearchTerms(searchParams) {
	if (searchParams) {
		var zipCode = this.GetControlValue(searchParams, Search.ZipCode.Type);
		if (zipCode && zipCode.length > 5)
			zipCode = zipCode.substring(0, 5);
					
		var args = { 
			"searchTerm": this.GetControlValue(searchParams, Search.SearchTerm.Type), 
			"stateCode": this.GetControlValue(searchParams, Search.StateCode.Type),
			"searchRadius": this.GetControlValue(searchParams, Search.SearchRadius.Type),
			"zipCode": zipCode
		}			
		var searchTerms = new SearchTerms(args);
	}
	else {
		searchTerms = SearchTerms.Instance || new SearchTerms();		
	}
	return searchTerms;
}

function Search_SearchBySuggestion(term, params) {
	if (term && params && params.Controls) {
		var input = params.Controls.Input;
		input.value = term;
		this.Execute(params);
	}
}

function Search_CheckKey(e, args) {
	onEnterPressed(e, this.Execute.bind(this, args)); 
}
// ----------
// Paging
var Paging = {
	FirstPage : 1,
	PageCount : 1,
	Go : Paging_Go
}
function Paging_Go(pageNumber) {
	if (SearchTerms && SearchTerms.Instance) {
		SearchTerms.Instance.pageNumber = pageNumber;
	}
		
	var search = new Search();
	
	SavedSchoolsManager.ResetSchoolsSelection();
	
	search.Execute(null);
}	
// ----------
// Sorting
var Sorting = {
	IsViewAll: Sorting_IsViewAll,
	Sort: Sorting_Sort,
	toggleSortOrder : Sorting_toggleSortOrder
}
function Sorting_IsViewAll() {
	return (SearchTerms && SearchTerms.Instance && SearchTerms.Instance.pageNumber == -1);
}
function Sorting_Sort(sortCriteria, sortOrder) {
	// the same sortCriteria (repeated sort) - revert sort order
	if (SearchTerms && SearchTerms.Instance) {
		if ($exist(SearchTerms.Instance.sortCriteria)
			&& SearchTerms.Instance.sortCriteria == sortCriteria) {
			SearchTerms.Instance.sortOrder = this.toggleSortOrder(SearchTerms.Instance.sortOrder);
		}
		else {
			SearchTerms.Instance.sortOrder = sortOrder;
		}
		SearchTerms.Instance.sortCriteria = sortCriteria;
	}

	if (!this.IsViewAll()) {
		// Reset paging on sorting
		if (SearchTerms && SearchTerms.Instance)
			delete(SearchTerms.Instance.pageNumber);
	}
		
	var search = new Search();
	var resetSelection = (Paging.PageCount > 1);
	search.Execute(null, resetSelection);
}
function Sorting_toggleSortOrder(sortOrder) {
	return (sortOrder == SchoolSortOrder.Ascending) ?
		SchoolSortOrder.Descending : SchoolSortOrder.Ascending;
}	
//----------
// SM.CompareTerms
SM.CompareTerms = function(terms) {
	if (terms) {
		this.stateCode = terms.stateCode;
		this.IDs = terms.IDs;
		this.PageNumbers = terms.PageNumbers;
		this.SearchTerms = terms.SearchTerms;
		this.messages = [];
		this.outlines = [];
		this.activeControl = null;
	}
}

SM.CompareSearch = function() {
	this.messages = [];
	this.outlines = [];
	
	this.serverMessages = [];
	this.serverOutlines = [];
}

SM.CompareSearch.prototype = {
	
	GetTermControl : SM_CompareSearch_GetTermControl,
	GetTermControlsCount : SM_CompareSearch_GetTermControlsCount,
	IsTermsEmpty : SM_CompareSearch_IsTermsEmpty,
	GetStateControl : SM_CompareSearch_GetstateControl,
	IsStateSelected : SM_CompareSearch_IsStateSelected,
	Validate : SM_CompareSearch_Validate,
	GetSelectedSchoolsCount : SM_CompareSearch_GetSelectedSchoolsCount,
	Execute : SM_CompareSearch_Execute,
	SetRedirect : SM_CompareSearch_SetRedirect,
	IsLessThanMinSchoolsToCompareSelected : SM_CompareSearch_IsLessThanMinSchoolsToCompareSelected,
	GetFirstEmptyInput : SM_CompareSearch_GetFirstEmptyInput,
	AddOutline : SM_CompareSearch_AddOutline,
	AddMessage : SM_CompareSearch_AddMessage,
	AddServerMessage : SM_CompareSearch_AddServerMessage,
	AddServerOutline : SM_CompareSearch_AddServerOutline,
	GetMessages : SM_CompareSearch_GetMessages,
	GetOutlines : SM_CompareSearch_GetOutlines,
	ShowMessages : SM_CompareSearch_ShowMessages,
	ShowOutlines : SM_CompareSearch_ShowOutlines,
	ClearMessages : SM_CompareSearch_ClearMessages,
	ClearOutlines : SM_CompareSearch_ClearOutlines,
	ClearServerMessages : SM_CompareSearch_ClearServerMessages,
	ClearServerOutlines : SM_CompareSearch_ClearServerOutlines,
	ClearMessagesAndOutlines : SM_CompareSearch_ClearMessagesAndOutlines,
	ClearServerMessagesAndOutlines : SM_CompareSearch_ClearServerMessagesAndOutlines,
	ShowMessages : SM_CompareSearch_ShowMessages,
	ShowOutlines : SM_CompareSearch_ShowOutlines,
	ShowMessagesAndOutlines : SM_CompareSearch_ShowMessagesAndOutlines,
	SetActiveControl : SM_CompareSearch_SetActiveControl,
	SetFocus : SM_CompareSearch_SetFocus,
	IsDifferentStateSelected : SM_CompareSearch_IsDifferentStateSelected,
	GetSelectedState : SM_CompareSearch_GetSelectedState,
	OnFrameLoad : SM_CompareSearch_OnFrameLoad,
	CheckKey : SM_CompareSearch_CheckKey,
	getSearchParameters : SM_CompareSearch_getSearchParameters,
	AddSchool : SM_CompareSearch_AddSchool,
	GoToPage : SM_CompareSearch_GoToPage,
	getIDsParameter : SM_CompareSearch_getIDsParameter,
	getPagingParameter : SM_CompareSearch_getPagingParameter,
	StartOver : SM_CompareSearch_StartOver,
	OnChangeState : SM_CompareSearch_OnChangeState,
	GetIsStateChanged : SM_CompareSearch_GetIsStateChanged
}

function SM_CompareSearch_GetTermControl(index) {
	if (this.Controls) {
		var inputIDs = this.Controls.Terms;
		return (index < inputIDs.length) ? $get(inputIDs[index]) : null;
	}
	return null;
}
		
function SM_CompareSearch_GetTermControlsCount() {
	if (this.Controls) {
		var inputIDs = this.Controls.Terms;
		return inputIDs.length;
	}
	return 0;
}
		
function SM_CompareSearch_IsTermsEmpty() {
	
	for (var i = 0, ic = this.GetTermControlsCount(); i < ic; ++i) {
		var termControl = this.GetTermControl(i);
		if (termControl) {
			var value = (termControl.iswatermarked && termControl.value.trim() == "Optional") ? "" : termControl.value.trim();
			if (!String.isEmpty(value))
				return false;
		}
	}
	return true;
}
		
function SM_CompareSearch_GetstateControl() {
	return (this.Controls) ? $get(this.Controls.State) : null;
}
		
function SM_CompareSearch_IsStateSelected() {
	var stateControl = this.GetStateControl();
	if (stateControl) {
		var value = stateControl.value.trim();
		return (!String.isEmpty(value) && value != "Select");
	}
	return false;
}
	
function SM_CompareSearch_Validate() {
	var validation = new Validation(Validity.Valid);
			
	if (this.IsTermsEmpty() && !this.IsStateSelected()) {
		validation.SetValidity(Validity.Invalid);
				
		validation.AddMessage(new Message("Please select a state and at least 2 schools.", this.Controls.MessageControl));
				
		validation.AddOutline(new Outline( { "Control" : this.GetStateControl() } ));
		validation.AddOutline(new Outline( { "Control" : this.GetTermControl(0) } ));
		validation.AddOutline(new Outline( { "Control" : this.GetTermControl(1) } ));
			
		validation.SetActiveControl(this.GetTermControl(0));
		
		this.ClearServerMessagesAndOutlines();
	}
	else if (this.IsStateSelected() && this.IsTermsEmpty()) {
		validation.SetValidity(Validity.Invalid);
				
		validation.AddMessage(new Message("Please select at least 2 schools.", this.Controls.MessageControl));
				
		validation.AddOutline(new Outline( { "Control" : this.GetTermControl(0) } ));
		validation.AddOutline(new Outline( { "Control" : this.GetTermControl(1) } ));
				
		validation.SetActiveControl(this.GetTermControl(0));
		
		this.ClearServerMessagesAndOutlines();		
	}
			
	return validation;
}
		
function SM_CompareSearch_GetSelectedSchoolsCount() {
	var result = 0;
	var controls = this.Controls;
	if (controls) {
		var params = [];
		var inputIDs = controls.Terms;
					
		var val = null;
		// the cycle below collects search terms' parameters (or selected schools names)
		// and invalidates selected school ID if needed
		for (var i=0, length = inputIDs.length; i<length; i++) {
			// get current value in the input control and 
			var termInput = $get(inputIDs[i]);
			var value = (termInput.iswatermarked && termInput.value.trim() == "Optional") ? "" : termInput.value.trim();
			if (!String.isEmpty(value)) {
				result++
			}
		}
	}
	return result;
}
	
function SM_CompareSearch_Execute(controls, redirect, action, source) {
	
	SM.CompareSchoolList.Update();
		
	var source = $ensure(source, null);
	var action = $ensure(action, CompareSearchAction.None);
	var redirect = $ensure(redirect, true);
	
	if (action != CompareSearchAction.AddSchool &&
		action != CompareSearchAction.PageNavigate) {
		
		var validation = this.Validate();
		
		Message.ClearMessages(this.messages);
		Outline.ClearOutlines(this.outlines);
				
		validation.ShowValidityMessage();
		validation.Outline();
		validation.SetFocus();
				
		this.messages = validation.GetMessages();
		this.outlines = validation.GetOutlines();
				
		if (validation.GetValidity() == Validity.Invalid) {
			if (validation.BreakOnInvalid())
				return;
		}
	}
			
	var controls = this.Controls;
	if (controls) {
		var params = [];
		var inputIDs = controls.Terms;
					
		var val = null;
		// the cycle below collects search terms' parameters (or selected schools names)
		// and invalidates selected school ID if needed
		for (var i=0, length = inputIDs.length; i<length; i++) {
			// get current value in the input control
			var termInput = $get(inputIDs[i]);
			var value = (termInput.iswatermarked && termInput.value.trim() == "Optional") ? "" : termInput.value.trim();
			if (!String.isEmpty(value)) {
				val = value;
				break;
			}
		}
		
		if (String.isEmpty(val)) {
			var selectState = $get(controls.State);
			var stateCode = selectState.selectedIndex == 0 ? "" : selectState.value;
					
			if (String.isEmpty(stateCode) || stateCode == "Select") {
				DomElement.addCssClass(DomElement.getParent(selectState), "errorOutline");
						
				var messageControl = (controls.MessageControl) ? controls.MessageControl : null;
				if (messageControl) {
					DomElement.removeCssClass(messageControl, "hide");
				}
						
				return;
			}
		}
	}
			
	this.CurrentAction = action;
	this.CurrentSource = source;
			
	var iframe = this.Controls.IFrame;
	if (iframe) {
		var params = this.getSearchParameters();
				
		if (WebFrameworkConfig && WebFrameworkConfig.RequestHandler) {
			var frmUrl = WebFrameworkConfig.RequestHandler;
			frmUrl = Url.addParameters(frmUrl, params);
			frmUrl = Url.addParameter(frmUrl, P_COMMAND, Command.IsCompareStateDefined);
					
			this.SetRedirect(redirect);
			if (!this.handlerAttached) {
				$attachEvent(iframe, 'load', this.OnFrameLoad.bind(iframe, this));
				this.handlerAttached = true;
			}
			iframe.src = frmUrl;
		}
	}
}
		
function SM_CompareSearch_SetRedirect(redirect) {
	this.redirect = redirect;			
}
		
function SM_CompareSearch_IsLessThanMinSchoolsToCompareSelected(res) {
	if (res) {
		var searchTermsCount = 0;
		for (var i = 0, ic = res.SearchTerms.length; i < ic; ++i) {
			var searchTerm = (res.SearchTerms[i] != null) ? res.SearchTerms[i].trim() : null;
			if (!String.isEmpty(searchTerm))
				searchTermsCount++;
		}
	}
	return (searchTermsCount < SchoolMattersConfig.MinSchoolsToCompare);
}
		
function SM_CompareSearch_GetFirstEmptyInput(res) {
	if (res) {
		if (!res.SearchTerms) 
			return null;				
		for (var i = 0, ic = res.SearchTerms.length; i < ic; ++i) {
			var searchTerm = (res.SearchTerms[i] != null) ? res.SearchTerms[i].trim() : null;
			if (String.isEmpty(searchTerm)) {
				var controls = this.Controls;
				if (controls) {
					return $get(controls.Terms[i]);
				}
			}
		}
	}
	return null;
}
		
function SM_CompareSearch_AddOutline(outline) {
	if (outline != null)
		this.outlines.push(outline);
}

function SM_CompareSearch_AddServerOutline(outline) {
	if (outline != null)
		this.serverOutlines.push(outline);
}
		
function SM_CompareSearch_AddMessage(message) {
	if (message != null)
		this.messages.push(message);
}

function SM_CompareSearch_AddServerMessage(message) {
	if (message != null)
		this.serverMessages.push(message);
}

function SM_CompareSearch_GetMessages() {
	return this.messages;
}

function SM_CompareSearch_GetOutlines() {
	return this.outlines;
}
		
function SM_CompareSearch_ShowMessages() {
	if (this.messages) {
		for (var i = 0, ic = this.messages.length; i < ic; ++i) {
			if (this.messages[i])
				this.messages[i].Show();				
		}
	}
}
		
function SM_CompareSearch_ShowOutlines() {
	if (this.outlines) {
		for (var i = 0, ic = this.outlines.length; i < ic; ++i) {
			if (this.outlines[i])
				this.outlines[i].Show();
		}
	}
}
		
function SM_CompareSearch_ClearMessages() {
	Message.ClearMessages(this.messages);
	this.messages = [];
}
		
function SM_CompareSearch_ClearOutlines() {
	Outline.ClearOutlines(this.outlines);
	this.outlines = [];
}

function SM_CompareSearch_ClearServerMessages() {
	Message.ClearMessages(this.serverMessages);
	this.serverMessages = [];
}
		
function SM_CompareSearch_ClearServerOutlines() {
	Outline.ClearOutlines(this.serverOutlines);
	this.serverOutlines = [];
}
		
function SM_CompareSearch_ClearMessagesAndOutlines() {
	this.ClearMessages();
	this.ClearOutlines();
}

function SM_CompareSearch_ClearServerMessagesAndOutlines() {
	this.ClearServerMessages();
	this.ClearServerOutlines();
}
		
function SM_CompareSearch_ShowMessages() {
	if (this.messages) {
		for (var i = 0, ic = this.messages.length; i < ic; ++i) {
			if (this.messages[i]) 
				this.messages[i].Show();
		}
	}
}

function SM_CompareSearch_ShowOutlines() {
	if (this.outlines) {
		 for (var i = 0, ic = this.outlines.length; i < ic; ++i) {
			if (this.outlines[i])
				this.outlines[i].Show();
		 }
	}
}
		
function SM_CompareSearch_ShowMessagesAndOutlines() {
	this.ShowMessages();
	this.ShowOutlines();
}

function SM_CompareSearch_SetActiveControl(control) {
	this.activeControl = control;
}
		
function SM_CompareSearch_SetFocus() {
	if (this.activeControl)
		this.activeControl.focus();
}
		
function SM_CompareSearch_IsDifferentStateSelected(res) {
		
	var controls = this.Controls;
	if (!controls) return false;
	
	var stateControl = (controls.State) ? $get(controls.State) : null;
	if (!stateControl) return false;
			
	var stateControlValue = stateControl.value;
	if (!String.isEmpty(stateControlValue) && !(stateControlValue == "Select"))
		return false;
		
	for (var i = 0, ic = res.StateCodes.length; i < ic; ++i) {
		var sign = new Number(res.Signs[i]);
		if (sign == StateSign.Selected) {
				
			var stateCode = res.StateCodes[i];
					
			for (var j = i + 1, jc = res.StateCodes.length; j < jc; ++j) {
				var s = new Number(res.Signs[j]);
				if (s == StateSign.Selected) {
					if (res.StateCodes[j] != stateCode)
						return true;
				}
			}
		}
	}
			
	return false;
}
		
function SM_CompareSearch_GetSelectedState(res) {
	var controls = this.Controls;
	if (!controls) return false;
			
	var stateControl = (controls.State) ? $get(controls.State) : null;
	if (!stateControl) return false;
			
	var stateControlValue = stateControl.value;
	if (!String.isEmpty(stateControlValue) && !(stateControlValue == "Select"))
		return stateControlValue;
				
	if (this.IsDifferentStateSelected(res)) 
		return null;
				
	for (var i = 0, ic = res.StateCodes.length; i < ic; ++i) {
		var sign = new Number(res.Signs[i]);
		if (sign == StateSign.Selected) 
					return res.StateCodes[i];
	}
			
	return null;
}
		
function SM_CompareSearch_OnFrameLoad(searchObj) {
			
	if (!searchObj) return;
	
	var messages = searchObj.GetMessages();
	var outlines = searchObj.GetOutlines();
	
	searchObj.messages = [];
	searchObj.outlines = [];
			
	var controls = searchObj.Controls;
	if (!controls) return;
			
	var stateControl = (controls.State) ? $get(controls.State) : null;
	if (!stateControl) return;
			
	var messageControl = (controls.MessageControl) ? controls.MessageControl : null;
	if (!messageControl) return;
			
	var iframe = (controls.IFrame) ? controls.IFrame : null;
	var res = null;
	if (iframe) {
		res = iframe.contentWindow[Constants.ClientResponseDataObjectName];
	}
			
	if ($notExistOrNull(res)  || $notExistOrNull(res.SearchTerms)) {
		DomElement.removeCssClass(DomElement.getParent(stateControl), "errorOutline");
		DomElement.addCssClass(messageControl, "hide");
		return;
	}
			
	var controls = searchObj.Controls;
	if (controls) {
		var params = [];
		var inputIDs = controls.Terms;
				
		var sign = StateSign.Undefined;
		var stateCode = searchObj.GetSelectedState(res);
				
		if (stateCode != null) {
			sign = StateSign.Selected;
			stateControl.value = stateCode;
		}
		else {
			sign = StateSign.Unselected;
		}
				
		if (searchObj.IsDifferentStateSelected(res)) {
			searchObj.AddMessage(new Message("Schools need to be in the same state.", messageControl));
			controls.StartOver.style.display = "";
		} 
		else if (sign == StateSign.Unselected) {
				
			searchObj.SetActiveControl(stateControl);
					
			if (searchObj.IsLessThanMinSchoolsToCompareSelected(res)) {
				searchObj.AddMessage(new Message("Please select a state and at least 2 schools.", messageControl));
						
				var emptyInput = searchObj.GetFirstEmptyInput(res);
				searchObj.AddOutline(new Outline({ "Control" : emptyInput }));
				searchObj.SetActiveControl(emptyInput);
			}
			else {
				searchObj.AddMessage(new Message("Please select a state.", messageControl));
			}
			searchObj.AddOutline(new Outline({ "Control" : stateControl }));
			
			searchObj.ClearServerMessagesAndOutlines();
		}
		else {
			if (searchObj.IsLessThanMinSchoolsToCompareSelected(res) &&
				searchObj.CurrentAction != CompareSearchAction.AddSchool &&
				searchObj.CurrentAction != CompareSearchAction.PageNavigate) {
				searchObj.AddMessage(new Message("Please select at least 2 schools.", messageControl));
					
				var emptyInput = searchObj.GetFirstEmptyInput(res);
				searchObj.AddOutline(new Outline( { "Control" : emptyInput } ));
				
				searchObj.SetActiveControl(emptyInput);
				
				searchObj.ClearServerMessagesAndOutlines();
			}
			else
			{
				var url = U_CMP; 
				var urlParams = searchObj.getSearchParameters();
				url = Url.addParameters(url, urlParams);
				if (!String.isEmpty(stateCode))
					url = Url.setParameter(url, P_US_STATE, stateCode);
					
				var termInput = null;
				var value = null;
						
				for (var i=0; i < inputIDs.length; ++i) {
						
					if (searchObj.AddedSchools && searchObj.AddedSchools[i]) {
						value = searchObj.AddedSchools[i];
						searchObj.AddedSchools = null;
					}
					else {
						termInput = $get(inputIDs[i]);
						value = (termInput.iswatermarked && termInput.value.trim() == "Optional") ? "" : termInput.value.trim();
					}
					
					if (!String.isEmpty(value)) {
						var paramName = window["P_SCHOOL_TERM_" + (i+1)];
						url	= Url.setParameter(url, paramName, res.SearchTerms[i]);
					}
				}
						
				if (searchObj.GetIsStateChanged()) {
					url = Url.removeParameter(url, P_SCHOOLS_TO_COMPARE);
					searchObj.isStateChanged = false;
				}
						
				if (searchObj.redirect == false) {
					url = Url.setParameter(url, P_BLOCK_REDIRECT, "true");
				}
				else {
					url = Url.removeParameter(url, P_BLOCK_REDIRECT);
				}
						
				if (searchObj.CurrentAction)
					url = Url.setParameter(url, P_COMPARE_SEARCH_ACTION, searchObj.CurrentAction);
				if (searchObj.CurrentSource != null)
					url = Url.setParameter(url, P_COMPARE_SEARCH_SOURCE, searchObj.CurrentSource);
							
				Url.navigate(url);	
			}
		}
		
		Message.ClearMessages(messages);
		Outline.ClearOutlines(outlines);
		
		searchObj.ShowMessagesAndOutlines();
		
		searchObj.SetFocus();
	}
}
		
function SM_CompareSearch_CheckKey(e) {
	onEnterPressed(e, this.Execute.bind(this, null, false, CompareSearchAction.Compare));
}

function SM_CompareSearch_getSearchParameters() {
	var controls = this.Controls;
	if (controls) {
		var params = [];
		var inputIDs = controls.Terms;
				
		// the cycle below collects search terms' parameters (or selected schools names)
		// and invalidates selected school ID if needed
		for (var i=0, length = inputIDs.length; i<length; i++) {
			// get current value in the input control and 
			var value = null;
			if (this.AddedSchools && this.AddedSchools[i]) {
				value = this.AddedSchools[i];
			}
			else {
				var termInput = $get(inputIDs[i]);
				var value = (termInput.iswatermarked && termInput.value.trim() == "Optional") ? "" : termInput.value.trim();
			}
					
			var compareTerms = SM.CompareTerms.Instance;
					
			// get respective item in the selected IDs array
			var id = compareTerms.IDs[i];
					
			// in case a school was previously selected but the term
			// value has been changed then drop school id from the
			// list of the selected schools' IDs
			if (!$notExistOrNull(id) && (compareTerms.SearchTerms[i] != value)) {
				compareTerms.IDs[i] = null;
				compareTerms.PageNumbers[i] = 1;
			} 
			var paramName = window["P_SCHOOL_TERM_" + (i+1)];
			params.push(Url.createParameter(paramName, value));
		}
		// process state code parameter
		var selectState = $get(controls.State);
		var stateCode = selectState.selectedIndex == 0 ? "" : selectState.value;
		params.push(Url.createParameter(P_US_STATE, stateCode));
				
		// process selected IDs parameter
		params.push(this.getIDsParameter());
				
		// add paging page numbers parameter
		params.push(this.getPagingParameter());
				
		// filter out empty parameters values
		params = params.filter(function(item) { return item.substr(-1) != "="; });
				
		return params;		
	}
}
		
function SM_CompareSearch_AddSchool(index, id, redirect, action) {
	var action = $ensure(action, CompareSearchAction.AddSchool);
	var redirect = $ensure(redirect, true);
			
	var compareTerms = SM.CompareTerms.Instance;
	compareTerms.IDs[index] = id;
	// get respective input control for the search term
	var input = $get(this.Controls.Terms[index]);
			
	this.AddedSchools = [];
			
	// get schools collection for the given schools list
	// defined by "index" parameter
	var schools = SchoolsToCompare[index];
			
	// search for school with the given ID
	for (var i=0; i<schools.length; i++) {
		if (schools[i].ID == id) {
			// found: set input control's value to the name of the school
			var name = schools[i].Name;
			this.AddedSchools[index] = name;
			//input.value = name;
			// set initial search term to the newly assigned value.
			// we need it to validate whether ID by name of the school later on
			compareTerms.SearchTerms[index] = name;
			break;
		}
	}	
	if (redirect) {
		if (this.GetSelectedSchoolsCount() == SchoolMattersConfig.MaxSchoolsToCompare)
			this.Execute(null, true, action);
		else
			this.Execute(null, false, action);
	}
	else {
		this.Execute(null, false, action);
	}
}
		
function SM_CompareSearch_GoToPage(index, pageNumber) {
		
	if (SM.CompareTerms && 
		SM.CompareTerms.Instance && 
		SM.CompareTerms.Instance.PageNumbers) {
				
		SM.CompareTerms.Instance.PageNumbers[index] = pageNumber;
		this.Execute(null, false, CompareSearchAction.PageNavigate, index);
	}
}
		
function SM_CompareSearch_getIDsParameter() {
	var ids = SM.CompareTerms.Instance.IDs;
	var value = ids.join(',');
	return Url.createParameter(P_SCHOOLS_TO_COMPARE, value);
}
		
function SM_CompareSearch_getPagingParameter() {
	var pageNumbers = SM.CompareTerms.Instance.PageNumbers;
	var value = pageNumbers.join(',');
	return Url.createParameter(P_PAGE_NUMBERS, value);
}
		
function SM_CompareSearch_StartOver() {
	Url.navigate(U_CMP);
}
		
function SM_CompareSearch_OnChangeState() {
	this.isStateChanged = true;
}
		
function SM_CompareSearch_GetIsStateChanged() {
	return this.isStateChanged;
}
// ----------
// SM.ParentReview
SM.ParentReview = {
	Execute: SM_ParentReviewSearch_Execute,
	GoToPage: SM_ParentReviewSearch_GoToPage
}
function SM_ParentReviewSearch_Execute() {
	var url = U_PR; // Search Results page URL		
	var params = SM.ParentReviewTerms.Instance.Serialize();	
	// get complete URL
	url = Url.addParameters(url, params);
	// navigate
	Url.navigate(url);
}
function SM_ParentReviewSearch_GoToPage(pageNumber) {
	SM.ParentReviewTerms.Instance.PageNumber = pageNumber;
	this.Execute();		
}
// ----------
// SM.ParentReviewTerms
SM.ParentReviewTerms = function(terms) {
	if (terms) {
		this.ID = $exist(terms.ID) ? terms.ID : null;
		this.firstPage = $exist(terms.FirstPage) ? terms.FirstPage : null;
 		this.pageNumber = $exist(terms.pageNumber) ? terms.pageNumber : 1;
	}
}
SM.ParentReviewTerms.prototype = {
	Serialize : SM_ParentReviewTerms_Serialize
}
function SM_ParentReviewTerms_Serialize() {
	var params = [];
	// create parameters
	params.push(Url.createParameter(P_SCHOOL_ID, this.ID));
	params.push(Url.createParameter(P_PAGE_NUMBER, this.PageNumber));
	params.push(Url.createParameter(P_FIRST_PAGE, this.FirstPage));
		
	return params;
}
SM.ParentReviewTerms.register();
// ----------
// SM.CompareSchoolList
SM.CompareSchoolList = function(index, isBuilded, isNotFound, schools, cmpSearch, container) {
	this.index = index;
	this.isBuilded = isBuilded;
	this.isNotFound = isNotFound;
	this.schools = schools;
	this.cmpSearch = cmpSearch;
	this.container = container;
	
	if (!SM.CompareSchoolList.Lists)
		SM.CompareSchoolList.Lists = [];
		
	SM.CompareSchoolList.Lists[this.index] = this;
}
SM.CompareSchoolList.Update = function() {
	if (SM.CompareSchoolList.Lists) {
		for (var i = 0; i < SM.CompareSchoolList.Lists.length; ++i)
			SM.CompareSchoolList.Lists[i].Update();
	}
}
SM.CompareSchoolList.prototype = {
	Update: SM_CompareSchoolList_Update,
	Hide: SM_CompareSchoolList_Hide
}
function SM_CompareSchoolList_Update() {
	if (this.isBuilded) {	
		var compareTerms = SM.CompareTerms.Instance;
		var searchTerm = compareTerms.SearchTerms[this.index];
		
		var inputIDs = this.cmpSearch.Controls.Terms;
		
		var input = $get(inputIDs[this.index]);
		var value = (input.iswatermarked && input.value.trim() == "Optional") ? "" : input.value.trim();
		
		if (String.isEmpty(value)) 
			this.Hide();
	}
}
function SM_CompareSchoolList_Hide() {
	DomElement.addCssClass(this.container, "hide");
}
SM.CompareSchoolList.register();

Function.registerNamespace("Data");
// Data.MetaData
Data.MetaData = function(IDField) {
	this.ID = IDField || "ID";
};

Data.MetaData.register();
// ----------
// Data.DataTable
Data.DataTable = function Data_DataTable(data, metaData) {
	data = data || [];
	metaData = metaData || new Data.MetaData();	
	this.metaData = metaData;		
	this.data = [];
	this.hash = {};
	
	for (var i = 0, ic = data.length; i < ic; i++) {
		this.Append(data[i]);		
	}
}

Data.DataTable.prototype =  {
	Add : Data_DataTable_Add,
	Append : Data_DataTable_Append,
	GetByID : Data_DataTable_Get,
	OnItemRemoved : Data_DataTable_OnItemRemoved,
	RemoveAt : Data_DataTable_RemoveAt,
	RemoveByID : Data_DataTable_RemoveByID,
	Clear : Data_DataTable_Clear,
	get_Count : Data_DataTable_Count,
	resetHash : Data_DataTable_resetHash,
	Update : Data_DataTable_Update,
	AttachRenderer : Data_DataTable_attachRenderer,
	get_Renderers : Data_DataTable_get_Renderers,
	getHandler : Data_DataTable_getHandler,
	get_Data : Data_DataTable_get_Data,
	get_IDs : Data_DataTable_get_IDs,
	contains : Data_DataTable_contains
}

function Data_DataTable_Add(item) {
	var id = item[this.metaData.ID];
	if ($notExistOrNull(id)) {
		throw new Error("DataTable: ID attribute is not defined");
	}
		
	if (!$exist(this.hash[id])) {
			
		var newData = [];
		newData.push(item);
		for (var i = 0, ic = this.data.length; i < ic; ++i)
			newData.push(this.data[i]);
		delete this.data;
		this.data = newData;
			
		this.resetHash();
						
		var handler = this.getHandler("ItemAdded");		
		handler(this, { "dataContext": item, "metaData": this.metaData });
	}
}

function Data_DataTable_Append(item) {
	var id = item[this.metaData.ID];
	if ($notExistOrNull(id)) {
		throw new Error("DataTable: ID attribute is not defined");
	}
		
	if (!$exist(this.hash[id])) {
		var len = this.data.length;
		
		this.hash[id] = len;
		this.data[len] = item;
			
		var handler = this.getHandler("ItemAdded");		
		handler(this, { "dataContext": item, "metaData": this.metaData });
	}
}

function Data_DataTable_Get(id) {
	var index = this.hash[id];
	if (index < 0 || index > this.get_Count()) {
		throw new Error("DataTable: index out of range");			
	}
	return this.data[index];
}

function Data_DataTable_OnItemRemoved(item) {
	var handler = this.getHandler("ItemRemoved");		
	handler(this, {"dataContext": item, "metaData": this.metaData});		
}

function Data_DataTable_RemoveAt(index) {
	var item = this.data.removeAt(index);
	this.resetHash();
	this.OnItemRemoved(item);
}

function Data_DataTable_RemoveByID(ID) {
	var index = this.hash[ID];
	if ($exist(index)) {
		delete this.hash[ID];
		this.RemoveAt(index);
	}
}

function Data_DataTable_Clear() {
	delete this.data;
	this.data = [];
	this.resetHash();
	this.OnItemRemoved(null);
}

function Data_DataTable_Count() {
	return this.data.length;
}

function Data_DataTable_resetHash() {
	this.hash=[];
	for (var i=0, length = this.data.length; i<length; i++) {
		var item = this.data[i];
		var id = item[this.metaData.ID];
		this.hash[id] = i;
	}
}

function Data_DataTable_Update(renderer) {
	if ($notExistOrNull(renderer)) {
		var renderers = this.get_Renderers();
		for (var i = 0; i < renderers.length; ++i) {
			if (renderers[i] && renderers[i].Update)
				renderers[i].Update(this.data, this.metaData);
		}
	} else {
		var renderers = this.get_Renderers();
		for (var i = 0; i < renderers.length; ++i) {
			if (renderers[i] && renderers[i].Update && renderers[i] == renderer) {
				renderers[i].Update(this.data, this.metaData);
				break;
			}
		}
	}
}

function Data_DataTable_attachRenderer(renderer, skipRendering) {
	var renderers = this.get_Renderers();		
	renderers.push(renderer);		
	if (!skipRendering) {
		renderer.Render(this.data, this.metaData);
	}
}

function Data_DataTable_get_Renderers() {
	if (!this.renderers) {
		this.renderers = [];
	}
	return this.renderers;
}

function Data_DataTable_getHandler(commandName) {
	var renderers = this.get_Renderers();
	return function(source, args) {
		for (var i=0, length=renderers.length; i<length; i++) {
			var renderer = renderers[i];
			var methodName = ["On" + commandName];
			if	(renderer[methodName] instanceof Function) {
				renderer[methodName](source, args);
			}
		}
	}
}

function Data_DataTable_get_Data() {
	return this.data;
}

function Data_DataTable_get_IDs() {
	var result = [];
	var id = this.metaData.ID;
	for (var i=0, length=this.data.length; i<length; i++) {
		result[i] = this.data[i][id];
	}
	return result;
}

function Data_DataTable_contains(ID) {
	return $exist(this.hash[ID]);
}

Data.DataTable.register();
Function.registerNamespace("SM.UI");
// SM.UI.Renderer
SM.UI.Renderer = function(tmplID) {
	this.template = $get(tmplID);
	this.events = null;	
	if (!this.template) {
		throw new Error(SystemMessages.RendererInitializationError);
	}
	if (!$get(SM.UI.Renderer.sandBoxID)) {
		this.createSandBox();
	}
}

SM.UI.Renderer.sandBoxID = "sandBox";
SM.UI.Renderer.prototype = {
	ClearIn : SM_UI_Renderer_ClearIn,
	RenderIn : SM_UI_Renderer_RenderIn,
	getAutogeneratedID : SM_UI_Renderer_getAutogeneratedID,
	createElement : SM_UI_Renderer_createElement,
	append : SM_UI_Renderer_append,
	insert : SM_UI_Renderer_insert,
	createSandBox : SM_UI_Renderer_createSandBox,
	get_events : SM_UI_Renderer_get_events,
	add_itemRenderBegin : SM_UI_Renderer_add_itemRenderBegin,
	remove_itemRenderBegin : SM_UI_Renderer_remove_itemRenderBegin,
	add_itemRenderEnd : SM_UI_Renderer_add_itemRenderEnd,
	remove_itemRenderEnd : SM_UI_Renderer_remove_itemRenderEnd
}

function SM_UI_Renderer_ClearIn(cntID) {
	var container = $get(cntID);
	if (container) {
		var parent = container.getElementsByTagName("TBODY")[0];
			
		while (parent.childNodes.length > 0) {
			var children = parent.childNodes;
			var child = children[0];
			parent.removeChild(child);
		}
	}		
}	

function SM_UI_Renderer_RenderIn(cntID, dataContext, metaData, append) {

	append = $ensure(append, false);
		
	var renderBeginHandler = this.get_events().getHandler("itemRenderBegin");
	if (renderBeginHandler) {
		 renderBeginHandler(this);
	}
	
	metaData = metaData || new Data.MetaData();
	var container = $get(cntID);
	if (container) {
		// get template
		var html = this.template.parentNode.innerHTML;
		// bind data
		html = html.contextFormat(dataContext);
		
		// generate element ID
		var idAttribute = 'id="~0"'.format(this.getAutogeneratedID(cntID, dataContext[metaData.ID]));
		html = html.replace(/id=[^>\s]+/i, idAttribute);
		
		// convert to DOM element	
		var el = this.createElement(html);
		// insert into container hierarchy
		if (append)
			this.append(container, el);
		else
			this.insert(container, el);
	}
	var renderEndHandler = this.get_events().getHandler("itemRenderEnd");
	if (renderEndHandler) {
		 renderEndHandler(this);
	}		
}

function SM_UI_Renderer_getAutogeneratedID(cntID, id) {
	return "~0_~1".format(cntID, id);		
}

function SM_UI_Renderer_createElement(html) {
	var tagName = this.template.tagName.toUpperCase();
	var sandBox = $get(SM.UI.Renderer.sandBoxID);
	if (tagName == "TR") {
		html = "<table>~0</table>".format(html);
	}
	sandBox.innerHTML = html;				

	var el = sandBox.getElementsByTagName(tagName)[0];
	var parent = el.parentNode;
	el = parent.removeChild(el);
	sandBox.innerHTML = "";
	return el;
}

function SM_UI_Renderer_append(container, el) {
	var parent = el.tagName.toUpperCase() == "TR" ? container.getElementsByTagName("TBODY")[0] : container;
	parent.appendChild(el);
}

function SM_UI_Renderer_insert(container, el) {
	var parent = el.tagName.toUpperCase() == "TR" ? container.getElementsByTagName("TBODY")[0] : container;
	var children = parent.childNodes;
	if (children.length < 1)
		parent.appendChild(el);
	else {
		var firstChild = children[0];
		parent.insertBefore(el, firstChild);
	}
}

function SM_UI_Renderer_createSandBox()  {
	var el = document.createElement("div");
	el.style.display = "none";
	el.innerHTML = "<div id='~0'></div>".format(SM.UI.Renderer.sandBoxID);
	document.body.appendChild(el);
}

function SM_UI_Renderer_get_events() {
	if (!this.events) {
		this.events = new EventList();
	}
	return this.events;
}

function SM_UI_Renderer_add_itemRenderBegin(handler) {
	this.get_events().add("itemRenderBegin", handler);
}

function SM_UI_Renderer_remove_itemRenderBegin(handler) {
	this.get_events().remove("itemRenderBegin", handler);
}

function SM_UI_Renderer_add_itemRenderEnd(handler) {
	this.get_events().add("itemRenderEnd", handler);
}

function SM_UI_Renderer_remove_itemRenderEnd(handler) {
	this.get_events().remove("itemRenderEnd", handler);
}		

SM.UI.Renderer.register();
// ----------
// SM.UI.CollectionRenderer
SM.UI.CollectionRenderer = function SM_UI_CollectionRenderer(cntID, tmplID) {
	this.containerID = cntID;
	SM.UI.CollectionRenderer.base(this, [tmplID]);	
}

SM.UI.CollectionRenderer.prototype = {
	Clear : SM_UI_CollectionRenderer_Clear,
	Render : SM_UI_CollectionRenderer_Render,
	Update : SM_UI_CollectionRenderer_Update,
	OnItemAdded : SM_UI_CollectionRenderer_OnItemAdded,
	OnItemRemoved : SM_UI_CollectionRenderer_OnItemRemoved,
	GetItemID : SM_UI_CollectionRenderer_GetItemID,
	add_itemRemoved : SM_UI_CollectionRenderer_add_itemRemoved,
	remove_itemRemoved : SM_UI_CollectionRenderer_remove_itemRemoved
}

function SM_UI_CollectionRenderer_Clear() {
	this.ClearIn(this.containerID);
}

function SM_UI_CollectionRenderer_Render(data, metaData) {
	for (var i=0, length=data.length; i<length; i++) {
		this.RenderIn(this.containerID, data[i], metaData, true);
	}
}

function SM_UI_CollectionRenderer_Update(data, metaData) {
	this.Clear();
	this.Render(data, metaData);
}	

function SM_UI_CollectionRenderer_OnItemAdded(source, args) {
	this.RenderIn(this.containerID, args.dataContext, args.metaData, false);
}

function SM_UI_CollectionRenderer_OnItemRemoved(source, args) {
	if (args.dataContext) {
		var id = this.GetItemID(args.dataContext[args.metaData.ID]);
		var el = $get(id);
		if (el) {
			var parent = el.parentNode;
			parent.removeChild(el);
		}
	}
		
	var itemRemovedHandler = this.get_events().getHandler("itemRemoved");
	if (itemRemovedHandler) {
		itemRemovedHandler(this);
	}	
}

function SM_UI_CollectionRenderer_GetItemID(id) {
	return this.getAutogeneratedID(this.containerID, id); 
}

function SM_UI_CollectionRenderer_add_itemRemoved(handler) {
	this.get_events().add("itemRemoved", handler);
}

function SM_UI_CollectionRenderer_remove_itemRemoved(handler) {
	this.get_events().remove("itemRemoved", handler);
}

SM.UI.CollectionRenderer.register(SM.UI.Renderer);
// ----------
// SM.UI.PartialCollectionRenderer
SM.UI.PartialCollectionRenderer = function SM_UI_PartialCollectionRenderer(cntID, tmplID, itemCountToRender, isSorted) {

	SM.UI.PartialCollectionRenderer.base(this, [cntID, tmplID]);

	SM.UI.PartialCollectionRenderer.itemCountToRenderDefault = 3;
	
	this.itemCountToRender = $ensure(itemCountToRender, SM.UI.PartialCollectionRenderer.itemCountToRenderDefault);
	this.isSorted = $ensure(isSorted, false);
}

SM.UI.PartialCollectionRenderer.prototype = {
	Render : SM_UI_PartialCollectionRenderer_Render,
	GetItemCountToRender : SM_UI_PartialCollectionRenderer_GetItemCountToRender,
	SetItemCountToRender : SM_UI_PartialCollectionRenderer_GetItemCountToRender,
	GetIsSorted : SM_UI_PartialCollectionRenderer_GetIsSorted,
	SetIsSorted : SM_UI_PartialCollectionRenderer_SetIsSorted
}

function SM_UI_PartialCollectionRenderer_Render(data, metaData) {
		
	var d = data.slice(0);
		
	if (this.isSorted == true) {
		d = d.sort(
			function(fo, so) { 
				
				var fol = fo.Name.toLowerCase();
				var sol = so.Name.toLowerCase();
					
				if (fol < sol)
					return -1;
				if (fol > sol)
					return 1;
				return 0;
			});
	}
		
	for (var i = 0, ic = d.length; i < ic && i < this.itemCountToRender; i++) {
		this.RenderIn(this.containerID, d[i], metaData, true, this.isSorted);
	}
}	

function SM_UI_PartialCollectionRenderer_GetItemCountToRender() {
	return this.itemCountToRender;
}

function SM_UI_PartialCollectionRenderer_GetItemCountToRender(itemCountToRender) {
	this.itemCountToRender = itemCountToRender;
}

function SM_UI_PartialCollectionRenderer_GetIsSorted() {
	return this.isSorted;
}

function SM_UI_PartialCollectionRenderer_SetIsSorted(isSorted) {
	this.isSorted = isSorted;
}

SM.UI.PartialCollectionRenderer.register(SM.UI.CollectionRenderer);
// ----------
// SM.UI.LayoutManager
SM.UI.LayoutManager = function(footerID) {
	this.footer = $get(footerID);	
}

SM.UI.LayoutManager.prototype = {
	updateFooter : SM_UI_LayoutManager_updateFooter
}

function SM_UI_LayoutManager_updateFooter() {
	if (this.footer) {
		var parent = this.footer.parentNode;
		parent.removeChild(this.footer);
		parent.appendChild(this.footer);
	}
}	

SM.UI.LayoutManager.register(SM.UI.LayoutManager);
// ----------

SM.UI.PageContentParser =  {
	Parse : SM_UI_PageContentParser_Parse,
	GetPageId : SM_UI_PageContentParser_GetPageId,
	GetFullUrl : SM_UI_PageContentParser_GetFullUrl,
	AddUrlParameters : SM_UI_PageContentParser_AddUrlParameters,
	CreateParameter : SM_UI_PageContentParser_CreateParameter,
	ParameterDelimiter : "&",
	QueryStringDelimiter : "?"
	
}

function SM_UI_PageContentParser_Parse(activePageId)	{
	var els = document.getElementsByTagName('a');
	var url = null;
	for ( var i = 0; i < els.length; i ++) {
		var element = els[i];
		if (element.getAttribute("fileName")) {
			var params = [];
			params.push(this.CreateParameter("rtype", "file"));
			params.push(this.CreateParameter("rpid", activePageId));
			params.push(this.CreateParameter("flnm", element.getAttribute("fileName")));
			
			element.href = this.GetFullUrl(params);
			element.target = "new";
		}
		else if (url = element.getAttribute("url")) {
			var pageId = this.GetPageId(url);
			var pages = GetPageInfo(PageInfo);
			if (pages[pageId] && pages[pageId].Popup) {
				element.setAttribute("href", "javascript:void(0)");
				$attachEvent(element, "click", (function(pid){
				 	return function(){
				 		SM.Popup.Open(pid);
				 	}
				 })(pageId));
			}
			else {
				element.setAttribute("href", 
					(url.charAt(0) == "#" || url.indexOf("mailto:") == 0) ? url :
					WebFrameworkConfig.RootUrl + url);
			}
		}
	}
}

function SM_UI_PageContentParser_GetPageId(url) {
	if (url) {
		if (/page=([a-z]+)/.test(url))
			return RegExp.$1;
	}
}

function SM_UI_PageContentParser_GetFullUrl (params) {
	var url = WebFrameworkConfig.ResourceHandlerUrl;
	url = this.AddUrlParameters(url, params);
	return url
}

function SM_UI_PageContentParser_AddUrlParameters(url, params){
	if (String.isEmpty(url) || !params) return url;
	
	// separate query string parameters
	var p = [], queryParams = [];
	for(var i = 0, ic=params.length; i < ic; ++i) {
		var param = params[i];
		if (!String.isEmpty(param)) {
			var target = Url.isQueryParameter(param) ? queryParams : p;
			target.push(params[i]);
		}
	}			
	// form parameter strings
	var paramsString = p.join(this.ParameterDelimiter);
	var queryParamsString = queryParams.join("&");
	
	// parse original URL
	var urlParts = url.split("?");
	var dirPart = urlParts[0];
	
	// combine query string
	var query = "";
	if (urlParts.length > 1) {
		query = String.isEmpty(queryParamsString) ? urlParts[1] 
						: [urlParts[1], queryParamsString].join("&");
	}
	else {
		query = queryParamsString;
	}
		
	var delimiter = "";

	if (!String.isEmpty(paramsString)) {
		delimiter = dirPart.indexOf(this.QueryStringDelimiter) == -1 ?
				this.QueryStringDelimiter : this.ParameterDelimiter;
	}
	
	var queryStringDelimiter = String.isEmpty(query) ? "" : "?";
	
	var result = [dirPart, delimiter, paramsString, queryStringDelimiter, query].join("");

	return result;
}

function SM_UI_PageContentParser_CreateParameter(name, value) {
	var result = "";
	if (!String.isEmpty(name)) {
		result = [encodeURIComponent(name), UrlContext.NameValueDelimiter, encodeURIComponent(value)].join('');
	}
	return result;
}
//------------------------------------------------------------------------------

function getYesNoParameter(name, value, startWithSeparator) {
	return (!$exist(value)) ? '' : [ startWithSeparator ? ',' : '',
		name, '=', value ? 'yes' : 'no'].join('');
}

function getDimensions(width, height, x, y) {
  x = $notExistOrNull(x) ? (screen.availWidth - width) >> 1 : x;
	y = $notExistOrNull(y) ? (screen.availHeight - height) >> 1 : y;
	if (x < 0) x = 0;
	if (y < 0) y = 0;
	return ["height=", height, ",width=", width, ",left=", x, ",top=", y].join('');
}

function openWindow(url, name, params, onopen) {
	
	if(name != null) name = name.replace(/%\d+/g,""); //delete from name substring like '%20' or '%1'
	var win = window.open(url, name, params);
	
	if (win != null) {
		if ($exist(onopen)) {
			onopen(win);
		}
		try {
			win.focus();
		}
		catch(e) {};
	}
	return win;
}

function createParameterString(width, height, isResizable, isScrollbars, isLocation, left, top) { 
	return [$exist(width) && $exist(height) ? getDimensions(width, height, left, top) : '',
		getYesNoParameter("resizable", isResizable, true), getYesNoParameter("scrollbars", isScrollbars, true),
		getYesNoParameter("location", isLocation, true), ',toolbar=no,titlebar=no,menubar=no'].join('');
}

function openPopupWindow(url, name, width, height, isResizable, isScrollbars, isLocation, left, top) {
	return openWindow(url, name,
		createParameterString(width, height, isResizable, isScrollbars, isLocation, left, top));
}


function StringHelper() {
}

StringHelper.fitToContainer = function StringHelper_fitToContainer(elementId) {
	var delimiters = Array.getHash(["-", ".", ","]);
	var el = $get(elementId);
	if (el) {
		var cnt = el.parentNode;
		// if string is too long
		if (cnt && cnt.offsetWidth < el.offsetWidth) {
			// search for text node
			var target = el.firstChild;
			while (target && target.nodeType != 3) {
				target = target.nextSibling;
			}
			if (target.nodeType == 3) {
				var text = target.nodeValue;
				var chars = text.split("");
				var index = chars.length - 1;

				// split while the string doesn't fit to its container 
				while (index > 0 && el.offsetWidth > cnt.offsetWidth) {
					var letter = chars[index];
					// current letter is a delimiter
					if (delimiters[letter]) {
						chars.splice(index, 1, letter, " ");
						target.nodeValue = chars.join("");
					}
					index--;
				}
			}
		}		
	}
}

StringHelper.register();

function EmailLinkHelper() {
	this.handlers = [];
}

EmailLinkHelper.prototype = {
	registerUrlHandler: EmailLinkHelper_registerUrlHandler,
	HandleUrl: EmailLinkHelper_HandleUrl
}

function EmailLinkHelper_registerUrlHandler(handler) {
	if (handler && typeof(handler) == "function") {
		this.handlers.push(handler);
	}
}

function EmailLinkHelper_HandleUrl(url) {
	for (var i=0; i<this.handlers.length; i++) {
		var handler = this.handlers[i];
		url = handler(url);
	}
	return url;
}

EmailLinkHelper.register();

EmailLinkHelper.Instance = new EmailLinkHelper();

// SM.Popup
SM.Popup = { 
	Open: SM_Popup_Open
};

function SM_Popup_Open(pageID) {
	switch (pageID) {
		case PID_PP:
			openPrivacyPolicyPopup();
			break;
		case PID_TMS:
			openTermsOfUsePopup();
			break;	
		case PID_PGL:
			openGuidelinesPopup();
			break;
		case PID_PLM:
			openLearnMorePopup();
			break;	
	}
}

function GetPageInfo() {
	if (this.pages) return this.pages;
	this.pages = [];	
	for (var i = 0; i < PageInfo.length; i++){
		this.pages[PageInfo[i].PageId] = PageInfo[i];
	}
	return this.pages;
}
// ----------
// Description
Description = {
	show: Description_show
};

function Description_show(configName, id, stateCode, level, width, height, schoolId, reviewId) {
	var url = Url.addParameter(U_DSC, P_CONFIG_DOCUMENT_NAME, configName);
	url = Url.addParameter(url, P_CONFIG_ELEMENT_ID, id);	
	url = Url.addParameter(url, P_US_STATE, stateCode);
	url = Url.addParameter(url, P_LEVEL, level);

	if (reviewId) {
	 	url = Url.addParameter(url, P_REVIEW_ID, reviewId);
	}
	if (schoolId) {
	 	url = Url.addParameter(url, P_SCHOOL_ID, schoolId);
	}	
	openPopupWindow(url, 
				"description" + (id ? id: ""), 
				width = width || 400,
				height = height || 250,
				false);
}

function printPage() {
	window.print();
}

//popup to confirmation
function openSchoolWebSitePopup(id)
{
	var url = Url.addParameter(U_SCL, P_SCHOOL_ID,id);
	if(this.popWin) this.popWin.close();
	this.popWin = openPopupWindow(url, "SchoolWebsite" + Number(new Date), 420, 365, false);
}

function openImageUploadPopup(id)
{
	var url = Url.addParameter(U_PIU, P_SCHOOL_ID,id);
	if(this.popWin) this.popWin.close();
	this.popWin = openPopupWindow(url, "ImageUpload" + Number(new Date), 420, 470);
}

function openReportReviewPopup(sid, rid)
{
	var url = Url.addParameter(U_PRR, P_SCHOOL_ID, sid);
		url = Url.addParameter(url, P_REVIEW_ID, rid);
	if(this.popWin) this.popWin.close();
	this.popWin = openPopupWindow(url, "ReportReview" + Number(new Date), 400, 500, false);
}

function openEmailPopup(parameterName, id) {
	var url = Url.addInnerUrl(U_PEM, window.location.href);
	if(this.popWin) this.popWin.close();
	if (parameterName) {
		url = Url.addParameter(url, parameterName, id);
		if (EmailLinkHelper && EmailLinkHelper.Instance) {
			url = EmailLinkHelper.Instance.HandleUrl(url);
		}
	}
	this.popWin = openPopupWindow(url, "Email" + Number(new Date), 560, 580, false);
}
//*******************************************************


function openDrivingDirectionPopup(idParameter, id, mapMode, navIndex) {
	var url = Url.addParameter(U_PDD, idParameter, id);
	url = Url.addParameter(url, P_MAP_MODE, mapMode);
	url = Url.addParameter(url, P_MENU_NAVIGATION_INDEX, navIndex);
	openPopupWindow(url, "DrivingDirections", 350, 280, false);
}
// SM.ReviewListManager
SM.ReviewListManager = function(controls, constants) {

	this.controls = controls;
	this.constants = constants;
	this.isProcess = false;
	
	var iframe = this.controls.IFrame;
	if (iframe) {
		$attachEvent(iframe, 'load', this.OnFrameLoad.bind(iframe, this));
	}
	
	this.DefinedReviews = [];
}

SM.ReviewListManager.prototype = {
	SetReviewStatus: SM_ReviewListManager_SetReviewStatus,
	OnFrameLoad: SM_ReviewListManager_OnFrameLoad,
	GetResponseData: SM_ReviewListManager_GetResponseData
}

function SM_ReviewListManager_SetReviewStatus(reviewId, isHelpful) {
	// if cookie is not enabled we use the DefinedReviews to save processed review id
	if (Cookie.IsEnabled() == false) {
		// if the review is processed just returns
		if (this.DefinedReviews[reviewId])
			return;
	}
	
	if (this.isProcess == true)
		return;
	var iframe = this.controls.IFrame;
	if (iframe) {
		if (WebFrameworkConfig && WebFrameworkConfig.RequestHandler) {
			var url = WebFrameworkConfig.RequestHandler;
			url = Url.addParameter(url, P_COMMAND, Command.SetReviewStatus);
			url = Url.addParameter(url, P_REVIEW_STATUS, reviewId + "$" + isHelpful);
			
			this.isProcess = true;
			iframe.src = url;
		}
	}
}

function SM_ReviewListManager_GetResponseData(iframe) {
	var responseDataObjectName = Constants.ClientResponseDataObjectName;
			
	return (iframe && iframe.contentWindow && iframe.contentWindow[responseDataObjectName]) ? 
		iframe.contentWindow[responseDataObjectName] : null;
}

function SM_ReviewListManager_OnFrameLoad(sender) {
	sender.isProcess = false;
	
	var iframe = sender.controls.IFrame;
	
	if (iframe) {
		var res = sender.GetResponseData(iframe);
		
		if (res) {
			if (res.Valid) {
				var reviewId = res.ReviewID;
				if (reviewId) {
					var lbHelpful = $get(window[sender.constants.PrefixHelpful + reviewId]);
					if (lbHelpful) {
						lbHelpful.innerText = res.HelpfulCount;
					}
					var lbTotal = $get(window[sender.constants.PrefixTotal + reviewId]);
					if (lbTotal) {
						lbTotal.innerText = res.TotalCount;
					}
					
					// if cookie is not enabled we use the DefinedReviews to save processed review id  
					if (Cookie.IsEnabled() == false) {
						sender.DefinedReviews[reviewId] = true;
					}
				}
			}
		}
	}
}

SM.ReviewListManager.register();

function openGuidelinesPopup()
{
	openPopupWindow(U_PGL, "GuidelinesForReview", 700, 550, true, true);
}

function openPrivacyPolicyPopup()
{
	openPopupWindow(U_PP, "PrivacyPolicy", 700, 580, true, true);
}

function openTermsOfUsePopup()
{
	openPopupWindow(U_TMS, "TermsOfUse", 800, 650, true, true);
}

function openLearnMorePopup()
{
	openPopupWindow(U_PLM, "LearnMore", 500, 200);
}

function openWidgetTermsOfUsePopup()
{
	openPopupWindow(U_WTMS, "WidgetTermsOfUse", 800, 650, true, true);
}

function openAPITermsOfUsePopup()
{
	openPopupWindow(U_ATMS, "APITermsOfUse", 800, 650, true, true);
}

function changePageNumber(page,e)
{
	var url = Url.setParameter(location.href,P_PAGE_NUMBER,page);
	var _e = e || event;
	if (_e)Event.cancel(_e);
	Url.navigate(url);
}

// onkeypressed handlers
// e - on keypress event
function onKeyPressed(e, keyCode, callFunc, cancel, codesToCancel) {
	if (e) {
		cancel = $ensure(cancel, true);
		codesToCancel == codesToCancel || [];
		var codesToHandle = codesToCancel.concat(keyCode);
		var code = e.keyCode;
		if (codesToHandle.indexOf(code) != -1) {
			// we can handle/cancel both "keypress" and "keydown" events
			// but execute given callback method for one event only (keypress)
			if (e.type == 'keypress') {
				if (typeof(callFunc) == 'function') {
					setTimeout(function() { callFunc(); }, 1);
				}
				if (cancel || (codesToCancel.indexOf(code) != -1)) {
					Event.cancel(e);
				}
			}
		}
	}
}

// e - on keypress event
function onEnterPressed(e, callFunc, cancel) {
	// codesToCancel parameter was set to 3 in 
	// order to fix page reloading under Mac OS with "Enter" key
	// pressed on the Numeric Pad
	onKeyPressed(e, 13, callFunc, cancel, [3]);
}

function trapAdSenseError(msg, url, lno) { 
	return true; 
}

ImageUpload = {
	adjustLayout: function(id, className) {
		var input = $get(id);
		if (input) {
			if (!isIE) {
				var cnt = input.parentNode.parentNode;
				if (cnt) {
					var inputWidth = input.offsetWidth;
					while (cnt.offsetWidth < input.offsetWidth) {
						input.size = --input.size;
						if (input.offsetWidth == inputWidth) {
							break;
						}
					}
				}
			}
		}		
		var els = DomElement.getElementsByClassName(document.body, "div", className);
		cnt = input.parentNode;
		if (els.length > 0 && cnt) {
			els[0].style.width = cnt.offsetWidth - 2 + "px";
		}
	}
}	

SM.Widget = {
	widgetCodeControlID: 'widgetCode',
	warningMessages: { 
		typeAndText: "Please select the options for your widget.",
		type: "Please select the type of widget you'd like on your site.",
		text: "Please select the text to display on your widget."
	},
	WidgetTextGroupName: "widgetText",
	WindowTypeGroupName: "windowType",
	getGroupValue: SM_Widget_getGroupValue,
	setGroupValue: SM_Widget_setGroupValue,
	getWidgetType: SM_Widget_getWidgetType,
	getWidgetText: SM_Widget_getWidgetText,
	getWindowType: SM_Widget_getWindowType,
	GetCode: SM_Widget_GetCode,
	ClearCode: 	SM_Widget_ClearCode,
	CheckCode: SM_Widget_CheckCode,
	getRadioButtonValue: SM_Widget_getRadioButtonValue
}		

function SM_Widget_getGroupValue(groupName) {
	var result = "";	
	if (!String.isEmpty(groupName)) {
		var group = document.forms[0][groupName];
		for (var i = 0; i < group.length; i++) {
			if (group[i].checked) {
				result = group[i].value;
				break;
			}
		}
	}
	return result;
}

function SM_Widget_setGroupValue(groupName, value) {
	if (!String.isEmpty(groupName)) {
		var group = document.forms[0][groupName];
		for (var i = 0; i < group.length; i++) {
			if (group[i].value == value) {
				group[i].checked = true;
				break;
			}
		}
	}
	SM.Widget.CheckCode();
}

function SM_Widget_getWidgetType() {
	return SM.Widget.getGroupValue(SM.Widget.WidgetTypeGroupName);
}

function SM_Widget_getWidgetText() {
	return SM.Widget.getGroupValue(SM.Widget.WidgetTextGroupName);
}

function SM_Widget_getWindowType() {
	return SM.Widget.getGroupValue(SM.Widget.WindowTypeGroupName);
}

function SM_Widget_GetCode() {
	var widgetCode = $get(SM.Widget.widgetCodeControlID);

	var widgetType = SM.Widget.getWidgetType();
	var widgetText = SM.Widget.getWidgetText();
	var windowType = SM.Widget.getWindowType();
	
	if (!String.isEmpty(widgetType) && !String.isEmpty(widgetText)) {
		var code = ['<scr', 'ipt '];
		code.push(
			'type="text/javascript" src="~0/widget/loader.js?'.format(SM.Widget.ApplicationPath),
			'smw_func=~0&smw_textCode=~1&smw_win=~2&'.format(widgetType, widgetText, windowType),
			'sec=~0"'.format(SchoolMattersConfig.WidgetMaxAge),
			'></scr', 'ipt>');
		widgetCode.value = code.join('');

		SM.Widget.widgetType = widgetType; 
		SM.Widget.widgetText = widgetText;
		SM.Widget.windowType = windowType;
					
		widgetCode.focus();
		widgetCode.select();		
	}
	else {
		var message;
		if (String.isEmpty(widgetType) && String.isEmpty(widgetText)) {
			message = "typeAndText";
		}
		else {
			message = String.isEmpty(widgetText) ? "text" : "type";
		}
		if (message) {
			alert(SM.Widget.warningMessages[message]);
		}
	}
}

function SM_Widget_getRadioButtonValue(el) {
	var button = el.firstChild;
	while (button && (button.nodeType !=1 || button.tagName.toLowerCase() != "input")) {
		button = button.nextSibling;
	}
	return button ? button.value : "";
}

function SM_Widget_ClearCode() {
	var el = $get(SM.Widget.widgetCodeControlID);
	if (el) {
		el.value = '';
	}		
}

function SM_Widget_CheckCode() {
	var widgetType = SM.Widget.getWidgetType();
	var widgetText = SM.Widget.getWidgetText();	
	var windowType = SM.Widget.getWindowType();
	
	if ((!String.isEmpty(widgetType) && widgetType != SM.Widget.widgetType) ||
		(!String.isEmpty(widgetText) && widgetText != SM.Widget.widgetText) ||
		(!String.isEmpty(windowType) && windowType != SM.Widget.windowType)) {
		SM.Widget.ClearCode();
	}
}

SM.Behavior = {}

SM.ChartHelper = {
	ApplyBehavior: SM_ChartHelper_ApplyBehavior
}

function SM_ChartHelper_ApplyBehavior(behaviorTypeName, containerID) {
	var behaviorType = SM.Behavior[behaviorTypeName];
	if (behaviorType && !String.isEmpty(containerID)) {
		var behavior = new behaviorType(containerID);
	}
}

SM.Behavior.RAMP_AdjustMathColumn = function(containerID) {
	this.cssClass = "math";
	this.re = /^\s*(Math)\s+(Proficiency)\s*$/i;
	var container = $get(containerID);
	
	if (container) {
		var els = DomElement.getElementsByClassName(container, "*", "math");
		if (els.length) {
			var cell = els[0];
			var content = cell.innerHTML;
			if (this.re.test(content)) {
				content = content.replace(this.re, "$1<br />$2");
				cell.innerHTML = content;				
			}			
		}
	}
}

FitTitleHeight = function() { 
	var divList = document.getElementsByTagName('div');
	var dHeight = 0;
	var divID;
	
	for (var i=0; i < divList.length; i++)
	{
		divID = divList[i];
		
		if(!$notExistOrNull(divID.className) && (divID.className == 'sclTtlClass'))  
		{
			(divID.offsetHeight < dHeight)?null:(dHeight = divID.offsetHeight);
		}
	}
	
	for (var i=0; i < divList.length; i++)
	{
		divID = divList[i];
		
		if(!$notExistOrNull(divID.className) && (divID.className == 'sclTtlClass'))  
		{
			divID.style.height = dHeight + 'px';
		}
	}
}

AddExamsStars = function() {
	var tblElements = document.getElementsByTagName('TABLE');
	var innerhtml;

	for(i = 0; i < tblElements.length; i++)
	{
		if(tblElements[i].className == "chartContainer chartTable" && ((innerhtml = tblElements[i].innerHTML) != ""))
		{
			for(n = 0; n < tblElements[i].childNodes.length; n++)
			{
				for(m = 0; m < tblElements[i].childNodes[n].childNodes.length; m++)
				{
					for(g = 0; g < tblElements[i].childNodes[n].childNodes[m].childNodes.length; g++)
					{
						if (typeof(tblElements[i].childNodes[n].childNodes[m].childNodes[g].innerHTML) != "undefined")
							tblElements[i].childNodes[n].childNodes[m].childNodes[g].innerHTML = tblElements[i].childNodes[n].childNodes[m].childNodes[g].innerHTML.replace(/SAT\sReasoning\sTest\s/g, "SAT Reasoning Test* ").replace(/PSAT\/NMSQT\s/g,	"PSAT/NMSQT** ").replace(/AP\s/g, "AP*** ");
					}
				}
			}
			break;
		}
	}
}

window.onload = function() {
	FitTitleHeight();
	AddExamsStars();
}

var Page_IsValid = true;
// SM.Validation
SM.Validation = {
	nonStylableTypes: ["file", "checkbox", "select-multiple", "select-one"],
	init : SM_Validation_Init,
	initValidator : SM_Validation_initValidator,
	initControl : SM_Validation_initControl,
	validateRequired : SM_Validation_validateRequired,
	validateExpression : SM_Validation_validateExpression,
	getControlValue : SM_Validation_getControlValue,
	getValueRecursive : SM_Validation_getValueRecursive,
	getOutlineControl: SM_Validation_getOutlineControl,
	updateStatus : SM_Validation_setDisplay,
	validate : SM_Validation_validate,
	Validate : SM_Validation_Validate
};

function SM_Validation_Init() {
	if ($exist(Validators)) {
		var validator = null;
	    for (var i=0, length = Validators.length; i < length; i++) {
	        validator = Validators[i];
			this.initValidator(validator);				
			if (!validator.isValid) {
				Page_IsValid = false;
			}				
	        this.initControl(validator.control, validator);
	    }
	}
}

function SM_Validation_initValidator(validator) {
	validator.control = validator.getAttribute("control");
	var methodAttribute = validator.getAttribute("method");
	var	method = this[methodAttribute];
	if (!method) {
		method = window[methodAttribute];
	}
	var onErr = validator.getAttribute("onError");
	if (onErr)
		validator.onError = window[onErr];
			
	validator.method = method;
	validator.isValid = validator.getAttribute("isValid") == "true";
	validator.display = validator.getAttribute("display");
	validator.errorCssClass = validator.getAttribute("errorCssClass");			
	validator.initialValue = validator.getAttribute("initialValue");
	validator.text = validator.getAttribute("text");
	validator.expression = validator.getAttribute("expression");
	validator.ignored = validator.getAttribute("ignored") == "true";
}

function SM_Validation_initControl(id, validator) {
	var control = $get(id);
	if (control) {
		if ($notExistOrNull(control.Validators)) {
			control.Validators = [];
		}
		control.Validators[control.Validators.length] = validator;
	}		
}

function SM_Validation_validateRequired(validator) {
	var value = SM.Validation.getControlValue(validator.control).trim();
	return value != validator.initialValue;
}

function SM_Validation_validateExpression(validator) {
	var value = SM.Validation.getControlValue(validator.control);
	var nameRx = new RegExp(validator.expression,"i");
	var matches = nameRx.exec(value);
	return  matches != null;
}

function SM_Validation_getControlValue(id) {
	var control = $get(id);
	var value = "";

    if (typeof(control.value) == "string" && control.type != "radio") {
        return control.type == "checkbox" ? control.checked.toString() : control.value;
    }	    
	return SM.Validation.getValueRecursive(control);		
}		

function SM_Validation_getValueRecursive(control) {
	
    if (typeof(control.value) == "string" && (control.type != "radio" || control.checked == true)) {
        return control.value;
    }	
    var value;
	
    for (var i = 0, length = control.childNodes.length; i < length; i++) {
        value = SM.Validation.getValueRecursive(control.childNodes[i]);
        if (value != "") return value;
    }	
    return "";	
}	

function SM_Validation_setDisplay(validator) {

	var isValid = validator.isValid;

	if (!isValid && validator.onError) {
		validator.onError(validator);				
	}
		
	var control = $get(validator.control);
	  if (control) {
		var element = this.getOutlineControl(control);
		var method = isValid ? "remove" : "add";
		DomElement[method + "CssClass"](element, validator.errorCssClass);
	}
		
    if (typeof(validator.display) == "string") {    
        if (validator.display == "None") {
            return;
        }
        if (validator.display == "Dynamic") {
            validator.style.display = validator.isValid ? "none" : "";
            return;
        }			
    }
    validator.style.visibility = validator.isValid ? "hidden" : "visible";
}

function SM_Validation_getOutlineControl(control){
	var element = this.nonStylableTypes.indexOf(control.type) != -1 ? control.parentNode : control;
	var outline = null;
	
	if (control._outline) {
		outline = control._outline;
	}
	else if (control.type == "text" && document.defaultView &&
			document.defaultView.getComputedStyle) {
		var style = document.defaultView.getComputedStyle(control, "");
		var borderWidth = parseInt(style.borderTopWidth);
		// Safari < 3.0 is the only browser reporting zero border width
		// and that is what we need to fix
		if (!borderWidth && !control._outline) {
			outline = control.document.createElement("div");
			outline.style.position = "absolute";
			outline.style.zIndex = -1;
			control.document.body.appendChild(outline);
			control._outline = outline;
		}
	}
	
	if (outline != null) {
		var location = DomElement.getLocation(control);		
		outline.style.top = location.y - 2 + "px";
		outline.style.left = location.x - 2 + "px";
		
		outline.style.width = control.clientWidth + 'px';
		outline.style.height = control.clientHeight + 'px';
		element = outline;
	}	
	return element;
}

function SM_Validation_validate(validator) {
	validator.isValid = true;
    if (validator.method) {
		validator.isValid = validator.method(validator);
    }
	this.updateStatus(validator);
		
	return validator.isValid;	    
}

function SM_Validation_Validate() {
	Page_IsValid = true;
	var validator;
	if ($exist(Validators)) {
		for (var i=0, length = Validators.length; i < length; i++) {
			var validator = Validators[i];
			if (!validator.ignored) {
				var isValid = this.validate(validator);
				if (!isValid) {
					Page_IsValid = false;
				}				
			}
		}
	}
}