
// IE FIX for document.getElementById.  By default ie returns both named and ided elements from getelement by id
if (/msie/i.test (navigator.userAgent)) {  // only override IE
 	document.nativeGetElementById = document.getElementById;
	 document.getElementById = function(id) {
		var elem = document.nativeGetElementById(id);
  		if(elem) {
			   // make sure that it is a valid match on id
			   if(elem.attributes['id'].value.toLowerCase() == id.toLowerCase())	{
				    return elem;
			   } else if (document.all[id].length) {
				   for(var i=1;i<document.all[id].length;i++) {
					     if(document.all[id][i].attributes['id'].value.toLowerCase() == id.toLowerCase()) {
  						    return document.all[id][i];
					     }
				    }
			   } else {
					if(document.all[id].attributes['id'].value.toLowerCase() == id.toLowerCase()) {
					    return document.all[id];
				    }
			   }
		  }
		return null;
	 };
}



//global DF namespace
window.DF = window.DF || {};


// * Returns the namespace specified and creates it if it doesn't exist
// *
// * DF.namespace("property.package");
// * DF.namespace("DF.property.package");
// *
// * Either of the above would create DF.property, then
// * DF.property.package
// *
// * Note: No reserved words as the property or package names!
// *
// * @param  {String} ns The name of the namespace
// * @return {Object} A reference to the namespace object
DF.namespace = function(ns) {

    if (!ns || !ns.length) {
        return null;
    }

    var levels = ns.split(".");
    var nsobj = DF;

    // ignore 'DF' on front, since it's already specified
    for (var i=(levels[0] == "DF") ? 1 : 0; i<levels.length; ++i) {
        nsobj[levels[i]] = nsobj[levels[i]] || {};
        nsobj = nsobj[levels[i]];
    }

    return nsobj;
};

//* ******************************************************** 
//* general language extensions and helpers 
//* ******************************************************** 

// Creates a callback bound to the arguments specified
Function.prototype.createCallback = function(/*args...*/){
    // make args available, in function below
    var args = arguments;
    var method = this;
    return function() {
        return method.apply(window, args);
    }
};


// * Creates a delegate (callback) scoped to obj.  If args are specifed then they
// * override the delegate's callee specified arguments.  You probably want to use
// * the callee's arguments.
// * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
// * @param {Object} obj The object for which the scope is set
// * @param {<i>Array</i>} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
// * @return {Function} The new function
Function.prototype.createDelegate = function(obj, args){
    var method = this;
    return function() {
        return method.apply(obj, args || arguments);
    }
};

// * Chain function calls of original function then the passed in function.
// * The resulting function returns the results of the original function.
// * The passed func is called with the parameters of the original function.
// * If you want to specify seperate args for your func, pass a delegate as func.
// *
// * @param {Function} func The function to sequence
// * @param {<i>Object</i>} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
// * @return {Function} The new function
Function.prototype.createChain = function(func, scope){
    if(typeof func != 'function'){
        return this;
    }
    var method = this;
    return function() {
        var retval = method.apply(this || window, arguments);
        func.apply(scope || this || window, arguments);
        return retval;
    }
};


Array.prototype.binarySearchContains = function(val, startIdx, endIdx) 
{
	var i = 0;
	var s = startIdx > -1 ? startIdx : 0;
	var e = endIdx > -2 ? endIdx : this.length;
	e = e < s ? s : e;
	var midP = Math.floor(((e - s) / 2) + s);
	//if(this[midP] == val || this[s] == val || this[e] == val){return true;}
	if(this[midP] == val){return true;}
	else if(s == e){return false;}
	else if(this[midP] < val){return this.binarySearchContains(val, midP+1, e);}
	else{return this.binarySearchContains(val, s, midP-1);}
}

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); };

String.prototype.capitalizeFirst = function()
{
	return this.length > 1 ? this.substring(0,1).toUpperCase() + this.substring(1) : this;
}

DF.namespace('DF.string');

DF.string.endsWith = function(src, sub){
	if (!src || !sub || src.length == 0 || sub.length == 0 || src.length < sub.length)
		return false;

	for (var i = 0; i < src.length && i < sub.length; i++){
		if (src.charAt(src.length - i - 1) != sub.charAt(sub.length - i - 1))
			return false;
	}
	return true;
};

DF.string.isNullOrEmpty = function(str){
	return (typeof(str)).toLowerCase() != 'string' || str.length == 0;
};

// *********** type checker functions ***********
function isArray(a) {
    return isObject(a) && a.constructor == Array;
};

function isBoolean(a) {
    return typeof a == 'boolean';
};

function isFunction(a) {
    return typeof a == 'function';
};

function isNull(a) {
    return a === null;
};

function isNumber(a) {
    return typeof a == 'number' && isFinite(a);
};

function isObject(a) {
    return (a && typeof a == 'object') || isFunction(a);
};

function isString(a) {
    return typeof a == 'string';
};

function isUndefined(a) {
    return typeof a == 'undefined';
};

function isNullOrEmpty(a) {
	return a == null || a == "";
}

