var FSR = {
    'version': '4.6.2',
    'date': '7/27/2009',
    'enabled': true,
    'files': '/gsa/foresee/',
    'id': 'svFnTBMGdHXdvSQW/H7OLg==',
    'sites': [{
        path: /\w+\.(com|org|edu|gov)/,
        cookie: 'session'
         
    }]
};
/************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/
function fsr$setAlive(){
    var time = new Date().getTime();
    document.cookie = 'foresee.alive=' + time + ';path=/' + ';domain=' + FSR.site.domain + ';';
}

(function(){
    if (window != window.top) {
        return;
    }
	
    var sites = FSR.sites;
    for (var i = 0, l = sites.length; i < l; i++) {
		var m;
        if (m = document.location.href.match(sites[i].path)) {
            FSR.siteid = i;
            FSR.site = FSR.sites[FSR.siteid];
			if (!FSR.site.domain) {
				FSR.site.domain = m[0];
			}
			if (!FSR.site.name) {
				FSR.site.name = FSR.site.domain;
			}
            var files = ['files', 'js_files', 'image_files', 'html_files']
            for (var i = 0, len = files.length; i < len; i++) {
                if (FSR.site[files[i]]) {
                    FSR[files[i]] = FSR.site[files[i]];
                }
            }
            break;
        }
    }
    if (!window['fsr$timer']) {
    	fsr$setAlive();
        window['fsr$timer'] = setInterval(fsr$setAlive, 1000);
    }
})();
/*
 Script: fsr$dbug.js
 A wrapper for Firebug console.* statements.
 License:
 http://clientside.cnet.com/wiki/cnet-libraries#license
 */
fsr$dbug = {
    logged: [],
    timers: {},
    firebug: false,
    enabled: false,
    log: function(){
        fsr$dbug.logged.push(arguments);
    },
    nolog: function(msg){
        fsr$dbug.logged.push(arguments);
    },
    time: function(name){
        fsr$dbug.timers[name] = new Date().getTime();
    },
    timeEnd: function(name){
        if (fsr$dbug.timers[name]) {
            var end = new Date().getTime() - fsr$dbug.timers[name];
            fsr$dbug.timers[name] = false;
            fsr$dbug.log('%s: %s', name, end);
        }
        else 
            fsr$dbug.log('no such timer: %s', name);
    },
    enable: function(silent){
        if (fsr$dbug.firebug) {
            try {
                fsr$dbug.enabled = true;
                fsr$dbug.log = function(){
                    (console.debug || console.log).apply(console, arguments);
                };
                fsr$dbug.time = function(){
                    console.time.apply(console, arguments);
                };
                fsr$dbug.timeEnd = function(){
                    console.timeEnd.apply(console, arguments);
                };
                if (!silent) 
                    fsr$dbug.log('enabling dbug');
                for (var i = 0; i < fsr$dbug.logged.length; i++) {
                    fsr$dbug.log.apply(console, fsr$dbug.logged[i]);
                }
                fsr$dbug.logged = [];
            } 
            catch (e) {
                fsr$dbug.enable.delay(400);
            }
        }
    },
    disable: function(){
        if (fsr$dbug.firebug) 
            fsr$dbug.enabled = false;
        fsr$dbug.log = fsr$dbug.nolog;
        fsr$dbug.time = function(){
        };
        fsr$dbug.timeEnd = function(){
        };
    },
    cookie: function(set){
        var value = document.cookie.match('(?:^|;)\\s*fsdebug=([^;]*)');
        var debugCookie = value ? unescape(value[1]) : false;
        if ((debugCookie != 'true' || set) && !set) {
            fsr$dbug.enable();
            fsr$dbug.log('setting debugging cookie');
            var date = new Date();
            date.setTime(date.getTime() + (24 * 60 * 60 * 1000));
            document.cookie = 'fsdebug=true;expires=' + date.toGMTString() + ';path=/;';
        }
        else 
            fsr$dbug.disableCookie();
    },
    disableCookie: function(){
        fsr$dbug.log('disabling debugging cookie');
        document.cookie = 'fsdebug=false;path=/;';
    }
};

(function(){
    if (typeof loadFirebugConsole == 'function') {
        loadFirebugConsole();
    }
    var fb = typeof console != "undefined";
    var debugMethods = ['debug', 'info', 'warn', 'error', 'assert', 'dir', 'dirxml'];
    var otherMethods = ['trace', 'group', 'groupEnd', 'profile', 'profileEnd', 'count'];
    function set(methodList, defaultFunction){
        for (var i = 0; i < methodList.length; i++) {
            fsr$dbug[methodList[i]] = (fb && console[methodList[i]]) ? console[methodList[i]] : defaultFunction;
        }
    };
    set(debugMethods, fsr$dbug.log);
    set(otherMethods, function(){
    });
	
	// Turn on always
    var date = new Date();
    date.setTime(date.getTime() + (24 * 60 * 60 * 1000));
    document.cookie = 'fsdebug=true;expires=' + date.toGMTString() + ';path=/;';
})();
if (typeof console != "undefined" && console.warn) {
    fsr$dbug.firebug = true;
    var value = document.cookie.match('(?:^|;)\\s*fsdebug=([^;]*)');
    var debugCookie = value ? unescape(value[1]) : false;
    if (window.location.href.indexOf("fsdebug=true") > 0 || debugCookie == 'true') 
        fsr$dbug.enable();
    if (debugCookie == 'true') 
        fsr$dbug.log('debugging cookie enabled');
    if (window.location.href.indexOf("fsdebugCookie=true") > 0) {
        fsr$dbug.cookie();
        if (!fsr$dbug.enabled) 
            fsr$dbug.enable();
    }
    if (window.location.href.indexOf("fsdebugCookie=false") > 0) 
        fsr$dbug.disableCookie();
}
/*
Script: Core.js
	MooTools - My Object Oriented JavaScript Tools.

Copyright:
	Copyright (c) 2006-2007 [Valerio Proietti](http://mad4milk.net/).

Code & FSR.Documentation:
	[The MooTools production team](http://mootools.net/developers/).

Inspiration:
	- FSR.Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
	- Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
*/

FSR.Native = function(options){
	options = options || {};

	var afterImplement = options.afterImplement || function(){};
	var generics = options.generics;
	generics = (generics !== false);
	var legacy = options.legacy;
	var initialize = options.initialize;
	var protect = options.protect;
	var name = options.name;

	var object = initialize || legacy;

	object.xconstructor = FSR.Native;
	object.fsr$family = {name: 'native'};
	if (legacy && initialize) object.prototype = legacy.prototype;
	object.prototype.xconstructor = object;

	if (name){
		var family = name.toLowerCase();
		object.prototype.fsr$family = {name: family};
	}

	var add = function(obj, name, method, force){
		if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;
		if (generics) FSR.Native.genericize(obj, name, protect);
		afterImplement.call(obj, name, method);
		return obj;
	};
	
	object.fsr$implement = function(a1, a2, a3){
		if (typeof a1 == 'string') return add(this, a1, a2, a3);
		for (var p in a1) add(this, p, a1[p], a2);
		return this;
	};
	
	object.fsr$alias = function(a1, a2, a3){
		if (typeof a1 == 'string'){
			a1 = this.prototype[a1];
			if (a1) add(this, a2, a1, a3);
		} else {
			for (var a in a1) this.fsr$alias(a, a1[a], a2);
		}
		return this;
	};

	return object;
};

FSR.Native.fsr$implement = function(objects, properties){
	for (var i = 0, l = objects.length; i < l; i++) objects[i].fsr$implement(properties);
};

FSR.Native.genericize = function(object, property, check){
	if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){
		var args = Array.prototype.slice.call(arguments);
		return object.prototype[property].apply(args.shift(), args);
	};
};

FSR.Native.fsr$alias = function(objects, a1, a2, a3){
	for (var i = 0, j = objects.length; i < j; i++) objects[i].fsr$alias(a1, a2, a3);
};

(function(objects){
	for (var name in objects) new FSR.Native({name: name, initialize: objects[name], protect: true, generics: true});
})({'String': String, 'Function': Function, 'Number': Number, 'RegExp': RegExp, 'Date': Date});

FSR.$chk = function (obj){
	return !!(obj || obj === 0);
};

FSR.$clear = function (timer){
	clearTimeout(timer);
	clearInterval(timer);
	return null;
};

FSR.$defined = function (obj){
	return (obj != undefined);
};

FSR.$empty = function (){};

FSR.$arguments = function (i){
	return function(){
		return arguments[i];
	};
};

FSR.$lambda = function (value){
	return (typeof value == 'function') ? value : function(){
		return value;
	};
};

FSR.$extend = function (original, extended){
	for (var key in (extended || {})) original[key] = extended[key];
	return original;
};

FSR.$unlink = function (object){
	var unlinked;
	
	switch (FSR.$type(object)){
		case 'object':
			unlinked = {};
			for (var p in object) unlinked[p] = FSR.$unlink(object[p]);
		break;
		case 'hash':
			unlinked = FSR.$unlink(object.getClean());
		break;
		case 'array':
			unlinked = [];
			for (var i = 0, l = object.length; i < l; i++) unlinked[i] = FSR.$unlink(object[i]);
		break;
		default: return object;
	}
	
	return unlinked;
};

FSR.$merge = function (){
	var mix = {};
	for (var i = 0, l = arguments.length; i < l; i++){
		var object = arguments[i];
		if (FSR.$type(object) != 'object') continue;
		for (var key in object){
			var op = object[key], mp = mix[key];
			mix[key] = (mp && FSR.$type(op) == 'object' && FSR.$type(mp) == 'object') ? FSR.$merge(mp, op) : FSR.$unlink(op);
		}
	}
	return mix;
};

FSR.$pick = function (){
	for (var i = 0, l = arguments.length; i < l; i++){
		if (arguments[i] != undefined) return arguments[i];
	}
	return null;
};

FSR.$random = function (min, max){
	return (Math.random() * (max - min)) + min;
};

FSR.$splat = function (obj){
	var type = FSR.$type(obj);
	return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];
};

FSR.$time = Date.now || function(){
	return new Date().getTime();
};

FSR.$try = function (){
	for (var i = 0, l = arguments.length; i < l; i++){
		try {
			return arguments[i]();
		} catch(e){}
	}
	return null;
};

FSR.$type = function (obj){
	if (obj == undefined) return false;
	if (obj.fsr$family) return (obj.fsr$family.name == 'number' && !isFinite(obj)) ? false : obj.fsr$family.name;

	if (obj.nodeName){
		switch (obj.nodeType){
			case 1: return 'element';
			case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
		}
	} else if (typeof obj.length == 'number'){
		if (obj.callee) return 'arguments';
		else if (obj.item) return 'collection';
	}

	if (FSR.isArray(obj)) return 'array';

	return typeof obj;
};

FSR.isArray = function (obj){
    if (typeof obj == 'object') {
        var criterion = obj.constructor.toString().match(/array/i);
        return (criterion != null);
    }
    return false;
}
 
FSR.Hash = new FSR.Native({

	name: 'Hash',

	initialize: function(object){
		if (FSR.$type(object) == 'hash') object = FSR.$unlink(object.getClean());
		for (var key in object) this[key] = object[key];
		return this;
	}

});

FSR.Hash.fsr$implement({
	getLength: function(){
		var length = 0;
		for (var key in this){
			if (this.hasOwnProperty(key)) length++;
		}
		return length;
	},

	forEach: function(fn, bind){
		for (var key in this){
			if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);
		}
	},
	
	getClean: function(){
		var clean = {};
		for (var key in this){
			if (this.hasOwnProperty(key)) clean[key] = this[key];
		}
		return clean;
	},
	
	empty: function(){
		FSR.Hash.each(this, function(value, key){
			delete this[key];
		}, this);
		return this;
	}
});

FSR.Hash.fsr$alias('forEach', 'each');

FSR.$H = function (object){
	return new FSR.Hash(object);
};

FSR.$each = function (iterable, fn, bind){
	var type = FSR.$type(iterable);
	(type == 'arguments' || type == 'collection' || type == 'array') ? FSR.Array.each(iterable, fn, bind) : FSR.Hash.each(iterable, fn, bind);
};


/*
Script: FSR.Browser.js
	The FSR.Browser Core. Contains FSR.Browser initialization, FSR.Window and FSR.Document, and the FSR.Browser FSR.Hash.
*/

