// File: TagSystem/js/assemblies/Core.js
// Dependencies: Protocol class (TagSystem/js/assemblies/Protocol.js)



// Capacent static class
var JSON = {};
(function() {
	function f(n) {
		return n < 10 ? '0' + n : n;
	}
	if (typeof Date.prototype.toJSON !== 'function') {
		Date.prototype.toJSON = function(key) {
			return isFinite(this.valueOf()) ?
							this.getUTCFullYear() + '-' +
							f(this.getUTCMonth() + 1) + '-' +
							f(this.getUTCDate()) + 'T' +
							f(this.getUTCHours()) + ':' +
							f(this.getUTCMinutes()) + ':' +
							f(this.getUTCSeconds()) + 'Z' : null;
		};
		String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function(key) {
			return this.valueOf();
		};
	}
	var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
		escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
		gap,
		indent,
		meta = {
			'\b': '\\b',
			'\t': '\\t',
			'\n': '\\n',
			'\f': '\\f',
			'\r': '\\r',
			'"': '\\"',
			'\\': '\\\\'
		},
		rep;
	function quote(string) {
		escapable.lastIndex = 0;
		return escapable.test(string) ? '"' + string.replace(escapable, function(a) {
			var c = meta[a];
			return typeof c === 'string' ? c :
				'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
		}) + '"' : '"' + string + '"';
	};

	function str(key, holder) {
		var i, k, v, length, mind = gap, partial, value = holder[key];
		if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
			value = value.toJSON(key);
		}
		if (typeof rep === 'function') {
			value = rep.call(holder, key, value);
		}
		switch (typeof value) {
			case 'string':
				return quote(value);
			case 'number':
				return isFinite(value) ? String(value) : 'null';
			case 'boolean':
			case 'null':
				return String(value);
			case 'object':
				if (!value) {
					return 'null';
				}
				gap += indent;
				partial = [];
				if (Object.prototype.toString.apply(value) === '[object Array]') {
					length = value.length;
					for (i = 0; i < length; i += 1) {
						partial[i] = str(i, value) || 'null';
					}
					v = partial.length === 0 ? '[]' :
						gap ? '[\n' + gap +
						partial.join(',\n' + gap) + '\n' +
						mind + ']' :
						'[' + partial.join(',') + ']';
					gap = mind;
					return v;
				}
				if (rep && typeof rep === 'object') {
					length = rep.length;
					for (i = 0; i < length; i += 1) {
						k = rep[i];
						if (typeof k === 'string') {
							v = str(k, value);
							if (v) {
								partial.push(quote(k) + (gap ? ': ' : ':') + v);
							}
						}
					}
				} else {
					for (k in value) {
						if (Object.hasOwnProperty.call(value, k)) {
							v = str(k, value);
							if (v) {
								partial.push(quote(k) + (gap ? ': ' : ':') + v);
							}
						}
					}
				}
				v = partial.length === 0 ? '{}' :
					gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
					mind + '}' : '{' + partial.join(',') + '}';
				gap = mind;
				return v;
		}
	}
	if (typeof JSON.stringify !== 'function') {
		JSON.stringify = function(value, replacer, space) {
			var i;
			gap = '';
			indent = '';
			if (typeof space === 'number') {
				for (i = 0; i < space; i += 1) {
					indent += ' ';
				}
			} else if (typeof space === 'string') {
				indent = space;
			}
			rep = replacer;
			if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
				throw new Error('JSON.stringify');
			}
			return str('', { '': value });
		};
	}
	if (typeof JSON.parse !== 'function') {
		JSON.parse = function(text, reviver) {
			var j;
			function walk(holder, key) {
				var k, v, value = holder[key];
				if (value && typeof value === 'object') {
					for (k in value) {
						if (Object.hasOwnProperty.call(value, k)) {
							v = walk(value, k);
							if (v !== undefined) {
								value[k] = v;
							} else {
								delete value[k];
							}
						}
					}
				}
				return reviver.call(holder, key, value);
			}
			cx.lastIndex = 0;
			if (cx.test(text)) {
				text = text.replace(cx, function(a) {
					return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
				});
			}
			if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
				j = eval('(' + text + ')');
				return typeof reviver === 'function' ?
walk({ '': j }, '') : j;
			}
			throw new SyntaxError('JSON.parse');
		};
	}

	var Capacent = {

		Util: {
			attachEvent: function(element, eventName, fn) {
				var eventNameWithOn = 'on' + eventName;
				if (typeof element.addEventListener != 'undefined') {
					element.addEventListener(eventName, fn, false);
				}
				else if (typeof element.document != 'undefined' && typeof element.document.addEventListener != 'undefined') {
					element.document.addEventListener(eventName, fn, false);
				}
				else if (typeof element.attachEvent != 'undefined') {
					element.attachEvent(eventNameWithOn, fn);
				}
				else {
					if (typeof element[eventNameWithOn] == 'function') {
						var existing = element[eventNameWithOn];
						element[eventNameWithOn] = function() {
							existing();
							fn();
						};
					}
					else {
						//setup function
						element[eventNameWithOn] = fn;
					}
				}
			},
			onLoadExternal: function(mywindow, fn) {
				this.attachEvent(mywindow, 'load', fn);
			},
			_onLoadCalls: null,
			onLoad: function(fn) {
				if (this._onLoadCalls == null) {
					var self = this;
					this._onLoadCalls = new Capacent.CallsQueue();
					this.onLoadExternal(window, function() { self._onLoadCalls.call(); });
				}
				this._onLoadCalls.add(fn);
			},
			_isLoaded: false,
			onLoadGuaranteed: function(fn) {
				if (this._isLoaded) {
					fn();
				} else {
					this.onLoad(fn);
				}
			},
			isDomReady: function() {
				return !!(document && document.getElementsByTagName && document.getElementById && document.body);
			},
			onDomReady: function(fn) {
				var self = this;
				if (self.isMSIE()) {
					self.onLoadGuaranteed(fn);
				} else {
					if (!self.isDomReady()) {
						setTimeout(function() { self.onDomReady(fn); }, 20);
						return;
					}
					fn();
				}
			},
			isMSIE: function() {
				return /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent);
			},
			isMSIE6: function() {
				return /msie 6/i.test(navigator.userAgent);
			},
			isFirefox: function() {
				return /firefox/i.test(navigator.userAgent);
			},
			getUrl: function() {
				var url;
				try {
					var doc = window.top;
					while (true) {
						doc = window.top;
						url = doc.location.href;
						if (doc == window.top) {
							break;
						}
					};
				} catch (ex) {
					url = url;
				} finally {
					return url || document.location.href;
				}
			},
			getHostname: function() {
				return document.location.hostname;
			},
			getPageArgs: function(myWindow) {
				var args = {};
				var location = (myWindow || window).location.href.toString();
				(/[?](.+)/).exec(location);
				var urlQuery = RegExp.$1;
				if (urlQuery != "") {
					Capacent.Array.each(urlQuery.split('&'), function(kv) {
						var param = kv.split('=');
						args[param[0]] = param.length == 0 ? null : param[1];
					});
				}
				return args;
			},
			setPageArgs: function(args) {
				var location = window.location.href.toString();
				(/([^?]+)/).exec(location);
				var url = RegExp.$1;
				var splitter = "?";
				for (var k in args) {
					url += splitter + k + "=" + args[k];
					splitter = "&";
				}
				window.location = url;
			},
			setVisibilityForPendentControls: function(show) {
				var d = function(s) {
					var elements = document.getElementsByTagName(s);

					for (var i = 0; i < elements.length; i++) {
						var elem = elements[i];

						if(elem.className.indexOf('urp-no-hide') >= 0){						
						    continue;
						}

						if (!show && elem.style.visibility ==  'hidden') {
							continue;
						}
						var v = show ? (typeof (elem.old_vis) == "undefined" ? 'visible' : elem.old_vis) : 'hidden';
						if (!show) {
							elem.old_vis = elem.style.visibility;
						}
						elem.style.visibility = v;
					}
				}
				d('object');
				d('embed');
				d('iframe');

				if (this.isMSIE()) {
					d('select');
				}
			},
			cancelEvent: function(event) {
				event.cancel = true;
				if (event.preventDefault) event.preventDefault();
				if (event.stopPropagation) event.stopPropagation();
			},
			mergeObjects: function(obj1, obj2) {
				for (attrname in obj2) {
					obj1[attrname] = obj2[attrname];
				}
				return obj1;
			},
			random: function() {
				return Math.ceil(100000 * Math.random());
			},
			convertFunctionToString: function(f) {
				var fName = "__capacentMethod" + this.random().toString();
				window[fName] = f;
				return fName;
			}
		},

		Css: {
			registerexternal: function(mywindow, styleText) {
				var styleElement = mywindow.document.createElement("style");
				styleElement.type = "text/css";
				if (styleElement.styleSheet) {
					styleElement.styleSheet.cssText = styleText;
				} else {
					styleElement.appendChild(mywindow.document.createTextNode(styleText));
				}
				var id = "CustomCSS_" + Math.random();
				styleElement.id = id;
				mywindow.document.getElementsByTagName("head")[0].appendChild(styleElement);
				return id;

			},
			register: function(styleText) {
				this.registerexternal(window, styleText);
			},
			registerUrl: function(url) {
				this.registerUrlExternal(window, url);
			},
			registerUrlExternal: function(mywindow, url) {
				if(Capacent.Css.isRegisteredExternal(mywindow, url)){
					return;
				}
				var linkElement = mywindow.document.createElement("link");
				linkElement.rel = "stylesheet";
				linkElement.type = "text/css";
				linkElement.href = url;
				mywindow.document.getElementsByTagName("head")[0].appendChild(linkElement);
			},
			isRegisteredExternal : function(mywindow, url) {			
				var links = mywindow.document.getElementsByTagName("head")[0].getElementsByTagName('link');
				for(var i = 0; i < links.length; i++){
					if(links[i].href.indexOf(url) > 0){
						return true;
					}
				}
				return false;
			},
			isRegistered : function(url) {			
				return this.isRegisteredExternal(window, url);
			},
			createCssBuilder: function() {
				var cssBuilder = {
					_rules: [],
					_currentRule: null,
					createRule: function(selector) {
						this._currentRule = {
							selector: selector,
							properties: {}
						};
						this._rules.push(this._currentRule);
					},
					addProperty: function(name, value) {
						if (Capacent.String.isNullOrEmpty(value)) {
							return;
						}
						this._currentRule.properties[name] = value;
					},
					toString: function() {
						var result = '';
						for (var i = 0; i < this._rules.length; i++) {
							var rule = this._rules[i];
							result += rule.selector + '{';
							for (var property in rule.properties) {
								result += property + ': ' + rule.properties[property] + ';';
							}
							result += '}';
						}
						return result;
					}
				};
				return cssBuilder;
			}
		},

		Ajax: {
			_crossDomainCallInited: false,
			crossDomainCall: function(url, method, params, onSuccess, onFailure, timeout) {
				if (this._crossDomainCallInited == false) {
					// ONLY FOR BACKWARD COMPATIBILITY
					if (typeof ($__BPN) == 'undefined') {
						$__BPN = {};
					}
					if (typeof ($__BPN.Protocol) == 'undefined') {
						$__BPN.Protocol = {};
					}
					if (typeof ($__BPN.Protocol.Complete) == 'undefined') {
						$__BPN.Protocol.Complete = Protocol.Complete;
					}
					// ONLY FOR BACKWARD COMPATIBILITY
					this._crossDomainCallInited = true;
				}
				var request = new Protocol(url);
				if (typeof (timeout) != "undefined") {
					request.Timeout = timeout;
				}
				request.execute(method, params, onSuccess, onFailure);
			}
		},

		String: {
			isNullOrEmpty: function(str) {
				return str == undefined || str == null || /^\s*$/.test(str);
			},
			replaceEx: function(str, data) {
				for (var p in data) {
					var r = new RegExp("{" + p + "}", "gi");
					str = str.replace(r, data[p]);
				}
				return str;
			}
		},

		RegularCookie: {
			set: function(name, value, days) {
				value = this._escape(value);
				if (days) {
					var date = new Date();
					date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
					var expires = "; expires=" + date.toGMTString();
				} else {
					var expires = '';
				}
				document.cookie = name + "=" + value + expires + "; path=/";
			},
			get: function(name) {
				var nameEQ = name + "=";
				var ca = document.cookie.split(';');
				for (var i = 0; i < ca.length; i++) {
					var c = ca[i];
					while (c.charAt(0) == ' ') c = c.substring(1, c.length);
					if (c.indexOf(nameEQ) == 0) return this._unescape(c.substring(nameEQ.length, c.length));
				}
				return null;
			},
			clear: function(name) {
				this.set(name, "", -1);
			},
			_escape: function(s) {
				return escape(decodeURIComponent(s));
			},
			_unescape: function(s) {
				return decodeURIComponent(unescape(s));
			}
		},

		Array: {
			each: function(arr, callback) {
				var c = arr.length;
				for (var i = 0; i < c; i++) {
					callback(arr[i], i, c);
				}
			}
		},

		CallsQueue: function() {
			var operations = [];
			this.add = function(op) {
				operations.push(op);
			};
			this.call = function() {
				var _operations = operations;
				operations = [];
				for (var i = 0; i < _operations.length; i++) {
					_operations[i]();
				}
			};
		},

		LazyCalls: function(initState) {
			var lazy = initState || true;
			var callsQueue = new Capacent.CallsQueue();
			this.call = function(op) {
				if (lazy) {
					callsQueue.add(op);
				} else {
					op();
				}
			};
			this.flush = function() {
				lazy = false;
				callsQueue.call();
			};
		},

		Synchronization: function() {
			var busy = false;
			var callsQueue = new Capacent.CallsQueue();
			this.lock = function(op) {
				if (busy) {
					callsQueue.add(op);
				} else {
					busy = true;
					op();
				}
			};
			this.release = function() {
				busy = false;
				callsQueue.call();
			};
		},

		TimeoutCall: function(time, op) {
			var timer = setTimeout(op, time);
			this.cancel = function() {
				if (timer != null) {
					clearTimeout(timer);
				}
			};
		},

		StopWatch: function() {
			var startTime = null;
			this.reset = function() {
				startTime = new Date().getTime();
			};
			this.duration = function() {
				var stopTime = new Date().getTime();
				return (stopTime - startTime) / 1000;
			};
			this.reset();
		},

		JSON: {
			encode: function(obj) {
				return JSON.stringify(obj);
			},
			decode: function(str) {
				return JSON.parse(str);
			}
		},
		init: function() {
			this.Util.onLoad(function() { Capacent.Util._isLoaded = true; });
		}
	};

	Capacent.init();


	if (typeof (window.Capacent) == "undefined") {
		window.Capacent = Capacent;
	} else {
		Capacent.Util.mergeObjects(window.Capacent, Capacent);
	}
} ());
// File: TagSystem/js/assemblies/Protocol.js

/************************************************************/
/********************** Protocol ****************************/
/************************************************************/
var addJS = function(src) {
	var s = window.document.createElement('script');
	s.setAttribute('type', 'text/javascript');
	s.setAttribute('charset', 'utf-8');
	s.setAttribute('src', src);
	window.document.documentElement.firstChild.appendChild(s);
};