function sortIntegeter(a,b)
{
	return a-b;
}

function getCookie(cName) 
{
	var start = cName + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(start) == 0) return c.substring(start.length,c.length);
	}
	return null;
}


/******************************************
* String Helpers
******************************************/
DF.StartsWith = function(str, chk) 
{
	return str.indexOf(chk) == 0;
}

DF.EndsWith = function(str, chk) 
{
	var ind = str.lastIndexOf(chk);
	return ind+(chk.length) == str.length;
}

/***********************************************
 * DF Helpers*************************
 **********************************************/
DF.convertPixelToInt = function(px)
{
    var cleanVal = px.replace('px','');
    return parseInt(cleanVal);   
};

DF.mouseX = function(e)
{
	 if (document.layers) 
     {
	    return document.body.scrollLeft + e.pageX;
     } 
     else if (document.all) 
     {
		return window.event.clientX + document.documentElement.scrollLeft;
     } 
     else if (document.getElementById) 
     {
	
        return document.body.scrollLeft + e.pageX;
     }
};

DF.mouseY = function(e)
{
	if (document.layers) 
    {
         return document.body.scrollTop + e.pageY;
    } 
    else if (document.all) 
    {
		return window.event.clientY + document.documentElement.scrollTop;
    } 
    else if (document.getElementById) 
    {
        return document.body.scrollTop + e.pageY;
    }
};

DF.mouseYRelative = function (e)
{
    if (document.layers) 
     {
         return e.layerY;
     } 
     else if (document.all) 
     {
        return window.event.offsetY;
     } 
     else if (document.getElementById) 
     {
        return e.layerY;
     }
};

DF.mouseXRelative = function (e)
{
    if (document.layers) 
     {
         return e.layerX;
     } 
     else if (document.all) 
     {
        return window.event.offsetX;
     } 
     else if (document.getElementById) 
     {
        return e.layerX;
     }
};

DF.parseDate = function(dateString)
{
	// takes in a string of the form 11/1/2006 8:00 PM
	var temp = new Date();
	var parts = dateString.split(' ');
	var dateParts = parts[0].split("/");
	var timeParts = parts[1].split(":");
	var month = parseInt(dateParts[0],10) -1; // month is 0 based
	var day = parseInt(dateParts[1],10);
	var year = parseInt(dateParts[2],10);
	
	var hour = parseInt(timeParts[0],10);
	hour = (hour == 12)? (hour - 12) : hour;
	var min = parseInt(timeParts[1],10);
	if(dateString.indexOf("PM") > -1)
	{
		hour = hour < 12 ? hour += 12 : 12;
	}
	temp.setFullYear(year,month,day);
	temp.setHours(hour,min,0,0);
	return temp;
};

// returns YYYYMMDD int from the date passed in.  String output optional.
DF.getYYYYMMDD = function(date, stringOut) {
	var intOutput = true;
	if (stringOut == true) { intOutput = false; }
		
	var iYear = date.getFullYear();
	var iMonth = date.getMonth() +1;
	var iDay = date.getDate();
	
	var sMonth = (iMonth<10)?"0":"";
	sMonth += iMonth;
	var sDay = (iDay<10)?"0":"";
	sDay += iDay;
	
	var sTodayYMD = "" + iYear + sMonth + sDay;
	
	if (intOutput) { return parseInt(sTodayYMD); }
	else { return sTodayYMD; }
}

// Converts an ISO 8601 timestamp (or the defacto format) to a javascript Date object.
// If the "Z" or "[+-]HH:MM" is left off, the local time will be used.
// Accepts: YYYY-MM-DD hh:mm:ss OR the correct YYYY-MM-DDThh:mm:ssZ
DF.parseISODate = function (str) {
	var isoRegexp = /(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/;
    str = str + "";
    if (typeof(str) != "string" || str.length === 0) {
        return null;
    }
    var res = str.match(isoRegexp);
    if (typeof(res) == "undefined" || res === null) {
        return null;
    }
    var year, month, day, hour, min, sec, msec;
    year = parseInt(res[1], 10);
    if (typeof(res[2]) == "undefined" || res[2] === '') {
        return new Date(year);
    }
    month = parseInt(res[2], 10) - 1;
    day = parseInt(res[3], 10);
    if (typeof(res[4]) == "undefined" || res[4] === '') {
        return new Date(year, month, day);
    }
    hour = parseInt(res[4], 10);
    min = parseInt(res[5], 10);
    sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0;
    if (typeof(res[7]) != "undefined" && res[7] !== '') {
        msec = Math.round(1000.0 * parseFloat("0." + res[7]));
    } else {
        msec = 0;
    }
    if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) {
        return new Date(year, month, day, hour, min, sec, msec);
    }
    var ofs;
    if (typeof(res[9]) != "undefined" && res[9] !== '') {
        ofs = parseInt(res[10], 10) * 3600000;
        if (typeof(res[11]) != "undefined" && res[11] !== '') {
            ofs += parseInt(res[11], 10) * 60000;
        }
        if (res[9] == "-") {
            ofs = -ofs;
        }
    } else {
        ofs = 0;
    }
    return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs);
};