FSR.Browser = new FSR.Hash({
	Type: {name: 'unknown', version: ''},
	Engine: {name: 'unknown', version: ''},
	Platform: {name: (navigator.platform.match(/mac|win32|linux/i) || ['other'])[0].toLowerCase(), os: 'unknown'},
	Features: {xpath: !!(document.evaluate), air: !!(window.runtime)},
	Plugins: {},
    searchString: function(data){
        for (var i = 0; i < data.length; i++) {
            var dataString = data[i].s;
            var dataProp = data[i].p;
            this.versionSearchString = data[i].v || data[i].i;
            if (dataString) {
                if (dataString.indexOf(data[i].b) != -1) 
                    return data[i].i;
            }
            else if (dataProp) 
                return data[i].i;
        }
    },
    searchVersion: function(dataString){
        var index = dataString.indexOf(this.versionSearchString);
        if (index == -1) 
            return;
        return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
    },
    dataBrowser: [{
        s: navigator.userAgent,
        b: "Chrome",
        i: "Chrome"
    }, {
        s: navigator.vendor,
        b: "Apple",
        i: "Safari",
        v: "Version"
    }, {
        p: window.opera,
        i: "Opera"
    }, {
        s: navigator.userAgent,
        b: "Firefox",
        i: "Firefox"
    }, { // for newer Netscapes (6+)
        s: navigator.userAgent,
        b: "Netscape",
        i: "Netscape"
    }, {
        s: navigator.userAgent,
        b: "MSIE",
        i: "Explorer",
        v: "MSIE"
    }, {
        s: navigator.userAgent,
        b: "Gecko",
        i: "Mozilla",
        v: "rv"
    }],
    dataOS: [{
        s: navigator.platform,
        b: "Win",
        i: "Windows"
    }, {
        s: navigator.platform,
        b: "Mac",
        i: "Mac"
    }, {
        s: navigator.platform,
        b: "Linux",
        i: "Linux"
    }]
});

if (window.opera) FSR.Browser.Engine = {name: 'presto', version: (document.getElementsByClassName) ? 950 : 925};
else if (window.ActiveXObject) FSR.Browser.Engine = {name: 'trident', version: (window.XMLHttpRequest) ? 5 : 4};
else if (!navigator.taintEnabled) FSR.Browser.Engine = {name: 'webkit', version: (FSR.Browser.Features.xpath) ? 420 : 419};
else if (document.getBoxObjectFor != null) FSR.Browser.Engine = {name: 'gecko', version: (document.getElementsByClassName) ? 19 : 18};
FSR.Browser.Engine[FSR.Browser.Engine.name] = FSR.Browser.Engine[FSR.Browser.Engine.name + FSR.Browser.Engine.version] = true;

if (window.orientation != undefined) FSR.Browser.Platform.name = 'ipod';

FSR.Browser.Platform[FSR.Browser.Platform.name] = true;

FSR.Browser.Plugins.Flash = (function(){
	var version = (FSR.$try(function(){
		return navigator.plugins['Shockwave Flash'].description;
	}, function(){
		return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
	}) || '0 r0').match(/\d+/g);
	return {version: parseInt(version[0] || 0 + '.' + version[1] || 0), build: parseInt(version[2] || 0)};
})();

FSR.Browser.Type.name = FSR.Browser.searchString(FSR.Browser.dataBrowser) || "unknown";
FSR.Browser.Type.version = FSR.Browser.searchVersion(navigator.userAgent) || FSR.Browser.searchVersion(navigator.appVersion) || "unknown";
FSR.Browser.Platform.os = FSR.Browser.searchString(FSR.Browser.dataOS) || "unknown";

FSR.$exec = function (text){
	if (!text) return text;
	if (window.execScript){
		window.execScript(text);
	} else {
		var script = document.createElement('script');
		script.setAttribute('type', 'text/javascript');
		script.text = text;
		document.fsr$head.appendChild(script);
		document.fsr$head.removeChild(script);
	}
	return text;
};

FSR.Native.UID = 1;

FSR.$uid = (FSR.Browser.Engine.trident) ? function(item){
	return (item.fsr$uid || (item.fsr$uid = [FSR.Native.UID++]))[0];
} : function(item){
	return item.fsr$uid || (item.fsr$uid = FSR.Native.UID++);
};

FSR.Window = new FSR.Native({

	name: 'Window',

	//legacy: (FSR.Browser.Engine.trident) ? null: window.Window, //TODO: Which Window

	initialize: function(win){
		FSR.$uid(win);
		//TODO: What is Element
		if (!win.Element){
			win.Element = FSR.$empty;
			if (FSR.Browser.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2
			win.Element.prototype = (FSR.Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {};
		}
		return FSR.$extend(win, FSR.Window.Prototype);
	},

	afterImplement: function(property, value){
		window[property] = value;
		FSR.Window.Prototype[property] = value;
	}

});

FSR.Window.Prototype = {fsr$family: {name: 'window'}};

new FSR.Window(window);

FSR.Document = new FSR.Native({

	name: 'Document',

	//legacy: (FSR.Browser.Engine.trident) ? null: window.Document, //TODO: Which Document

	initialize: function(doc){
		FSR.$uid(doc);
		doc.fsr$head = doc.getElementsByTagName('head')[0];
		doc.fsr$html = doc.getElementsByTagName('html')[0];
		doc.fsr$window = doc.defaultView || doc.parentWindow;
		if (FSR.Browser.Engine.trident4) FSR.$try(function(){
			doc.execCommand("BackgroundImageCache", false, true);
		});
		return FSR.$extend(doc, FSR.Document.Prototype);
	},

	afterImplement: function(property, value){
		document[property] = value;
		FSR.Document.Prototype[property] = value;
	}

});

FSR.Document.Prototype = {fsr$family: {name: 'document'}};

new FSR.Document(document);

FSR.Array = {

	indexOf: function(a, item, from){
		var len = a.length;
		for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
			if (a[i] === item) return i;
		}
		return -1;
	},

	map: function(a, fn, bind){
		var results = [];
		for (var i = 0, l = a.length; i < l; i++) results[i] = fn.call(bind, a[i], i, a);
		return results;
	},

	associate: function(a, keys){
		var obj = {}, length = Math.min(a.length, keys.length);
		for (var i = 0; i < length; i++) obj[keys[i]] = a[i];
		return obj;
	},

	contains: function(a, item, from){
		return FSR.Array.indexOf(a, item, from) != -1;
	},

	extend: function(a, array){
		for (var i = 0, j = array.length; i < j; i++) a.push(array[i]);
		return a;
	},

	include: function(a, item){
		if (!FSR.Array.contains(a, item)) a.push(item);
		return a;
	},

	flatten: function(a){
		var array = [];
		for (var i = 0, l = a.length; i < l; i++){
			var type = FSR.$type(a[i]);
			if (!type) continue;
			array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? FSR.Array.flatten(a[i]) : a[i]);
		}
		return array;
	},
	
	slice: function(){
		var args = Array.prototype.slice.call(arguments)
		return Array.prototype.slice.apply(args.shift(), args);
	},
	
	forEach: function(a, fn, bind){
		for (var i = 0, l = a.length; i < l; i++) fn.call(bind, a[i], i, a);
	},
	
	each: function(a, fn, bind){
		for (var i = 0, l = a.length; i < l; i++) fn.call(bind, a[i], i, a);
	},

    toJSON: function(a){
        return FSR.JSON.encode(a);
    }
};

FSR.$A = function (iterable){
	if (iterable.item){
		var array = [];
		for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i];
		return array;
	}
	return Array.prototype.slice.call(iterable);
};

/*
Script: Function.js
	Contains Function Prototypes like create, bind, pass, and delay.
*/

Function.fsr$implement({
	fsr$extend: function(properties){
		for (var property in properties) this[property] = properties[property];
		return this;
	},

	fsr$create: function(options){
		var self = this;
		options = options || {};
		return function(event){
			var args = options.arguments;
			args = (args != undefined) ? FSR.$splat(args) : FSR.Array.slice(arguments, (options.event) ? 1 : 0);
			if (options.event) args = FSR.Array([event || window.event], args);
			var returns = function(){
				return self.apply(options.bind || null, args);
			};
			if (options.delay) return setTimeout(returns, options.delay);
			if (options.periodical) return setInterval(returns, options.periodical);
			if (options.attempt) return FSR.$try(returns);
			return returns();
		};
	},

	fsr$pass: function(args, bind){
		return this.fsr$create({arguments: args, bind: bind});
	},

	fsr$attempt: function(args, bind){
		return this.fsr$create({arguments: args, bind: bind, attempt: true})();
	},

	fsr$bind: function(bind, args){
		return this.fsr$create({bind: bind, arguments: args});
	},

	fsr$bindWithEvent: function(bind, args){
		return this.fsr$create({bind: bind, event: true, arguments: args});
	},

	fsr$delay: function(delay, bind, args){
		return this.fsr$create({delay: delay, bind: bind, arguments: args})();
	},

	fsr$periodical: function(interval, bind, args){
		return this.fsr$create({periodical: interval, bind: bind, arguments: args})();
	},

	fsr$run: function(args, bind){
		return this.apply(bind, FSR.$splat(args));
	}
});

/*
Script: Number.js
	Contains Number Prototypes like limit, round, times, and ceil.
*/

Number.fsr$implement({
	fsr$toInt: function(base){
		return parseInt(this, base || 10);
	}
});

/*
Script: String.js
	Contains String Prototypes like camelCase, capitalize, test, and toInt.
*/

String.fsr$implement({

	fsr$test: function(regex, params){
		return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);
	},

	fsr$contains: function(string, separator){
		return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
	},

	fsr$trim: function(){
		return this.replace(/^\s+|\s+$/g, '');
	},

	fsr$clean: function(){
		return this.replace(/\s+/g, ' ').fsr$trim();
	},

	fsr$camelCase: function(){
		return this.replace(/-\D/g, function(match){
			return match.charAt(1).toUpperCase();
		});
	},

	fsr$hyphenate: function(){
		return this.replace(/[A-Z]/g, function(match){
			return ('-' + match.charAt(0).toLowerCase());
		});
	},

	fsr$capitalize: function(){
		return this.replace(/\b[a-z]/g, function(match){
			return match.toUpperCase();
		});
	},

	fsr$escapeRegExp: function(){
		return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
	},

	fsr$toInt: function(base){
		return parseInt(this, base || 10);
	},

	fsr$stripScripts: function(option){
		var scripts = '';
		var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
			scripts += arguments[1] + '\n';
			return '';
		});
		if (option === true) FSR.$exec(scripts);
		else if (FSR.$type(option) == 'function') option(scripts, text);
		return text;
	},

	fsr$substitute: function(object, regexp){
		return this.replace(regexp || (/\\?\{([^}]+)\}/g), function(match, name){
			if (match.charAt(0) == '\\') return match.slice(1);
			return (object[name] != undefined) ? object[name] : '';
		});
	}

});

/*
Script: FSR.Hash.js
	Contains FSR.Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.
*/

FSR.Hash.fsr$implement({

	has: Object.prototype.hasOwnProperty,

	keyOf: function(value){
		for (var key in this){
			if (this.hasOwnProperty(key) && this[key] === value) return key;
		}
		return null;
	},
	
	extend: function(properties){
		FSR.Hash.each(properties, function(value, key){
			FSR.Hash.set(this, key, value);
		}, this);
		return this;
	},

	combine: function(properties){
		FSR.Hash.each(properties, function(value, key){
			FSR.Hash.include(this, key, value);
		}, this);
		return this;
	},

	erase: function(key){
		if (this.hasOwnProperty(key)) delete this[key];
		return this;
	},

	get: function(key){
		return (this.hasOwnProperty(key)) ? this[key] : null;
	},

	set: function(key, value){
		if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
		return this;
	},

	include: function(key, value){
		var k = this[key];
		if (k == undefined) this[key] = value;
		return this;
	},

	toQueryString: function(base){
		var queryString = [];
		FSR.Hash.each(this, function(value, key){
			if (base) key = base + '[' + key + ']';
			var result;
			switch (FSR.$type(value)){
				case 'object': result = FSR.Hash.toQueryString(value, key); break;
				case 'array':
					var qs = {};
					FSR.Array.each(value, function(val, i){
						qs[i] = val;
					});
					result = FSR.Hash.toQueryString(qs, key);
				break;
				default: result = key + '=' + encodeURIComponent(value);
			}
			if (value != undefined) queryString.push(result);
		});
		
		return queryString.join('&');
	}

});

FSR.Hash.fsr$alias({keyOf: 'indexOf', hasValue: 'contains'});

/*
Script: FSR.Event.js
	Contains the FSR.Event FSR.Native, to make the event object completely crossbrowser.
*/

