
try { if(navigator.appVersion.match(/[34]\.[.0-9 ]+Safari/)) {
	var d = document.createElement('div');
	d.style.height = 0;
	var tgt = 'jsk-ifrmsess-' + Math.random();
	d.innerHTML = '<iframe id="' + tgt + '" name="' + tgt + '" src="about:blank" width=0 height=0 style="border: none"></iframe>';
	var f = function() {
		document.body.appendChild(d);
		var ifrsess = d.firstChild;
		var getFrame = function(FrameName, Parent) {
			var tp = Parent ? getFrameDoc(Parent) : document;
			var fr = tp.getElementById(FrameName).contentWindow;
			return fr;
		}
		var getFrameDoc = function(FrameName, Parent) {
			var FEl = getFrame(FrameName, Parent);
			return FEl.contentDocument || FEl.document;
		}

		var iDOC = getFrameDoc(tgt);
		var frm = iDOC.createElement('form');
		frm.method = 'post';frm.action = window.location.protocol + '//js-kit.com/api/session/refresh.js';
		iDOC.body.appendChild(frm);
		ifrsess.onreadystatechange = ifrsess.onload = function() {
			if(ifrsess.readyState && ifrsess.readyState != 'loaded'
				&& ifrsess.readyState != 'complete') return;
			ifrsess.onload = ifrsess.onreadystatechange = null;
			
		};
		frm.submit();
	}
	if(document.body) f();
	else setTimeout(f, 0);
} else {}} catch(e) {};
/*
 * Copyright (c) 2006-2009 JS-Kit <support@js-kit.com>. All rights reserved.
 * You may copy and modify this script as long as the above copyright notice,
 * this condition and the following disclaimer is left intact.
 * This software is provided by the author "AS IS" and no warranties are
 * implied, including fitness for a particular purpose. In no event shall
 * the author be liable for any damages arising in any way out of the use
 * of this software, even if advised of the possibility of such damage.
 * $Id: comments.js 14554 2009-06-10 10:15:59Z jskit $
 */

if(!window.$JCA) {
  var $JCA = [];
  var $JCLT = {
	leaveComment: 'Leave a comment',
	leaveCommentAs: 'Leave a comment as:',
	guest: 'Guest',
	existingJSKitProfile: 'Existing JS-Kit profile',
	newJSKitProfile: 'New JS-Kit profile',
	existingHaloscanProfile: 'Existing Haloscan profile',
	usingOpenID: 'Using OpenID',
	blogspotURL: 'Using Blogspot URL',
	connectFacebook: 'Connect with Facebook account',
	connectYahoo: 'Connect with Yahoo account',
	connectGFC: 'Connect with Google Friend Connect',
	connectTwitter: 'Connect with Twitter account',
	login: 'Login',
	loginBtn: 'Login',
	register: 'Register',
	password: 'Password:',
	retypePassword: 'Re-type Password:',
	haloscanLogin: 'Haloscan login',
	haloscanPassword: 'Haloscan password:',
	openID: 'OpenID:',
	url: 'URL:',
	nameLabel: 'Your name:',
	nicknameLabel: 'Nickname (required):',
	nicknameRequired: 'Nickname is a required field',
	emailLabel: 'Send replies to email:',
	emailNote: '(if provided, email will not be displayed or shared)',
	emailFirstNote: 'E-mail is mandatory for administrator',
	emailRequired: 'E-mail is required. Click "OK" if you are the administrator of this site. \n Click "Cancel" if you are not the administrator of this site.',
	emailConfirmation: 'is about to become the official administrator for this site. \n Click "OK" to confirm or "Cancel" to remove the e-mail address.',
	ratingLabel: 'Rating:',
	commentLabel: 'Comment:',
	submit: 'Submit comment',
	save: 'Save',
	cancel: 'Cancel',
	tooShort: 'Your message is too short',
	tooLong: 'Message size should not exceed {maxCommentLength} characters',
	junkCtl: 'Junk control',
	byVotes: 'by',
	selectedAvatar: 'Selected Avatar',
	uploadAvatar: 'Upload new avatar:',
	removeAvatar: 'Remove Avatar',
	removeAvatarConfirm: 'Remove this avatar?',
	jskitAccount: 'JS-Kit as: ',
	haloscanAccount: 'Haloscan as: ',
	logout: 'logout',
	less: 'less',
	more: 'more',
	optionsU: 'Options &#x25b2;',
	optionsD: 'Options &#x25bc;',
	isJunkVote: 'Is this inappropriate junk or SPAM message?',
	editAvatarsBtnLabel: 'Click to manage avatars',
	deleteAvatarsBtnLabel: 'Click to delete avatar',
	avatarsManagementLabel: 'Avatars management:',
	noAvatarsMessage: 'No avatars uploaded',
	loading: 'Loading ...',
	submitPM: 'Leave private message',
	welcomeToComments: 'Welcome to JS-Kit Comments &mdash; we\'re very happy to see you!',
	adminNote: 'Administration Note - JS-Kit Comments widget',
	openWelcome: 'Open Administration Panel',
	closeWelcome: 'Close Administration Panel',
	contactSupport: 'Contact our support team',
	editProfile: 'Edit your public profile',
	readFAQ: 'Read our FAQ',
	customizeLook: 'Customize the look and feel',
	adminDashboard: 'Admin Dashboard',
	followTwitter: 'Follow us on Twitter',
	checkWidgets: 'Check out our other widgets',
	requireAuth: 'This site requires registration before you can leave a comment. Select an authentication option under the "Leave a comment as" menu',
	deleteImage: 'Delete image',
	editImage: 'Edit description',
	bigImage: 'The image file you are trying to upload is too big.',
	uploadImage: 'Upload new image (up to 10 megabytes):',
	addPicText: 'Add pictures',
	picTitle: 'PICTURES',
	commentMoveNotice: "Page reload will cause your comment to move according to your sorting and ordering preferences.",
	shareYahoo: "Share via ",
	shareTwitter: "Tweet this",
	shareFB: "Share via Facebook",
	shareGFC: "Share via Google Friend Connect",
	commentMoveNotice: 'Page reload will cause your comment to move according to your sorting and ordering preferences.',
        getPermalinkURL: 'URL of this comment',
        getWidgetLikeThis: 'Get a widget like this',
	options: 'More',
	showUserProfile: 'Show user\'s profile',
	markAsOffensive: 'Mark comment as offensive'
  };
  var $JCL = window.JSCC_Translate || function(t, tmpl) {
	var text = (window.$JCLTL ? $JCLTL[t] : false) || $JCLT[t] || t;
	if(tmpl) JSKitLib.fmap(tmpl,
		function(v,k){text=text.replace(new RegExp('{'+k+'}','g'),v);});
	return text;
  }
}


if(!window.JSKitAPI) JSKitAPI = {};
JSKitAPI.allowed_event_names = { "comment-submit": true, "comments-data-loaded": true };
JSKitAPI.subscribe = function(kit_event, callback) {
	if(this.allowed_event_names.hasOwnProperty(kit_event)) {
		return JSKW$Events.registerEventCallback(null,
		function(name, base, args) {
			try {
				var v = callback.apply(base['this'], args);
				var rvalue = { 'type': 'value', 'value': v };
			} catch(e) {
				var rvalue = { 'type':'exception', 'value': e };
			}
			base.returns.push(rvalue);
		}, "STABLE-API-" + kit_event);
	} else {
		return null;
	}
}
JSKitAPI.unsubscribe = function(token) {
	JSKW$Events.invalidateContext(token);
}
JSKitAPI.publish = function(kit_event) {
	var elist = window.JSKitEvents;
	if (elist) {
		JSKitLib.fmap(elist, function(v) {
			JSKitAPI.subscribe(v.subscribe, v.callback);
		});
		window.JSKitEvents = null;
	}
	var base = { 'this': this, returns: [] };
	JSKW$Events.syncBroadcast("STABLE-API-" + kit_event, base, arguments);
	return base.returns;
}
// .askpublic() publishes the event, interprets the response and _throws_
// if any called callback threw. Otherwise, a simple .publish will ignore
// throws. This is used to translate errors generated in the callback
// to the application itself.
JSKitAPI.askpublic = function(kit_event) {
	return JSKitAPI._interpret(JSKitAPI.publish.apply(this, arguments));
}
JSKitAPI._interpret = function(returns) {
	var rvalue = { 'type': 'value', 'value': true };
	// Throw _some_ observed exception or returns _some_ value.
	// "_some_" because the subscription order can not be relied upon.
	return JSKitLib.foldl(rvalue, returns, function(r) {
		if(r.type == 'exception') throw(r.value);
		rvalue.value = r.value;
	}).value;
}



if(!window.JSKitEPB){
	var JSKitEPB = new JSKitEPBLib();
}

function JSKitEPBLib() {
	this.JSK$EPB = window.JSK$EPB ? window.JSK$EPB : {};
}

JSKitEPBLib.prototype.isExists = function() {
	return (this.JSK$EPB.mac && this.JSK$EPB.profile) ? 1: 0;
}

JSKitEPBLib.prototype.isAdmin = function(Path) {
	var arrIndexOf = function(arr, Val) {
		var ValLC = Val.toLowerCase();
		for(var i = arr.length - 1; i >= 0; i--) {
			var v = arr[i];
			if(typeof(v) == "string")
				v = v.toLowerCase();
			if(v == ValLC) return i;
		}
		return -1;
	}
	return this.isExists() && this.JSK$EPB.profile.owner && arrIndexOf(this.JSK$EPB.profile.owner,Path) != -1 ? 1 : 0;
}

JSKitEPBLib.prototype.getValue = function(ValueName) {
	return !this.isExists() || this.JSK$EPB.profile[ValueName] == undefined ? undefined : this.JSK$EPB.profile[ValueName];
}

JSKitEPBLib.prototype.getElement = function(Pref,El,ArrKey) {
	var rslt = [];
	if(typeof(El) == 'object') {
		if(El instanceof Array) {
			if(ArrKey) {
				var len = El.length;
				for(var i=0; i<len; i++)
					rslt = rslt.concat(this.getElement(Pref,El[i],ArrKey));
			}
		} else {
			for(var i in El)
				rslt = rslt.concat(this.getElement(Pref,El[i],i));
		}
	} else {
		if(ArrKey) {
			rslt.push({'Name': Pref+ArrKey, 'Value': El});
		}
	}
	return rslt;
}

JSKitEPBLib.prototype.getAsObj = function() {
	var rslt = [];
	var pref = "epb-";
	var epb = this.JSK$EPB;
	if(!epb.profile || !epb.mac) return rslt;
	rslt.push({'Name': pref+"mac",'Value': epb.mac});
	return rslt.concat(this.getElement(pref,epb.profile));
}

JSKitEPBLib.prototype.getURIEncodedSerialize = function() {
	var ser = this.getAsObj();
	var ar = [];
	for(var i=0; i<ser.length; i++) {
		ar.push(ser[i].Name + "=" + encodeURIComponent(ser[i].Value));
	}
	return ar.join("&");
}

JSKitEPBLib.prototype.getAsHash = function(obj) {
	var ser = this.getAsObj();
	JSKitLib.fmap(ser, function(v) { obj[v.Name] = v.Value; });
	return obj;
}



if(!window.JSKitLib) JSKitLib = {vars:{}};



JSKitLib.cr = function(arg) {
	if(!arg) return document.createElement("div");
	arg.t = arg.t || "div";
	var div = document.createElement(arg.t);
	if(arg.className) div.className = arg.className;
	if(arg.style) JSKitLib.fmap(arg.style, function(value, key) { div.style[key] = value; });
	return div;
}

JSKitLib.deleteProperty = function(obj, prop) {
	if (typeof obj[prop] == 'function') {
		obj[prop] = null;
	} else {
		try {
			delete obj[prop];
		} catch (e) {
			obj[prop] = null;
		}
	}
}

JSKitLib.trim = function(str) {
	if (typeof(str) != "string") return "";
	var str = str.replace(/^\s\s*/, ''), ws = /\s/, i = str.length;
	while (ws.test(str.charAt(--i)));
	return str.slice(0, i + 1);
}

JSKitLib.encodeJSONLiteral = function(string) {
	var replacements = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'};
	return string.replace(/[\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff\\]/g, 
		function (a) { return (replacements.hasOwnProperty(a)) ? replacements[a] : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); });
}

JSKitLib.Object2JSON = function(obj) {
	var out;
	switch (typeof(obj)) {
		case "number"  : out = obj; break; 
		case "string"  : out = '"' + JSKitLib.encodeJSONLiteral(obj) + '"'; break;	
		case "boolean" : out = '"' + obj.toString() + '"'; break;
		default :
			if (obj instanceof Array) {
				var container = JSKitLib.fmap(obj, function(element) { return JSKitLib.Object2JSON(element); });
				out = '[' + container.join(",") + ']';
			} else if(obj instanceof Object) {
				var source = obj.exportProperties || obj;
				var container = JSKitLib.fmap(source, function(value, property) {
					if (source instanceof Array) { property = value; value = obj[property]; } 
					return '"' + property + '":' + JSKitLib.Object2JSON(value);
				});
	      			out = '{' + container.join(",") + '}';
			}
	}
	return out;
}

JSKitLib.appendExternalParams = function(service, requestType, currentParams) {
	if (!window.JSKitExternalParams) return currentParams;
	JSKitLib.fmap(window.JSKitExternalParams, function(data) {
		var serviceRegExp = new RegExp(data.service || "*");
		var requestTypeRegExp = new RegExp(data.requestType || "*");
		if (serviceRegExp.test(service) && requestTypeRegExp.test(requestType)) {
			JSKitLib.fmap(data.params, function(value, key) { currentParams[key] = value; });
		}
	});
	return currentParams;
}



/////////////////////////////////////////
//	JS Menu base class
/////////////////////////////////////////

function JSMenuItemBase(obj) {
	if(!obj) return;
	this.init(obj);
}

JSMenuItemBase.prototype.init = function(obj) {
	JSKitLib.fmap.call(this, obj, function(value, key) {this[key] = value;});
	this.items = [];
	this.createItem();
	this.addItemHighlighting();
	this.createContainer();
	this.attachContainer();
	this.addAction();
	JSKitLib.hide(this.outerCnt);
}

JSMenuItemBase.prototype.createItem = function() {
	this.itemNode = JSKitLib.cr({t:"tr", className: this.cssPrefix + "Item"});
	if(this.hidden) JSKitLib.hide(this.itemNode);
	JSKitLib.fmap.call(this, ["Icon", "Title", "Ending"], function(part, i) {
		var td = JSKitLib.cr({t:"td", className: this.cssPrefix + "Item"});
		this.itemNode.appendChild(td);
		var div = JSKitLib.cr({className: this.cssPrefix + "Item" + part});
		td.appendChild(div);
		this["render" + part](div);
		JSKitLib.preventSelect(div);
		this[part.toLowerCase() + "Node"] = div;
	});
}

JSMenuItemBase.prototype.renderIcon = function(cnt) {
	if(this.icon) JSKitLib.addPNG(cnt, this.icon);
}

JSMenuItemBase.prototype.renderTitle = function(cnt) {
	cnt.appendChild(document.createTextNode(this.title));
}

JSMenuItemBase.prototype.renderEnding = function(cnt) {};

JSMenuItemBase.prototype.addItemHighlighting = function() {
	var self = this;
	JSKitLib.fmap([{event: "mouseover", action: "addClass"}, {event: "mouseout", action: "removeClass"}], function(e) {
		JSKitLib.addEventHandler(self.itemNode, [e.event], function() {
			if(self.statusText) {
					window.status = e.event == "mouseover" ? self.statusText : "";
			}
			JSKitLib.fmap(["item", "icon", "title", "ending"], function(part) {
				JSKitLib[e.action](self[part + "Node"], self.cssPrefix + "ItemMO");
			});
		});
	});
}

JSMenuItemBase.prototype.createContainer = function() {
	this.outerCnt = JSKitLib.cr({className: this.cssPrefix + "Container"});	
	if(JSKitLib.isIE()) this.outerCnt.style.zoom = "1";
	var tbl = JSKitLib.cr({t:"table"});
	tbl.cellSpacing = tbl.cellPadding = "0";
	this.innerCnt = JSKitLib.cr({t:"tbody"});
	this.outerCnt.appendChild(tbl);
	tbl.appendChild(JSKitLib.cr({t:"thead"}));
	tbl.appendChild(this.innerCnt);
	tbl.appendChild(JSKitLib.cr({t:"tfoot"}));
}

JSMenuItemBase.prototype.attachContainer = function() {
	JSKitLib.show(this.outerCnt, "inline");
	this.endingNode.parentNode.appendChild(this.outerCnt);
}

JSMenuItemBase.prototype.appendItem = function(item) {
	if(!this.items.length) {
		this.addExpandMarker();
		this.addExpandHandler();
		this.addCollapseCallback();
	}
	this.innerCnt.appendChild(item.itemNode);
	this.items.push(item);
	item.parent = this;
}

JSMenuItemBase.prototype.addExpandMarker = function() {
	this.endingNode.appendChild(document.createTextNode("\u25BA"));
}

JSMenuItemBase.prototype.addExpandHandler = function() {
	var self = this;
	JSKitLib.fmap([{event: "mouseover", display: "inline"}, {event: "mouseout", display: "none"}], function(e) {
		JSKitLib.addEventHandler(self.itemNode, [e.event], function() {
			JSKitLib.show(self.outerCnt, e.display);
		});
	});
}

JSMenuItemBase.prototype.addCollapseCallback = function() {
	var self = this;
	JSKW$Events.registerEventCallback(undefined, function() {
		self.outerCnt.style.display = "none";
	}, "JSMenu-CollapseAll");
}

JSMenuItemBase.prototype.addAction = function() {
	if(this.action) JSKitLib.addEventHandler(this.itemNode, ["click"], this.action);
}

/////////////////////////////////////////
//	JS Root Menu class
/////////////////////////////////////////

function JSMenuItemRoot(obj) {
	this.init(obj);
	JSKitLib.addClass(this.outerCnt, this.cssPrefix + "RootContainer");
}

JSMenuItemRoot.prototype = new JSMenuItemBase();

JSMenuItemRoot.prototype.createItem = function() {
	this.itemNode = JSKitLib.cr();
	JSKitLib.fmap.call(this, [{name: "title", suff: ""}, {name: "ending", suff: "ExpandMarker"}], function(part) {
		this[part.name + "Node"] = JSKitLib.cr({className: this.cssPrefix + "Title" + part.suff});
	});
	if(this.title) {
		var tbl = JSKitLib.cr({t:"table"});
		var row = tbl.insertRow(0);
		JSKitLib.fmap.call(this, ["title", "ending"], function(part, i) {
			row.insertCell(i).appendChild(this[part + "Node"]);
		});
		JSKitLib.addPNG(this.endingNode, "//js-kit.com/images/menu/vertical-menu-expand-marker.png");
		this.titleNode.appendChild(document.createTextNode(this.title));
		this.itemNode.appendChild(tbl);
	}
}

JSMenuItemRoot.prototype.addItemHighlighting = function() {
	var self = this;
	JSKitLib.fmap([{event: "mouseover", action: "addClass"}, {event: "mouseout", action: "removeClass"}], function(e) {
		JSKitLib.addEventHandler(self.itemNode, [e.event], function() {
			JSKitLib[e.action](self.itemNode, self.cssPrefix + "TitleMO");
		});
	});
}

JSMenuItemRoot.prototype.addExpandHandler = function() {
	var self = this;
	JSKitLib.addEventHandler(this.itemNode, ["click"], function(e) {
		var need2hide = (self.outerCnt.style.display != "none");
		JSKW$Events.syncBroadcast("JSMenu-CollapseAll");
		JSKitLib.stopEventPropagation(e);
		if(need2hide) {
			JSKitLib.removeClass(self.titleNode, self.cssPrefix + "TitlePressed");
		} else {
			JSKitLib.addClass(self.titleNode, self.cssPrefix + "TitlePressed");
			JSKitLib.show(self.outerCnt, "block");
		}
	});
}

JSMenuItemRoot.prototype.addCollapseCallback = function() {
	var self = this;
	JSKW$Events.registerEventCallback(undefined, function() {
		self.outerCnt.style.display = "none";
		JSKitLib.removeClass(self.titleNode, self.cssPrefix + "TitlePressed");
	}, "JSMenu-CollapseAll");
}

JSMenuItemRoot.prototype.attachContainer = function() {
	this.itemNode.appendChild(this.outerCnt);
}

JSMenuItemRoot.prototype.addExpandMarker = function() {};

/////////////////////////////////////////
//	JS Menus Delimeter
/////////////////////////////////////////

function JSMenuItemDelimeter(obj) {
	this.level = obj.level;
	this.itemNode = JSKitLib.cr({t:"tr"});
	var td = JSKitLib.cr({t:"td"});
	td.colSpan = "3";
	var delim = JSKitLib.cr({className: obj.cssPrefix + "Delimeter"});
	td.appendChild(delim);
	this.itemNode.appendChild(td);
}

/////////////////////////////////////////
//	JS Menus with dynamic text input
/////////////////////////////////////////

function JSMenuItemDTI(obj) {
	this.init(obj);
}

JSMenuItemDTI.prototype = new JSMenuItemBase();

JSMenuItemDTI.prototype.renderTitle = function(cnt) {
	var text = document.createTextNode(this.title);
	var input = JSKitLib.html('<input type="text" readonly style="display:none" value="' + this.inputValue + '" class="' + this.cssPrefix + 'Input">');
	cnt.appendChild(text);
	cnt.parentNode.insertBefore(input, cnt);
	JSKitLib.addEventHandler(this.itemNode, ["click"], function(e) {
		JSKitLib.stopEventPropagation(e);
		cnt.style.visibility = "hidden";
		JSKitLib.show(input);
		input.focus();
		input.select();
	});
	input.onblur = function() {
		JSKitLib.hide(input);
		cnt.style.visibility = "visible";
	}
}

/////////////////////////////////////////
//	JS Menus interface
/////////////////////////////////////////

function JSMenu(title, data, cssPrefix, scroller) {
	var root = new JSMenuItemRoot({title: title, cssPrefix: cssPrefix, level: 0});
	var curItem = root;
	JSKitLib.fmap(data, function(itemData) {
		itemData.cssPrefix = cssPrefix;
		var item = itemData.type ? (new window["JSMenuItem" + itemData.type](itemData)) : (new JSMenuItemBase(itemData));
		while(item.level <= curItem.level) curItem = curItem.parent;
		curItem.appendItem(item);
		curItem = item;
	});
	JSKitLib.addEventHandler(document, ["click"], function(e) {
		if(JSKitLib.getBrowser() != "gecko" || e.button != 2) JSKW$Events.syncBroadcast("JSMenu-CollapseAll");
	});
	return root.itemNode;
}




JSKitLib.isPreIE7 = function() {
	if (document.body && document.body.filters && parseInt(navigator.appVersion.split("MSIE") [1]) < 7)
		return true;
}

JSKitLib.isPreIE8 = function() {
	if (document.body && document.body.filters && parseInt(navigator.appVersion.split("MSIE") [1]) < 8)
		return true;
}

JSKitLib.isIE = function() {
	if (document.body && document.body.filters && navigator.appVersion.match(/MSIE/))
		return true;
}

JSKitLib.getBrowser = function() {
	if (JSKitLib.vars.browser) return JSKitLib.vars.browser;
	if (document.body && document.body.filters && navigator.appVersion.match(/MSIE/)) {
			JSKitLib.vars.browser = "IE";
	} else if ((navigator.appCodeName.toLowerCase()=="mozilla") 
		&& (navigator.appName.toLowerCase()=="netscape") 
		&& (navigator.product.toLowerCase()=="gecko") 
	) {
		if (navigator.userAgent.toLowerCase().indexOf("safari")!=-1) {
			JSKitLib.vars.browser = "safari";
		} else if (navigator.userAgent.toLowerCase().indexOf("firefox")!=-1) {
			JSKitLib.vars.browser = "gecko";
		}
	} else if (navigator.product && navigator.product.toLowerCase()=="gecko") {
		JSKitLib.vars.browser = "gecko";
	}
	return JSKitLib.vars.browser;
}

JSKitLib.isFF3 = function() {
	return (navigator.userAgent.indexOf("Firefox/3") != -1);
}

JSKitLib.isGChrome = function() {
	return (navigator.userAgent.toLowerCase().indexOf('chrome') != -1);
}

JSKitLib.isSafari = function() {
	if (navigator.appVersion.match(/Safari/)) {
		return true;
	}
}

JSKitLib.isOpera = function() {
	if (navigator.appName.match(/Opera/)) {
		return true;
	}
}



JSKitLib.addEventHandler = function(obj, eventNames, eventHandler, capture) {
	JSKitLib.fmap(eventNames, function(e) {
		if (obj.addEventListener) {
			obj.addEventListener(e, eventHandler, !!capture);
		} else if (obj.attachEvent) {
			if (capture) {
				if (capture === true) capture = obj;
				capture.setCapture();
				capture.attachEvent('onlosecapture', eventHandler);
			}
			obj.attachEvent('on' + e, eventHandler);
		}
	});
}

JSKitLib.removeEventHandler = function(obj, eventNames, eventHandler, capture) {
	JSKitLib.fmap(eventNames, function(e) {
		if (obj.removeEventListener) {
			obj.removeEventListener(e, eventHandler, !!capture);
		} else if (obj.detachEvent) {
			if (capture) {
				if (capture === true) capture = obj;
				capture.detachEvent('onlosecapture', eventHandler);
				capture.releaseCapture();
			}
			obj.detachEvent('on' + e, eventHandler);
		}
	});
}

JSKitLib.stopEventPropagation = function(e) {
	if (!e) e = window.event;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
}

JSKitLib.preventDefaultEvent = function(e) {
  if (!e) e = window.event;
  e.returnValue = false;
  if (e.preventDefault) e.preventDefault();
}

JSKitLib.deferCall = function(func, onlyIE) {
	if (!JSKitLib.vars.windowOnLoadFired && (!onlyIE || (onlyIE && JSKitLib.isIE() && !window.$JSKitNoDeferCallIfIE))) {
		JSKitLib.addEventHandler(window, ['load'], func);
	} else {
		func();
	}
}

JSKitLib.addHandlers = function(obj, moveHandler, upHandler, capture) {
	JSKitLib.addEventHandler(obj, ['mousemove'], moveHandler, capture);
	JSKitLib.addEventHandler(obj, ['mouseup'], upHandler, capture);
}

JSKitLib.removeHandlers = function(obj, moveHandler, upHandler, capture) {
	JSKitLib.removeEventHandler(obj, ['mousemove'], moveHandler, capture);
	JSKitLib.removeEventHandler(obj, ['mouseup'], upHandler, capture);
}

JSKitLib.notDraggable = function(element) {
	element.onselectstart = function(ev) { JSKitLib.stopEventPropagation(ev); return true; }
	element.onmousedown = JSKitLib.stopEventPropagation;
	return element;
}

JSKitLib.getMousePosition = function(e) {
	if (!e) var e = window.event;
	if (e.clientX || e.clientY) {
		return {x:e.clientX, y:e.clientY};
	} else {
		return {x:e.pageX, y:e.pageY};
	}
}

JSKitLib.preventSelect = function(element, exceptions) {
	var browser = JSKitLib.getBrowser();
	var prevent = function() {
		if (browser == 'IE' || browser == 'safari') {
			element.onselectstart = function() { return false; }
		} else if (browser == 'gecko') {
			JSKitLib.addClass(element, 'js-nsgecko');
		}
	}
	if (typeof exceptions == 'object') {
		var include = exceptions.include || [];
		var exclude = exceptions.exclude || [];
		// Do not handle for certain browsers
		if (exclude.length) {
			for (var i=0; i < exclude.length; i++) {
				if (exclude[i] != browser) {
					prevent();
				}
			}
		}
		// Handle for certain browsers
		if (include.length) {
			for (var i=0; i < include.length; i++) {
				if (include[i] == browser) {
					prevent();
				}
			}
		}
	} else {
		prevent();
	}
}



JSKitLib.addCss = function(cssCode, name, content) {
	var doc = content || document;
	if(name) {
		name = "js-" + name + "-css";
		if (doc.getElementById(name)) return;
	}
	var se = doc.createElement("style");
	se.type = "text/css";
	if(name) se.id = name;
	if (se.styleSheet) se.styleSheet.cssText = cssCode;
	else se.appendChild(doc.createTextNode(cssCode));
	var hd = doc.getElementsByTagName("head");
	if(hd && hd[0]) hd[0].appendChild(se);
	else doc.write('<style>'+cssCode+'</style>');
}

JSKitLib.getElementsByClass = function(node, searchClass, tag) {
	var classElements = [];
	node = node || document;
	tag = tag || '*';
	var tagElements = node.getElementsByTagName(tag);
	var regex = new RegExp("(^|\\s)" + searchClass + "(\\s|$)");
	for (var i=0, j=0; i < tagElements.length; i++) {
		if (regex.test(tagElements[i].className)) {
			classElements[j] = tagElements[i];
			j++;
		}
	}
	return classElements;
};

JSKitLib.mapClass2Object = function(ctl, e) {
        if(e.className) {
                var arr = String(e.className).split(/[ ]+/);
                JSKitLib.map(function(el) { ctl[el] = e }, arr);
        }
        if(e.name) ctl[e.name] = e;
        try {
                var self = this;
                JSKitLib.map(function(child) {
                        JSKitLib.mapClass2Object(ctl, child);
                }, e.childNodes);
        } catch(e){}
        return ctl;
}

JSKitLib.hasClass = function(element, className) {
	return element.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
}

JSKitLib.addClass = function(element, className) {
	if (!JSKitLib.hasClass(element, className)) {
		element.className += ' ' + className;
	}
}

JSKitLib.removeClass = function(element, className) {
	if (JSKitLib.hasClass(element, className)) {
		var regex = new RegExp('(\\s|^)' + className + '(\\s|$)');
		element.className = element.className.replace(regex, ' ');
	}
}



JSKitLib.removeChildren = function(element) {
	while(element && element.hasChildNodes())
		element.removeChild(element.firstChild);
}

JSKitLib.visible = function(element) {
	return element.style.display != 'none';
}

JSKitLib.show = function(element, style) {
	element.style.display = style || '';
}

JSKitLib.hide = function(element) {
	element.style.display = 'none';
}

JSKitLib.toggle = function(element, style) {
	(element.style.display == 'none') ? JSKitLib.show(element, style) :  JSKitLib.hide(element);
}

JSKitLib.getStyle = function(element) {
	if (typeof element.style.cssText != "undefined") {
		return element.style.cssText;
	} else {
		return element.getAttribute("style");
	}
}

JSKitLib.setStyle = function(element, style) {
	if (typeof element.style.cssText != "undefined") {
		element.style.cssText = style;
	} else {
		element.setAttribute("style", style);
	}
}

JSKitLib.addStyle = function(element, style) {
	var oldStyle = JSKitLib.getStyle(element);
	JSKitLib.setStyle(element, oldStyle + '; ' + style); // IE needs ;
}

JSKitLib.findPos = function(obj) {
	var origObj = obj;
	var curleft = curtop = curright = curbottom = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		}
	}
	curright = curleft + origObj.offsetWidth;
	curbottom = curtop + origObj.offsetHeight;
	return [curleft,curtop,curright,curbottom];
}

JSKitLib.getDocSize = function (){
	var doc_width,doc_height;
	if(typeof window.innerWidth=="number"){
		if(document.documentElement && document.defaultView && typeof document.defaultView.scrollMaxY=="number"){
			doc_height=document.documentElement.offsetHeight-document.defaultView.scrollMaxY;
			doc_width=document.documentElement.offsetWidth-document.defaultView.scrollMaxX;
		} else {
			doc_height=window.innerHeight;
			doc_width=window.innerWidth;
		}
	} else {
		if(document.documentElement && typeof document.documentElement.clientWidth=="number" && document.documentElement.clientWidth){
			doc_height=document.documentElement.clientHeight;
			doc_width=document.documentElement.clientWidth;
		} else {
			if(document.compatMode == "BackCompat"){
				doc_height=document.body.offsetHeight;
				doc_width=document.body.offsetWidth;
			} else {                                
				doc_height=document.body.clientHeight;
				doc_width=document.body.clientWidth;
			}
		}
	}
	return [doc_height,doc_width];
}

JSKitLib.getJSKitBodyElement = function() {
	var be = document.getElementById('js-kit-body-element');
	if (!be) {
		be = document.createElement('div');
		be.id = "js-kit-body-element";
		document.body.appendChild(be);
	}
	return be;
}

JSKitLib.isChildNodeOf = function(parent, child) {
	if (parent === child) 
		return false
	while (child && child !== parent) {
		child = child.parentNode;
	}
	return child === parent;
}

JSKitLib.addChild = function(to, what) {
        if (typeof(to) != 'object')
                return;
        if(arguments.length == 3 && arguments[2])
                to.insertBefore(what, to.firstChild);
        else
                to.appendChild(what);
}

JSKitLib.setOpacity = function(div, val) {
	if(document.body.filters) {
		if(val == 1) div.style.filter = '';
		else div.style.filter = 'alpha(opacity: ' + Math.round(val * 100) + ')';
	} else {
		div.style.opacity = val;
	}
}



JSKitLib.addPNG = function(node, imageURL) {
	if (JSKitLib.isIE()) {
		var cp = $JSKitGlobal.cachedPngs;
		JSKitLib.fmap(cp, function(img) {
			img.nodes = JSKitLib.filter(function(elm) { return elm != node; }, img.nodes);
		});
		if(cp[imageURL]) {
			if(cp[imageURL].loaded) {
				node.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageURL + "', sizingMethod='crop')"
			} else {
				cp[imageURL].nodes.push(node);
			}
		} else {
			cp[imageURL] = {nodes:[node]};
			var tPng = document.createElement("IMG");
			tPng.style.display = "none";
			tPng.onload = function() {
				cp[imageURL].loaded = true;
				var n = cp[imageURL].nodes;
				for(var i=0; i<n.length; i++) {
					n[i].runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageURL + "', sizingMethod='crop')";
				}
				cp[imageURL].nodes = [];
			};
			node.appendChild(tPng);
			tPng.src = imageURL;
		}
	} else {
		node.style.backgroundImage = 'url(' + imageURL + ')';
		node.style.backgroundRepeat = 'no-repeat';        
	}
	return node;
}

JSKitLib.preloadImg = function(imgURL) { 
	if (!JSKitLib.preloadImgList) JSKitLib.preloadImgList = {};
	if (!JSKitLib.preloadImgList[imgURL]) {
		(new Image()).src = imgURL; 
		JSKitLib.preloadImgList[imgURL] = true;
	}
};

JSKitLib.pngBar = function(color, div, fixed) {
	var str;
	var url = "'//js-kit.com/images/bars/bar-" + color + ".png'";
	if(document.body && document.body.filters) {
		str = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src="
			+ url + ", sizingMethod='"+(fixed?'crop':'scale')+"')";
		if(div) div.runtimeStyle.filter = str;
		return "filter: " + str + ";";
	} else {
		str = "url(" + url + ")";
		if(div) div.style.backgroundImage = str;
		return "background: " + str + ";";
	}
};

JSKitLib.createMiniStarObject = function(rating, scale, specs) {
	var fullStar = specs.full;
	var emptyStar = specs.empty;
	var starWidth = specs.width;
	var starHeight = specs.height;

	var setImage = function(star, imageURL) {
		if(star.imageURL == imageURL)
			return; // Already set and we know it

		star.imageURL = imageURL;
		JSKitLib.addPNG(star, imageURL);
	}

	var obj = document.createElement('div');
	var objWidth = 0;
	var objHeight = starHeight;

	/* Increment by Full Star Ratings */
	for (var i=2; i <= scale; i += 2) {
		var star = document.createElement('div');

		star.style.cssFloat   = 'left';
		star.style.styleFloat = 'left';
		star.style.width    = starWidth + 'px';
		star.style.height   = starHeight + 'px';
		star.style.fontSize = starHeight + 'px'; // ie6

		objWidth += starHeight;

		if (rating >= i) {
			setImage(star, fullStar);
		} else {
			setImage(star, emptyStar);
		}

		obj.appendChild(star);
	}

	JSKitLib.setStyle(obj, "height: " + objHeight + "px; width: " + objWidth + "px; float: left; margin-right: 5px;");

	return obj;
}



JSKitLib.getOuterHTML = function(node) {
	var clone = node.cloneNode(true);
	var parent = document.createElement('div');
	parent.appendChild(clone);
	var ihtml = parent.innerHTML;

    // ff converts sp characters inside of href to hex ascii
	var ihtmlHref = ihtml.match(/href\s*=\s*"[^"]*(%7B|%7D)[^"]*"/g) || [];
	for (var i=0; i< ihtmlHref.length; i++) {
		var a = ihtmlHref[i];
		var b = a.replace(/%7B/g, '{');
		b = b.replace(/%7D/g, '}');
		ihtml = ihtml.replace(a, b);
	}
	return ihtml;
};

JSKitLib.html = function() {
        var div = document.createElement("div");
        for(var text = '', i = 0; i < arguments.length; i++)
                text += arguments[i];
        div.innerHTML = text;
        var ch = div.firstChild;
        div = null;
        return ch;
}

JSKitLib.htmlQuote = function (newValue, param) {
	newValue = newValue.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")
	param = param || {};
	if(!param.title)
		newValue = newValue.replace(/ /,"&nbsp;");
	if(param.attribute)
		newValue = newValue.replace(/"/g,"&quot;");
	return newValue;
}

JSKitLib.htmlUnquote = function (newValue) {
	return newValue.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&");
}

JSKitLib.addJS = function(src,content) {
	var sId = "js-kit-script-"+src.replace(/[\/.]/g, '');
	content.jsk$scriptId = sId;
	if(document.getElementById(sId)) {
		return;
	}
	var s = document.createElement('script');
	s.id = sId;
	s.type ='text/javascript';
	s.charset = 'utf-8';
	s.src = src;
	content.appendChild(s);
	return s;
}

JSKitLib.stripTags = function(text) {
	var r = /<\/?(a|em|strong|i|b|u|sup|sub|object|param|embed|span|pre|p)(.|\n)*?>/gi;
	text = text.replace(/<object(.|\n)+?<\/object>/gi,"[video]");
	text = text.replace(r,"");
	return (text.length > 150) ? text.slice(0,150) + "..." : text;
}

JSKitLib.createHiddenIframe = function(id, target, cb, clearOnload, src) {
	clearOnload = (typeof clearOnload == 'undefined' ? true : !!clearOnload);
	src = src || 'about:blank';
	target = target || document.body;
	var d = document.createElement('div');
	d.style.height = 0;
	d.innerHTML = '<iframe id="' + id + '" name="' + id + '" src="' + src + '" width="0" height="0" frameborder="0"  style="border: none"></iframe>';
	target.appendChild(d);
	var ifr = d.firstChild;
	if (cb) {
		ifr.onreadystatechange = function(e) {
			if (ifr.readyState && ifr.readyState != 'loaded' && ifr.readyState != 'complete') return;
			if (clearOnload) {
				ifr.onreadystatechange = ifr.onload = null;
			}
			cb();
		};
		if (!JSKitLib.isOpera()) {
			ifr.onload = ifr.onreadystatechange;
		}
	}
	return ifr;
}



JSKitLib.map = function(f, arr) {
	if(arr) for(var i = 0; i < arr.length; i++) f(arr[i], i, arr);
	return arr;
}

JSKitLib.filter = function(f, arr) {
	var newArr = [];
	if(arr)
		for(var i = 0; i < arr.length; i++)
			if(f(arr[i], i, arr))
				newArr.push(arr[i]);
	return newArr;
}

JSKitLib.fmap = function(o,f) {
	var r, a = [], l = o.length;
	if(l > 0 || l === 0)
		for(var i = 0; i < l; i++) {
			r = f.call(this,o[i],i,arguments);
			if(r !== undefined) a.push(r);
		}
	else
		for(var i in o)
			if(o.hasOwnProperty(i)) {
				r = f.call(this,o[i],i,arguments);
				if(r !== undefined) a.push(r);
			}
	return a;
}

JSKitLib.foldl = function(acc,o,f) {
	var r, l = o.length;
	if(l > 0 || l === 0)
		for(var i = 0; i < l; i++) {
			r = f.call(this,o[i],acc,i);
			if(r != undefined) acc = r;
		}
	else
		for(var i in o)
			if(o.hasOwnProperty(i)) {
				r = f.call(this,o[i],acc,i);
				if(r != undefined) acc = r;
			}
	return acc;
}

JSKitLib.intersperse = function(f) {
	return JSKitLib.foldl([], this, function(e, acc, i) {
		if(acc.length) acc.push(f);
		acc.push(e);
	});
}



if (typeof JSKitLib.vars.windowOnLoadFired == 'undefined') {
        JSKitLib.vars.windowOnLoadFired = false;
        JSKitLib.addEventHandler(window, ['load'], function(){ JSKitLib.vars.windowOnLoadFired = true; });
}



var JSKitGlobal = function() {

	this._appAvailable = {};
	this._appObjects = {};  // Specific objects of an application type 
	this._appObjectActions = {}; // app.object.actions
	
	this.cachedPngs = {};

	this._isAppAvailable = function(app) {
		return (this._appAvailable[app]) ? true : false;
	}

	this.isRatingsAppAvailable = function() {
		return this._isAppAvailable('ratings');
	}

	this.isCommentsAppAvailable = function() {
		return this._isAppAvailable('comments');
	}

	this._setAppAvailable = function(app) {
		this._appAvailable[app] = true;
		/* index this app */
		this.indexAppObjects(app);
		/* execute any queued actions */
		this.executeAppObjectActions(app);
	}

	this.setRatingsAppAvailable = function() {
		this._setAppAvailable('ratings');
	}

	this.setCommentsAppAvailable = function() {
		this._setAppAvailable('comments');
	}

	this.indexAppObjects = function(app) {
		if (app == 'ratings') {
			var appArray = $JRA;
		} else if (app == 'comments') {
			var appArray = $JCA;
		} else {
			alert('Attempt to index invalid app type');
			return;
		}
		for (var i=0; i < appArray.length; i++) {
			// Check that it's not standalone
			if (appArray[i].isStandalone()) {
				continue;
			}
			var uniq = appArray[i].uniq;
			if ( ! this._appObjects[uniq] ) {
				this._appObjects[uniq] = {};
			}
			if ( ! this._appObjects[uniq][app]) {
				this._appObjects[uniq][app] = [];
			}
			this._appObjects[uniq][app].push(appArray[i]);
		}
	}

	this.executeAppObjectActions = function(app) {
		if (this._appObjectActions[app]) {
			for (var i=0; i < this._appObjectActions[app].length; i++) {
				var uniq = this._appObjectActions[app][i].uniq;
				if (this._getAppObject(app, uniq)) {
					this._appObjectActions[app][i].action();
				}
			}
		}
	}

	this._getAppObject = function(app, uniq) {
		if (this._appObjects[uniq] && this._appObjects[uniq][app]) {
			return this._appObjects[uniq][app][0];  // Return only the first
		}
		return null;
	}

	this.getCommentsAppObject = function(uniq) {
		return this._getAppObject('comments', uniq);
	}

	/* Returns a Ratings Object */
	this.getRatingsAppObject = function(uniq) {
		return this._getAppObject('ratings', uniq);
	}

	this.copyRatingsAppObject = function(uniq, node) {
		if ( ! this.isRatingsAppAvailable()) {
			return;
		}
		var oldObj = this.getRatingsAppObject(uniq);
		var newObj = oldObj.clone(node, { 'view':'user', 'commentprompt':'no', 'menu':'no'  } );
		return newObj;
	}

	this._tryAppObjectAction = function(app, uniq, action) {
		if (this._isAppAvailable(app)) {
			if (this._getAppObject(app, uniq)) {
				action();
			}
		} else {
			if ( ! this._appObjectActions[app]) {
				this._appObjectActions[app] = [];
			}
			this._appObjectActions[app].push( { 'uniq' : uniq, 'action' : action } );
		}
	}

	this.tryRatingsAppObjectAction = function(uniq, action) {
		this._tryAppObjectAction('ratings', uniq, action);
	}

	this.tryCommentsAppObjectAction = function(uniq, action) {
		this._tryAppObjectAction('comments', uniq, action);
	}
}

/* Singleton-like handler */
JSKitGlobal.getInstance = function() {
	if ( ! window.JSKitGlobalInstance) {
		JSKitGlobalInstance = new JSKitGlobal();
	}
	return JSKitGlobalInstance;
}



/* JSKitGlobal  object */
$JSKitGlobal = JSKitGlobal.getInstance();



JSKitLib.getRef = function(self, ignorePath) {
	var wl = window.location;
	return wl.protocol + '//'
		+ (self.pathOverride
			? (self.config.domain.replace(/\/.*/, '')
				+ (ignorePath ? '' : self.pathOverride))
			: (self.config.domain + wl.pathname));
}

JSKitLib.readConfig = function(wtype, target, cf) {
	var gtags = JSKitLib.parseConfigTags(document, wtype, 'span');
	var ltags = JSKitLib.parseConfigTags(target, '', 'span');
	for(var i = 3; i < arguments.length; i++) {
		var arg = arguments[i];
		if(typeof(arg) == 'string') arg = [arg];
		var name = arg[0];
		var value = target.getAttribute(name) || ltags[name] || gtags[name];
		var wl = window.location;
		switch (name) {
			case 'path': value = JSKitLib._normPath(target, value || cf[name]); break;
			case 'permalink':
				value = value || cf[name] || wl.href.replace(wl.hash,'');
				if (!value.match(/^https?:\/\//))
					value = "http://" + wl.host + value.replace(/^([^\/]+)/, "/$1");
				break;
			case 'title': value = value || cf[name] || document.title; break;
			case 'domain': value = value || cf[name] || wl.host; break;
			default: value = value || cf[name];
		}
		if(arg.length > 1) {
			if(typeof(arg[1]) == 'number') {
				if(value) {
					var n = parseInt(value);
					if(isNaN(n) || n < 0) {
						if(value == "no") value = 0;
						else value = arg[1];
					} else value = n;
				} else value = arg[1];
			} else if(typeof(arg[1]) == 'object') {
				for(var j=arg[1].length; j; j--)
					if(arg[1][j-1] == value) break;
				if(!j) value = arg[1][j];
			} else {
				if(!value) value = arg[1];
			}
		}
		cf[name] = value;
	}
	return cf;
}

JSKitLib.parseConfigTags = function(target, wtype, tag) {
	var cache = document._widgets_config;
	if (wtype && cache && cache[wtype])
		return cache[wtype];
	var regp = wtype ? wtype+'?-' : '';
	var nodes = target.getElementsByTagName(tag);
	var config = {};
	for (var i = 0; i < nodes.length; i++) {
		var reg = RegExp("^js-kit-config-"+regp+"(.*)$");
		var m = reg.exec(nodes[i].className);
		if (m && m.length) {
			config[m[1].toLowerCase()] = nodes[i].innerHTML;
			nodes[i].style.display = 'none';
		}
	}
	if (wtype) {
		document._widgets_config = document._widgets_config || {};
		document._widgets_config[wtype] = config;
	}
	return config;
}

JSKitLib._normPath = function(target, path) {
	var wl = window.location;
	var uniq = String(target.getAttribute("uniq") || target.getAttribute("unique") || '');
	/* trim uniq */
	var uniq = uniq.replace(/^\s\s*/, ''), ws = /\s/, i = uniq.length;
	while (ws.test(uniq.charAt(--i)));
	uniq = uniq.slice(0, i + 1);
	/* end of trim */
	var plus = true;
	if (uniq) {
		plus = uniq.match(/^\+\/*(.*)/);
		if (plus) path = plus[1];
		else path = uniq;
	}
	if(path) {
		path = String(path);
		var ar = path.match(/^https?:\/\/[^\/]+(.*)/);
		if(ar) path = ar[1];
		else path = path.replace(/^([^\/]+)/, (plus ? wl.pathname : "") + "/$1");
		path = path.replace(/^\/+/, "/");
	} else { path=wl.pathname; }
	return path;
}



JHI2 = {};
JHI2.create = function(hint, element) {
	if (!element) {
		element = document.createElement("input");
		element.type = "text";
	}
	element.origColor = element.style.color || 'black';
	element.hint = hint;
	element.defaultRemoved = !!element.value;
	if (!element.value) {
		element.style.color = 'gray';
		element.value = element.hint;
	}
	element.onblur = function() {
		if (!this.defaultRemoved || this.value == '') {
			this.defaultRemoved = false;
			this.style.color = 'gray';
			this.value = this.hint;
		}
	}
	element.onfocus = function() {
		if (!this.defaultRemoved) {
			this.defaultRemoved = true;
			this.style.color = this.origColor;
			this.value = '';
		}
	}
	return element;
}

JHI2.remove = function(element) {
	if (!element || !element.hint) return;
	element.onfocus();
	JSKitLib.fmap(['origColor', 'hint', 'defaultRemoved', 'onblur', 'onfocus'], function(v){ JSKitLib.deleteProperty(element, v); });
}



JSKitFB.prototype.displayState = function(el) {
	var s = this;
	var d = function(id) { return document.getElementById(id+'-'+s.tgt); };
	JSKitLib.fmap(['wait','login','process'],
		function(v) {
			d(v).style.display = (el==v) ? 'block' : 'none';
		}
	);
}

JSKitFB.prototype.processProfile = function() {
	var s = this;
	s.displayState('process');
	var api = FB.Facebook.apiClient;
	var uids = [api.get_session().uid];
	var fields = ['name', 'profile_url', 'pic_big', 'pic_square', 'pic_square_with_logo'];
	api.users_getInfo(uids, fields, function(data) {
		if(!data) {
			s.processLoginStatus();
		} else {
			FB.Connect.addSignedPublicSessionDataToUrl("http://js-kit.com/api/facebook/process_profile",function(url){
				JSKitLib.addJS(url+'&profile_data='+encodeURIComponent(JSKitLib.Object2JSON(data))+'&ref='+s.ref+'&rnd='+Math.random(),document.getElementById(s.tgt));
				if(s.onready) s.onready();
			});
		};
	});
}

JSKitFB.prototype.processLogin = function() {
	FB.ensureInit(function(){
		FB.Connect.requireSession();
	});
}

JSKitFB.prototype.processLoginStatus = function() {
	var s = this;
	s.displayState('login');
	FB.ensureInit(function(){
		FB.XFBML.Host.parseDomTree();
		FB.Facebook.get_sessionState().waitUntilReady(function(state) {
			if(state) {
				s.processProfile();
			} else {
				s.displayState('login');
			}
		});
	});
}

JSKitFB.prototype.init = function(cb) {
	var s = this;
	var target = document.getElementById(s.tgt);
	if(!s.api_key || !target) return;
	window.jsk$fb_init = true;
	var initFB = function() {
		FB.init(s.api_key,s.xd_receiver || window.jsk$xd_receiver,{fetchSignedPublicSessionData : true});
		if(cb) cb();
	};
	var fbLoaded = function(el) {
		if(el && el.readyState && el.readyState != 'loaded'
			&& el.readyState != 'complete') return;
		if(el) el.onreadystatechange = el.onload = null;
		initFB();
	};
	if(!document.getElementById('FB_HiddenContainer')) {
		var hc = document.createElement('div');
		hc.id = 'FB_HiddenContainer';
		hc.style.position = 'absolute';
		hc.style.top = '-10000px';
		hc.style.left = '-10000px';
		hc.style.width = '0px';
		hc.style.height = '0px';
		target.appendChild(hc);
	}
	if(!window.FB) {
		var sc = JSKitLib.addJS('http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php', target);
		sc.onload = sc.onreadystatechange = function() {fbLoaded(sc);};
	} else {
		initFB();
	}
};

JSKitFB.prototype.shareComment = function() {
	var sd = this.sharedata;
	FB.ensureInit(function(){
		FB.Connect.showFeedDialog(sd.template, sd.comment_data, null,
				null, null, FB.RequireConnect.promptConnect);
	});
}

function JSKitFB(ref, tgt, api_key, xd_receiver, cb, sharedata) {
	this.ref = ref;
	this.tgt = tgt;
	this.api_key = api_key;
	this.xd_receiver = xd_receiver;
	this.onready = cb;
	this.sharedata = sharedata;
	var s = this;
	var f = function(logged) {
			if(logged) {
				FB.ensureInit(function(){
				if(FB.Connect._singleton._userInfo)
					FB.Connect._singleton._userInfo.shortStorySetting = 1;
				FB.Connect._singleton._feedStatusMustBeRefetched = !sharedata;
				});
			} else {
				FB.ensureInit(function(){
				FB.Connect._singleton._feedStatusMustBeRefetched = true;
				});
			};
			return sharedata ? s.shareComment() : s.processLoginStatus();
		};
	if(window.jsk$fb_init) {
		f(true);
	} else {
		this.init(f);
	}
}

JSKitFB.prototype.logout = function() {
	if(window.jsk$fb_init) {
		FB.ensureInit(function(){
			FB.Connect.logout();
		});
	}
}

JSKitFB.prototype.detectXD = function(target) {
	if(window.location.search.indexOf('fbc_channel=1')>=0) {
		JSKitLib.addJS('http://static.ak.facebook.com/js/api_lib/v0.4/XdCommReceiver.js', target);
	}
}



JSKitGFC.prototype.init = function(cb) {
	var s = this;
	if(!s.site || !s.target) return;
	window.jsk$gfc_init = true;
	var initGFC = function() {
		google.friendconnect.container.setParentUrl('/');
		google.friendconnect.container.loadOpenSocialApi({
			site: s.site,
			onload: function(securityToken) {
				if(cb) cb(securityToken);
			}
		});
	};
	var gfcLoaded = function(el) {
		if(el && el.readyState && el.readyState != 'loaded'
			&& el.readyState != 'complete') return;
		if(el) el.onreadystatechange = el.onload = null;
		initGFC();
	};
	if(!window.google || !window.opensocial) {
		var sc = JSKitLib.addJS('http://www.google.com/friendconnect/script/friendconnect.js?key=notsupplied&v=0.8', s.target);
		sc.onload = sc.onreadystatechange = function() {gfcLoaded(sc);};
	} else {
		initGFC();
	}
}

JSKitGFC.prototype.processProfile = function(profileData) {
	JSKitLib.addJS('//js-kit.com/api/google/process_profile?'
		+'id='+encodeURIComponent(profileData.getId())
		+'&st='+encodeURIComponent(this.securityToken)
		+'&rnd='+Math.random(),this.target);
	if(this.onready) this.onready();
}

JSKitGFC.prototype.displayState = function(el) {
	var s = this;
	var d = function(id) { return document.getElementById(id+'-'+s.tgt); };
	JSKitLib.fmap(['wait','login','process'],
		function(v) {
			d(v).style.display = (el==v) ? 'block' : 'none';
		}
	);
}

JSKitGFC.prototype.getViewerData = function(success_cb, fail_cb) {
	var onData = function(data) {
		var vd = data.get("viewer_data");
		if (!vd.hadError() && vd.getData()) {
			if(success_cb) success_cb(vd.getData());
		} else {
			if(fail_cb) fail_cb(vd);
		}
	};
	var req = opensocial.newDataRequest();
	req.add(req.newFetchPersonRequest("VIEWER"), "viewer_data");
	req.send(onData);
}

JSKitGFC.prototype.processLoginStatus = function() {
	var s = this;
	s.getViewerData(function(profileData){
		var processEl = document.getElementById('process-' + s.tgt);
		if(processEl) processEl.innerHTML = 'Logging in ' + profileData.getDisplayName() + '...';
		s.displayState('process');
		s.processProfile(profileData);
	}, function() {
		s.displayState('login');
		google.friendconnect.renderSignInButton({ 'id': 'login-' + s.tgt, 'text' : 'Log in with Google Friend Connect', 'style': 'long' });
	});
}

JSKitGFC.prototype.shareComment = function() {
	var s = this;
	s.getViewerData(function(data){
		var sd = s.sharedata;
		var UserName = data.getDisplayName();
		var params = {};
		params[opensocial.Activity.Field.TITLE] = UserName + ' just posted the following comment on <a href="' + sd.permalink + '">' + sd.domain + '</a>';
		params[opensocial.Activity.Field.BODY] = ((sd.Text.length > 128) ? sd.Text.substr(0, 128) + '...' : sd.Text) + '<br><br>Powered ';
		var activity = opensocial.newActivity(params);
		opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH);
	},function(){
		google.friendconnect.requestSignIn();
	});
}

JSKitGFC.prototype.processLogout = function() {
	google.friendconnect.requestSignOut();
}

function JSKitGFC(ref, tgt, site, cb) {
	this.ref = ref;
	this.tgt = tgt;
	this.site = site;
	var s = this;
	s.target = document.getElementById(s.tgt);
	var f = function(securityToken) {
		s.securityToken = securityToken;
		cb.apply(s);
	}
	if(window.jsk$gfc_init) {
		f();
	} else {
		this.init(f);
	}
}



if(!window.JSKitAuthInstance) var JSKitAuthInstance = null;

$JALT = {
	//Authentication methods labels:
	registerJSKAMethod: 'New JS-Kit account',
	loginJSKAMethod: 'JS-Kit account',
	haloscanJSKAMethod: 'Haloscan account',
	openidJSKAMethod: 'OpenID',
	blogspotJSKAMethod: 'Blogspot URL',
	facebookJSKAMethod: 'Facebook account',
	yahooJSKAMethod: 'Yahoo account',
	gfcJSKAMethod: 'Google Friend Connect',
	twitterJSKAMethod: 'Twitter account',
	//Error messages:
	error : 'Error',
	no_email : 'Email not found for this account',
	long_login : 'Login is too long (should be not more 63 characters)',
	empty_login : 'Enter your login',
	empty_email : 'Enter your e-mail',
	short_login : 'Login is too short (should be at least 6 characters)',
	empty_openid : 'Enter your OpenID URL',
	empty_blogspot : 'Enter your Blogspot URL',
	empty_password : 'Enter your password',
	empty_password2 : 'Enter your password',
	incorrect_login : 'Login must begin with a letter and contain 6 or more characters, including numbers, a dash and a dot.',
	incorrect_email : 'Your email is incorrect, please check it',
	full_description : 'JS-Kit login need to start with a letter and may also contain numbers, a dash and a dot. Login and password must have a minimum of 6 characters. Example of a good login name: Joe.Bloggs',
	nonexisting_login : 'Login does not exist ',
	password_is_short : 'Password is too short (should be at least 6 characters)',
	user_already_logged : 'You are already signed in with this login',
	incorrect_recovery_key: 'Incorrect recovery key',
	login_is_already_used : 'Login name is already taken by someone else',
	incorrect_blogspot_url : 'Your Blogspot URL doesn\'t seem to be valid',
	incorrect_login_or_password : 'Login or password is incorrect',
	user_already_has_other_login : 'You are logged in already',
	password2_mismatch: 'Passwords do not match',
	//Common labels
	authentication: 'Authentication',
	jskaInfoNewAcc: 'New JS-Kit account:',
	jskaInfoNewAccNote: 'JS-Kit authentication can also be used as an OpenID across the web: (http://yourname.js-kit.com)',
	jskaInfoLoginNote: 'If you already have a JS-Kit account, use it to login',
	jskaInfoOIDFB: 'OpenID, Facebook and Yahoo (when enabled)',
	jskaInfoOIDFBNote: 'You can use your existing OpenID URL, your FaceBook or Yahoo authentication to login here',
	jskaInfoPrivacy: 'Privacy:',
	jskaInfoPrivacyNote: 'Your email address and authentication information will not be shared. <a href="//js-kit.com/about/policy.html" target="_blank">More</a>',
	passwordRecovery: 'JS-Kit Password Recovery',
	enterYourLoginNote: 'Enter your login you registered with below and click "Send Password". Then check your email (Inbox or SPAM folder).',
	forgotYourPassword: 'forgot your password?',
	sendPassword: 'Send Password',
	authCode: 'Auth Code',
	jskaLogout: 'Logout',
	existingJSKitProfile: 'Existing JS-Kit profile',
	submit: 'Submit',
	back: 'Back',
	login: 'Login',
	username: 'Username',
	loginWith: 'Login with:',
	loginBtn: 'Login',
	register: 'Register',
	password: 'Password:',
	retypePassword: 'Re-type Password:',
	loginWith : 'Login with:',
	cancel : 'Cancel',
	loading : 'Loading ...',
	jskaLogout : 'Logout',
	openID : 'OpenID:',
	allFieldsAreMandatory : 'All fields are mandatory',
	yourEmail : 'Your Email',
	blogspotUrl : 'Blogspot URL:'
}
$JAL = window.JSKA_Translate || function(t) { return $JALT[t] || t; }

JSKAuth.prototype.setAuthInstance = function() {
	if (window.JSKitAuthInstance) {
		var authForm = JSKitAuthInstance.authForm;
		if(authForm && authForm.parentNode)
			JSKitLib.hide(authForm);
	}
	JSKitAuthInstance = this;
}

JSKAuth.prototype.show = function(areaName, data) {
	this.setAuthInstance();
	this.showBackdrop();
	var authForm = this.authForm;
	JSKitLib.show(authForm);
	if(this.calcPosition) {
		var position = this.calcPosition();
		authForm.style.top = parseInt(position.y) + "px";
		authForm.style.left = parseInt(position.x) + "px";
	}
	this.authSelector.value = areaName;
	this.setActiveArea(areaName, data);
}

JSKAuth.prototype.loadCss = function() {
        JSKitLib.addCss(
		".jska-backdrop { opacity: 0; background-color: #404040; z-Index: 14500; width: 100%; " + (JSKitLib.isIE() ? "filter:progid:DXImageTransform.Microsoft.Alpha(opacity='0'); position: absolute; top: expression(eval(document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 'px'); right: 0; bottom: 0; height: expression(eval(document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight)); width: expression(eval(document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth));" : "position: fixed; left: 0; top: 0; height: 100%; -webkit-transition: opacity 0.5s ease-out;" ) + "}" +
		".jska-wrapper { " + (this.mode != "embedded" ? "position: absolute;" : "") + "background-color: white; z-index: 20000; border: solid 4px #cbcbcb; text-align: left; width: 350px; }" +
		".jska-facebookFrame { height: 27px; width: 194px; background-color: transparent; border: none; z-Index: 14000; }" +
		".jska-selector { margin-left: 5px;}" +
		".jska-header { background-color: #ececec; padding: 8px 0 6px 10px; }" +
		".jska-headerText { font-family: Verdana, Helvetica; font-weight: bold; font-size: 12pt; color: grey; float: left; }" +
		".jska-infoText { margin: 0; padding: 0;}" +
		".jska-infoContainer { margin: 0 10px;}" +
		".jska-showMore { color: #403030; font-family: Arial, Helvetica, sans-serif; }" +
		".jska-infoBtn { width: 16px; height: 16px; cursor: pointer; margin-left: 10px; float: left}" +
		".jska-selectorContainer { background-color: #ececec; padding: 0 0 4px 10px;}" +
		".jska-container { border-top: solid 1px #cbcbcb; padding-top: 20px;}" +
		".jska-controls { background-color: #ececec; width: 100%; padding: 5px 0 5px 0; margin-top: 20px;}" +
		".jska-rightColumn { float: right; width: 65%;}" +
		".jska-leftColumn { float: right; width: 33%; padding: 2px 5px 0 0; text-align: right;}" +
		".jska-label { font-size: 9pt; font-family: Arial;}" +
		".jska-input { border: solid 1px #7f99b9; width: 80%;}" +
		".jska-openidInput { background: url(//js-kit.com/images/openid-16x16.png) no-repeat; background-position: 0 50%; padding-left: 18px;}" +
		".jska-blogspotInput { background: url(//js-kit.com/images/blogger-16x16.png) no-repeat; background-position: 0 50%; padding-left: 18px;}" +
		".jska-error { color: #FF3030; font: 11px Arial; margin-bottom: 2px; }" +
		".jska-cancelBtn { float: right; margin-right: 5px; cursor: pointer;}" +
		".jska-text { color: #404040; font: 11px Arial; }" +
		".jska-back { font: 15px Helvetica; cursor: pointer; margin-left: 10px; float: left;}" +
		".jska-logout { float: left; margin-left: 10px; cursor: pointer;}" +
		".jska-passwordRecoveryText { margin: 0px 0px 5px 10px; }" +
		".jska-forgotPassword{ color: #001faa; cursor: pointer; }" +
		"a.jska-forgotPassword:hover {color: #001faa;}" +
		"a.jska-forgotPassword:visited {color: #001faa;}" +
		".jska-linkToLogin{ color: #001faa; cursor: pointer; }" +
		".jska-progressArea { display: none; }" +
		".jska-progressPic { display: inline; float: left; margin-right: 0.2em; margin-left: 1em; margin-top: 0.3em; width: 16px; height: 16px; background: no-repeat url(//js-kit.com/images/polls/loading.gif); }" +
		".jska-progressLbl { display: inline; margin-left: 0.3em; margin-top: 0.5em; float: left; }" +
		".jska-authButton {float: right; margin-right: 7px; cursor: pointer;}" +
		".jska-clear { clear: both;}", "jska");
}

JSKAuth.prototype.cancelRequests = function(){
	var self = this;
	JSKitLib.fmap(["facebook", "yahoo", "gfc", "twitter"], function(provider){
		if(self.areas && self.areas[provider] && self.areas[provider].rpickup) {
			try{ self.areas[provider].rpickup.cancelRequest(); } 
			catch(e){};
		}
	 });
}

JSKAuth.prototype.hide = function() {
	this.hideBackdrop();
	this.cancelRequests();
	JSKitLib.hide(this.authForm);
}

JSKAuth.prototype.destroy = function() {
	this.hide();
	var prn = this.authForm.parendNode;
	if (prn) prn.removeChild(this.authForm);
}

JSKAuth.prototype.prepareAuthForm = function() {
	var self = this;
	var div = self.authForm;
	JSKitLib.hide(div);
	if (self.mode == "popup"){
	        var jsd = new JSDL(div, div.dragElements);
		var calcPosition = function(){
			var coords = jsd.getElmAbsPos(self.target, false);
			return { "x" : coords.x, "y" : coords.y + self.target.offsetHeight};
		}		

		self.calcPosition = self.startPosition || calcPosition;
		document.body.insertBefore(div, document.body.firstChild);
	} else {
		self.target.appendChild(div);
	}
}

JSKAuth.prototype.showBackdrop = function() {
	if (this.withBackdrop && this.mode == "popup") {
		if(!window.backdrop) {
			window.backdrop = document.createElement('DIV');
			backdrop.className = 'jska-backdrop';
			document.body.insertBefore(backdrop, document.body.firstChild);
		}
		JSKitLib.show(backdrop);
		JSKitLib.setOpacity(backdrop, 0.5);
	}
}

JSKAuth.prototype.hideBackdrop = function() {
	if (this.withBackdrop && window.backdrop){
		JSKitLib.setOpacity(backdrop, 0);
		JSKitLib.hide(backdrop);
	}
}

JSKAuth.prototype.checkAuthOptions = function(options) {
	var defaultOptions = this.defaultAuthOptions.join("|");
	for (var i=0; i<options.length; i++){
		if (!options[i].match(defaultOptions)) return false;
	}
	return true;
}

JSKAuth.prototype.assemble = function() {
	var self = this;
	var defaultOptions = ["register", "login", "haloscan", "openid"];
	var authForm = self.toDom(self.authFormTmpl);
	var authFormElements = JSKitLib.mapClass2Object({}, authForm);
	authForm.dragElements = [authFormElements["jska-header"]];

	self.areaContainer = authFormElements["jska-container"];
	self.selectorContainer = authFormElements["jska-selectorContainer"];

	JSKitLib.addPNG(authFormElements["jska-infoBtn"], "//js-kit.com/images/information.png");
	authFormElements["jska-infoBtn"].onclick = function(){
		self.toggleInfoArea();
		return false;
	}

	options = (self.authOptions ? self.authOptions : defaultOptions);
	self.authSelector = self.createAuthSelector(options, self.activeAreaByDefault, function(ev){ self.setActiveArea(this.value); });
	authFormElements["jska-selectorContainer"].appendChild(self.authSelector);

	self.setActiveArea(self.activeAreaByDefault);
	return authForm;
}

JSKAuth.prototype.toggleInfoArea = function(mode){
	this.setActiveArea(((mode == "hide" || this.isInfoAreaActive) ? this.currentArea : "info"));
}

JSKAuth.prototype.setActiveArea = function(name, data){
	var self = this;
	self.cancelRequests();
	if (name == "info") {
		self.isInfoAreaActive = true; 
	} else { 
		self.isInfoAreaActive = false;
		self.currentArea = name;
	}
	if (name.match(/info|passwordRecovery/)) JSKitLib.hide(self.selectorContainer); else JSKitLib.show(self.selectorContainer);
	JSKitLib.removeChildren(self.areaContainer);
	if (!self.areas[name]) self.areas[name] = self.createArea(name, data);
	else {
		JSKitLib.fmap(data || [], function(value, key){
		self.HNDL[name]["input"][key].value = value;
		});
	}

	self.areaContainer.appendChild(self.areas[name]);

	var createThirdPartyLoginCB = function(provider) {
		return function(error, data){
				if (error != "data") return;
				if (window.JSKW$Events) JSKW$Events.syncBroadcast('JSKitAuth_success_' + provider + '_login', error, data);
				self.hide();
			}
	}

	var createRVCRequest = function(provider, target) {
		return new JSRVC({
				uri: self.uriDomain + '/api/server-answer.js', 
				'target': target, 
				'onreturn': createThirdPartyLoginCB(provider), 
				'pickup': true, 
				'requestId': provider + '_connect'});	
	}

	if (name == "yahoo"){ self.areas["yahoo"].rpickup = createRVCRequest("yahoo", self.target); }
	if (name == "gfc"){
		var gfc_cb = function() {
			self.areas["gfc"].rpickup = createRVCRequest("gfc", self.target);
		};
		if(self.gfc_site) {
			var jsk$gfc = new JSKitGFC(
				self.ref,
				self.areas["gfc"].id,
				self.gfc_site,
				function(){
					this.onready = gfc_cb();
					this.processLoginStatus();
				});
		} else {
			gfc_cb();
		}
	}
	if (name == "twitter"){ self.areas["twitter"].rpickup = createRVCRequest("twitter", self.target); }
	if (name == "facebook") {
		var fb_cb = function() {
			self.areas["facebook"].rpickup = createRVCRequest("facebook", self.rvcTarget);
		};
		if(self.facebook_api_key) {
			var logel = document.getElementById('login-' + self.areas["facebook"].id);
			var jsk$fb = new JSKitFB(self.ref, self.areas["facebook"].id, self.facebook_api_key, self.facebook_xd_receiver, fb_cb);
			logel.onclick = jsk$fb.processLogin;
		} else {
			fb_cb();
		}

	}
}

JSKAuth.prototype.getErrorTarget = function(errCode) {
	if (errCode.match(/no_email/)) return "login";
	if (errCode.match(/email/)) return "email";
	if (errCode.match(/password2/)) return "password2";
	if (errCode.match(/password/)) return "password";
	return "login";
}

JSKAuth.prototype.processControls = function(name, type, func){
	JSKitLib.fmap(this.HNDL[name][type], func);	
}

JSKAuth.prototype.addKeyHandler = function(name) {
	var self = this;
	var button = self.HNDL[name]["button"].button;
	this.processControls(name, "input", function(element){ if (element) {
		if(JSKitLib.isIE() || JSKitLib.isOpera()) element.onkeydown = function(ev) { return self.keyHandler(ev, button);}
		else element.onkeypress = function(ev) { return self.keyHandler(ev, button);}
	}});	
}

JSKAuth.prototype.hideMessages = function(name) {
	this.processControls(name, "message", function(element){ if (element) JSKitLib.hide(element); });
}

JSKAuth.prototype.disableControls = function(name, value) {
	JSKitLib.fmap.call(this, ["input", "button"], function(type){ this.processControls(name, type, function(element){ if (element) element.disabled = value; })});
}

JSKAuth.prototype.clearInputFields = function(name) {
	this.processControls(name, "input", function(element){ if (element) { element.value = ""; if (typeof(element.onblur) == "function") element.onblur(); } });
}

JSKAuth.prototype.toDom = function(area) {
	return JSKitLib.html(area.replace(/{Label:([^:}]+[^}]*)}/g, function(a,m){ return $JAL(m); }));
}

JSKAuth.prototype.autoComplete = (JSKitLib.getBrowser() == 'gecko' ? ' autocomplete="Off"' : '');

JSKAuth.prototype.keyHandler = function(e, button){
	e = e || window.event;
	switch(e.keyCode) {
		case 10: case 13:
			JSKitLib.preventDefaultEvent(e);
			button.click();
		break;
	}
}

JSKAuth.prototype.authFormTmpl =
'<div class="jska-wrapper">' +
	'<div class="jska-header">' +
		'<div class="jska-headerText">{Label:authentication}</div>' +
		'<div class="jska-infoBtn" title="{Label:info}"></div>' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-selectorContainer jska-label">{Label:loginWith}</div>' +
	'<div class="jska-container"></div>' +
'</div>';

JSKAuth.prototype.infoSectionTmpl =
'<div>' +
	'<div class="jska-text jska-infoContainer">' +
		'<p class="jska-infoText jska-error">{Label:jskaInfoNewAcc}</p>' + 
		'{Label:jskaInfoNewAccNote}' +
		'<p class="jska-infoText jska-error">{Label:existingJSKitProfile}</p>' +
		'{Label:jskaInfoLoginNote}' +
		'<p class="jska-infoText jska-error">{Label:jskaInfoOIDFB}</p>' +
		'{Label:jskaInfoOIDFBNote}' +
		'<p class="jska-infoText jska-error">{Label:jskaInfoPrivacy}</p>' +
		'{Label:jskaInfoPrivacyNote}' +
	'</div>' +
	'<div class="jska-controls">' +
		'<span class="jska-back">{Label:back}</span>' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.progressAreaTmpl =
'<div class="jska-progressArea js-progressHandle">' +
	'<div class="jska-progressPic"></div>' +
	'<div class="jska-progressLbl jska-label">{Label:loading}</div>' +
	'<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.loginSectionTmpl =
'<div>' + JSKAuth.prototype.progressAreaTmpl +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="loginInput"' + JSKAuth.prototype.autoComplete +'>' +
		'<div class="jska-error js-loginMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:username}:</div>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="passwordInput" type="password">' +
		'<div class="jska-error js-passwordMessageHandle"></div>' +
		'<div><a class="jska-forgotPassword jska-text">{Label:forgotYourPassword}</a></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:password}</div>' +
	'<div class="jska-clear"></div>' +
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:loginBtn}" name="authButton" class="jska-authButton" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.haloscanSectionTmpl =
'<div>' + JSKAuth.prototype.progressAreaTmpl +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="loginInput"' + JSKAuth.prototype.autoComplete +'>' +
		'<div class="jska-error js-loginMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:username}:</div>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="passwordInput" type="password">' +
		'<div class="jska-error js-passwordMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:password}</div>' +
	'<div class="jska-clear"></div>' +
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:loginBtn}" name="authButton" class="jska-authButton" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.openidSectionTmpl =
'<div>' + JSKAuth.prototype.progressAreaTmpl +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input jska-openidInput" name="loginInput"' + JSKAuth.prototype.autoComplete + '>' +
		'<div class="jska-error js-loginMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:openID}</div>' +
	'<div class="jska-clear"></div>' +
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:loginBtn}" name="authButton" class="jska-authButton" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.blogspotSectionTmpl =
'<div>' + JSKAuth.prototype.progressAreaTmpl +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input jska-blogspotInput" name="loginInput"' + JSKAuth.prototype.autoComplete + '>' +
		'<div class="jska-error js-loginMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:blogspotUrl}</div>' +
	'<div class="jska-clear"></div>' +
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:loginBtn}" name="authButton" class="jska-authButton" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.yahooSectionTmpl =
'<div style="text-align: center">' +
'<div class="jska-progressArea js-progressHandle"></div>' +
'<div onclick="window.open(\'//js-kit.com/api/oauth/yahoo.html\',\'_blank\',\'status=no, menubar=no, resizable=no, scrollbars=yes, toolbar=no, location=yes, directories=no\')" style="margin-left: auto; margin-right: auto; width:161px; height:22px; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'//js-kit.com/images/yahoo/yos.png\', sizingMethod=\'crop\');' : 'background: no-repeat url(//js-kit.com/images/yahoo/yos.png);') + ' cursor:pointer;"></div>' +
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
'</div>';

JSKAuth.prototype.twitterSectionTmpl =
'<div style="text-align: center">' +
'<div class="jska-progressArea js-progressHandle"></div>' +
'<div onclick="window.open(\'//js-kit.com/api/oauth/twitter.html\',\'_blank\',\'status=no, menubar=no, resizable=no, scrollbars=yes, toolbar=no, location=yes, directories=no\')" style="margin-left: auto; margin-right: auto; width:176px; height:28px; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'//js-kit.com/images/twitter/twitter.png\', sizingMethod=\'crop\');' : 'background: no-repeat url(//js-kit.com/images/twitter/twitter.png);') + ' cursor:pointer;"></div>' +
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
'</div>';

JSKAuth.prototype.facebookSectionTmpl = function() {
	var tgt = "fb-" + Math.random();
	return ('<div id="' + tgt + '" style="text-align: center;">' +
'<div class="jska-progressArea js-progressHandle"></div>' +
	(!this.facebook_api_key ?
	'<div style="width: 200px; height: 27px; margin: auto; "><iframe src="http://js-kit.com/api/facebook/connect-button" height="30px" width="210px" allowtransparency="true" style="background-color: transparent; border: none; z-Index: 14000;" frameborder="0"></iframe></div>' :
	'<div name=' + tgt + '" style="width: 200px; height: 27px; margin: auto; "><div id="wait-' + tgt + '">Asking Facebook...</div><div id="login-' + tgt + '" style="display: none; width: 200px; height: 27px; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'//js-kit.com/images/facebook/connect_white_large_long.gif\', sizingMethod=\'crop\');' : 'background: no-repeat url(//js-kit.com/images/facebook/connect_white_large_long.gif);') + ' cursor:pointer;"></div><div id="process-' + tgt + '" style="display: none;">Logging in <fb:name uid="loggedinuser" linked="false" capitalize="true" useyou="false"></fb:name>...</div></div>') +
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
'</div>');
}

JSKAuth.prototype.gfcSectionTmpl = function() {
	var tgt = "gfc-" + Math.random();
return '<div id="' + tgt + '" style="text-align: center">' +
'<div class="jska-progressArea js-progressHandle"></div>' +
(this.gfc_site ? '<div name="' + tgt + '"><div id="wait-' + tgt + '">Asking Google...</div><div id="login-' + tgt + '" style="display: none;"></div><div id="process-' + tgt + '" style="display: none;"></div></div>' :
'<div style="width: 270px; height: 30px; margin: auto; overflow: hidden; "><iframe src="//js-kit.com/api/google/connect-button" height="50px" width="300px" allowtransparency="true" style="background-color: transparent; border: none; z-Index: 14000;" frameborder="0"></iframe></div>')+
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
'</div>';
}

JSKAuth.prototype.registerSectionTmpl =
'<div>' + JSKAuth.prototype.progressAreaTmpl +
	'<p class="jska-infoText jska-error" style="text-align: center;">{Label:allFieldsAreMandatory}</p>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="loginInput"' + JSKAuth.prototype.autoComplete +'>' +
		'<div class="jska-error js-loginMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:username}:</div>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="emailInput"' + JSKAuth.prototype.autoComplete +'>' +
		'<div class="jska-error js-emailMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:yourEmail}:</div>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="passwordInput" type="password">' +
		'<div class="jska-error js-passwordMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:password}</div>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="password2Input" type="password">' +
		'<div class="jska-error js-password2MessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:retypePassword}</div>' +
	'<div class="jska-clear"></div>' +
	'<div class="jska-controls">' +
		'<input value="{Label:jskaLogout}" class="jska-logout" type="button">' +
		'<input value="{Label:register}" name="authButton" class="jska-authButton" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	 '<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.passwordRecoveryRequestSectionTmpl =
'<div>' +
	'<p class="jska-text jska-passwordRecoveryText"><b>{Label:passwordRecovery}</b></p>' +
	JSKAuth.prototype.progressAreaTmpl +
	'<p class="jska-text jska-passwordRecoveryText">{Label:enterYourLoginNote}</p>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="loginInput"' + JSKAuth.prototype.autoComplete +'>' +
		'<div class="jska-error js-loginMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:username}:</div>' +
	'<div class="jska-clear"></div>' +
	'<div class="jska-controls">' +
		'<span class="jska-back">{Label:back}</span>' +
		'<input value="{Label:sendPassword}" name="authButton" class="jska-authButton" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.passwordRecoverySetPasswordSectionTmpl =
'<div>' +
	'<p class="jska-text jska-passwordRecoveryText"><b>{Label:passwordRecovery}</b></p>' +
	JSKAuth.prototype.progressAreaTmpl +
	'<p class="jska-text jska-passwordRecoveryText">Please enter the new password</p>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="loginInput"' + JSKAuth.prototype.autoComplete +'>' +
		'<div class="jska-error js-loginMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:username}:</div>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="authCodeInput"' + JSKAuth.prototype.autoComplete +'>' +
		'<div class="jska-error js-authCodeMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:authCode}:</div>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="passwordInput" type="password">' +
		'<div class="jska-error js-passwordMessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:password}</div>' +
	'<div class="jska-rightColumn">' +
		'<input class="jska-input" name="password2Input" type="password">' +
		'<div class="jska-error js-password2MessageHandle"></div>' +
	'</div>' +
	'<div class="jska-leftColumn jska-label">{Label:retypePassword}</div>' +
	'<div class="jska-clear"></div>' +
	'<div class="jska-controls">' +
		'<span class="jska-back">{Label:back}</span>' +
		'<input value="{Label:submit}" name="authButton" class="jska-authButton" type="button">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-clear"></div>' +
'</div>';

JSKAuth.prototype.passwordRecoverySuccessSectionTmpl = 
'<div>' +
	'<div class="jska-passwordRecoveryText">' +
		'<p class="jska-text"><b>{Label:passwordRecovery}</b></p>' +
		'<p class="jska-text">New password was set successfully. </p>' +
		'<a class="jska-linkToLogin jska-text">Click here to log in</a>' +
	'</div>' +
	'<div class="jska-controls">' +
		'<span class="jska-back">{Label:back}</span>' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
'</div>';

JSKAuth.prototype.processMessage = function(name, errCode, data) {
	if(errCode=='success') {
		this.disableControls(name, false);
		this.clearInputFields(name);
		switch (name) {
			case "passwordRecoveryRequest" : this.show("passwordRecoverySetPassword", {login: this.passwordRecoveryData["login"]});break;
			case "passwordRecoverySetPassword" : this.show("passwordRecoverySuccess");break;
			default : if (window.JSKW$Events) JSKW$Events.syncBroadcast('JSKitAuth_success_login', data); if (this.mode != "embedded") this.hide();	
		}
	} else {
		this.showErrorMessage(name, errCode);
	}
}

JSKAuth.prototype.showErrorMessage = function(name, errCode){
	JSKitLib.hide(this.HNDL[name].progress);
	this.disableControls(name, false);
	var errorTarget = this.getErrorTarget(errCode);
	if(errorTarget) {
		var inputHandle = this.HNDL[name]["input"][errorTarget];
		var errorMessageHandle = this.HNDL[name]["message"][errorTarget + "Msg"];
		if (inputHandle) inputHandle.focus();
		if (errorMessageHandle) {
			errorMessageHandle.innerHTML = $JAL(errCode);
			if (name == "register" && errorTarget != "email") errorMessageHandle.appendChild(this.buildShowMore());
			errorMessageHandle.style.display = 'block';
		}
	}
}

JSKAuth.prototype.serverCallback = function(type, errCode, data) {
	if (this.HNDL && this.HNDL[type]) JSKitLib.hide(this.HNDL[type].progress)
	if (type == "register" && data && data.yours) data.yours.newUser = true; 
	this.processMessage(type, errCode, data);
}

JSKAuth.prototype.createArea = function(name, data) {
	var self = this;

	var logoutAction = function() {
		setTimeout(function(){
			new JSRVC({uri: self.uriDomain + '/api/session/logout.js', 'target': self.target, request: {}});
		}, 0);
	}

	var sectionTmpl = self[name + "SectionTmpl"];
	var area = self.toDom(typeof(sectionTmpl) == "function" ? sectionTmpl.apply(self) : sectionTmpl);
	var areaElements = JSKitLib.mapClass2Object({}, area);

	var bindOnclick = function(element, func){
		if (element) element.onclick = function(){ func(); return false; }
	}

	if (self.mode != "embedded") bindOnclick(areaElements["jska-cancelBtn"], function(){ self.hide(); })
	else JSKitLib.hide(areaElements["jska-cancelBtn"]);

	if (name != "info"){
		bindOnclick(areaElements["jska-logout"], function(){ logoutAction(); self.hide();});
		if (!self.loginStatus && areaElements["jska-logout"]) JSKitLib.hide(areaElements["jska-logout"]);
	} else bindOnclick(areaElements["jska-back"], function(){ self.toggleInfoArea("hide"); }); 

	bindOnclick(areaElements["jska-forgotPassword"], function(){ self.show("passwordRecoveryRequest") });
	bindOnclick(areaElements["jska-linkToLogin"], function(){ self.show("login") });
	if (name.match(/passwordRecovery/)) {
		bindOnclick(areaElements["jska-back"], function(){ self.show("login") });
	}
	if (!name.match(/register|login|haloscan|openid|blogspot|passwordRecovery/)) return area;

	var createAction = function(type){
		return function(){
			var error = undefined;
			var params = {
				login: self.HNDL[type]["input"].login.value,
				password: self.HNDL[type]["input"].password.value,
				place: self.place || ""};
			if (type == "register") {
				params["retype_password"] = self.HNDL["register"]["input"].password2.value;
				params["email"] = self.HNDL["register"]["input"].email.value;
				params["version"] = "1";
			}
			if (params['login'].length < 1 || !self.HNDL[type]["input"].login.defaultRemoved) error = 'empty_login';
			if (!error && type == "register" && params['email'].length < 1) error = 'empty_email';
			if (!error && params['password'].length < 1) error = 'empty_password';
			if (!error && type == "register" && params['retype_password'].length<1) error = 'empty_password2';
			if (error) { self.showErrorMessage(type, error); return false; };
			var scripts = {"register" : "/user-registration", "login" : "/user-login", "haloscan" : "/user-haloscan-login"}
			new JSRVC({uri: self.uriDomain + scripts[type], 'target': self.target, request: params});
		}
	};

	var createOpenidAction = function(type){
		return function(){
			var random = function() {return Math.floor(Math.random() * 10000000000);};
			var PPID = 'prfl_' + random() + '-' + random() + '-' + random();
			var params = { jsktid: PPID};
			if (type == "blogspot") params.provider = "blogspot";
			if (self.mode == "popup" && self.LoginWindow && !self.LoginWindow.closed) {
				self.LoginWindow.focus();
				new JSRVC({uri: self.uriDomain + '/openid-auth-prolongate', 'target': self.target, request: params});
				return false;
			}
			var OpenID = self.HNDL[type]["input"].login;
			if(OpenID.value.length < 1 || !OpenID.defaultRemoved) {
				self.showErrorMessage(type, 'empty_' + type);
				return false;
			}
			if(type == "blogspot" && !OpenID.value.match(/\.blogspot\.com\/?$/)) {
				self.showErrorMessage(type, 'incorrect_blogspot_url');
				return false;
			}
			var AuthUrl = self.uriDomain + '/settings/auth.cgi?openid_url=' + OpenID.value;
			if (self.mode == "popup") {
				new JSRVC({uri: self.uriDomain + '/openid-auth-wait-for-completion', 'target': self.target, request: params});
				self.LoginWindow = window.open(AuthUrl + '&action=prfl&jsktid=' + PPID, '_blank',
				'status=no, menubar=no, resizable=no, scrollbars=yes, toolbar=no, location=yes, directories=no');
			} else {
				window.location = AuthUrl + '&action=prfl&place=' + (self.place || "");
			}
		}
	}

	var specificSubmitActions = {
		openid : createOpenidAction("openid"),
		blogspot : createOpenidAction("blogspot"), 
		login : createAction("login"),
		haloscan : createAction("haloscan"), 
		register: createAction("register"),
		passwordRecoveryRequest: function() {
			var loginInputBox = self.HNDL["passwordRecoveryRequest"]["input"].login;
			if (loginInputBox.value.length < 1 || !loginInputBox.defaultRemoved) {
				self.showErrorMessage('passwordRecoveryRequest', 'empty_login');
			} else {
				self.passwordRecoveryData["login"] = loginInputBox.value;
				new JSRVC({uri: self.uriDomain + '/user-password-recovery', 'target': self.target, request: {login: loginInputBox.value}});
			}
		},
		passwordRecoverySetPassword: function() {
			var inputCollection = self.HNDL["passwordRecoverySetPassword"]["input"]
			var params = {
				step: "set-password",
				login: inputCollection.login.value,
				key: JSKitLib.trim(inputCollection.authCode.value),
				password: inputCollection.password.value,
				retype_password: inputCollection.password2.value
			}
			this.passwordRecoveryData["login"] = undefined;
			new JSRVC({uri: self.uriDomain + '/user-password-recovery', 'target': self.target, request: params});
		}
	};

	var submitAction = function() {
		self.hideMessages(name);
		self.disableControls(name, true);
		self.HNDL[name].progress.style.display = "inline";
		specificSubmitActions[name].call(self);
		return false;
	};	

	if (!self.HNDL) self.HNDL = [];
	self.HNDL[name] = {
		progress  : areaElements['js-progressHandle'],
		container : area,
		button :
			{button : areaElements["authButton"]},
		message :
			{loginMsg : areaElements["js-loginMessageHandle"],
			emailMsg : areaElements["js-emailMessageHandle"],
			passwordMsg : areaElements["js-passwordMessageHandle"],
			password2Msg : areaElements["js-password2MessageHandle"]},
		input :
			{login : areaElements["loginInput"],
			authCode : areaElements["authCodeInput"],
			email: areaElements["emailInput"],
			password : areaElements["passwordInput"],
			password2 : areaElements["password2Input"]}
	};

	if (name != "passwordRecoverySetPassword") JHI2.create( (name == "openid" ? "http://user.myopenid.com" : (name == "blogspot" ? "http://yourblog.blogspot.com" : "Joe.Bloggs")), self.HNDL[name]["input"].login); 
	JSKitLib.fmap(data || [], function(value, key){
		self.HNDL[name]["input"][key].value = value;
	});
	bindOnclick(self.HNDL[name]["button"].button, submitAction);
	self.addKeyHandler(name);
	return area;
}

JSKAuth.prototype.buildShowMore = function() {
	var template = 
	'<span class="jska-showMore"> (' + 
		'<a class="js-fullDescLink" href="javascript:void(0);">Learn more...</a>)' +
		'<div style="display: none;" class="js-fullDescDiv">' + $JAL('full_description') + '</div>' 
	'</span>';

	var span = this.toDom(template);
	var handlers = JSKitLib.mapClass2Object({}, span);

	var fullDescLink = handlers['js-fullDescLink'];
	var fullDescDiv = handlers['js-fullDescDiv']; 
	fullDescLink.onclick = function(ev){
		JSKitLib.stopEventPropagation(ev);
		fullDescLink.innerHTML = this.visFullDesc ? 'Learn more...' : 'Hide';
		fullDescDiv.style.display = this.visFullDesc ? 'none' : '';
		this.visFullDesc = !this.visFullDesc;
		return false;
	}
	return span;
}

JSKAuth.prototype.createAuthSelector = function(options, selected, onchange) {
	var authSelector = this.toDom(
		'<select class="jska-selector">' +   
			JSKitLib.foldl("", options, function(option, acc) {
				return acc + '<option value="' + option + '"' + ((selected == option) ? ' selected="true"' : '') + '>' + $JAL(option+"JSKAMethod") + '</option>';
			}) +
		'</select>');
	authSelector.onchange = onchange;
	return authSelector;
}

function JSKAuth(config, target) {
	this.uriDomain = (window.location.protocol.substr(0, 4) != 'http' ? 'http:' : '') + '//js-kit.com';
	this.areas = {};
	this.passwordRecoveryData = {};
	this.defaultAuthOptions = ["register", "login", "haloscan", "openid", "facebook", "yahoo", "gfc", "twitter"];
	JSKitLib.fmap.call(this, config, function(v, k){ this[k] = v; });
	this.activeAreaByDefault = this.activeAreaByDefault || "login";

	this.authForm = this.assemble();
	this.target = target;
	this.prepareAuthForm();
	this.loadCss();
}




function JSDL(elmParent, arrDragElms) {
       var self = this;
       self.isIE = JSKitLib.isIE();
       var drgElms = arrDragElms || [elmParent];
       for(var i=0; i<drgElms.length; i++) {
               self.addDraggableChild(drgElms[i]);
       }
       self.elmParent = elmParent;
       self.setParent = 1;
}

JSDL.prototype.reSetDragParent = function () {
       if(!this.setParent) return;
       if(this.elmParent.parentNode!=document.body || this.elmParent.style.position!='absolute') {
               var elmPos;
               if(this.elmParent.parentNode) {
                       elmPos = this.getElmAbsPos(this.elmParent, false);
                       this.elmParent.parentNode.removeChild(this.elmParent);
               }
               document.body.appendChild(this.elmParent);
               this.elmParent.style.position = 'absolute';
               if(elmPos) {
                       this.elmParent.style.left = elmPos.x + "px";
                       this.elmParent.style.top = elmPos.y + "px";
               }
       }
       this.setParent = 0;
}

JSDL.prototype.getCurScroll = function() {
       var scroll_left=0,scroll_top=0;
       if(self.pageXOffset){
               scroll_left=self.pageXOffset;
       } else {
               if(document.documentElement&&document.documentElement.scrollLeft){
                       scroll_left=document.documentElement.scrollLeft;
               } else {
                       if(document.body){
                               scroll_left=document.body.scrollLeft;
                       }
               }
       }
       if(self.pageYOffset){
               scroll_top=self.pageYOffset;
       } else {
               if(document.documentElement&&document.documentElement.scrollTop){
                       scroll_top=document.documentElement.scrollTop;
               } else {
                       if(document.body){
                               scroll_top=document.body.scrollTop;
                       }
               }
       }
       return {"scroll_left":scroll_left,"scroll_top":scroll_top};
}

JSDL.prototype.getElmAbsPos = function (element, usescroll){
       var x=0;
       var y=0;
       var e=element;
       var scroll_left=0,scroll_top=0,cur_scroll;
       if(usescroll){
               cur_scroll=this.getCurScroll();
               scroll_left=cur_scroll.scroll_left;
               scroll_top=cur_scroll.scroll_top;
       }
       if(!this.isIE){
               while(e){
                       x+=e.offsetLeft;
                       y+=e.offsetTop;
                       e=e.offsetParent;
               }
               e=element;
               while(e && e!=document.body && e!=document.documentElement){
		       x -= e.scrollLeft || 0;
		       y -= e.scrollTop || 0;
                       e=e.parentNode;
               }
               if(usescroll){
                       x-=scroll_left;
                       y-=scroll_top;
               }
               return {x:x,y:y};
       }
       e=element;
       while(e){
               var left_border=0;
               var top_border=0;
               if(e!=element){
                       var left_border = parseInt(e.style.borderLeftWidth) || 0;
                       var top_border = parseInt(e.style.borderTopWidth) || 0;
               }
               if(document.compatMode == "BackCompat"){
                       x+=e.offsetLeft-left_border;
                       y+=e.offsetTop-top_border;
               } else {
                       x+=e.offsetLeft+left_border;
                       y+=e.offsetTop+top_border;
               }
               try {
                       e=e.offsetParent;
               } catch(err) { e=null; };
       }
       if(usescroll){
               x-=scroll_left;
               y-=scroll_top;
       }
       return {x:x,y:y};
}

JSDL.prototype.addDraggableChild = function(dragElm) {
       var self = this;
       dragElm.style.cursor = "move";
       dragElm.onmousedown = function(e){self.onStartDragHandler(e);}
}

JSDL.prototype.onStartDragHandler = function (e) {
       var self = this;
       self.reSetDragParent();
       e=e || window.event;
       var elmPos = self.getElmAbsPos(this.elmParent, false);
       var mousePos = JSKitLib.getMousePosition(e);
       self.startx = mousePos.x - elmPos.x;
       self.starty = mousePos.y - elmPos.y;
       var maxLeft = document.body.clientWidth - self.elmParent.offsetWidth -
               (parseInt(self.elmParent.style.marginLeft) || 0) -
               (parseInt(self.elmParent.style.marginRight) || 0);

       var onMoveDragHandler = function(event) {
               event = event || window.event;
               var mousePos = JSKitLib.getMousePosition(event);
               var left = mousePos.x - self.startx;
	       self.elmParent.style.left = (left >= maxLeft ? maxLeft : (left < 0 ? 0 : left)) + "px";
               self.elmParent.style.top = (mousePos.y - self.starty < 0) ? 0 : (mousePos.y - self.starty) + "px";
       }

       var onStopDragHandler = function(event) {
               event = event || window.event;
               JSKitLib.removeHandlers(document, onMoveDragHandler, onStopDragHandler, self.elmParent);
               JSKitLib.stopEventPropagation(event);
               if(self.elmParent.jsk$on_stop_drag) self.elmParent.jsk$on_stop_drag(e);
       }

       JSKitLib.addHandlers(document, onMoveDragHandler, onStopDragHandler, self.elmParent);
       JSKitLib.stopEventPropagation(e);
       JSKitLib.preventDefaultEvent(e);
       if(self.elmParent.jsk$on_start_drag) self.elmParent.jsk$on_start_drag(e);
}



function JSKitAvatars(config) {
	JSKitLib.fmap.call(this, config, function(value, key) { this[key] = value; });
	this.cleanupOpsQueue();
	this.activateEvents();
	this.loadCSS();
}

JSKitAvatars.prototype._labels = {
	"loading" : "Loading ...",
	"uploadAvatar" : "Upload new avatar :",
	"removeAvatar" : "Remove avatar",
	"selectedAvatar" : "Selected avatar",
	"noAvatarsMessage" : "No avatars uploaded",
	"loadingAvatarsData" : "Avatars are loading. Please wait ...",
	"removeAvatarConfirm" : "Remove this avatar?"
}

JSKitAvatars.prototype.label = function(name) { return (this.labels ? (this.labels(name) == name ? false : this.labels(name)) : false) || this._labels[name] || name; }

JSKitAvatars.prototype.anonymousAvatarData = function() { return {"name": "//js-kit.com/avatar/gxpA99f0jKlohF_DgthroT.png", "width": 100, "height": 100}; }

JSKitAvatars.prototype.assembleAvatarArea = function(container, avatar) {
	if (!container) return;
	this.avatarArea = container;
	this.setActiveAvatar(avatar);
	return container;
}

JSKitAvatars.prototype.setActiveAvatar = function(activeAvatar) {
	if (!this.avatarArea) return;
	activeAvatar = activeAvatar || this.getActiveAvatar();
	if (!activeAvatar) {
		activeAvatar = this.anonymousAvatarData(); 
		this.chosenAvatar = undefined;
	}
	JSKitLib.addStyle(this.avatarArea, " background: url('" + this.avatarURL(activeAvatar.name) + "') no-repeat center center;");
	JSKitLib.removeChildren(this.avatarArea);
	if (this.controlButtons) this.appendControlButtons(this.avatarArea);
}

JSKitAvatars.prototype.toggleAvatarsListView = function() { if (this.avatarsListContainer) JSKitLib.toggle(this.avatarsListContainer); }

JSKitAvatars.prototype.appendControlButtons = function(container) {
	var self = this;
	var onEditButtonClick = function() { self.toggleAvatarsListView(); };
	var onDeleteButtonClick = function() {
		if (!confirm(self.label('removeAvatarConfirm'))) return;
		var outer = self.chosenAvatar[1];
		outer.parentNode.removeChild(outer);
		self.processAction("remove", self.chosenAvatar[0].name);
		if (self.avatars.length == 0) self.showNoAvatarsMessage();
		self.setActiveAvatar();
	};
	container.editButton   = this.createControlButton("edit",   {"top": 60, "left": 15}, onEditButtonClick);
	container.deleteButton = this.createControlButton("delete", {"top": 60, "left": 55}, onDeleteButtonClick);

	container.appendChild(container.editButton);
	container.appendChild(container.deleteButton);

	container.onmouseout = function(e) {
		JSKitLib.hide(this.editButton);
		JSKitLib.hide(this.deleteButton);
	};
	container.onmouseover = function(e) {
		JSKitLib.show(this.editButton);
		if (self.chosenAvatar) JSKitLib.show(this.deleteButton);
	};
}

JSKitAvatars.prototype.createControlButton = function(type, position, onClickAction) {
	var button = document.createElement("DIV");
	JSKitLib.setStyle(button,
		"display: none; background: transparent; position: absolute; padding: 0; margin: 0; " +
		"width: 30px; height: 30px; top:" + position.top + "px; left:" + position.left + "px; cursor: pointer;");
	button.onclick = onClickAction;
	button.title = this.label(type + "AvatarsBtnLabel");
	JSKitLib.addPNG(button, "//js-kit.com/images/avatar-" + type + ".png");
	return button;
}

JSKitAvatars.prototype.getAvatars = function() { return this.avatars || []; }

JSKitAvatars.prototype.getActiveAvatar = function(getFromList) {
	if (this.bulkOperations && !getFromList) return this.chosenAvatar ? this.chosenAvatar[0] : undefined;
	return JSKitLib.foldl(undefined, this.avatars || [], function(avatar) { if (avatar.chosen) return avatar; });
}

JSKitAvatars.prototype.avatarURL = function(name) { return (/^(https?:)*\/\//.test(name)) ? name : this.uriAvatar + name; }

JSKitAvatars.prototype.cleanupOpsQueue = function() { this.opsQueue = []; }

JSKitAvatars.prototype.processAction = function(operation, avatar) {
	this.opsQueue.push({"op": operation, "avatar": avatar});
	if (this.bulkOperations) return; 
	this.avatars = this.applyAvatarsChanges(this.avatars);
	if (operation == "remove") this.removeAvatar(avatar);
	this.opsQueue.pop();
}

JSKitAvatars.prototype.removeAvatar = function(avatar) { this.sendServerRequest("remove", [], ["avrm", avatar]); }

JSKitAvatars.prototype.mkAvatar = function(avatar, onmouseover, onmouseout, onmousedown, outeronmousedown) {
	var self = this;
	var content = JSKitLib.html(
		'<div class="jsk-avt-container js-hideBorder">' +
		  '<div class="jsk-avt-wrapper">' +
		    '<div class="jsk-avt-image"></div>' +
		    '<div class="jsk-avt-control">' + 
		      '<div class="jsk-avt-control-selected">' + self.label('selectedAvatar') + '</div>' +
		      '<div class="jsk-avt-control-remove">' + self.label('removeAvatar') + '</div>' +
		    '</div>' +
		  '</div>' +
		'</div>'
	);
	var elements = JSKitLib.mapClass2Object({}, content);
	var get = function(name) { return elements["jsk-avt-" + name]; };
	JSKitLib.addPNG(get("image"), JSKitAvatars.prototype.avatarURL.call({uriAvatar: self.uriAvatar}, avatar.name));
	JSKitLib.addStyle(get("image"), "width: " + avatar.width + "px; height: " + avatar.height + "px; " +
			(this.oldStyleIE ? "" : "position: relative; left: " + ((114-avatar.width)/2) + "px;"));
	JSKitLib.hide(get("control-selected"));
	JSKitLib.hide(get("control-remove"));
	var args = [avatar, get("container"), get("control-selected"), get("control-remove")];
	get("control").onmouseover = function() { return onmouseover.apply(self, args); };
	get("control").onmouseout = function() { return onmouseout.apply(self, args); };
	get("control-remove").onmousedown = function(e) { 
		JSKitLib.stopEventPropagation(e); 
		return onmousedown.apply(self, args);
	};
	get("container").onmousedown = function() { outeronmousedown.apply(self, args); };
	if (avatar.chosen) outeronmousedown.apply(self, args); 
	return get("container");
}

JSKitAvatars.prototype.applyAvatarsChanges = function(avatars) {
	var getAvatarIdx = function(avts, avatarName) {
		for (var j=0; j<avts.length; j++) { if (avts[j].name == avatarName) return j; }
		return -1;
	};
	for (var i=0; i<this.opsQueue.length; i++) {
		var avatarIdx = getAvatarIdx(avatars, this.opsQueue[i].avatar);
		if (avatarIdx < 0) break;
		switch (this.opsQueue[i].op) {
                        case 'remove': avatars.splice(avatarIdx,1); break;
			case 'activate': avatars[avatarIdx].chosen = true; break;
			case 'deactivate': avatars[avatarIdx].chosen = false; break;
		}
	}
	if (this.bulkOperations) {
		var avatarUploaded = true;
		for (var k=0; k<avatars.length; k++) {
			avatarIdx = getAvatarIdx(this.origAvatars, avatars[k].name);
			if (avatarIdx < 0) {
				for (var l=0; l<this.opsQueue.length; l++) {
					if (this.opsQueue[l].avatar==avatars[k].name) { avatarUploaded = false; break; }
				}
				if (avatarUploaded) this.processAction("add", avatars[k].name); 
			}
		}
	}
	return avatars;
}

JSKitAvatars.prototype.replaceAvatars = function(avatars) {
	var self = this;
	if (!this.avatarsListArea) return;
	avatars = avatars || [];
	if (this.bulkOperations) {
		if (typeof(this.avatars) == "undefined") {
			this.origAvatars = this.avatars = avatars;
		} else this.avatars = this.applyAvatarsChanges(avatars);
	} else {
		this.avatars = avatars;
		this.setActiveAvatar();
	}
	var avatarsCount = this.avatars.length;
	var onmouseover = function(avatar, outer, sel, rem) {
		JSKitLib.hide(sel);
		JSKitLib.show(rem);
	};
	var onmouseout = function(avatar, outer, sel, rem) {
		JSKitLib.hide(rem);
		if (self.chosenAvatar && self.chosenAvatar[1] == outer) JSKitLib.show(sel);
	};
	var onmousedown = function(avatar, outer, sel, rem) {
		if (confirm(self.label('removeAvatarConfirm'))) {
			self.processAction("remove", avatar.name);
			outer.parentNode.removeChild(outer);
			if (self.chosenAvatar && self.chosenAvatar[1] == outer) {
				self.chosenAvatar = undefined;
				self.setActiveAvatar(); 
			}
			avatarsCount--;
		}
		if (avatarsCount < 1) self.showNoAvatarsMessage();
	};
	var outeronmousedown = function(avatar, outer, sel, rem) {
		if (self.chosenAvatar) {
			JSKitLib.removeClass(self.chosenAvatar[1], 'js-showBorder');
			JSKitLib.addClass(self.chosenAvatar[1], 'js-hideBorder');
			JSKitLib.hide(self.chosenAvatar[2]);
			JSKitLib.hide(self.chosenAvatar[3]);
		}
		if (self.chosenAvatar && self.chosenAvatar[1] == outer) {
			self.processAction("deactivate", avatar.name);
			self.chosenAvatar = undefined;
			self.setActiveAvatar();
		} else {
			JSKitLib.removeClass(outer, 'js-hideBorder');
			JSKitLib.addClass(outer, 'js-showBorder');
			if (self.chosenAvatar) self.processAction("deactivate", self.chosenAvatar[0].name);
			self.processAction("activate", avatar.name);
			self.chosenAvatar = [avatar, outer, sel, rem];
			JSKitLib.show(sel);
			JSKitLib.hide(rem);
			self.setActiveAvatar(avatar);
		}
	};
	var mkAvatar = function(avatar) { return self.mkAvatar(avatar, onmouseover, onmouseout, onmousedown, outeronmousedown); };
	JSKitLib.removeChildren(this.avatarsListArea);
	for (var i = this.avatars.length - 1; i >= 0; i--) this.avatarsListArea.appendChild(mkAvatar(this.avatars[i]));
	this.avatarsListArea.appendChild(JSKitLib.html('<div class="js-kit-clear"></div>'));
	if (avatarsCount < 1) self.showNoAvatarsMessage();
}

JSKitAvatars.prototype.showNoAvatarsMessage = function() {
	JSKitLib.removeChildren(this.avatarsListArea);
	this.avatarsListArea.appendChild(JSKitLib.html('<div class="jsk-avt-noAvatarsMsg">' + this.label("noAvatarsMessage") + '</div>'));
}

JSKitAvatars.prototype.refreshAvatars = function(isDataValid, avatars) {
	var self = this;
	if (isDataValid) { this.replaceAvatars(avatars); return; }
	setTimeout(function() { self.sendServerRequest("list"); }, 0);
}

JSKitAvatars.prototype.sendServerRequest = function(action, bulkOperations, singleOperation) {
	var self = this;
	if (action == "save" && bulkOperations.length < 1) return;
	var request = JSKitEPB.getAsHash({"ref": self.ref});
	if (action == "list") request["id"] = this.id;
	if (bulkOperations) request.avatars = bulkOperations.join(';');
	if (singleOperation) request[singleOperation[0]] = singleOperation[1];
	new JSRVC({"uri": self.uriAvatar + action, "request": request});
}

JSKitAvatars.prototype.saveAvatars = function() {
	if (this.opsQueue.length < 1) return;
	var ops = JSKitLib.foldl([], this.opsQueue, function(operation, acc) { if (operation.op != 'add') acc.push(operation.op + ',' + operation.avatar); });
	this.avatars = this.origAvatars = this.applyAvatarsChanges(this.avatars);
	this.sendServerRequest("save", ops);
	this.cleanupOpsQueue();
}

JSKitAvatars.prototype.revertAvatars = function() {
	if (this.opsQueue.length < 1) return;
	var ops = JSKitLib.foldl([], this.opsQueue, function(operation, acc) { if (operation.op == 'add') acc.push('remove,' + operation.avatar); });
	this.avatars = this.origAvatars;
	var avatar = this.getActiveAvatar(true);
	if (ops.length > 0) {
		if (avatar) ops.push('activate,' + avatar.name);
		this.sendServerRequest("save", ops);
	}
	if (!avatar) this.chosenAvatar = undefined;
	this.cleanupOpsQueue();
}

JSKitAvatars.prototype.activateEvents = function() {
	var self = this;
	this.avatarsListHandler = function(name, avatars, id, callerId) {
		if ((id && id == self.id) || (callerId && callerId != self.id)) self.replaceAvatars(avatars);
	};
	this.eventsCtx = JSKW$Events.registerEventCallback(this.eventCtx, self.avatarsListHandler, "JSAvatars_replaceAvatars");
}

JSKitAvatars.prototype.deActivateEvents = function() {
	if (!this.eventsCtx) return;
	JSKW$Events.deRegisterEventCallback(this.eventsCtx, this.avatarsListHandler, "JSAvatars_replaceAvatars");
	delete this.eventsCtx;
}

JSKitAvatars.prototype.syncAvatarsChanges = function() { JSKW$Events.syncBroadcast("JSAvatars_replaceAvatars", this.getAvatars(), undefined, this.id); }

JSKitAvatars.prototype.assembleAvatarsListArea = function(container, avatars, isHidden) {
	var self = this;
	if (!container || (container && container.uploadForm)) return;
	if (!this.controls) this.controls = [];
	var content = JSKitLib.html(
		'<div class="jsk-avt-area">' +
		  '<div class="jsk-avt-section-label">' + self.label('avatarsManagementLabel') + '</div>' +
		  '<div class="jsk-avt-list-area">' +
		    '<div class="jsk-avt-dataLoading">' +
		      '<img class="jsk-avt-dataLoading-icon" src="//js-kit.com/images/profile/loading.gif" />' +
		      '<div class="jsk-avt-dataLoading-label">' + self.label('loadingAvatarsData') + '</div>' +
		    '</div>' +
		  '</div>' +
		  '<div class="jsk-avt-upload-area">' +
		    '<form class="jsk-avt-upload-form" method="POST" enctype="multipart/form-data" action="' + this.uriAvatar + 'add">' +
		      '<div class="jsk-avt-upload-label">' + self.label('uploadAvatar') + '</div>' +
		      '<input type="file" name="image" class="jsk-avt-upload-input" />' +
		    '</form>' +
		  '</div>' +
		'</div>'
	);
	var avatarsValid = !this.bulkOperations || !!avatars;
	var elements = JSKitLib.mapClass2Object({}, content);
	var uploadForm = elements["jsk-avt-upload-form"];
	this.uploadControl = elements["jsk-avt-upload-input"];
	this.controls.push(this.uploadControl);
	this.avatarsListArea = elements["jsk-avt-list-area"];
	this.avatarsListContainer = container;

	JSKitLib.fmap(JSKitEPB.getAsHash({"ref": self.ref}), function(v, k) {
		uploadForm.appendChild(JSKitLib.html('<input type="hidden" name="' + k + '" value="' + encodeURIComponent(v) + '">'));
	});

	var freeze = function(lock) {
		elements["jsk-avt-upload-label"].innerHTML = self.label(lock ? "loading" : "uploadAvatar");
		JSKitLib.fmap(self.controls, function(control) {
			if (!control.btnLocked) control.disabled = (lock == true) ? "true" : "";
		});
	};
	var onLoad = function() {
		freeze(false);
		elements["jsk-avt-upload-form"].reset();
		if (!avatarsValid) {
			self.refreshAvatars(false);
			avatarsValid = true;
		}
	};
	elements["jsk-avt-upload-input"].onchange = function() {
		avatarsValid = false;
		if (!uploadForm.target) {
			var tgt = 'js-ifrm-' + Math.random();
			JSKitLib.createHiddenIframe(tgt, elements["jsk-avt-upload-area"], onLoad, false);
			uploadForm.target = tgt;
		}
		uploadForm.submit();
		freeze(true);
	};

	if (avatars) this.avatars = avatars; 
	this.refreshAvatars(avatarsValid, this.avatars);
	container.uploadForm = uploadForm;
	container.appendChild(content);
	if (isHidden) JSKitLib.hide(this.avatarsListContainer);
	return container;
}

JSKitAvatars.prototype.loadCSS = function() {
	this.oldStyleIE = JSKitLib.isPreIE8() || (JSKitLib.isIE() && !JSKitLib.isPreIE8() && document.compatMode == "BackCompat");
	JSKitLib.addCss(
		".jsk-avt-container { float: left; display: inline-block; margin: 2px; width: 118px; text-align: center; }" +
		".jsk-avt-wrapper { margin: 2px; width: 114px; height: 114px; background-position: top center; }" +
		".jsk-avt-control { padding: 2px 5px 0px 5px; font-family: Helvetica, Verdana; font-size: 8pt; height: 14px; }" +
		".jsk-avt-control-selected { text-align: center; }" +
		".jsk-avt-control-remove { text-align: center; cursor: pointer; text-decoration: underline; }" +
		".jsk-avt-upload-label { font-size: 12px; }" +
		".jsk-avt-noAvatarsMsg { font-style: italic; padding: 10px; }" +
		".jsk-avt-dataLoading { text-align: center; font-style: italic; margin: 10px; font-size: 12px; }" +
		".js-showBorder { border:ridge 2px #a0a0a0; }" +
		".js-hideBorder { border:solid 2px #fefefe; }" +
		".js-kit-clear { clear: both; }", "avatars"
	);
}



function JSKbdHandler(element, events) {

	this.kbdCallback = function(e) {
		var event = e || window.event;
		var key = event.charCode || event.keyCode;
		if (key == 9 || key == 13 || key == 27) JSKitLib.preventDefaultEvent(event);
		if(JSKitLib.isSafari()) JSKitLib.stopEventPropagation(event);
		for(var i = 0; i < events.length; i++) {
			for(var j = 0; j < events[i].keys.length; j++) {
				if(typeof(events[i].keys[j]) == "string") events[i].keys[j] = String.charCodeAt(events[i].keys[j]);
				var shiftCondition = (events[i].shift != undefined) ? events[i].shift == event.shiftKey : true; 
				if (events[i].keys[j] == key && shiftCondition) {
					if(!events[i].args)
						(events[i].action)();
					else
						events[i].action.apply(events[i], events[i].args);
				}
			}
		}
	}

	if(element.addEventListener) {
		if(JSKitLib.isSafari()) element.addEventListener("keydown", this.kbdCallback, false);
		else if(JSKitLib.isOpera()) element.addEventListener("keydown", this.kbdCallback, false);
		else element.addEventListener("keypress", this.kbdCallback, false);
	} else {
		element.onkeydown = this.kbdCallback;
	}
}



function JSIPE2(obj) {
/* 
	JSIPE2 API

	obj:		object contains property
	title: 		hint
	defaultText:	default text in created div
	property:	property where save the result
	maxLength:	max string length
	width: 		input width
	jsk$wasEdited	callback, called at the end of editing 
	
	example: 
	var jsipe = new JSIPE2({obj: elem,
				property: 'descr',
				title: 'Description',
				defaultText: 'Add caption',
				width: '90px',
				maxLength: 12,
				jsk$wasEdited: function(){...}
	});

*/

	for(var i in obj)
		this[i] = obj[i];
	var div = JSKitLib.cr();
	div.title = this.title || "Click to edit";
	var defaultText = this.defaultText || "Empty value (click to edit)";
	var maxTextLength = this.maxLength || 256;

	var self = this;

	var textDiv = JSKitLib.cr({style:{display:"inline"}});
	textValue = (JSKitLib.trim(self.obj[self.property]).length > 0) ? self.obj[self.property] : defaultText;
	var text = document.createTextNode(textValue);
	textDiv.onmouseover = function() { JSKitLib.addClass(textDiv, "jsipe-onmouseover"); }
	textDiv.onmouseout  = function() { JSKitLib.removeClass(textDiv, "jsipe-onmouseover"); }
	textDiv.appendChild(text);
	div.appendChild(textDiv);

	var editDiv = JSKitLib.cr({style:{display:"none"}});
	div.appendChild(editDiv);
	var edit = JSKitLib.cr({t:"input", type:"edit", style:{width: (self.width || "150px")}});
	edit.value = this.obj[this.property];
	editDiv.appendChild(edit);

	var applyDiv = JSKitLib.cr();
	JSKitLib.addClass(applyDiv, "jsipe-applyButton");
	applyDiv.title = "Apply";
	JSKitLib.addPNG(applyDiv, "//js-kit.com/images/tick.png");
	editDiv.appendChild(applyDiv);
	
	this.displayMode = function() {
		textDiv.style.display = "inline";
		editDiv.style.display = "none";
		textDiv.removeChild(text);
		text = document.createTextNode(self.obj[self.property] || defaultText);
		textDiv.appendChild(text);
		if(self.jsk$wasEdited) self.jsk$wasEdited();
	}

	this.editMode = function(e) {
		textDiv.style.display = "none";
		editDiv.style.display = "inline";
		edit.focus();
		edit.select();
	}

	var applyChanges = function() {
		if(edit.value == self.obj[self.property]) { self.displayMode(); return;}
		if(edit.value.length > maxTextLength) {
			alert("The text you entered cannot exceed "+ maxTextLength +" symbols");
			resetChanges();
			return;
		}
		self.obj[self.property] = edit.value = JSKitLib.trim(edit.value);
		edit.blur();
		self.displayMode();
	}

	var resetChanges = function() {
		edit.value = self.obj[self.property];
		edit.blur();
		self.displayMode();
	}

	var jumpNextSibling = function() {
		edit.blur();
		if(self.nextSib)
			self.nextSib.editMode();
	}

	var jumpPrevSibling = function() {
		edit.blur();
		if(self.prevSib)
			self.prevSib.editMode();
	}

	if(this.dblclick)
		textDiv.ondblclick = this.editMode;
	else
		textDiv.onclick = this.editMode;
	edit.onblur = applyChanges;
	applyDiv.onmousedown = applyChanges;

	var KbdHandler = new JSKbdHandler(edit, [
					{action:applyChanges, keys:[10,13]}
					,{action:resetChanges, keys:[27]}
					,{action:jumpNextSibling, keys:[9], shift:false}
					,{action:jumpPrevSibling, keys:[9], shift:true}
					]);

	this.div = div;
}

JSIPE2.prototype.addNextSibling = function(next) {
	if (next) {
		this.nextSib = next;
		next.prevSib = this;
	}
}



function JSIPE(obj) {
	var self = this;
	self.obj = obj;
	var form = this.makeForm(obj.title);
	var inp = form.input;
	self.form = form;

	form.cleaner.onmousedown = function(e){
		inp.value = "";
		form.cleaner.style.visibility = "hidden";
		inp.focus();
		JSKitLib.preventDefaultEvent(e || window.event);
	}
	
	var keyHandler = function(e) {
		e = e || window.event;
		setTimeout(function(){
			form.cleaner.style.visibility = (inp.value.length != 0) ? "visible" : "hidden";
			if(obj.type == "Tab" || obj.type == "Image") form.cleaner.style.display = "none";
		}, 0);
		switch(e.keyCode || e.which) {
			case 27:
				JSKitLib.preventDefaultEvent(e);
				if(obj.mode == "full") self.finishEditing(obj.field, obj.field.lastValue);
				if(obj.jsk$on_cancel_exit) obj.jsk$on_cancel_exit();
			break;
			case 10: case 13:
				JSKitLib.preventDefaultEvent(e);
				if (inp.value && obj.mode == "full")
					self.finishEditing(obj.field, inp.value);
				if(obj.jsk$on_submit_exit) obj.jsk$on_submit_exit(inp.value);
			break;
			case 9:
				JSKitLib.preventDefaultEvent(e);
				if (obj.siblings) obj.siblings[(obj.field.pos+1)%obj.siblings.length].tabKeyHandler();
			break;
		}
	}
	self.addKeyHndl(keyHandler);		
	if (obj.inpSize) inp.style.width = obj.inpSize;
	form.cleaner.style.visibility = "hidden";
	if(obj.mode == "form") return form;

	if(!window.jsipe$glob) window.jsipe$glob = {};
	var glob = window.jsipe$glob;
	obj.field.style.cursor = "pointer";
	if(obj.siblings) obj.field.pos = obj.siblings.length;

	this.finishEditing = function(field, newValue) {
		if(!field.input) return;
		glob.isEditing = false;
		field.input.onblur = JSKitLib.isOpera() ? undefined : "";
		field.input.onkeypress = JSKitLib.isOpera() ? undefined : "";
		field.input = null;
		field.wasEdited(newValue);
		field.style.textDecoration = field.oldDecoration;
	}

	var onclickHandler = function() {
		if(obj.field.input) return false;
		if(obj.jsipe$start && !obj.jsipe$start()) return false;
		if(glob.stopEditing) glob.stopEditing();
		if(obj.containerElement.tId) {
			clearTimeout(obj.containerElement.tId);
			obj.containerElement.tId = 0} 
		obj.field.oldDecoration = obj.field.style.textDecoration;
		obj.field.isHtmlLink = obj.field.firstChild.tagName == 'A';
		obj.field.lastValue = obj.itemObject[obj.Property];
		obj.field.ondblclick = JSKitLib.isOpera() ? undefined : "";
		inp.type = 'text';
		inp.value = obj.itemObject[obj.Property];
		self.addKeyHndl(keyHandler);		

		inp.onblur = function(e) {
			if(self.form.input.value) {
				self.finishEditing(self.obj.field, self.form.input.value);
				if (obj.field.lastValue == self.form.input.value) {
					if(obj.jsk$on_cancel_exit) obj.jsk$on_cancel_exit(self.form.input.value)}
				else{
					if(obj.jsk$on_submit_exit) obj.jsk$on_submit_exit(self.form.input.value)}
			};
			//Do not close field until non-empty
		}

		obj.field.input = inp;
		glob.stopEditing = function() {
			glob.stopEditing = null;
			if((obj.field.input)&&obj.field.input.value) self.finishEditing(obj.field, obj.field.input.value);
		}
		JSKitLib.removeChildren(obj.field);
		obj.field.appendChild(form.main);
		obj.field.style.textDecoration = "none";
		form.cleaner.style.visibility = (inp.value.length != 0) ? "visible" : "hidden";
		if(obj.type == "Tab"  || obj.type == "Image") form.cleaner.style.display = "none";
		inp.onselectstart = function(e) {
			JSKitLib.stopEventPropagation(e || window.event);
			return true;
		};
		obj.containerElement.onselectstart = function(e) { return true };
		inp.focus();
		inp.select();
		glob.isEditing = true;
		return false;
	}

	var ondblclickHandler = function() {
		if(0 && obj.field.isHtmlLink)
			window.location.href = this.firstChild.value;
	}

	switch(obj.type) {
	case "Tab":
		obj.field.ondblclick = onclickHandler;
		break;
	case "Others":
                obj.field.onclick = onclickHandler;
                obj.field.tabKeyHandler = onclickHandler;
                obj.field.ondblclick = ondblclickHandler;
		break;
	case "Search": case "Image":
		obj.field.onclick = onclickHandler;
		break;
	}
}

JSIPE.prototype.addKeyHndl = function(keyHandler){
	var inp = this.form.input;
        switch(this.obj.type) {
        case "Tab":
                if (JSKitLib.isIE()) inp.onkeydown = keyHandler;
                else if(JSKitLib.isSafari()) inp.onkeyup = keyHandler;
                else inp.onkeypress = keyHandler;
                break;
        case "Others": case "Image":
		if(JSKitLib.isOpera()) inp.onkeypress = keyHandler;
		else inp.onkeydown = keyHandler;
                break;
        case "Search":
		if (JSKitLib.isIE() || JSKitLib.isSafari())
			inp.onkeydown = keyHandler;
		else inp.onkeypress = keyHandler;
                break;
        }
}

JSIPE.prototype.makeForm = function(title){
	var text = this.dtContent.replace(/TITLE/, title || "");
	var div = JSKitLib.html(text);
	var ctls = JSKitLib.mapClass2Object({}, div);
	if(!title) ctls['js-JSIPETitle'].style.display = "none";
	return {'main': div,'input': ctls['js-JSIPEInput'], 'cleaner':ctls['js-JSIPECleaner']};
}

JSIPE.prototype.dtContent
='<table border=0 style="padding: 0px; display: inline" cellspacing="0px" cellpadding="0px">'
+'      <tr>'
+'              <td class="js-JSIPETitle" style="padding:0px 4px 0px 0px; cursor: text;"><b>TITLE</b></td>'
+'              <td style="padding: 0px;">'
+'                      <input class="js-JSIPEInput" style="vertical-align:middle; padding: 0px;"></input></td>'
+'              <td style="padding: 0px;">'
+'                      <img class="js-JSIPECleaner" style="margin-left: 4px; vertical-align:bottom; cursor: pointer;" src="//js-kit.com/images/clear-search-button.gif" width="16" height="16"></img></td>'
+'      </tr>'
+'</table>';



if(!window.JSKW$Events){
        var JSKW$Events = new JSEC();
}

/////////////////////////////////////
// JS Event Class
/////////////////////////////////////
function JSEC() {
	this.contextHandles = [];
}

JSEC.prototype.registerEventCallback = function (contextHandle, eventHandle, eventName) {
	if(!contextHandle) {
		contextHandle = new JSECC(eventHandle, eventName);
		this.contextHandles.push(contextHandle);
		contextHandle.cHdlId = this.contextHandles.length - 1;
	} else {
		contextHandle.registerEventCallback(eventHandle, eventName);
	}
	return contextHandle;
}

JSEC.prototype.deRegisterEventCallback = function (contextHandle, eventHandle, eventName) {
	contextHandle.deRegisterEventCallback(eventHandle, eventName);
}

JSEC.prototype.syncBroadcast = function (eventName) {
	var args = arguments;
	JSKitLib.fmap(this.contextHandles, function(c){
		if(c) c.broadCast.apply(c, args);
	});
}

JSEC.prototype.asyncBroadcast = function (eventName) {
	var self = this;
	var args = arguments;
	setTimeout(function(){
		self.syncBroadcast.apply(self, args);
	}, 0);
}

JSEC.prototype.invalidateContext = function (contextHandle) {
	if(contextHandle) {
		contextHandle.invalidateContext();
		delete this.contextHandles[contextHandle.cHdlId];
	}
}

/////////////////////////////////////
// JS Event Context Class
/////////////////////////////////////
function JSECC(eventHandle, eventName) {
	this.registeredCallbacks = [];
	if(eventName || eventHandle) this.registerEventCallback(eventHandle, eventName);
}

JSECC.prototype.registerEventCallback = function (eventHandle, eventName) {
	var ev = eventName || '';
	if(!this.registeredCallbacks[ev]) this.registeredCallbacks[ev] = [];
	this.registeredCallbacks[ev].push(eventHandle);
}

JSECC.prototype.deRegisterEventCallback = function (eventHandle, eventName) {
	var ev = eventName || '';
	var self = this;
	if(!eventHandle) {
		delete this.registeredCallbacks[ev];
		return;
	}
	var k=0;
	while(k<this.registeredCallbacks[ev].length) {
		if(this.registeredCallbacks[ev][k] == eventHandle) {
			self.registeredCallbacks[ev].splice(k, 1);
		} else k++;
	}
	if(!this.registeredCallbacks[ev].length) delete this.registeredCallbacks[ev];
}

JSECC.prototype.invalidateContext = function () {
	this.registeredCallbacks = [];
	try {
		if(this.jsk$invalidate) this.jsk$invalidate();
	} catch(e) { ; };
}

JSECC.prototype.broadCast = function (eventName) {
	var self = this;
	var ar = [''];
	var args = arguments;
	if(eventName!='') ar.push(eventName);
	JSKitLib.fmap(ar, function(ev){
		if(self.registeredCallbacks[ev]) JSKitLib.fmap(self.registeredCallbacks[ev], function(evHdl){
			evHdl.apply(self, args);
		});
	});
}



function JSPGC(itemsCount, itemsPerPage) {
	this.itemsPerPage = itemsPerPage;
	this.items = [];
	this.itemsCount = 0;
	this.pages = [];
	this.pageCount = 0;
	this.setPageCount(this.getPageCntByItemCnt(itemsCount), itemsCount);
}

JSPGC.prototype.newItem = function(item) {
	var newItem = { obj: undefined, html: undefined, div: undefined };
	if(item) JSKitLib.fmap(item, function(V,K){ newItem[K] = V; });
	return newItem;
};

JSPGC.prototype.setItems = function (sIdx, Cnt, itemsArr) {
	for(var i=sIdx; i<sIdx+Cnt; i++) {
		this.items[i] = itemsArr[i-sIdx];
	}
}

JSPGC.prototype.addItem = function (item, sIdx) {
	this.items.splice(sIdx, 0, item);
	this.itemsCount++;
}

JSPGC.prototype.getItems = function (sIdx, Cnt) {
	return (sIdx>=0 && Cnt) ? this.items.slice(sIdx, sIdx+Cnt) : [];
}

JSPGC.prototype.deleteItems = function (sIdx, Cnt) {
	this.items.splice(sIdx, Cnt);
	this.itemsCount -= Cnt;
}

JSPGC.prototype.setItemsCount = function (newItemsCount) {
	if(newItemsCount<this.itemsCount) {
		this.deleteItems(newItemsCount, this.itemsCount-newItemsCount);
	} else {
		if(newItemsCount>0) this.items[newItemsCount-1] = undefined;
		this.itemsCount = newItemsCount;
	}
}

JSPGC.prototype.getItemIdxById = function (itemId) {
	var itemIdx;
	for(var i=0; i<this.itemsCount; i++) {
		if(this.items[i] && this.items[i].obj.ID==itemId) {
			itemIdx = i;
			break;
		}
	}
	return itemIdx;
}

JSPGC.prototype.invalidateItemsAttr = function(itemIdx, Cnt, Attr) {
	JSKitLib.fmap(this.getItems(itemIdx, Cnt), function(item) {
		item[Attr] = undefined;
	});
}

JSPGC.prototype.invalidateItems = function(itemIdx, Cnt) {
	var items = this.getItems(itemIdx, Cnt);
	JSKitLib.fmap(items, function(V,K) {
		items[K] = undefined;
	});
}

JSPGC.prototype.newPage = function (page) {
	var newPage = {invalidVisualization: true, invalidData: true};
	if(page) JSKitLib.fmap(page, function(V,K){ newPage[K] = V; });
	return newPage;
}

JSPGC.prototype.addPage = function (page) {
	this.pages[this.pages.length] = page || this.newPage();
	this.pageCount++;
}

JSPGC.prototype.deletePage = function () {
	delete this.pages[this.pages.length];
	this.pageCount--;
}

JSPGC.prototype.getPages = function (pageIdx, Cnt) {
	return (pageIdx>=0 && Cnt) ? this.pages.slice(pageIdx, pageIdx+Cnt) : [];
}

JSPGC.prototype.getPage = function (pageIdx) {
	var pageArr = this.getPages(pageIdx, 1);
	return (pageArr.length>0) ? pageArr[0] : undefined;
}

JSPGC.prototype.getStartPageItem = function (pageIdx) {
	return pageIdx * this.itemsPerPage;
}

JSPGC.prototype.setPageCount = function (newPageCount, newItemsCount) {
	while(this.pageCount<newPageCount) this.addPage();
	while(this.pageCount-newPageCount>0) this.deletePage();
	this.pageCount = newPageCount;
	this.setItemsCount(newItemsCount);
	if(!newItemsCount && newPageCount) this.setPageAttr(0, 1, {invalidData: false});
}

JSPGC.prototype.getPageAttr = function (pageIdx, Attr) {
	var page = this.getPage(pageIdx);
	return page ? page[Attr] : undefined;
}

JSPGC.prototype.setPageAttr = function (pageIdx, Cnt, Attrs) {
	JSKitLib.fmap(this.getPages(pageIdx, Cnt),
		function(curPage) {
			JSKitLib.fmap(Attrs, function(V,K){ curPage[K] = V }) 
		});
}

JSPGC.prototype.getPageByItemIdx = function(index) {
	return Math.floor(index/this.itemsPerPage);
}

JSPGC.prototype.getPageCntByItemCnt = function(itemCnt) {
	return Math.ceil(itemCnt/this.itemsPerPage);
}

JSPGC.prototype.setPageItems = function (startPage, newData) {
	var pageCount = this.getPageCntByItemCnt(newData.length);
	this.setPageAttr(startPage, pageCount, {invalidData: false, invalidVisualization: true});
	var startItem = this.getStartPageItem(startPage);
	var self = this;
	this.setItems(startItem, newData.length, JSKitLib.fmap(newData, function(C){ return self.newItem({obj: C}); }));
}

JSPGC.prototype.addPageItem = function (item, itemIdx) {
	if(this.pageCount*this.itemsPerPage==this.itemsCount) {
		this.addPage();
		this.setPageAttr(this.pageCount-1, 1, {invalidData: false});
	}
	var idx = (typeof itemIdx == "undefined") ? this.itemsCount : itemIdx;
	this.addItem(item, idx);
	var insertPageIdx = this.getPageByItemIdx(idx);
	this.setPageAttr(insertPageIdx, this.pageCount-insertPageIdx, { invalidVisualization: true});
	for(var i=insertPageIdx+1; i<this.pageCount; i++) {
		if(!this.getPageAttr(i, 'invalidData')) {
			if(!(this.getPageItems(i)[0])) {
				this.setPageAttr(i, 1, {invalidData: true});
			}
		}
	}
}

JSPGC.prototype.deletePageItem = function (itemIdx) {
	var deletePageIdx = this.getPageByItemIdx(itemIdx);
	this.deleteItems(itemIdx, 1);
	this.setPageAttr(deletePageIdx, this.pageCount-deletePageIdx, { invalidVisualization: true});
	for(var i=deletePageIdx; i<this.pageCount-1; i++) {
		if(!this.getPageAttr(i, 'invalidData')) {
			var itemsCnt = this.getPageItemsCnt(i);
			if(!(this.getPageItems(i)[itemsCnt-1])) {
				this.setPageAttr(i, 1, {invalidData: true});
			}
		}
	}
	if((this.pageCount-1)*this.itemsPerPage==this.itemsCount && this.pageCount>1) this.deletePage();
}

JSPGC.prototype.getPageItems = function (pageIdx) {
	var startItem = this.getStartPageItem(pageIdx);
	var itemsCnt = this.getPageItemsCnt(pageIdx);
	return this.getItems(startItem, itemsCnt);
}

JSPGC.prototype.invalidatePagesView = function (pageIdx, Cnt) {
	this.setPageAttr(pageIdx, Cnt, {invalidVisualization: true});
}

JSPGC.prototype.invalidatePages = function (pageIdx, Cnt) {
	for(var i=0; i<Cnt; i++) {
		var startItem = this.getStartPageItem(pageIdx+i);
		var itemsCnt = this.getPageItemsCnt(pageIdx+i);
		this.invalidateItems(startItem, itemsCnt);
	}
	this.setPageAttr(pageIdx, Cnt, {invalidData: true, invalidVisualization: true});
}

JSPGC.prototype.newData = function (newItemsCount, startPage, newData) {
	var newPageCount = this.getPageCntByItemCnt(newItemsCount);
	this.setPageCount(newPageCount || 1, newItemsCount);
	this.setPageItems(startPage, newData);
}

JSPGC.prototype.addNewItem = function (obj, itemId, isPrepend) {
	var item = this.newItem();
	item.obj = obj;
	this.addPageItem(item, itemId ? this.getItemIdxById(itemId) + (isPrepend ? 0 : 1) : undefined);
}

JSPGC.prototype.deleteItem = function (itemId) {
	this.deletePageItem(this.getItemIdxById(itemId));
}

JSPGC.prototype.getPageVisualization = function (pageIdx, cb) {
	var self = this;
	if(pageIdx<0 || pageIdx>=this.pageCount) return cb(undefined);
	var curPage = this.getPage(pageIdx);
	var getPageFunc = function(){ self.getPageVisualization(pageIdx, cb); };
	if(this.getPageAttr(pageIdx, 'invalidData'))
		return this.dataRequest(pageIdx, curPage, cb);
	if(this.getPageAttr(pageIdx, 'invalidVisualization')) {
		curPage.invalidVisualization = false;
		return this.dataVisualizator(this.getStartPageItem(pageIdx), this.getPageItems(pageIdx), curPage, getPageFunc);
	}
	return cb(this.getPage(pageIdx).target, true);
}

JSPGC.prototype.getPageItemsCnt = function(pageIdx) {
	if(pageIdx<0 || pageIdx>=this.pageCount) return 0;
	return (pageIdx==this.pageCount-1 ? (this.itemsCount-pageIdx*this.itemsPerPage) : this.itemsPerPage);
}

JSPGC.prototype.getItemById = function(itemId) {
	var itemsArr = this.getItems(this.getItemIdxById(itemId), 1);
	return (itemsArr.length>0) ? itemsArr[0] : undefined;
}

JSPGC.prototype.getPageByItemId = function(itemId) {
	return this.getPageByItemIdx(this.getItemIdxById(itemId));
}

JSPGC.prototype.getFirstItem = function () {
	if(this.itemsCount) {
		var itemsArr = this.getItems(0, 1);
		return (itemsArr.length>0) ? itemsArr[0] : undefined;
	} else {
		return undefined;
	}
}

JSPGC.prototype.invalidateItemView = function (itemId) {
	var itemIdx = this.getItemIdxById(itemId);
	this.invalidateItemsAttr(itemIdx, 1, 'html');
	var pageIdx = this.getPageByItemIdx(itemIdx);
	this.invalidatePagesView(pageIdx, 1);
}

JSPGC.prototype.invalidate = function () {
	this.invalidatePages(0, this.pageCount);
}



//////////////////// JSRVC
// requestObj
// request: {uri: someuri, param1: val1, param2: val2, ...}
// [transport: ("GET" | "POST")]
// [target: some_DOM_element]
// [variableRequest: [{param1_1: val1_1, param1_2: val1_2, ...},
//			{param2_1: val2_1, param2_2: val2_2,...}, ...]]
// [form: some_form]
// [onreturn: some_callback]
// [randevu : (true | false)]
// [requestId: some request identity]

function JSRVC(requestObj) {
	var s = this;
	s.requestId = requestObj.requestId || s.generateRequestId();
	s.requestsInProgress = 0;
	s.requestsQueue = [];
	s.processRequest(requestObj);
}

JSRVC.prototype.generateRequestId = function() {
	return ((new Date()).valueOf() + Math.random()).toString();
}

JSRVC.prototype.processRequest = function(requestObj) {
	var s = this;
	s.error = undefined;
	if(s.requestsInProgress) {
		s.requestsQueue.push(requestObj);
		return;
	}
	s.requestObj = requestObj;
	if(s.requestObj.pickup && !s.eventCtx) s.eventCtx = JSKW$Events.registerEventCallback(s.eventCtx, function() {s.eventCallback.apply(s, arguments);}, "randevu_answer");
	var req = s.requestObj;
	s.preProcessRequest();
	if(!req.transport)
		req.transport = req.form ? "POST" : s.getRequestTransport();
	req.target = req.target || document.body;
	var onCompleteCB = req.timeout ? function() {
		s.startTimeoutTimer.call(s);
	} : undefined;
	var handlers = {'onload': s.onLoadRequest, 'onreadystatechange': s.onLoadRequest};
	switch(req.transport) {
	case "GET":
		s.processGETRequest(onCompleteCB, handlers);
		break;
	case "POST":
		s.processPOSTRequest(onCompleteCB, handlers);
		break;
	}
}

JSRVC.prototype.preProcessRequest = function() {
	var req = this.requestObj;
	if(!req.request) req.request = {};
	JSKitLib.fmap(req.epb || {}, function(v, k) { req.request[k] = v; });
	if (req.ref) req.request.ref = req.ref;
	req.request.randevuId = this.requestId;
	if(!req.variableRequest) req.variableRequest = [];
	if(req.pickup) req.request.randevuRnd = Math.random();
}

JSRVC.prototype.calcGetRequest = function() {
	var s = this;
	var req = s.requestObj;
	var reqvar = req.variableRequest;
	var permGETReq = s.serializeRequest(req.request);
	var varGETReq = JSKitLib.fmap(reqvar, function(el, idx){
		return s.serializeRequest(el, '[' + idx + ']');
	});
	return [permGETReq, varGETReq];
}

JSRVC.prototype.getRequestTransport = function() {
	var ser = this.calcGetRequest();
	var permReq = ser[0];
	var varReq = ser[1];
	var firstReqLen = permReq.length +
		(varReq.length>0 ? varReq[0].length : 0);
	var totalReqLen = 0;
	for(var i=0; i<varReq.length; i++)
		totalReqLen += varReq[i].length;
	
	return ((firstReqLen > 1700) || (totalReqLen > 3400) ?
		"POST" : "GET");
}

JSRVC.prototype.startTimeoutTimer = function() {
	var s = this;
	s.timeoutTimer = setTimeout(function() { s.timeoutExpired(); }, s.requestObj.timeout);
}

JSRVC.prototype.timeoutExpired = function() {
	this.error = "timeout";
	this.returnAnswer();
}

JSRVC.prototype.returnAnswer = function(answerData) {
	var s = this;
	answerData = answerData || {};
	if(answerData.script) {
		var script = document.createElement('script');
		script.text = answerData.script;
		this.requestObj.target.appendChild(script);
	}
	if(s.requestObj.onreturn) {
		s.requestObj.onreturn.call(s, s.error || "data", answerData.data);
	}
}

JSRVC.prototype.serializeRequest = function(obj, prefix) {
	return JSKitLib.fmap(obj, function(v, k) {
		return encodeURIComponent(k) + (prefix || '') + "=" + encodeURIComponent(v);
       }).join("&");
}

JSRVC.prototype.setElementAttributes = function(obj, attrs) {
	var s = this;
	if (!obj) return;
	JSKitLib.fmap(attrs, function(v, k) {
		obj[k] = function() { v.call(s, obj) };
	});
}

JSRVC.prototype.runScript = function(src, data, handlers) {
	var script = document.createElement('script');
	this.setElementAttributes(script, handlers);
	script.setAttribute("charset", "utf-8");
	script.setAttribute("src",  src + (data ? '?' + data : ''));
	this.requestsInProgress++;
	this.requestObj.target.appendChild(script);
	this.script = script;
}

JSRVC.prototype.processGETRequest = function(onCompleteCB, handlers) {
	var s = this;
	var ser = s.calcGetRequest();
	var reqperm = ser[0];
	var reqpermlen = reqperm.length;
	var reqvar = ser[1];
	var reqvarlen = reqvar.length;
	var currequest = '';
	for(var i=0; i<reqvarlen; i++) {
		currequest += '&' + reqvar[i];
		if(currequest.length + reqpermlen +
			(i+1<reqvarlen ? reqvar[i+1].length : 0) > 2000) {
			s.runScript(s.requestObj.uri,
				reqperm + currequest, handlers);
			currequest = '';
		}
	}
	if((currequest) || (!reqvarlen))
		s.runScript(s.requestObj.uri,
			reqperm + '&' + currequest, handlers);
	if(onCompleteCB) onCompleteCB();
}

JSRVC.prototype.processPOSTRequest = function(onCompleteCB, handlers) {
	var s = this;
	var req = s.requestObj.request;
	var reqvar = s.requestObj.variableRequest;
	var reqvarlen = s.requestObj.variableRequest.length;
	var createForm = function() {
		var iframe = 'js-ifrm-' + Math.random();
		var ifr = JSKitLib.createHiddenIframe(iframe, s.requestObj.target);
		var doc = ifr.contentDocument ? ifr.contentDocument : ifr.document;
		var f = doc.createElement('FORM');
		f.doc = doc;
		if(JSKitLib.isIE()) doc.charset = "utf-8";
		f.target = iframe;
		doc.body.appendChild(f);
		return f;
	};
	var getForm = function() {
		return (s.requestObj.form && !reqvarlen) ?
			s.requestObj.form : createForm();
	}
	var fillForm = function(form, obj) {
		form.method  = 'POST';
		form.enctype = "application/x-www-form-urlencoded";
		form.acceptCharset = 'UTF-8';
		form.action  = s.requestObj.uri;
		JSKitLib.fmap(obj, function(v, k) {
			var frmel = (form.doc || document).createElement('INPUT');
			frmel.type = "hidden";
			frmel.name = k;
			frmel.value = v;
			form.appendChild(frmel);
		});
	}
	var postRequest = function(pobj, vobj) {
		var form = getForm();
		fillForm(form, pobj);
		if(vobj) fillForm(form, vobj);
		if (form.target) s.setElementAttributes(document.getElementById(form.target), handlers);
		JSKitLib.fmap(handlers, function(v, k) {
			form[k] = v;
		});
		s.requestsInProgress++;
		form.submit();
	}
	JSKitLib.fmap(reqvar, function(v) {
		postRequest(req, v);
	});
	if(!reqvarlen) postRequest(req);
	if(onCompleteCB) onCompleteCB();
}

JSRVC.prototype.onLoadRequest = function(el) {
	var s = this;
	if(el.readyState && el.readyState != 'loaded'
		&& el.readyState != 'complete') return;
	el.onreadystatechange = el.onload = null;
	if(!s.requestObj.pickup) {
		s.requestObj.checked = true;
		s.requestsInProgress--;
	}
	s.postProcessRequest();
}

JSRVC.prototype.postProcessRequest = function(source, data) {
	var s = this;
	if(s.requestObj.pickup && source!="pickup") return;
	if(s.requestObj.randevu && !s.error && s.requestObj.transport == "POST") {
		s.processRequest({
			'uri': '//js-kit.com/api/server-answer.js',
			'ref': s.requestObj.ref,
			'epb': s.requestObj.epb,
			'pickup': true,
			'onreturn': s.requestObj.onreturn,
			'target': s.requestObj.target});
		return;
	}
	s.returnAnswer(data);
	if(!s.requestsInProgress) {
		if(s.timeoutTimer) clearTimeout(s.timeoutTimer);
		if(s.requestsQueue.length && !s.error)
			s.processRequest(s.requestsQueue.pop());
	}
}

JSRVC.prototype.eventCallback = function(eventName, randevuId, status, data) {
	if(this.requestId != randevuId) return;
	this.requestsInProgress--;
	if(this.script && this.script.parentNode) {
		this.script.parentNode.removeChild(this.script);
		this.script = undefined;
	}
	switch(status) {
	case "ready":
		if(this.eventCtx) {
			JSKW$Events.invalidateContext(this.eventCtx);
			this.eventCtx = undefined;
		}
		this.postProcessRequest("pickup", data);
		break;
	case "timeout":
		if(this.error) {
			this.returnAnswer(data);
		} else {
			this.processRequest(this.requestObj);
		}
		break;
	}
}

JSRVC.prototype.cancelRequest = function() {
	this.error = 'canceled';
}



/* Constants */
JSCC.DOMAIN = (window.location.protocol.substr(0, 4) != 'http' ? 'http:' : '')
              + '//js-kit.com';
JSCC.URI = JSCC.DOMAIN + '/comment';
JSCC.URI_AVATAR = JSCC.DOMAIN + '/avatar/';
JSCC.URI_IMAGE = JSCC.DOMAIN + '/image/';

/* JavaScript Comment Class */
new JSCC();

/* JSKitGlobal : App is ready */
$JSKitGlobal.setCommentsAppAvailable();

function JSCC(target, extra) {
	this.get = function(id) { return document.getElementById(id); }
	var idName = "js-kit-comments";
	var target = arguments.length ? arguments[0] : this.get(idName);
	if (target && target.jsk$initialized) return;

	this.cr = function(tag) { return document.createElement(tag); }
	var wl = window.location;
	this.uriDomain = JSCC.DOMAIN;
	this.uriAvatar = JSCC.URI_AVATAR;
	this.uriImage = JSCC.URI_IMAGE;
	this.uri = JSCC.URI;
	this.fieldDfl = {};
	this.TC = {};
	this.tmpID = 0;
	this.pathOverride = "";
	this.uniq = wl.pathname;
	this.objById = {};
	this.utmpl={};
	this.config = (extra?extra.config:null)||{};
	this.IM = this.config.nolc && extra && extra.sargs && extra.sargs.source=='profileIM' ? (extra.sargs['destProfile'] ? 'foreign' : 'own') : false;
	this.gen = 0;
	this.ctag = null;
	this.czidx = 300;
	this.stripecount = 2;
	var self = this;

	var cl = wl.hash.match(/^#(jsid-[0-9]+-?[0-9]*)$/i);
	this.comment_location = cl ? cl[1] : undefined;

	this.getData = function(domain, multiParams) {
		if(!multiParams.length) return;
		var wl = window.location;
		var req = {
			uri: JSCC.URI + 's-data.js',
			ref: wl.protocol + "//" + domain + wl.pathname,
			epb: JSKitEPB.getAsHash({}),
			request: this.comment_location ? {'jsid': this.comment_location} : {},
			variableRequest: multiParams,
			transport: 'GET',
			target: $JCA[$JCA.length-1].target
		};
		new JSRVC(req);
	}

	this.isStandalone = function() {
		return (this.config.standalone == 'yes');
	}

	this.scoringEnabled = function() {
		return ((this.config.scoring != 'no') && (this.serverOptions.scoring));
	}

	if(target) {
		this.jcaIndex = $JCA.length;
		$JCA.push(this);
		this.labelHTML = target.getAttribute("label");

		var cn = target.childNodes;
		for(var n=0;n < cn.length;n++) 
			this.utmpl[cn[n].className] = JSKitLib.getOuterHTML(cn[n]);
		if(cn.length) target.innerHTML = "";
		target.style.display = "block";
		target.style.visibility = "visible";
		var utsc = this.utmpl['js-singleComment'];
		if(utsc) this.dtComment = utsc;

		// Override
		var jovs = window.JSKit$Override;
		if(jovs) {
		  for(var i = jovs.length-1; i>=0; i--) {
			var fName = jovs[i][0];
			var func = jovs[i][1];
			this[fName] = func;
		  }
		}
	} else {
		if(!document.body){
			alert("Enclose the script in a <BODY></BODY> tag!");
			return;
		}
		var els = document.body.getElementsByTagName(idName);
		var oWay = false;
		if(els && els.length) oWay = true;
		else els = document.body.getElementsByTagName("div");

		var multiI = {};
		var multiQ = {};
		if(els && els.length) {
			for(var i=0; i < els.length;i++) {
				if(oWay || els[i].className.match(/js-kit-comments/)) {
					// Check to see if this div has already been processed
					if(els[i].jsk$initialized) 
						continue;

					var c = new JSCC(els[i], {'config': {'noDataRequest': true}});
					var p = c.config.path;
					var d = c.config.domain;

					if (!multiQ[d]) {
						multiQ[d] = [];
						multiI[d] = 0;
					}
					var params = {'jx': c.jcaIndex, 'p': p, 'srt': c.preq.srt,
						'ps': c.preq.ps, 'pn': c.preq.pn, 'sp': 1, 'gen': 0}; 
					if (c.preq.ord == 'desc') params.ord = 'desc';
					if (c.preq.thr != 'yes') params.prs = 'flat';
					if (c.config.moderate) params.mod = 1;
					multiQ[d].push(params);

					if(multiI[d] >= 1) { //temporary condition
						this.getData(d, multiQ[d]);
						multiQ[d] = [];
						multiI[d] = 0;
					} else {
						multiI[d]++;
					}
				}
			}
			JSKitLib.fmap(multiQ, function(v, k){ if (v) self.getData(k, v); });
			if($JCA.length) return;
		}
		this.jcaIndex = $JCA.length;
		$JCA.push(this);
		document.write('<div id="'+idName+'"></div>');
		target = this.get(idName);
	}
	target.jsk$initialized = true;
	target.className = idName;
	target.id = "";

	// Handling user configuration settings
	this.config = JSKitLib.readConfig("comments",
		target,
		this.config,
		'path',
		['avatars', 'yes'],
		['standalone', 'no'],
		['scoring', 'yes'],
		['paginate', 50],
		['backwards', this.config.nolc && !this.IM ? 'yes' : 'no'],
		['disabled', 'no'],
		'domain',
		['sort', ['date','karma','name','status','rating']],
		['thread', ['yes','no']],
		'adminBgColor',
		'flashColor',
		'moderate',
		'permalink',
		'skin',
		'noautoexpand',
		['smiles', 'no'],
		['editable', 'no']
	);
	this.uniq = this.config.path;
	this.pathOverride = this.config.path;
	this.config.thread = this.config.nolc && !this.IM ? 'no' : this.config.thread;
	this.config.domain = this.config.moderate || this.config.domain;
	this.config.noautoexpand = this.config.noautoexpand == 'yes';
	if(this.config.paginate <= 0) this.config.paginate = 200;
	if(target.getAttribute('backwards'))
		this.backwards = (this.config.backwards == 'yes');
	else if(target.getAttribute('paginate'))
		this.backwards = !!this.config.paginate;
	else
		this.backwards = !!this.config.nolc && !this.IM;
	this.preq = {
		srt:this.config.sort,
		ord:(this.backwards?'desc':'asc'),
		thr:this.config.thread,
		sp: 1, pn: 5, ps: this.config.paginate };
	if(!this.preq.ps) this.preq.ps = 100;
	this.preq.pn = Math.round(50 / this.preq.ps);
	if(this.preq.pn < 2) this.preq.pn = 2;

	self.target = target;

	this.runscr = function(url, args) {
		var sc = this.cr("script");
		sc.setAttribute("charset", "utf-8");
		sc.src = url + (args?"?"+args:"");
		this.target.appendChild(sc);
		return false;
	}

	this.server = function(ext, data, ajax, rvcparams) {
		if((self.serverFilter && !self.serverFilter(ext)) || self.config.disabled == 'yes') return;

		// ensure window.location is current (re:blogspot)
		var wl = window.location;
		var prms = data;
		JSKitLib.fmap(((extra||{})['sargs']||{}),
			function(v, k){ prms[k] = v; });
		var getAction = function(scr) {
			return scr.match(self.uriDomain) ? wl.protocol + scr: wl.protocol + self.uri + scr;
		};
		var action = getAction(ext);
		if(self.config.moderate) prms.mod = '1';
		prms = JSKitLib.appendExternalParams("comments", ext, prms);
		var req = {
			uri: action,
			ref: JSKitLib.getRef(self),
			epb: JSKitEPB.getAsHash({}),
			request: prms,
			target: self.target,
			randevu: !!ajax
		};
		if (rvcparams) JSKitLib.fmap(rvcparams, function(v, k) { req[k] = v; });
		new JSRVC(req);
	}

	this.getpages = function(sp, ap) {
		var preq = self.preq;
		if(!sp) sp = preq.sp;
		self.loading = (new Date()).valueOf();

		var prms = {"jx[0]": self.jcaIndex,
			"p[0]": self.config.path,
			"gen[0]": self.gen,
			"srt[0]": preq.srt,
			"ord[0]": preq.ord,
			"sp[0]": sp,
			"pn[0]": preq.pn,
			"ps[0]": preq.ps};
		if(preq.thr!='yes') prms['prs[0]']='flat';
		if(ap) JSKitLib.fmap(ap, function(v,k){ prms[k] = v ;});
		self.server("s-data.js", prms);
	}

	if (!this.config.noDataRequest) this.getpages();
}

JSKitLib.addCss(''
+ '.js-WelcomePanel { margin: 0px 0px 10px 0px; font: 12px Arial; text-align: left; }'
+ '.js-WelcomePanelBottom { margin: 10px 0px 0px 0px; }'
+ '.js-WelcomePanelTitle { padding-left: 7px; border-bottom: 1px solid #d1bea4; background: #e4d0b3; color: #fff; font: 14px Arial; font-weight: bold; line-height: 21px; }'
+ '.js-WelcomePanelClose { height: 21px; width: 20px; float: right; cursor: pointer; position: relative; top: 7px; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="//js-kit.com/images/welcome/close.png", sizingMethod="crop")' : 'background: no-repeat url(//js-kit.com/images/welcome/close.png);') + ' }'
+ '.js-WelcomePanelContent { padding: 18px 20px; background-color: #fffae4; color: #2e2e30; line-height: 21px; ' + (JSKitLib.isIE() ? 'zoom: 1' : '') + ' }'
+ '.js-WelcomePanelContentBlock a, .js-WelcomePanelContentBlock a:link, .js-WelcomePanelContentBlock a:visited, .js-WelcomePanelContentBlock a:hover, .js-WelcomePanelContentBlock a:active { text-decoration: none; color: #2e2e30; font: 12px Arial; white-space: nowrap; }'
+ '.js-WelcomePanelContentBlock a:hover, .js-WelcomePanelContentBlock a:active { text-decoration: underline; }'
+ '.js-WelcomePanelHeader { font: 16px Arial; font-weight: bold; color: #2e2e30; padding: 0px; line-height: 20px; ' + (JSKitLib.isIE() ? 'zoom: 1' : '') + ' }'
+ '.js-WelcomePanelContentBlock { float: left; padding-bottom: 5px; ' + (JSKitLib.isIE() ? 'zoom: 1' : '') + '}'
+ '.js-WelcomePanelContentBlock table img { vertical-align: middle; }'
+ '.js-WelcomePanelCtls { float: left; text-align: center; margin-top: 9px; line-height: 15px; }'
+ '.js-WelcomePanelCtls a, .js-WelcomePanelCtls a:active, .js-WelcomePanelCtls a:visited, .js-WelcomePanelCtls a:hover { color: #2e2e30; font: 11px Arial; }'
+ '.js-WelcomePanelArrow { height: 12px; }'
+ JSKitLib.fmap({Info: 'information', Reg: 'pencil', Profile: 'edit_profile', Help: 'help', Custom: 'bullet_wrench', Dashboard: 'dashboard', Twitter: 'twitter', Support: 'support', Widgets: 'widgets', Panel: 'admin_panel' }, function(v, k) {
	var paddingTop = (k == 'Info' || k == 'Reg' ? 4 : 1);
	var paddingLeft = (k == 'Info' || k == 'Reg' ? 23 : 25) - (JSKitLib.isIE() ? 2 : 0);
	return '.js-WelcomeImg' + k + ' { height: 16px; line-height: 16px; padding: ' + paddingTop + 'px 0px 0px ' + paddingLeft + 'px; float: left; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="//js-kit.com/images/welcome/' + v + '.png", sizingMethod="crop");' : 'background: url(//js-kit.com/images/welcome/' + v + '.png) no-repeat left center;') + ' }';
}).join('')
, 'welcome');

JSKitLib.addCss(""
+ ".js-CommentsSkin-smoothgray .js-commentInputName { margin-right: 110px; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + "}"
+ ".js-CommentsSkin-smoothgray .js-commentInputEmail { margin-right: 110px; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + "}"
+ ".js-CommentsSkin-smoothgray .js-commentInputUrl { margin-right: 110px; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + "}"
+ ".js-CommentsSkin-smoothgray .js-AuthAreaWrap { margin-right: 110px; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + "}"
+ ".js-CommentsSkin-smoothgray .js-CCButtons { margin: 0.3em 0 0.5em 5px; width: 100%;" + (JSKitLib.isIE() ? "zoom: 1; " : "") + "}"
+ ".js-authSelector { float: left; margin-bottom: 5px; }"
+ ".js-logoutSpan { display:none; margin-left: 5px;" + (JSKitLib.isIE() ? "zoom: 1; " : "margin-top: 3px; ") + "}", "AuthAreaWrap");

// Optionally leave all CSS up to template
if (!window.$JSKitNoCommentCss) {
	JSKitLib.addCss(''
	+ ".js-OldComments { margin-bottom: 1px; clear:both;}"
	+ ".js-LeaveComment { margin: 3pt 0; }"
	+ ".js-CreateComment, .js-EditComment { text-align: left; display: none; }"
	+ ".js-commentInputUrl { display: none; }"
	+ ".js-CCMore { padding-left: 3px }"
	+ ".js-commentOptions { float: left; }"
	+ ".js-commentPubOptions { float: left; padding: 2px 5px; }"
	+ ".js-commentYahooShareCheckbox { float: left; margin: " + (JSKitLib.isIE() ? "-3px" : "1px") + " 0 0 5px; }"
	+ ".js-commentYahooShareLabel {margin: 1px 3px 0 3px; line-height: 13px; float: left;}"
	+ ".js-commentYahooShareLabelLogo {margin: 1px 0 0 0; float: left; width: 49px; height: 13px; " + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="//js-kit.com/images/yahoo/yoslogo.png", sizingMethod="crop");' : 'background: no-repeat url(//js-kit.com/images/yahoo/yoslogo.png);') + " }"
	+ ".js-commentFBShareCheckbox { float: left; margin: " + (JSKitLib.isIE() ? "-3px" : "1px") + " 0 0 5px; }"
	+ ".js-commentFBShareLabel {margin: 1px 3px 0 3px; line-height: 13px; float: left;}"
	+ ".js-commentGFCShareCheckbox { float: left; margin: " + (JSKitLib.isIE() ? "-3px" : "1px") + " 0 0 5px; }"
	+ ".js-commentGFCShareLabel {margin: 1px 3px 0 3px; line-height: 13px; float: left;}"
	+ ".js-commentTwitterShareCheckbox { float: left; margin: " + (JSKitLib.isIE() ? "-3px" : "1px") + " 0 0 5px; }"
	+ ".js-commentTwitterShareLabel {margin: 1px 3px 0 3px; line-height: 13px; float: left;}"
	+ ".js-commentSubmit { text-align: right; }"
	+ ".js-CreateCommentBg { margin: 1em; padding: 0.5em; border: solid 1px #c0c0c0; text-align: left; float: left; }"
	+ ".js-EditComment .js-CreateCommentBg { float: none; border: none; padding: 0; }"
	+ ".js-CreateCommentArea { -moz-border-radius: 7px; -webkit-border-radius: 7px; padding: 5px 5px 5px 9px; }"
	+ ".js-CommentsArea .js-CreateCommentArea { background-color: #cbcbcb; }"
	+ ".js-OldComments { background-color: transparent; }"
	+ ".js-CreateCommentFieldsWrap { margin-left: -4px; background-color: #ececec; border: solid 1px #b0b0b0; padding: 4px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }"
	+ '.js-CreateCommentFields {zoom: 1; color: #404040; background-color: #f8f8f8; padding: 4px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }'
	+ ".js-PageNavTop { margin-bottom: 3px; }"
	+ ".js-PageNavBottom { margin-top: 3px; clear: both; }"
	+ ".js-PageNOther { text-decoration: none; }"
	+ ".js-PageNCur { font-weight: bold; }"
	+ ".js-PageArrowCur { opacity: 0.3; zoom:1; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30); }"
	+ ".js-commentFieldSubject { font-weight: bold; margin-bottom: 5px;}"
	+ ".js-commentFieldLabel { margin-top: 5px; clear:both; margin-right: 0.5em;}"
	+ ".js-pmFieldLabel { margin-top: 5px; clear:both; margin-right: 0.5em; text-align: left;}"
	+ ".js-commentFieldNote { font-family: Verdana; font-size: 7pt; color: #808080; }"
	+ ".js-siteAdmin { font-weight: bold; }"
	+ ".js-singleComment { zoom: 1; font-size: 8pt; font-family: Verdana, Helvetica; border: solid 1px #c0c0c0; text-align: left; margin-bottom: -1px; }"
	+ ".js-singleCommentBg { zoom: 1; padding: 0.3em; position: relative; }"
	+ '.js-singleCommentHeader { color: #484848; margin: 3px 0; }'
	+ '.js-singleCommentBody { clear: both; color: #404040; background-color: #fefefe; padding: 4px 4px 4px 8px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }'
	+ 'table.js-singleCommentBodyT { margin: 0; padding: 0; font-family: Verdana, Helvetica; text-align: left; font-size: 8pt; color: #404040; }'
	+ '.js-singleCommentQuote { position:relative; top: 4px; font-family: "Times New Roman"; font-size: 32px; line-height: 24px; padding-right: 1px; display: none; }'
	+ ".js-singleCommentINFO { color: #808080; float: right; padding: 3px; margin-left: 2em; text-align: right;}"
	+ ".js-singleCommentAvatar { float: right; }"
	+ ".js-singleCommentAvatarCell { text-align: right; }"
	+ ".js-singleCommentText { padding-top: " + (JSKitLib.isIE()?"0":"4") + "px; }"
	+ ".js-singleCommentName { font-weight: bold; }"
	+ ".js-singleCommentUrl { margin: 0px 0px 0px 2px; padding: 0px; border: 0px; width: 10px; height: 10px; display: none; }"
	+ ".js-singleCommentDate { font-size: 7pt; }"
	+ ".js-singleCommentOrigin { position: absolute; display: none; bottom: 0.3em; font-size: 7pt; color: #808080; }"
	+ ".js-singleCommentKarmaComMod { clear: both; }"
	+ ".js-singleCommentKarma { float: left; font-size: 7pt; color: #808080; margin-right: 1em; padding-top: 3px; }"
	+ ".js-singleCommentKarmaShow { float: left; font-size: 7pt; color: #808080; margin-right: 2em; padding-top: 3px; display: none; }"
	+ ".js-singleCommentKarmaScore { display: none; }"
	+ ".js-singleCommentComMod { float: left; font-size: 7pt; color: #808080; display: none; padding-top: 3px; margin-right: 1em; }"
	+ ".js-singleCommentCtls { float: right; white-space: nowrap; }"
	+ ".js-singleCommentMenu { float: left; margin: -4px 15px 0px 0px; " + (JSKitLib.isIE() ? "zoom: 1; " : "") + " white-space: nowrap; }"
	+ ".js-singleCommentMenuTitle { cursor:pointer; padding: 3px; white-space: nowrap; color: #476cb8; font-size: 11px; width: 100%; }"
	+ ".js-singleCommentMenuTitleMO { }"
	+ ".js-singleCommentMenuTitlePressed { }"
	+ ".js-singleCommentMenuTitleExpandMarker { width: 16px; height: 16px; margin: 2px 0px 0px -5px; }"
	+ ".js-singleCommentMenuContainer { border: 1px solid #E7E7E7; background-color: #FFFFFF; cursor:pointer; position: absolute; margin-left: -2px; -moz-border-radius: 4px; -webkit-border-radius: 4px; }"
	+ ".js-singleCommentMenuContainer table { border: 2px solid #D6E2E9; -moz-border-radius: 2px; -webkit-border-radius: 2px;}"
	+ ".js-singleCommentMenuRootContainer { margin: 0px; }"
	+ ".js-singleCommentMenuItem {border-top: 2px solid #FFFFFF; border-bottom: 2px solid #FFFFFF; line-height: 15px;}"
	+ ".js-singleCommentMenuItemIcon { width: 16px; height: 16px; margin: 2px 6px; }"
	+ ".js-singleCommentMenuItemTitle { margin: 5px 20px 4px 0px; color: #000000; font-size: 12px; font-family: Arial; text-decoration: none; white-space: nowrap; }"
	+ ".js-singleCommentMenuItemEnding { height: 16px; margin: 2px; font-size: 14px; color: #000000; display: inline; font-family: Arial; }"
	+ ".js-singleCommentMenuItemMO { background-color: #EDEDED; }"
	+ ".js-singleCommentMenuDelimeter { margin: 2px 0px; height: 1px; width: 100%; background-color: #CCCCCC; font-size: 1px; width: 100%; }"
	+ ".js-singleCommentMenuInput { line-height: 14px; font: 12px Arial; padding: 0px; border: 0px; height: 14px; margin: " + (JSKitLib.isIE() ? "4px" : "5px") + " 0px; width: 120px; position: absolute; }"
	+ 'div.js-singleCommentEdit, div.js-singleCommentReply, div.js-singleCommentDelete, div.js-singleCommentModerate { background: right top url(http://js-kit.com/images/button-clear.png) no-repeat; height: 16px; font-size: 8pt; line-height: 9px; color: #404040; cursor: pointer; float: left; margin: 0 0.5em 0 4px; }'
	+ 'div.js-singleCommentEdit div, div.js-singleCommentReply div, div.js-singleCommentDelete div, div.js-singleCommentModerate div { background: left top url(http://js-kit.com/images/button-clear.png) no-repeat; height: 16px; padding: 2px 4px 0px 5px; position: relative; left: -1px; float: left; }'
	+ ".js-singleCommentNotice { color: #ff0000; font-size: 8pt; }"
	+ ".js-commentControl { float: left; margin-right: 2em; }"
	+ '.js-commentFieldInput { border: solid 1px #7f99b9; width:' +(JSKitLib.isPreIE7()?'98%':'100%')+';}'
	+ '.js-commentFieldInputProfile { border: solid 1px #7f99b9; width:' +(JSKitLib.isIE()?'98%':'100%')+' !important;}'
	+ ".js-CmtButton { margin-right: 0.5em }"
	+ ".js-CCButtons { margin: 0.3em 0 0.5em 0 }"
	+ ".js-CCButtons INPUT { font-size: 8pt; }"
	+ ".js-poweredBy { margin-top: 2pt; margin-right: 2pt; color: #808080; font-size: 7pt; font-family: Verdana, Helvetica; }"
	+ ".js-poweredBy A { text-decoration: none; color: #8080a0 }"
	+ ".js-antispamBy { text-align: right; }"
	+ ".js-Progress { position: absolute; visibility: hidden; right: 5px; top: 5px; width: 15px; height: 15px; }"
	+ ".js-SettingsWindow { padding: 0.3em; border: solid 1px #cccccc; color: #404040; white-space: normal; font-family: Verdana, Helvetica; font-size: small; z-index: 400; }"
	+ ".js-SettingsWindowNolc { z-index: 14400 }"
	+ ".js-SettingsWindowHeader { text-align:center; padding: 5px 0; margin-bottom: 5px; background-color: #e6e9ec; font-size: 10pt; font-family: Verdana, Helvetica; color: #435362}"
	+ ".js-ControlBlockText, .js-ControlBlockTextDisabled {font-size: 8pt; text-align: left;}"
	+ ".js-ControlBlockButton {font-size: 8pt;}"
	+ ".js-ControlBlockTextDisabled {color: #808080}"
        + ".js-showBorder {border:ridge 2px #a0a0a0;}"
	+ ".js-hideBorder {border:solid 2px #fefefe;}"
	+ ".js-SearchTitle {margin-right: 5px;}"
	+ ".js-SearchWords {padding: 0px; margin-right: 5px; border-bottom: 1px dashed #0000ff}"
	+ ".js-uploadAvatarForm {margin-top: 0px;}"
	+ ".js-singleCommentConversationHead {padding: 0.3em; " + (JSKitLib.isIE() ? "margin-top: 36px !important;" : "margin-top: 26px !important;") + "}"
	+ ".js-singleCommentConversationChild {padding: 0.3em; margin-top: -1px !important}"
	+ ".js-Conversation {padding: 0.3em; position: relative; top: -20px; display: inline; }"
	+ ".js-ConversationWrapper { height: 0px; " + (JSKitLib.isIE() ? "overflow: hidden;" : "") + "}"
	+ ".js-TornPageTop { margin-left: -5px; margin-right: -5px; " + (JSKitLib.isIE() ? "height: 6px;" : "height: 11px; margin-top: -5px; background: url(//js-kit.com/images/tornPaperT.gif) no-repeat;") + " }"
	+ ".js-TornPageBottom { margin-left: -5px; margin-right: -5px; " + (JSKitLib.isIE() ? "height: 6px;" : "height: 11px; margin-bottom: -5px; background: url(//js-kit.com/images/tornPaperB.gif) no-repeat;") + " }"
	+ ".js-TornPageTopImg { " + (JSKitLib.isIE() ? (JSKitLib.isPreIE7() ? "position: absolute;" : "float: left;") : "") + " margin-top: -5px; height: 11px; width: 100%; }"
	+ ".js-TornPageBottomImg { " + (JSKitLib.isIE() ? (JSKitLib.isPreIE7() ? "position: absolute;" : "float: left;") : "") + " margin-bottom: -5px; height: 11px; width: 100%; }"
	+ ".js-TornPageDivider { margin-left: -5px; margin-right: -5px;" + (JSKitLib.isPreIE7()?"":"margin-bottom: -1px;") + " height: 22px; background-color: #CBCBCB; }"
	+ ".js-TornPageDividerTop { height: 10px; background-color: #ECECEC; border: solid 1px #b0b0b0; border-top-width: 0; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; margin-bottom: 6px; }"
	+ ".js-TornPageDividerBottom { height: 10px; background-color: #ECECEC; border: solid 1px #b0b0b0; border-bottom-width: 0; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; }"
	+ ".js-commentBodyLabel { clear: both; }"
        + ".js-CreateCommentFieldsBaseInfo { float: right; margin-bottom : 5px; width: 100%; }"
	+ ".js-commentCmtTextarea { clear: both; }"
	+ ".js-commentAvatar { position: relative; float: right; margin-left : -102px; border: 1px solid #c0c0c0; width: 100px; height:100px; }"
	+ ".js-commentAvatarArea { clear: both; margin : 5px 0px 10px 0px; }"
	+ ".js-CmtSpam { background: url(//js-kit.com/images/bio-hazard.gif) bottom right repeat-x; background-color: #ffffe0 !important; color: #404040; }"
	+ (JSKitLib.isIE() ? ".js-CreateComment { zoom: 1; }" : "")
        + ".js-imageWrap { width: 102px; height: 102px; margin-bottom: 3px;}"
        + ".js-previewImageDescr { width: 102px; left: 0px; bottom: 0px; }"
        + ".js-previewImage {position: relative; text-align: center; margin: 4px; float: left; width: 102px; }"

	+ ".js-all-previewImages {position: relative; margin-top: 15px; border-top: 1px solid #ececec; border-bottom: 1px solid #ececec;}"
	+ ".js-uploadImageButton { float: left; color: blue; cursor: pointer; }"
	+ ".js-previewImageTitle { background-color: #ececec; font-size: 7pt; float: left;}"
	+ ".js-uploadImageInputWrapper2 { margin: 0; padding: 0; position: absolute; top: 0px; left: 0px;}"
	+ ".js-uploadImageInputWrapper1 {position: relative;}"
	+ ".js-uploadGreyDescr { color: #c0c0c0; }"
	+ ".js-uploadImageIcon { height: 16px; vertical-align: "+(JSKitLib.isSafari()?"sub":"middle")+"; margin-right: 5px; }"
	, 'cmt');
	if(JSKitLib.isOpera()) JSKitLib.addCss("wbr:after{content:\"\\00200B\"}", 'wbr');
	else JSKitLib.addCss(".js-singleCommentTEXT{word-wrap:break-word}", 'wbr');

	JSKitLib.addCss(""
	+ ".js-CommentsSkin-smoothgray .js-OldCommentsWrap {zoom:1; margin-bottom: 1px; clear: both; background-color: #cbcbcb; -moz-border-radius: 7px; -webkit-border-radius: 7px; padding: 5px; }"
	+ ".js-CommentsSkin-smoothgray .js-OldComments { background-color: #ececec; border: solid 1px #b0b0b0; padding: 4px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }"
	+ ".js-CommentsSkin-smoothgray .js-singleComment { border-style: none; margin: 0px; " + (JSKitLib.isIE() ? "zoom:1;" : "") + "; background: transparent; }"
	+ ".js-CommentsSkin-smoothgray .js-PageNOther { font-weight: bold; color: #0066cc; text-decoration: none; } "
	+ ".js-CommentsSkin-smoothgray .js-PageNCur { color: #fe9600; } "
	+ ".js-CommentsSkin-smoothgray .js-OldComments .js-CreateCommentArea { background-color: transparent; }"
	+ ".js-CommentsSkin-smoothgray .js-OldComments .js-singleCommentName { color: #0066cc; }"
	+ ".js-CommentsSkin-smoothgray .js-singleCommentBody { clear: both; color: #404040; background-color: #fefefe; padding: 4px 4px 4px 8px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; " + (JSKitLib.isIE() ? "zoom:1;" : "") + "}"
	+ ".js-CommentsSkin-smoothgray .js-singleCommentCtls { float: right; }"
	, "comments-skin-smoothgray");
	JSKitLib.addCss(".js-CommentsSkin-haloscan .js-singleComment { font-size: 11px; font-family: Verdana, Helvetica; border: none; zoom: 0; }"
	+ ".js-CommentsSkin-haloscan .js-singleCommentCtls { float: right; white-space: nowrap; }"
	+ ".js-CommentsSkin-haloscan .js-singleCommentAvatar { padding-bottom: 1em }"
	+ ".js-CommentsSkin-haloscan .js-LeaveComment { text-align: center; }"
	+ ".js-CommentsSkin-haloscan .js-commentControl, .js-CommentsSkin-haloscan .js-commentTool, .js-CommentsSkin-haloscan .js-poweredBy, .js-CommentsSkin-haloscan .js-poweredBy div { display: inline; float: none; }"
	+ ".js-CommentsSkin-haloscan .js-antispamBy { display: block; }"
	+ ".js-CommentsSkin-haloscan .js-CreateCommentBg { width: 30em; margin-top: 1em; margin-left: auto; margin-right: auto; padding: 0.5em; text-align: left; float: none; border: none; }"
	+ ".js-CommentsSkin-haloscan .js-singleCommentBg { padding: 0em }"
	, "comments-skin-haloscan");
}

JSCC.prototype.setDefaultField = function(name,value) {
	var epbval = JSKitEPB.getValue(name);
	this.fieldDfl[name]= epbval == undefined ? value : epbval;
}

JSCC.prototype.addChild = function(to, what) {
	if (typeof(to) != 'object')
		return;

	if(arguments.length == 3 && arguments[2])
		to.insertBefore(what, to.firstChild);
	else
		to.appendChild(what);
}

JSCC.prototype.a = function() {
	var a = this.cr("a");
	a.href = "javascript:void(0);";
	for(var text = '', i = 0; i < arguments.length; i++)
		text += arguments[i];
	a.innerHTML += text;
	return a;
}

JSCC.prototype.text = function(div, text) {
	if(div.tagName == "INPUT") {
		div.value = text;
	} else {
		JSKitLib.removeChildren(div);
		div.appendChild(document.createTextNode(text));
	}
	return div;
}

JSCC.prototype.div = function(id) {
	var div = this.cr("div");
	for(var i = 1; i < arguments.length; i++) {
		var arg = arguments[i];
		switch(typeof(arg)) {
		case "string":
			this.addChild(div, document.createTextNode(arg));
			break;
		case "undefined":
			break;
		default:
		case "object":
			if(!arg) break;
			this.addChild(div, arg);
			break;
		}
	}
	if(id) {
		div.className = id;
		var idText = String(id);
		if(idText.charCodeAt(3) < 91)
			this.TC[idText] = div;
	}
	return div;
}

JSCC.prototype.dtComment
 = '<div class="js-singleComment">'
 + '<div class="js-singleCommentBg">'
 + '<div class="js-singleCommentAvatar"></div>'
 + '<div class="js-singleCommentINFO">'
   + '<span class="js-singleCommentName">{Name}</span>'
   + '<img class="js-singleCommentUrl" src="//js-kit.com/images/icon10-external-url.png" />'
   + '<div class="js-singleCommentDate">{Date}</div>'
 + '</div>'
 + '<div class="js-singleCommentRating" style="display:none;"></div>'
 + '<div class="js-singleCommentText">{Text}</div>'
 + '<div style="clear: both"></div>'
 + '<div class="js-singleCommentNotice">{Notice}</div>'
 + '<div class="js-singleCommentPreviewImage"></div>'
 + '<div class="js-singleCommentKarmaComMod">'
     + '<div class="js-singleCommentMenu"></div>'
     + '<div class="js-singleCommentKarma">{Label:Like this comment?}'
         + ' [<a class="js-singleCommentKarmaY">{Label:yes}</a>]'
         + ' [<a class="js-singleCommentKarmaN">{Label:no}</a>]'
     + ' <span class="js-singleCommentKarmaScore">({Label:Score}:'
     + ' <span class="js-singleCommentKarmaValue">0</span> {Label:byVotes}'
     + ' <span class="js-singleCommentKarmaVoters">0</span>)'
     + '</span>'
     + '</div>'
     + '<div class="js-singleCommentKarmaShow">{Label:Community assigned karma score}:'
     + ' <span class="js-singleCommentKarmaValueShow">0</span> {Label:byVotes}'
     + ' <span class="js-singleCommentKarmaVotersShow">0</span>'
     + '</div>'
   + '<div class="js-singleCommentCtls">'
     + '<span class="js-singleCommentReplyable">[<a class="js-singleCommentReply">{Label:reply}</a>]</span>'
     + '<span class="js-singleCommentDeletable"> [<a class="js-singleCommentDelete">{Label:delete}</a>]</span>'
     + '<span class="js-singleCommentEditable"> [<a class="js-singleCommentEdit">{Label:edit}</a>]</span>'
     + '<span class="js-singleCommentModeratable"> [<a class="js-singleCommentModerate">{Label:moderate}</a>]</span>'
   + '</div>'
 + '</div>'
 + '<br clear="all" />'
 + '</div>'
 + '</div>'
;

JSCC.prototype.dtComment2
 = '<div class="js-singleComment">'
 + '<div class="js-singleCommentBg">'
 + '<div class="js-singleCommentHeader">'
 + '<div style="float: left;">'
   + '<span class="js-singleCommentName">{Name}</span>'
   + '<img class="js-singleCommentUrl" src="//js-kit.com/images/icon10-external-url.png" />'
   + ' {Label::depth?replies:says}:'
 + '</div>'
 + '<div class="js-singleCommentDate" style="float: right;">{Age}</div>'
 + '<div style="clear: both"></div>'
 + '</div>'
 + '<div class="js-singleCommentBody">'
 + '<table border="0" width="100%" cellspacing="0" cellpadding="0" class="js-singleCommentBodyT">'
 + '<tr style="vertical-align: top"><td colspan="2" style="padding-bottom: 8px;">'
 + '<div class="js-singleCommentRating" style="display:none;"></div>'
 + '<div class="js-singleCommentText"><span class="js-singleCommentQuote">&#x201C;</span>{Text}</div>'
 + '<div class="js-singleCommentNotice">{Notice}</div>'
 + '<div class="js-singleCommentPreviewImage"></div>'
 + '</td><td class="js-singleCommentAvatarCell" width="{SO:maxAvatarWidth+4}" rowspan="2">'
 + '<div class="js-singleCommentAvatar"></div>'
 + '</td></tr><tr><td style="vertical-align: bottom">'
     + '<div class="js-singleCommentMenu"></div>'
     + '<div class="js-singleCommentKarma"><span>{Label:Like this comment?}</span>'
         + ' [<a class="js-singleCommentKarmaY">{Label:yes}</a>]'
         + ' [<a class="js-singleCommentKarmaN">{Label:no}</a>]'
     + ' <span class="js-singleCommentKarmaScore">({Label:Score}:'
     + ' <span class="js-singleCommentKarmaValue">0</span> {Label:byVotes}'
     + ' <span class="js-singleCommentKarmaVoters">0</span>)'
     + '</span>'
     + '</div>'
     + '<div class="js-singleCommentKarmaShow">{Label:Community assigned karma score}:'
     + ' <span class="js-singleCommentKarmaValueShow">0</span> {Label:byVotes}'
     + ' <span class="js-singleCommentKarmaVotersShow">0</span>'
     + '</div>'
 + '</td><td style="vertical-align: bottom;">'
   + '<div class="js-singleCommentCtls">'
     + '<span class="js-singleCommentReplyable"><div class="js-singleCommentReply"><div>{Label:reply}</div></div></span>'
     + '<span class="js-singleCommentDeletable"><div class="js-singleCommentDelete"><div>{Label:delete}</div></div></span>'
     + '<span class="js-singleCommentEditable"><div class="js-singleCommentEdit"><div>{Label:edit}</div></div></span>'
     + '<span class="js-singleCommentModeratable"><div class="js-singleCommentModerate"><div>{Label:moderate}</div></div></span>'
   + '</div>'
 + '</td></tr></table>'
 + '</div>'	// Body
 + '</div>'
 + '</div>'
;

JSCC.prototype.dtComment3
 = '<div class="js-singleComment"><div class="js-singleCommentBg">'
 + '<div class="MessageCell">'
 + '<a name="{ID}"></a>'
 + '<div class="former_p"><div class="js-singleCommentAvatar"></div>'
 + '<span class="js-singleCommentText">{Text}</span><br />'
 + '<div class="js-singleCommentPreviewImage"></div>'
 + '<span class="byline"><span class="js-singleCommentName">{Name}</span>'
 + '<img class="js-singleCommentUrl" src="//js-kit.com/images/icon10-external-url.png" /> '
 + '<span class="js-singleCommentEditable">'
 + '<a href="" class="js-singleCommentEdit" title="Edit comment">'
 + '<img src="//js-kit.com/images/halo-button-edit.png" title="Edit comment" alt="Edit comment" border="0">'
 + '</a>'
 + '</span>'
 + '<span class="js-singleCommentModeratable">'
 + '<a href="" class="js-singleCommentDelete" title="Delete comment">'
 + '<img src="//js-kit.com/images/halo-button-delete.png" title="Delete comment" alt="Delete comment" border="0">'
 + '</a>'
 + '</span>'
 + ' <span class="js-singleCommentDate">{Date}</span> - <span class="js-singleCommentDate">{Time}</span> | <a href="#{ID}" title="Link to this comment">#</a>'
 + '</span></div>'
 + '</div></div><div style="clear: both;"><hr /></div></div>'
;

JSCC.prototype.dtCreate
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentBg">'
 + '<div class="js-commentFieldSubject">{Label:leaveComment}</div>'
 + '<div class="js-AuthAreaWrap"></div>'
 + '<div class="js-commentFieldLabel">{Label:nicknameLabel}</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtName" size="32" maxlength="100"/></div>'
 + '<div class="js-commentInputUrl">'
 + '<div class="js-commentFieldLabel">{Label:url}</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtUrl" size="32" maxlength="100"/></div>'
 + '</div>'
 + '<div class="js-commentInputEmail">'
 + '<div class="js-commentFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtEmail" type="email" SIZE=32 /></div>'
 + '</div>'
 + '<div class="js-commentFieldLabel js-commentRatingDisplay">{Label:ratingLabel}</div>'
 + '<div class="js-commentFieldRating js-commentRatingDisplay"></div>'
 + '<div class="js-commentFieldLabel">{Label:commentLabel}</div>'
 + '<div><textarea class="js-commentFieldInput" name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-commentAvatarArea"></div>'
 + '<div class="js-commentImageArea"></div>'
 + '<div class="js-uploadImageInput"></div>'
 + '<div class="js-CCButtons">'
   + '<input type="submit" name="js-Cmtsubmit" class="js-CmtButton" VALUE="{Label:submit}">'
   + '<input type="reset" name="js-Cmtcancel" class="js-CmtButton" VALUE="{Label:cancel}">'
   + '<span class="js-CCMore">[<a class="js-commentMore">{Label:more}</a>]</span>'
 + '</div>'
 + '<div class="js-poweredBy js-antispamBy">(<a href="http://js-kit.com/comments?wow" target="js-kit">Powered by JS-kit</a>)</div>'
 + '<div class="js-poweredBy js-antispamBy">(Spam filtering by <a href="http://akismet.com/" target="akismet">Akismet</a>)</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.dtCreate2
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentArea">'
 + '<div class="js-commentFieldSubject" style="margin: 0">{Label:leaveComment}</div>'
 + '<div class="js-CreateCommentFieldsWrap">'
 + '<div class="js-CreateCommentFields">'
 + '<div class="js-commentAvatar"></div>'
 + '<div class="js-CreateCommentFieldsBaseInfo">'
 + '<div class="js-AuthAreaWrap"></div>'
 + '<div class="js-commentInputName">'
 + '<div class="js-commentFieldLabel">{Label:nicknameLabel}</div>'
 + '<div class="js-authContainer"><input class="js-commentFieldInput" name="js-CmtName" size="32" maxlength="100"/></div>'
 + '</div>'
 + '<div class="js-commentInputUrl">'
 + '<div class="js-commentFieldLabel">{Label:url}</div>'
 + '<div class="js-authContainer"><input class="js-commentFieldInput" name="js-CmtUrl" size="32" maxlength="100"/></div>'
 + '</div>'
 + '<div class="js-commentInputEmail">'
 + '<div class="js-commentFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div class="js-authContainer"><input class="js-commentFieldInput" name="js-CmtEmail" type="email" SIZE=32 /></div>'
 + '</div>'
 + '</div>'
 + '<div class="js-commentAvatarArea"></div>'
 + '<div class="js-commentFieldLabel js-commentRatingDisplay">{Label:ratingLabel}</div>'
 + '<div class="js-commentFieldRating js-commentRatingDisplay"></div>'
 + '<div class="js-commentFieldLabel js-commentBodyLabel">{Label:commentLabel}</div>'
 + '<div class="js-commentCmtTextarea"><textarea class="js-commentFieldInput" name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-commentImageArea"></div>'
 + '</div>' // Fields
 + '<div class="js-CCButtons">'
   + '<div class="js-uploadImageButton">'
    + '<img class="js-uploadImageIcon" src="//js-kit.com/images/picture_add.png"></img>{Label:addPicText}'
   + '</div>'
   + '<div class="js-commentPubOptions"></div>'
   + '<div class="js-commentOptions"><input type="button" class="js-commentMore" value="{Label:optionsD}" less="{Label:optionsU}" more="{Label:optionsD}"></input></div>'
   + '<div class="js-commentSubmit">'
   + '<input type="reset" name="js-Cmtcancel" class="js-CmtButton" VALUE="{Label:cancel}">'
   + '<input type="submit" name="js-Cmtsubmit" class="js-CmtButton" VALUE="{Label:submit}">'
 + '</div>'
 + '<div style="clear: both"></div>'
 + '</div>'
 + '<div class="js-uploadImageInputWrapper1">'
   + '<div class="js-uploadImageInputWrapper2">'
     + '<div class="js-uploadImageInput"></div>'
   + '</div>'
 + '</div>'
 + '<div class="js-poweredBy js-antispamBy">(<a href="http://js-kit.com/comments?wow" target="js-kit">Powered by JS-kit</a>)</div>'
 + '<div class="js-poweredBy js-antispamBy">(Spam filtering by <a href="http://akismet.com/" target="akismet">Akismet</a>)</div>'
 + '</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.dtCreate3
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentBg">'
 + '<div class="js-commentFieldSubject">{Label:leaveComment}</div>'
 + '<div class="js-AuthAreaWrap"></div>'
 + '<div class="js-commentFieldLabel">{Label:nicknameLabel}</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtName" size="32" maxlength="100"/></div>'
 + '<div class="js-commentInputEmail">'
 + '<div class="js-commentFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtEmail" type="email" SIZE=32 /></div>'
 + '</div>'
 + '<div class="js-commentInputUrl">'
 + '<div class="js-commentFieldLabel">{Label:url}</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtUrl" SIZE=32 /></div>'
 + '</div>'
 + '<div class="js-commentFieldLabel js-commentRatingDisplay">{Label:ratingLabel}</div>'
 + '<div class="js-commentFieldRating js-commentRatingDisplay"></div>'
 + '<div class="js-commentFieldLabel">{Label:commentLabel}</div>'
 + '<div><textarea class="js-commentFieldInput" name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-commentAvatarArea"></div>'
 + '<div class="js-commentImageArea"></div>'
 + '<div class="js-uploadImageInput"></div>'
 + '<div class="js-CCButtons"><input type="submit" name="js-Cmtsubmit" class="js-CmtButton" VALUE="{Label:submit}">'
 + '<input type="reset" name="js-Cmtcancel" class="js-CmtButton" VALUE="{Label:cancel}">'
 + '<span class="js-CCMore">[<a class="js-commentMore">{Label:more}</a>]</span>'
 + '</div>'
 + '<div class="js-poweredBy js-antispamBy">(<a href="http://js-kit.com/comments?wow" target="js-kit">Powered by JS-kit</a>)</div>'
 + '<div class="js-poweredBy js-antispamBy">(Spam filtering by <a href="http://akismet.com/" target="akismet">Akismet</a>)</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.dtProfileCreate
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentArea">'
 + '<div class="js-commentFieldSubject" style="margin: 0">{Label:leaveComment}</div>'
 + '<div class="js-CreateCommentFieldsWrap">'
 + '<div class="js-CreateCommentFields">'
 + '<div class="js-AuthAreaWrap"></div>'
 + '<div class="js-pmFieldLabel">{Label:nicknameLabel}</div>'
 + '<div><input class="js-commentFieldInputProfile" name="js-CmtName" size="32" maxlength="100"/></div>'
 + '<div>'
 + '<div class="js-pmFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div><input class="js-commentFieldInputProfile" name="js-CmtEmail" type="email" SIZE=32 /></div>'
 + '</div>'
 + '<div class="js-pmFieldLabel">{Label:commentLabel}</div>'
 + '<div><textarea class="js-commentFieldInputProfile" name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '</div>' // Fields
 + '<div class="js-CCButtons">'
 + '<div class="js-commentSubmit">'
 + '<input type="reset" name="js-Cmtcancel" class="js-CmtButton" VALUE="{Label:cancel}">'
 + '<input type="submit" name="js-Cmtsubmit" class="js-CmtButton" VALUE="{Label:submitPM}">'
 + '</div>'
 + '<div style="clear: both"></div>'
 + '</div>'
 + '</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.dtEditComment
 = '<div class="js-EditComment" style="display: none">'
 + '<div class="js-CreateCommentBg">'
 + '<div><textarea name="js-CmtTextEdit" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-CCButtons"><input type="submit" name="js-CmtsubmitEdit" class="js-CmtButton" VALUE="{Label:save}">'
 + '<input type="reset" name="js-CmtcancelEdit" class="js-CmtButton" VALUE="{Label:cancel}">'
 + '</div></div></div>'
;

JSCC.prototype.dtEditComment2
 = '<div class="js-EditComment" style="display: none">'
 + '<div class="js-CreateCommentArea">'
 + '<div class="js-CreateCommentFieldsWrap">'
 + '<div><textarea class="js-commentFieldInput" name="js-CmtTextEdit" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-CCButtons">'
 + '<div class="js-commentSubmit">'
 + '<input type="reset" name="js-CmtcancelEdit" class="js-CmtButton" VALUE="{Label:cancel}">'
 + '<input type="submit" name="js-CmtsubmitEdit" class="js-CmtButton" VALUE="{Label:save}">'
 + '</div>'
 + '<div style="clear: both"></div>'
 + '</div></div></div></div>'
;

JSCC.prototype.dtConversation
 = '<div class="js-ConversationWrapper">'
 + '<div class="js-Conversation">'
 + '{Label}<span class="js-ConversationName"><b>{Name}</b></span>'
 + '</div>'
 + '</div>'
;

JSCC.prototype.localDate = function(t) {
	if(!t) return "";
	var d = new Date(t * 1000);
	return d.toLocaleDateString();
}

JSCC.prototype.localTime = function(t) {
	if(!t) return "";
	var d = new Date(t * 1000);
	return d.toLocaleTimeString();
}

JSCC.prototype.localAge = function(t) {
	if(!t) return "";
	if(t)
	var d = new Date(t * 1000);
	var offset = d.getTimezoneOffset() * 60;
	var day = Math.ceil(((new Date()).valueOf() - offset * 1000) / 86400000) * 86400;
	var when = Math.floor((day - t + offset) / 86400);
	switch(when) {
	case 0: when = $JCL("Today"); break;
	case 1: when = $JCL("Yesterday"); break;
	default:
		if(when > 0 && when < 6)
			when = when + $JCL(" days ago");
		else
			when = d.toLocaleDateString();
	}
	return when + ", " + d.toLocaleTimeString();
}

JSCC.prototype.JCL = function(v) {
	return $JCL(
		(v == 'leaveComment') ? (this.labelHTML || v) : v
	);
}

JSCC.prototype.gtmpl = function(t, mObj) {
	var s = this;
	var lowercase = function(a, m) { return String(m).toLowerCase(); }
	t = t.replace(/^[^<]*(<[\s\S]*>)[^>]*$/, "$1");
	t = t.replace(/(<[\/]?[A-Z]+)/g, lowercase);
	if(mObj && mObj.ID) t = t.replace(/(<[a-z]+)/, '$1 id="' + mObj.ID + '"');
	t = t.replace(/{Label:([^:}]+[^}]*)}/g,
		function(a, m) { return s.JCL(m); });
	return t;
}
JSCC.prototype.tmpl = function(t, obj, dontPutId) {
	var self = this;
	t = self.gtmpl(t, dontPutId ? false : obj);
	t = t.replace(/{Age}/g, self.localAge(obj.TS));
	t = t.replace(/{Date}/g, self.localDate(obj.TS));
	t = t.replace(/{Time}/g, self.localTime(obj.TS));
	var text = String(obj.Text);
	if ((obj.status == 'M' || obj.status == 'H')
		&& (this.serverOptions.mmode == 'pre' || this.serverOptions.mmode == 'onhold' || (obj.msgtype && obj.msgtype.match(/T|P/)))) {
		text += (this.serverOptions.mtext || '');
	}
	text = text.replace(/^[ \s]+|[ \s]+$/, '');
	text = text.replace(/\n\n+/g, '\n\n');
	text = text.replace(/\n/g, '&nbsp;<br />');
	if(text.indexOf('<') == -1)
	text = text.replace(/([^&<>\s]{12})([^&<>\s]{12})/g, '$1<wbr></wbr>$2');
	text = text.replace(/{/g, '&#123;');
	t = t.replace(/{Text}/g, text);
	t = t.replace(/{Label:(:([a-z]+)\?([^:}]*):([^}]*))?([^}]*)}/g,
		function(a,b,p,f,s,m){
			if(p) m = (obj[p]?f:s)+m;
			return $JCL(m);
		});
	var d = {"SO:":this.serverOptions,"":obj};
	t = t.replace(/{([A-Z]+:)?([A-Za-z0-9]+)(\+\d+)?}/g,
		function(a,t,m,p){ var v = ((d[t]||obj)[m])||''; if(p) v = parseInt(v) + parseInt(p); return v; });
	return t;
}

JSCC.prototype.FRef = function(cmt, tgt, funcName) {
	if(!cmt || !tgt) return;

	var self = this;
	var args = arguments;

	tgt.href = "";
	tgt.onclick = function() {
	  try {
		var arr = [];
		if(cmt) arr.push(cmt.id);
		for(var i = 3; i < args.length; i++) arr.push(args[i]);
		self[funcName].apply(self, arr);
	  } catch(e) { ; }
		return false;
	}
}
JSCC.prototype.setCommentStyle = function(cmt, className) {
	var el = cmt.ctls['js-singleCommentBody'] || cmt;
	if(el) JSKitLib.addClass(el,className);
}

JSCC.prototype.cmtSetSpamStatus = function(cmt, s) {
	cmt.cobj.status = s ? 'S' : 'A';
	if(s) {
		this.setCommentStyle(cmt, "js-CmtSpam");
	} else {
		cmt.style.backgroundColor = "";
		cmt.style.backgroundImage = "";
		cmt.style.color = '';
	}
	if(cmt.domINFO) cmt.domINFO.style.backgroundColor = s ? '#ffffe0' : "";
}

JSCC.prototype.cmtSetOffensiveStatus = function(cmt, s) {
	cmt.cobj.status = s ? 'O' : 'A';
	if(s) {
		this.setCommentStyle(cmt, "js-CmtSpam");
	} else {
		cmt.style.backgroundColor = "";
		cmt.style.backgroundImage = "";
		cmt.style.color = '';
	}
	if(cmt.domINFO) cmt.domINFO.style.backgroundColor = s ? '#ffffe0' : "";
}

JSCC.prototype.blockAction = function(action) {
	var s = this;
	var cid = s.ctBlock.forId;
	var cmt = s.jspg.getItemById(cid).div;
	s.hideSettingsWindow('ctBlock');
	switch(action) {
	case "approve":
		s.cmtApprove(cid);
		break;
	case "approveuser":
		s.cmtApproveUser(cid);
		break;
	case "delete":
		s.cmtDelete(cid, 'delete');
		break;
	case "spam":
		s.cmtSetSpamStatus(cmt, true);
		if(s.config.moderate)
			s.pathOverride = cmt.cobj.path;
		s.server('.jnk',{'id': cid, 'jx': this.jcaIndex, "junk": "yes"});
		setTimeout(function() { // screen del
			s.cmtDelete(cid, 'ignore');
		}, 1000);
		break;
	case "ip":
	case "user":
		if(s.config.moderate)
			s.pathOverride = cmt.cobj.path;
		s.cmtDelete(cid, 'block_by_action', action);
		break;
	case "unban":
		if(s.config.moderate)
			s.pathOverride = cmt.cobj.path;
		s.cmtDelete(cid, action);
	}
}

JSCC.prototype.cmtBlock = function(cid) {
	var s = this;
	var cmt = s.jspg.getItemById(cid).div;
	var status = cmt.cobj.status;
	var msgtype = cmt.cobj.msgtype || '';
	var cmtreason;
	if (status && status=='S' && cmt.cobj.reason) {
		switch (cmt.cobj.reason) {
		case 'Blocked by User':
		case 'User':
			cmtreason = 'User';
			break;
		case 'IP':
		case 'Blocked by IP':
			cmtreason = 'IP';
			break;
		}
	}
	if(s.ctBlock) { s.hideSettingsWindow('ctBlock'); return; }
	if(!s.blockDom) { s.blockDom = {}; }
	if(!s.blockDom[status]) { s.blockDom[status] = {}; }
	if(!s.blockDom[status][cmtreason]) { var jca = '$JCA[' + s.jcaIndex + '].blockAction';
	var cb = function(a, d) {
		return '" class="js-ControlBlockButton" '+(d ? 'disabled="on"' : '')+'" onclick="this.blur();'+jca+"('"+a+'\');return false;" /></span></td></tr>';}
	var trth =  '<tr><td style="font-size: 9pt; background-color: #8192a2; color: #ffffff;"align=left><nobr>';
	var trtd = '</nobr></td></tr><tr><td class="js-ControlBlockText">';
	var trtdd = '</nobr></td></tr><tr><td class="js-ControlBlockTextDisabled">';
	var tinp = '<span style="float:right"><input type=submit value="';

	var mtrt = trtd, aumsg, ammsg;
	switch(status) {
	case 'A':
		mtrt = trtdd;
		aumsg = "This user has a trusted status";
		ammsg = "The message is not blocked";
		break;
	case 'S':
		aumsg = "Approve this and future messages from this user";
		ammsg = "This message is not spam or junk";
		break;
	case 'O':
		aumsg = "Approve this message";
		ammsg = "This message is not spam or junk";
	default: // M/H
		aumsg = "Approve future messages from this user";
		ammsg = "Accept this message as good";
	}

	var unbantext = trth + 'Unblock this commenter'
		+ trtd + 'Lift ban from this user/IP'
		+ tinp + 'Unban User'+cb('unban');

	s.blockDom[status][cmtreason] = JSKitLib.html('<table border="0" cellpadding="4" cellspacing="0">'
	+ (s.serverOptions.mmode != 'onhold' ? '' : (
		trth + 'Approve user' + trtd + aumsg
		+ tinp + 'Approve user' + cb('approveuser')))
	+ trth + 'Approve message'
	+ mtrt + ammsg
	+ tinp + 'Approve message' + cb('approve')
	+ trth + 'Delete unwanted comment'
	+ trtd + 'Get rid of comment without prejudice'
	+ tinp + 'Delete' + cb('delete')
	+ ((cmtreason == 'User' || cmtreason == 'IP') ?
		'' :
		trth + 'Flag as Spam or Junk'
		+ trtd + 'Train <a href="http://akismet.com">Akismet</a> to flag similar comments in the future'
		+ tinp + 'Spam/Junk' + cb('spam'))
	+ ((cmtreason == 'User') ?
		unbantext
		: trth + 'Block this commenter'
		+ trtd + 'Make comments from this user invisible to other users'
		+ tinp + 'Block User'+cb('user'))
	+ ((cmtreason == 'IP') ?
		unbantext
		: trth + 'Block commenter\'s IP'
		+ trtd + 'Make comments from this IP invisible to other users'
		+ tinp + 'Block IP'+cb('ip'))
	+ "</table>");
	}
	s.settingsWindow('ctBlock', cmt.domCtls || cmt.domINFO, s.blockDom[status][cmtreason]);
	s.ctBlock.forId = cid;
}
JSCC.prototype.cmtApprove = function(cid) {
	var cmt = this.jspg.getItemById(cid).div;
	if(cmt.cobj.status == 'S') {
		this.cmtSetSpamStatus(cmt, false);
		cmt.cobj.status = 'S'; // cmtDelete's deal
	}
	if(cmt.cobj.status == 'O') {
		this.cmtSetOffensiveStatus(cmt, false);
		cmt.cobj.status = 'O';
	}
	this.cmtDelete(cid, 'message');
}

JSCC.prototype.cmtApproveUser = function(cid) {
	var cmt = this.jspg.getItemById(cid).div;
	if(cmt.cobj.status == 'S') {
		this.cmtSetSpamStatus(cmt, false);
		cmt.cobj.status = 'S'; // cmtDelete's deal
	}
	this.cmtDelete(cid, 'user');
}

JSCC.prototype.routeMsg = function(fname, args) {
	var myRef = JSKitLib.getRef(this);
	var a = [this];
	var rtShared = {};
	for(var i = 0; i < $JCA.length; i++) {
		if($JCA[i].jcaIndex != this.jcaIndex
		&& JSKitLib.getRef($JCA[i]) == myRef &&
		!this.IM && !$JCA[i].IM)
			a.push($JCA[i]);
	}
	for(var i = 0; i < a.length; i++) {
		var e = a[i];
		e.rtShared = rtShared;
		if(i) e.serverFilter = function(n) {
			return (n == 's-data.js'); }
		e[fname].apply(e, args);
		delete e.serverFilter;
	}
}

JSCC.prototype.cmtDelete = function(cid, approvalMode) {
	this.routeMsg("cmtDeleteAct", arguments);
}

JSCC.prototype.cmtDeleteAct = function(cid, approvalMode, action) {
	var cmt = this.jspg.getItemById(cid).div;
	if(!cmt) {
		(this.objById[cid]||{}).status = 'D';
		this.jspg.deleteItem(cid);
		this.reCalcPages();
		return;
	}

	if(arguments.length == 1) approvalMode = 'delete';

	var oldStatus = cmt.cobj.status;
    
	if(this.config.moderate || (this.config.nolc && !this.IM))
		this.pathOverride = cmt.cobj.path;
	if(this.config.nolc && !this.IM)
		this.config.domain = cmt.cobj.domain;
	var prms = {'id': cid, 'jx': this.jcaIndex};
	if(this.inlineModeration) prms.inln = 1;
	switch(approvalMode) {
	case 'message':
		if(this.config.permalink) prms.permalink = this.config.permalink;
		if (!this.inlineModeration) {
			this.preHandlerDelete(cmt);
		}
		if(oldStatus == 'S') {
			prms.junk = 'no';
			this.server('.jnk', prms);
			cmt.cobj.action = 'unban';
		} else if(oldStatus == 'O') {
			this.server('-appr.cgi', prms);
		} else {
			prms.apr = 'message';
			this.server('.del', prms);
		}
		if (this.inlineModeration) this.postHandlerModerate(cid);
		break;
	case 'user':
		if (!this.inlineModeration) {
			this.preHandlerDelete(cmt);
		}
		prms.apr = 'user';
		if(oldStatus == 'S') prms.junk = 'no';
		this.server('.del', prms);
		if (this.inlineModeration) this.postHandlerModerate(cid);
		break;
	case 'delete':
		this.preHandlerDelete(cmt);
		delete prms.inln;
		this.server('.del', prms);
		break;
	case 'block_by_action':
		this.preHandlerDelete(cmt);
		prms.by = action;
		this.server('.blk', prms);
		cmt.cobj.action = 'ban';
		break;
	case 'unban':
		if (!this.inlineModeration) {
			this.preHandlerDelete(cmt);
		}
		if(this.config.permalink) prms.permalink = this.config.permalink;
		prms.unban = 1;
		this.server('-appr.cgi', prms);
		cmt.cobj.action = 'ban';
		if (this.inlineModeration) this.postHandlerModerate(cid);
		break;
	case 'ignore':
		/* Just delete from screen */
	default:
		this.removeComment(cmt, true);
	}
}

JSCC.prototype.preHandlerDelete = function(cmt) {
	JSKW$Events.syncBroadcast("comments_serverRequest_deleting", this.jcaIndex, cmt.cobj.ID);
}

JSCC.prototype.postHandlerDelete = function(cmt) {
	JSKW$Events.syncBroadcast("comments_serverRequest_deleted", this.jcaIndex, cmt.cobj.ID);
}

JSCC.prototype.removeComment = function(cmt, useRecursion) {
	var cobj = cmt.cobj;
	var deletedPageIdx = this.jspg.getPageByItemId(cobj.ID);
	if(cobj.ParentID && this.objById[cobj.ParentID]) {
		var prn = this.objById[cobj.ParentID];
		this.jspg.invalidateItemView(cobj.ParentID);
		var parentPageIdx = this.jspg.getPageByItemId(cobj.ParentID);
		this.jspg.invalidatePagesView(parentPageIdx, deletedPageIdx-parentPageIdx);
	} else {
		if(deletedPageIdx && cobj.ParentID) this.jspg.invalidatePagesView(deletedPageId-1, 1);
	}
	if(cobj.cedge) {
		var curItemIdx = this.jspg.getItemIdxById(cobj.ID);
		if((cobj.cedge==1 && !this.IM && typeof curItemIdx!='undefined') || (cobj.cedge==2 && typeof curItemIdx!='undefined')) {
			var itemIdxD = cobj.cedge==1 ? 1 : -1;
			var items = this.jspg.getItems(curItemIdx+itemIdxD, 1);
			if(items.length && items[0]) items[0].obj.cedge += cobj.cedge;
		}
	}
	var self = this;
	if(this.IM) {
		var cnt = 0;
		var deletedPageItems = this.jspg.getPageItems(deletedPageIdx);
		JSKitLib.fmap(deletedPageItems, function(V){
			if(V.obj.status!='D' && V.obj.status!='DT' && V.obj.conversation==cobj.conversation) cnt++;
		});
		if(cnt>1) {
			if(cmt.cobj.hasCnvs) {
				cmt.cobj.status = 'DT';
				this.jspg.invalidateItemView(cobj.ID);
			} else {
				this.jspg.deleteItem(cmt.cobj.ID);
			}
		} else if(cnt<=1){
			JSKitLib.fmap(deletedPageItems, function(V){
					if(V.obj.conversation==cobj.conversation) self.jspg.deleteItem(V.obj.ID);
			});
		}
	} else {
		this.jspg.deleteItem(cobj.ID);
		this.reCalcPages();
	}
	this.ctag = null;
	var pageNo = this.curPage;
	this.curPage = 0;
	this.displayPage(pageNo, function(immed){
			if(immed) {
				if(useRecursion && this.jspg.getItemById(cmt.cobj.ID)) {
					self.removeComment(cmt);
				}
			}
	});
}

JSCC.prototype.postHandlerModerate = function(cid) {
	var cmt = this.jspg.getItemById(cid).div;
	cmt.cobj.status = 'A';
	this.jspg.invalidateItemView(cid);
	var pageNo = this.curPage;
	this.curPage = 0;
	this.displayPage(pageNo);
}

JSCC.prototype.createCommentAsHTML = function(obj) {
	if(obj.status == 'D') return '';
	if(this.objppc) this.objppc(obj);
	return this.tmpl(this.dtComment, obj);
}

JSCC.prototype.markOffensive = function(cid) {
	if(confirm($JCL("isJunkVote"))) {
		if ((this.adminMode) && (!this.inlineModeration)) {
			this.cmtDelete(cid);
		} else {
			this.server('-mark.off',{'id': cid});
		}
	}
}

JSCC.prototype.showProfile = function(av, obj, profileLevel) {
	if((!obj.profile && !obj.ProfileURL) || !this.serverOptions.showProfile || $JSKitGlobal.isProfileLoaded == "no") return;
	if(obj.ProfileURL) {
		window.location = obj.ProfileURL;
		return;
	}
	av.cmtTarget = this.target;
	av.targetRef = JSKitLib.getRef(this);
	if (typeof($JSKitGlobal.isProfileLoaded) == "undefined") {
		$JSKitGlobal.isProfileLoaded = "no";
		window.jsk$prof$tgt = av;
		this.server(this.uriDomain + '/api/profile/get',
			{'target': 'jsk$prof$tgt', 'profile': obj.profile}, undefined, {"onreturn": function() { $JSKitGlobal.isProfileLoaded = "yes"; }});
	} else JSKW$openProfile(obj.profile, av, profileLevel); 
}

JSCC.prototype.fixComment = function(cmt, obj, pageIdx, globalIdx, itemsOnPage) {
	var self = this;

	self.objById[obj.ID] = obj;
	if(obj.status == 'D') {
		cmt.style.display = 'none';
		return;
	}

	if(obj.depth) {
		cmt.style.marginLeft = this.level4margin(obj.depth)
	} else {
		obj.depth = 0;
	}

	var ctls = JSKitLib.mapClass2Object({}, cmt);
	cmt.ctls = ctls;
	cmt.cobj = obj;
	var imgArea = cmt.ctls["js-singleCommentPreviewImage"];
	if (imgArea && cmt.cobj.imgs && cmt.cobj.imgs.length && self.config.uploadImages){ 
		self.addChild(imgArea,self.createImages(cmt.cobj.imgs));
		imgArea.style.display = "block";
	}

	var jsc = function(t){return ctls['js-singleComment'+t]}

	var stripe = jsc('Body') || jsc('');
	stripe.className += " js-singleCommentDepth" + (obj.depth || 0);
	if(!(cmt.style.display.match(/none/))){
		stripe.className += " js-comment-stripe-" + ((globalIdx % this.stripecount) + 1);
	}

	if(self.IM && typeof(obj.conversation)=='number') {
		if(obj.hasCnvs) {
			this.appendConversation(cmt, obj.conversation);
		} else {
			this.appendConversationChild(cmt);
		}
	}

	/* Handle avatars */
	if(obj.status!='DT' && obj.status!='DD') self.placeAvatar(obj, jsc('Avatar'));

	/* Handle if ratings are present */
	if (obj.Rating > 0 && ( ! this.isStandalone()) ) {
		var self = this;
		var action = function() {
			if (jsc('Rating')) {
				jsc('Rating').appendChild(self.createMiniStarObject(obj.Rating, 10));
				jsc('Rating').style.display = '';
				var clear = document.createElement('div');
				clear.style.clear = 'left';
				jsc('Rating').appendChild(clear);
			}
		}
		$JSKitGlobal.tryRatingsAppObjectAction(this.uniq, action);
	} else {
		if (jsc('Rating')) {
			jsc('Rating').style.display = 'none';
		}
	}

	if (jsc('Url') && obj.Url) { jsc('Url').style.display = ''; }

	var sa = jsc("Name");
	if(sa) {
		self.rerenderName(cmt);
		if(obj.admin) sa.className = sa.className + " js-siteAdmin";
	}
	var pl = jsc("ProfileLinkable");
	if(pl) {
		if(!(obj.profile && !this.config.nolc))
			pl.style.display = 'none';
	}

	if(!this.scoringEnabled()
	|| obj.yours || !obj.karma || (obj.msgtype && obj.msgtype.match(/T|P/) && !this.serverOptions.trackbackreply) || this.config.nolc) {
		var kA = jsc("Karma");
		if(kA) kA.style.display = "none";
	}
	var kS = jsc("KarmaScore");
	if(kS && obj.karma) {
		var kVal = jsc("KarmaValue");
		var kVot = jsc("KarmaVoters");
		if(obj.karma.votes) {
			self.text(kVal, obj.karma.score);
			self.text(kVot, obj.karma.votesText);
			kS.style.display = "inline";
		}
		var kY = jsc("KarmaY");
		if(kY) {
			kY.href = "";
			kY.onclick = function() {
				obj.karma.recomputeScore(1);
				self.text(kVal, obj.karma.score);
				self.text(kVot, obj.karma.votesText);
				kS.style.display = "inline";
				this.blur();
				return false;
			}
		}
		var kN = jsc("KarmaN");
		if(kN) {
			kN.href = "";
			kN.onclick = function() {
				obj.karma.recomputeScore(-1);
				self.text(kVal, obj.karma.score);
				self.text(kVot, obj.karma.votesText);
				kS.style.display = "inline";
				this.blur();
				return false;
			}
		}
	}
	var kSS = jsc("KarmaShow");
	if(kSS && obj.karma && obj.yours && obj.karma.votes) {
		kSS.style.display = "inline";
		var kVal = jsc("KarmaValueShow");
		var kVot = jsc("KarmaVotersShow");
		self.text(kVal, obj.karma.score);
		self.text(kVot, obj.karma.votesText);
	}

	if(this.serverOptions.commod && !obj.yours && !this.config.nolc && (!obj.msgtype || !obj.msgtype.match(/T|P/) || this.serverOptions.trackbackreply)){
		var cmO = jsc("ComMod");
		if(cmO){
			cmO.style.display = "inline";
			cmM = jsc("ComModMark");
			if(cmM) {
				cmM.href = "";
				cmM.onclick = function() {
					self.markOffensive(obj.ID);
					return false;
				}
			}
		}
	}

	if(this.config.nolc || this.config.moderate) {
		var cP = jsc("Origin");
		if(cP) {
			cP.style.display = "inline";
		}
	}
    /* FIXME(?) Lev, this.serverOptions are not defined in moderation mode
       but the result is likely as desired, i.e. admin can still reply */
	if (this.serverOptions.mmode == "pause" || (obj.msgtype && obj.msgtype.match(/T|P/) && !this.serverOptions.trackbackreply) || (this.config.nolc && (!this.IM || obj.yours))) {
		var rb = jsc("Replyable");
		if(rb) rb.style.display = "none";
	}

	this.FRef(cmt, jsc('Edit'), 'ShowCommentDialog', {isEditing: true});
	this.FRef(cmt, jsc("Reply"), "ShowCommentDialog");
	this.FRef(cmt, jsc("Delete"), "cmtDelete");
	this.FRef(cmt, jsc("Block"), "cmtBlock");
	this.FRef(cmt, jsc("Moderate"), "cmtBlock");
	this.FRef(cmt, jsc("Approve"), "cmtApprove");
	this.FRef(cmt, jsc("ApproveUser"), "cmtApproveUser");

	var au = jsc("ApproveUser");
	if (au && this.serverOptions.mmode != "onhold")
		au.style.display = "none";

	var hideCtl = jsc('Editable');
	if (hideCtl && (this.config.editable != 'yes' || this.config.nolc || (!(this.adminMode || JSKitEPB.isAdmin(this.pathOverride)))))
		hideCtl.style.display = 'none';

	var hideCtl = jsc("Deletable");
	if(hideCtl && ((!obj.yours && !this.IM && !JSKitEPB.isAdmin(this.pathOverride)) || (this.adminMode && !this.config.nolc)))
		hideCtl.style.display = "none";

	var hideCtl = jsc("Moderatable");
	if(hideCtl && (!this.adminMode || this.config.nolc))
		hideCtl.style.display = "none";

	cmt.bg = jsc('Bg');
	cmt.bg.style.zIndex = this.czidx - (pageIdx % this.czidx);
	cmt.domINFO = jsc('INFO');
	cmt.domCtls = jsc('Ctls') || jsc('Controls');

	if(obj.isEmbryonic) {
		/* Waiting for permanent ID */
		if(cmt.domCtls) cmt.domCtls.style.visibility = "hidden";
	}

	if(obj.status == 'S')
		this.cmtSetSpamStatus(cmt, true);

	if(obj.status == 'O')
		this.cmtSetOffensiveStatus(cmt, true);

	if(obj.admin) {
		JSKitLib.addClass(cmt, "js-commentByAdmin");
		if(this.config.adminBgColor) {
			cmt.style.backgroundColor = this.config.adminBgColor;
		}
	}

	if(obj.status == 'DT') {
		if(cmt.domINFO) cmt.domINFO.style.display = 'none';
		if(cmt.domCtls) cmt.domCtls.style.display = 'none';
	}
	if(obj.status == 'DD') {
		if(cmt.domCtls) cmt.domCtls.style.display = 'none';
		this.placeProcessAvatar(jsc('Avatar'));
	}
	if(jsc("Menu")) {
		if(!obj.menu) 
			obj.menu = self.addMenu(cmt, obj);
		if(obj.menu) 
			jsc("Menu").appendChild(obj.menu);
	}
}

JSCC.prototype.level2margin = function(level) {
	if(level < 20) return "10px";
	if(level < 40) return "4px";
	return "0px";
}
JSCC.prototype.level4margin = function(level) {
	if(level <= 20) return (10 * level) + 'px';
	if(level <= 40) return (200 + 4 * level) + 'px';
	return '280px';
}
JSCC.prototype.cmtInDiv = function(div, obj, fincb) {
	JSKW$Events.syncBroadcast("smileys-newCommentInDiv", obj);
	if (!obj.isEditing) {
		var cIdx, insBefore = false;
		if(this.preq.ord == 'desc') {
			var fitem = this.jspg.getFirstItem();
			if(fitem) {
				cIdx = fitem.obj.ID;
				insBefore = true;
			}
		}
		if(this.preq.thr != 'yes') {
			obj.Notice = $JCL('commentMoveNotice');
			cIdx = obj.ParentID || cIdx;
			delete obj.ParentID;
			delete obj.depth;
		}
		obj.cedge = 3;
		if(obj.ParentID) {
			obj.cedge = 0;
			var prn = this.objById[obj.ParentID];
			var td = (prn && prn.depth) ? prn.depth : 0;
			if(prn) {
				if(!obj.depth) {
					prn.thread.push(obj);
					obj.depth = 1 + td;
				}
				if(this.IM && typeof(prn.conversation)=='number') obj.conversation = prn.conversation;
				cIdx = this.getLastReply(obj.ParentID).obj.ID;
				insBefore = false;
				var curItem = this.jspg.getItemById(cIdx);
				if(curItem && curItem.obj.cedge>1) {
					obj.cedge = 2;
					curItem.obj.cedge -= 2; 
					var parentPageIdx = this.jspg.getPageByItemId(obj.ParentID);
					var insertedPageIdx = this.jspg.getPageByItemId(cIdx);
					this.jspg.invalidatePagesView(parentPageIdx, insertedPageIdx-parentPageIdx+1);
				}
			}
		}
	
		if(this.IM) {
			for(var i=0; i<this.conversations.length; i++) {
				if(this.conversations[i].current) {
					obj.conversation = i;
					break;
				}
			}
			if(typeof(obj.conversation)!='number') {
				this.conversations.push({'direction':'out'});
				obj.waitConversation = {cnvsIdx: this.conversations.length-1};
			}
		}
	
		this.jspg.addNewItem(obj, cIdx, insBefore);
	}
	var pn = this.jspg.getPageByItemId(obj.ID);
	var item = this.jspg.getItemById(obj.ID);
	if (obj.isEditing) {
		item.obj.Text = obj.Text;
		item.obj.goesInto = obj.goesInto;
		this.jspg.invalidateItemView(obj.ID);
	}
	if(pn+1==this.curPage) this.curPage = 0;
	var self = this;
	this.displayPage(pn+1, function(immed) {
		if(immed) {
			if(!item.div) {
				self.cmtInDiv(undefined, obj, fincb);
			} else {
				fincb.apply(this, [item.div]);
			}
		}
		delete item.obj.isEditing;
	});
}

JSCC.prototype.setOpacity = function(div, val) {
	if(div) {
		div.style.opacity = val;
		div.style.filter = 'alpha(opacity: ' + Math.round(val * 100) + ')';
	} else {
		if(document.body.filters)
			return 'zoom:1;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=' + Math.round(val * 100) + ');';
		else
			return 'opacity: ' + val + ';';
	}
}

JSCC.prototype.flash = function(cmt) {
	if(!cmt) return;

	var self = this;
	cmt.scrollIntoView(true);
	var bg = cmt.bg;

	try {
		bg.style.backgroundColor = self.config.flashColor || "#ffff00";
		self.setOpacity(bg, 0);
	} catch(e) { return; }

	cmt.cntDown = 3.14 / 2;
	cmt.cntMode = 0;

	cmt.intvl = setInterval(function() {
		cmt.cntDown -= cmt.cntMode ? 0.5 : 0.3;
		if(cmt.cntDown > 0) {
			if(cmt.cntMode)
				var c = Math.sin(cmt.cntDown);
			else
				var c = Math.cos(cmt.cntDown);
			self.setOpacity(bg, c);
		} else if(cmt.cntMode) {
			clearInterval(cmt.intvl);
			cmt.intvl = null;
			bg.style.backgroundColor = "";
			self.setOpacity(bg, 1);
		} else {
			cmt.cntMode = 1;
			cmt.cntDown = 3.14 / 2;
		}
	}, 100);
}

JSCC.prototype.foldInputFields = function(e, acc, f) {
  if(e.getAttribute) {
	var name = e.getAttribute('NAME');
	if(name && (name.substr(0, 6) == 'js-Cmt')) {
		var shortName = name.substr(6);
		acc = f.call(this, e, acc, shortName) || acc;
	}
  }
  var cn = e.childNodes;
  if(cn) {
	var clen = cn.length;
	for(var i = 0; i < clen; i++)
		acc = this.foldInputFields(cn[i], acc, f);
  }
  return acc;
}

JSCC.prototype.inputFieldsMsg = function(ctl, cmtObj, pText) {
	return this.foldInputFields(ctl, [], function(e, a, name){
		if (e.jsk$not_specified) return;
		var isText = /^Text(Edit)?$/.test(name);
		var text = isText ? pText : e.value;
		a.push({"Name": "js-Cmt" + name, "Value": text});
		if(isText && this.serverOptions.htmlMode)
			text = text.replace(/<[\/]?[a-z]{1,3}(\s+(href)=[^>]+)?>/g, '');
		//text = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
		cmtObj[name] = text;
	});
}

JSCC.prototype.cmtInPlace = function(cobj, fincb) {
	var div = this.TC["js-OldComments"];
	var shar = this.rtShared;
	if(shar) {
		if(shar.goesInto) shar.goesInto.push(this);
		else shar.goesInto = [this];
		cobj.goesInto = shar.goesInto;
	}
	if (!cobj.isEditing) {
		this.tmpID++;
		cobj.ID = "jst-" + this.tmpID;
		cobj.isEmbryonic = true;
	
		cobj.status = 'A';
		if(this.serverOptions.showProfile) cobj.profile = this.serverOptions.profile;
		if(this.avatarsManagement) {
			var avt = this.avatarsManagement.getActiveAvatar();
			if (avt) {
				cobj.avatar = avt.name;
				cobj.avatarWidth = avt.width;
				cobj.avatarHeight = avt.height;
			}
		}
		cobj.thread = [];
		cobj.depth = 0;
		cobj.admin = this.adminMode;
		var d = new Date();
		cobj.TS = Math.round(d.valueOf() / 1000);
	} else {
		cobj.Text = cobj.TextEdit;
		delete cobj.TextEdit;
 	}
	cobj.jcaIndex = this.jcaIndex;
	this.cmtInDiv(div, cobj, function(cmt) {
		if(cmt) this.flash(cmt);
		fincb.apply(this, [cmt]);
	});
}

JSCC.prototype.ShowCommentDialog = function(msgId, extra) {
	msgId = msgId || '';
	this.forMsg = this.objById[msgId];
	extra = extra || {};

	var isReply = !!msgId;
	var cct = this.TC["js-LeaveComment"];

	/* Remove dialog from sight */
	this.CommentCancelled();

	if(this.getSkin()!='smoothgray'){
		this.onAddImgButton(this.imgShow);
	}

	var ccd = this.TC[extra.isEditing ? "js-EditComment" : "js-CreateComment"];
	if (extra.isEditing) {
		this.TC['js-CmtTextEdit'].value = this.forMsg.originalText || JSKitLib.htmlUnquote(this.forMsg.Text.replace(/<wbr><\/wbr>/g, ''));
		isReply = false;
		if (!this.serverOptions.wysiwyg) {
			JSKW$Events.syncBroadcast("smileys-beforePostNewComment", this.TC['js-CmtTextEdit']);
		}
	}
	this.replyForId = (isReply ? msgId : '');

	var placeDialog = function(immediate, apl) {
		if (!apl) apl = [this.TC["js-CommentsArea"], this.TC["js-CommentsArea"].firstChild];
		if(msgId){
			apl[0].insertBefore(ccd, apl[1]);
		} else if (this.backwards) {
			apl[0].insertBefore(ccd, this.TC['js-WelcomePanel'] ? apl[1].nextSibling : apl[1]);
		} else {
			this.addChild(apl[0], ccd);
		}
		if (extra.isEditing) JSKitLib.hide(apl[1]);

		if(this.backwards && msgId)
			cct.style.visibility = "hidden";
		else
			cct.style.display = "none";
		ccd.style.display = "block";
		try {
			var name_suffix = (extra.isEditing ? 'Edit' : '');
			var text = this.TC["js-CmtText" + name_suffix];
			/* TinyMCE support (A) */
			if(!text.id) text.id = "js-CmtText" + name_suffix + "-" + this.jcaIndex;
			if(!text.richEditor && this.serverOptions.wysiwyg) try {
				var s = this; 
				var addMCECtrl = function(){
					if(s.tmce.foreign) tinyMCE.settings = s.tmce.cfg;
					tinyMCE.execCommand('mceAddControl', false, text.id);
					text.richEditor = true;
					if(text.mceLoadedCtx) {
						JSKW$Events.invalidateContext(text.mceLoadedCtx);
						text.mceLoadedCtx = null;
					}
				}
				if(window.tinyMCE) {
					if(tinyMCE.getInstanceById(text.id) == null) addMCECtrl();
				} else text.mceLoadedCtx = JSKW$Events.registerEventCallback(undefined, addMCECtrl, "mceLoaded");
			} catch(e) {}

			var sub = this.TC["js-Cmtsubmit" + name_suffix];
			var can = this.TC["js-Cmtcancel" + name_suffix];
			var prev = function(e){JSKitLib.stopEventPropagation(e); JSKitLib.preventDefaultEvent(e); return false;}

			if(JSKitLib.isOpera()) {
				var onkey = function(){};
			} else if(JSKitLib.isIE()) {
				var onkey = function(d,f){d.onkeydown=f};
			} else {
				var onkey = function(d,f){d.onkeypress=f};
			}

			/* combined ratings */
			var commentRatingElements = JSKitLib.getElementsByClass(ccd, "js-commentRatingDisplay");
			var commentRatingDisplay = 'none';
			this.submitRating = false;
			if (this.hasRatingsAppObject() && ( ! isReply)) {
 				if (this.TC["js-commentFieldRating"]) {
 					this.embedRatingsAppObject(this.TC["js-commentFieldRating"]);
 					commentRatingDisplay = '';
					this.submitRating = true;
				}
			}
			for (var i=0; i < commentRatingElements.length; i++) {
				commentRatingElements[i].style.display = commentRatingDisplay;
			}


			var flds = this.foldInputFields(ccd, [],
			function(e, a, name) {
				var dfl = this.fieldDfl[name];
				if(dfl) {
					if(e.jsk$setdfl)
						e.jsk$setdfl(dfl);
					else if(!e.value)
						e.value = dfl;
				}
				var aclen = a.length;
				if(e.richEditor) {
					if (e.value) {
						e.value = e.value.replace(/^\n\n+/, '');
						e.value = e.value.replace(/\n\n+/g, '</p><p>');
						if(!e.value.match(/^<p>(\n|.)*<\/p>$/)) e.value = '<p>' + e.value + '</p>';
					}
					var o = { focus: function() {
						var setupFocusing = function(ed) {
							var focus = function(){tinyMCE.execCommand('mceFocus',false,text.id);};
							var delayFocus = function(){setTimeout(focus, 10)};
							if(!extra.nofocus) {
								if(ed.initialized) focus();
								else ed.onInit.add(delayFocus);
							};
							var keyHandler = function(ed, e) { 
								if(e.keyCode != 9) return true;
								window.focus();
		try {
								a[aclen+(e.shiftKey?-1:1)].focus();
		} catch(ex) { ; }
								return prev(e);
							};
							if (JSKitLib.isIE()) ed.onKeyDown.add(keyHandler); else ed.onKeyPress.add(keyHandler);
						}
						var ed = tinyMCE.getInstanceById(text.id);
						if(ed) {
							setupFocusing(ed);
						} else {
							var t = setInterval(function() {
								var ed = tinyMCE.getInstanceById(text.id);
								if(ed) { clearInterval(t); setupFocusing(ed); }
							}, 100);
						}
					} };
					if(aclen) onkey(a[aclen-1], function(e) { 
						e = e || window.event; 
						if(e.keyCode == 9 && !e.shiftKey) { 
							this.blur();
							o.focus(); 
							return prev(e); 
						}
					});
					a.push(o);
				} else {
					a.push(e);
				}
			});

			var okd = function(offset) { return function(e) {
				e = e || window.event;
				if(e.keyCode != 9) return true;
				this.blur();
				flds[offset+(e.shiftKey?(flds.length-2):0)].focus();
				return prev(e);
			} }

			onkey(flds[flds.length-1], okd(0));
			onkey(flds[0], okd(1));

			// Place initial focus.
			if(!extra.nofocus) {
				for(var i = 0; i < flds.length; i++)
					if(!flds[i].value || flds[i].type == 'submit') {
						flds[i].focus();
						break;
					}
				sub.scrollIntoView(false);
			}
		} catch(e) { }
	};
	if(!msgId) {
		placeDialog.apply(this,[true]);
	} else {
		if (extra.isEditing) {
			var item = this.jspg.getItemById(msgId);
			item.obj.isEditing = true;
			this.editingCmt = item.div.ctls['js-singleCommentText'];
		} else {
			var item = this.getLastReply(msgId);
		}
		var pn = this.jspg.getPageByItemId(item.obj.ID);
		this.displayPage(pn+1, function(immed) {
				if(immed) {
					if (extra.isEditing) {
						placeDialog.apply(this, [true, [this.editingCmt.parentNode, this.editingCmt]]);
					} else {
						var pItem = this.jspg.getItemById(item.obj.ID);
						placeDialog.apply(this, [true, [pItem.div.parentNode, pItem.div.nextSibling]]);
					}
				}
			});
	}
	return false;
}

JSCC.prototype.CommentCancelled = function() {
	if(this.tmce && (this.serverOptions.media || this.serverOptions.smiley)) 
		this.tmce.cfg.closePopups();
	var cct = this.TC["js-LeaveComment"];
	var ccd = [this.TC["js-EditComment"], this.TC["js-CreateComment"]];
	if (cct) {
		cct.style.visibility = "";
		cct.style.display = "";
	}
	var name_suffix = (this.editingCmt ? 'Edit' : '');
	var text = this.TC["js-CmtText" + name_suffix];
	if(text && text.richEditor) {
		try {
		tinyMCE.execCommand('mceRemoveControl', false, text.id);
		} catch(e) { ; };
		text.richEditor = false;
		if(text.mceLoadedCtx) {
			JSKW$Events.invalidateContext(text.mceLoadedCtx);
			text.mceLoadedCtx = null;
		}
	}
	var s = this;
	JSKitLib.fmap(ccd, function(el, i){
		el && el.parentNode && el.parentNode.removeChild(el);
	});
	if (this.editingCmt) {
		JSKitLib.show(this.editingCmt);
		delete this.editingCmt;
	}
	return false;
}

JSCC.prototype.smileTag = function(smile) {
	var proto = (/^(http)(.*)/i.test(this.uriDomain) ? '' : 'http:'); 
	return '<img src="' + proto + this.uriDomain + '/extra/tiny_mce/plugins/emotions/img/smiley-' + smile.file + '" title="' + smile.title + '" border="0" alt="' + smile.title + '" />';
}

JSCC.prototype.textSmiles2Graphical = function(text, reverse) {
	var s = this;
	if(window.tinyMCE) tinyMCE.settings.smiley = false;
	var flag = true;
	var orig = text;
	JSKitLib.fmap(s.smiles, function(el, i){
		text = reverse ? text.replace(el.regexpTag, ' ' + i + ' ') : text.replace(el.regexpText, function($0, $1){return ($1 ? $0 : s.smileTag(el));});
		if(window.tinyMCE && flag && (text !== orig)) {
			tinyMCE.settings.smiley = true;
			flag = false;
		}
	});
	return text;
}

JSCC.prototype.thirdPartyImport = function(KVLMsg) {
	var s = this;
	var text = JSKitLib.stripTags(KVLMsg['js-CmtText']);
	var permalink = KVLMsg['permalink'] || s.config.permalink;
	var reg = RegExp("^http(.)?://(.*?)/");
	var m = reg.exec(permalink);
	var domain = (m && m.length>1) ? m[2] : s.config.domain;
	var share_data = {
			'domain': domain,
			'permalink': permalink,
			'Text': text
	};
	var createTargetDiv = function() {
		var tgt;
		tgt = 'div-sharing-' + Math.random();
		var div = document.createElement('DIV');
		div.id = div.name = tgt;
		div.style.disply = 'none';
		div.style.height = 0;
		div.style.width = 0;
		s.target.appendChild(div);
		return tgt;
	}
	if(s.serverOptions.facebook_api_key && KVLMsg['js-CmtFBShare']=='on') {
		var jsk$fb = new JSKitFB(JSKitLib.getRef(s),
			createTargetDiv(),
			s.serverOptions.facebook_api_key,
			s.serverOptions.facebook_xd_receiver, undefined,
			{'template': s.serverOptions.facebook_template,
			'comment_data': share_data});
	}
	if(s.serverOptions.gfc_site && KVLMsg['js-CmtGFCShare']=='on') {
		var jsk$gfc = new JSKitGFC(JSKitLib.getRef(s),
			createTargetDiv(),
			s.serverOptions.gfc_site,
			function(){
				this.sharedata = share_data;
				this.shareComment();
			});
	}
}

JSCC.prototype.CommentSubmitted = function() {
	var prn = this.forMsg;
	var isEditing = prn && prn.isEditing;

	if (!isEditing && !this.TC['js-CmtName'].value) {
		alert($JCL('nicknameRequired'));
		return;
	}
	
	/* TinyMCE support (B) */
	var name_suffix = (isEditing ? 'Edit' : '');
	var text = this.TC["js-CmtText" + name_suffix];
	var textValue;
	if(text.richEditor) {
		tinyMCE.triggerSave(false, false);
		JSKW$Events.syncBroadcast("smileys-beforePostNewComment", text);
		textValue = String(text.value).
                                replace(/(<\/p>)[\r\n]+(<p>)/g, '$1$2').
				replace(/<p>/g, '\n').replace(/<\/p>/g, '').replace(/<br\s?\/?>/g, '\n');
	} else {
		textValue = String(text.value).replace(/&/g, '&amp;');
	}

	var textMsg = encodeURIComponent(textValue);

	if(!textMsg || !textMsg.length) {
		alert($JCL("tooShort"));
		return;
	}

	var mcl = this.serverOptions.maxCommentLength || 3000;
	if(text.value.length > mcl) {
		alert($JCL("tooLong",{"maxCommentLength":mcl}));
		return;
	}

	if (this.adminFirstMsgMode) {
		var cmtEmail = this.TC['js-CmtEmail'];
		if (cmtEmail) {
			var cmtEmailDefMsg = $JCL("emailFirstNote");
			if (cmtEmail.value == cmtEmailDefMsg || cmtEmail.value.indexOf('@') < 0) {
				if (confirm($JCL("emailRequired"))) {
					cmtEmail.value = cmtEmailDefMsg;
					cmtEmail.style.color = '#FF0000';
					cmtEmail.style.fontWeight = "bold";
					return;
				}
			} else {
				if (!confirm(cmtEmail.value + " " + $JCL("emailConfirmation"))) {
					return;
				}
			}
		}
	}
	
	var form = this.TC[isEditing ? "js-EditComment" : "js-CreateComment"];

        var avt = this.avatarsManagement ? (this.avatarsManagement.getActiveAvatar() || 'no') : null;
	var permalink = this.config.permalink;
	var moderate = this.config.moderate;

	var tmpObj = {yours:true};
	if(prn) {
		if (isEditing) {
			tmpObj.ID = prn.ID;
		} else {
			tmpObj.ParentID = prn.ID;
		}
		tmpObj.path = prn.path;
		if(prn.permalink) {
			tmpObj.permalink = prn.permalink;
			permalink = prn.permalink;
		}
	}

	var message = this.inputFieldsMsg(form, tmpObj, textValue);

	/* combined ratings */
	if (this.submitRating) {
		rating = this.getRatingsAppObject().userRating;
		message.push({'Name': 'js-CmtRating', 'Value': rating});
		tmpObj.Rating = rating;
	}
	if(prn && !isEditing) {
		message.push({'Name': 'js-CmtParentID', 'Value': prn.ID});
		if(this.IM=='own' && prn.profile) {
			message.push({'Name': 'destProfile', 'Value': prn.profile});
		}
	}
	if(permalink) message.push({'Name': 'permalink', 'Value': permalink});
	if (!isEditing) {
		if(avt) message.push({'Name': 'avatar', 'Value': (avt.name ? avt.name : avt)});
	} else {
		tmpObj.isEditing = true;
	}

	if(moderate) this.pathOverride = this.forMsg.path;

	var KVLCmt = this.getKVListFromMsg(message);
	// API: subscriber expects (ConstructedMessageObject[, FormDOM])
	try {
		JSKitAPI.askpublic.call(this, "comment-submit",
			KVLCmt, form);
	} catch(e) {
		return;
	}

	this.CommentCancelled();
	this.routeMsg("attachComment",
		[tmpObj, message, textMsg.length > 1700]);

	if (this.TC['js-CmtText' + name_suffix]) {
		this.TC['js-CmtText' + name_suffix].value = '';
	}
	if(this.clearImgs) this.clearImgs();
	this.thirdPartyImport(KVLCmt);
}

JSCC.prototype.attachComment = function(tmpObj, tmpMsg, longMsg) {
	var s = this;
	var cmtObj = this.cloneObj(tmpObj);
	if(s.images) cmtObj.imgs = s.images;
	var msg = JSKitLib.fmap(tmpMsg, function(e){return e});

	if(cmtObj.ParentID && !this.objById[cmtObj.ParentID]) {
		this.jspg.invalidate();
		return;
	}

	var rtShared = this.rtShared;
	var submitMsg = function() {
		if(rtShared.sent) return;
		rtShared.sent = true;
		/* Kick in message submission */
		msg.push({'Name': 'tid', 'Value': cmtObj.ID});
		s.prepareImgData(msg);
		var src = (cmtObj.isEditing ? '.edit' : '.put');
		var prms = this.getKVListFromMsg(msg);
		this.server(src, prms, longMsg);
	}

	this.cmtInPlace(cmtObj, function() {
		this.controls.reveal();
		this.reCalcPages();
		submitMsg.call(this);
	});
}

JSCC.prototype.getKVListFromMsg = function(msg) {
	var prms = {};
	JSKitLib.fmap(msg, function(v) { prms[v.Name] = v.Value; });
	return prms;
}

JSCC.prototype.cloneObj = function(f) {
	var t = {};
	for(var p in f) t[p] = f[p];
	return t;
}

JSCC.prototype.getRatingsAppObject = function() {
	return this.isStandalone() ? null : $JSKitGlobal.getRatingsAppObject(this.uniq);
}

JSCC.prototype.hasRatingsAppObject = function() {
	return this.getRatingsAppObject() ? true : false;
}

JSCC.prototype.embedRatingsAppObject = function(node) {
	// One time
	if ( ! this.embedRatingsAppObjectCompleted) {
		$JSKitGlobal.copyRatingsAppObject(this.uniq, node);
		this.embedRatingsAppObjectCompleted = true;
	}
}

JSCC.prototype.createMiniStarObject = function(rating, scale) {

	var rao = this.getRatingsAppObject();
	var fullStar = rao.miniFullStar['user'];
	var emptyStar = rao.miniEmptyStar['user'];
	var starWidth = rao.miniStarWidth + 'px';
	var starHeight = rao.miniStarHeight + 'px';

	var setImage = function(star, imageURL) {
		if(star.imageURL == imageURL)
			return; // Already set and we know it

		star.imageURL = imageURL;

		if(document.body.filters) {
			star.runtimeStyle.filter
				= "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
				+ imageURL + "', sizingMethod='crop')"
		} else {
			star.style.backgroundImage = 'url(' + imageURL + ')';
		}
	}

	var obj = document.createElement('div');

	/* Increment by Full Star Ratings */
	for (var i=2; i <= scale; i += 2) {

		var star = this.cr('div');

		star.style.cssFloat   = 'left';
		star.style.styleFloat = 'left';
		star.style.width    = starWidth;
		star.style.height   = starHeight;

		setImage(star, (rating >= i ? fullStar : emptyStar));

		obj.appendChild(star);
	}

	return obj;
}

JSCC.prototype.rerenderName = function(cmt) {
	var self = this;
	var ctls = cmt.ctls;
	var jsc = function(t){return ctls['js-singleComment'+t]};
	var sn = jsc("Name");
	if(sn && cmt.cobj.profile && self.serverOptions.showProfile
	&& !(cmt.cobj.msgtype && cmt.cobj.msgtype.match(/T|P/))) {
		sn.style.textDecoration = 'underline';
		sn.style.cursor = 'pointer';
		sn.onclick = function() {
			self.showProfile(sn, cmt.cobj, self.serverOptions.profileLevel);
			return false;
		}
	}
	var su = jsc("Url");
	if(su && cmt.cobj.Url && self.serverOptions.extraFieldURL
	&& !(cmt.cobj.msgtype && cmt.cobj.msgtype.match(/T|P/))) {
		su.style.cursor = 'pointer';
		su.setAttribute('title', cmt.cobj.Url);
		su.style.display = 'inline';
		su.onclick = function() {
			window.open(cmt.cobj.Url, '_blank');
			return false;
		}
	}
}

JSCC.prototype.gotPermanentId = function(tmpid, msgId) {
	var self = this;
	var cobj = this.objById[tmpid];
	var cmt = this.jspg.getItemById(tmpid).div;
	delete self.objById[tmpid];
	delete cobj.isEmbryonic;
	cobj.ID = msgId;
	cmt.id = msgId;
	this.jspg.invalidateItemView(msgId);
	self.objById[msgId] = cobj;
	var aux = arguments.length > 2 ? arguments[2] : {};
	var props = {'Text': cobj, 'status': cobj,
		'mtext': self.serverOptions,
		'mmode': self.serverOptions};
	for(var pname in props) {
		if(aux.hasOwnProperty(pname)) {
			props[pname][pname] = aux[pname];
		}
	}
	if (aux.Text) {
		JSKW$Events.syncBroadcast('smileys-loadCommentsWidget', cobj, self.jcaIndex);
	}
	if(self.serverOptions.showProfile && !self.serverOptions.profile && aux.profile) {
		self.serverOptions.profile = aux.profile;
		cobj.profile = aux.profile;
	}
	var cnvsObj = {};
	cnvsObj.Name = cobj.Name;
	if(aux.avatar) {
		cobj.avatar = aux.avatar;
		cobj.avatarWidth = aux.avatarWidth;
		cobj.avatarHeight = aux.avatarHeight;
		cnvsObj.avatar = aux.avatar;
		cnvsObj.avatarWidth = aux.avatarWidth;
		cnvsObj.avatarHeight = aux.avatarHeight;
		self.placeAvatar(cobj);
	}
	if (aux.gravatarId) {
		cobj.GravatarID = aux.gravatarId; 
		self.placeAvatar(cobj);
	}
	if(aux.destName){
		cobj.destName = aux.destName;
		cnvsObj.destName = aux.destName;
	}
	if(aux.destavatar) {
		cobj.destavatar = aux.destavatar;
		cobj.destavatarWidth = aux.destavatarWidth;
		cobj.destavatarHeight = aux.destavatarHeight;
		cnvsObj.destavatar = aux.destavatar;
		cnvsObj.destavatarWidth = aux.destavatarWidth;
		cnvsObj.destavatarHeight = aux.destavatarHeight;
	}
	if(this.IM && cobj.waitConversation) {
		cnvsObj.direction = "out";
		this.conversations[cobj.waitConversation.cnvsIdx] = cnvsObj;
		cobj.conversation = cobj.waitConversation.cnvsIdx;
		cobj.waitConversation = false;
		cobj.hasCnvs = false;
	}
	if(cmt.domCtls) cmt.domCtls.style.visibility = "";
	if(this.jspg.getPageByItemId(msgId)==this.curPage-1) {
		var pageNo = this.curPage;
		this.curPage = 0;
		this.displayPage(pageNo);
	}
}

function JSReplyMSGId(tmpid, msgId) {
	try {
		var cmt = document.getElementById(tmpid);
		var cobj = cmt.cobj;
		if(cobj.goesInto) {
			var args = arguments;
			JSKitLib.fmap(cobj.goesInto,
				function(s){s.gotPermanentId.apply(s,args)});
		} else {
			var self = $JCA[cobj.jcaIndex];
			self.gotPermanentId(tmpid, msgId);
		}
	} catch(e){}
}

function JSDeleteMSGId(msgId, jcaIndex, deletedCount) {
	try {
		var cmt = document.getElementById(msgId);
		if(cmt) {
			var self = $JCA[jcaIndex];
			if(cmt.cobj.action)
				JSKW$Events.syncBroadcast("comments_serverRequest_" + cmt.cobj.action);
			if(deletedCount>1){
				self.tag = null;
				self.jspg.invalidate();
				var pageNo = self.curPage;
				self.curPage = 0;
				self.displayPage(pageNo);
			} else {
				self.postHandlerDelete(cmt);
			}
		}
	} catch(e){}
}

function JSCCKarma(cObj, self) {
	var kObj = { p: cObj.karmaP || 0, n: cObj.karmaN || 0 };
	this.score = kObj.p - kObj.n;
	this.votes = kObj.p + kObj.n;
	this.cObj = cObj;
	this.self = self;
	this.vote2text();
	return this;
}
JSCCKarma.prototype.vote2text = function() {
	this.votesText = this.votes + ' '
			+ ((this.votes == 1) ? $JCL("vote") : $JCL("votes"));
}

JSCCKarma.prototype.recomputeScore = function(scoreAdjustment) {
	var now = new Date();
	if(this.votedAlready) {
		this.score -= this.myVote;
	} else {
		this.votes += 1;
		this.votedAlready = true;
		var kObj = this;
		setTimeout(function() {
			var action = kObj.myVote > 0 ? '+' : '-';
			kObj.self.server('-karma', {'id': kObj.cObj.ID,
					'action': action});
			}, 2000);
	}
	this.score += scoreAdjustment;
	this.myVote = scoreAdjustment;
	this.vote2text();
}

JSCC.prototype.divPages = function(so, items) {
	var srv = so.pages;
	this.curPage = 0;
	var self = this;
	if(!this.jspg) {
		this.jspg = new JSPGC(items.length, this.preq.ps);
		this.jspg.dataRequest = function(pageIdx, pg, cb) {
			var pageNo = pageIdx+1;
			if(!pg.target) pg.target = self.cr('div');
			var tgt = pg.target;
			if(tgt.parentNode) tgt.parentNode.removeChild(tgt);
			self.dataLoader = function() {
				self.curPage = 0;
				self.displayPage(pageNo, function(immed){ cb.apply(self, [undefined, immed])});
                                }
			if(self.preq.pn < 10)
				self.preq.pn += 5;
			self.getpages(pageNo - Math.ceil(self.preq.pn / 2));
			return cb(self.text(tgt, $JCL("Loading...")), false);
			};
		this.jspg.dataVisualizator = function(sIdx, arr, pg, cb) {
			if(!pg.target) pg.target = self.cr('div');
			var tgt = pg.target;
			if(tgt.parentNode) tgt.parentNode.removeChild(tgt);
			var itemsOnPage = arr.length;
			var cnvs = [];
			var cn = JSKitLib.fmap(arr,function(V,K){
				if(!V.html) {
					var oldN = V.obj.Name;
					V.obj.Name = (self.IM && V.obj.yours) ? 'Me' : oldN;
					var oldT = V.obj.Text;
					if(V.obj.status=='DT') V.obj.Text = 'Deleted';
					if (V.obj.Url && !V.obj.Url.match(/^https?:\/\//) ) {
						V.obj.Url = "http://" + V.obj.Url;
					}
					V.html = self.createCommentAsHTML(V.obj);
					V.obj.Name = oldN;
					V.obj.Text = oldT;
					delete V.div;
				}
				V.div = JSKitLib.html(V.html);
				V.div.id = V.obj.ID;
				V.obj.hasCnvs = !cnvs[V.obj.conversation];
				cnvs[V.obj.conversation] = true;
				self.fixComment(V.div, V.obj, K, K+sIdx, itemsOnPage);
				return V;
			});
			JSKitLib.removeChildren(tgt);
			self.pageHeader(tgt, sIdx, arr, itemsOnPage);
			for(var i=0; i<cn.length; i++) {
				tgt.appendChild(cn[i].div);
				if(!self.IM && (!self.adminMode || self.inlineModeration) && i<cn.length-1 && self.getSkin()=='smoothgray' && cn[i].obj.cedge>1) {
					var crdiv = function(className) {
						var div = self.cr("div");
						div.className = className;
						return div;
					};
					var div = crdiv("js-TornPageDivider");
					var divT = crdiv("js-TornPageDividerTop");
					var divB = crdiv("js-TornPageDividerBottom");
					div.appendChild(divT);
					div.appendChild(divB);
					tgt.appendChild(div);
				}
			}
			self.pageFooter(tgt, sIdx, arr, itemsOnPage);
			return cb(tgt, true);
		};
	}
	this.jspg.newData(srv.tc, srv.sp-1, items);
}

JSCC.prototype.pageHeader = function(target, globalIndex, items, itemsOnPage) {
	if(this.getSkin()=='smoothgray' && itemsOnPage>0 && items.length>0 && (!this.adminMode || this.inlineModeration)) {
		var obj = items[0].obj;
		if(obj.cedge!=3 && obj.cedge!=1) {
			var div = this.cr("div");
			div.className = "js-TornPageTop";
			if(JSKitLib.isIE()) {
				var img = this.cr("img");
				img.className = "js-TornPageTopImg";
				img.src = "//js-kit.com/images/tornPaperT.gif";
				div.appendChild(img);
			}
			target.appendChild(div);
		}
	}
}

JSCC.prototype.pageFooter = function(target, globalIndex, items, itemsOnPage) {
	if(this.getSkin()=='smoothgray' && itemsOnPage>0 && items.length==itemsOnPage && (!this.adminMode || this.inlineModeration)) {
		var obj = items[itemsOnPage-1].obj;
		if(obj.cedge!=3 && obj.cedge!=2) {
			var div = this.cr("div");
			div.className = "js-TornPageBottom";
			if(JSKitLib.isIE()) {
				var img = this.cr("img");
				img.className = "js-TornPageBottomImg";
				img.src = "//js-kit.com/images/tornPaperB.gif";
				div.appendChild(img);
			}
			target.appendChild(div);
		}
	}
}

JSCC.prototype.htmlPaginate = function(thread) {
	return this.htmlPaginator(thread, []);
}

JSCC.prototype.htmlPaginator = function(thread, arr) {
	var tl = thread.length;
	for(var i = 0; i < tl; i++) {
		var obj = thread[i];
		var present = (obj.status == 'D') ? 0 : 1;
		if(present) {
			arr.push(obj);
		}
		this.htmlPaginator(obj.thread, arr);
	}
	return arr;
}

// Part of externally useable API
JSCC.prototype.rerender = function() {
	var pageToDisplay = this.curPage;
	this.curPage = 0;
	this.jspg.invalidatePagesView(pageToDisplay-1, 1);
	this.displayPage(pageToDisplay);
}

JSCC.prototype.setPath = function(path) {
	this.pathOverride = path;    
}

JSCC.prototype.displayPage = function(pageNo, cb) {

	if(this.loading && !cb) {
		var nt = (new Date()).valueOf();
		if((nt - this.loading) > 5000) {
			this.gen++;
		} else  {
			return;
		}
	}

	if(pageNo < 1)
		return;

	if(pageNo > this.jspg.pageCount)
		pageNo = this.jspg.pageCount;

	var immediate = true;

	if(this.curPage != pageNo) {
		try {
			this.CommentCancelled();
			if(this.curPage) {
				var p = this.jspg.getPage(this.curPage - 1);
				if(p && p.target && p.target.parentNode)
					p.target.parentNode.removeChild(p.target);
			}
		} catch(e) { }
		this.curPage = pageNo;
		var oc = this.TC["js-OldComments"];
		var self = this;
		var pcb = function(p, immed) {
			if(p) {
				oc.appendChild(p);
				p.style.display = '';
			}
			if(immed && cb) cb.apply(self, [immed]);
		};
		var newPage = this.jspg.getPageVisualization(this.curPage-1, pcb);
		immediate = false;
	}

	var ocw = this.TC["js-OldCommentsWrap"];
        if (this.jspg.itemsCount != 0)
        {
          JSKitLib.show(ocw);
        }
        else
        {
          JSKitLib.hide(ocw);
        }

	this.rePageNavigator(this.curPage-1);
	if(immediate && cb) cb.apply(this, [immediate]);
}

JSCC.prototype.cutSearchLine = function(text) {
	return (text.length > 15) ? text.slice(0,15) + "..." : text;
}

JSCC.prototype.SearchLine = function() {
	var self = this;	
	var sExit = self.cr('span');
	var title = self.cr('span');
	title.className = 'js-SearchTitle';
	title.innerHTML = '<b>'+$JCL("You searched for")+':</b>';
	sExit.appendChild(title);
	var line = self.cr('span');
	line.className = 'js-SearchWords';
	text = self.cutSearchLine(self.searchString);
	line.insertBefore(document.createTextNode(text),line.firstChild);
	sExit.appendChild(line);
	var del = self.cr('input');
	del.type = 'button';
	del.value = $JCL('Clear Search');
	sExit.appendChild(del);
	var obj={
		 'containerElement':	 	sExit,
		 'field': 			line,
		 'itemObject': 			self,
		 'type':			'Search',
		 'Property': 			'searchString',
		 'title':			$JCL("You searched for")+': ',
		 'mode': 			'full'
		};
	obj.jsipe$start = function(){
		del.style.display = "none";
		line.style.border = "0px";
		title.style.display = "none";
		return true;
	}
	obj.jsk$on_submit_exit = function(value){
		self.searchString = value;	
		self.viewControl({name: "search"});
	}
	line.wasEdited = function(value){
		JSKitLib.removeChildren(line);
		line.appendChild(document.createTextNode(self.cutSearchLine(value)));
		del.style.display = "";
		line.style.borderBottom = "";
		title.style.display = "";
	}
	del.onclick = function(){
		this.name="del-line";
		self.viewControl(this);
	}
	var jsipe = new JSIPE(obj);
	return sExit;
}

JSCC.prototype.navSym = { "prev": "&larr;", "next": "&rarr;" };

JSCC.prototype.rePageNavigator = function(pageIdx) {
	var nav = '';
	var display = this.searchString ? "" : "none";
	if(this.jspg.pageCount > 1){
		display = "";
		nav = this.pageNavigator(this.jspg.pageCount, this.curPage);
	}
	var nvs = ['Top','Bottom'];
	for(var i = 0; i < nvs.length; i++) {
		var bar = this.TC['js-PageNav' + nvs[i]];
		bar.innerHTML = nav ? '<div>' + nav + '</div>' : '';
		bar.onselectstart = function() { return false; }
		bar.style.display = display;
		if(i) bar.style.display = ((pageIdx==undefined || (this.jspg.getPageItemsCnt(pageIdx) <= 5)) ? 'none' : '');
		if(this.searchString) this.addChild(bar, this.SearchLine(), true);
	}
}

JSCC.prototype.pageNavigator = function(pages, cur) {
	var self = this;
	var arr = [$JCL('Page: ')];
	var f = function(i, txt, cmt, cls, cf) {
		return '<a href="#'+cmt+'" onclick="' + (cf || '$JCA['+self.jcaIndex+'].displayPage('+i+');') + ' return false;" onmouseover="window.status='+"'"+cmt+"'"+'; return false;" onmouseout="window.status=\'\'; return true;" class="js-PageNOther'+(cls?' '+cls:'')+'">' + txt + '</a> '; }
	arr.push(f(cur - 1, this.navSym.prev, $JCL('Previous page'),
		'js-PageArrow' + ((cur == 1)?' js-PageArrowCur':'')));
	for(var i = 1; i <= pages; i++) {
		if((i == 4 || i == 3) && (cur - i) > 3) {
			i = Math.floor((cur - i) / 2 + i);
			arr.push(f(i, '&hellip;', 'Page-' + i));
			i = cur - ((pages - cur > 3 || cur == pages) ? 2 : 1);
		}
		if((i == cur + 3) && (pages - cur) > 4) {
			i = Math.floor((pages - cur) / 2 + cur);
			arr.push(f(i, '&hellip;', 'Page-' + i));
			i = pages - 1;
		}
		if(i == cur) {
			arr.push(f(i, i, 'Page-' + i, "js-PageNCur", '$JCA['+self.jcaIndex+'].jspg.invalidate(); $JCA['+self.jcaIndex+'].rerender();'));
		} else {
			arr.push(f(i, i, 'Page-' + i));
		}
	}
	arr.push(f(cur + 1, this.navSym.next, $JCL('Next page'),
		'js-PageArrow' + ((pages == cur)?' js-PageArrowCur':'')));
	return arr.join('');
}

JSCC.prototype.hideSettingsWindow = function(wname) {
	if(this[wname]) this.settingsWindow(wname);
}

JSCC.prototype.showProgress = function(wname, on) {
	if(this[wname]) this[wname].showProgress(on);
}

JSCC.prototype.settingsWindow = function(wname, atDiv, html) {
	var s = this;
	if(s[wname]) {
		if(!s.sWHideable) return;
		s[wname].parentNode.removeChild(s[wname]);
		delete s[wname];
		return;
	}
	var nohide = function() {
		s.sWHideable = false;
		if(s.swsHidt) clearTimeout(s.swsHidt);
		s.swsHidt = setTimeout(function(){s.sWHideable=true}, 100);
	}
	var div = this.cr("div");
	div.className = "js-SettingsWindow";
	if (s.config.nolc) JSKitLib.addClass(div, "js-SettingsWindowNolc");
	div.style.background = '#FFFFFF url('+this.uriDomain
				+'/images/bg-header-gray.png) bottom repeat-x';
	div.onclick = nohide;
	div.onselectstart = function() { return false; }
	if(typeof(html) == 'string') {
		div.innerHTML = html;
	} else {
		if(!html.dropWidth) div.style.width = '20em';
		div.appendChild(html);
	}

	if (wname == 'ctWnd' && s.TC['js-WelcomePanel']) {
		var aoh = s.cr('div');
		aoh.className = 'js-SettingsWindowHeader';
		s.text(aoh, $JCL('Administrator Options'));
		div.appendChild(aoh);
		var wp = s.TC['js-WelcomePanel'];
		var links = JSKitLib.html(''
			+ '<table border=0 cellpadding=4 align=center width="220" style="white-space: nowrap">'
			+ '<tr valign="top"><td class="js-WelcomeOpenPanel"><div class="js-WelcomeImgPanel"><a href="javascript:void(0);">' + $JCL(JSKitLib.visible(wp) ? 'closeWelcome' : 'openWelcome') + '</a></div></td></tr>'
			+ '<tr><td class="js-WelcomeContact"><div class="js-WelcomeImgSupport"><a href="javascript:void(0);">' + $JCL('contactSupport') + '</a></div></td></tr>'
			+ '</table>');
		var tc = JSKitLib.mapClass2Object({}, links);
		div.appendChild(links);
		tc['js-WelcomeOpenPanel'].onclick = function() {
			JSKitLib.toggle(wp);
			s.text(this.lastChild.lastChild, $JCL(JSKitLib.visible(wp) ? 'closeWelcome' : 'openWelcome'));
		};
		tc['js-WelcomeContact'].onclick = function(){location.href = s.uriDomain + '/comments/qa.html';};
	}

	var pgr = this.cr('div');
	pgr.className = "js-Progress";
	var url = this.uriDomain + '/images/progress-wg.png';
	if(document.body.filters) {
                pgr.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + url + ", sizingMethod=crop)";
       	} else pgr.style.backgroundImage = 'url(' + url + ')';
	div.appendChild(pgr);
	div.showProgress = function(on) {
		if(!on) {
			if(div.pIntvl) clearInterval(div.pIntvl);
			div.pIntvl = null;
			pgr.style.visibility  = 'hidden';
			return;
		} else if(div.pIntvl) return;
		var f = function() {
			pgr.vison = !pgr.vison;
			pgr.style.visibility = pgr.vison
				? 'visible' : 'hidden';
		}
		f();
		div.pIntvl = setInterval(f, 500);
	}

	s[wname] = div;
	var swh = this.cr("div");
	swh.className = "js-SettingsWindowHeader";
	this.text(swh, $JCL(wname == 'ctWnd' ? "View Options" : "Moderation"));
	div.insertBefore(swh, div.firstChild);
	div.style.position = "absolute";

	var jsd = new JSDL(div, [swh]);
	document.body.appendChild(div);
	div.style.left = jsd.getElmAbsPos(atDiv, false).x + "px";
	div.style.top =  jsd.getElmAbsPos(atDiv, false).y + atDiv.offsetHeight + "px";

	try {
		if (document.body.clientWidth < jsd.getElmAbsPos(atDiv, false).x + div.offsetWidth)
			div.style.left = document.body.clientWidth - div.offsetWidth -
                        	(parseInt(div.style.marginLeft) || 0) -
                                (parseInt(div.style.marginRight) || 0) + "px";
	} catch(e) {;}
	
	var ifrWr;
	if(JSKitLib.getBrowser() == 'gecko' && !atDiv.notShowIfr) {
                ifrWr = this.cr("div");
                ifrWr.id = "jsk-yIfr";
                var yIfr = this.cr("iframe");
                yIfr.style.position = "absolute";
                yIfr.style.top = 0;
                yIfr.style.left = 0;
                yIfr.style.zIndex = -1;
                yIfr.style.display = "block";
                yIfr.style.height = div.offsetHeight + "px";
                yIfr.style.width = div.offsetWidth + "px";
                yIfr.scrolling = "no";
                yIfr.frameBorder = "0";
                ifrWr.appendChild(yIfr);
                div.appendChild(ifrWr);
	}
	div.jsk$on_start_drag = function(){if(ifrWr) ifrWr.style.display = "none"};
	div.jsk$on_stop_drag = function(){if(ifrWr) ifrWr.style.display = ""};
	nohide();
}

JSCC.prototype.getImages = function(id) {
	var arg = {rnd: id, jx: this.jcaIndex};
	this.server(this.uriDomain + '/api/images/pick-attachments.js', arg);
}

JSCC.prototype.prepareImgData = function(msg) {
	if(this.images){
		JSKitLib.removeChildren(this.imgArea);
		JSKitLib.map(function(elem, i){
			JSKitLib.fmap(['img','orig','width','height','descr','mime'],
				function(E) { msg.push({'Name': 'js-CmtattachFile_'+i+'_'+E, 'Value': elem[E]})}
			);
		},this.images);
	}
}

JSCC.prototype.parseImgData = function(obj) {
	var re = /attachFile_(\d+)_(\w+)/;
	var imgs = [];
	for (var i in obj){
		var keys = re.exec(i);
		if (keys) {
                        if (!imgs[keys[1]]) imgs[keys[1]] = {};
                        imgs[keys[1]][keys[2]] = obj[i];
		}
	}
	return imgs;
}

JSCC.prototype.createImages = function(imgs, isPreview){
	var s = this;
	var d=function(){return s.div.apply(s,arguments);}

	var content = isPreview ? d() :
		      d("js-all-previewImages",d("js-previewImageTitle", $JCL('picTitle')),
			JSKitLib.html('<div style="clear:both;"></div>'));

	var crImg = function(elem, i){
		var img = d("js-previewImage");
		var thumb = s.cr("img");
		elem.descr = elem.descr || '';
		thumb.src = s.uriDomain+"/blob/"+elem.img;
		JSKitLib.setStyle(thumb, "border: 1px solid "+((isPreview)?"#0066cc":"#ececec")+"; padding: 2px;"
					+" width: "+elem.width+"px; height: "+elem.height+"px; cursor: pointer;" 
					+" position: relative; top: "+((96-elem.height)/2)+"px;");
		thumb.onclick = function() { window.open(s.uriDomain+"/blob/"+elem.orig); }
		var text = d("js-previewImageDescr");
		var wrap = d("js-imageWrap");
		s.addChild(wrap, thumb);
		s.addChild(img, wrap);
		if (isPreview) {
			var wasEdited = function(){
				if(elem.descr != "" ) JSKitLib.removeClass(text,"js-uploadGreyDescr");
				else JSKitLib.addClass(text,"js-uploadGreyDescr");
			}
			var jsipe = new JSIPE2({obj: elem,
						property: 'descr',
						title: 'Description',
						defaultText: 'Add caption',
						width: '90px',
						maxLength: 80,
						jsk$wasEdited: wasEdited
			});
			text.appendChild(jsipe.div);
			var onEditBtnClick = function(e){ 
				if(jsipe.editMode) jsipe.editMode();
				JSKitLib.stopEventPropagation(e || window.event); 
			}
			var onDeleteBtnClick = function(e){
				img.parentNode.removeChild(img);
				if(imgs && imgs[i]) imgs.splice(i, 1);
				JSKitLib.stopEventPropagation(e || window.event);
			}		
			var editBtn   = s.crImgCtrl("edit",   {top: "60px", left: "15px"}, onEditBtnClick);
			var deleteBtn = s.crImgCtrl("delete", {top: "60px", left: "57px"}, onDeleteBtnClick);
			var displayMode = function(mode){
				editBtn.style.display = mode;
                                deleteBtn.style.display = mode;
			}
			img.onmouseover = function(e) { displayMode("inline"); }
			img.onmouseout = function(e) { displayMode("none"); }
			s.addChild(img, editBtn);
			s.addChild(img, deleteBtn);
			if(elem.descr == "") JSKitLib.addClass(text,"js-uploadGreyDescr");
		} else {
			text.innerHTML = elem.descr.replace(/</g,"&lt;").replace(/>/g,"&gt;");
		}
		thumb.title = JSKitLib.htmlUnquote(elem.descr);
		s.addChild(img, text);
		s.addChild(content, img);
	}
	JSKitLib.map(crImg,imgs);
	s.addChild(content, JSKitLib.html('<div style="clear:both;"></div>'));

	return content;
}

JSCC.prototype.crImgCtrl = function(type, position, onClick) {
	var btn = this.cr("div");
	var ctrlBtn = { width : "30px", height : "30px", imgWidth :  "30px", imgHeight : "30px" };
	JSKitLib.setStyle(btn, "display:none; background:transparent; position:absolute; float:left; padding:0; margin:0; "
		+ "width:" + ctrlBtn.width + "; height:" + ctrlBtn.height + "; cursor: pointer;"
		+ "top:" + position.top + "; left:" + position.left);
	btn.title = $JCL(type + "Image");
	btn.onclick = onClick;
	imgUrl = this.uriDomain + "/images/" + "avatar-" + type + ".png";
	JSKitLib.addPNG(btn, imgUrl);

	return btn;
}


JSCC.prototype.addImage = function(img) {
	if(this.lbliChange) this.lbliChange(0);
	if (typeof(img) == "object"){
		if(img.error == "bigimg") {
			alert($JCL('bigImage'));
			return;
		}
		if (this.images) this.images.push(img)
		else this.images = [img];
		if (!this.imgArea) return;
		JSKitLib.removeChildren(this.imgArea);
		var content = this.createImages(this.images, true);
		this.addChild(this.imgArea, content);
	}
}

JSCC.prototype.viewControl = function(sel) {
	var s = this;
	var ap = { "usr": "yes"};
	switch(sel.name) {
	case "jss-srt":
		var newSortBy = sel.options[sel.selectedIndex].value;
		if(newSortBy == s.preq.srt) return true;
		s.preq.srt = newSortBy;
		s.showProgress('ctWnd', true);
		break;
	case "jss-rev":
		var newOrder = sel.selectedIndex?'desc':'asc';
		if(s.preq.ord == newOrder) return true;
		s.preq.ord = newOrder;
		s.showProgress('ctWnd', true);
		break;
	case "jss-prs":
		var newPrs = sel.options[sel.selectedIndex].value;
		if(newPrs == s.preq.thr) return true;
		s.preq.thr = newPrs;
		s.showProgress('ctWnd', true);
		break;
        case "search":
                ap.srch = s.searchString;
                break;
        case "del-line":
                break;
	default: return false;
	}
	s.dataLoader = function() {
		this.showProgress('ctWnd', false);
		this.curPage = 0;
		this.displayPage(1); }
	if(this.curPage) {
		var p = this.jspg.getPage(this.curPage - 1);
		if(p && p.target && p.target.parentNode)
			p.target.parentNode.removeChild(p.target);
	}
	s.ctag = null;
	s.getpages(0, ap);
	return true;
}

JSCC.prototype.splitAvatarDim = function(so, dim) {
	var re = /(\d+)x(\d+)/;
	var vl=re.exec(dim) || ['96x96', '96', '96'];
	so.maxAvatarWidth = parseInt(vl[1]);
	so.maxAvatarHeight = parseInt(vl[2]);
}

JSCC.prototype.calcAvatarDim = function (Width, Height, Avatar) {
	var so = this.serverOptions;
	var MW = so.maxAvatarWidth;
	var MH = so.maxAvatarHeight;
	if((MW>=96)&&(MH>=96)&&(Width<=100)&&(Height<=100)){
		return {'width': Width,'height': Height,'name': Avatar};
	} else if((MW<Width)||(MH<Height)){
		var DW = (MW<Width) ? MW/Width : 1;
		var DH = MH<Height ? MH/Height : 1;
		var D = DW < DH ? DW : DH;
		DW = Math.round(Width*D+0.000001);
		DH = Math.round(Height*D+0.000001);
		Name = Avatar.substr(0,Avatar.length-4)+'-'+DW.toString()+'x'+DH.toString()+Avatar.substr(Avatar.length-4);
		return {'width': DW, 'height': DH,'name': Name};
	} else {
		return {'width': Width,'height': Height,'name': Avatar};
	}
}

JSCC.prototype.placeGravatar = function(obj, div) {

	if (this.config.gravatars != 'yes') { return; }

	if (obj.GravatarID) {

		var img = this.cr('img');
		img.style.width = this.config.gravatar_size + 'px';
		img.style.height = this.config.gravatar_size + 'px';
		img.src = 'http://www.gravatar.com/avatar.php?' 
			+ 'gravatar_id=' + obj.GravatarID
			+ '&default=' + this.config.gravatar_default
			+ '&rating=' + this.config.gravatar_rating
			+ '&size=' + this.config.gravatar_size;

		JSKitLib.removeChildren(div);
		div.style.width = img.style.width;
		div.appendChild(img);

	}
}

JSCC.prototype.placeAvatar = function(obj, div) {
	div = div || obj.avatarPlace;
	if(!div) return;

	if(this.config.avatars != 'yes') {
		this.placeGravatar(obj, div);
		return;
	}

	if(!obj.avatar) {
		obj.avatarPlace = div;
		return;
	}
	var img = this.cr('img');
	img.style.visibility = 'hidden';
	var WH = this.calcAvatarDim(obj.avatarWidth,obj.avatarHeight,obj.avatar);
	var imgurl = JSKitAvatars.prototype.avatarURL.call({uriAvatar: this.uriDomain + '/blob/'}, WH['name']);

	img.style.width = WH['width'] + 'px';
	img.style.height = WH['height'] + 'px';
	img.src = imgurl;
	JSKitLib.removeChildren(div);
	JSKitLib.addPNG(div, imgurl);
	div.style.width = WH['width'] + 'px';
	div.appendChild(img);

	var self = this;
	if(obj.profile && this.serverOptions.showProfile) {
		div.style.cursor = 'pointer';
		div.onclick = function(e) {
			JSKitLib.stopEventPropagation(e);
			JSKitLib.preventDefaultEvent(e);
			self.showProfile(div, obj, self.serverOptions.profileLevel);
			return false;
		}
	}
	return div;
}

JSCC.prototype.placeProcessAvatar = function(div) {
	if(!div) return;
	var img = this.cr("img");
	img.style.visibility = 'hidden';
	JSKitLib.removeChildren(div);
	JSKitLib.addPNG(div, this.uriDomain + '/images/progress-wg.png');
	div.style.width = "15px";
	div.style.height = "15px";
	div.appendChild(img);
}

JSCC.prototype.replaceAvatars = function(avatars) {
        if (this.avatarsManagement) this.avatarsManagement.replaceAvatars(avatars);
}

JSCC.prototype.refreshComments = function() {
	var s = this;
	s.deleteWelcomePanel();
	s.jspg.invalidate();
	if (s.curPage == 1) s.curPage = 0;
	s.displayPage(1, function() {
		if (s.avatarsManagement) {
			var avatars = s.serverOptions.avatars || [];
			s.avatarsManagement.refreshAvatars(true, avatars.reverse());
		}
		s.preventAnonymousComments();
		s.makeWelcomePanel();
		s.ShowCommentDialog(s.replyForId);
	});
}

JSCC.prototype.preventAnonymousComments = function() { 
	var s = this;
	var cmtText = s.TC['js-CmtText']; 
	var cmtEmail = s.TC['js-CmtEmail'];
	var cmtUpload = (s.avatarsManagement) ? s.avatarsManagement.uploadControl : undefined;
	var disableCtrls = [cmtText, s.TC['js-Cmtsubmit'], s.TC['js-CmtName'], cmtEmail, cmtUpload, s.imgUpload];
	var lockCtrls = [s.TC['js-Cmtsubmit'], cmtUpload];
	var imgArea = s.TC['js-commentImageArea'];
	var so = s.serverOptions;
	var anonymCond = s.anonymousCmt && !(s.openID || (so.facebookLogin && so.facebook) ||
	(so.yahooLogin && so.yahoo) || (so.gfcLogin && so.gfc)
	|| (so.twitterLogin && so.twitter));

	JSKitLib.fmap(disableCtrls, function(V){ if (V) V.disabled = (anonymCond) ? true : false; });
	JSKitLib.fmap(lockCtrls, function(V){ if (V) V.btnLocked = (anonymCond) ? "true" : null; });
	if (imgArea) imgArea.disableUpload = anonymCond;
	if (cmtText) { cmtText.value = (anonymCond) ? $JCL('requireAuth') : ""; }
	if (cmtEmail && anonymCond) cmtEmail.value = "";
} 

JSCC.prototype.setThirdPartyShare = function() {
	var s = this;
	var po = s.TC["js-commentPubOptions"];
	if(!po) return;
	JSKitLib.removeChildren(po);
	var change_fun = function() {
		this.value = this.checked ? "on" : "off";
	};
	var crEl = function(ltype, lname) {
		var publish = s.serverOptions[ltype].publish;	
		var inp = s.cr("input");
		inp.className = "js-comment"+lname+"ShareCheckbox";
		inp.type = "checkbox";
		inp.defaultChecked = !!publish;
		inp.checked = !!publish;
		inp.value = inp.checked ? "on" : "off";
		inp.name = 'js-Cmt'+lname +'Share';
		inp.onchange = change_fun;
		var divtxt = s.cr("div");
		divtxt.className = "js-comment"+lname+"ShareLabel";
		var txt = document.createTextNode($JCL('share'+lname));
		divtxt.appendChild(txt);
		po.appendChild(inp);
		po.appendChild(divtxt);
	};
	if(s.serverOptions.yahoo) {
		crEl("yahoo","Yahoo");
		var lbl = s.cr("div");
		lbl.className = "js-commentYahooShareLabelLogo";
		po.appendChild(lbl);
	}
	if(s.serverOptions.facebook && s.serverOptions.facebook_api_key) {
		crEl("facebook","FB");
	}
	if(s.serverOptions.gfc) {
		crEl("gfc","GFC");
	}
	if(s.serverOptions.twitter) {
		crEl("twitter","Twitter");
	}
}

JSCC.prototype.createJSKAuth = function() {
	var s = this;
	var calcStartPosition = function(){
		var doc = (document.compatMode == "BackCompat") ? document.body : document.documentElement;
		var scroll = JSDL.prototype.getCurScroll();
		return {
			x : scroll.scroll_left + Math.round((doc.clientWidth - 300)/2),
			y : scroll.scroll_top + Math.round((doc.clientHeight - 200)/2)
		};  
	};

	var calcAuthOptions = function() {
		return JSKitLib.foldl(["register", "login", "haloscan", "openid"], ["blogspot", "facebook", "yahoo", "gfc", "twitter"], function(method, container) {
			if (s.serverOptions[method + "Login"] && !s.serverOptions[method]) container.push(method);
        	});
	}
	if(s.jskauth) s.jskauth.destroy();	
	s.jskauth = new JSKAuth({
		mode: "popup",
		authOptions: calcAuthOptions(),
		startPosition: calcStartPosition,
		withBackdrop: "true",
		loginStatus: !!(s.openID || s.serverOptions.facebook || s.serverOptions.yahoo || s.serverOptions.gfc || s.serverOptions.twitter),
		ref: JSKitLib.getRef(s),
		rvcTarget: s.target,
		facebook_api_key: s.serverOptions.facebook_api_key,
		facebook_xd_receiver: s.serverOptions.facebook_xd_receiver,
		gfc_site: s.serverOptions.gfc_site
		}, s.TC['js-AuthAreaWrap']);
}


JSCC.prototype.wrapJSKAuth = function() {
	var s = this;
	var tc = s.TC;

	if (s.config.nolc) return; 
	if (!tc['js-AuthAreaWrap']) {
		var items = ['js-commentOpenID', 'js-commentInputOpenID', 'js-CmtOpenID', 'js-OpenIDError'];
		JSKitLib.fmap(items, function(item) {
			if (tc[item]) tc[item].parentNode.removeChild(tc[item]);
		});
		return;
	}

	var authAreaTmpl =
	'<div>' +
		'<div class="js-commentFieldLabel">{Label:leaveCommentAs}</div>' +
		'<div class="js-authSelector">' + 
			'<span class="js-logoutSpan">[<a class="js-commentOpenIDLogout">{Label:logout}</a>]</span>' +
		'</div>' +
		'<div class="js-authArea"></div>' +
	'</div>';

	JSKitLib.fmap(['Name', 'Email', 'Text'], function(type){
		if (tc['js-Cmt' + type]) tc['js-Cmt' + type].className = "js-commentFieldInput";
	});

	if (tc['js-commentInputOpenID']) tc['js-commentInputOpenID'].style.display = "none";

	var authAreaContainer = JSKitLib.html(s.gtmpl(authAreaTmpl));
	tc['js-AuthAreaWrap'].appendChild(authAreaContainer);
	JSKitLib.mapClass2Object(tc, authAreaContainer);

	var normalizeOpenID = function(oid) {
		var m = oid.match(/^https?:\/\/([a-z0-9\.\-]+?).js-kit.com\/$/);
		if(m) return {type: "jskit", login: m[1]};
		return {type: "openid", login: oid.replace(/https?:\/\/(.*?)\/$/, '$1')};
	}

	var calcLogin  = function(login) {
		if (login == "guest") return;
		var getPostFix = function(type) {
			var r;
			switch(type) {
			case "facebook": r = " @ Facebook"; break;
			case "yahoo": r = " @ Yahoo"; break;
			case "gfc": r = " @ Google Friend Connect"; break;
			case "twitter": r = " @ Twitter"; break;
			default: r = "";
			}
			return r;
		}
		var soll = s.serverOptions.lastLogin;
		if(soll && (soll.type != "yahoo" || s.serverOptions.yahoo)
		&& (soll.type != "gfc" || s.serverOptions.gfc)
		&& (soll.type != "facebook" || s.serverOptions.facebook)
		&& (soll.type != "twitter" || s.serverOptions.twitter)) {
			var normLogin =
				soll.type == "openid" ?
				normalizeOpenID(soll.login).login : soll.login;
			return normLogin
				+ getPostFix(soll.type);
		}
		var rslt;
		var f = function(ltype) {
			return (s.serverOptions[ltype] &&
				s.serverOptions[ltype+'Login']) ?
				s.serverOptions[ltype].name + getPostFix(ltype) : undefined;
		}
		rslt = rslt || f('facebook') || f('yahoo') || f('gfc') || f('twitter');
		return (rslt ? rslt + (login ? " / " + login : "") : login );
	}

	var buildAuthOptions = function(login){ return(
		[{value : (login == "guest" ? "opt-anonymous" : "opt-user"),  
		text  : calcLogin(login) || $JCL('guest')},
		{value : "register",
		text  : $JCL('newJSKitProfile')},
		{value : "login", 
		text  : $JCL('existingJSKitProfile')},
		{value : "haloscan",
		text  : $JCL('existingHaloscanProfile')},
		{value : "openid",
		text  : $JCL('usingOpenID')},
		{value : "blogspot",
		guard: function(){return s.serverOptions.blogspotLogin ? 1:0;},
		text  : $JCL('blogspotURL')},
		{value : "facebook",
		guard: function(){return s.serverOptions.facebook || !s.serverOptions.facebookLogin ? 0:1;},
		text  : $JCL('connectFacebook')},
		{value : "yahoo",
		guard: function(){return s.serverOptions.yahoo || !s.serverOptions.yahooLogin ? 0:1;},
		text  : $JCL('connectYahoo')},
		{value : "gfc",
		guard: function(){return s.serverOptions.gfc || !s.serverOptions.gfcLogin ? 0:1;},
		text  : $JCL('connectGFC')},
		{value : "twitter",
		guard: function(){return s.serverOptions.twitter || !s.serverOptions.twitterLogin ? 0:1;},
		text  : $JCL('connectTwitter')}
	]);
	};
	var options = buildAuthOptions(s.openId);

	var onSuccessLoginAction = function(eventName, data) {
		s.serverOptions.lastLogin = {
			'type': 'openid',
			'login': data['yours']['openid-tie']};
		s.openID = data['yours']['openid-tie'];	
		showActualInfo(
			data['yours']['openid-tie'], 
			data['yours']['Name'], 
			data['yours']['Url'], 
			data['yours']['Email']);
		s.refreshComments();
	};

	var reDrawSelector = function(selector, options) {
		if (!selector || !options) return;
		JSKitLib.removeChildren(selector);
		JSKitLib.fmap(options, function(opt) {
			if(opt.guard && !opt.guard()) return;
			var option = document.createElement('option');
			var optionText = document.createTextNode((typeof(opt.text) == "function") ? opt.text() : opt.text);
			option.value = opt.value;
			option.appendChild(optionText);
			selector.appendChild(option);
		});
		s.createJSKAuth();
	};

	var showActualInfo = function(openID, name, url, email) {
		if (tc['js-CmtName']) {
			JHI2.remove(tc['js-CmtName']);
			tc['js-CmtName'].value = name || '';
		}
		
		s.setFormFields({'Email': email, 'Url': url});

		if (openID || s.serverOptions.facebook || s.serverOptions.yahoo || s.serverOptions.gfc || s.serverOptions.twitter) {
			var oiddiv = tc['js-logoutSpan'];
			if (oiddiv) oiddiv.style.display = 'inline';
		}
		if (openID) {
			var openid = String(openID);
			var curLogin = normalizeOpenID(openid);
			reDrawSelector(authSelector, buildAuthOptions(curLogin.login));
		} else {
			reDrawSelector(authSelector, buildAuthOptions());
		}
		s.setThirdPartyShare();
	};

	var createThirdPartyCallback = function(provider){
		return function(eventName, error, data) {
			if(error!="data") return;
			if (!data.name && provider == "yahoo") {
				alert("Can not process yahoo data");
				return;
			}
			s.serverOptions[provider] = { name: data.name, publish: data.publish };
			data = {yours: {
				'Name': data.name,
				'Email': data.email || ''
				}
			};
			s.serverOptions.lastLogin = {
				'type': provider,
				'login': data['yours']['Name']};
	                showActualInfo(
				null,
                	        data['yours']['Name'],
				data['yours']['Url'],
                        	data['yours']['Email']);
			s.refreshComments();
		}
	};

	JSKW$Events.registerEventCallback(undefined, onSuccessLoginAction, 'JSKitAuth_success_login');
	JSKitLib.fmap(["facebook", "yahoo", "gfc", "twitter"], function(provider){
		JSKW$Events.registerEventCallback(undefined, createThirdPartyCallback(provider), "JSKitAuth_success_" + provider + "_login");
	});

	var createAuthSelector = function(options, selectedIndex) {
	        var authSelector = document.createElement('select');
	        authSelector.className = 'jsk-SectionLoginInput';
        	authSelector.name = 'jsk-User-login-type';
	        reDrawSelector(authSelector, options);
	        authSelector.selectedIndex = selectedIndex;
        	authSelector.onchange = function() {
			if (this.value.match(/register|login|haloscan|openid|blogspot|facebook|yahoo|gfc|twitter/)) s.jskauth.show(this.value);
		};
        	return authSelector;
	};

	var authSelector = createAuthSelector(options, 0);
	tc['js-authSelector'].insertBefore(authSelector, tc['js-logoutSpan']);

	if (s.openID || s.serverOptions.facebook || s.serverOptions.yahoo || s.serverOptions.gfc || s.serverOptions.twitter)
		showActualInfo(s.openID);
	s.preventAnonymousComments();
	var onLogout = function(eventName) {
		s.clearSOData();
		if (tc['js-CmtName']) {
			JHI2.create($JCL('guest'), tc['js-CmtName']);
			tc['js-CmtName'].value = "";
		}
		s.setFormFields({'Email': '', 'Url': ''});
		var oiddiv = s.TC['js-logoutSpan'];
		if (oiddiv) { oiddiv.style.display = 'none'; }
		s.openID = 0;
		s.setThirdPartyShare();
		reDrawSelector(authSelector, buildAuthOptions("guest"));
		setTimeout(function(){
			s.refreshComments();
		}, 0);
	};
	JSKW$Events.registerEventCallback(undefined, onLogout, 'JSKitAuth_logout');
}

JSCC.prototype.wrapAvatarsManagement = function() {
	var self = this;
	var avatarArea = this.TC["js-commentAvatar"];
	var avatarsListArea = this.TC["js-commentAvatarArea"];
	if (this.config.nolc || this.config.avatars != 'yes' || !avatarsListArea) {
		if (avatarArea) JSKitLib.hide(avatarArea);
		return;
	}
	var avatars = this.serverOptions.avatars || [];
	var config = {
		"id" : "comments-" + self.jcaIndex,
		"ref" : JSKitLib.getRef(self),
		"labels" : $JCL,
		"avatars" : avatars.reverse(),
		"controls" : [self.TC["js-Cmtsubmit"]],
		"uriAvatar" : self.uriAvatar,
		"controlButtons" : true,
		"bulkOperations" : false,
		"useOptionsButton" : avatarArea ? false : true
	};
	this.avatarsManagement = new JSKitAvatars(config);
      	this.avatarsManagement.assembleAvatarArea(avatarArea);
	this.avatarsManagement.assembleAvatarsListArea(avatarsListArea, undefined, true);
}

JSCC.prototype.clearSOData = function() {
	var self = this;
	JSKitLib.fmap(["facebook", "yahoo", "gfc", "twitter", "lastLogin"], function(property) { self.serverOptions[property] = undefined; })
	self.fieldDfl = [];
}

JSCC.prototype.setFormFields = function(fields) {
	var s = this;
	var tc = s.TC;
	var emptyLabels = {
		'Url': $JCL('URL is optional'),
		'Email': s.adminFirstMsgMode ? $JCL('emailFirstNote') :
			$JCL('email is ' + (s.adminMode ? 'mandatory for you (admin)' : 'optional'))
	}

	JSKitLib.fmap(fields, function(v, name) {
		var o = tc['js-Cmt'+name];
		if(o) {
			o.jsk$setdfl = function(val) {
				o.style.color = '';
				o.jsk$setdfl = false;
				o.jsk$not_specified = false;
				o.value = val || '';
			}
			if (v) {
				o.jsk$setdfl(v);
			} else {
				o.style.color = '#808080';
				o.value = emptyLabels[name];
				o.jsk$not_specified = true;
			}
			o.onfocus = function() { if (o.jsk$setdfl) o.jsk$setdfl(); }
		}
	});
}

JSCC.prototype.dataLoader = function(so, nc) {
	var s = this;
	var tc = s.TC;
	var d=function(){return s.div.apply(s,arguments);}
	
	if (this.config.disabled != 'no') return;

	var cc = JSKitLib.html(s.gtmpl(s.utmpl['js-CreateComment'] || (s.config.nolc ? s.dtProfileCreate : s.dtCreate)));
	JSKitLib.mapClass2Object(tc, cc);
	var ec = JSKitLib.html(s.gtmpl(s.dtEditComment));
	JSKitLib.mapClass2Object(tc, ec);
	if(s.config.profileLC) {
		var cin = tc['js-commentInputName'];
		if(cin) cin.style.display = 'none';
		var cie = tc['js-commentInputEmail'];
		if(cie) cie.style.display = 'none';
	}
	if(so.extraFieldURL) {
		var ciu = tc['js-commentInputUrl'];
		if (ciu) ciu.style.display = 'block';
	}
	var ac = function(name, cb) {
		var o = tc['js-'+name];
		if(!o) return;
		if(o.tagName == 'A') o.href="javascript:void(0);";
		o.style.cursor = 'pointer';
		o.onselectstart = function() { return false; }
		o.onclick = cb;
	}

	var uInp = tc['js-uploadImageInput'];
	var uInpW = tc['js-uploadImageInputWrapper1'];
	
	s.clearImgs = function(){
		JSKitLib.removeChildren(s.imgArea);
		if(uInpW) uInpW.style.paddingTop = '0px';
		if(uInp && uInp.ifri) {
			JSKitLib.removeChildren(uInp);
			JSKitLib.hide(uInp);
			uInp.ifri = undefined;
		}
		if(s.images) delete(s.images);
	}

	JSKitLib.fmap(['', 'Edit'], function(el, i) {
		ac('Cmtsubmit' + el, function() { s.CommentSubmitted(); return false; });
		ac('Cmtcancel' + el, function() { s.clearImgs(); if(s.onCancel) s.onCancel(); return s.CommentCancelled();
		});
	});
	if (JSKitLib.isIE()) {
		var op = tc['js-commentOptions'];
		var sub = tc['js-commentSubmit'];
		if (op) op.style.paddingLeft = "3px";
		if (sub) sub.style.paddingLeft = "3px";
	}
	var so = s.serverOptions;
	if (!(s.openID || (so.facebookLogin && so.facebook) || (so.yahooLogin && so.yahoo) || (so.gfcLogin && so.gfc) || (so.twitterLogin && so.twitter))) {
		JHI2.create($JCL('guest'), tc['js-CmtName']);
	}
	var n = tc['js-CmtName']; 
	n.jsk$setdfl = function(val) { 
		n.jsk$setdfl = false; 
		n.value = val || ''; 
	}

	s.setFormFields({'Email': '', 'Url': ''});

	s.anonymousCmt = so.anonymousCmt;

	s.wrapAvatarsManagement();

	if (!JSKitEPB.isExists()) s.wrapJSKAuth();

	ac('commentOpenIDLogout', function() {
		setTimeout(function(){
			if(so.gfc_site && so.gfc && so.gfcLogin) {
				new JSKitGFC(JSKitLib.getRef(s),
					s.target,
					so.gfc_site,
					function(){
						this.processLogout();
					});
			}
			s.server(s.uriDomain + '/api/session/logout.js', {});
		}, 0);
		return false;
	});

	if(!tc['js-commentMore'] && s.config.avatars != 'yes') { 
		var m = tc['js-CCMore']; 
		if(m) m.style.display = 'none'; 
	} 

	var handler = function(e){
		e = e || window.event;
		if(e.keyCode == 27 || e.which == 27) JSKitLib.preventDefaultEvent(e);
	};
	var blockEsc = function(){
		if (document.addEventListener) 
			document.addEventListener("keydown", handler, true);
		else if (document.attachEvent) 
			document.attachEvent("onkeydown", handler);
	}	
	var unblockEsc = function(){
		if (document.removeEventListener)
			document.removeEventListener("keydown", handler, true);
		else if (document.detachEvent)
			document.detachEvent("onkeydown", handler);
	}

	s.onAddImgButton = function(isShow){
		if(s.config.uploadImages) {
			s.imgArea = tc['js-commentImageArea'];
			if(uInp && s.imgArea) {
				uInp.style.display = isShow ? 'block' : 'none';
				if(uInpW) uInpW.style.paddingTop = isShow ? '15px' : '0px';
				s.imgShow = isShow;
			}
		}
		if (uInp && !uInp.ifri){
			var frmi = s.cr('form');
			JSKitLib.setStyle(frmi, "clear: both;");
			JSKitLib.addClass(frmi, "js-uploadImageForm");
			frmi.method = 'post';
			frmi.acceptCharset = 'UTF-8';
			frmi.encoding = 'multipart/form-data';
			frmi.style.margin = "0px";
			var lbli = s.cr('div');
			s.lbliChange = function(mode) {
				JSKitLib.removeChildren(lbli);
				lbli.appendChild(document.createTextNode(
					mode ? $JCL("Loading...")
					     : $JCL("uploadImage")));
			}
			s.lbliChange(0);

			params = JSKitEPB.getAsHash({ref: JSKitLib.getRef(s)});
			JSKitLib.fmap(params, function(v, k) {
				var item = s.cr('input');
				item.type = 'hidden';
				item.name = k;
				item.value = encodeURIComponent(v);
				frmi.appendChild(item);
			});

			var upfi = s.cr('input');
			s.imgUpload = upfi; 
			upfi.disabled = ( s.imgArea && s.imgArea.disableUpload ) ? true : false ;
			upfi.type = 'file';
			upfi.name = 'image';
			var formitems = JSKitLib.mapClass2Object({}, frmi);
			var val;
			var fi = function() {
				if(val) {
					var subi = s.TC["js-Cmtsubmit"];
					subi.disabled = false;
					upfi.disabled = false;
					frmi.reset();
					JSKitLib.fmap(params, function(v, k) {
						formitems[k].value = encodeURIComponent(v);
					});
					unblockEsc();
					s.getImages(val);
				}
			}
			var tgti = 'js-ifrm-'+s.jcaIndex + Math.random();
			var ifri = JSKitLib.createHiddenIframe(tgti, uInp, fi, false);
			frmi.target = tgti;
			upfi.onchange = function() {
				val = (new Date()).getUTCMilliseconds() + "-" + Math.random( );
				frmi.action = s.uriImage+'add?rnd='+val;
				s.lbliChange(1);
				frmi.submit();
				var subi = s.TC["js-Cmtsubmit"];
				subi.disabled = true;
				upfi.disabled = true;
				blockEsc();
			};
			uInp.appendChild(lbli)
			frmi.appendChild(upfi);
			uInp.appendChild(frmi);
			uInp.ifri = ifri;
		}
	}
	
	var uImg = tc['js-uploadImageButton'];
	if (uInp) JSKitLib.hide(uInp);
	if(uInp && uImg && !s.config.uploadImages) {
		JSKitLib.hide(uImg);
		JSKitLib.hide(uInp);
	}
	ac('uploadImageButton', function(){
		s.onAddImgButton(!JSKitLib.visible(uInp));
	});
	
	var onCommentMore = function(obj, label) {
		obj.ashown = !obj.ashown;
		s.text(obj, obj.ashown ? label.less : label.more);
                if (s.avatarsManagement && s.avatarsManagement.useOptionsButton) s.avatarsManagement.toggleAvatarsListView();
		s.onAddImgButton(obj.ashown);	
		if(!obj.ashown) return false;

		return false;
	};

	ac('commentAddAvatar', function() {
		var label = {'less': '-', 'more': '+'};
		return onCommentMore(this, label);
	});
	ac('commentMore', function() {
		var label = {'less': this.getAttribute("less") || $JCL('less'),
			'more': this.getAttribute("more") || $JCL('more') };
		return onCommentMore(this, label);
	});

	if ((!s.avatarsManagement || !s.avatarsManagement.useOptionsButton) && (!s.config.uploadImages || tc['js-uploadImageButton'])) {
		JSKitLib.fmap(['js-commentMore', 'js-CCMore'], function(element) { if (tc[element]) JSKitLib.hide(tc[element]); });
	}

	s.labelHTML = s.labelHTML || 'leaveComment';

	if(so.mmode == "pause") {
		var lca = null;
	} else {
		var lca = d('js-commentControl', s.a($JCL(s.labelHTML)));
		lca.onclick = function() { return s.ShowCommentDialog(); };
	}

	var jmg = d('js-commentControl js-commentTool', JSKitLib.html('<font face="Webdings">&#64;</font>&nbsp;'), s.a($JCL("Controls")));
	jmg.onclick = function() {
		var srt = ["date", "name"];
		if(!s.config.moderate && s.scoringEnabled()) srt.push("karma");
		if(s.adminMode) srt.push("status");
		/* s.submitRating check is not good for all the cases */
		if ( $JSKitGlobal.isRatingsAppAvailable() ) srt.push("rating");
		var srtOpts = [];
		for(var i = 0; i < srt.length; i++) {
			srtOpts.push('<option value="'+srt[i] + '"'
				+ (srt[i]==s.preq.srt?" selected":"")+'>'
				+$JCL(srt[i])+'</option>');
		}
		var bkw = ["ascending", "descending"];
		var bkwOpts = [];
		for(var i = 0; i < bkw.length; i++) {
			bkwOpts.push('<option value="'+bkw[i]+'"'
				+ ((!!i) == (s.preq.ord=='desc')?" selected":"")+'>'
				+$JCL(bkw[i])+'</option>');
		}
		var prs = ["on (threaded)", "off (flat)"];
		var prsMap = {'on (threaded)':'yes','off (flat)':'no'}
		var prsOpts = [];
		for(var i = 0; i < prs.length; i++) {
			prsOpts.push('<option value="'+prsMap[prs[i]]+'"'
				+ (prsMap[prs[i]] == s.preq.thr?" selected":"")+'>'
				+$JCL(prs[i])+'</option>');
		}
		var div = s.cr("div");
		div.innerHTML = 
			"<table border=0 cellpadding=4>"
			+ "<tr><td align=right>" + $JCL("Sort by") + '</td><td align=left><select name="jss-srt" onchange="$JCA['+s.jcaIndex+'].viewControl(this);return true;">'
			+ srtOpts.join("")
			+ "</select></td></tr>"
			+ "<tr><td align=right>" + $JCL("Order") + '</td><td align=left><select name="jss-rev" onchange="$JCA['+s.jcaIndex+'].viewControl(this);return true;">'
			+ bkwOpts.join("")
			+ "</select></td></tr>"
			+ "<tr><td align=right>" + $JCL("Threading") + '</td><td align=left><select name="jss-prs" onchange="$JCA['+s.jcaIndex+'].viewControl(this);return true;">'
			+ prsOpts.join("")
			+ "</select></td></tr>"
			+ "<tr><td align=right>" + $JCL("Search") + '</td><td id="js-SearchCell-'+s.jcaIndex+'" align=left></td></tr>'
			+ (s.adminMode && !s.config.moderate?('<tr><td align=center colspan=2><a href="'+s.uriDomain+'/moderate/'+s.config.domain+'" onclick="window.location.href = this.href; return true;">Moderate whole site</a></td></tr>'):'')
			+ "</table>"
		this.notShowIfr = true;
		s.settingsWindow('ctWnd', this, div);
                var obj={'mode': 'form', 'inpSize': '121px', type: 'Search'};
                var form = new JSIPE(obj);
                obj.jsk$on_submit_exit = function(){
                        s.searchString = form.input.value;
                        s.viewControl({name: "search"});
			s.hideSettingsWindow('ctWnd');
                }
		form.input.value = s.searchString || "";
		if (s.searchString) form.cleaner.style.visibility = "visible";
		var sCell = document.getElementById("js-SearchCell-"+s.jcaIndex);
		if (sCell) s.addChild(sCell, form.main);

		return false;
	}
	s.controls = jmg;
	if(nc || s.config.moderate) {
		s.controls.reveal = function(){};
	} else {
		s.controls.style.display = 'none';
		s.controls.reveal = function(){s.controls.style.display=''}
	}

	if(so.subs || so.noJunk) {
		var pb = "";
	} else {
		var propLink = JSKitLib.html('<a href="http://js-kit.com/comments?wow" target="js-kit">Powered by JS-Kit</a>');
		var prop = d('', "(", propLink, ")");
		prop.style.position = 'relative';
		var pb = d("js-commentControl js-poweredBy", prop);
	}

	var ca = d("js-CommentsArea",
		(s.config.nolc && !s.IM)?null:d("js-LeaveComment", s.config.moderate || s.IM=='own' ?null:lca, s.IM ? null : jmg, !s.config.nolc ? pb : null,
			JSKitLib.html('<br clear="all"/>')),
		tc["js-CreateComment"], tc["js-EditComment"]);
	this.makeWelcomePanel();

	if (!so.wysiwyg && so.smiley) {
		JSKitLib.fmap(['Text', 'TextEdit'], function(v) {
			var sd = s.cr('div');
			sd.style.margin = '3px 0px 0px 3px';
			var text = tc['js-Cmt' + v];
			var processed = {};
			var index = 0;
			JSKitLib.fmap(s.smiles, function(el, i) {
				if (!processed[el.file]) {
					processed[el.file] = 1;
					var smile = JSKitLib.html(s.smileTag(el));
					smile.style.display = 'inline';
					smile.style.cursor = 'pointer';
					smile.style.marginRight = '5px';
					smile.onclick = function() {
						text.value += ' ' + i;
						text.focus();
						if (JSKitLib.isSafari()) {
							text.setSelectionRange(text.value.length, text.value.length);
						}
					};
					sd.appendChild(smile);
					if (s.getSkin() != 'smoothgray' && !(++index % 8)) {
						sd.appendChild(JSKitLib.html('<br>'));
					}
				}
			});
			text.parentNode.insertBefore(sd, text.nextSibling);
		});
	}

	var pageNavTop = d('js-PageNavTop');
	var pageNavBottom = d('js-PageNavBottom');
	s.addChild(ca, d(null, pageNavTop, d("js-OldCommentsWrap", d("js-OldComments")), pageNavBottom), !s.backwards);
	var pageToDisplay = so.pages.sp;
	var dpCB;
	if(s.comment_location) {
		var obj = s.jspg.getItemById(s.comment_location);
		if(obj) {
			pageToDisplay = s.jspg.getPageByItemId(s.comment_location) + 1;
			dpCB = function() {
				if(obj.div) s.flash(obj.div);
			};
		}
		delete s.comment_location;
	}
	s.displayPage(pageToDisplay, dpCB);

	var closeControlsPopup = function() {
                s.hideSettingsWindow('ctWnd');
                s.hideSettingsWindow('ctBlock');
	}
	JSKW$Events.registerEventCallback(undefined, closeControlsPopup, "comments_closeControlsPopup");

	ca.onclick = function() {
		closeControlsPopup();
	}
	s.addChild(s.target, ca);
	if(lca && ((s.config.nolc && s.IM=='foreign') || (so.expandLeaveCmt && !s.config.noautoexpand)) && !s.config.moderate) {
		s.ShowCommentDialog(undefined, {nofocus: true});
	} else if (s.adminFirstMsgMode) {
		s.ShowCommentDialog();
	}

	JSKitLib.deferCall(function() {
		var trIfrId = 'jsk-ifrtr-c' + s.jcaIndex;
		if (document.getElementById(trIfrId)) return;
		JSKitLib.createHiddenIframe(trIfrId, s.target, null, true, s.uriDomain + '/api/static/landing.html');
	});
}

JSCC.prototype.objRerender = function(obj, cmt) {
	cmt.ctls['js-singleCommentText'].innerHTML =
		this.tmpl("{Text}", obj, true);
}

JSCC.prototype.getLastReply = function(pobjId) {
	var pobj = this.jspg.getItemById(pobjId);
	var lreplyObj = null;
	for(var i=pobj.obj.thread.length-1; i>=0; i--){
		if(pobj.obj.thread[i].status!='D') {
			var c = this.jspg.getItemById(pobj.obj.thread[i].ID);
			if(c) {
				lreplyObj = this.getLastReply(c.obj.ID);
				break;
			}
		}
	}
	return lreplyObj || pobj;
}

JSCC.prototype.reCalcPages = function() {
	if(this.curPage>this.jspg.pageCount) this.displayPage(this.jspg.pageCount);
	this.rePageNavigator(this.jspg.pageCount>0 ? this.jspg.pageCount-1 : undefined);
}

JSCC.prototype.appendConversation = function (cmt, conversation) {
	var cnvsObj = {};
	var cnvs = this.conversations[conversation];
	var self = this;
	if(!cnvs) return;
	JSKitLib.fmap(["Name","avatar","avatarHeight","avatarWidth"],
		function(V){ cnvsObj[V] = cnvs.direction=="in" ? cnvs[V] : cnvs["dest"+V] });
	cnvsObj.Label = "Conversation with ";
	var dtc = JSKitLib.html(this.tmpl(this.dtConversation, cnvsObj));
	var ctls = JSKitLib.mapClass2Object({}, dtc);
	var nm = ctls['js-ConversationName'];
	if(nm && this.serverOptions.showProfile) {
		nm.style.textDecoration = 'underline';
		nm.style.cursor = 'pointer';
		nm.onclick = function() {
			self.showProfile(nm, {profile: cnvs.profile}, self.serverOptions.profileLevel);
			return false;
		}
	}
	cmt.insertBefore(dtc, cmt.firstChild);
	JSKitLib.addClass(cmt, "js-singleCommentConversationHead");
}

JSCC.prototype.removeConversation = function (cmt) {
	JSKitLib.removeClass(cmt, "js-singleCommentConversationHead");
	cmt.removeChild(cmt.firstChild);
}

JSCC.prototype.appendConversationChild = function (cmt) {
	JSKitLib.addClass(cmt, "js-singleCommentConversationChild");
}

JSCC.prototype.removeConversationChild = function (cmt) {
	JSKitLib.removeClass(cmt, "js-singleCommentConversationChild");
}

JSCC.prototype.getSkin = function() {
	return this.config.skin==="wireframe" ? "" : (this.config.skin || "");
}

JSCC.prototype.processServerRequestEvent = function(eventName, jcaIndex, cmtId) {
	if(this.jcaIndex!=jcaIndex) return;
	var item = this.jspg.getItemById(cmtId);
	if(!item || !item.div) return;
	var div = item.div;
	var self = this;
	if(eventName=="comments_serverRequest_deleting" ) {
		if(div.domCtls) div.domCtls.style.visibility = "hidden";
		var av = div.ctls['js-singleCommentAvatar'];
		this.placeProcessAvatar(av);
		item.obj.origstatus = item.obj.status;
		item.obj.status = 'DP';
		item.obj.dTimer = setTimeout(function(){
			item.obj.status = 'A';
			if(div.domCtls) div.domCtls.style.visibility = "";
			if(av && item.obj.avatar) self.placeAvatar(item.obj, av);
			delete item.obj.dTimer;
		}, 30000);
	}
	if(eventName=="comments_serverRequest_deleted") {
		if(item.obj.dTimer) clearTimeout(item.obj.dTimer);
		this.removeComment(div, true);
	}
}

JSCC.prototype.makeWelcomePanel = function() {
	var s = this;
	if (s.jcaIndex) return;
	if (!s.adminMode) {
		s.deleteWelcomePanel();
		return;
	}
	if (s.TC['js-WelcomePanel'] || s.config.moderate || s.config.nolc) return;

	var wp_html = ''
	+ '<div class="js-WelcomePanel' + (s.backwards ? '' : ' js-WelcomePanelBottom') + '"' + (s.serverOptions.welcome ? '' : ' style="display: none"') + '>'
		+ '<div class="js-WelcomePanelTitle"><div class="js-WelcomePanelClose"></div>{Label:adminNote}</div>'
		+ '<div class="js-WelcomePanelContent">'
			+ '<div class="js-WelcomePanelHeader"><div class="js-WelcomeImgInfo"></div>{Label:Welcome}</div>'
			+ ((s.serverOptions.welcome || {}).message || $JCL('welcomeToComments'))
			+ '<div>'
			+ '<div class="js-WelcomePanelContentBlock" style="padding-right: 50px">'
				+ '<b>{Label:Get started}:</b>'
				+ '<table border="0" cellspacing="0" cellpadding="0">'
				+ '<tr style="display: none"><td><div class="js-WelcomeImgProfile"><a href="javascript:void(0);" class="js-WelcomeProfileLink">{Label:editProfile}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgHelp"><a href="http://wiki.js-kit.com/FAQ+-+Comments">{Label:readFAQ}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgCustom"><a href="http://wiki.js-kit.com/Customize-Comments">{Label:customizeLook}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgDashboard"><a href="' + s.uriDomain + '/settings/">{Label:adminDashboard}</a></td></div></tr>'
				+ '</table>'
			+ '</div>'
			+ '<div class="js-WelcomePanelContentBlock">'
				+ '<b>{Label:Get involved}:</b>'
				+ '<table border="0" cellspacing="0" cellpadding="0">'
				+ '<tr><td><div class="js-WelcomeImgTwitter"><a href="http://twitter.com/jskit">{Label:followTwitter}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgSupport"><a href="' + s.uriDomain + '/comments/qa.html">{Label:contactSupport}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgWidgets"><a href="' + s.uriDomain + '">{Label:checkWidgets}</a></div></td></tr>'
				+ '</table>'
			+ '</div>'
			+ '<br style="clear: both" />'
			+ '</div>'
		+ '</div>'
		+ '<div class="js-WelcomePanelArrow"></div>'
	+ '</div>';
	var wp = JSKitLib.html(s.gtmpl(wp_html));
	JSKitLib.mapClass2Object(s.TC, wp);
	s.TC['js-WelcomePanelClose'].onclick = function() {
		s.TC['js-WelcomePanel'].style.display = 'none';
		if (s.serverOptions.welcome && s.serverOptions.welcome.ts) {
			s.server('s-welcome-close', {'ts': 
					s.serverOptions.welcome.ts});
		}
	}
	s.TC['js-WelcomeProfileLink'].onclick = function() {
		s.showProfile(this, {profile: s.serverOptions.profile});
	}
	JSKitLib.addPNG(s.TC['js-WelcomePanelArrow'], s.uriDomain + "/images/welcome/triangle.png");
	var lc = s.TC['js-LeaveComment'];
	if (lc) lc.parentNode.insertBefore(wp, lc);
}

JSCC.prototype.deleteWelcomePanel = function() {
	if (this.TC['js-WelcomePanel']) {
		this.TC['js-WelcomePanel'].parentNode.removeChild(this.TC['js-WelcomePanel']);
		delete this.TC['js-WelcomePanel'];
	}
}

JSCC.prototype.addMenu = function(cmt, obj) {
	if(cmt.id.match(/jsid/)) {
		var self = this;
		var showOffensive = this.serverOptions.commod && !obj.yours && !this.config.nolc && (!obj.msgtype || !obj.msgtype.match(/T|P/) || this.serverOptions.trackbackreply);
		var showProfile = obj.profile && self.serverOptions.showProfile && !(obj.msgtype && obj.msgtype.match(/T|P/)) && !this.config.nolc;
		var cmtURL = ((obj.permalink || this.config.permalink).replace(/#jsid-*/, "") + "#") + obj.ID;
		var data = [
			{level: 1, title: $JCL("showUserProfile"), action: function() {self.showProfile(cmt.firstChild, obj, self.serverOptions.profileLevel);}, hidden: !showProfile, icon: this.uriDomain + "/images/menu/show-user-profile.png"},
			{level: 1, title: $JCL("markAsOffensive"), icon: this.uriDomain + "/images/menu/mark-comment-as-offensive.png", action: function(){self.markOffensive(obj.ID)}, hidden: !showOffensive},
			{level: 1, title: $JCL("getPermalinkURL"), icon: this.uriDomain + "/images/menu/comment-permalink.png", inputValue: cmtURL, type: "DTI"},
			{level: 1, type: "Delimeter"},
			{level: 1, title: $JCL("getWidgetLikeThis"), action: function() { window.open("http://js-kit.com/comments?menu", "_blank");}, statusText: "http://js-kit.com/comments?menu"}
		];
		var mtgt = this.config.nolc ? self.target.parentNode.parentNode : undefined;
		var menu = new JSMenu($JCL("options"), data, "js-singleCommentMenu");
		return menu;
	}
}

/* Must be last to support Opera */
JSCC.prototype.newData = function(arr, so) {
	var s = this;
	s.serverOptions = so;
	s.openID = so.openID;
	s.searchString = so.srch;
	s.adminMode = !!so.adminMode;
	s.adminFirstMsgMode = !!so.adminFirstMsgMode;
	s.inlineModeration = (s.adminMode && !s.config.moderate);
	if(this.config.nolc) so.avatardim = '48x48';
	s.splitAvatarDim(so, so.avatardim);

	if(s.serverOptions.facebookLogin && s.serverOptions.facebook_api_key) {
		JSKitFB.prototype.detectXD(s.target);
	}
	so.smiley = so.smiley || s.config.smiles == "yes";
	s.config.uploadImages = so.uploadImages;
	s.config.skin = s.hasOwnProperty("dtComment") ? s.config.skin : (s.config.skin || so.skin);

	JSKitLib.addClass(s.target, "js-CommentsSkin-" + (s.getSkin() || "wireframe"));
	if(s.config.skin === "smoothgray") {
		s.navSym = JSKitLib.isIE() ? { "prev": '&larr;', "next": '&rarr;'} : { "prev": '&#x25c0;', "next": '&#x25b6;' };
		if(!s.hasOwnProperty("dtComment")) s.dtComment = JSCC.prototype.dtComment2;
		s.dtCreate = JSCC.prototype.dtCreate2;
		s.dtEditComment = JSCC.prototype.dtEditComment2;
	}
	else if (s.config.skin === "haloscan") {
		s.dtComment = JSCC.prototype.dtComment3;
		s.dtCreate = JSCC.prototype.dtCreate3;
		s.dtEditComment = JSCC.prototype.dtEditComment;
		if (window.JK$HS$haloscan_style)
			JSKitLib.addCss(window.JK$HS$haloscan_style, "comments-skin-haloscan-custom");
	}

	if(!s.eventsCtx) {
		var processServerRequestEvent = function() {
			s.processServerRequestEvent.apply(s, arguments);
		}
		s.eventsCtx = JSKW$Events.registerEventCallback(s.eventsCtx, processServerRequestEvent, "comments_serverRequest_deleting");
		s.eventsCtx = JSKW$Events.registerEventCallback(s.eventsCtx, processServerRequestEvent, "comments_serverRequest_deleted");
	}

	if (so.smiley) {
		s.smiles = {
			"O:-)"  : {file: 'innocent.gif', title: 'Innocent'},
			"&gt;:o": {file: 'yell.gif', title: 'Yell'},
			":)"    : {file: 'smile.gif', title: 'Smile'},
			":-)"   : {file: 'smile.gif', title: 'Smile'},
			";)"    : {file: 'wink.gif', title: 'Wink'},
			";-)"   : {file: 'wink.gif', title: 'Wink'},
			":'("   : {file: 'cry.gif', title: 'Cry'},
			"8-)"   : {file: 'cool.gif', title: 'Cool'},
			":("    : {file: 'frown.gif', title: 'Frown'},
			":-("   : {file: 'frown.gif', title: 'Frown'},
			":*"    : {file: 'kiss.gif', title: 'Kiss'},
			":-*"   : {file: 'kiss.gif', title: 'Kiss'},
			":-D"   : {file: 'laughing.gif', title: 'Laughing'},
			"=-O"   : {file: 'surprised.gif', title: 'Surprised'},
			"=-X"   : {file: 'sealed.gif', title: 'Sealed'},
			":-["   : {file: 'embarassed.gif', title: 'Embarassed'},
			":-$"   : {file: 'money-mouth.gif', title: 'Money mouth'},
			":-P"   : {file: 'tongue-out.gif', title: 'Tongue out'},
			":-E"   : {file: 'foot-in-mouth.gif', title: 'Foot in mouth'},
			"*DONT_KNOW*"   : {file: 'undecided.gif', title: 'Undecided'}
		};
		var f = function(v) { return v.replace(/([\W])/g,"\\$1"); };
		JSKitLib.fmap(s.smiles, function(el, i) {
			/* fix for case ">)" */
			s.smiles[i].regexpText = new RegExp('(&gt|&lt)?' + f(i), 'g');
			s.smiles[i].regexpTag = new RegExp(' ?' + f(s.smileTag(el)) + ' ?', 'g');
		});
	}
	var cb = function(name, obj, jcaIndex) {
		switch(name) {
			case "smileys-onchangeCommentText":
				if(so.smiley && obj && obj.Text) obj.Text = s.textSmiles2Graphical(obj.Text.replace(/&amp;/g, "&")); 
			break;
			case "smileys-beforePostNewComment":
				if(so.smiley && obj && obj.value) obj.value = s.textSmiles2Graphical(obj.value, 1);
			break;
			case "smileys-loadCommentsWidget": 
				if (s.jcaIndex != jcaIndex) return;
			/* no break needed !!! */
			case "smileys-newCommentInDiv":
				var needAutolink = (so.htmlMode || s.config.nolc);
				if ((so.smiley || needAutolink) && obj && obj.Text) {
					obj.Text = obj.Text.split('<wbr></wbr>').join('');
					if (needAutolink) {
						var tags;
						var tags2meta = function(t){tags = []; t = t.replace(/<a href="[^"]+">.*?<\/a>|<.*?>/ig, function(m){tags.push(m); return ' %#HTML_TAG#% ';}); return t;};
						var meta2tags = function(t){JSKitLib.map(function(v){t = t.replace(' %#HTML_TAG#% ', v);}, tags); return t;};
						obj.Text = tags2meta(obj.Text);
						obj.Text = obj.Text.replace(/((?:http|ftp|https):\/\/(?:[a-z0-9#:\/\;\?\-\.\+,@&=%!\*\'(){}\[\]$_|^~`](?!gt;|lt;))+)/ig, '<a href="$1">$1</a>');
						obj.Text = tags2meta(meta2tags(obj.Text));
					}
					obj.Text = obj.Text.replace(/&amp;/g, '&');
					if (so.smiley) obj.Text = s.textSmiles2Graphical(obj.Text);
					if (needAutolink) {
						obj.Text = meta2tags(obj.Text);
					}
					obj.Text = obj.Text.replace(/(<a\s+href="[^">]*)?([^&<>\s\/\-]{12})([^&<>\s\/\-]{12})/ig, function($0, $1, $2, $3){if($1)return $0; return $2+'<wbr></wbr>'+$3;});
				}
			break;
		}
	}
	var ctx = JSKW$Events.registerEventCallback(undefined, cb, "smileys-newCommentInDiv");
	JSKW$Events.registerEventCallback(ctx, cb, "smileys-loadCommentsWidget");
	JSKW$Events.registerEventCallback(ctx, cb, "smileys-beforePostNewComment");
	JSKW$Events.registerEventCallback(ctx, cb, "smileys-onchangeCommentText");

	if(so.req) {
		s.preq.srt = so.req.srt;
		s.preq.ord = so.req.ord;
		s.preq.thr = ((so.req.prs == 'flat') ? 'no' : 'yes');
	}

	if(so.gravatars) {
		s.config.gravatars = 'yes';
		s.config.gravatar_rating = so.gravatar_rating;
		s.config.gravatar_size = so.gravatar_size;
		s.config.gravatar_default = so.gravatar_default;
	}
	if (!so.avatars)
		s.config.avatars = 'no';

	s.gen++;
	s.loading = false;

	if(s.ctag != so.tag) {
		s.objById = {};
		if(s.jspg) s.jspg.invalidate();
	}

	var flat = (s.searchString) ? true : s.preq.thr != 'yes';

	var ttt = []; // top level thread
	var nc = 0;
	var newChilds = {};
	for(var i = 0; i < arr.length; i++) {
		var obj = arr[i];
		if(!obj.ID || !obj.Text) continue;
		if(this.IM && obj.yours) obj.Name = 'Me';
		if(flat) {
			delete(obj.ParentID);
			delete(obj.depth);
		}
		s.objById[obj.ID] = obj;
		obj.thread = [];
		JSKW$Events.syncBroadcast("smileys-loadCommentsWidget", obj, s.jcaIndex);
		obj.karma = new JSCCKarma(obj, this);
		if(obj.status != 'D') nc++;
		var prn = s.objById[obj.ParentID];
		if(prn) {
			if(!newChilds[obj.ParentID]) {
				ttt.push(obj);
			}
			prn.thread.push(obj);
		} else {
			ttt.push(obj);
		}
		newChilds[obj.ID] = 1;
		obj.imgs = s.parseImgData(arr[i]);
	}
	s.divPages(so, s.htmlPaginate(ttt));

	if(this.IM) this.conversations = so.conversations;

	s.ctag = so.tag;
	s.dataLoader(so, nc);

	s.tmce = { foreign: true, cfg: {
		relative_urls: 0,
		remove_script_host: 0,
		uri_domain: s.uriDomain,
		closePopups: function() {
        			var cns = document.body.childNodes;
        			var i = 0;
        			while(i < cns.length) {
                			if(cns[i].id && cns[i].id.match(/^mce_\d+$/) && cns[i].className.match(/clearlooks2/)) document.body.removeChild(cns[i]);
                			else i++;
        			}
			},
		bookMark: function() { 
			tinyMCE.settings.curBM = tinyMCE.activeEditor.selection.getBookmark(); 
			},
		mode: "none",
		plugins: (so.smiley?"emotions":"") + (so.media?",youtube":""),
		theme: "advanced",
		theme_advanced_buttons1: 
			"bold,italic,underline,|,undo,redo,link,unlink"
			+ (so.media?",youtube":"") + (so.smiley?",emotions":""),
		theme_advanced_buttons2: "",
		theme_advanced_buttons3: "",
		theme_advanced_toolbar_location: "top",
		theme_advanced_toolbar_align: "left",
		extended_valid_elements:
			"a[href],b,i,u,em,strong,sup,sub"
			+ (so.media?",object[classid|codebase|width|height|align],param[name|value],embed[quality|type|pluginspage|width|height|src|align|wmode]":"")
			+ (so.smiley?",img[src|title|border|alt]":""),
		setup: (!so.smiley) ? undefined : function(ed) {
			      var mceEvents = ["onClick","onKeyUp"];
			      JSKitLib.map(function(ev) {
				ed[ev].add(function(ed, e){ tinyMCE.settings.bookMark();});
			      }, mceEvents);
			      ed.onKeyUp.add(function(ed, e) {
			      	var content = {Text: ed.getContent({format: 'raw'})};
			      	JSKW$Events.syncBroadcast("smileys-onchangeCommentText", content);
					if(tinyMCE.settings.smiley) { 
						if(JSKitLib.isIE()) {
							ed.setContent(content.Text, {format: 'raw'});
							tinyMCE.execInstanceCommand(ed.id, "selectall");
							ed.selection.collapse(0);
						} else {  
							ed.setContent('', {format: 'raw'});
							ed.execCommand('mceInsertContent', false, content.Text, {format: 'raw'});
						}
					}
			      });
		       }
	}};

	var showCD = function() {
		if(so.ShowSavedCommentDialog)
			so.ShowSavedCommentDialog(s);
	}

	if(so.wysiwyg && !window.tinyMCE) {
		var inittmce = function() {
			s.tmce.foreign = false;
			s.tmce.cfg.plugins = "inlinepopups"+(so.smiley?",emotions":"")+(so.media?",youtube":""); // !inl-pop
			s.tmce.cfg.strict_loading_mode = true;
			tinyMCE.init(s.tmce.cfg);
			showCD();
		}
		var oldcb = window.jsk$tmcecb;
		if(oldcb) {
			jsk$tmcecb = function() { if(oldcb) oldcb(); showCD(); };
		} else {
			jsk$tmcecb = inittmce;
			s.runscr(s.uriDomain + '/extra/tiny_mce/tmce.js');
		}
	} else {
		showCD();
	}

	var f = s.onDataLoad;
	if(f) { s.onDataLoad = null; setTimeout(f, 0); }
	JSKitAPI.publish.call(this, "comments-data-loaded", this.jcaIndex, so.pages.tc);
}