DF.$ = function(el){
	if (el){
		if (DF.Dom.isEl(el)) return el;
		if (!DF.string.isNullOrEmpty(el)) return document.getElementById(el);
	}
	return null;
};

DF.$F = function(el){
	var field = DF.$(el);
	if(field != null)
	{
		if(field.value)
			return field.value;
		else
			return "";
	}
	field = document.getElementsByName(el);
	if(field.length > 0)
	{
		for(var i = 0; i < field.length; i++)
		{
			var f = field[i];
			if(f.checked == true)
			{
				return f.value;
			}
		}
		return "";
	}
}
$ = DF.$; // alias
$F = DF.$F;

DF.daysOfWeek = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
DF.monthAbrevLiterals = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
DF.monthLiterals = ["January","February","March","April","May","June","July","August","September","October","November","December"];
	    
DF.evalJson = function(jsonText) { return eval("(" + jsonText + ")"); };

DF.convDateToDir = function(date) {
	return date.getFullYear() + ((date.getMonth()+1) < 10 ? "0" : "") + (date.getMonth() + 1) + (date.getDate() < 10 ? "0" : "") + date.getDate();
};

DF.elementScreenPosition = function(obj)
{
//	var offsetX = 8; // body offset margin
//	var offsetY = 8; // body offset margin
//	
//	var offsetElem = element;
//	while(offsetElem != document.body)
//	{
//		offsetX += offsetElem.offsetLeft;
//		offsetY += offsetElem.offsetTop;
//		offsetElem = offsetElem.parentNode;
//	}
	var curleft = curtop = window.event ? 0 : 8;
	if (obj.offsetParent) {
		curleft += obj.offsetLeft
		curtop += obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
	}

	return {"offsetX": curleft, "offsetY" : curtop};
};

// Set opacity of an element from 0 to 100
DF.setOpacity = function(domElement, val)
{
	val = val < 0 ? 0 : val;
	val = val > 99 ? 100 : val;
	domElement.style.opacity = val / 100.0;
	domElement.style.filter = 'alpha(opacity=' + val + ')';
};

//******************** CONNECTION **********************
DF.namespace("DF.connection");

DF.connection = {
	_xmlReqType : ['MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP','Microsoft.XMLHTTP'],
	asyncConnect : function(type, uri, delegateCB, disableCache, postData)
	{
		var conn = null;
		try 
		{
			conn = new XMLHttpRequest();
		}
		catch(e)
		{
			for(var i = 0; i < this._xmlReqType.length; i++)
			{
				try
				{
					conn = new ActiveXObject(this._xmlReqType[i]);
					if(conn)
					{
						break;
					}
				}
				catch(e)
				{
					conn = null;
				}
			}
		}
		if(conn) 
		{
			conn.onreadystatechange = this.connectionUpdateHandler.createDelegate(this,[conn,delegateCB]);
			conn.open(type, uri, true);
			if(disableCache)
			{
				var d = new Date();
				d.setYear(100);
				conn.setRequestHeader("If-Modified-Since", d.toString());
			}
			if(postData)
			{
				conn.setRequestHeader("Content-length", postData.length);
				conn.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
				conn.setRequestHeader("Connection", "close");
			}
			conn.send(postData?postData : null);
		}
	},
	connectionUpdateHandler : function(conn, cb)
	{
		try
		{
			if (conn.readyState == 4) 
			{
				if ((conn.status == 200 || conn.status == 202) && cb) 
				{
					cb({"status":conn.status,"ok":true,"responseText" : conn.responseText, "argument": cb.argument});
				} 
				else if(cb)
				{
					cb({"status":conn.status,"ok":false,"responseText" : conn.responseText, "argument": cb.argument});
				}
			}
		}
		catch(e)
		{
			// something blew up in FF
			if(cb)
			{
				cb({"status":"Status Unavailable","ok":false,"responseText" : null, "argument": cb.argument});
			}
		}
	}
};


//******************** EVENT **********************
DF.namespace("DF.evt");


var DOM_READY = false;

DF.evt.DomLoadEvents = [];

DF.evt.AddDomLoadEvent = function(fn) 
{
	//console.log("DF.evt.AddDomLoadEvent");
	if(DOM_READY)
	{
	    window.setTimeout(fn.createDelegate(window,["onDomReady"]),0);
	    //fn();
	}
	else
	{
	    DF.evt.DomLoadEvents.push(fn);
	}
};