FSR.Event = new FSR.Native({

	name: 'Event',

	initialize: function(event, win){
		win = win || window;
		var doc = win.document;
		event = event || win.event;
		if (event.fsr$extended) return event;
		this.fsr$extended = true;
		var type = event.type;
		var target = event.target || event.srcElement;
		while (target && target.nodeType == 3) target = target.parentNode;
		
		if (type.fsr$test(/key/)){
			var code = event.which || event.keyCode;
			var key = FSR.Event.Keys.keyOf(code);
			if (type == 'keydown'){
				var fKey = code - 111;
				if (fKey > 0 && fKey < 13) key = 'f' + fKey;
			}
			key = key || String.fromCharCode(code).toLowerCase();
		} else if (type.match(/(click|mouse|menu)/i)){
			doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.getElementsByTagName('html')[0] : doc.body;
			var page = {
				x: event.pageX || event.clientX + doc.scrollLeft,
				y: event.pageY || event.clientY + doc.scrollTop
			};
			var client = {
				x: (event.pageX) ? event.pageX - win.pageXOffset : event.clientX,
				y: (event.pageY) ? event.pageY - win.pageYOffset : event.clientY
			};
			if (type.match(/DOMMouseScroll|mousewheel/)){
				var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
			}
			var rightClick = (event.which == 3) || (event.button == 2);
			var related = null;
			if (type.match(/over|out/)){
				switch (type){
					case 'mouseover': related = event.relatedTarget || event.fromElement; break;
					case 'mouseout': related = event.relatedTarget || event.toElement;
				}
				if (!(function(){
					while (related && related.nodeType == 3) related = related.parentNode;
					return true;
				}).fsr$create({attempt: FSR.Browser.Engine.gecko})()) related = false;
			}
		}

		return FSR.$extend(this, {
			event: event,  //TODO: Look into this
			type: type,
			
			page: page,
			client: client,
			rightClick: rightClick,
			
			wheel: wheel,
			
			relatedTarget: related,
			target: target,
			
			code: code,
			key: key,
			
			shift: event.shiftKey,
			control: event.ctrlKey,
			alt: event.altKey,
			meta: event.metaKey
		});
	}

});

FSR.Event.Keys = new FSR.Hash({
	'enter': 13,
	'up': 38,
	'down': 40,
	'left': 37,
	'right': 39,
	'esc': 27,
	'space': 32,
	'backspace': 8,
	'tab': 9,
	'delete': 46
});

/*
Script: FSR.Class.js
	Contains the FSR.Class Function for easily creating, extending, and implementing reusable FSR.Classes.
*/

FSR.Class = new FSR.Native({

	name: 'Class',

	initialize: function(properties){
		properties = properties || {};
		var klass = function(empty){
			for (var key in this) this[key] = FSR.$unlink(this[key]);
			for (var mutator in FSR.Class.Mutators){
				if (mutator == 'extend') continue;
				if (!this[mutator]) continue;
				FSR.Class.Mutators[mutator](this, this[mutator]);
				delete this[mutator];
			}

			this.constructor = klass;
			if (empty === FSR.$empty) return this;
			
			var self = (this.initialize) ? this.initialize.apply(this, arguments) : this;
			if (this.options && this.options.initialize) this.options.initialize.call(this);
			return self;
		};

		FSR.$extend(klass, this);
		klass.constructor = FSR.Class;
		klass.prototype = properties;
		return klass;
	}

});

FSR.Class.fsr$implement({

	fsr$implement: function(){
		FSR.Class.Mutators.Implements(this.prototype, FSR.Array.slice(arguments));
		return this;
	}

});

FSR.Class.Mutators = {
  
  Implements: function(self, klasses){
  	FSR.Array.each(FSR.$splat(klasses), function(klass){
  		FSR.$extend(self, (FSR.$type(klass) == 'class') ? new klass(FSR.$empty) : klass);
  	});
  },
  
  Extends: function(self, klass){
  	var instance = new klass(FSR.$empty);
  	delete instance.parent;
  	delete instance.parentOf;

  	for (var key in instance){
  		var current = self[key], previous = instance[key];
  		if (current == undefined){
  			self[key] = previous;
  			continue;
  		}

  		var ctype = FSR.$type(current), ptype = FSR.$type(previous);
  		if (ctype != ptype) continue;

  		switch (ctype){
  			case 'function': 
  				// this code will be only executed if the current browser does not support function.caller (currently only opera).
  				// we replace the function code with brute force. Not pretty, but it will only be executed if function.caller is not supported.

  				if (!arguments.callee.caller) self[key] = eval('(' + String(current).replace(/\bthis\.parent\(\s*(\))?/g, function(full, close){
  					return 'arguments.callee._parent_.call(this' + (close || ', ');
  				}) + ')');

  				// end "opera" code
  				self[key]._parent_ = previous;
  			  break;
  			case 'object': self[key] = FSR.$merge(previous, current);
  		}

  	}

  	self.parent = function(){
  		return arguments.callee.caller._parent_.apply(this, arguments);
  	};

  	self.parentOf = function(descendant){
  		return descendant._parent_.apply(this, FSR.Array.slice(arguments, 1));
  	};
  }
  
};

FSR.Events = new FSR.Class({

	fsr$addEvent: function(type, fn, internal){
		type = FSR.Events.removeOn(type);
		if (fn != FSR.$empty){
			this.$events = this.$events || {};
			this.$events[type] = this.$events[type] || [];
			FSR.Array.include(this.$events[type], fn);
			if (internal) fn.internal = true;
		}
		return this;
	},

	fsr$addEvents: function(events){
		for (var type in events) this.fsr$addEvent(type, events[type]);
		return this;
	},

	fsr$fireEvent: function(type, args, delay){
		type = FSR.Events.removeOn(type);
		if (!this.$events || !this.$events[type]) return this;
		FSR.Array.each(this.$events[type], function(fn){
			fn.fsr$create({'bind': this, 'delay': delay, 'arguments': args})();
		}, this);
		return this;
	},

	fsr$removeEvent: function(type, fn){
		type = FSR.Events.removeOn(type);
		if (!this.$events || !this.$events[type]) return this;
		if (!fn.internal) this.$events[type].erase(fn);
		return this;
	},

	fsr$removeEvents: function(type){
		for (var e in this.$events){
			if (type && type != e) continue;
			var fns = this.$events[e];
			for (var i = fns.length; i--; i) this.fsr$removeEvent(e, fns[i]);
		}
		return this;
	}

});

FSR.Events.removeOn = function(string){
	return string.replace(/^on([A-Z])/, function(full, first) {
		return first.toLowerCase();
	});
};