Protocol = function(url) {
	this.ServiceURL = url;
};

// public properties
Protocol.prototype.ServiceURL = '';
Protocol.prototype.Timeout = 25000; // Default timeout is 25 sec
Protocol.prototype.RID = '';

// internal properties
Protocol.prototype.timerID = null;
Protocol.prototype.url = null;
Protocol.prototype.runing = false;

//Status codes
Protocol.ST_OK = 0;
Protocol.ST_METHOD_NOT_FOUND = 1;
Protocol.ST_SERVER_EXCEPTION = 2;
Protocol.ST_METHOD_EXCEPTION = 3;
Protocol.ST_TIMEOUT = 4;
Protocol.ST_OTHER = 10;

Protocol.ExplainCode = function(code) {
	switch (code) {
		case Protocol.ST_OK:
			return 'Ok';
		case Protocol.ST_METHOD_NOT_FOUND:
			return 'Method not found';
		case Protocol.ST_SERVER_EXCEPTION:
			return 'Serverside exception';
		case Protocol.ST_METHOD_EXCEPTION:
			return 'Unhandled method exception';
		case Protocol.ST_TIMEOUT:
			return 'Execution timeout';
		case Protocol.ST_OTHER:
			return 'Unknown';

	}
};

// Static fields
Protocol._pool = {};

// Private static methods
Protocol._send = function(url, instance, onSuccessCallback, onFailureCallback) {
	Protocol._pool[instance.RID] = { instance: instance, onSuccess: onSuccessCallback, onFailure: onFailureCallback };
	addJS(url);
};


// Public static methods
Protocol.Complete = function(rid, statusCode, data) {
	try {
		if (data != null) {
			//data = data.replace(/\n\r|\r\n|\n|\r/gi, '__NewLine__');
			//data = JSON.parse(data);
			data = eval('(' + data + ')');
			//for (var p in data) {
			//	data[p] = data[p].replace(/__NewLine__/, '\n');
			//}
		}
	} catch (ex) {
//		debugger;
		log("Fail to parse: " + ex);
		data = null;
	};

	var record = Protocol._pool[rid];
	if (record != null && typeof (record) != 'undefined') {
		clearTimeout(record.instance.timerID);
		//log('&larr; RID: ' + rid);

		if (statusCode == Protocol.ST_OK) {
			if (typeof (record.onSuccess) == 'function')
				record.onSuccess(data);
		}
		else {
			if (typeof (record.onFailure) == 'function')
				record.onFailure(statusCode, data);
		}
		record.instance.runing = false;
		delete Protocol._pool[rid];
	}
};

Protocol.prototype.execute = function(methodName, params, onSuccessCallback, onFailureCallback) {
	if (this.runing) {
		log('Already runned');
		return;
	}

	this.runing = true;
	var rid = 'PROTOCOL-' + Math.random();
	//log('&rarr; RID: ' + rid);
	this.RID = rid;
	var stringParams = '';
	for (var i = 0; i < params.length; i++) {
		var v = params[i];
		if (typeof (v) != 'number') {
			v = '"' + v + '"';
		}
		stringParams += v + (i != params.length - 1 ? ',' : '');
	}
	stringParams = '[' + stringParams + ']';

	var url = this.ServiceURL + '?methodName=' + escape(methodName) + '&params=' + escape(stringParams) + '&rid=' + rid + '&r=' + Math.random();
	//	log('-&gt;&nbsp;URL:&nbsp;' + escapeHTML(url));
	this.timerID = setTimeout(function() {
		Protocol.Complete(rid, Protocol.ST_TIMEOUT, null);
	}, this.Timeout);

	Protocol._send(url, this, onSuccessCallback, onFailureCallback);
};

window.$__Protocol = Protocol;
// File: TagSystem/js/assemblies/Logger.js

// Log class
Capacent.Log = function(constructorParams) {
	this.Enable = true;
	this.ModuleName = "";
	this._container = null;
	this._containerHTML = "";
	this.init = function() {
		if (typeof (Capacent.Log._container) == 'undefined') {
			if (document.body == null) {
				setTimeout(arguments.callee, 50);
				return;
			}
			var l = document.createElement('div');
			l.style.position = 'absolute';
			l.style.width = '400px';
			l.style.height = '500px';
			l.style.right = '0';
			l.style.top = '0';
			l.style.border = '2px solid #000';
			l.style.background = '#ddd';
			l.style.overflow = 'auto';
			l.style.padding = '5px';
			l.style.zIndex = '1000';
			l.style.fontFamily = 'Monospace';
			l.style.fontSize = '8pt';
			l.style.MozBoxSizing = 'border-box';
			Capacent.Log._container = document.body.appendChild(l);
			l.innerHTML = this._containerHTML;
			this._containerHTML = "";
		}
		this._container = Capacent.Log._container;
	};

	this.write = function(message) {
		if (this.Enable) {
			if (message != null && message != '') {
				var html = '&bull;&nbsp;' + this.ModuleName + ": " + message + '<br />';
				if (this._container == null) {
					this._containerHTML += html;
				} else {
					this._container.innerHTML += html;
				}
			}
		}
	};

	// read constructor parameters
	Capacent.Util.mergeObjects(this, constructorParams || {});

	if (typeof (constructorParams) != 'undefined') {
		this.Enable = typeof (constructorParams.Enable) != 'undefined' ? constructorParams.Enable : this.Enable;
		this.ModuleName = typeof (constructorParams.ModuleName) != 'undefined' ? constructorParams.ModuleName : this.ModuleName;
	}

	if (this.Enable) {
		this.init();
	}
};

// File: TagSystem/js/assemblies/CrossDomain.js
// Dependencies: Core (TagSystem/js/assemblies/Core.js)
//               Logger (TagSystem/js/assemblies/Logger.js)
//               Protocol (TagSystem/js/assemblies/Protocol.js)
/// <reference path="Core.js" />
/// <reference path="Protocol.js" />
/// <reference path="Logger.js" />

Capacent.CrossDomain = {
	StringStream: function(sessionId) {
		/// <summary>String stream communication between two sides: reader (message listner), writer (message sender)</summary>
		/// <param name="sessionId" type="String">Session within the scope of its communication goes</param>

		var self = this;
		this.className = "Capacent.CrossDomain.StringStream";
		this.log = function() { };
		var log = function(m) { self.log(m); };
		var isDisposed = false;
		var listenTimeout = 20000;
		var writeTimeout = 100;

		var hosts = [document.location.protocol + '//tag.userreport.com/CrossDomainProxy.ashx'];
		var usedHosts = [];
		var getUrl = function() {
			function randomUpTo(max) {
				return Math.floor(Math.random() * max);
			}

			if (usedHosts.length == 0 && hosts.length == 0) {
				log("Comet urls are not configured!");
				throw "Comet urls are not configured!";
			}
			if (hosts.length == 0) {
				hosts = usedHosts;
				usedHosts = [];
			}
			var i = randomUpTo(hosts.length);
			var host = hosts[i];
			usedHosts.push(host);
			hosts = hosts.slice(0, i).concat(hosts.slice(i + 1));

			return host;
		};
		var url = getUrl();
		var writeUrl = getUrl();
		this.write = function(str, callback) {
			///<summary>Write message and get callback when done</summary>
			///<param name="str">Text of message which will be sent</param>
			///<param name="callback">Function which will be invoked when message sent</param>

			if (!isDisposed) {
				log("Begin write '" + str + "'");
				Capacent.Ajax.crossDomainCall(writeUrl, "Write", [sessionId, str], callback, callback, writeTimeout);
			}
		};
		this.read = function(callback) {
			///<summary>Read message via get callback when new message comes</summary>
			///<param name="callback">Function which will be invoked when new message comes</param>

			if (!isDisposed) {
				// SetTimeout needs for suppress "Page loading..." message in Safari
				function listen(callback) {
					if (isDisposed) {
						log("Listener disposed");
					} else {
						log("Start listen...");
						var onSuccessCallback = function(result) {
							if (result.Value.Error) {
								log("Server error. Error=" + result.Value.Error);
							} else {
								if (!isDisposed) {
									log("Data received");
									callback(result.Value.Content);
								}
							}
							listen(callback);
						};
						var onFailureCallback = function(errorCode) {
							if (errorCode == 4) {
								log("Listener reconnection...");
							} else {
								log("Protocol error. Error-code=" + errorCode);
							}
							listen(callback);
						};
						Capacent.Ajax.crossDomainCall(url, "Read", [sessionId], onSuccessCallback, onFailureCallback, listenTimeout);
					}
				}
				log("Begin read...");
				listen(callback);
			}
		};
		this.close = function() {
			///<summary>Close communication channel</summary>

			if (!isDisposed) {
				isDisposed = true;
				log("Marked as disposed");
							}
		};
	}
};
// File: TagSystem/js/assemblies/Cookie.js
// Dependencies: Core (TagSystem/js/assemblies/Core.js)
//               Logger (TagSystem/js/assemblies/Logger.js)
//               Protocol (TagSystem/js/assemblies/Protocol.js)