DF.evt.AddDomLoadEventReaper = function()
{
	//console.log("DF.evt.AddDomLoadEventReaper");
	var eventsFired = false;
	var fireEvts = function()
	{
		//console.log("fireEvts");
	    while(DF.evt.DomLoadEvents.length > 0)
	    {
		    var delegate = DF.evt.DomLoadEvents.pop()
		    window.setTimeout(delegate.createDelegate(window,["onDomReady"]),0);
		    //delegate();
	    }
	};

	var readyState = function()
	{
		//console.log("readyState");
		if(document.readyState == "interactive" || document.readyState == "complete"){fireEvts();}
	};
	
	if(document.addEventListener)
	{
		// typical of Mozilla
		document.addEventListener("DOMContentLoaded", fireEvts, false);
	}
	else
	{	// fall back to IE
		document.onreadystatechange = function()
			{
				if (document.readyState == "complete")
					readyState(fireEvts); 
					
				return false;
			};
	}
	
	if (/WebKit/i.test(navigator.userAgent)) 	// check for safari
	{
		load_timer = setInterval(
			function() 
			{
				if (/loaded|complete/.test(document.readyState))
					readyState(fireEvts);
			}, 10);
	}
	
	
}();

DF.evt.AddDomLoadEvent(function(){DOM_READY = true;});

DF.evt.AddLoadEvent = function(func) 
{
	var oldOnLoad = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldOnLoad();
			func();
		}
	}
};


DF.evt.AddUnloadEvent = function(fn) {
	var curr = window.onunload;
	if (typeof(window.onunload) != 'function') {
		window.onunload = fn;
	} 
	else {
		window.onunload = function() {
			curr();
			fn();
		}
	}
};

DF.evt.CancelEvent = function(e) {
	if (typeof(e.preventDefault) == 'function')
		e.preventDefault();
	else
		e.preventDefault = true;
	if (typeof(e.cancelBubble) == 'function')
		e.cancelBubble();
	else
		e.cancelBubble = true;
	if (typeof(e.cancelEvent) == 'function')
		e.cancelEvent();
	else
		e.cancelEvent = true;
	if (typeof(e.stopPropagation) == 'function')
		e.stopPropagation();
	else
		e.stopPropagation = true;
	return false;
}

DF.evt.CustomEvent = function(type) {
    this.type = type;
    this.scope = window;
    this.subscribers = [];
};

DF.evt.CustomEvent.prototype = {
    subscribe: function(fn) {
        this.subscribers.push( new DF.evt.Subscriber(fn) );
    },

    unsubscribe: function(fn) {
        var found = false;
        for (var i=0, len=this.subscribers.length; i<len; ++i) {
            var s = this.subscribers[i];
            if (s && s.contains(fn)) {
                this._delete(i);
                found = true;
            }
        }
        return found;
    },
    fire: function() {
        var len=this.subscribers.length;
        if (!len) {
            return;
        }

        var args = [];

        for (var i=0; i<arguments.length; ++i) {
            args.push(arguments[i]);
        }

        for (i=0; i<len; ++i) {
            var s = this.subscribers[i];
            if (s) {
                s.fn.call(window, this.type, args);
            }
        }
    },
    unsubscribeAll: function() {
        for (var i=0, len=this.subscribers.length; i<len; ++i) {
            this._delete(len - 1 - i);
        }
    },
    _delete: function(index) {
        var s = this.subscribers[index];
        if (s) {
            delete s.fn;
        }
        this.subscribers.splice(index, 1);
    }
};

//must call with a wrapped delegate
DF.evt.Subscriber = function(fn) {
    this.fn = fn;
    this.obj = null;
    this.override = false;
};

//must call with a wrapped delegate for scoping
DF.evt.Subscriber.prototype.contains = function(fn) {
    return (this.fn == fn);
};


// Load once
if (!DF.evt.Event) {
    DF.evt.Event = function() {
        var listeners = [];

        return {
            EL: 0,
            TYPE: 1,
            FN: 2,

            //el : id or element Obj
            //wrap up your own functions, no delayed attaching, no load/unload handling, DOM2 events only!
            addListener: function(el, sType, fn) {
                if (!fn || !fn.call) {
                    return false;
                }

                if (typeof el == "string") {
                    el = document.getElementById(el);
                }

                if (!el) {
                    return false;
                }

                var li = [el, sType, fn];
                var index = listeners.length;
                listeners[index] = li;

                //DOM2 events reg
                if (el.addEventListener) { //Non-IE

                    el.addEventListener(sType, fn, false);
                }
                else if (el.attachEvent) { // IE

                    el.attachEvent("on" + sType, fn);
                }

                return true;              
            },

            //optional index, overrides listener lookup by fn reference
            removeListener: function(el, sType, fn, index) {

                if (!fn || !fn.call) {
                    return false;
                }

                if (typeof el == "string") { //assumed element id if string
                    el = document.getElementById(el);
                } 

                var listener = null;
  
                if ("undefined" == typeof index) { //optional index arg
                    index = this._getListenerIndex(el, sType, fn);
                }
                if (index >= 0) {
                    listener = listeners[index];
                }
                if (!el || !listener) {
                    return false;
                }

				//DOM2 event unloading
                if (el.removeEventListener) {
                    el.removeEventListener(sType, listener[this.FN], false);
                }
                else if (el.detachEvent) { //IE
                    el.detachEvent("on" + sType, listener[this.FN]);
                }

                delete listeners[index][this.FN];
                listeners.splice(index, 1);

                return true;
            },
            
            _getListenerIndex: function(el, sType, fn) {
                for (var i=0,len=listeners.length; i<len; ++i) {
                    var li = listeners[i];
                    if ( li                 && 
                         li[this.FN] == fn  && 
                         li[this.EL] == el  && 
                         li[this.TYPE] == sType ) {
                        return i;
                    }
                }

                return -1;
            },

            _unload: function() {
                if (listeners && listeners.length > 0) {
                    var j = listeners.length;
                    while (j) {
                        var index = j-1;
                        l = listeners[index];
                        if (l) {
                            this.removeListener(l[this.EL], l[this.TYPE], l[this.FN], index);
                        } 
                        j = j - 1;
                    }
                }
            }
        };
    }();
}