FSR.Options = new FSR.Class({

	setOptions: function(){
		this.options = FSR.$merge.fsr$run(FSR.Array.extend([this.options], arguments));
		if (!this.fsr$addEvent) return this;
		for (var option in this.options){
			if (FSR.$type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
			this.fsr$addEvent(option, this.options[option]);
			delete this.options[option];
		}
		return this;
	}

});

/*
Script: FSR.Element.js
	One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser,
	time-saver methods to let you easily work with HTML FSR.Elements.
*/

FSR.Document.fsr$implement({

	fsr$newElement: function(tag, props){
		if (FSR.Browser.Engine.trident && props){
			FSR.Array.each(['name', 'type', 'checked'], function(attribute){
				if (!props[attribute]) return;
				tag += ' ' + attribute + '="' + props[attribute] + '"';
				if (attribute != 'checked') delete props[attribute];
			});
			tag = '<' + tag + '>';
		}
		return $fsr.element(this.createElement(tag)).fsr$set(props);
	},

	fsr$newTextNode: function(text){
		return this.createTextNode(text);
	},

	fsr$getDocument: function(){
		return this;
	},

	fsr$getWindow: function(){
		return this.defaultView || this.parentWindow;
	},

	fsr$purge: function(){ 
		var elements = this.getElementsByTagName('*');
		for (var i = 0, l = elements.length; i < l; i++) {
			FSR.Browser.freeMem(elements[i]);
		}
		for (var p in FSR.Document.Prototype)
			document[p] = null;
		document.fsr$uid = null;
		for (var p in FSR.Window.Prototype)
			window[p] = null;
		window.fsr$uid = null;
		document.fsr$head = null;
		document.fsr$html = null;
		document.fsr$window = null;
		FSR.Element.Storage = null;
	}
});

FSR.Element = new FSR.Native({

	name: 'Element',

	//legacy: window.Element, //TODO: Which Element

	initialize: function(tag, props){
		var konstructor = FSR.Element.Constructors.get(tag);
		if (konstructor) return konstructor(props);
		if (typeof tag == 'string') return document.fsr$newElement(tag, props);
		return $fsr(tag).fsr$set(props);
	},

	afterImplement: function(key, value){
		if (!Array[key]) FSR.Elements.fsr$implement(key, FSR.Elements.fsr$multi(key));
		FSR.Element.Prototype[key] = value;
	}

});

FSR.Element.Prototype = {fsr$family: {name: 'element'}};

FSR.Element.Constructors = new FSR.Hash;

FSR.Elements = new FSR.Native({

	initialize: function(elements, options){
		options = FSR.$extend({ddup: true, cash: true}, options);
		elements = elements || [];
		if (options.ddup || options.cash){
			var uniques = {}, returned = [];
			for (var i = 0, l = elements.length; i < l; i++){
				var el = $fsr.element(elements[i], !options.cash);
				if (options.ddup){
					if (uniques[el.fsr$uid]) continue;
					uniques[el.fsr$uid] = true;
				}
				returned.push(el);
			}
			elements = returned;
		}
		return (options.cash) ? FSR.$extend(elements, this) : elements;
	}

});

FSR.Elements.fsr$implement({

	fsr$filter: function(filter, bind){
		if (!filter) return this;
		return new FSR.Elements(FSR.Array.filter(this, (typeof filter == 'string') ? function(item){
			return item.match(filter); //TODO: Which match
		} : filter, bind));
	}

});

FSR.Elements.fsr$multi = function(property){
	return function(){
		var items = [];
		var elements = true;
		for (var i = 0, j = this.length; i < j; i++){
			var returns = this[i][property].apply(this[i], arguments);
			items.push(returns);
			if (elements) elements = (FSR.$type(returns) == 'element');
		}
		return (elements) ? new FSR.Elements(items) : items;
	};
};

FSR.Window.fsr$implement({

	$fsr: function(el, nocash){
		if (el && el.fsr$family && el.fsr$uid) return el;
		var type = FSR.$type(el);
		return ($fsr[type]) ? $fsr[type](el, nocash, this.document) : null;
	},

	$$fsr: function(selector){
		if (arguments.length == 1 && typeof selector == 'string') return this.document.fsr$getElements(selector);
		var elements = [];
		var args = FSR.Array.flatten(arguments);
		for (var i = 0, l = args.length; i < l; i++){
			var item = args[i];
			switch (FSR.$type(item)){
				case 'element': item = [item]; break;
				case 'string': item = this.document.fsr$getElements(item, true); break;
				default: item = false;
			}
			if (item) FSR.Array.extend(elements, item);
		}
		return new FSR.Elements(elements);
	},

	fsr$getDocument: function(){
		return this.document;
	},

	fsr$getWindow: function(){
		return this;
	}

});

$fsr.string = function(id, nocash, doc){
	id = doc.getElementById(id);
	return (id) ? $fsr.element(id, nocash) : null;
};

$fsr.element = function(el, nocash){
	FSR.$uid(el);
	if (!nocash && !el.fsr$family && !(/^object|embed$/i).test(el.tagName)){
		var proto = FSR.Element.Prototype;
		for (var p in proto) el[p] = proto[p];
	};
	return el;
};

$fsr.object = function(obj, nocash, doc){
	if (obj.toElement) return $fsr.element(obj.toElement(doc), nocash);
	return null;
};

$fsr.textnode = $fsr.whitespace = $fsr.window = $fsr.document = FSR.$arguments(0);

FSR.Native.fsr$implement([FSR.Element, FSR.Document], {

	fsr$getElement: function(selector, nocash){
		return $fsr(this.fsr$getElements(selector, true)[0] || null, nocash);
	},

	fsr$getElements: function(tags, nocash){
		tags = tags.split(',');
		var elements = [];
		var ddup = (tags.length > 1);
		FSR.Array.each(tags, function(tag){
			var partial = this.getElementsByTagName(tag.fsr$trim());
			(ddup) ? FSR.Array.extend(elements, partial) : elements = partial;
		}, this);
		return new FSR.Elements(elements, {ddup: ddup, cash: !nocash});
	}

});

FSR.Element.Storage = {

	get: function(uid){
		return (this[uid] || (this[uid] = {}));
	}

};

FSR.Element.Inserters = new FSR.Hash({

	after: function(context, element){
		if (!element.parentNode) return;
		var next = element.nextSibling;
		(next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context);
	},

	bottom: function(context, element){
		element.appendChild(context);
	}

});

FSR.Element.Inserters.inside = FSR.Element.Inserters.bottom;

FSR.Element.fsr$implement({

	fsr$getDocument: function(){
		return this.ownerDocument;
	},

	fsr$getWindow: function(){
		return this.ownerDocument.fsr$getWindow();
	},

	fsr$set: function(prop, value){
		switch (FSR.$type(prop)){
			case 'object':
				for (var p in prop) this.fsr$set(p, prop[p]);
				break;
			case 'string':
				var property = FSR.Element.Properties.get(prop);
				if (property && property.set) {
					property.set.apply(this, FSR.Array.slice(arguments, 1))
				}
				else {
					this.fsr$setProperty(prop, value)
				};
		}
		return this;
	},

	fsr$inject: function(el, where){
		FSR.Element.Inserters.get(where || 'bottom')(this, $fsr(el, true));
		return this;
	},

	fsr$dispose: function(){
		return (this.parentNode) ? this.parentNode.removeChild(this) : this;
	},
	
	fsr$setProperty: function(attribute, value){
		var EA = FSR.Element.Attributes, key = EA.Props[attribute], hasValue = FSR.$defined(value);
		if (key && EA.Bools[attribute]) value = (value || !hasValue) ? true : false;
		else if (!hasValue) return this.removeProperty(attribute);
		(key) ? this[key] = value : this.setAttribute(attribute, value);
		return this;
	},

	fsr$setProperties: function(attributes){
		for (var attribute in attributes) this.fsr$setProperty(attribute, attributes[attribute]);
		return this;
	}
});

FSR.Element.Properties = new FSR.Hash;

FSR.Element.Properties.html = {set: function(){
	return this.innerHTML = FSR.Array.flatten(arguments).join('');
}};

FSR.Native.fsr$implement([FSR.Element, FSR.Window, FSR.Document], {

	fsr$addListener: function(type, fn){
		if (this.addEventListener) this.addEventListener(type, fn, false);
		else this.attachEvent('on' + type, fn);
		return this;
	},

	fsr$removeListener: function(type, fn){
		if (this.removeEventListener) this.removeEventListener(type, fn, false);
		else this.detachEvent('on' + type, fn);
		return this;
	},

	fsr$retrieve: function(property, dflt){
		var storage = FSR.Element.Storage.get(this.fsr$uid);
		var prop = storage[property];
		if (FSR.$defined(dflt) && !FSR.$defined(prop)) prop = storage[property] = dflt;
		return FSR.$pick(prop);
	},

	fsr$store: function(property, value){
		var storage = FSR.Element.Storage.get(this.fsr$uid);
		storage[property] = value;
		return this;
	},

	fsr$eliminate: function(property){
		var storage = FSR.Element.Storage.get(this.fsr$uid);
		delete storage[property];
		return this;
	}

});

FSR.Element.Attributes = new FSR.Hash({
	Props: {'html': 'innerHTML', 'class': 'className', 'for': 'htmlFor', 'text': (FSR.Browser.Engine.trident) ? 'innerText' : 'textContent'},
	Bools: ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer'],
	Camels: ['value', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap']
});

FSR.Browser.freeMem = function(item){
	if (!item) return;
	if (FSR.Browser.Engine.trident && (/object/i).test(item.tagName)){
		for (var p in item){
			if (typeof item[p] == 'function') item[p] = FSR.$empty;
		}
		FSR.Element.fsr$dispose(item);
	}
	if (item.fsr$uid && item.fsr$removeEvents) item.fsr$removeEvents();
	if (item.fsr$uid) item.fsr$uid = null;
};

(function(FSR$EA){

	var fsr$EAB = FSR$EA.Bools, fsr$EAC = FSR$EA.Camels;
	FSR$EA.Bools = fsr$EAB = FSR.Array.associate(fsr$EAB, fsr$EAB);
	FSR.Hash.extend(FSR.Hash.combine(FSR$EA.Props, fsr$EAB), FSR.Array.associate(fsr$EAC, FSR.Array.map(fsr$EAC, function(v){
		return v.toLowerCase();
	})));
	FSR$EA.erase('Camels');

})(FSR.Element.Attributes);

window.fsr$addListener('unload', function(){ //TODO: Is this a problem if multiple do it
	window.fsr$removeListener('unload', arguments.callee);
	window.fsr$fireEvent('unload');
	document.fsr$purge();
	if (window.CollectGarbage) CollectGarbage();
});

/*

Script: FSR.Element.Event.js
	Contains FSR.Element methods for dealing with events, and custom FSR.Events.
*/
FSR.Element.Properties.events = {set: function(events){
	this.fsr$addEvents(events);
}};

FSR.Native.fsr$implement([FSR.Element, FSR.Window, FSR.Document], {
	fsr$addEvent: function(type, fn){
		var events = this.fsr$retrieve('events', {});
		events[type] = events[type] || {'keys': [], 'values': []};
		if (FSR.Array.contains(events[type].keys, fn)) return this;
		events[type].keys.push(fn);
		var realType = type, custom = FSR.Element.Events.get(type), condition = fn, self = this;
		if (custom){
			if (custom.onAdd) custom.onAdd.call(this, fn);
			if (custom.condition){
				condition = function(event){
					if (custom.condition.call(this, event)) return fn.call(this, event);
					return false;
				};
			}
			realType = custom.base || realType;
		}
		var defn = function(){
			return fn.call(self);
		};
		var nativeEvent = FSR.Element.NativeEvents[realType] || 0;
		if (nativeEvent){
			if (nativeEvent == 2){
				defn = function(event){
					event = new FSR.Event(event, self.fsr$getWindow());
					if (condition.call(self, event) === false) event.stop();
				};
			}
			
			if (realType != 'unload') {
				this.fsr$addListener(realType, defn);
			}
		}
		events[type].values.push(defn);
		return this;
	},

	fsr$removeEvent: function(type, fn){
		var events = this.fsr$retrieve('events');
		if (!events || !events[type]) return this;
		var pos = FSR.Array.indexOf(events[type].keys, fn);
		if (pos == -1) return this;
		var key = events[type].keys.splice(pos, 1)[0];
		var value = events[type].values.splice(pos, 1)[0];
		var custom = FSR.Element.Events.get(type);
		if (custom){
			if (custom.onRemove) custom.onRemove.call(this, fn);
			type = custom.base || type;
		}
		return (FSR.Element.NativeEvents[type]) ? this.fsr$removeListener(type, value) : this;
	},

	fsr$addEvents: function(events){
		for (var event in events) { //COMCAST FIX
			if (events.hasOwnProperty(event)) {
				this.fsr$addEvent(event, events[event]);
			}
		}
		return this;
	},

	fsr$removeEvents: function(type){
		var events = this.fsr$retrieve('events');
		if (!events) return this;
		if (!type){
			for (var evType in events) {//COMCAST FIX
				if (events.hasOwnProperty(evType)) {
					this.fsr$removeEvents(evType);
				}
			}
			events = null;
		} else if (events[type]){
			while (events[type].keys[0]) this.fsr$removeEvent(type, events[type].keys[0]);
			events[type] = null;
		}
		return this;
	},

	fsr$fireEvent: function(type, args, delay){
		var events = this.fsr$retrieve('events');
		if (!events || !events[type]) return this;
		FSR.Array.each(events[type].keys, function(fn){
			fn.fsr$create({'bind': this, 'delay': delay, 'arguments': args})();
		}, this);
		return this;
	}
});

FSR.Element.NativeEvents = {
	click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
	mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
	mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
	keydown: 2, keypress: 2, keyup: 2, //keyboard
	focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements
	load: 1, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
	error: 1, abort: 1, scroll: 1 //misc
};

(function(){
    FSR.$check = function(event){
        var related = event.relatedTarget;
        if (related == undefined) 
            return true;
        if (related === false) 
            return false;
        return (FSR.$type(this) != 'document' && related != this && related.prefix != 'xul' && !this.fsr$hasChild(related));
    };
    
    FSR.Element.Events = new FSR.Hash({
        mouseenter: {
            base: 'mouseover',
            condition: FSR.$check
        },
        
        mouseleave: {
            base: 'mouseout',
            condition: FSR.$check
        },
        
        mousewheel: {
            base: (FSR.Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel'
        }
    });
})();

FSR.Element.fsr$implement({
    fsr$hasChild: function(el){
        el = $fsr(el, true);
        return (!!el && FSR.Array.contains(FSR.$A(this.getElementsByTagName(el.tagName)), el));
    }
});

/*
Script: FSR.Element.Dimensions.js
	Contains methods to work with size, scroll, or positioning of FSR.Elements and the window object.

Credits:
	- FSR.Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
	- Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).
*/

(function(){

FSR.Native.fsr$implement([FSR.Document, FSR.Window], {

	fsr$getSize: function(){
		var win = this.fsr$getWindow();
		if (FSR.Browser.Engine.presto || FSR.Browser.Engine.webkit) return {x: win.innerWidth, y: win.innerHeight};
		var doc = fsr$getCompatElement(this);
		return {x: doc.clientWidth, y: doc.clientHeight};
	},

	fsr$getScroll: function(){
		var win = this.fsr$getWindow();
		var doc = fsr$getCompatElement(this);
		return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
	},

	fsr$getScrollSize: function(){
		var doc = fsr$getCompatElement(this);
		var min = this.fsr$getSize();
		return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)};
	}

});

function fsr$getCompatElement(element){
	var doc = element.fsr$getDocument();
	return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.getElementsByTagName('html')[0] : doc.body;
};

})();

/*
Script: Domready.js
	Contains the domready custom event.
*/

FSR.Element.Events.domready = {
	onAdd: function(fn){
		if (FSR.Browser.loaded) fn.call(this);
	}
};

(function(){
	
	var fsr$domready = function(){
		if (FSR.Browser.loaded) return;
		FSR.Browser.loaded = true;
		window.fsr$fireEvent('domready');
		document.fsr$fireEvent('domready');
	};
	
	switch (FSR.Browser.Engine.name){

		case 'webkit': (function(){
			(FSR.Array.contains(['loaded', 'complete'], document.readyState)) ? fsr$domready() : arguments.callee.fsr$delay(50);
		})(); break;

		case 'trident':
			var temp = document.createElement('div');
			(function(){
				(FSR.$try(function(){
					temp.doScroll('left');
					return $fsr(temp).fsr$inject(document.body).fsr$set('html', 'temp').fsr$dispose();
				})) ? fsr$domready() : arguments.callee.fsr$delay(50);
			})();
		break;
		
		default:
			window.fsr$addEvent('load', fsr$domready);
			document.fsr$addEvent('DOMContentLoaded', fsr$domready);

	}
	
})();

/*
Script: JSON.js
	JSON encoder and decoder.

See Also:
	<http://www.json.org/>
*/

FSR.JSON = new FSR.Hash({

	encode: function(obj){
		switch (FSR.$type(obj)){
			case 'string':
				return '"' + obj.replace(/[\x00-\x1f\\"\\;]/g, FSR.JSON.$replaceChars) + '"';
			case 'array':
				return '[' + String(FSR.Array.map(obj, FSR.JSON.encode).fsr$filter(FSR.$defined)) + ']';
			case 'object': case 'hash':
				var string = [];
				FSR.Hash.each(obj, function(value, key){
					var json = FSR.JSON.encode(value);
					if (json) string.push(FSR.JSON.encode(key) + ':' + json);
				});
				return '{' + string + '}';
			case 'number': case 'boolean': return String(obj);
			case false: return 'null';
		}
		return null;
	},

	$specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'},

	$replaceChars: function(chr){
		return FSR.JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16);
	},

	decode: function(string, secure){
		if (FSR.$type(string) != 'string' || !string.length) return null;
		if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
		return eval('(' + string + ')');
	}

});

FSR.Native.fsr$implement([FSR.Hash, Number], {

	fsr$toJSON: function(){
		return FSR.JSON.encode(this);
	}

});


/*
Script: FSR.Cookie.js
	FSR.Class for creating, loading, and saving browser FSR.Cookies.

Credits:
	Based on the functions by Peter-Paul Koch (http://quirksmode.org).
*/

FSR.Cookie = new FSR.Class({

	Implements: FSR.Options,

	options: {
		path: false,
		domain: false,
		duration: false,
		secure: false,
		document: document
	},

	initialize: function(key, options){
		this.key = key;
		this.setOptions(options);
	},

	write: function(value){
		//value = encodeURIComponent(value);
		if (this.options.domain) value += '; domain=' + this.options.domain;
		if (this.options.path) value += '; path=' + this.options.path;
		if (this.options.duration){
			var date = new Date();
			date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
			value += '; expires=' + date.toGMTString();
		}
		if (this.options.secure) value += '; secure';
		this.options.document.cookie = this.key + '=' + value;
		return this;
	},

	read: function(){
		var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.fsr$escapeRegExp() + '=([^;]*)');
		//return (value) ? decodeURIComponent(value[1]) : null;
		return (value) ? value[1] : null;
	},

	dispose: function(){
		new FSR.Cookie(this.key, FSR.$merge(this.options, {duration: -1})).write('');
		return this;
	}

});

FSR.Cookie.write = function(key, value, options){
	return new FSR.Cookie(key, options).write(value);
};

FSR.Cookie.read = function(key){
	return new FSR.Cookie(key).read();
};

FSR.Cookie.dispose = function(key, options){
	return new FSR.Cookie(key, options).dispose();
};

/*
Script: Hash.Cookie.js
	Class for creating, reading, and deleting Cookies in JSON format.
*/

FSR.Hash.Cookie = new FSR.Class({

	Extends: FSR.Cookie,

	options: {
		autoSave: true
	},

	initialize: function(name, options){
		this.parent(name, options);
		this.load();
	},

	save: function(){
		var value = FSR.JSON.encode(this.hash);
		if (!value || value.length > 4096) return false; //cookie would be truncated!
		if (value == '{}') this.dispose();
		else this.write(value);
		return true;
	},

	load: function(){
		this.hash = new FSR.Hash(FSR.JSON.decode(this.read(), true));
		return this;
	}

});

FSR.Hash.Cookie.fsr$implement({
    get: function(name){
        return this.hash.get(name);
    },
    
    set: function(name, value){
		this.hash.set(name, value);
        this.save()
        return this;
    },
    
    erase: function(name){
 		this.hash.erase(name);
        this.save()
        return this;
    },
    
    empty: function(){
  		this.hash.empty();
        this.save()
        return this;
    }
});

/*
Script: Assets.js
	Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
*/

FSR.Asset = new FSR.Hash({

	src: function(source){
		var src = source;
		if (source.substring(0,2) == '//') {
			src = document.location.protocol + src;
		}
		return src;
	},

	javascript: function(source, properties){
		properties = FSR.$extend({
			onload: FSR.$empty,
			document: document,
			check: FSR.$lambda(true)
		}, properties);
		
		var script = new FSR.Element('script', {'src': FSR.Asset.src(source), 'type': 'text/javascript'});
		
		var load = properties.onload.fsr$bind(script), check = properties.check, doc = properties.document;
		delete properties.onload; delete properties.check; delete properties.document;
		
		script.fsr$addEvents({
			load: load,
			readystatechange: function(){
				if (FSR.Browser.Engine.trident && FSR.Array.contains(['loaded', 'complete'], this.readyState)) load();
			}
		}).fsr$setProperties(properties);
		
		
		if (FSR.Browser.Engine.webkit419) var checker = (function(){
			if (!FSR.$try(check)) return;
			FSR.$clear(checker);
			load();
		}).fsr$periodical(50);
		
		return script.fsr$inject(document.getElementsByTagName('head')[0]);
	},

	image: function(source, properties){
		properties = FSR.$merge({
			'onload': FSR.$empty,
			'onabort': FSR.$empty,
			'onerror': FSR.$empty
		}, properties);
		var image = new Image();
		var element = $fsr(image) || new FSR.Element('img');
		FSR.Array.each(['load', 'abort', 'error'], function(name){
			var type = 'on' + name;
			var event = properties[type];
			delete properties[type];
			image[type] = function(){
				if (!image) return;
				if (!element.parentNode){
					element.width = image.width;
					element.height = image.height;
				}
				image = image.onload = image.onabort = image.onerror = null;
				event.fsr$delay(1, element, element);
				element.fsr$fireEvent(name, element, 1);
			};
		});
		image.src = FSR.Asset.src(source);
		if (element.src != image.src) element.src = image.src;
		if (image && image.complete) image.onload.fsr$delay(1);
		return element.fsr$setProperties(properties);
	},
	
	css: function(source, properties){
		return new FSR.Element('link', FSR.$merge({
			'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': FSR.Asset.src(source)
		}, properties)).fsr$inject(document.getElementsByTagName('head')[0]);
	}
});

/*
Script: Popup.js
	Defines the Popup class useful for making popup windows.

License:
	http://clientside.cnet.com/wiki/cnet-libraries#license
*/

FSR.Browser.set("Popup", new FSR.Class({
	Implements:[FSR.Options, FSR.Events],
	options: {
		width: 500,
		height: 300,
		x: 50,
		y: 50,
		toolbar: 0,
		location: 0,
		directories: 0,
		status: 0,
		scrollbars: 'auto',
		resizable: 1,
		name: 'popup',
		blur: false,
		menubar: 1
//	onBlock: $empty
	},
	initialize: function(url, options){
		this.url = url || false;
		this.setOptions(options);
		if(this.url) this.openWin();
	},
	openWin: function(url){
		url = url || this.url;
		var options = 'toolbar='+this.options.toolbar+
			',location='+this.options.location+
			',directories='+this.options.directories+
			',status='+this.options.status+
			',scrollbars='+this.options.scrollbars+
			',resizable='+this.options.resizable+
			',width='+this.options.width+
			',height='+this.options.height+
			',top='+this.options.y+
			',left='+this.options.x+
			',menubar='+this.options.menubar;
		this.window = window.open(url, this.options.name, options);
		if (!this.window) {
			this.window = window.open('', this.options.name, options);
			this.window.location.href = url;
		}
		if (!this.options.blur)
			this.focus.fsr$delay(100, this);
		else
			this.window.blur();
		return this;
	},
	focus: function(){
		if (this.window) this.window.focus();
		else if (this.focusTries<10) this.focus.delay(100, this); //try again
		else {
			this.blocked = true;
			this.fsr$fireEvent('onBlock');
		}
		return this;
	},
	focusTries: 0,
	blocked: null,
	close: function(){
		this.window.close();
		return this;
	}
}));
// Remote Event
FSR.RemoteEvent = new FSR.Class({

    Implements: [FSR.Events, FSR.Options],
    
    options: {
        /*onFSR.Service: FSR.$empty,
         onSuccess: FSR.$empty,
         onFailure: FSR.$empty,
         onException: FSR.$empty,*/
        host: '',
        path: '',
        url: ''
    },
    
    initialize: function(event, options){
        this.setOptions(options);
		this.event = event
    },
    
    onStateChange: function(status){
        if (!this.running) 
            return;
        this.running = false;
        this.status = 0;
        FSR.$try(function(){
            this.status = status;
        }.fsr$bind(this));
        if (this.isSuccess()) {
            this.success();
        }
        else {
            this.failure();
        }
    },
    
    isSuccess: function(){
        return (this.status == 1);
    },
    
    success: function(){
        this.onSuccess();
    },
    
    onSuccess: function(){
        this.fsr$fireEvent('success');
    },
    
    failure: function(){
        this.onFailure();
    },
    
    onFailure: function(){
        this.fsr$fireEvent('failure');
    },
    
    send: function(values){
        this.running = true;
        var self = this;
        var params = FSR.Hash.toQueryString(values);
        var url = document.location.protocol + '//' +
        this.options.host + this.options.path  + this.options.url + '?' +
        'event=' + this.event + '&' + params + '&' + 'uid=' + FSR.$time();
        
        new FSR.Asset.image(url, {
            'onload': function(image){
                self.onStateChange(1);
            },
            
            'onerror': function(){
                self.onStateChange(0);
            },
            
            'onabort': function(){
                self.onStateChange(0);
            }
        })
        
        return this;
    }
	
});

FSR.CPPS = new FSR.Hash({

    set: function(key, value){
        var cpps = FSR.c().get('cpps') ||
        {};
        cpps[key] = value;
        FSR.c().set('cpps', cpps);
    },
    
    get: function(key){
        var cpps = FSR.c().get('cpps') ||
        {};
        return cpps[key];
    },
    
    erase: function(key){
        var cpps = FSR.c().get('cpps') ||
        {};
        delete cpps[key];
        FSR.c().set('cpps', cpps);
    },
    
    append: function(key, value){
        var cpps = FSR.c().get('cpps') ||
        {};
        cpps[key] = cpps[key] ? cpps[key] + value : value;
        FSR.c().set('cpps', cpps);
    },
	
    toQueryString: function(){
		var c = FSR.c();
		
		var browser = c.get('browser');
        var o = {
            browser: FSR.Browser.Type.name + ' ' + FSR.Browser.Type.version,
            os: FSR.Browser.Platform.os,
            pv: c.get('pv'),
            url: c.get('current'),
            ref_url: c.get('ref_url'),
			locale: c.get('locale') || '',
			site: c.get('site') || '',
			referrer: c.get('referrer') || '',
			terms: c.get('terms') || '',
			sessionid: c.get('rid') || '',
			flash: FSR.Browser.Plugins.Flash.version
       };

        var cpps = c.get('cpps') ||
        {};
        var h = new FSR.Hash(cpps);
        
        var other = o ||
        {};
        for (k in other) 
            h.set(k, other[k]);
        
        var qs = h.toQueryString('cpp');
        
        return qs;
    }
});

FSR.Service = new FSR.Class({

    Implements: [FSR.Events, FSR.Options],
    
    options: {        /*onFSR.Service: FSR.$empty,
         onSuccess: FSR.$empty,
         onFailure: FSR.$empty,
         onError: FSR.$empty,
         host: '',
         path: '',
         url: '',
         params: '',
         success: ''*/
    },
    
    initialize: function(options){
        this.setOptions(options);
    },
    
    onStateChange: function(status){
        if (!this.running) 
            return;
        this.running = false;
        this.status = 0;
        FSR.$try(function(){
            this.status = status;
        }.fsr$bind(this));
        if (this.status == 1) {
            this.success();
        }
        else if(this.status == 0) {
            this.failure();
        }
        else if(this.status == -1) {
            this.error();
        }
    },
    
    success: function(){
        this.onSuccess();
    },
    
    onSuccess: function(){
        this.fsr$fireEvent('complete').fsr$fireEvent('success');
    },
    
    failure: function(){
        this.onFailure();
    },
    
    onFailure: function(){
        this.fsr$fireEvent('complete').fsr$fireEvent('failure');
    },
    
    error: function(){
        this.onError();
    },
    
    onError: function(){
        this.fsr$fireEvent('complete').fsr$fireEvent('error');
    },

    ping: function(){
        this.running = true;
        var self = this;
		
		var params = this.options.params || {};
		params['protocol'] = document.location.protocol;
		params['uid'] = FSR.$time();
		
        var qs = FSR.Hash.toQueryString(params);
        var url = document.location.protocol + '//' + this.options.host + this.options.path  + this.options.url + '?' + qs;
        new FSR.Asset.image(url, {
            'onload': function(image){
				if (image.width == self.options.success)
                	self.onStateChange(1);
				else
                	self.onStateChange(0);
            },
            
            'onerror': function(){
                self.onStateChange(-1);
            },
            
            'onabort': function(){
                self.onStateChange(0);
            }
        });
        
        return this;
    },
    
    cancel: function(){
        if (!this.running) 
            return this;
        this.running = false;
        this.fsr$fireEvent('cancel');
        return this;
    }
    
});

/*
Script: FSR.RR.js
	The FSR.RR Core. Contains FSR.RR initialization. Robotreplay Integration code
*/

FSR.RR = new FSR.Hash({
	hasRR: function() {
		if (typeof robotreplay != "undefined")
			return true;
		return false;
	},
	setOKTransmit: function() {
		if (this.hasRR()) {
			var replay_id = robotreplay.Session.rr_group_session_id;
			robotreplay.Log.setOKTransmit();
			FSR.CPPS.set('replay_id', replay_id);
		}
	},
	recordEvent: function(eventName, eventValue) {
		if (this.hasRR())
			robotreplay.Log.push(eventName, eventValue);
	},
	cancelRecord: function() {
		if (this.hasRR())
			robotreplay.Log.cancelRecord();		
	},
	getPosition: function(elid) {
		if (this.hasRR())
			return robotreplay.Dom.getAbsoluteCoords(document.getElementById(elid));
		else
			return {position:false}
	}
	
});

FSR.services = {
    survey: {
        host: 'survey.foreseeresults.com',
        path: '/survey',
        url: '/display'
    },
    
    check: {
        host: 'controller2.foreseeresults.com',
        path: '/fsrSurvey',
        url: '/OTCImg',
        success: 3
    },
    
    event: {
        host: 'events.foreseeresults.com',
        path: '/rec',
        url: '/process',
        enabled: true
    },
    
    domain: {
        host: 'survey.foreseeresults.com',
        path: '/survey',
        url: '/FSRImg',
        success: 3
    }
}
FSR.UnsupportedBrowsers = {
    Explorer: 5.5,
    Safari: 2,
    Firefox: 1.4
}

FSR.SupportedPlatforms = {
    win32: true,
    mac: true,
    linux: true,
	iphone: false,
	blackberry: false,
	wince: false,
	other: false
}
FSR.$P = function(){
    return FSR.properties;
};

FSR.c = function(){
    return new FSR.Hash.Cookie('foresee.' + FSR.site.cookie, {
        path: '/',
        domain: FSR.site.domain || false
    });
};

FSR.log = function(msg, param){
    if (!FSR.services.event.enabled)
        return;

	var c = FSR.c()
	
    new FSR.RemoteEvent('logit', {
        host: FSR.services.event.host,
        path: FSR.services.event.path,
        url: FSR.services.event.url
    }).send({
    	'cid' : FSR.id,
    	'rid' : c.get('rid'),
    	'cat' : c.get('sd').name,
    	'sec' : c.get('sd').section || '',
    	'type' : c.get('qual') || '',
    	'site' : c.get('site') || '',
    	'lang' : c.get('locale') || FSR.locale || '',
        'msg': msg,
        'param': param,
        'tmz' : new Date().getTimezoneOffset()*60000
    });
};

FSR.popNow = function(sp){
    FSR.pop(sp, 'now');
};

FSR.popLater = function(sp){
    FSR.pop(sp, 'later');
};

FSR.popImmediate = function(){
    FSR.pop(100, 'now');
};

FSR.popFeedback = function(){
	FSR.controller.popFeedback();
};

FSR.pop = function(sp, when){
    var tsp = sp;
    if (!tsp)
        tsp = FSR.controller.sd.criteria.sp;

    var twhen = when;
    if (!twhen)
        twhen = FSR.controller.sd.pop.when;

    var tsv = FSR.controller.sd.sv;

    if (!(tsv <= tsp))
        return;

    if (twhen == 'now') {
        if (!(FSR.controller.surveyShown() && tsp < 100)) {
            FSR.controller.popImmediate();
        }
    }
    else if (twhen == 'later') {
        if (!FSR.controller.trackerRunning()) {
            FSR.controller.popTracker();
        }
    }
};

FSR.close = function(){
    FSR.controller.cancelTracker();
};

FSR.run = function(){
    FSR.controller.run(false);
};

var ForeSee = {
    CPPS: {
        fsr$set: function(name, value){
            FSR.CPPS.set(name, value);
        }
    }
};

FSR.accepted = function(locale){
	FSR.language(locale);
    FSR.controller.accepted();
    FSR.idhtml.hide();
}

FSR.declined = function(locale){
	FSR.language(locale);
    FSR.controller.declined();
    FSR.idhtml.hide();
}

FSR.qualified = function(){
    FSR.controller.qualified();
    FSR.idhtml.hide();
}

FSR.language = function(locale){
	if (!locale)
		return;
	FSR.locale = locale;
	FSR.c().set('locale', locale);
}

FSR.qualify = function(q){
    FSR.canceled = false;
    FSR.qid = q;
	FSR.c().set('qual', q);
};

FSR.cancel = function(){
    FSR.canceled = true;
};

FSR.canceled = false;

FSR.SurveyController = new FSR.Class({

    Implements: FSR.Options,

    options: {},

    initialize: function(options){
        this.setOptions(options);
        FSR.controller = this;
    },

    load: function(){
        if (!FSR.enabled) {
			return;
		}
        
        if (window != window.top) {
            return;
        }

        var self = this;
        new FSR.Asset.javascript((FSR.js_files || FSR.files) + 'foresee-surveydef.js', {
            id: 'foresee-surveydef',
            onload: function(){
                fsr$dbug.log('Survey Definitions Loaded.');
				self.def_loaded = true;
				self.run(true);
            }
        });
    },

    run: function(init){
		if (!this.def_loaded)
			return;
			
		if (init) {
			if (!this.init())
				return;
		}

        if (!this.setup())
            return;
			
		this.cpp();

        var p;

        this.sd = this.pd;
        this.sdi = this.pdi;
        p = this.process()


        if (p)
            return;

        this.sd = this.cd;
        this.sdi = this.cdi;

        p = this.process();
    },

    process: function(){

        if (!this.sd)
            return false;

        if (this.sd.type == 'current') {
            FSR.c().set('sd', {
                idx: this.sd.idx,
                name: this.sd.name,
				section: this.sd.section || ''
            });
        }

        if (this.processTracker()) {
            var self = this;
            (function(){
                self.launch('tracker');
            }).fsr$delay(1);
            return true;
        }

        if (this.processInvite()) {
            var self = this;
			self.processAlt();
            (function(){
                self.launch('invite');
            }).fsr$delay(1);
            return true;
        }

        if (this.sd.type == 'current') {            
            if (this.inviteAccepted() && !this.surveyShown()) {
                this.setupLinks('pop', this.popLink);
                this.setupLinks('cancel', this.cancelTracker);
            }
			
            if (!this.inviteAccepted()) {
				this.setupLinks('attach', this.popAttach);
			}
			
 			if (this.trackerRunning()) {
				this.setupLinks('pause', this.pause);
			}
       }

        return false;
    },

    processTracker: function(){
        if (!this.shouldTrack())
            return false;

        if (!this.trackerRunning())
            return false;

        return true;
    },

    shouldTrack: function(){
		if (!this.sd.ls)
			return false;

        if (this.sd.type == 'previous') {
            if (!(this.sd.pop.when == 'later') || !(this.sd.pop.after == 'leaving-section'))
                return false;
        }
        else if (this.sd.type == 'current') {
            if (!(this.sd.pop.when == 'now'))
                return false;
        }

        return true;
    },

    trackerRunning: function(){
        if (FSR.$defined(FSR.c().get('tracker')))
            return true;

        return false;
    },

    processInvite: function(){
        if (this.inviteShown())
            return false;

        if (!this.shouldInvite())
            return false;

        return true;
    },

    shouldInvite: function(){
		if (this.sd.invite === false)
			return false;
		
        if (this.sd.exclude) {
            var e = false;
            if (!e) {
                e = this.checkExclude(this.sd.exclude.local || [], document.location.href);
            }

            if (!e) {
                e = this.checkExclude(this.sd.exclude.referer || [], document.referrer);
            }

            if (e) {
                var c = FSR.c();
                var v = c.get('ec');
                this.sd.ec = v[this.sd.name] = v[this.sd.name] + 1;
                c.set('ec', v);
                return false;
            }
        }

        var when = (this.sd.type == 'previous') ? 'onexit' : 'onentry'
        if (this.sd.invite && this.sd.invite.when != when)
            return false;

		if (!this.sd.ls)
			return false;

        if (!(this.sd.sv > 0 && this.sd.sv <= this.sd.criteria.sp))
            return false;

        return true;
    },

    processAlt: function(){
		if (this.sd.alt) {
			var empty;
			var sv = FSR.$random(0, 100);
			var sp = 0;
	        var a = this.sd.alt;
	        for (var i = 0, len = a.length; i < len; i++) {
				sp += a[i].sp;
	            if (sv <= sp) {
					if (a[i].url) {
						this.sd.pop.what = 'url';
						this.sd.pop.url = a[i].url;
					}
					else if (a[i].script) {
						this.sd.pop.what = 'script';
						this.sd.pop.script = a[i].script;
					}
					delete this.sd.invite;
					break;
            	}
        	}	
		}
    },

    inviteShown: function(){
        if (FSR.$defined(FSR.c().get('invite')))
            return true;

        return false;
    },

    inviteAccepted: function(){
        if (FSR.c().get('invite') == 1)
            return true;

        return false;
    },

    surveyShown: function(){
        if (FSR.$defined(FSR.c().get('survey')))
            return true;

        return false;
    },

    launch: function(target){
        if (target == 'invite') {
            this.attemptInvite();
        }
        else if (target == 'tracker') {
            this.popImmediate();
        }
    },

    checkExclude: function(list, source){
        for (var j = 0, n = list.length; j < n; j++) {
            if (source.match(list[j])) {
                return true;
            }
        }

        return false;
    },

    attemptInvite: function(){
        var self = this;

        var fn = 'invite'
		if (FSR.$P().mode == 'hybrid') {
			fn = 'checkDomain';
        }

        new FSR.Service({
            host: FSR.services.check.host,
            path: FSR.services.check.path,
            url: FSR.services.check.url,
            success: FSR.services.check.success,

            onSuccess: function(){
                self[fn]();
            },

            onFailure: function(){
            },

            onError: function(){
                self[fn]();
            }
        }).ping();
    },

    checkDomain: function(){
        var self = this;

        var fn = 'invite'

        new FSR.Service({
            host: FSR.services.domain.host,
            path: FSR.services.domain.path,
            url: FSR.services.domain.url,
            params: {
                'do': 0
            },
            success: FSR.services.check.success,

            onSuccess: function(){
                self[fn]();
            },

            onFailure: function(){
            }
        }).ping();
    },

    setupLinks: function(type, fn){
        if (!this.sd.links) 
            return;
        
        var linked = 0;
        var links = this.sd.links[type] || [];
        for (var i = 0, l = links.length; i < l; i++) {
            var x = this.link(links[i].tag, links[i].attribute, links[i].patterns || [], links[i].qualifier, fn, {'sp': links[i].sp, 'when': links[i].when});
            linked = linked + x;
        }
        fsr$dbug.log('linked (' + type + '): ' + linked);
    },

    link: function(tag, attribute, patterns, qualifier, fn, params){
		var self = this;
        var linked = 0;
        FSR.Array.each($$fsr(tag), function(el){
            for (var i = 0, l = patterns.length; i < l; i++) {
                if (el[attribute] && (el[attribute] + '').match(patterns[i])) {
                    linked++;
                    el.fsr$addEvents({
                        'click': function(){
							if (qualifier) {
								FSR.qualify(qualifier);
							}
                            fn.call(self, params);
                        }
                    })
                    break;
                }
            }
        });
 		return linked;
    },

    init: function(){
        fsr$dbug.log('======INIT=======');

        var c = FSR.c();

        var pv = c.get('pv') ? c.get('pv') + 1 : 1;
        c.set('pv', pv);
        fsr$dbug.log('pv: ' + pv);

        c.set('paused', '0');
        this.ralive = true;

        // Check of cookies are enabled
        c = FSR.c();
        pv = c.get('pv');
        if (!pv) {
            fsr$dbug.log('Exit...cookies are not enabled.');
            return false;
        }

        if (!this.trackerRunning()) {
            clearInterval(fsr$timer);
            FSR.Cookie.dispose('foresee.alive', {
                path: '/',
                domain: FSR.site.domain || false
            });
        }

        var browser = FSR.Browser;
        fsr$dbug.log('browser: ' + browser.Type.name + ' ' + browser.Type.version + ' on ' + browser.Platform.os);

        if (!FSR.SupportedPlatforms[browser.Platform.name]) {
                fsr$dbug.log('Platform not surpported.');
                return false;
        }

        if (FSR.UnsupportedBrowsers[browser.Type.name]) {
            if (browser.Type.version <= FSR.UnsupportedBrowsers[browser.Type.name]) {
                fsr$dbug.log('Browser not surpported.');
                return false;
            }
        }
		

        if (this.validateIP() == 0) {
            fsr$dbug.log('Invalid IP Address.');
            return false;
        }

        var timeout;
        if (FSR.$defined(c.get('finish'))) {
            var ptimeout = c.get('timeout');
            var loadtime = ((FSR.$time() - c.get('finish')) / 1000);
            fsr$dbug.log('ptimeout: ' + ptimeout);
            fsr$dbug.log('loadtime: ' + loadtime);
            timeout = (0.90 * ptimeout) + (0.10 * (loadtime * 2));
            if (timeout < 2)
				timeout = 2;
            else if (timeout > 5)
				timeout = 5;
        }
        else {
            timeout = FSR.$P().tracker.timeout;
        }
        c.set('timeout', timeout);
        fsr$dbug.log('timeout: ' + timeout);

        if (!c.get('start')) {
            var rd;
            if (rd = FSR.Cookie.read('foresee' + '.repeatdays', {
                path: '/',
                domain: FSR.site.domain || false
            })) {
                fsr$dbug.log('Persistent Cookie Found: ' + rd);
                return false;
            }

            c.set('start', FSR.$time());

            var self = this;
            this.dhtml_win = 1;
            new FSR.Asset.javascript((FSR.js_files || FSR.files) + 'foresee-dhtml-popup.js', {
                id: 'foresee-dhtml-popup',
                onload: function(){
                    fsr$dbug.log('DHTML popup script loaded (1).');
                    self.dhtml_win = 2;
                }
            });

            this.dhtml_css = 1;
            new FSR.Asset.css((FSR.image_files || FSR.files) + FSR.$P().invite.css);
			if (FSR.$P().qualifier.css && (FSR.$P().qualifier.css != FSR.$P().invite.css)) {
				new FSR.Asset.css((FSR.image_files || FSR.files) + FSR.$P().qualifier.css);
			}
            this.dhtml_css = 2;

            var id = this.generateid();
            c.set('rid', id);

            if (document.referrer && document.referrer != "") {
				if (FSR.$P().meta.ref_url)
					c.set('ref_url', document.referrer);

				var rmatch = document.referrer.match(/^(\w+\:\/\/)?(((\w+-?\w+\.?))+)\//);
				var referrer = ''
				if (rmatch && rmatch.length >=3) {
					referrer = rmatch[2]
				}
				if (FSR.$P().meta.referer)
					c.set('referrer', referrer);
				fsr$dbug.log('referrer: ' + referrer);
				
				var terms = this.decodeReferrer(document.referrer) || ''
				if (FSR.$P().meta.terms)
        			c.set('terms', terms);
				fsr$dbug.log('search terms: ' + terms);
            }
        }

        fsr$dbug.log('invite: ' + (FSR.$pick(c.get('invite'), '')));
        fsr$dbug.log('tracker: ' + (FSR.$pick(c.get('tracker') || '')));

        return true;
    },

    setup: function(){
        fsr$dbug.log('======SETUP=======');

        var c = FSR.c();

        FSR.sv = FSR.$random(0, 100);

		this.sp = new FSR.Hash.Cookie('foresee.sp', {
            path: '/',
            domain: FSR.site.domain || false
        });

        var cs, cm, cdi, ps, pm, pdi;

        if (c.get('sd')) {
            pdi = c.get('sd').idx;
        }

        cs = document.location.href;
		if (!FSR.$P().meta.url_params)
			cs = cs.replace(/(.*?)(\?.*)/g, "$1");

        c.set('current', cs);

		this.language();
		if (FSR.locale)
        	fsr$dbug.log('language: ' + FSR.locale || '');

		var site = FSR.site.name;
		if (site) {
			c.set('site', site || '');
			fsr$dbug.log('site: ' + site || '');
		}

        var lc = c.get('lc') || {};
        var ls = c.get('ls') || {};
        var ec = c.get('ec') || {};

        cm = this.match(document.location.href)
        if (cm.length != 0) {
            fsr$dbug.log('===CURRENT====');
            for (var i = 0, j = cm.length; i < j; i++) {
                var sd = FSR.surveydefs[cm[i]];
                sd.idx = cm[i];

				this.criteria(sd.criteria);

                sd.lc = lc[sd.name] = lc[sd.name] ? lc[sd.name] + 1 : 1;
                sd.ec = ec[sd.name] = ec[sd.name] ? ec[sd.name] : 0;
                sd.type = 'current'

				this.configLoyalty(sd);

				var ld = this.loyaltyDef(sd);

				var li = this.checkLoyalty(ld, sd.lc, sd.ec);

                if (li > -1) {
					sd.ls= ls[sd.name] = true;
					if (FSR.$type(sd.criteria.lf) == 'array') {
						sd.criteria.lf = sd.criteria.lf[li];
						sd.criteria.sp = sd.criteria.sp[li];
						sd.pop.when = sd.pop.when[li];
						if (FSR.$type(sd.invite.content) == 'array') {
							sd.invite.content = sd.invite.content[li];
						}
					}
                    if (sd.pin) {
                        var p = c.get('p') || {};
                        p[sd.name] = 1;
                        c.set('p', p);
                    }
                }
				else {
					sd.ls = ls[sd.name] = false;
					if (FSR.$type(sd.criteria.lf) == 'array') {
						sd.criteria.lf = sd.criteria.lf[0];
						sd.criteria.sp = sd.criteria.sp[0];
						sd.pop.when = sd.pop.when[0];
						if (FSR.$type(sd.invite.content) == 'array') {
							sd.invite.content = sd.invite.content[0];
						}
					}
				}

                this.configure(sd);

                this.cd = sd;
				cdi = sd.idx;

                break;
            }
            c.set('lc', lc);
            c.set('ls', ls);
            c.set('ec', ec);
        }

        if (FSR.$defined(pdi) && (pdi != cdi)) {
            fsr$dbug.log('===PREVIOUS===');
            var sd = FSR.surveydefs[pdi];
            sd.idx = pdi;

 			this.criteria(sd);

            sd.lc = lc[sd.name];
            sd.ls = ls[sd.name] || false;
            sd.type = 'previous'

			this.configLoyalty(sd);

            this.configure(sd);

            this.pd = sd;
        }

        if (!this.cd && !this.pd)
            return false;

        return true;
    },

    configLoyalty: function(sd){
		if (FSR.$type(sd.criteria.lf) == 'number') {
			sd.criteria.lf = {
				v: sd.criteria.lf,
				o: '>='
			};
		}
	},

    loyaltyDef: function(sd){
		var ld = sd.criteria.lf;
		if (FSR.$type(sd.criteria.lf) == 'object') {
			ld = [sd.criteria.lf];
		}

		return ld;
	},

    checkLoyalty: function(ld, lc, ec){
		var k = -1;
        for (var i = 0, l = ld.length; i < l; i++) {
            if (ld[i].o == '>=') {
                if (lc >= ld[i].v)
					k = i;;
            }
            else if (ld[i].o == '=') {
                if ((lc - ec) == ld[i].v)
					k = i;;
            }
            else if (ld[i].o == '>') {
                if (lc > ld[i].v)
					k = i;
            }
        }

        return k;
    },

    validateIP: function(ip){
        var match = 1;

        var d = FSR.$P().ipexclude;

        if (!d)
            return match;

        var ip;
        if (d.src == 'cookie') {
            if (d.type && d.type == 'client')
                ip = FSR.Cookie.read(d.name, {
                    path: '/',
                    domain: FSR.site.domain || false
                });
            else
                ip = FSR.c().get('ip');
        }
        else if (d.src == 'variable') {
            if (d.type && d.type == 'client')
                ip = window[d.name];
            else
                ip = FSR[d.name];
        }

		ip = ip || '';

        for (var i = 0; i < d.ips.length; i++) {
            if (ip.match(d.ips[i])) {
                match = 0;
                break;
            }
        }
        return match;
    },

    configure: function(sd){
        var c = FSR.c();

        fsr$dbug.log('sid: ' + sd.name);
        fsr$dbug.log('lc: ' + sd.lc);
        fsr$dbug.log('lf: ' + sd.criteria.lf.v + ' (' + sd.criteria.lf.o + ') ');

        sd.sv = FSR.sv;
        fsr$dbug.log('sv: ' + sd.sv);

        if (FSR.$type(sd.criteria.sp) == 'array')
            sd.criteria.sp = sd.criteria.sp[(new Date()).getDay()];

		var lname1 = (!sd.section) ? sd.name : sd.name +  '-' + sd.section
		var lname2 = (!FSR.locale) ? lname1 : lname1 +  '-' + FSR.locale
		sd.criteria.sp = this.sp.get(lname1) || this.sp.get(lname2) || sd.criteria.sp;

        fsr$dbug.log('sp: ' + sd.criteria.sp);

        if (sd.invite)
            sd.invite = FSR.$merge(FSR.$P().invite, sd.invite);

        sd.tracker = FSR.$merge(FSR.$P().tracker, sd.tracker);

        sd.survey = FSR.$merge(FSR.$P().survey, sd.survey);

        sd.qualifier = FSR.$merge(FSR.$P().qualifier, sd.qualifier);

        sd.cancel = FSR.$merge(FSR.$P().cancel, sd.cancel);

        sd.pop = FSR.$merge(FSR.$P().pop, sd.pop);

        sd.repeatdays = FSR.$pick(FSR.$P().repeatdays, sd.repeatdays);
		if (FSR.$type(sd.repeatdays) != 'array') {
			sd.repeatdays = [sd.repeatdays, sd.repeatdays];
		}

        var local = FSR.Array.extend([], FSR.$P().exclude.local);
        if (sd.exclude && sd.exclude.local)
            sd.exclude.local = FSR.Array.extend(local, sd.exclude.local);
        else if (sd.exclude)
            sd.exclude.local = local;
        else
            sd.exclude = {
                'local': local
            };

        var referer = FSR.Array.extend([], FSR.$P().exclude.referer);
        if (sd.exclude && sd.exclude.referer)
            sd.exclude.referer = FSR.Array.extend(referer, sd.exclude.referer);
        else if (sd.exclude)
            sd.exclude.referer = referer;
        else
            sd.exclude = {
                'referer': referer
            };
    },

    unload: function(){
		if (!FSR.enabled)
			return;

        if (!this.runload && this.ralive) {
            this.runload = true;
            this.uninit();
        }
        return;
    },

    uninit: function(){
        var c = FSR.c();

        if (FSR.$P().previous)
			c.set('previous', c.get('current'));
        c.set('finish', FSR.$time());
    },

    match: function(source){
        if (!source)
            return;

        var m = [];

        var d = FSR.surveydefs;
        var pin = FSR.c().get('p') || {};

        for (var i = 0, p, l = d.length, k = 0; i < l; i++) {
            var pk = k;

            p = d[i].include.urls || [];
            for (var j = 0, n = p.length; j < n; j++) {
                if (source.match(p[j])) {
                    m[k++] = i;
                    break;
                }
            }

            if (k != pk)
                break;

            p = d[i].include.cookies || [];
            for (var j = 0, n = p.length; j < n; j++) {
                var value;
                if (value = FSR.Cookie.read(p[j].name, {
                    path: p[j].path || false,
                    domain: p[j].domain || false
                })) {
                    if (value.match(p[j].value || '.')) {
                        m[k++] = i;
                        break;
                    }
                }
            }

            if (k != pk)
                break;

            p = d[i].include.variables || [];            
            for (var j = 0, n = p.length; j < n; j++) {
				var name = p[j].name; var value = p[j].value;
				if (FSR.$type(name) != 'array') {
					name = [name]; value = [value];
				}
                var v, z = true;
            	for (var x = 0, y = name.length; x < y; x++) {
                    try {
                        v = eval(name[x]);
                    } 
                    catch (err) {
						v = '';
                    }
					if (v || v === '') {
						if (!v.match(value[x])) {
							z = false;
							break;
						}
					}
				}
				
				if (z) {
					m[k++] = i;
					break;
				}
            }

            if (k != pk)
                break;

            if (pin[d[i].name])
                m[k++] = i;

            if (k != pk)
                break;
        }

        return m;
    },

    invite: function(){
		FSR.invite = 0;

		if (FSR.locale)
        	FSR.c().set('locale', FSR.locale);

        var self = this;
        if (this.sd.invite) {
            (function(){
				//Invite Shown
            	FSR.log(100, FSR.c().get('current'));
                self.prepareDHTML('invite', 'accepted', 'declined', 'closed');
            }).fsr$delay((this.sd.invite.delay || 0) * 1000);
			if (this.sd.invite.timeout) {
				(function(){
					FSR.idhtml.hide();
				}).fsr$delay(this.sd.invite.timeout * 1000);
			}
        }
        else {
            (function(){
                self.accepted();
                self.closed();

            }).fsr$delay(0);
        }
    },

    prepareDHTML: function(type, accepted, declined, closed){
        var self = this;
        if (!FSR.$defined(this.dhtml_css)) {
            this.dhtml_css = 1;
            new FSR.Asset.css((FSR.image_files || FSR.files) + this.sd[type].css);
            this.dhtml_css = 2;
        }

        if (!FSR.$defined(this.dhtml_win)) {
            this.dhtml_win = 1;
            new FSR.Asset.javascript((FSR.js_files || FSR.files) + 'foresee-dhtml-popup.js', {
                id: 'foresee-dhtml-popup',
                onload: function(){
                    fsr$dbug.log('DHTML popup script loaded (2).');
                    self.dhtml_win = 2;
                    self.showDHTML(type, accepted, declined, closed);
                }
            });
        }
        else if (this.dhtml_win == 1) {
            var checker = (function(){
                if (self.dhtml_win == 1)
                    return;
                FSR.$clear(checker);
                self.showDHTML(type, accepted, declined, closed);
            }).fsr$periodical(50);
        }
        else if (this.dhtml_win == 2) {
            (function(){
                self.showDHTML(type, accepted, declined, closed);
            }).fsr$delay(1);
        }
    },

    showDHTML: function(type, accepted, declined, closed){
        var self = this;

        var dhtml = this.sd[type];

        this.page(dhtml);

        var buttons = [];
        if (dhtml.buttons) {
			var i = 0;
			if (dhtml.buttons.accept) {
                buttons[i] = {
                    properties: {
                        id: 'accept'
                    },
                    style: 'fsr_button fsr_accept',
                    text: dhtml.buttons.accept,
                    onClick: function(){
                        self[accepted]();
                    },
                    onMouseover: function(){
                        this.className = 'fsr_closeSticky fsr_button fsr_mouseover_accept';
                    },
                    onMouseout: function(){
                        this.className = 'fsr_closeSticky fsr_button fsr_accept';
                    }
                };
                i++;
            };
			if (dhtml.buttons.decline) {
				buttons[i] = {
					properties: {
						id: 'decline'
					},
					style: 'fsr_button fsr_decline',
					text: dhtml.buttons.decline,
					onClick: function(){
						self[declined]();
					},
					onMouseover: function(){
						this.className = 'fsr_closeSticky fsr_button fsr_mouseover_decline';
					},
					onMouseout: function(){
						this.className = 'fsr_closeSticky fsr_button fsr_decline';
					}
				};
				i++;
			};
        }

        var options = {
            position: {
                x: dhtml.x,
                y: dhtml.y
            },
            wrapWithUi: true,
            uiOptions: {
                width: dhtml.width + 'px',
                baseHref: (FSR.image_files || FSR.files),
                buttons: buttons
            },
            modalOptions: {
                modalStyle: {
                    'background-color': dhtml.bgcolor,
                    'opacity': dhtml.opacity
                },
                'hideOnClick': dhtml.hideOnClick
            },
            requestOptions: {
                evalScripts: true
            }
        };

		FSR[type] = 0;

        var idhtml;
		if (dhtml.content) {
            options.content = dhtml.content;
			idhtml = new FSR.StickyWinModal(options);
		}
		else {
            options.url = (FSR.html_files || FSR.files) + (dhtml.url.dhtml || dhtml.url);
            idhtml = new FSR.StickyWinModal.Ajax(options);
		}

        if (closed) {
			idhtml.fsr$addEvent('onClose', function(){
				self[closed]();
			});
		}

        if (FSR.Browser.Type.name != 'Explorer') {
			var h = this.sd.invite.hide;
			for (var i = 0, len = h.length; i < len; i++) {
				if ($fsr(h[i])) 
					$fsr(h[i]).fsr$setStyle('visibility', 'hidden');
			}
		}

		if (dhtml.content)
        	idhtml.show();
		else
        	idhtml.update();

		FSR.idhtml = idhtml;
    },

    accepted: function(){
        FSR.invite = 1;
		//Invite Accepted
        FSR.log(101);
        FSR.c().set('invite', FSR.invite);

		this.setRepeatdays(0);
		
        if (FSR.$P().mode == 'hybrid') {
            new FSR.Service({
                host: FSR.services.domain.host,
                path: FSR.services.domain.path,
                url: FSR.services.domain.url,
                params: {
                    'do': 1,
                    'rw': this.sd.repeatdays[0]*24*60
                }
            }).ping();
        }

		// tell robotreplay to begin transmitting		
		FSR.RR.setOKTransmit();

        var self = this;
        //(function(){ //Can't do this...blocked by popup blockers
        	self.processAccept();
        //}).fsr$delay(1);
    },

    declined: function(){
        FSR.invite = -1;
		//Invite Declined
        FSR.log(102);
        FSR.c().set('invite', FSR.invite);

		this.setRepeatdays(1);

		// tell robotreplay to stop recording
		FSR.RR.cancelRecord();
	},

    closed: function(){
        if (FSR.Browser.Type.name != 'Explorer') {
			var h = this.sd.invite.hide;
			for (var i = 0, len = h.length; i < len; i++) {
				if ($fsr(h[i])) 
					$fsr(h[i]).fsr$setStyle('visibility', 'visible');
			}
		}
    },

    qualified: function(){
        FSR.qualifier = 1;
		//Qualifier Accepted
        FSR.log(301);
        FSR.c().set('qualifier', FSR.qualifier);

        var self = this;
        //(function(){ //Can't do this...blocked by popup blockers
        	self.processQualifier();
        //}).fsr$delay(1);
    },

    processAccept: function(){
        
        if (this.sd.pop.when == 'later') {
            if (this.sd.pop.tracker) 
                this.popTracker();
            this.setupLinks('pop', this.popLink);
            this.setupLinks('cancel', this.cancelTracker);
            this.setupLinks('pause', this.pause);
        }
        else if (this.sd.pop.when == 'now') {
            FSR.c().set('survey', 1);
            if (this.sd.pop.what == 'survey') {
                this.popSurvey();
            }
            else if (this.sd.pop.what == 'qualifier') {
                this.popQualifier();
            }
            else if (this.sd.pop.what == 'url') {
                this.popUrl();
            }
            else if (this.sd.pop.what == 'script') {
                this.popScript();
            }
            else if (this.sd.pop.what == 'movie') {
            }
        }
        else if (this.sd.pop.when == 'both') {
            this.popTracker();
            this.popSurvey();
        }
    },

    processQualifier: function(){
        if (!FSR.canceled) {
            this.popSurvey();
        }
        else {
            this.popCancel();
        }
    },

    popImmediate: function(){
        var self = this;

        var c = FSR.c();

        if (this.trackerRunning()) {
            if (FSR.Browser.Type.name != 'Firefox' || !this.sd.qualifier.content) {
                c.set('force', 1);
            }
            else {
				this.cancelTracker();
                (function(){
					//Qualifier Shown
                	FSR.log(300, FSR.c().get('current'));
                    self.prepareDHTML('qualifier', 'qualified');
                }).fsr$delay((this.sd.qualifier.delay || 0) * 1000);
            }
        }
        else {
            FSR.c().set('survey', 1);
            if (this.sd.pop.what == 'survey') {
                this.popSurvey();
            }
            else if (this.sd.pop.what == 'qualifier') {
                this.popQualifier();
            }
            else if (this.sd.pop.what == 'url') {
                this.popUrl();
            }
            else if (this.sd.pop.what == 'script') {
                this.popScript();
            }
            else if (this.sd.pop.what == 'movie') {
            }
        }
    },

    popSurvey: function(){
        var survey = this.sd.survey;
        var pop = this.sd.pop;
        this.popMain(this.sid(), survey.width, survey.height, pop.pu, survey.loading, '400');
    },

    popFeedback: function(){
        var sd = FSR.$P();

		var sid = 'feedback';
        var l = FSR.locale;
        if (l) {
            sid = sid + '-' + l;
        }
		this.popMain(sid, sd.survey.width, sd.survey.height, false, sd.survey.loading, '600');
    },

	popMain: function(sid, width, height, pu, loading, type){
        var service = FSR.services.survey;

		var c = FSR.c();
		var id = c.get('rid');
		var hid = this.hash(id);
		var current = c.get('current');
		
		var params = new FSR.Hash({
            'sid': sid,
            'cid': FSR.id,
			'pattern': current,
			'a': id,
			'b': hid,
			'c': 24*60*60*1000,
            'version': FSR.version
        }).toQueryString();

        var cpps = FSR.CPPS.toQueryString();

        var url = document.location.protocol + '//' + service.host + service.path + service.url + '?' + params + '&' + cpps;

        if (loading) {
            this.page(FSR.$P().loading);
            url = (FSR.html_files || FSR.files) + FSR.$P().loading.url + '?url=' + url;
        }

        this.pop('fsr' + type, url, (window.screen.width - width) / 2, (window.screen.height - height) / 2, width, height, pu);
        FSR.log(type, FSR.c().get('current'));
    },

    popTracker: function(){
		fsr$timer = setInterval(fsr$setAlive, 1000);
        this.popOther(this.sd.tracker, true, '200');
    },

    popQualifier: function(){
        this.popOther(this.sd.qualifier, this.sd.pop.pu, '300');
    },

    popCancel: function(){
         this.popOther(this.sd.cancel, false, '500')
    },

    popLink: function(){
        if (!this.surveyShown()) {
            this.popImmediate();
        }
	},

    cancelTracker: function(){
        if (this.trackerRunning()) {
			//fsr200 Tracker window name
            var w = window.open('', 'fsr200');
            if (w) {
                w.close();
            }
        }
    },

    popOther: function(d, pu, type){
        this.page(d);

        var left = (window.screen.width - d.width) / 2;
        var top = (window.screen.height - d.height) / 2;

        var url = (FSR.html_files || FSR.files) +  (d.url.pop || d.url);
        var params = new FSR.Hash({
            'siteid': FSR.siteid,
            'domain': FSR.site.domain,
            'sdidx': this.sd.idx
        }).toQueryString();
		url = url  + '?' + params;

        this.pop('fsr' + type, url, left, top, d.width, d.height, pu);
        FSR.log(type, FSR.c().get('current'));
    },

    popAttach: function(p){
        var self = this;
        
        if (p.sp) {
            this.sd.criteria.sp = p.sp;
        }
        if (p.when) {
            this.sd.pop.when = p.when;
        }
		
        if (!(this.sd.sv > 0 && this.sd.sv <= this.sd.criteria.sp)) 
            return;
        
        if (FSR.locale) 
            FSR.c().set('locale', FSR.locale);
        
        (function(){
            self.accepted();
            self.closed();
            
        }).fsr$delay(0);
	},
	
	popUrl: function(){
        var width = FSR.$P().survey.width;
        var height = FSR.$P().survey.height;
        this.pop('fsrOther', this.sd.pop.url, (window.screen.width - width) / 2, (window.screen.height - height) / 2, width, height);
    },

	popScript: function(){
        new FSR.Asset.javascript(this.sd.pop.script);
    },

    pause: function(){
        var c = FSR.c();
        c.set('paused', '1');
	},

	sid: function(){
        var c = FSR.c();

        var sid = this.sd.name;

        var site = this.sd.site;
        if (site) {
            sid = sid + '-' + site;
        }

        var sec = this.sd.section;
        if (sec) {
            sid = sid + '-' + sec;
        }

        var q1 = this.sd.pop.now;
        if (q1) {
            sid = sid + '-' + q1;
        }

        var qual = c.get('qual');
        if (qual) {
            sid = sid + '-' + qual;
        }

        var loc = c.get('locale');
        if (loc) {
            sid = sid + '-' + loc;
        }

        return sid;
    },

    pop: function(name, url, left, top, width, height, under, delay){
        (function(){
            new FSR.Browser.Popup(url, {
                name: name,
                toolbar: 0,
                location: 0,
                directories: 0,
                status: 0,
                scrollbars: 1,
                resizable: 1,
                width: width,
                height: height,
                x: left,
                y: top,
                blur: under,
                menubar: 0
            });
        }).fsr$delay(delay || 0);
    },

    language: function(){
        var d = FSR.$P().language;

        if (!d)
            return;

		var locale = d.locale;

        var source;
        if (d.src == 'location') {
            source = document.location.href;
        }
        else if (d.src == 'cookie') {
            if (d.type && d.type == 'client')
                source = FSR.Cookie.read(d.name, {
                    path: '/',
                    domain: FSR.site.domain || false
                });
            else
                source = FSR.c().get('lang');
        }
        else if (d.src == 'variable') {
            if (d.type && d.type == 'client')
                source = window[d.name];
            else
                source = FSR[d.name];
        }

		source = source || '';

        var l = d.locales || [];
        for (var i = 0, len = l.length; i < len; i++) {
            if (source.match(l[i].match)) {
				locale = l[i].locale;
                break;
            }
        }

		FSR.locale = locale;
    },

    page: function(d){
        var locale = FSR.c().get('locale');

        if (!locale)
            return;

        var p = d.locales || [];
        for (var i = 0, len = p.length; i < len; i++) {
            if (p[i].locale == locale) {
                if (p[i].url)
                	d.url = p[i].url;
                if (p[i].content)
                	d.content = p[i].content;
				if (p[i].buttons) {
					d.buttons = {accept: '', decline: ''};
					if (p[i].buttons.accept)
						d.buttons.accept = p[i].buttons.accept;
					if (p[i].buttons.decline)
						d.buttons.decline = p[i].buttons.decline;
				}
                if (p[i].width)
                    d.width = p[i].width;
                if (p[i].height)
                    d.height = p[i].height;
                break;
            }
        }
    },

    criteria: function(d){
        var locale = FSR.locale;

        if (!locale)
            return;

        var p = d.locales || [];
        for (var i = 0, len = p.length; i < len; i++) {
            if (p[i].locale == locale) {
                d.sp = p[i].sp;
                d.lf = p[i].lf;
                break;
            }
        }
    },

	generateid: function(){
		var id = '';
		
		/*
        new FSR.RemoteEvent('getsessionid', {
            host: FSR.services.event.host,
            path: FSR.services.event.path,
            url: FSR.services.event.url
        }).send({
            'id': 'foresee.' + FSR.site.cookie
        });
        */
		
		id = ((new Date())-0) + "_" + Math.round(Math.random()*1000000);
		
		return id;
    },

    decodeReferrer: function(referrer){
        referrer = decodeURIComponent(referrer);
        var query;

		var matches = document.referrer.match(/[?&]q=([^&]*)/) || document.referrer.match(/[?&]p=([^&]*)/) || document.referrer.match(/[?&]query=([^&]*)/);
  		if (!matches)
			return query;
			
  		var query = unescape(matches[1]);
        if (query) {
            query = query.replace(/\+/g, " ");
        }

        return query;
    },
	
    setRepeatdays: function(d){
        if (this.sd.repeatdays[d]) {
            FSR.Cookie.write('foresee' + '.repeatdays', this.sd.repeatdays[d], {
                path: '/',
                domain: FSR.site.domain || false,
                duration: this.sd.repeatdays[d]
            });
        }
    },
	
    hash: function(id){
        var v = id.split('_');
        return ((v[0] * 3) + 1357) + '' + ((v[1] * 9) + 58);
    },
	
    cpp: function(){
        var cpps = FSR.$P().cpps;
        
        if (!cpps) 
            return;
        
        for (var name in cpps) {
            if (!cpps.hasOwnProperty(name)) 
                continue;
				
			var cpp = cpps[name];
            var value;
            
            if (cpp.source == 'url') {
                var p = cpp.patterns || [];
                for (var j = 0, n = p.length; j < n; j++) {
                    if (document.location.href.match(p[j].regex)) {
                        value = p[j].value;
                        break;
                    }
                }
            }
            
            if (cpp.source == 'parameter') {
                value = this.parameter(cpp.name);
            }
            
            if (cpp.source == 'cookie') {
                value = FSR.Cookie.read(cpp.name, {
                    path: cpp.path || false,
                    domain: cpp.domain || false
                });
            }
            
            
            if (cpp.source == 'varialble') {
                try {
                    value = eval(cpp.name);
                } 
                catch (err) {
                    value = false;
                }
            }
           
            if (value) {
                FSR.CPPS.set(name, value);
            }
        }
    },
	
    parameter: function(name){
        name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
        var regexS = "[\\?&]" + name + "=([^&#]*)";
        var regex = new RegExp(regexS);
        var results = regex.exec(window.location.href);
        if (results == null) 
            return false;
        else 
            return results[1];
	}
});

new FSR.SurveyController({});

window.fsr$addEvent('domready', function(){
    (function(){
        FSR.controller.load();
    }).fsr$delay(1);
});

window.fsr$addEvent('unload', function(){
    FSR.controller.unload();
});