Capacent.Cookie = {};
Capacent.Cookie.Result = function(id, sender, time) {
	this.Id = id || null;
	this.Sender = sender || null;
	this.Time = time || null;
	this.toString = function() {
		return "Id=" + this.Id
			+ " Sender=" + (this.Sender == null ? "" : this.Sender.className)
			+ " Time=" + (this.Time == null ? "" : this.Time);
	};
	this.serialize = function() {
		return "{id:'" + this.Id + "', senderClassName:'" + (this.Sender == null ? "" : this.Sender.className) + "', time:" + this.Time + "}";
	};
};
Capacent.Cookie.Silverlight = function(silverlightCookieUrl) {
	var self = this;
	var onready = new Capacent.LazyCalls();
	this._movie = null;
	this.className = "Capacent.Cookie.Silverlight";
	var url = silverlightCookieUrl;
	this.isEnabled = function() {
		function isInstalled(version) {
			if (version == undefined)
				version = null;

			var isVersionSupported = false;
			var container = null;

			try {
				var control = null;
				var tryNS = false;

				if (window.ActiveXObject) {
					try {
						control = new ActiveXObject('AgControl.AgControl');
						if (version === null) {
							isVersionSupported = true;
						}
						else if (control.IsVersionSupported(version)) {
							isVersionSupported = true;
						}
						control = null;
					}
					catch (e) {
						tryNS = true;
					}
				}
				else {
					tryNS = true;
				}
				if (tryNS) {
					var plugin = navigator.plugins["Silverlight Plug-In"];
					if (plugin) {
						if (version === null) {
							isVersionSupported = true;
						}
						else {
							var actualVer = plugin.description;
							if (actualVer === "1.0.30226.2")
								actualVer = "2.0.30226.2";
							var actualVerArray = actualVer.split(".");
							while (actualVerArray.length > 3) {
								actualVerArray.pop();
							}
							while (actualVerArray.length < 4) {
								actualVerArray.push(0);
							}
							var reqVerArray = version.split(".");
							while (reqVerArray.length > 4) {
								reqVerArray.pop();
							}

							var requiredVersionPart;
							var actualVersionPart;
							var index = 0;

							do {
								requiredVersionPart = parseInt(reqVerArray[index]);
								actualVersionPart = parseInt(actualVerArray[index]);
								index++;
							}
							while (index < reqVerArray.length && requiredVersionPart === actualVersionPart);

							if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) {
								isVersionSupported = true;
							}
						}
					}
				}
			}
			catch (e) {
				isVersionSupported = false;
			}

			return isVersionSupported;
		}
		return isInstalled();
	};
	this.init = function() {
		function registerPlugin(params) {
			var html = [];
			html.push('<object type=\"application/x-silverlight\" data="data:application/x-silverlight,"');
			var id = params.id || ("__slPlugin" + Capacent.Util.random().toString());
			html.push(' id="' + id + '"');
			html.push(' width="1"');
			html.push(' height="1"');
			html.push(' >');
			var movie = null;
			for (key in params) {
				var value = params[key];
				if (value) {
					if (typeof (value) == 'function') {
						var f = value;
						value = Capacent.Util.convertFunctionToString(function() { f(movie); });
					};
					html.push('<param name="' + key + '" value="' + value + '" />');
				}
			}
			html.push('<\/object>');

			var l = document.createElement('div');
			l.style.width = '0px';
			l.style.height = '0px';
			l.style.position = 'absolute';
			l.style.left = '-10px';
			document.body.appendChild(l);
			l.innerHTML = html.join('');
			movie = l.firstChild;
			return movie;
		}
		registerPlugin({
			source: url,
			enableHtmlAccess: 'true',
			onLoad: function(movie) {
				self._movie = movie;
				onready.flush();
			}
		});
	};
	this.get = function(callback) {
		var time = new Capacent.StopWatch();
		onready.call(function() {
			var id = self._movie.Content.SLCookie.Get("UserId");
			callback(new Capacent.Cookie.Result(id == "" || id == "null" ? null : id, self, time.duration()));
		});
	};
	this.set = function(id, callback) {
		onready.call(function() {
			self._movie.Content.SLCookie.Set("UserId", id);
			callback(new Capacent.Cookie.Result(id, self));
		});
	};
};
Capacent.Cookie.Flash = function(flashCookieUrl) {
	var self = this;
	var onready = new Capacent.LazyCalls();
	this._movie = null;
	this.className = "Capacent.Cookie.Flash";
	var url = flashCookieUrl;
	this.isEnabled = function() {
		function isInstalled() {
			var getActiveXObject = function(name) {
				var obj = -1;
				try {
					obj = new ActiveXObject(name);
				} catch (err) {
					obj = { activeXError: true };
				}
				return obj;
			};
			var activeXDetectRules = [
				{ "name": "ShockwaveFlash.ShockwaveFlash.7" },
				{ "name": "ShockwaveFlash.ShockwaveFlash.6" },
				{ "name": "ShockwaveFlash.ShockwaveFlash" }
			];

			var flashDetect = function() {
				if (navigator.plugins && navigator.plugins.length > 0) {
					var type = 'application/x-shockwave-flash';
					var mimeTypes = navigator.mimeTypes;
					if (mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description) {
						return true;
					}
				} else if (navigator.appVersion.indexOf("Mac") == -1 && window.execScript) {
					for (var i = 0; i < activeXDetectRules.length; i++) {
						var obj = getActiveXObject(activeXDetectRules[i].name);
						if (!obj.activeXError) {
							return true;
						}
					}
				}
				return false;
			};
			return flashDetect();
		}
		return isInstalled();
	};
	this.init = function() {
		function registerPlugin(params) {
			var insertFlash = function(node, id, url, width, height, params) {
				var object, param, key;
				function newParam(name, value) {
					if (0/*@cc_on + 1@*/) return ['<PARAM name="', name, '" value="', value, '" />'].join('');
					else {
						param = document.createElement('param');
						param.name = name;
						param.value = value;
						return param;
					}
				}
				if (0/*@cc_on + 1@*/) {
					object = ['<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="' + id + '" width="', width, '" height="', height, '"><PARAM name="movie" value="', url, '" />'];
					if (params) for (key in params) if (params.hasOwnProperty(key)) object.push(newParam(key, params[key]));
					object.push('</OBJECT>');
					node.innerHTML = object.join('');
				}
				else {
					object = document.createElement('object');
					object.type = 'application/x-shockwave-flash';
					object.id = id;
					object.data = url;
					object.width = width;
					object.height = height;
					if (params) for (key in params) if (params.hasOwnProperty(key)) object.appendChild(newParam(key, params[key]));
					while (node.firstChild) node.removeChild(node.firstChild);
					node.appendChild(object);
				}
			};

			var l = document.createElement('div');
			l.style.width = '1px';
			l.style.height = '1px';
			l.style.position = 'absolute';
			l.style.left = '-10px';
			document.body.appendChild(l);
			var id = params.id || ("__fshPlugin" + Capacent.Util.random().toString());
			delete params.id;
			var source = params.source;
			delete params.source;
			var movie = null;
			var runOnLoadAfter = false;
			if (typeof (params.onLoad) == 'function') {
				// IMPORTANT!!!: onFlashReady method should be implemented in flash movie, otherwise onLoad functionality will doesn't work!!!
				params.flashvars = "onFlashReady=" + Capacent.Util.convertFunctionToString(function() {
					if (movie == null) {
						runOnLoadAfter = true;
					} else {
						params.onLoad(movie);
					}
				});
			}
			insertFlash(l, id, source, 1, 1, params);
			movie = l.firstChild;
			if (runOnLoadAfter) {
				params.onLoad(movie);
			}
			return movie;
		}

		registerPlugin({
			source: url,
			allowScriptAccess: "always",
			onLoad: function(movie) {
				if (typeof (movie.getCookie) != "undefined" && typeof (movie.setCookie) != "undefined") {
					self._movie = movie;
					onready.flush();
				}
			}
		});

	};
	this.get = function(callback) {
		var time = new Capacent.StopWatch();
		onready.call(function() {
			var id = self._movie.getCookie();
			callback(new Capacent.Cookie.Result(id == "" || id == "null" ? null : id, self, time.duration()));
		});
	};
	this.set = function(id, callback) {
		onready.call(function() {
			self._movie.setCookie(id);
			callback(new Capacent.Cookie.Result(id, self));
		});
	};
};
Capacent.Cookie.LocalDomStorage = function() {
	var self = this;
	this.className = "Capacent.Cookie.LocalDomStorage";
	this.cookieKey = "BpnKey";
	ieStorage = null;
	this.get = function() {
		if (typeof (globalStorage) != "undefined") {
			try {
				var id = globalStorage[document.domain][this.cookieKey] || null;
				return Capacent.String.isNullOrEmpty(id) ? null : id;
			}
			catch (ex) {
				return null;
			}
		} else if (ieStorage != null) {
			return ieStorage.getAttribute(this.cookieKey);
		}
		return null;
	};
	this.set = function(id) {
		id = Capacent.String.isNullOrEmpty(id) ? null : id;
		if (typeof (globalStorage) != "undefined") {
			try {
				globalStorage[document.domain][this.cookieKey] = id;
			}
			catch (ex) { }
		} else if (ieStorage != null) {
			ieStorage.setAttribute(this.cookieKey, id);
			ieStorage.save(this.className);
		}
	};
	this.init = function() {
		var l = document.createElement('div');
		l.style.display = "none";
		if (l.addBehavior) {
			l.addBehavior("#default#userData");
			document.body.appendChild(l);
			ieStorage = l;
			ieStorage.load(this.className);
		}
	};
	this.initWindow = function() {
		// read args
		var args = Capacent.Util.getPageArgs();
		var id = args.Id || null;
		var result = args.Result || null;

		// run engine
		var action = (id == null) ? "get" : "set";
		if (result == null) {
			switch (action) {
				case "get":
					args.Result = self.get() || "null";
					Capacent.Util.setPageArgs(args);
					break;
				case "set":
					self.set(id);
					args.Result = id;
					Capacent.Util.setPageArgs(args);
					break;
			}
		}
	};
	Capacent.Util.onLoadGuaranteed(function() {
		self.init();
		self.initWindow();
	});
};
Capacent.Cookie.DomStorage = function(connectionStrings) {
	var self = this;
	this.className = "Capacent.Cookie.DomStorage";
	var url = connectionStrings.DomStorageUrl;
	var iframe = null;
	var requestTimeout = 1000;
	var onready = new Capacent.LazyCalls();
	var tagBackend = new Capacent.TagBackend(connectionStrings.BackendUrl);
	var sync = new Capacent.Synchronization();
	var getRequestResult = function(requestId, callback, timeoutState) {
		if (typeof (timeoutState) == "undefined") {
			timeoutState = { retry: true };
			var timeout = new Capacent.TimeoutCall(requestTimeout, function() { timeoutState.retry = false; });
		}
		tagBackend.getRequestResult(requestId, callback, function(args) {
			// if timeout, then retry
			if (args.Error == 4 && timeoutState.retry) {
				getRequestResult(requestId, callback, timeoutState);
			}
		}, timeoutState);
	};
	var getRequestId = function() { return Capacent.Util.random().toString() + Capacent.Util.random().toString() };
	this.isEnabled = function() {
		return (Capacent.Util.isFirefox() && typeof (globalStorage) != "undefined") || Capacent.Util.isMSIE();
	}
	this.init = function() {
		Capacent.Util.onDomReady(function() {
			if (self.isEnabled()) {
				var l = document.createElement('div');
				l.style.width = '1px';
				l.style.height = '1px';
				l.style.position = 'absolute';
				l.style.left = '-10px';
				l.innerHTML = "<iframe scrolling='no' frameborder='0' style='width:1px;height:1px'></iframe>";
				document.body.appendChild(l);
				iframe = l.firstChild;
				onready.flush();
			}
		});
	};
	var currentId = "undefined";
	this.get = function(callback) {
		var time = new Capacent.StopWatch();
		onready.call(function() {
			sync.lock(function() {
				var requestId = getRequestId();
				iframe.src = url + "?RequestId=" + requestId;
				getRequestResult(requestId, function(requestResult) {
					currentId = requestResult;
					sync.release();
					callback(new Capacent.Cookie.Result(requestResult, self, time.duration()));
				});
			});
		});
	};
	this.set = function(id, callback) {
		onready.call(function() {
			sync.lock(function() {
				if (id == currentId) {
					sync.release();
					callback(new Capacent.Cookie.Result(currentId, self));
				} else {
					var requestId = getRequestId();
					iframe.src = url + "?RequestId=" + requestId + "&Id=" + ((id == null || id == "") ? "null" : id.toString());
					getRequestResult(requestId, function(requestResult) {
						currentId = requestResult;
						sync.release();
						callback(new Capacent.Cookie.Result(requestResult, self));
					});
				}
			});
		});
	};
};
Capacent.Cookie.Proxy = function(connectionStrings) {
	var self = this;
	var timeoutTime = 3000;
	this.log = function() { };
	var log = function(m) { self.log(m); };
	//var modules = [new Capacent.Cookie.Silverlight(connectionStrings.SilverlightCookieUrl), new Capacent.Cookie.Flash(connectionStrings.FlashCookieUrl), new Capacent.Cookie.DomStorage(connectionStrings.domStorageUrl)];
	var modules = [new Capacent.Cookie.Silverlight(connectionStrings.SilverlightCookieUrl), new Capacent.Cookie.Flash(connectionStrings.FlashCookieUrl)];
	this.get = function(callback) {
		var isCallbackDone = false;
		function doCallbackOnce(result) {
			if (!isCallbackDone) {
				isCallbackDone = true;
				callback(result || new Capacent.Cookie.Result(null, null));
			}
		}
		var info = [];
		var returned = false;
		var c = modules.length;
		var i = 0;
		if (c == 0) {
			doCallbackOnce();
			self.onGetCompleted(info);
		} else {
			var additionalInfo = "";
			var timeout = new Capacent.TimeoutCall(timeoutTime, function() {
				log("Get timeout occurred. Executed for: " + additionalInfo);
				doCallbackOnce();
				self.onGetCompleted(info);
			});
			Capacent.Array.each(modules, function(module) {
				module.get(function(result) {
					additionalInfo += module.className + " ";
					i++;
					if (!returned && result.Id != null) {
						returned = true;
						// if is exist we set its to another modules
						self.set(result.Id, function() { });
						// call first callback
						doCallbackOnce(result);
					}
					info.push(result);
					// return if nothing found
					if (i == c) {
						timeout.cancel();
						doCallbackOnce();
						self.onGetCompleted(info);
					}
				});
			});
		}
	};
	this.onGetCompleted = function(info) { };
	this.set = function(id, callback) {
		var returned = false;
		var additionalInfo = "";
		var timeout = new Capacent.TimeoutCall(timeoutTime, function() {
			log("Set timeout occurred. Executed for: " + additionalInfo);
			callback(new Capacent.Cookie.Result(returned ? id : null, null));
		});
		var c = modules.length;
		var i = 0;
		Capacent.Array.each(modules, function(module) {
			module.set(id, function(res) {
				additionalInfo += module.className + " ";
				returned = true;
				i++;
				// waiting of all callbacks
				if (i == c) {
					timeout.cancel();
					callback(new Capacent.Cookie.Result(id, null));
				}
			});
		});
	};
	this.clear = function(callback) {
		this.set("", callback);
	};

	Capacent.Util.onDomReady(function() {
		// looking for enabled module
		var enabledModules = [];
		Capacent.Array.each(modules, function(module) {
			if (module.isEnabled()) {
				enabledModules.push(module);
			}
		});
		modules = enabledModules;
		// init
		Capacent.Array.each(modules, function(module) {
			module.init();
		});
	});
}
Capacent.TagBackend = function(backendUrl) {
	var self = this;
	this.log = function() { };
	var log = function(m) { self.log(m); };
	var url = backendUrl;
	this.getUser = function(localId, callback) {
		log('Send GetUser() request');
		Capacent.Ajax.crossDomainCall(url, "GetUser", [localId == null ? "" : localId],
			function(result) {
				result.executeClear = !Capacent.String.isNullOrEmpty(result.FlashIdToSet) && result.FlashIdToSet == "clear";
				result.idToSet = Capacent.String.isNullOrEmpty(result.FlashIdToSet) ? null : result.FlashIdToSet;
				callback(result);
			}, function(code, response) {
				log('Failed with code ' + code, response);
				callback({ Error: code });
			});
	};
	this.setUser = function(id, callback) {
		log('Send SetUser() request');
		Capacent.Ajax.crossDomainCall(url, "SetUser", [id],
			function(result) {
				result.executeClear = !Capacent.String.isNullOrEmpty(result.FlashIdToSet) && result.FlashIdToSet == "clear";
				result.idToSet = Capacent.String.isNullOrEmpty(result.FlashIdToSet) ? null : result.FlashIdToSet;
				callback(result);
			}, function(code, response) {
				log('Failed with code ' + code, response);
				callback({ Error: code });
			});
	};
	this.clearUser = function(callback) {
		log('Send ClearUser() request');
		Capacent.Ajax.crossDomainCall(url, "ClearUser", [],
			function(data) {
				callback({});
			}, function(code, response) {
				log('Failed with code ' + code, response);
				callback({ Error: code });
			});
	};
	this.getRequestResult = function(requestId, callback, errorCallback) {
		log('Send GetRequestResult(requestId=' + requestId + ') request');
		Capacent.Ajax.crossDomainCall(url, "GetRequestResult", [requestId],
			function(data) {
				callback(data.Value || null);
			}, function(code, response) {
				errorCallback({ Error: code, Response: response });
			});
	};
	this.writeDebugInfo = function(info) {
		log('Send WriteDebugInfo(' + info + ') request');
		Capacent.Ajax.crossDomainCall(url, "WriteDebugInfo", [info], function(data) { }, function(code, response) { });
	};
	this.writeMigrationInfo = function(userId) {
	var message = "User Migrated: " + userId;
	log('Send WriteLog(' + message + ') request');
		Capacent.Ajax.crossDomainCall(url, "WriteLog", [message], function(data) { }, function(code, response) { });
	}
};
Capacent.Tag = function(connectionStrings, performMigration) {
	performMigration = performMigration || false;
	var self = this;
	this.ConnectionStrings = {
		BackendUrl: document.location.protocol + '//tag.userreport.com/execute.ashx',
		FlashCookieUrl: document.location.protocol + '//tag.userreport.com/FlashCookieProxy.swf',
		SilverlightCookieUrl: document.location.protocol + '//tag.userreport.com/SilverlightCookieProxy.xap',
		DomStorageUrl: document.location.protocol + '//tag.userreport.com/DomStorageProxy.aspx'
	};

	Capacent.Util.mergeObjects(this.ConnectionStrings, connectionStrings);
	var cookie = new Capacent.Cookie.Proxy(this.ConnectionStrings);
	var backend = new Capacent.TagBackend(this.ConnectionStrings.BackendUrl);
	this.log = function() { };
	var log = function(m) { self.log(m); };
	cookie.log = log;
	backend.log = log;
	cookie.onGetCompleted = function(info) {
		var s = "[";
		var d = "";
		for (var i = 0; i < info.length; i++) {
			s += d + info[i].serialize();
			d = ",";
		}
		s += "]";
		backend.writeDebugInfo(s);
	};
	//var checkBVTRegex = /brugervenlighedstesten\.dk/i;
	var checkBVTRegex = /brugervenlighedstesten\.dk/i;
	this.get = function(callback) {
		log('Try to get local cookie');
		cookie.get(function(cookieResult) {
			log('Local cookie: ' + cookieResult.toString());
			backend.getUser(cookieResult.Id, function(backendResult) {
				log('GetUser() successfully completed', backendResult);
				if (backendResult.executeClear) {
					log("Clear local cookie");
					cookie.clear(function() { });
				}
				else if (backendResult.idToSet != null) {
					log("Update local cookie");
					cookie.set(backendResult.idToSet, function() { });
				}
				
				if (Capacent.String.isNullOrEmpty(backendResult.UserId) && performMigration) {
					//========= BEGIN Cookies Migration
					var scriptIncludes = document.getElementsByTagName("script");
					var loadedFromBVT = false;
					for (var i = 0; i < scriptIncludes.length; i++) {
						var script = scriptIncludes[i];
						if (checkBVTRegex.test(script.src)) {
							loadedFromBVT = true;
							break;
						}
					}
					if (loadedFromBVT == true) {
						log("=======================================");
						log("Script loaded from BVT. Try to migrate cookie");
						var bvtTAG = window.$__BVT_TAG;
						bvtTAG.GetUser(function(userId) {
							if (!Capacent.String.isNullOrEmpty(userId)) {
								log("<b>User id found: " + userId + "</b>");
								self.set(userId, function() {
									log("USER MIGRATED!");
								backend.writeMigrationInfo(userId);	
								});
							} else {
								log("User not found in BVT");
							}
							log("=======================================");
							callback(userId, backendResult, cookieResult);
						});
					} else {
						callback(backendResult.UserId, backendResult, cookieResult);
					}
					//========= END Cookies Migration
				} else {
					callback(backendResult.UserId, backendResult, cookieResult);
				}
			});
		});
	};

	this.set = function(id, callback) {
		backend.setUser(id, function(backendResult) {
			if (backendResult.executeClear) {
				log("Clear local cookie");
				cookie.clear(function() {
					if (callback) {
						callback(id);
					}
				});
			}
			else if (backendResult.idToSet != null) {
				log("Update local cookie");
				cookie.set(backendResult.idToSet, function() {
					if (callback) {
						callback(id);
					}
				});
			}
		});
	};

	this.clear = function(callback) {
		backend.clearUser(function(backendResult) {
			log("Clear local cookie");
			cookie.clear(function() {
				if (callback) {
					callback();
				}
			});

		});
	};
};