//******************** STYLES **********************
DF.namespace('DF.pguide.styles');

DF.pguide.styles.styleController = function()
{
	this.sSheet = null;
	this.styleRules = [];
	this.safari = (browserCheck.getBrowser().id == 'Safari');
	this.safariDeprecated = this.safari && (browserCheck.getVersion(browserCheck.getBrowser()) < 400);
};

DF.pguide.styles.styleController.prototype = 
{
	init : function()
	{
		// get the style block from the page for general rules
		this.getSheet();
		if(document.all)
		{
			for(var i = 0; i < this.sSheet.rules.length; i++)
			{
				var cssRule = this.sSheet.rules[i];
				if(cssRule.selectorText == null)
					continue;
				this.styleRules[cssRule.selectorText.toLowerCase()] = cssRule;
			}
		}
		else
		{
			for(var i = 0; i < this.sSheet.cssRules.length; i++)
			{
				var cssRule = this.sSheet.cssRules[i];
				if(cssRule.selectorText == null)
					continue;
				this.styleRules[cssRule.selectorText.toLowerCase()] = cssRule;
			}
		}
	},
	getSheet : function()
	{
		if(this.safari)
		{
			this.sSheet = document.styleSheets[0];
			return;
		}
		for(var i = 0; i < document.styleSheets.length; i++)
		{
			var sheet = document.styleSheets[i];
			if(sheet.ownerNode != null && sheet.ownerNode.getAttribute('name') == 'DFStyleController')
			{
				this.sSheet = sheet;
				break;
			}
			else if(sheet.owningElement != null && sheet.owningElement.id == 'DFStyleController')
			{
				this.sSheet = sheet;
				break;
			}
		}
		if(!this.sSheet)
		{
			this.sSheet = document.styleSheets[0];
		}
	},
	setStyle : function(styleName, val, idx) 
	{	
		if(!this.styleRules[styleName.toLowerCase()])
		{
			if(!this.createRule(styleName, val, idx))
			{
				return;
			}
		}
		var cssRule = this.styleRules[styleName.toLowerCase()];
		cssRule.style.cssText = val;
	},
	createRule : function(styleName, value, idx)
	{
//		debugger;
		if(document.all)
		{
			var idx = (idx != null && idx >= 0 ? idx : this.sSheet.rules.length-1);
			this.sSheet.addRule(styleName,'{' + value + '}', idx);
			this.styleRules[styleName.toLowerCase()] = this.sSheet.rules[idx];
		}
		else
		{
			var index = this.sSheet.insertRule(styleName + '{' + value + '}', (idx != null && idx >= 0 ? idx : this.sSheet.cssRules.length));
			this.styleRules[styleName.toLowerCase()] = this.sSheet.cssRules[index];
		}
		return this.safari;
	},
	flush : function()
	{
		this.sSheet = null;
		delete this.styleRules;
		this.styleRules = [];
	}
};

DF.namespace('DF.browserInformation');

DF.browserInformation = function()
{
	this.init();
};

DF.browserInformation.prototype = {
	init: function () 
	{
		this.browser = this.getBrowser();
		this.version = this.getVersion(this.browser);
		this.supported = (this.browser  && this.version) ? (this.browser.versMin <= this.version) : false;
	},
	getBrowser : function () 
	{
		for (var i=0;i<this.supportedBrowsers.length;i++)	
		{
			var dataString = this.supportedBrowsers[i].string;
			if (dataString) 
			{
				if (dataString.indexOf(this.supportedBrowsers[i].searchStr) != -1)
				{
					return this.supportedBrowsers[i];
				}
			}
		}
	},
	getVersion: function (browser) 
	{
		if(!browser)
		{
			return -1;
		}
		
		var version = navigator.userAgent;
			
		var index = version.indexOf(browser.versionStr || browser.id);
		if (index != -1)
		{
			var browserVersion = parseFloat(version.substring(index+(browser.versionStr || browser.id).length+1));
			if(browserVersion)
			{
				return browserVersion;
			}
			
		}
		
		version = navigator.appVersion;
		index = version.indexOf(browser.versionStr || browser.id);
		if (index != -1)
		{
			var browserVersion = parseFloat(version.substring(index+(browser.versionStr || browser.id).length+1));
			if(browserVersion)
			{
				return browserVersion;
			}
			
		}
		return -1;
	},
	supportedBrowsers: 
	[
		{
			string: navigator.vendor,
			searchStr: "Apple",
			id: "Safari",
			versMin : 1.3
		},
		{
			string: navigator.userAgent,
			searchStr: "Firefox",
			id: "Firefox",
			versMin : 1.1
		},
		{
			string: navigator.userAgent,
			searchStr: "MSIE",
			id: "Explorer",
			versionStr : "MSIE",
			versMin : 6
		},
		{
			string: navigator.userAgent,
			searchStr: "Mozilla",
			id: "Netscape",
			versMin : 7.2
		}
	]	
};

DF.namespace('DF.Modules');

// loadCallback is an optional callback that's called when the module loading response
// is received. Its arguments are the module name and the asyncConnect callback param.
// It's called whether loading succeeds or fails.
DF.Modules.Module = function(name,url,loadCallback) {
	this._name = name;
	this._url = url;
	this._loadCallback = loadCallback;
}

DF.Modules.Module.prototype = {
	refresh: function(cbDelegate) {
		this._cbDelegate = cbDelegate;
		DF.connection.asyncConnect("GET",this._url,this.callBack.createDelegate(this), true, "");
	},
	callBack: function(result) {
		if(result.ok == true)
		{
			var elements = document.getElementsByName(this._name);
			for (var i = 0; i < elements.length; i++) {
				elements[i].innerHTML = result.responseText;				
				var sTags = elements[i].getElementsByTagName('script');
				for(var j=0; j<sTags.length; j++)
				{
					var nTag = document.createElement('script');
					nTag.text = sTags[j].text;
					elements[i].appendChild(nTag);
					j++;
				}
			}
			if(this._cbDelegate != null)
			{
				this._cbDelegate();
			}
		}
		
		if(this._loadCallback != null)
		{
			this._loadCallback(this._name, result);
		}
	},
	getModuleElement: function() {
		return document.getElementsByName(this._name);
	}
}
if(!DF.Modules.ModuleCollection) { // only do this once
DF.Modules.ModuleCollection = function() {
	var items = new Array();
	var length = 0;	
	var count = 0;
	return {
		add: function (module) {
			items[length] = module;
			length++;
			module.refresh(this.callBack.createDelegate(this));
		},
		refresh: function(cbDelegate) {
			count = 0;
			this._cbDelegate = cbDelegate;
			for(var i = 0; i < items.length; i++)
			{
				var item = items[i];
				item.refresh(this.callBack.createDelegate(this));
			}
		},
		callBack: function() {
			count++;
			if(count == length && this._cbDelegate != null)
			{
				this._cbDelegate();
			}
		},
		getItem: function (index) {
			return items[index];
		},
		getLength: function () {
			return length;
		},
		testLoad: function() {
			return count == length;
		},
		setCompleteDelegate: function(cbDelegate) {
			this._cbDelegate = cbDelegate;
		}
	}
}();

DF.namespace('DF.Ui.PNGFix');
// * Fixes PNG transparency for images in IE6
// *
// * @rootElement {Object} optional starting point for fix up
DF.Ui.fixPngImages = function(rootElement) {
	var browserInfo = new DF.browserInformation();
	if(browserInfo.getBrowser().versionStr == "MSIE" && browserInfo.getVersion(browserInfo.browser) < 7)
	{
		rootElement = rootElement == null ? document : rootElement;
		var imgList = rootElement.getElementsByTagName("img");
		var regEx = /\.png$/;
		var list = imgList.length + "\n";
		for(var i = 0; i < imgList.length; i++)
		{
			var img = imgList[i]
			var result = img.src.match(regEx);			
			if(result != null && img.style.display != "none")
			{
				var placeHolder = document.createElement("div");
				placeHolder.style.width = img.clientWidth + "px";
				placeHolder.style.height = img.clientHeight + "px";
				placeHolder.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + img.src + "',sizingMethod='scale')";
				img.parentElement.appendChild(placeHolder);
				img.style.display = "none";		
			}
		}		
	}
}

// * Fixes PNG transparency for backgrounds in IE6
// *
// * @tagName {String} name of the type of tags to fix up
// * @rootElement {Object} optional starting point for fix up
DF.Ui.fixPngBackgrounds = function(tagName, rootElement) {
	var browserInfo = new DF.browserInformation();
	if(browserInfo.getBrowser().versionStr == "MSIE" &&  browserInfo.getVersion(browserInfo.browser) < 7)
	{
		rootElement = rootElement == null ? document : rootElement;
		var nodeList = rootElement.getElementsByTagName(tagName);
		var regEx = /\.png/;
		var urlReg = /url\(([^\)]+)\)$/
		for(var i = 0 ; i < nodeList.length; i++)
		{
			var node = nodeList[i];
			var result = node.style.backgroundImage.match(regEx);			
            			
			if(result != null)
			{				
				result = node.style.backgroundImage.match(urlReg);
				node.style.backgroundImage = "";
				node.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + result[1] + "',sizingMethod='scale')";
			}
		}
	}
}