//Only for backward compatibility 
(function() {
	var TagPublicInterface = function(connectionStrings) {
		this.newTag = null;
		this.GetUser = function(callback) {
			this.init();
			this.newTag.get(callback);
		};
		this.SetUser = function(userId, callback) {
			this.init();
			this.newTag.set(userId, callback);
		};
		this.ClearUser = function(callback) {
			this.init();
			this.newTag.clear(callback);
		};
		this.SetLogger = function(logger) {
			this.init();
			this.newTag.log = logger;
		};
		this.init = function() {
			if (this.newTag == null) {
				this.newTag = new Capacent.Tag(connectionStrings);
			}
		};
	};

	window.$__TAG = new TagPublicInterface(null, true);
	window.$__BVT_TAG = new TagPublicInterface({
		BackendUrl: document.location.protocol + '//tag.brugervenlighedstesten.dk/execute.ashx',
		FlashCookieUrl: document.location.protocol + '//cookieproxy.brugervenlighedstesten.dk/FlashCookieProxy.swf',
		SilverlightCookieUrl: document.location.protocol + '//tag.brugervenlighedstesten.dk/SilverlightCookieProxy.xap',
		DomStorageUrl: document.location.protocol + '//tag.brugervenlighedstesten.dk/DomStorageProxy.aspx'
	}, false);

	window.$__getTAG = TagPublicInterface;
})();
if (typeof (Capacent) == 'undefined') {
	window.Capacent = {};
}

Function.prototype.urp = {};
Function.prototype.urpBind = function(scope) {
	var _function = this;

	return function() {
		return _function.apply(scope, arguments);
	}
}

Capacent.RoundButtons = {
	// findPos() borrowed from http://www.quirksmode.org/js/findpos.html
	_findPos: function (obj) {
		var curleft = curtop = 0;

		if (obj.offsetParent) {
			do {
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
			} while (obj = obj.offsetParent);
		}

		return ({
			'x': curleft,
			'y': curtop
		});
	},
	_handleWindowResize: function () {
		for (var i = 0; i < this._buttons.length; i++) {
			var el = this._buttons[i];
			var strokeWeight = parseInt(el.currentStyle.borderWidth);
			if (isNaN(strokeWeight)) { strokeWeight = 0; }

			var parent_pos = this._findPos(el.vml.parentNode);
			var pos = this._findPos(el);
			pos.y = pos.y + (0.5 * strokeWeight) - parent_pos.y;
			pos.x = pos.x + (0.5 * strokeWeight) - parent_pos.x;

			el.vml.style.top = pos.y + 'px';
			el.vml.style.left = pos.x + 'px';
		}
	},
	_buttons: [],
	_classID: "v02vnSVo78t4JfjA",
	_isVisible: function (elem) {
		var e = elem;
		var isControlHidden = false;
		while (e != null && isControlHidden == false) {
			var curStyle = e.currentStyle;
			if (curStyle != null) {
				isControlHidden = curStyle.display == 'none' || curStyle.visibility == 'hidden';
			}
			e = e.parentNode;
		}
		return !isControlHidden;
	},
	_buttonsToRound: [],
	Register: function (button) {
		if (Capacent.Util.isMSIE() == false) {
			return;
		}
		if (button.className.match(this._classID)) { return (false); }
		if (this._isVisible(button) == false) {
			this._buttonsToRound.push(button);
			return;
		}
		var doc = button.document;

		if (!doc.namespaces.v) {
			doc.namespaces.add("v", "urn:schemas-microsoft-com:vml");
			var css = doc.createStyleSheet();
			css.addRule("v\\:roundrect", "behavior: url(#default#VML)");
			css.addRule("v\\:fill", "behavior: url(#default#VML)");
		}

		button.className = button.className.concat(' ', this._classID);
		var arcSize = Math.min(parseInt(button.currentStyle['-moz-border-radius'] ||
	                                button.currentStyle['-webkit-border-radius'] ||
	                                button.currentStyle['border-radius'] ||
	                                button.currentStyle['-khtml-border-radius']) /
	                       Math.min(button.offsetWidth, button.offsetHeight), 1);
		var fillColor = button.currentStyle.backgroundColor;
		var fillSrc = button.currentStyle.backgroundImage.replace(/^url\("(.+)"\)$/, '$1');
		var strokeColor = button.currentStyle.borderColor;
		var strokeWeight = parseInt(button.currentStyle.borderWidth);
		var stroked = 'true';
		if (isNaN(strokeWeight)) {
			strokeWeight = 0;
			strokeColor = fillColor;
			stroked = 'false';
		}

		button.style.background = 'transparent';
		button.style.borderColor = 'transparent';

		// Find which element provides position:relative for the target element (default to BODY)
		var el = button.parentElement;
		var limit = 100, i = 0;
		while ((typeof (el) != 'unknown') && (el.currentStyle.position != 'relative') && (el.tagName != 'BODY')) {
			el = el.parentElement;
			i++;
			if (i >= limit) { return (false); }
		}
		var el_zindex = parseInt(el.currentStyle.zIndex);
		if (isNaN(el_zindex)) { el_zindex = 0; }

		var rect_size = {
			'width': button.offsetWidth - strokeWeight,
			'height': button.offsetHeight - strokeWeight
		};
		var el_pos = this._findPos(el);
		var this_pos = this._findPos(button);

		this_pos.y = this_pos.y + (0.5 * strokeWeight) - el_pos.y;
		this_pos.x = this_pos.x + (0.5 * strokeWeight) - el_pos.x;

		var rect = doc.createElement('v:roundrect');
		rect.arcsize = arcSize + 'px';
		rect.strokecolor = strokeColor;
		rect.strokeWeight = strokeWeight + 'px';
		rect.stroked = stroked;
		rect.style.display = 'block';
		rect.style.position = 'absolute';
		rect.style.top = this_pos.y + 'px';
		rect.style.left = this_pos.x + 'px';
		rect.style.width = rect_size.width + 'px';
		rect.style.height = rect_size.height + 'px';
		rect.style.antialias = true;
		rect.style.zIndex = el_zindex - 1;
		rect.id = 'rect' + button.id;

		var fill = doc.createElement('v:fill');
		fill.color = fillColor;
		fill.src = fillSrc;
		fill.type = 'tile';

		rect.appendChild(fill);
		el.appendChild(rect);

		isIE6 = /msie|MSIE 6/.test(navigator.userAgent);
		// IE6 doesn't support transparent borders, use padding to offset original element
		if (isIE6 && (strokeWeight > 0)) {
			button.style.borderStyle = 'none';
			button.style.paddingTop = parseInt(button.currentStyle.paddingTop || 0) + strokeWeight;
			button.style.paddingBottom = parseInt(button.currentStyle.paddingBottom || 0) + strokeWeight;
		}

		button.vml = rect;
		this._buttons.push(button);
		this._attachOnResizeHandler();
		var self = this;
		button.update = function () {			
			var isControlHidden = !self._isVisible(button);
			button.vml.style.visibility = isControlHidden ? 'hidden' : 'visible';
			if (isControlHidden == false) {
				button.style.borderColor = '';
				button.style.backgroundColor = '';

				rect.strokecolor = button.currentStyle.borderColor;
				fill.color = button.currentStyle.backgroundColor;

				button.style.borderColor = 'transparent';
				button.style.backgroundColor = 'transparent';
			}
		};

		button.onmouseover = function () {
			fill.color = button.currentStyle['-hover-bg-color'] || button.currentStyle['hover-bg-color'];
		};

		button.onmouseleave = function () {
			fill.color = button.currentStyle['-normal-bg-color'] || button.currentStyle['normal-bg-color'];
		};
	},
	Update: function () {
		if (Capacent.Util.isMSIE() == false) {
			return;
		}
		var a = [];
		for (var i = 0; i < this._buttonsToRound.length; i++) {
			var b = this._buttonsToRound[i];
			if (this._isVisible(b)) {
				this.Register(b);
			} else {
				a.push(b);
			}
		}
		this._buttonsToRound = a;
		for (var i = 0; i < this._buttons.length; i++) {
			this._buttons[i].update();
		}
	},
	_attachOnResizeHandler: function () {
		if (arguments.callee.done) return;
		arguments.callee.done = true;
		Capacent.Util.attachEvent(window, "resize", this._handleWindowResize.urpBind(this));
	}
};
Capacent.ViewPort = {
	getSize: function (w, d) {
		w = w || window;
		d = d || document;

		var viewportwidth;
		var viewportheight;

		// the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight

		if (typeof w.innerWidth != 'undefined') {
			viewportwidth = w.innerWidth,
			viewportheight = w.innerHeight
		}

		// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)

		else if (
			typeof d.documentElement != 'undefined' &&
			typeof d.documentElement.clientWidth != 'undefined' &&
			d.documentElement.clientWidth != 0) {
			viewportwidth = d.documentElement.clientWidth,
				viewportheight = d.documentElement.clientHeight
		}
		// older versions of IE
		else {
			viewportwidth = d.getElementsByTagName('body')[0].clientWidth,
			viewportheight = d.getElementsByTagName('body')[0].clientHeight
		}

		return { w: viewportwidth, h: viewportheight };
	},
	getDocSize: function () {
		var D = document;
		var DE = D.documentElement;
		var h = Math.max(
			Math.max(D.body.scrollHeight, DE.scrollHeight),
			Math.max(D.body.offsetHeight, DE.offsetHeight),
			Math.max(D.body.clientHeight, DE.clientHeight)
		);

		var w = D.body.offsetWidth;
		return { w: w, h: h };
	}
};

Capacent.CI_Status = {
	Disabled: 0,
	Auto: 1,
	Forced: 2
};

// BPN class
Capacent.BPN = function (constructorParams) {
	this.Settings = {
		TestInviteMode: false,
		ShowLog: false,
		Inline: false,
		SurveyUrl: null,
		SiteId: null,
		RespondentId: null,
		Params: {},
		InvitationId: null,
		CustomMainColor: null,
		CustomSecondaryColor: null,
		PopupCssUrl: ("https:" == document.location.protocol) ? "https://sds.userreport.com/Popup2/popup2.css" : "http://sdscdn.userreport.com/Popup2/popup2.css", // null,
		BackendUrl: document.location.protocol + "//be.userreport.com/protocol/execute.ashx",
		DisclaimerUrl: document.location.protocol + "//www.userreport.com/AnonymousModule/InvitationPrivacyPolicy.aspx",
		SmallScreen: false,
		CIEnabled: Capacent.CI_Status.Auto,
		OverlayEnabled: true,
		TrackingEnabled: true,
		LinksEnabled: true,
		RefreshSession: false,
		_determineByBackendUrl: function (url) { return this.BackendUrl.replace(/Protocol\/Execute.ashx/i, url); },
		getImagesFolderUrl: function () {
			return this.PopupCssUrl.replace(/popup2.css$/i, '');
		},
		getDisclaimerUrl: function (culture) { return this.DisclaimerUrl + "?PPculture=" + culture; },
		getTestInviteSurveyUrl: function () { return this._determineByBackendUrl("?test_invite=1&Id=" + this.SiteId + (this.Inline ? "&inline=true" : "")); },
		getFeedbackUrl: function () { return this._determineByBackendUrl("Feedback.aspx"); },
		getCIExecuteUrl: function () { return this._determineByBackendUrl("CIExecute.aspx"); }
	};
	Function.prototype.urp = {};
	Function.prototype.urpBind = function (scope) {
		var _function = this;

		return function () {
			return _function.apply(scope, arguments);
		}
	}
	this.CurrentSession = {
		WasInvited: false,
		FeedbackEnabled: true,
		InvitationTitle: '',
		UserReportWithGaUrl: '',
		InvitationText: '',
		AcceptTitle: '',
		ContinueTitle: '',
		IsPostponed: '',
		IsSurveyStarted: '',
		SurveyUrl: '',
		RejectTitle: '',
		CloseTooltip: '',
		FeedbackPin: null,
		FeedbackAttach: null,
		FeedbackOffset: null,
		Skin: '',
		SurveyCulture: '',
		SiteName: '',
		TrackingImageUrl: '',
		_sessionCookieName: "__urpSession",
		_sessionSuffix: '',
		_persistent: true,
		_getCookieName: function (cookieSuffix) {
			return this._sessionCookieName + "_" + this._sessionSuffix + "_" + cookieSuffix;
		},
		_skipFields: ['InvitationText', 'AcceptTitle', 'RejectTitle', 'TrackingImageUrl', 'Skin'],
		save: function () {
			if (this._persistent == false) {
				return;
			}
			var data = {};
			for (var o in this) {
				if (/^_/i.test(o)) {
					continue;
				}

				var shouldContinue = false;
				for (var i = 0; i < this._skipFields.length; i++) {
					if (this._skipFields[i] == o) {
						shouldContinue = true;
						break;
					}
				}
				if (shouldContinue) { continue; }

				data[o] = this[o];
			}

			var sessionStr = Capacent.JSON.encode(data);
			var maxCookieSize = 512;
			for (var currentPos = 0, cookieSuffix = 1; currentPos < sessionStr.length; currentPos += maxCookieSize, cookieSuffix++) {
				var chunk = sessionStr.substr(currentPos, maxCookieSize);
				Capacent.RegularCookie.set(this._getCookieName(cookieSuffix), chunk);
			}
		},
		initDone: function (doneCallback) {
			var self = this;
			return function () {
				self.save();
				if (typeof doneCallback == 'function') {
					doneCallback();
				}
			};
		},
		destroy: function () {
			for (var i = 0; i < 10; i++) {
				Capacent.RegularCookie.clear(this._getCookieName(i));
			}
		},
		init: function (doneCallback, initCallback, persistent) {
			this._persistent = persistent;
			var sessionStr = '';
			var cookieSuffix = 1;
			while (true) {
				var chunk = Capacent.RegularCookie.get(this._getCookieName(cookieSuffix));
				if (Capacent.String.isNullOrEmpty(chunk)) {
					break;
				}
				sessionStr += chunk;
				cookieSuffix++;
			};

			if (Capacent.String.isNullOrEmpty(sessionStr) == false) {
				var sessionData = Capacent.JSON.decode(sessionStr);
				for (var o in sessionData) {
					this[o] = sessionData[o];
				}
				if (typeof doneCallback == 'function') {
					doneCallback();
				}
			} else {
				initCallback(this, this.initDone(doneCallback));
			}
		}
	};

	this.Communication = new (function () {
		var self = this;
		this.SessionId = Capacent.Util.random().toString();
		var stream = null;
		var callbacks = [];
		var onMessageDelivered = function (messages) {
			Capacent.Array.each(messages, function (message) {
				Capacent.Array.each(callbacks, function (callback) {
					if (message != null && message.indexOf(callback.sender) == 0) {
						callback.func(message);
					}
				});
			});
		};
		var init = function () {
			if (stream == null) {
				stream = new Capacent.CrossDomain.StringStream(self.SessionId);
				stream.read(function (message) { onMessageDelivered(message); });
			}
		};
		this.waitForMessage = function (sender, callback) {
			callbacks.push({ sender: sender, func: callback });
			setTimeout(function () {
				init();
			}
			, 300);
		};
		this.close = function () {
			if (stream != null) {
				stream.close();
				stream = null;
			}
		};
	})();

	this.Overlay = new (function () {
		var self = this;
		var isHidden = true;
		var ctrl = null;
		var numberOfLayers = 0;

		var css = "div.bpn-overlay { padding: 0; margin: 0; position:absolute; left:0px; top:0px; z-index:100000; background-color: #333; opacity:0.8; -moz-opacity: 0.8; filter: progid:DXImageTransform.Microsoft.Alpha(opacity=80); }";
		css += "body.bpn-overlay { height:100%;}";

		var tweekSize = function () {
			var size = Capacent.ViewPort.getDocSize();
			ctrl.style.height = size.h + 'px';
			if (Capacent.Util.isMSIE()) {
				ctrl.style.width = document.body.clientWidth + 'px';
			}
			else {
				ctrl.style.width = '100%';
			}
		};

		var init = function () {
			if (init.done) return;
			init.done = true;

			ctrl = document.createElement('div');
			ctrl.className = "bpn-overlay";
			ctrl.style.display = 'none';
			document.body.appendChild(ctrl);

			Capacent.Css.register(css);
			Capacent.Util.attachEvent(window, "resize", tweekSize);
		};

		this.show = function () {
			init();
			numberOfLayers++;
			if (isHidden) {
				isHidden = false;
				tweekSize();
				ctrl.style.display = 'block';
				document.body.className += " bpn-overlay";
			}
		};
		this.hide = function () {
			init();
			if (!isHidden) {
				numberOfLayers--;
				if (numberOfLayers == 0) {
					isHidden = true;
					ctrl.style.display = 'none';
					document.body.className = document.body.className.replace("bpn-overlay", "");
				}
			}
		};
	})();

	this.Backend = {
		bpn: null,
		getSiteInfoAsync: function (siteId, callbackResult) {
			var self = this;
			self.bpn.log.write('Start init site');
			Capacent.Ajax.crossDomainCall(
				self.bpn.Settings.BackendUrl,
				'InitSite', [siteId],
				function (data) {
					self.bpn.log.write('BE say: ' + data.Message);
					if (typeof (callbackResult) == 'function') {
						callbackResult(data);
					}
				}, self.bpn._onCommunicationFailure);
		},
		getParticipationFactorAsync: function (url, siteId, respondentId, hasFlashCookie, params, callbackResult) {
			var self = this;
			self.bpn.log.write('Try to communicate BE');
			var json = [];
			for (var i in params) {
				if (!params.hasOwnProperty(i)) continue;
				json.push(i + ":" + ((params[i] != null) ? params[i] : "null"));
			}
			var sParams = "{" + json.join(",") + "}";

			Capacent.Ajax.crossDomainCall(self.bpn.Settings.BackendUrl, 'GetParticipationFactor2', [siteId, respondentId, hasFlashCookie, sParams],
				function (data) {
					self.bpn.log.write('BE say: ' + data.Message);
					data.AllowToParticipate = /^true/.test(data.Message);
					if (data.AllowToParticipate) {
						data.SurveyUrl = data.SurveyUrl.replace(/\{back_url\}/, escape(url));
					}
					if (typeof (callbackResult) == 'function') {
						callbackResult(data);
					}
				}, self.bpn._onCommunicationFailure);
		},
		setInvitationAcceptedAsync: function (invitationId, callbackResult) {
			var self = this;
			self.bpn.log.write('Try to set invitation accepted');
			Capacent.Ajax.crossDomainCall(self.bpn.Settings.BackendUrl, 'SetInvitationAccepted', [invitationId],
				function (data) {
					self.bpn.log.write('BE say: ' + data.Message);
					if (typeof (callbackResult) == 'function') {
						callbackResult(data);
					}
				}, self.bpn._onCommunicationFailure);
		},
		setInvitationClosed: function (invitationId, callbackResult) {
			var self = this;
			self.bpn.log.write('Try to log user closed popup');
			Capacent.Ajax.crossDomainCall(self.bpn.Settings.BackendUrl, 'SetInvitationClosed', [invitationId],
				function (data) {
					self.bpn.log.write('BE say: ' + data.Message);
					if (typeof (callbackResult) == 'function') {
						callbackResult(data);
					}
				}, self.bpn._onCommunicationFailure);
		},
		setDeclinedRespondent: function (invitationId, respondentId, disclaimerAgree, callbackResult) {
			var self = this;
			self.bpn.log.write('Try to set decline respondent');
			Capacent.Ajax.crossDomainCall(self.bpn.Settings.BackendUrl, 'SetDeclinedRespondent2', [invitationId, respondentId, disclaimerAgree],
				function (data) {
					self.bpn.log.write('BE say: ' + data.Message);
					if (typeof (callbackResult) == 'function') {
						callbackResult(data);
					}
				}, self.bpn._onCommunicationFailure);
		},
		setStayAwayRespondent: function (callbackResult) {
			var self = this;
			self.bpn.log.write('Try to set repondent as stay away');
			$__TAG.GetUser(function (currentId) {
								Capacent.Ajax.crossDomainCall(self.bpn.Settings.BackendUrl, 'SetStayAwayRespondent', [currentId],
									function(data){
										self.bpn.log.write('BE says' + data.Message);
										$__TAG.SetUser(data.UserIdToSet, callbackResult);
									}, self.bpn._onCommunicationFailure
								);
							});
		},
		setInvitationPostponed: function (invitationId, respondentId, callbackResult) {
			var self = this;
			self.bpn.log.write('Try to set postponed invitation');
			Capacent.Ajax.crossDomainCall(self.bpn.Settings.BackendUrl, 'SetInvitationPostponed', [invitationId, respondentId],
				function (data) {
					self.bpn.log.write('BE say: ' + data.Message);
					if (typeof (callbackResult) == 'function') {
						callbackResult(data);
					}
				}, self.bpn._onCommunicationFailure);
		},

		getWebsiteId: function (callbackResult) {
			var self = this;
			self.bpn.log.write('Try to get website id');
			var url = Capacent.Util.getUrl();
			Capacent.Ajax.crossDomainCall(self.bpn.Settings.BackendUrl, 'GetWebsiteId', [url],
				function (data) {
					self.bpn.log.write('BE say: ' + data.Message);
					if (typeof (callbackResult) == 'function') {
						callbackResult(data);
					}
				}, self.bpn._onCommunicationFailure);
		}
	};

	this.CIAction = new (function () {
		var self = this;
		var inited = false;
		this.bpn = null;
		var popupCtrl = null;
		var frameCtrl = null;
		var height = 335;
		var width = 520;
		var paramName = "UserReportAction";
		this.resultQuery = null;
		this.init = function () {
			var query = window.name;
			var indexOfSharp = query.lastIndexOf("#" + paramName);
			var indexOfAction = query.lastIndexOf(paramName);
			if (indexOfSharp >= 0 && indexOfAction >= 0) {
				resultQuery = query.substring(indexOfSharp + 1);
				if (resultQuery.indexOf(paramName + "=ViewComments") >= 0) {
					var ideaId;
					parts = resultQuery.split('&');
					for (var i = 0; i < parts.length; i++) {
						if (parts[i].indexOf("id") >= 0) {
							var ideaId = parts[i].split("=")[1];
							break;
						}
					}
					this.bpn.Feedback.initPopup();
					this.bpn.Feedback.showPopup(ideaId);
				}
				else {
					this.initPopup();
					this.show();
				}
				this.removeQueryFromWindowName();
			}
		};

		this.initPopup = function () {
			popupCtrl = document.createElement('div');
			popupCtrl.id = "__bpnCIActionPopup";
			popupCtrl.className = "bpnCIAction";
			popupCtrl.style.display = 'none';
			popupCtrl.innerHTML = this.getContent();
			document.body.appendChild(popupCtrl);

			frameCtrl = document.getElementById('bpnCIActionFrame');
		}

		this.show = function () {
			Capacent.Util.setVisibilityForPendentControls(false);
			this.bpn.Communication.waitForMessage("bpnCIActionFrame", function (m) { self._onFrameMessageDelivered(m); });
			if (this.bpn.Settings.OverlayEnabled) {
				this.bpn.Overlay.show();
			}
			window.scroll(0, 0);
			popupCtrl.style.display = 'block';
			document.getElementById('bpnCIAction').style.display = 'block';
			this.resizeToInitState();

			frameCtrl.src = this.bpn.Settings.getCIExecuteUrl() + '?siteId=' + this.bpn.Settings.SiteId
					+ '&url=' + escape(document.location.href) + '&' + resultQuery + "&sessionId=" + this.bpn.Communication.SessionId;
			frameCtrl.style.display = 'block';

			Capacent.Css.register(this.getCss());
		};

		this.getContent = function () {
			var html = '';
			html += '<div id="bpnCIAction">';
			html += '<iframe class="urp-no-hide" border="0" scrolling="no" frameborder="0" style="width: 0px; border: none 0; height: 0px; display: none; clear: both;" id="bpnCIActionFrame" scrolling="no"></iframe>';
			html += '</div>';
			return html;
		};

		this.getCss = function () {
			var css = '.bpnCIAction, .bpnCIAction * { padding: 0; margin: 0; }';
			css += '.bpnCIAction {background-color: #fff;position: absolute; top: 50%; left: 50%; z-index: 2147483647; padding: 0px;}';

			return css;

		};

		this.resize = function (size) {
			var w = size.w + "px";
			var h = size.h + "px";
			var root = document.getElementById("__bpnCIActionPopup");
			root.style.width = w;
			root.style.height = h;
			root.style.marginLeft = -1 * Math.round(size.w / 2) + "px";
			root.style.marginTop = -1 * Math.round(size.h / 2) + "px";
			frameCtrl.style.width = w;
			frameCtrl.style.height = h;
		};
		this.resizeToInitState = function () {
			this.resize({ w: width, h: height });
		};

		var getWindowHeight = function () {
			var h = null;
			//IE
			if (!window.innerHeight) {
				//strict mode
				if (!(document.documentElement.clientHeight == 0)) {
					h = document.documentElement.clientHeight;
				}
				//quirks mode
				else {
					h = document.body.clientHeight;
				}
			}
			//w3c
			else {
				h = window.innerHeight;
			}
			return h;
		};
		this._onFrameMessageDelivered = function (message) {
			if (message.indexOf(".close()") != -1) {
				this.hide();
			}
		};
		this.hide = function () {
			Capacent.Util.setVisibilityForPendentControls(true);
			this.bpn.Overlay.hide();
			popupCtrl.style.display = 'none';
			frameCtrl.src = 'about:blank';
			this.bpn.Communication.close();
		};
		this.removeQueryFromWindowName = function () {
			var s = window.name;
			var start = s.lastIndexOf('#' + paramName);
			var end = s.lastIndexOf(paramName + '#');
			var userReportQuery = window.name.substring(start, end + (paramName.length) + 1);
			window.name = window.name.replace(userReportQuery, '');
		}
	})();

	this.Feedback = new (function () {
		var self = this;
		var inited = false;
		var preloaded = false;
		var linkInited = false;
		this.bpn = null;
		var popupCtrl = null;
		var frameCtrl = null;
		var heights = [630, 560];
		var width = 961;
		var frameSrc = null;
		var feedbackControl = null;
		var ideaId = null;
		this.initPopup = function () {
			if (inited == true) {
				return;
			}
			// add popup
			popupCtrl = document.createElement('div');
			popupCtrl.id = "__bpnFeedbackPopup";
			popupCtrl.className = "bpnFeedbackPopup";
			popupCtrl.style.display = 'none';
			popupCtrl.innerHTML = this.getContent();
			document.body.appendChild(popupCtrl);

			frameCtrl = document.getElementById('bpnFeedbackFrame');

			inited = true;
			Capacent.Css.register(this.getCss());

			this.frameSrc = this.getFrameSrc();
		};

		this.getFrameSrc = function () {
			return this.bpn.Settings.getFeedbackUrl() + '?siteId=' + this.bpn.Settings.SiteId
				+ '&url=' + escape(document.location.href) + "&sessionId=" + this.bpn.Communication.SessionId;
		};

		this._preLoadCI = function (event) {
			if (preloaded == false) {
				if (frameCtrl.src == '' || typeof (frameCtrl.src) == 'undefined') {
					var frameUrl = self.frameSrc;
					if (ideaId) {
						frameUrl += '&ideaId=' + ideaId;
					}

					frameCtrl.src = frameUrl;
					self.resizeToInitState();
				}
				preloaded = true;
			}
		};

		this.showPopup = function (_ideaId) {
			ideaId = _ideaId;
			if (this.bpn.Settings.OverlayEnabled) {
				this.bpn.Overlay.show();
			}

			this._preLoadCI();

			Capacent.Util.setVisibilityForPendentControls(false);
			window.scroll(0, 0);

			popupCtrl.style.display = 'block';
			document.getElementById('bpnFeedback').style.display = 'block';
			frameCtrl.style.display = 'block';
			Capacent.Util.attachEvent(window, "resize", this._onResize.urpBind(this));
			this.bpn.Communication.waitForMessage("FeedbackFrame", function (m) { self._onFrameMessageDelivered(m); });
		};

		var getWindowHeight = function () {
			var h = null;
			//IE
			if (!window.innerHeight) {
				//strict mode
				if (!(document.documentElement.clientHeight == 0)) {
					h = document.documentElement.clientHeight;
				}
				//quirks mode
				else {
					h = document.body.clientHeight;
				}
			}
			//w3c
			else {
				h = window.innerHeight;
			}
			return h;
		};
		this.getContent = function () {
			var html = '';
			html += '<div id="bpnFeedback">';
			html += '<iframe border="0" scrolling="no" class="urp-no-hide" frameborder="0" style="width: 0px; border: none 0; height: 0px; display: none; clear: both;" id="bpnFeedbackFrame" scrolling="no"></iframe>';
			html += '</div>';
			return html;
		};
		this.getLinkContent = function (pin) {
			//TODO: use popup CSS for this button
			var html = '';
			html += '<div id="CIFeedback" class="' + pin + '"><div class="shortcut"><div class="w1"><div class="w2"><div class="t"></div></div></div></div></div>';
			return html;
		};
		this.getCss = function () {
			var topDistance = Math.round(getWindowHeight() / 2.0) - 50;
			var css = '.bpnFeedbackPopup, .bpnFeedbackPopup * { padding: 0; margin: 0; }';
			css += '.ci-feedback { z-index:2147483646;  }';
			// css hack IE6+ quirks and IE5 (= all IE/Win quirks) only
			css += '* html .bpn-feedback-link { position /**/: absolute; }';
			css += '.bpnFeedbackPopup {background-color: #fff;position: absolute; top: 50%; left: 50%; z-index: 2147483647; padding: 0px;}';
			css += '.bpnFeedbackPopup-resetwidth {';
			css += '	margin-left:0px !important;';
			css += '	left:5px !important;';
			css += '}';
			css += '.bpnFeedbackPopup-resetheight {';
			css += '	margin-top:0px !important;';
			css += '	top:5px !important;';
			css += '}';
			return css;

		};
		this.getLinkCss = function (pin, offset, attach) {
			var cssBuilder = Capacent.Css.createCssBuilder();

			var color1 = this._color1 || this.bpn.CurrentSession.CustomMainColor;
			var color2 = this._color2 || this.bpn.CurrentSession.CustomSecondaryColor;

			if (typeof (pin) != 'undefined' && typeof (offset) != 'undefined' && typeof (attach) != 'undefined' && pin != 'default') {
				feedbackControl.style.top = '';
				feedbackControl.style.left = '';
				feedbackControl.style.right = '';
				feedbackControl.style.bottom = '';

				cssBuilder.createRule('body #CIFeedbackContainer.' + pin);
				cssBuilder.addProperty(attach, offset);
				if (Capacent.Util.isMSIE()) {
					cssBuilder.addProperty('position', 'absolute');
					var positionTheFeedback = function () {
						var indexOfPX = offset.indexOf('px');
						if (indexOfPX < 0) {
							indexOfPX = offset.indexOf('PX');
						}

						var offsetValue = offset.substring(0, indexOfPX);
						if (attach == 'top') {
							cssBuilder.addProperty('top', 'expression(((e = document.documentElement.scrollTop) ? e : document.body.scrollTop) + ' + offsetValue + ' + "px")');
						}
						else {
							cssBuilder.addProperty('top', 'expression(Capacent.ViewPort.getSize().h+(((e=document.documentElement.scrollTop) ? e : document.body.scrollTop) - ' + offsetValue + ' - 96) +"px")');
						}
					}
					switch (pin) {
						case 'top':
							{
								cssBuilder.addProperty('top', 'expression(((e=document.documentElement.scrollTop)?e:document.body.scrollTop) +"px")');
								break;
							}
						case 'bottom':
							{
								cssBuilder.addProperty('top', 'expression(Capacent.ViewPort.getSize().h+(((e=document.documentElement.scrollTop) ? e : document.body.scrollTop) - 30) +"px")');
								break;
							}
						case 'right':
							{
								positionTheFeedback();
								break;
							}
						case 'left':
							{
								positionTheFeedback();

								break;
							}

					}
				}
				else {
					cssBuilder.addProperty('position', 'fixed');
				}
			}
			else {
				if (pin == 'default' && Capacent.Util.isMSIE()) {
					cssBuilder.createRule('body #CIFeedbackContainer.' + pin);
					cssBuilder.addProperty('position', 'absolute');
					cssBuilder.addProperty('top', 'expression((Capacent.ViewPort.getSize().h * 0.5) + ((e = document.documentElement.scrollTop) ? e : document.body.scrollTop) + "px")');
				}
			}

			if (Capacent.String.isNullOrEmpty(color1) == false) {
				cssBuilder.createRule('.feedbackLinkFrameBody #CIFeedback .shortcut .w1');
				cssBuilder.addProperty('border-color', color1);

				cssBuilder.createRule('.feedbackLinkFrameBody #CIFeedback .shortcut .w2');
				cssBuilder.addProperty('background-color', color1);
			}


			return cssBuilder.toString();
		};

		this.hide = function (resizeToInitState) {
			Capacent.Util.setVisibilityForPendentControls(true);
			this.bpn.Overlay.hide();
			popupCtrl.style.display = 'none';
			if (resizeToInitState == true) {
				this.resizeToInitState();
			}

			this.bpn.Communication.close();
		};

		this.showLink = function () {
			this.initLink();

			if (arguments.callee.done) return;
			arguments.callee.done = true;

			feedbackControl.style.display = 'block';
			feedbackControl.style.visibility = 'visible';

			this.initPopup();
		};

		this.initLink = function () {
			if (this.linkInited == true) {
				return;
			}
			var positionPin = this.bpn.CurrentSession.FeedbackPin;
			var attach = this.bpn.CurrentSession.FeedbackAttach;
			var offset = this.bpn.CurrentSession.FeedbackOffset;
			feedbackControl = document.createElement('div');
			feedbackControl.setAttribute('id', "CIFeedbackContainer");

			if (typeof (positionPin) == 'undefined' || positionPin == null || positionPin == '') {
				positionPin = 'default';
			}

			feedbackControl.className = 'ci-feedback-container ' + positionPin;

			feedbackControl.style.display = 'none';
			feedbackControl.style.visibility = 'hidden';
			feedbackControl.bpn = this.bpn;
			document.body.appendChild(feedbackControl);
			var iframe = this._createFeedbackLinkIframe(feedbackControl, "CIFeedbackFrame");
			var iframeDoc = this.bpn.Popup._getFrameDoc(iframe);
			iframeDoc.open();
			iframeDoc.write(this.bpn.Popup._getHeader(this.bpn));
			iframeDoc.write(this.getLinkContent(positionPin));
			iframeDoc.write(this.bpn.Popup._footer);
			iframeDoc.close();

			iframeDoc.getElementsByTagName("body")[0].className = "feedbackLinkFrameBody " + positionPin;
			iframeDoc.getElementsByTagName("html")[0].className = "feedbackLinkFrameHtml " + positionPin;

			var feedbackLink = iframeDoc.getElementById('CIFeedback');

			Capacent.Util.attachEvent(feedbackLink, "click", this._onShowFeedbackClick);
			Capacent.Util.attachEvent(feedbackLink, "mouseover", this._preLoadCI);

			Capacent.Css.registerUrl(this.bpn.Settings.PopupCssUrl);
			Capacent.Css.registerexternal(iframe.window || iframe.contentWindow, this.getLinkCss(positionPin, offset, attach));
			Capacent.Css.register(this.getLinkCss(positionPin, offset, attach));

			this.linkInited = true;
		},

		this._onResize = function () {
			var viewportwidth;
			var viewportheight;

			var sizes = Capacent.ViewPort.getSize(window, document);
			viewportheight = sizes.h;
			viewportwidth = sizes.w;

			popupCtrl.className = 'bpnFeedbackPopup';
			if (viewportwidth < (width + 20)) {
				popupCtrl.className += ' bpnFeedbackPopup-resetwidth';
			}


			var windowHeight = getWindowHeight();
			var height = windowHeight < heights[0] ? heights[1] : heights[0];
			if (viewportheight < (height + 10)) {
				popupCtrl.className += ' bpnFeedbackPopup-resetheight';
			}
		};

		this._onShowFeedbackClick = function (event) {
			var bpn = self.bpn;
			if (popupCtrl != undefined &&
				popupCtrl != null &&
				typeof (popupCtrl) != 'undefined' &&
				popupCtrl.style.display == 'block') {
				stream = new Capacent.CrossDomain.StringStream(bpn.Communication.SessionId);
				stream.write("FeedbackFrame.close()");
			}
			else {
				bpn.Feedback.showLink();
				bpn.Feedback.showPopup();
			}
		};

		this._onFrameMessageDelivered = function (message) {
			if (message.indexOf(".close()") != -1) {
				this.hide();
			}
			else if (message.indexOf('.closeWithInitialResize()') != -1) {
				this.hide(true);
			}
			else if (message.indexOf(".resizeToInitState") != -1) {
				this.resizeToInitState();
			} else if (message.indexOf(".resize") != -1) {
				var rawSize = message.replace(/.*([{][^}]+[}]).*/i, "$1");
				var size = eval("[" + rawSize + "]")[0];
				this.resize(size);
			}
		};

		this.resize = function (size) {
			var w = size.w + "px";
			var h = size.h + "px";
			var root = document.getElementById("__bpnFeedbackPopup");
			root.style.width = w;
			root.style.height = h;
			root.style.marginLeft = -1 * Math.round(size.w / 2) + "px";
			root.style.marginTop = -1 * Math.round(size.h / 2) + "px";
			frameCtrl.style.width = w;
			frameCtrl.style.height = h;
		};
		this.resizeToInitState = function () {
			var windowHeight = getWindowHeight();
			var height = windowHeight < heights[0] ? heights[1] : heights[0];
			this.resize({ w: width, h: height });
			this._onResize();
		};
		this._createFeedbackLinkIframe = function (parent, iframeName) {
			var iframe;
			if (document.createElement && (iframe = document.createElement('iframe'))) {
				iframe.name = iframe.id = iframeName;
				iframe.border = '0';
				iframe.frameBorder = '0';
				iframe.className += ' urp-no-hide';
				iframe.src = 'about:blank';
				parent.appendChild(iframe);
			}
			return iframe;
		}
	})();
	this.GA = {
		bpn: null,
		log: null,
		_getTracker: function () { return window._gat ? window._gat._getTrackerByName() : null },
		_writeLog: function (message) {
			if (this.log) {
				this.log.write(message);
			}
		},
		_isGAEnabled: function () {
			return this._getTracker() != null;
		},
		_setVariable: function (slot, name, value) {
			this._getTracker()._setCustomVar(slot, name, value, 2);
		},
		_flushVariables: function () {
			this._getTracker()._trackPageview();
		},
		_initGAV: function () {
			this._getTracker()._setMaxCustomVariables(10);
		},
		_cleanup: function (s) {
			return s
				.replace(/\s+/gi, '_')
				.replace(/\//gi, '-')
				.replace(/,/gi, '')
				.replace(/\(/gi, '')
				.replace(/\)/gi, '');
		},
		SetVariables: function (variables) {
			var self = this;

			var setVariables = function () {
				if (self._isGAEnabled()) {
					self._writeLog("<b>GA tracker found</b>");
					self._initGAV();
					for (var variableIndex = 0; variableIndex < variables.length; variableIndex++) {
						var gaVariable = variables[variableIndex];
						var slot = gaVariable.Slot;
						var questionIdent = gaVariable.QuestionIdent;
						var varName = self._cleanup(gaVariable.VariableName);
						var varValue = self._cleanup(gaVariable.Value).substr(0, 64 - varName.length);
						self._writeLog("Slot: " + slot + ", QuestionIdent: " + questionIdent + ", VariableName: " + varName + ", Value: " + varValue);
						self._setVariable(slot, varName, varValue);
					}
					self._flushVariables();
					self._writeLog('<b>GA variables set</b>');
					return true;
				}
				return false;
			};

			var i = 0;
			if (!setVariables()) {
				self._writeLog('Try to set GA variables with interval');
				var interval = setInterval(function () {
					i++;
					if (setVariables()) {
						clearInterval(interval);
						return;
					}

					if (i > 60) {
						self._writeLog("<b>GA tracker <u>NOT</u> found after minute of tries</b>");
						clearInterval(interval);
					}
				}, 1000);
			}
		}
	};
	this.Popup = {
		bpn: null,
		getContent: function () {
			var html =
'<div class="urpInvitationHeader"> \
	<span class="urpLogo" id="urpLogo"><!-- --></span> \
	<h1>{invitation-title}</h1> \
	<span class="urpSiteName">{site-url}</span> \
</div> \
<div id="bpnPopupContent"> \
	<div class="urpInvitationContent" id="urpInvitationContent"> \
		{invitation-text} \
	</div> \
	<div class="urpButtons"> \
		<div class="urpButtonsContent"> \
			<div class="urpBtn urpDefault"> \
				<a href="#accept" id="bpnAccept">{accept-title}</a> \
			</div> \
			<div class="urpBtn"> \
				<a href="#reject" id="bpnReject">{reject-title}</a> \
			</div> \
		</div> \
	</div> \
</div> \
<iframe id="bpnInlineSurvey" class="urp-no-hide" style="border: 0 none; width: 100%; display: none; height: 100%;position:relative;z-index:200;" border="0" frameborder="0"></iframe>';
			return html;
		},
		_popupCtrl: null,
		_onCloseClick: function (event) {
			var bpn = (event.target || event.srcElement).bpn;
			bpn.Popup.hide();
			if (bpn.Settings.TestInviteMode == false) {
				bpn.Backend.setInvitationClosed(bpn.Settings.InvitationId, function (data) {
					bpn.Popup.checkWhetherSurveyCompleted(data, bpn);
				});
			}
			else {
				bpn.Popup.checkWhetherSurveyCompleted({ IsSurveyCompleted: false }, bpn);
			}

			Capacent.Util.cancelEvent(event);
			return false;
		},

		_resizeFrame: function () {
			var surveyFrame = this._inlineSurveyFrame;
			var offsset = this.bpn.Settings.SmallScreen == false ? 200 : 135;
			surveyFrame.style.height = Capacent.ViewPort.getSize().h - offsset + 'px';
		},
		_onResize: function (event) {
			this._resizeFrame();
		},
		_onDisclaimerAgreeClick: function (event) {
			var me = event.target || event.srcElement;
			var link = me.bpn.Popup._acceptCtrl;
			var ctrl = link.parentNode;
			ctrl.className = (me.checked) ? ctrl.className.replace("bpnDisabled", "") : ctrl.className + " bpnDisabled";
			Capacent.RoundButtons.Update();
		},
		_onRejectClick: function (event) {
			Capacent.Util.cancelEvent(event);

			var bpn = (event.target || event.srcElement).bpn;
			var disclaimerAgree = bpn.Popup._disclaimerAgreeCtrl.checked;
			bpn.Popup.hide();
			if (bpn.Settings.SurveyUrl != null && bpn.Settings.TestInviteMode == false) {
				bpn.Backend.setDeclinedRespondent(bpn.Settings.InvitationId, bpn.Settings.RespondentId, disclaimerAgree, function (data) {
					if (!Capacent.String.isNullOrEmpty(data.UserIdToSet)) {
						bpn.log.write("<b>Set flash cookie value to " + data.UserIdToSet + "</b>");
						var rejectCompleted = function () { bpn.log.write("Reject completed"); };
						var tag = new Capacent.Tag();
						if (data.UserIdToSet == "clear") {
							tag.clear(rejectCompleted);
						} else {
							tag.set(data.UserIdToSet, rejectCompleted);
						}
					}
				});
				bpn.Settings.InvitationId = null;
				bpn.Settings.SurveyUrl = null;
			}
			return false;
		},
		_onAcceptClick: function (event) {
			var bpn = (event.target || event.srcElement).bpn;
			if (bpn.Popup._disclaimerAgreeCtrl.checked) {
				// Send accepted info to server
				if (bpn.Settings.SurveyUrl != null && bpn.Settings.TestInviteMode == false) {
					bpn.Backend.setInvitationAcceptedAsync(bpn.Settings.InvitationId, function (data) {
						var acceptCompleted = function () { bpn.log.write("Accept completed"); };
						bpn.Popup.SetTagUserId(bpn, data.UserIdToSet, acceptCompleted);
					});
					//bpn.Settings.InvitationId = null;
					//bpn.Settings.SurveyUrl = null;
				}

				return bpn.Popup.ShowSurvey(bpn, event, false);
			} else {
				Capacent.Util.cancelEvent(event);
				return false;
			}

		},
		SetTagUserId: function (bpn, userId, callback) {

			if (!Capacent.String.isNullOrEmpty(userId)) {
				bpn.log.write("<b>Set RespondentId to " + userId + "</b>");
				var tag = new Capacent.Tag();
				if (userId == "clear") {
					tag.clear(callback);
				} else {
					tag.set(userId, callback);
				}
			} else {
				callback();
			}
		},
		ShowSurvey: function (bpn, event, resume) {
			if (bpn.Settings.Inline == false) {
				bpn.Popup.hide();
			} else {
				if (resume == true) {
					bpn.Popup.show();
					bpn.Popup.showInlineSurvey("Resumed=true");
				}
				else {
					bpn.Popup.showInlineSurvey();
				}
				bpn.CurrentSession.IsSurveyStarted = true;
				bpn.CurrentSession.save();

				if (typeof (event) != 'undefined' && event != null) {
					Capacent.Util.cancelEvent(event);
				}
				bpn.Popup.HideContinueLink();
				return false;
			};
			return true;
		},

		_disclaimerAgreeCtrl: null,
		_rejectCtrl: null,
		_postponeCtrl: null,
		_acceptCtrl: null,
		_invitationControl: null,
		_inlineSurveyFrame: null,
		_iframe: null,
		_iframeDoc: null,
		_createIframe: function (parent, iframeName, width, height) {
			var iframe;
			if (document.createElement && (iframe = document.createElement('iframe'))) {
				iframe.name = iframe.id = iframeName;
				iframe.style.width = width;
				iframe.style.height = height;
				iframe.style.border = 'none 0';
				iframe.style.backgroundColor = '#fff';
				iframe.className += ' urp-no-hide';
				iframe.border = '0';
				iframe.frameBorder = '0';
				iframe.src = 'about:blank';
				parent.appendChild(iframe);
			}
			return iframe;
		},
		_createContinueIframe: function (parent, iframeName, bgColor) {
			var iframe;
			if (document.createElement && (iframe = document.createElement('iframe'))) {
				iframe.name = iframe.id = iframeName;
				iframe.border = '0';
				iframe.frameBorder = '0';
				iframe.className += ' urp-no-hide';
				iframe.src = 'about:blank';
				parent.appendChild(iframe);
			}
			return iframe;
		},
		_getFrameDoc: function (iframe) {
			var iframeDoc;
			if (iframe.contentDocument) {
				iframeDoc = iframe.contentDocument;
			}
			else if (iframe.contentWindow) {
				iframeDoc = iframe.contentWindow.document;
			}
			else if (window.frames[iframe.name]) {
				iframeDoc = window.frames[iframe.name].document;
			}
			return iframeDoc;
		},

		_getHeader: function (bpn) {
			var header =
			'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> \
			<html xmlns="http://www.w3.org/1999/xhtml"> \
			<head> \
			<title>Web survey</title> \
			<meta http-equiv="content-type" content="text/html; charset=utf-8" /> \
			<link type="text/css" rel=Stylesheet href="' + bpn.Settings.PopupCssUrl + '" /></head>';
			return header;
		},
		_footer: '</html>',
		_color1: '',
		_color2: '',
		getCss: function () {
			var cssBuilder = Capacent.Css.createCssBuilder();

			var color1 = this._color1 || this.bpn.CurrentSession.CustomMainColor;
			var color2 = this._color2 || this.bpn.CurrentSession.CustomSecondaryColor;

			if (Capacent.String.isNullOrEmpty(color1) == true && Capacent.String.isNullOrEmpty(color2) == true) {
				return '';
			}
			cssBuilder.createRule('.urpBtn a');
			cssBuilder.addProperty('border-color', color1);
			cssBuilder.addProperty('background-color', color2);
			cssBuilder.addProperty('color', color1);
			cssBuilder.addProperty('-hover-bg-color', color1);
			cssBuilder.addProperty('-normal-bg-color', color2);

			cssBuilder.createRule('.urpBtn a:hover');
			cssBuilder.addProperty('background-color', color1);
			cssBuilder.addProperty('color', color2);

			cssBuilder.createRule('body .urpDefault a');
			cssBuilder.addProperty('background-color', color1);
			cssBuilder.addProperty('color', color2);
			cssBuilder.addProperty('-hover-bg-color', color2);
			cssBuilder.addProperty('-normal-bg-color', color1);

			cssBuilder.createRule('body .urpDefault a:hover');
			cssBuilder.addProperty('background-color', color2);
			cssBuilder.addProperty('color', color1);

			cssBuilder.createRule('.urpReset .urpPopupContent .urpInvitationContent h2');
			cssBuilder.addProperty('color', color1);

			cssBuilder.createRule('.urpReset div.urpPopupContent .urpInvitationContent a');
			cssBuilder.addProperty('color', color1);

			cssBuilder.createRule('.urpReset div.urpPopupContent .urpInvitationHeader .urpSiteName');
			cssBuilder.addProperty('color', color1);

			var css = cssBuilder.toString();
			return css;
		},



		ensureInit: function () {
			if (arguments.callee.done) return;
			arguments.callee.done = true;

			// inject style
			Capacent.Css.registerUrl(this.bpn.Settings.PopupCssUrl);

			// add popup
			this._popupCtrl = document.createElement('div');
			this._popupCtrl.id = "__bpnPopup";
			var popupClass = "urpPopup urpReset";
			if (Capacent.ViewPort.getSize().h <= 700) {
				popupClass += " urpSmallScreen";
				this.bpn.Settings.SmallScreen = true;
			}
			this._popupCtrl.className = popupClass;
			this._popupCtrl.style.visibility = 'hidden';
			this._popupCtrl.style.display = 'none';
			var closeHtml = '<a href="#close" id="bpnClose" class="urpClose" title="{close-tooltip}"><span><!-- --></span></a>';
			closeHtml = Capacent.String.replaceEx(closeHtml,
				{
					'close-tooltip': this.bpn.CurrentSession.CloseTooltip
				});
			this._popupCtrl.innerHTML = '<div class="urpHeader"><div class="urpContent" id="urpFrameContainer">' + closeHtml + '</div></div><div class="urpFooter"><div><span><!-- --></span></div></div><div class="urpPreload"></div>';
			document.body.appendChild(this._popupCtrl);

			var iframe = this._createIframe(document.getElementById('urpFrameContainer'), "urpFrame", '100%', '0');
			this._iframe = iframe;
			var iframeDoc = this._getFrameDoc(iframe);
			this._iframeDoc = iframeDoc;


			var content = this.getContent();
			var settings = this.bpn.Settings;
			var session = this.bpn.CurrentSession;
			var trackingImg = "";
			if (settings.TrackingEnabled
				&& settings.TestInviteMode == false
				&& Capacent.String.isNullOrEmpty(session.TrackingImageUrl) == false) {
				trackingImg = "<img style='display:none;height:1px;width:1px;' src='" + session.TrackingImageUrl + "' />";
			}
			content = Capacent.String.replaceEx(content, { 'invitation-text': this.bpn.CurrentSession.InvitationText + trackingImg });
			content = Capacent.String.replaceEx(content,
			{
				'invitation-title': this.bpn.CurrentSession.InvitationTitle,
				'site-url': this.bpn.CurrentSession.SiteName,
				'userreport-with-ga-url': this.bpn.CurrentSession.UserReportWithGaUrl,
				'accept-title': this.bpn.CurrentSession.AcceptTitle,
				'reject-title': this.bpn.CurrentSession.RejectTitle,
				'postpone-link-id': 'bpnPostpone',
				'user-agreement-checbox-id': 'bpnDisclaimerAgree',
				'privacy-policy-url': this.bpn.Settings.getDisclaimerUrl(this.bpn.CurrentSession.SurveyCulture)
			});

			var skinClass = "urpSkin-" + this.bpn.CurrentSession.Skin;
			if (this.bpn.Settings.SmallScreen) {
				skinClass += " urpSmallScreen";
			}
			var body = '<body class="urpReset"><div class="urpPopupContent ' + skinClass + '" id="urpPopupContent" style="overflow: hidden; zoom: 1; clear: both;">' + content + '</div>'
			body +=
'<scr' + 'ipt> \
var frame =  null;\
var getFrame = function() { if (frame == null) { frame = window.parent.document.getElementById("urpFrame"); } }; \
var resize = function() { \
	getFrame(); \
	if (frame != null) {\
		frame.style.height = (document.body.offsetHeight) + "px"; \
	} \
};\
setInterval(resize, 10); \
resize(); \
window.parent.document.getElementById("__bpnPopup").style.visibility = "visible"; \
</script>';
			body += '</body>';



			iframeDoc.open();
			iframeDoc.write(this._getHeader(this.bpn));
			iframeDoc.write(body);
			iframeDoc.write(this._footer);
			iframeDoc.close();
			this._logoElement = iframeDoc.getElementById('urpLogo');
			if (Capacent.String.isNullOrEmpty(this.bpn.CurrentSession.CustomLogoUrl) == false) {
				this._logoElement.style.backgroundImage = 'url(' + this.bpn.CurrentSession.CustomLogoUrl + ')';
			}

			var links = iframeDoc.getElementById('urpInvitationContent').getElementsByTagName('a');
			for (var i = 0; i < links.length; i++) {
				links[i].target = '_blank';
			}

			// add events
			this._rejectCtrl = iframeDoc.getElementById("bpnReject");
			this._acceptCtrl = iframeDoc.getElementById("bpnAccept");
			this._postponeCtrl = iframeDoc.getElementById("bpnPostpone");
			this._inlineSurveyFrame = iframeDoc.getElementById("bpnInlineSurvey");
			this._invitationControl = iframeDoc.getElementById("bpnPopupContent");

			this._disclaimerAgreeCtrl = iframeDoc.getElementById("bpnDisclaimerAgree");
			if (this._disclaimerAgreeCtrl != null) {
				this._disclaimerAgreeCtrl.checked = true;
			}
			var closeCtrl = document.getElementById("bpnClose");

			this._acceptCtrl.href = this.bpn.Settings.SurveyUrl;
			this._acceptCtrl.target = "_blank";

			this._rejectCtrl.bpn = this.bpn;
			this._acceptCtrl.bpn = this.bpn;
			if (this._postponeCtrl) {
				this._postponeCtrl.bpn = this.bpn;
			}
			if (this._disclaimerAgreeCtrl) {
				this._disclaimerAgreeCtrl.bpn = this.bpn;
			}
			closeCtrl.bpn = this.bpn;

			if (this._disclaimerAgreeCtrl) {
				Capacent.Util.attachEvent(this._disclaimerAgreeCtrl, "click", this._onDisclaimerAgreeClick);
			}

			if (this.bpn.Settings.LinksEnabled == true) {
				Capacent.Util.attachEvent(this._rejectCtrl, "click", this._onRejectClick);
				if (this._postponeCtrl != null && typeof (this._postponeCtrl) != 'undefined') {
					Capacent.Util.attachEvent(this._postponeCtrl, "click", this._onPostponeClick);
				}
				Capacent.Util.attachEvent(this._acceptCtrl, "click", this._onAcceptClick);
				Capacent.Util.attachEvent(closeCtrl, "click", this._onCloseClick);
			} else {
				var links = iframeDoc.getElementsByTagName('a');
				var cancelEvent = function (e) {
					Capacent.Util.cancelEvent(e);
					return false;
				};
				Capacent.Util.attachEvent(closeCtrl, "click", cancelEvent);
				for (var i = 0; i < links.length; i++) {
					Capacent.Util.attachEvent(links[i], "click", cancelEvent);
				}
			}

			Capacent.Util.attachEvent(window, "resize", this._onResize.urpBind(this));
			this._customCssId = Capacent.Css.registerexternal(iframe.window || iframe.contentWindow, this.getCss());
			var tempThis = this;

			Capacent.Util.attachEvent(this._iframe.window || this._iframe.contentWindow, "load", function () {
				setTimeout(function () {
					Capacent.RoundButtons.Register(tempThis._acceptCtrl);
					Capacent.RoundButtons.Register(tempThis._rejectCtrl);
				}, 10)
			});
		},
		intervalTimerId: null,
		show: function () {
			this.ensureInit();
			var self = this;
			this.intervalTimerId = setInterval(function () {
				if (self.intervalTimerId != null) {
					Capacent.Util.setVisibilityForPendentControls(false);
				}
			}, 10);
			if (this.bpn.Settings.OverlayEnabled) {
				this.bpn.Overlay.show();
			}
			this._popupCtrl.style.display = 'block';

		},
		hide: function () {
			if (this.intervalTimerId != null) {
				clearInterval(this.intervalTimerId);
				this.intervalTimerId = null;
			}
			this.ensureInit();
			this.bpn.Overlay.hide();
			this._popupCtrl.style.display = 'none';
			this._inlineSurveyFrame.src = 'about:blank';
			Capacent.Util.setVisibilityForPendentControls(true);
		},

		showInlineSurvey: function (additionalQuery) {
			this.ensureInit();
			if (this._popupCtrl.style.display != 'block') {
				this._popupCtrl.style.display = 'block';
			}

			this._popupCtrl.className += ' urpSurveyPopup';
			this._invitationControl.style.display = 'none';
			var surveyFrame = this._inlineSurveyFrame;
			var surveyUrl = this.bpn.Settings.SurveyUrl;
			if (typeof (additionalQuery) != 'undefined' && additionalQuery != '') {
				surveyUrl = surveyUrl + "&" + additionalQuery;
			}
			surveyFrame.src = surveyUrl;
			this._resizeFrame();
			surveyFrame.style.display = 'block';
		},

		/**** Live preview API ****/
		SetPopupPosition: function (left, top) {
			var self = this;
			self.bpn.addOnPopupReadyNandler(function () {

				self.ensureInit();
				self._popupCtrl.style.top = top;
				self._popupCtrl.style.left = left;
				self._popupCtrl.style.position = 'absolute';
			});
		},
		_logoImage: null,
		_logoElement: null,
		_oldLogoUrl: null,
		SetLogoUrl: function (url) {
			var self = this;
			self.bpn.addOnPopupReadyNandler(function () {
				self.ensureInit();
				var logoContainer = self._logoElement;
				if (Capacent.String.isNullOrEmpty(url) == false) {
					if (self._logoImage == null) {
						self._oldLogoUrl = logoContainer.style.backgroundImage;
						logoContainer.style.backgroundImage = 'none';
						logoContainer.style.overflow = 'hidden';

						var img = self._iframeDoc.createElement('img');
						self._logoImage = logoContainer.appendChild(img);
					}
					self._logoImage.src = url;
				} else {
					if (self._oldLogoUrl == null) {
						return;
					}
					logoContainer.style.backgroundImage = '';
					logoContainer.removeNode(self._logoImage);
					self._logoImage = null;
				}

			});
		},
		SetLogoHeight: function (h) {
			var self = this;
			self.bpn.addOnPopupReadyNandler(function () {
				if (self._logoImage != null) {
					self._logoImage.style.height = parseInt(h, 10) + 'px';
				}
			});
		},
		SetLogoPosition: function (x, y) {
			var self = this;
			self.bpn.addOnPopupReadyNandler(function () {
				if (self._logoImage != null) {
					self._logoImage.style.marginLeft = x + 'px';
					self._logoImage.style.marginTop = y + 'px';
				}
			});
		},
		SetColors: function (color1, color2) {
			var self = this;
			self.bpn.addOnPopupReadyNandler(function () {
				self.ensureInit();

				self._color1 = color1;
				self._color2 = color2;

				var iframe = self._iframe;
				var iframeDoc = self._iframeDoc;
				var el = iframeDoc.getElementById(self._customCssId);
				if (el != null) {
					el.parentNode.removeChild(el);
				}
				self._customCssId = Capacent.Css.registerexternal(iframe.window || iframe.contentWindow, self.getCss());
				Capacent.RoundButtons.Update();
			});
		},
		_onPostponeClick: function (event) {
			Capacent.Util.cancelEvent(event);
			var bpn = (event.target || event.srcElement).bpn;
			bpn.Popup.hide();
			bpn.Popup.PostponeInvitation(bpn);
			return false;
		},

		checkWhetherSurveyCompleted: function (data, bpn) {
			if (data.IsSurveyCompleted == true) {
				bpn.Popup.CompleteTheInvitation(bpn);
			}
			else {
				if (this.bpn.CurrentSession.IsSurveyStarted == true) {
					bpn.Popup.PostponeInvitation(bpn);
				}
			}
		},
		CompleteTheInvitation: function (bpn) {
			this.bpn.Popup.HideContinueLink();
			this.bpn.CurrentSession.IsPostponed = false;
			this.bpn.CurrentSession.save();
		},
		PostponeInvitation: function (bpn) {
			this.bpn.CurrentSession.IsPostponed = true;
			this.bpn.CurrentSession.save();

			var postponeCompleted = function () { bpn.log.write("Postpone completed"); };
			if (bpn.Settings.TestInviteMode == false) {
				bpn.Backend.setInvitationPostponed(bpn.Settings.InvitationId, bpn.Settings.RespondentId, function (data) {
					bpn.Popup.SetTagUserId(bpn, data.UserIdToSet, postponeCompleted);
				});
			}
			else {
				postponeCompleted();
			}
			bpn.Popup.ShowContinueSurveyButton();
		},

		continueInited: null,
		_continueLink: null,
		InitContinueSurveyButton: function () {
			if (arguments.callee.done) return;
			arguments.callee.done = true;
			if (this.continueInited == true) {
				return;
			}
			if (Capacent.String.isNullOrEmpty(this.bpn.CurrentSession.ContinueTitle)) {
				return;
			}
			Capacent.Css.registerUrl(this.bpn.Settings.PopupCssUrl);
			var continueLink = document.createElement('div');
			continueLink.setAttribute('id', "bpnContinueDiv");
			continueLink.className = "bpn-continue-survey-link";

			continueLink.style.display = 'none';
			continueLink.style.visibility = 'hidden';
			continueLink.bpn = this.bpn;
			this._continueLink = document.body.appendChild(continueLink);
			var iframe = this._createContinueIframe(document.getElementById('bpnContinueDiv'), "urpContinueFrame");
			this._iframe = iframe;
			var iframeDoc = this._getFrameDoc(iframe);
			this._iframeDoc = iframeDoc;
			iframeDoc.open();
			iframeDoc.write(this._getHeader(this.bpn));
			iframeDoc.write(this.getContinueLinkContent());
			iframeDoc.write(this._footer);
			iframeDoc.close();
			iframeDoc.getElementsByTagName("body")[0].className = "continueFrameBody";
			iframeDoc.getElementsByTagName("html")[0].className = "continueFrameHtml";

			var link = iframeDoc.getElementsByTagName("a")[0];
			link.href = this.bpn.Settings.SurveyUrl;
			link.target = "_blank";
			link.bpn = this.bpn;
			link.firstChild.bpn = this.bpn;
			Capacent.Util.attachEvent(link, "click", this._onContinueSurveyClick);

			Capacent.Css.registerexternal(iframe.window || iframe.contentWindow, this.getContinueLinkCss());
			this.ensureDocumentBGExists();
			this.continueInited = true;
		},

		ShowContinueSurveyButton: function () {
			this.InitContinueSurveyButton();
			if (this._continueLink != null) {
				this._continueLink.style.display = 'block';
				this._continueLink.style.visibility = 'visible';
			}
		},
		getContinueLinkContent: function () {
			//TODO: use popup CSS for this button
			var html = '';
			html += '<a id="bpnContnue"><span>' + this.bpn.CurrentSession.ContinueTitle + '</span></a>';
			return html;
		},

		_onContinueSurveyClick: function (event) {
			var bpn = (event.target || event.srcElement).bpn;
			return bpn.Popup.ShowSurvey(bpn, event, true);
		},

		HideContinueLink: function () {
			if (this._continueLink != null) {
				this._continueLink.style.display = 'none';
				this._continueLink.style.visibility = 'hidden';
			}
		},

		ensureDocumentBGExists: function () {
			if (Capacent.Util.isMSIE6()) {
				if (document.body.currentStyle.backgroundImage == '' || document.body.currentStyle.backgroundImage == 'none') {
					document.body.className += ' urpBackgroundFix';
				}
			}
		},

		getContinueLinkCss: function () {
			var cssBuilder = Capacent.Css.createCssBuilder();

			var color1 = this._color1 || this.bpn.CurrentSession.CustomMainColor;
			var color2 = this._color2 || this.bpn.CurrentSession.CustomSecondaryColor;

			if (Capacent.String.isNullOrEmpty(color1) != true || Capacent.String.isNullOrEmpty(color2) != true) {
				cssBuilder.createRule('a#bpnContnue');
				cssBuilder.addProperty('border-color', color1);
				cssBuilder.addProperty('color', color2);
				cssBuilder.addProperty('background-color', color1);

				cssBuilder.createRule('a#bpnContnue:hover');
				cssBuilder.addProperty('border-color', color1);
				cssBuilder.addProperty('color', color1);
				cssBuilder.addProperty('background-color', color2);
			}
			var css = cssBuilder.toString();
			return css;

		}
	};
	// read constructor parameters
	Capacent.Util.mergeObjects(this.Settings, constructorParams || {});

	this.log = new Capacent.Log({ Enable: this.Settings.ShowLog, ModuleName: "SYSTEM" });
	this.Backend.bpn = this;
	this.Feedback.bpn = this;
	this.Popup.bpn = this;
	this.CIAction.bpn = this;
	this.GA.bpn = this;
	this.GA.log = new Capacent.Log({ Enable: this.Settings.ShowLog, ModuleName: "GA" });

	var self = this;

	this._onCommunicationFailure = function (code, data) {
		self.log.write('Failed to communicate server. Error code: ' + code);
	};
	this._onPopupReadyCallsQueue = new Capacent.LazyCalls();

	this.addOnPopupReadyNandler = function (f) {
		self._onPopupReadyCallsQueue.call(f);
	}
	// Calls after site is were set
	this.init = function () {
		// Initialize session function
		var initSession = function (sessionVariables, doneCallback) {
			self.Backend.getSiteInfoAsync(self.Settings.SiteId, function (data) {
				sessionVariables.InvitationTitle = data.InvitationTitle;
				sessionVariables.UserReportWithGaUrl = data.UserReportWithGaUrl;
				sessionVariables.InvitationText = data.InvitationText;
				sessionVariables.AcceptTitle = data.AcceptTitle;
				sessionVariables.ContinueTitle = data.ContinueTitle;
				sessionVariables.RejectTitle = data.RejectTitle;
				sessionVariables.CloseTooltip = data.CloseTooltip;
				sessionVariables.FeedbackEnabled = data.CrowdIntelligenceEnabled;
				sessionVariables.Skin = data.Skin;
				sessionVariables.CustomLogoUrl = data.CustomLogoUrl;
				sessionVariables.SurveyCulture = data.SurveyCulture;
				sessionVariables.CustomMainColor = data.CustomMainColor;

				sessionVariables.FeedbackPin = data.ShortcutPin;
				sessionVariables.FeedbackAttach = data.ShortcutAttach;
				sessionVariables.FeedbackOffset = data.ShortcutOffset;

				sessionVariables.CustomSecondaryColor = data.CustomSecondaryColor;
				sessionVariables.SiteName = data.SiteName;
				sessionVariables.TrackingImageUrl = data.TrackingImageUrl;
				doneCallback();
			});
		};
		// Continue initialization routine. Calls after session have been initialized
		var init = function () {
			this._onPopupReadyCallsQueue.flush();
			if (this.Settings.TestInviteMode) {
				this.Settings.SurveyUrl = this.Settings.getTestInviteSurveyUrl();
				this.Settings.FeedbackUrl = this.Settings.getFeedbackUrl();
				Capacent.Util.onLoadGuaranteed(function () {
					self.Popup.show();
					self.CIAction.init();
					if ((self.CurrentSession.FeedbackEnabled && self.Settings.CIEnabled != Capacent.CI_Status.Disabled)
						|| self.Settings.CIEnabled == Capacent.CI_Status.Forced) {
						self.Feedback.showLink();
					}
				});
			} else {
				this.log.write('Starting initialization');
				if ((self.CurrentSession.FeedbackEnabled && self.Settings.CIEnabled != Capacent.CI_Status.Disabled)
						|| self.Settings.CIEnabled == Capacent.CI_Status.Forced) {
					self.log.write("<b>Feedback enabled!</b>");
					Capacent.Util.onLoadGuaranteed(function () {
						self.CIAction.init();
						self.Feedback.showLink();
					});
				}
				else {
					self.log.write("<b>Feedback disabled!</b>");
				}
				if (self.CurrentSession.WasInvited) {
					self.log.write('User <b>was</b> invited in this session<br />Invitation skipped.');
					if (self.CurrentSession.IsPostponed == true) {
						self.Settings.SurveyUrl = self.CurrentSession.SurveyUrl;
						self.Settings.InvitationId = self.CurrentSession.InvitationId;
						self.Popup.ShowContinueSurveyButton();
					}
				} else {
					this.log.write('Begin get user id');
					//Turn on migration!
					var tag = new Capacent.Tag({}, true);
					var tagLog = new Capacent.Log({ Enable: self.Settings.ShowLog, ModuleName: "TAG" });
					tag.log = function (message) { tagLog.write(message); };

					tag.get(function (id, options) {
						if (!Capacent.String.isNullOrEmpty(id)) {
							self.Settings.RespondentId = id;
							self.log.write("<b>Detected respondent: " + id + "</b>");
						}
						var url = Capacent.Util.getUrl();
						var respondentId = self.Settings.RespondentId;
						//TODO: fetch this info From Tag System
						self.Backend.getParticipationFactorAsync(url, self.Settings.SiteId, respondentId, options.HasFlashCookie, self.Settings.Params, function (data) {
							self.CurrentSession.WasInvited = true;

							if (data.GAVariables && data.GAVariables.length > 0) {
								self.log.write("<b>Got variables to set from server</b>");
								self.GA.SetVariables(data.GAVariables);
							}

							if (data.AllowToParticipate) {
								self.log.write("<b>Invitate user to participate the survey!</b>");
								self.Settings.SurveyUrl = data.SurveyUrl;
								if (self.Settings.Inline == true) {
									self.Settings.SurveyUrl += "&inline=true";
								}
								self.CurrentSession.SurveyUrl = self.Settings.SurveyUrl;
								self.Settings.InvitationId = data.NavId;
								self.CurrentSession.InvitationId = data.NavId;
								self.log.write("BE-Server returned the following survey URL: " + self.Settings.SurveyUrl);
								Capacent.Util.onLoadGuaranteed(function () {
									self.log.write("<b>Showing popup!</b>");
									self.Popup.show();
								});
							}

							self.CurrentSession.save();

						});
					});
				}
			}
		};
		this.CurrentSession._sessionSuffix = this.Settings.SiteId;
		if (this.Settings.RefreshSession == true || this.Settings.TestInviteMode == true) {
			this.CurrentSession.destroy();
		}
		// Initialize session and procced with
		// Session are saving in cookie named "urpSession_{$SiteId}"
		this.CurrentSession.init(init.urpBind(this), initSession, this.Settings.TestInviteMode == false);
	};
	this.ensureInit = function () {
		// Allow to run method only one time
		if (arguments.callee.done) return;
		arguments.callee.done = true;
		this.init();
	};
	this.setSite = function (value) {
		if (Capacent.String.isNullOrEmpty(value)) {
			var self = this;
			this.Backend.getWebsiteId(function (data) {
				var siteId = data.WebsiteId;
				if (Capacent.String.isNullOrEmpty(siteId)) {
					self.log.write("Site id not found by URL!");
				} else {
					self.log.write("<b>Site id detected: " + siteId + "</b>");
					self.Settings.SiteId = siteId;
					self.ensureInit();
				}
			});
		} else {
			this.Settings.SiteId = value;
			this.ensureInit();
		}
	};
};