DF.namespace('DF.Util.Cookies');
DF.Util.Cookies.getCookie = function(key1,key2) {       

	var sCookie = new String(document.cookie);
	//alert(sCookie)
	if(key1 != null)
	{
		var aCList = sCookie.split('; ');
		for(var i = 0;i < aCList.length;i++)
		{
			sCookie = aCList[i];
			var oReg = new RegExp("(^"+key1+"=)(.*)","ig");
			var aResult = oReg.exec(sCookie);
			if(aResult != null)
			{
				sCookie = RegExp.$2;
				if(key2 != null)
				{
					aCList = sCookie.split("&");
					for(var i = 0;i < aCList.length;i++)
					{
						sCookie = aCList[i];
						var oReg = new RegExp("(^"+key2+"=)(.*)","ig");
						var aResult = oReg.exec(sCookie);;
						if(aResult != null)
						{
							sCookie = unescape(RegExp.$2);
							break;
						}else {
							sCookie = false;
						}
					}
				}
				break;
			} else {
				sCookie = false;
			}
		}
	}
	return sCookie;
}}
DF.Util.Cookies.deleteCookie = function(sName, sSub)
{
	// cookies are separated by semicolons
	var aCookie = document.cookie.split("; ");
	for (var i=0; i < aCookie.length; i++)
	{
		// a name/value pair (a crumb) is separated by an equal sign
		var aCrumb = aCookie[i].split("=");
		if (sName == aCrumb[0]) 
		{
			// Get cookie substring
			var sCookieSubString = aCookie[i].substring(aCookie[i].indexOf('='),aCookie[i].length);
			
			// Get index of sSub
			var nSubIndex = sCookieSubString.indexOf(sSub);
			if(nSubIndex != -1)
			{
				var nNextIndex = sCookieSubString.substring(nSubIndex, sCookieSubString.length).indexOf('&');
				// is last key in cookie
				if(nNextIndex == -1)
				{
					nNextIndex = sCookieSubString.length;
				
					// Find possible leading &
					if(sCookieSubString.charAt(nSubIndex - 1) == '&')
					{
						nSubIndex = nSubIndex - 1;
					}
				}
				else
				{
					nNextIndex = nNextIndex + nSubIndex + 1
				}
				
				var sReplaceVal = sCookieSubString.substring(nSubIndex, nNextIndex);
				
				// Replace value
				sCookieSubString = sCookieSubString.replace(sReplaceVal,"");

				// If cookie is now empty, delete whole cookie
				if(sCookieSubString.length == 0)
				{
					document.cookie = sName + "=; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
				}
				else
				{
					document.cookie = sName + sCookieSubString + "; path=/";
				}
				
				return true;
			}
		}
	}

	// a cookie with the requested name does not exist
	return false;
}
DF.Util.FormToParams = function(formElement) { 
	// load parameters from a form to query string
	var sParams = "";
	if(formElement != null)
	{
		for (var i = 0; i < formElement.elements.length; i++)
		{
			sParam = formElement.elements[i];
			
			if(((sParam.type == "radio" || sParam.type == "checkbox") && sParam.checked == true) || (sParam.type != "radio" && sParam.type != "checkbox") )
			{
				if (sParams != "") sParams = sParams + "&";
				sParams = sParams + sParam.name + "=" + encodeURIComponent(sParam.value);
				
			}
		}
	}
	// alert("sParams=" + sParams);
	return sParams;
}

DF.namespace('DF.array');

DF.array.isArray = function(o){
	if (DF.isSafari)
		return (typeof(o)).toLowerCase() == 'object' && o.length && o.pop && o.push;
	else
		return o.constructor && o.constructor.toString().indexOf('Array') > -1;
}

DF.array.applyFunction = function(array, func, params){
	if (array){
		if (DF.array.isArray(array)){
			for (var i = 0; i < array.length; i++){
				func(array[i], params);
			}
		}else{
			func(array, params);
		}
	}
};

DF.namespace('DF.Dom');

DF.Dom.isEl = function(el){
	return !!(el.nodeType && el.tagName);
};

DF.Dom.getNextSiblingElement = function(el) {
    if(DF.Dom.isEl(el.nextSibling))
    {
        return el.nextSibling;
    }
    else
    {
        return DF.Dom.getNextSiblingElement(el.nextSibling);    
    }  
};

DF.Dom.getFirstChildElement = function(el) {
    if(DF.Dom.isEl(el.firstChild))
    {
        return el.firstChild;
    }
    else
    {
        return DF.Dom.getNextSiblingElement(el.firstChild);    
    }  
};

DF.Dom.getAllElements = function(rootEl, els){
	els = els || [];
	rootEl = $(rootEl) || document.body;
	for (var i = 0; i < rootEl.childNodes.length; i++){
		var child = rootEl.childNodes[i];
		if (DF.Dom.isEl(child)){
			els.push(child);
			DF.Dom.getAllElements(child, els);
		}
	}
	return els;
};

DF.Dom.getElementsByClassName = function(className, tagName, rootEl){
	var els = [];
	if (!DF.string.isNullOrEmpty(className)){
		rootEl = $(rootEl) || document;
		var searchEls = DF.string.isNullOrEmpty(tagName) ? DF.Dom.getAllElements() : rootEl.getElementsByTagName(tagName);
		for (var i = 0; i < searchEls.length; i++){
			var el = searchEls[i];
			if (DF.Dom.hasClass(el, className))
				els.push(el);
		}
	}
	return els;
};

DF.Dom.getNearestAncestorByTag = function(startEl, tagName) {
	tagName = tagName.toLowerCase();
	
	for (var where = startEl.parentNode; where; where = where.parentNode)
	{
		if (where.tagName && where.tagName.toLowerCase() == tagName)
			return where;
	}
	
	// Not found
	return null;
}

DF.Dom.addClass = function(el, className){
	DF.array.applyFunction(el, function(el){
		el = $(el);
		if (!DF.string.isNullOrEmpty(className) && !DF.Dom.hasClass(el, className))
			el.className += ' ' + className;
	});
};

DF.Dom.removeClass = function(el, className){
	DF.array.applyFunction(el, function(el){
		el = $(el);
		if (!DF.string.isNullOrEmpty(className)){
		
			var r = new RegExp('(?:^|[ ]+)'+className+'(?:$|[ ]+)');
			el.className = el.className.replace(r, '');
		}
	});
};

DF.Dom.hasClass = function(el, className){
	if (!DF.string.isNullOrEmpty(className)){
		el = $(el);
		if (el){
			var classes = el.className.split(' ');
			for (var i = 0; i < classes.length; i++){
				if (classes[i] == className)
					return true;
			}
		}
	}
	return false;
};

DF.Dom.removeAttribute = function(el, attr){
	DF.array.applyFunction(el, function(el, attr){ // el array
		DF.array.applyFunction(attr, function(attr, el){ // attr array
			$(el).removeAttribute(attr);
		}, el);
	}, attr);
};

DF.Dom.removeEl = function(el){
	if (el){
		DF.array.applyFunction(el, function(el){
			el = $(el);
			if (el.parentNode) el.parentNode.removeChild(el);
		});
	}
};

DF.Dom.prependEl = function(child, parent){
	child = $(child);
	parent = $(parent);

	if (parent.childNodes.length > 0)
		parent.insertBefore(child, parent.childNodes[0]);
	else
		parent.appendChild(child);
};

/* Many browser-specific issues, especially with IE, can be fixed 
   by forcing the browser to redisplay part of the page. The most 
   sure way to do this is yank the element out of the DOM and put 
   it back in, which is what forceRedisplay does.
   
   node is any DOM node that has a parent.
   browserID and maxBrowserVersion are optional. If specified,
   forceRedisplay won't do anything unless the browser ID (as given
   by DF.browserInformation) is the same as browserID and the
   version is lss than or equal to maxBrowserVersion.                 */
DF.Dom.forceRedisplay = function(node, browserID, maxBrowserVersion)
{
	// Bail out if we don't match the passed-in browser specification
	if (browserID)
	{
		var bi = new DF.browserInformation();
		
		if (bi.getBrowser().id != browserID || (maxBrowserVersion && bi.getVersion() > maxBrowserVersion))
			return;
	}
	
	// IE <= 7 tends to lose the checked state of checkboxes and radio buttons when they are
	// inserted into the DOM. Save a list of checked buttons to restore later.
	var checkedButtons = [];
	var inputs = node.getElementsByTagName("input");
	
	for (var i = 0; i < inputs.length; i++)
	{
		var inp = inputs[i];
		var t = inp.type.toLowerCase();
		
		if ((t == "checkbox" || t == "radio") && inp.checked)
			checkedButtons[checkedButtons.length] = inp;
	}

	var nextsib = node.nextSibling;
	var parent = node.parentNode;
	parent.removeChild(node);
				
	if (nextsib)
		parent.insertBefore(node, nextsib);
	else
		parent.appendChild(node);
		
	// Restore checked buttons
	for (var i = 0; i < checkedButtons.length; i++)
		checkedButtons[i].checked = true;
}

DF.forceSSL = function() {
	if(window.location.protocol == "http:")
		window.location = "https://" + window.location.hostname + window.location.pathname + window.location.search;
};

DF.forceNoSSL = function() {
	if(window.location.protocol == "https:")
		window.location = "http://" + window.location.hostname + window.location.pathname + window.location.search;
}

DF.clearSSL = function(url) {
	if(window.location.protocol == "https:")
		window.location = "http://" + window.location.hostname + url;
}

DF.mapCurrentToSSL = function()
{
	if (window.location.protocol == "http:")
	{
		var currentUrl = window.location.href;
		var hostName = window.location.hostname;
		return "https://" + hostName + currentUrl.substr(currentUrl.indexOf(window.location.hostname) + hostName.length);
	}
	return window.location.href;	
}