// Run-time below...
// External bvt instance
(function () {
	var BPN;
	window._bvt = {
		inline: true,
		parameters: {},
		setParam: function (paramName, paramValue) {
			this.parameters[paramName] = paramValue;
		},
		site: null,
		initSite: function (value) {
			this.site = value;
			var _this = this;
			Capacent.Util.onDomReady(function () {
				var location = window.location.href;
				var testInviteMode = (/__(bpn|urp)=test_invite/i).test(location);
				var showLog = (/__(bpn|urp)ui=show_debug/i).test(location) || (/__(bpn|urp)=debug/i).test(location);
				var ciStatus = (/__urpCI=force/i).test(location) ? Capacent.CI_Status.Forced : Capacent.CI_Status.Auto;
				// Internal bvt instance
				BPN = new Capacent.BPN({
					TestInviteMode: testInviteMode,
					ShowLog: showLog,
					Inline: _this.inline,
					Params: _this.parameters,
					CIEnabled: ciStatus
				});
				BPN.setSite(_this.site);
			});
		},
		setStayAwayRespondent: function(callback){
			BPN.Backend.setStayAwayRespondent(callback);
		}
	};
})();

(function () {
	var BPN;
	window.InvitationPreview = {
		SetLogoUrl: function (url) {
			BPN.Popup.SetLogoUrl(url);
		},
		SetColors: function (c1, c2) {
			BPN.Popup.SetColors(c1, c2);
		},
		SetPopupPosition: function (left, top) {
			BPN.Popup.SetPopupPosition(left, top);
		},
		SetLogoHeight: function (h) {
			BPN.Popup.SetLogoHeight(h);
		},
		SetLogoPosition: function (x, y) {
			BPN.Popup.SetLogoPosition(x, y);
		},
		Init: function (siteId) {
			// Internal bvt instance
			BPN = new Capacent.BPN({
				TestInviteMode: true,
				ShowLog: false,
				Inline: true,
				Params: {},
				CIEnabled: Capacent.CI_Status.Disabled,
				OverlayEnabled: false,
				LinksEnabled: false,
				RefreshSession: true,
				TrackingEnabled: false
			});
			BPN.setSite(siteId);
		}
	};
})();