                                                                                                                                                                                                                                         
try { if(!window.JSK$EPB && navigator.appVersion.match(/[345]\.[.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 32210 2011-04-07 07:09:41Z jskit $
 */

if(!window.$JCA) {
  var $JCA = [];
  var $JCLT = {
	leaveComment: 'Leave a comment',
	leaveCommentAs: 'Leave a comment as:',
	guest: 'Guest',
	url: 'URL:',
	nameLabel: 'Your name:',
	nicknameLabel: 'Nickname (required):',
	nicknameRequired: 'Please enter your name to leave a comment',
	emailLabel: 'Send replies to email:',
	emailNote: '(if provided, email will not be displayed or shared)',
	ratingLabel: 'Rating:',
	commentLabel: 'Comment:',
	commentsCountLabel: '{Count} Items',
	submit: 'Submit comment',
	save: 'Save',
	cancel: 'Cancel',
	avatar: 'Avatar:',
	tooShort: 'The comment field can\'t be blank',
	tooLong: 'Message size should not exceed {maxCommentLength} characters',
	junkCtl: 'Junk control',
	byVotes: 'by',
	logout: 'logout',
	loggingOut: 'Logging out ...',
	less: 'less',
	more: 'more',
	optionsU: 'Options &#x25b2;',
	optionsD: 'Options &#x25bc;',
	isJunkVote: 'Is this an inappropriate message?',
	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',
	readOurBlog: 'Read our Blog',
	loginRequiredNotice: 'Login required, click here to begin',
	deleteImage: 'Delete image',
	editImage: 'Edit description',
	imgUploadErrorBigImage: 'The image file you are trying to upload is too big.',
	imgUploadErrorWrongFormat: 'The image file you are trying to upload has wrong format.',
	imgUploadErrorInternal: 'An internal error occurred during image upload. Please try again later.',
	uploadImage: 'Upload new image <span class="js-kit-images-imgSizeSpec">(up to 10 megabytes)</span>:',
	addImgText: 'Add images',
	addPicText: 'Add pictures',
	picTitle: 'PICTURES',
	commentMoveNotice: "Page reload will cause your comment to move according to your sorting and ordering preferences.",
	shareVia_yahoo: "Share via ",
	shareVia_twitter: "Tweet this",
	shareVia_friendfeed: "Share via FriendFeed",
	shareVia_facebook: "Share via Facebook",
	shareVia_gfc: "Share via Google Friend Connect",
	getPermalinkURL: 'URL of this comment',
	getWidgetLikeThis: 'Get a widget like this',
	options: 'More',
	showUserProfile: 'Show user\'s profile',
	markAsOffensive: 'Mark comment as offensive',
	post: 'Post',
	retry: 'Retry',
	messagePostFailed: 'Could not post your comment to the server. Please try again.',
	posting: 'Posting',
	messagePostingInProgress: 'Posting in progress. Please wait',
	attempt: 'attempt',
	userIsAdmin: 'This user is an administrator',
	defaultThreadTitle: 'Echo',
	defaultCommentText: 'What\'s on your mind...',
	expandXMoreReplies: '{count} more (expand)',
	sharedThisOn: 'I shared this on {service_name}...',
	statePaused: 'Paused',
	stateLive: 'Live',
	itemsNew: 'new',
	leftToday: 'Today',
	leftYesterday: 'Yesterday',
	leftDaysAgo: ' days ago',
	vote: 'vote',
	votes: 'votes',
	youSearchedFor: 'You searched for',
	clearSearch: 'Clear Search',
	page: 'Page: ',
	pagePrevious: 'Previous page',
	pageNext: 'Next page',
	btnPagePrevious: '&lt; Prev',
	btnPageNext: 'Next &gt;',
	administratorOptions: 'Administrator Options',
	viewOptions: 'View Options',
	moderation: 'Moderation',
	urlIsOptional: 'URL is optional',
	emailIsOptional: 'email is optional',
	controls: 'Controls',
	sortBy: 'Sort by',
	order: 'Order',
	threading: 'Threading',
	search: 'Search',
	btnDelete: 'delete',
	btnEdit: 'edit',
	btnFlag: 'flag',
	btnLike: 'like',
	btnModerate: 'moderate',
	btnReply: 'reply',
	no: 'no',
	More: 'More',
	Score: 'Score',
	Welcome: 'Welcome',
	yes: 'yes',
	getInvolved: 'Get involved',
	getStarted: 'Get started',
	likeThisComment: 'Like this comment?',
	communityAssignedCarmaScore: 'Community assigned karma score',
	userHasTrustedStatus: 'This user has a trusted status',
	messageIsNotBlocked: 'The message is not blocked',
	approveMessagesFromUser: 'Approve this and future messages from this user',
	messageIsNotSpam: 'This message is not spam or junk',
	approveMessage: 'Approve this message',
	approveFutureMessagesFromUser: 'Approve future messages from this user',
	acceptMessage: 'Accept this message as good',
	unblockCommenter: 'Unblock this commenter',
	liftBanFromUser: 'Lift ban from this user/IP',
	unbanUser: 'Unban User',
	approveUser: 'Approve user',
	approveMessage: 'Approve message',
	deleteUnwantedComment: 'Delete unwanted comment',
	getRidOfComment: 'Get rid of comment without prejudice',
	deleteMessage: 'Delete',
	flagAsSpam: 'Flag as Spam or Junk',
	trainAksimet: 'Train <a href:"http://akismet.com">Akismet</a> to flag similar comments in the future',
	spamJunk: 'Spam/Junk',
	blockCommenter: 'Block this commenter',
	hideCommentsFromUser: 'Make comments from this user invisible to other users',
	blockUser: 'Block User',
	blockCommenterIP: 'Block commenter\'s IP',
	hideCommentsFromIP: 'Make comments from this IP invisible to other users',
	blockIP: 'Block IP',
	markoffMessage: 'Thank you',
	askingFacebook: 'Asking Facebook...',
	askingGoogle: 'Asking Google...',
	loggingIn: 'Logging in ',
	loginWithGFC: 'Log in with Google Friend Connect',
	justPostedCommentOn: ' just posted the following comment on',
	poweredBy: 'Powered by',
	clickToEditEmpty: 'Empty value (click to edit)',
	savingScriptMessage: 'Enclose the script in a <BODY></BODY> tag!',

	//Like
	like_you: 'You',
	like_like: 'Like',
	like_guest: 'Guest',
	like_unlike: 'Unlike',
	like_guests: '{guestsCount} Guests',
	like_likedBy: 'Liked by',
	like_andXMore: 'And {count} more',
	like_like_title: 'Click here if you like this item',
	like_unlike_title: 'Made a mistake?',
	like_collapseList: 'Collapse list',
	like_like_progress: 'Liking...',
	like_unlike_progress: 'Unliking...',

	// Menu labels
	menuAdmin: 'Admin',
	menuLogin: 'Log In',
	menuLogout: 'Log Out',
	menuFollow: 'Follow',
	menuEditProfile: 'Edit My Profile',
	menuModeration: 'Moderation',
	menuSettings: 'General Settings',
	menuAdminNotices: 'Admin Notices',
	menuGetThis: 'Get this for your site',
	menuJSKBlog: 'Echo Blog',
	menuJSKTwitter: 'Echo on Twitter',
	menuHelp: 'Help',

	menuUnbindIdentity: 'Unbind this service',

	from: 'Login',
	to: 'Share',
	Iam: 'Login with:',
	shareWith: 'Share with:',
	myWebsites: 'My Websites:',
	thisPage: 'This Page',
	addAnotherSite: 'Add another site',
	myURL: 'My Site (click to edit)',
	urlIsEmpty: 'URL cannot be empty!',
	urlAlreadyExists: 'The same URL already exists!',
	follow: "Follow",
	addImagesSectionNotice: '<strong>Add images:</strong> this site allows you to attach pictures to your comment.',
	miniProf_viewDetails: 'View details',
	miniProf_ILeft: 'I have left ',
	miniProf_userLeft: 'User left ',
	miniProf_commentsStats: 'comment(s)',
	miniProf_visitMeOn: 'Visit me on...',
	miniProf_openFullProfile: 'View profile',
	miniProf_ext_profile_gfc: 'View Google Friend Connect profile',
	miniProf_ext_profile_facebook: 'View Facebook profile',
	miniProf_ext_profile_yahoo: 'View Yahoo! profile',
	miniProf_ext_profile_twitter: 'View Twitter profile',
	miniProf_ext_profile_friendfeed: 'View FriendFeed profile',
	miniProf_ext_profile_blogspot: 'Visit Blogger site',
	miniProf_ext_profile_jskit: 'Visit JS-Kit profile',
	miniProf_ext_profile_epb: 'View external profile',
	follow_emailNotification: 'Notify me by Email:',
	follow_emailNotificationDesc: 'Send Email notification each time a user leaves a new comment',
	follow_rssThread: 'Subscribe to this Stream via RSS:',
	follow_popupHeader: 'Follow',
	follow_editMyNotifications: 'Edit my notifications',
	follow_cancelButton: 'Cancel',
	follow_doneButton: 'Done',
	follow_subscriptionInProgress: 'Saving...',
	follow_notifyMode_noemail: 'Never for this Stream',
	follow_notifyMode_email: 'Only when someone replies to my comments in this stream',
	follow_notifyMode_anymails: 'Each time a new item is added to the Stream',
	follow_emailAddressLabel: 'My Email address is:',
	follow_editProfile: 'Edit',
	follow_emptyEmail: 'Not provided',
	follow_openingProfile: 'Opening Profile...',
	shareWith_facebook: "My Facebook Friends",
	shareWith_yahoo: "My Yahoo! Friends",
	shareWith_gfc: "My Google Friends",
	shareWith_twitter: "My Twitter Followers",
	shareWith_friendfeed: "My FriendFeed Followers",
	expirationBanner_title: "The Echo subscription for this domain has expired.",
	expirationBanner_description: "Renew your subscription now and enjoy a smooth continuation of the service.<br /> You are getting this notice because your subscription or your free trial period has expired.",
	expirationBanner_domain: "Domain:",
	expirationBanner_subscriptionType: "Subscription type:",
	expirationBanner_serviceFirstDate: "First date of service:",
	expirationBanner_expirationDate: "Expiration date:",
	yourNameHere: "Your name here...",
	yourNameRequired: "Your name (required)",
	clickToEdit: "Click to edit",

	confirmMessage_unbindAccount: "Note: This will unbind this service from your Account. Are you sure?",
	confirmMessage_unbindLastAccount: "WARNING: This is the last remaining service bound to this account.\nIf you proceed, you will not be able to access this account anymore. Are you sure?"
  };
  var $JCL = window.JSCC_Translate || function(t, tmpl) {
	var text = (window.JSKitLabels && window.JSKitLabels[t]) || (window.$JCLTL && $JCLTL[t]) || $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,
	"comment-added": true,
	"comment-deleting": true,
	"comment-deleted": true,
	"comments-data-loaded": true,
	"comments-count-updated": true,
	"user-login": true,
	"user-logout": 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.map(function(v) {
			JSKitAPI.subscribe(v.subscribe, v.callback);
		}, elist);
		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.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();
	obj = obj || {};
	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.addStyle(div, arg.style);
	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.truncate = function(text, maxLength, postfix, cutWords) {
        if (text.length <= maxLength) return text;
        var match = text.match(new RegExp("^.{1," + maxLength + "}\\b"));
        return ((match && !cutWords ? match[0] : false) || text.substr(0, maxLength)) + (postfix || "");
}

JSKitLib.extractDomain = function(url) {
	var match = url.match(/(https?:\/\/)?(www.)?([^\/]*)/);
	return match ? match[3] : url;
}

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 = isFinite(obj) ? obj : 'null'; 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(",") + '}';
			} else {
				out = 'null';
			}
	}
	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.createContainer();
	this.attachContainer();
	if(obj.disabled) {
		this.disableItem();
	} else {
		this.addItemHighlighting();
		this.setAction(this.action);
	}
	if (this.oninit) this.oninit();
	JSKitLib.hide(this.outerCnt);
	if(this.hidden) JSKitLib.hide(this.itemNode);
}

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

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

JSMenuItemBase.prototype.renderTitle = function(cnt) {
	JSKitLib.text(this.title, cnt);
}

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

JSMenuItemBase.prototype.disableItem = function() {
	var self = this;
	JSKitLib.fmap(["item", "icon", "title", "ending"], function(part) {
		JSKitLib.addClass(self[part + "Node"], "jsk-DisabledFontColor");
	});
}

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(["icon", "title", "ending"], function(part) {
				JSKitLib[e.action](self[part + "NodeCnt"], "jskit-MenuItemMO");
			});
		});
	});
}

JSMenuItemBase.prototype.createContainer = function() {
	this.outerCnt = JSKitLib.cr({className: "jskit-MenuContainer"});	
	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, after) {
	if(!this.items.length) {
		this.addExpandMarker();
		this.addExpandHandler();
		this.addCollapseCallback();
	}
	this.innerCnt.insertBefore(item.itemNode, after ? after.itemNode.nextSibling : null);
	this.items.push(item);
	item.parent = this;
}

JSMenuItemBase.prototype.removeItem = function(item2del) {
	JSKitLib.fmap.call(this, this.items, function(item, i) {
		if(item != item2del) return;
		this.innerCnt.removeChild(item.itemNode);
		this.items.splice(i, 1);
	});
}

JSMenuItemBase.prototype.addExpandMarker = function() {
	JSKitLib.text("\u25BA", this.endingNode);
}

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.setAction = function(action) {
	var self = this;
	this.action = action;
	if (action) this.itemNode.onclick = function() {action.call(self);};
}

JSMenuItemBase.prototype.rename = function(text) {
	this.title = text;
	this.titleNode.replaceChild(JSKitLib.text(text), this.titleNode.firstChild);
}

JSMenuItemBase.prototype.hide = function() {
	this.hidden = true;
	JSKitLib.hide(this.itemNode);
}

JSMenuItemBase.show = function() {
	this.hidden = false;
	JSKitLib.show(this.itemNode);
}

/////////////////////////////////////////
//	JS Menu with inner HTML
/////////////////////////////////////////

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

JSMenuItemHTML.prototype = new JSMenuItemBase();

JSMenuItemHTML.prototype.createItem = function() {
	this.itemNode = JSKitLib.cr({t: "tr"});
	var td = this.itemNode.appendChild(JSKitLib.cr({t: "td"}));
	td.colSpan = "3";
	JSKitLib.fmap.call(this, ["Title", "Ending"], function(part) {
		this[part.toLowerCase() + "Node"] = td.appendChild(JSKitLib.cr({style: "float: left;"}));
	});
	this.titleNode.appendChild(this.title);
	JSKitLib.addStyle(this.titleNode, "overflow: hidden; width: 100%;");
}

JSMenuItemHTML.prototype.addItemHighlighting = function(){};

/////////////////////////////////////////
//	JS Menu with checkboxes
/////////////////////////////////////////
function JSMenuItemCheckbox(obj) {
	if(!obj) return;
	obj.controlElementType = "Checkbox";
	this.init(obj);
	this.addCheckEvents();
	this.addDeleteEvent();
	this.setState();
}

JSMenuItemCheckbox.prototype = new JSMenuItemBase();

JSMenuItemCheckbox.prototype.renderIcon = function(cnt) {
	this.checkbox = cnt.appendChild(JSKitLib.html('<div class="jskit-MenuItem' + this.controlElementType + '"></div>'));
	if(this.hideCheckbox) this.checkbox.style.visibility = "hidden";
	JSKitLib.addPNG(cnt.appendChild(JSKitLib.cr({className: "jskit-MenuItemIcon"})), this.icon);
	JSKitLib.addClass(cnt, "jskit-MenuItem" + this.controlElementType + "Cnt");
}

JSMenuItemCheckbox.prototype.renderTitle = function(cnt) {
	JSKitLib.text(this.displayTitle || this.title, cnt);
}

JSMenuItemCheckbox.prototype.renderEnding = function(cnt) {
	if (this.deletable) {
		JSKitLib.addClass(cnt, "jskit-MenuDeleteButton");
		JSKitLib.addPNG(cnt, "//cdn.js-kit.com/images/menu/menu-delete-button.png");
		cnt.title = this.deleteLabel;
	}
}

JSMenuItemCheckbox.prototype.addDeleteEvent = function() {
	var self = this;
	this.endingNode.onclick = function(e) {
		JSKitLib.stopEventPropagation(e);
		if(self.ondelete) self.ondelete.apply(self);
	}
}

JSMenuItemCheckbox.prototype.addCheckEvents = function() {
	var self = this;
	JSKitLib.addEventHandler(self.itemNode, ["click"], function(e) {
		if (!self.state.match(/disabled/)) JSKitLib.stopEventPropagation(e);
		if (self.hideCheckbox) return;
		switch(self.state) {
			case "unchecked": if(self.oncheck) self.oncheck(self.title); self.setState("checked"); break;
			case "checked": if(self.onuncheck) self.onuncheck(self.title); self.setState("unchecked"); break;
		}
	});
}

JSMenuItemCheckbox.prototype.setState = function(state) {
	this.state = state || this.state;
	JSKitLib[(this.state == "disabled" ? "add" : "remove") + "Class"](this.titleNode, "jsk-DisabledFontColor");
	JSKitLib.addPNG(this.checkbox, "//cdn.js-kit.com/images/common/" + this.controlElementType.toLowerCase() + "_" + this.state + ".png");
	if (this.state == "disabled" && this.endingNode) this.endingNode.style.display = 'none';
}

/////////////////////////////////////////
//      JS Menu with radio buttons
/////////////////////////////////////////
function JSMenuItemRadio(obj) {
	if(!obj) return;
	var self = this;
	obj.enableSelect = true;
	obj.controlElementType = "Radio";
	JSKitLib.fmap(obj.extend || {}, function(extendFunc, name) {
		var basicFunc = self[name];
		self[name] = function() {
			basicFunc.apply(self, arguments);
			extendFunc.apply(self, arguments);
		};
	});
	this.init(obj);
	this.addCheckEvents();
	this.setState();
}

JSMenuItemRadio.prototype = new JSMenuItemCheckbox();

JSMenuItemRadio.prototype.renderTitle = function(cnt) {
	cnt.appendChild(this.title);
}

JSMenuItemRadio.prototype.addCheckEvents = function() {
	var self = this;
	JSKitLib.addEventHandler(self.itemNode, ["click"], function(e) {
		if (!self.state.match(/disabled/)) JSKitLib.stopEventPropagation(e);
		self.setActiveState(function() {
			if (self.oncheck) self.oncheck(self.title);
		});
	});
}

JSMenuItemRadio.prototype.setActiveState = function(onActivateCallback) {
	var self = this;
	if (self.state == "unchecked") {
		if (onActivateCallback) onActivateCallback();
		JSKitLib.fmap(self.parent.items, function(item) {
			if (item.type == "Radio" && item.state == "checked") {
				if (item.onuncheck) item.onuncheck(item.title);
				item.setState("unchecked");
			}
		});
		self.setState("checked");
	}
}


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

function JSMenuItemRoot(obj) {
	if(!obj) return;
	this.init(obj);
	JSKitLib.addClass(this.outerCnt, "jskit-MenuRootContainer");
}

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: "jskit-MenuTitle" + part.suff});
	});
	if(this.title) {
		var tbl = JSKitLib.cr({t:"table"});
		tbl.cellSpacing = tbl.cellPadding = "0";
		var row = tbl.insertRow(0);
		JSKitLib.fmap.call(this, ["title", "ending"], function(part, i) {
			row.insertCell(i).appendChild(this[part + "Node"]);
		});
		JSKitLib.preventSelect(this.titleNode);
		JSKitLib.addPNG(this.endingNode, "//cdn.js-kit.com/images/menu/vertical-menu-expand-marker.png");
		JSKitLib.text(this.title, this.titleNode);
		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, "js-kitMenuTitleMO");
		});
	});
}

JSMenuItemRoot.prototype.addExpandHandler = function() {
	var self = this;
	JSKW$Events.registerEventCallback(undefined, function(eventName, menuNode) {
		if (self.itemNode != menuNode) return;
		var need2hide = (self.outerCnt.style.display != "none");
		JSKW$Events.syncBroadcast("JSMenu-CollapseAll");
		if (need2hide) {
			JSKitLib.removeClass(self.titleNode, "js-kitMenuTitlePressed");
		} else {
			JSKitLib.addClass(self.titleNode, "jskit-MenuTitlePressed");
			JSKitLib.show(self.outerCnt, "block");
			if (self.layer && !self.leftPosCorrection) {
				var titleNodePos = JSKitLib.findPos(self.titleNode);
				self.leftPosCorrection = titleNodePos[0] + self.outerCnt.offsetWidth - JSKitLib.findPos(self.layer)[2];
				if (self.leftPosCorrection > 0) self.outerCnt.style.left = (self.outerCnt.offsetLeft - self.leftPosCorrection) + "px";
			}
		}
	}, 'JSMenu-Opened');
	JSKitLib.addEventHandler(this.itemNode, ['click'], function(e) {
		JSKitLib.stopEventPropagation(e);
		JSKW$Events.syncBroadcast('JSMenu-Opened', self.itemNode);
	});
}

JSMenuItemRoot.prototype.addCollapseCallback = function() {
	var self = this;
	JSKW$Events.registerEventCallback(undefined, function() {
		self.outerCnt.style.display = "none";
		JSKitLib.removeClass(self.titleNode, "jskit-MenuTitlePressed");
	}, "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: "jskit-MenuDelimeter"});
	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 input = JSKitLib.html('<input type="text" readonly style="display:none" value="' + this.inputValue + '" class="' + 'jskit-MenuItemInput">');
	JSKitLib.text(this.title, cnt);
	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 Root menu with HTML inside
/////////////////////////////////////////
function JSMenuItemRootHTML(obj) {
	this.init(obj);
	JSKitLib.addClass(this.outerCnt, "jskit-MenuRootContainer");
}

JSMenuItemRootHTML.prototype = new JSMenuItemRoot();

JSMenuItemRootHTML.prototype.createItem = function() {
	this.itemNode = JSKitLib.cr();
	JSKitLib.fmap.call(this, ["Title", "Ending"], function(part) {
		this[part.toLowerCase() + "Node"] = this.itemNode.appendChild(JSKitLib.cr());
	});
	JSKitLib.preventSelect(this.titleNode);
	JSKitLib.addClass(this.itemNode, "jskit-MenuRootHTML");
	this.titleNode.appendChild(this.title);
}

JSMenuItemRootHTML.prototype.addItemHighlighting = function() {}

JSMenuItemRootHTML.prototype.attachContainer = function() {
	this.endingNode.appendChild(this.outerCnt);
}

/////////////////////////////////////////
//	JS Self-Reproducing Checkbox Menu
/////////////////////////////////////////

function JSMenuItemSRCheckbox(obj) {
	var self = this;
	if(!obj) return;
	obj.enableSelect = true;
	obj.controlElementType = "Checkbox";
	this.init(obj);
	this.defaultData = obj;
	this.addCheckEvents();
	this.addDeleteEvent();
	this.setState(this.state || "checked");
}

JSMenuItemSRCheckbox.prototype = new JSMenuItemCheckbox();

JSMenuItemSRCheckbox.prototype.renderTitle = function(cnt) {
	var self = this;
	var title = this.title;
	duplicate = function() {
		if(!self.alreadyEdited && self.title != self.defaultData.title) {
			self.alreadyEdited = true;
			if(!self.unclonable) {
				self.parent.appendItem(new JSMenuItemSRCheckbox(self.defaultData), self);
			}
			self.checkbox.style.visibility = "visible";
			self.hideCheckbox = false;
			if(self.oncreate) self.oncreate(self.title);
			self.setState("checked");
			self.endingNode.style.display = "block";
		} else {
			if(self.onupdate && title != self.title) {
				self.onupdate([title, self.title]);
				title = self.title;
			}
		}
	}
	this.ipe = new JSIPE2({obj: self, property: 'title', jsk$wasEdited: duplicate, maxLength: 100, hideApplyBtn: true, jsk$validate: function(newValue) {if(self.validator) return self.validator.call(self, newValue); else return true;}})
	JSKW$Events.registerEventCallback(0, function() {self.ipe.resetChanges();}, "JSMenu-CollapseAll");
	cnt.appendChild(this.ipe.div);
}

JSMenuItemSRCheckbox.prototype.renderEnding = function(cnt) {
	JSKitLib.addClass(cnt, "jskit-MenuDeleteButton");
	JSKitLib.addPNG(cnt, "//cdn.js-kit.com/images/menu/menu-delete-button.png");
	if(!this.alreadyEdited || this.unclonable) cnt.style.display = "none";
}

JSMenuItemSRCheckbox.prototype.addDeleteEvent = function() {
	var self = this;
	this.endingNode.onclick = function(e) {
		JSKitLib.stopEventPropagation(e);
		if(self.ondelete) self.ondelete(self.title);
		self.parent.removeItem(self);
	}
}

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

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

function JSDogtag(data) {
	var obj = JSKitLib.cr({className: "jskit-Dogtag"});
	JSKitLib.fmap(["Icon", "Text", "Cross"], function(part) {
		var node = JSKitLib.cr({className: "jskit-Dogtag" + part});
		obj.appendChild(node);
		obj[part.toLowerCase() + "Node"] = node;
	});
	JSKitLib.text(JSKitLib.truncate(data.text, 17, "...", true), obj.textNode);
	JSKitLib.preventSelect(obj.textNode);
	JSKitLib.addEventHandler(obj, ['click'], function(e) {
		JSKitLib.stopEventPropagation(e);
	});
	if(data.icon) JSKitLib.addPNG(obj.iconNode, data.icon);
	JSKitLib.addPNG(obj.crossNode, "//cdn.js-kit.com/images/cross.png");
	if (data.onclose) obj.crossNode.onclick = data.onclose; else JSKitLib.hide(obj.crossNode);
	obj.title = data.text;
	obj.hide = function() {
		JSKitLib.hide(obj);
	}
	obj.show = function(newText) {
		JSKitLib.show(obj);
		obj.title = newText || obj.title;
		obj.textNode.replaceChild(JSKitLib.text(JSKitLib.truncate(obj.title, data.maxLength || 12, "...", true)), obj.textNode.firstChild);
	}
	return obj;
}






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";
	} else if (navigator.appName.match(/Opera/)) { 
		JSKitLib.vars.browser = "opera"; 
	}
	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.setEventHandler = function(obj, eventNames, eventHandler) {
	JSKitLib.fmap(eventNames, function(eventName) {
		obj["on" + eventName] = function(){
			eventHandler();
			return false;
		}
	});
}

JSKitLib.resetEventHandler = function(obj, eventNames) {
	JSKitLib.fmap(eventNames, function(eventName) {
		obj["on" + eventName] = function(){};
	});
}

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.setMouseEvent = function(obj, eventName, eventHandler) {
	var normalize = function(pr_event){
		e = pr_event || window.event;
		if (!e.target)
			e.target = e.srcElement || document;
		if (e.target.nodeType == 3)
			e.target = e.target.parentNode;
		if (!e.relatedTarget && e.fromElement)
			e.relatedTarget = (e.fromElement == e.target) ? e.toElement : e.fromElement;
		return e;
	};
	obj["onmouse" + eventName] = function(pr_event) {
		var e = normalize(pr_event);
		if (e.relatedTarget == obj || JSKitLib.isChildNodeOf(obj, e.relatedTarget)) return false;
		eventHandler(e);
	};
}

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.timedRetry = function(obj) {
	if(obj.pred()) {
		obj.onSuccess();
	} else {
		obj.currentRetries = (obj.currentRetries || 0) + 1;
		if(obj.currentRetries > obj.maxRetries) {
			if(obj.onFailure) obj.onFailure();
		} else {
			if(obj.onRetry) obj.onRetry();
			setTimeout(function(){
					JSKitLib.timedRetry(obj);
				}, obj.timeout);
		}
	}
}

JSKitLib.addDOMLoadedListener = function(callback) {
	window.JSK$DOMLoadedCallbacks = window.JSK$DOMLoadedCallbacks || [];
	window.JSK$DOMLoadedCallbacks.push(callback);
	if (window.JSK$DOMLoadedCallbacks.length > 1)
		return;
	var totalListener = function() {
		JSKitLib.fmap(window.JSK$DOMLoadedCallbacks, function(c) { c(); });
	}
	switch (JSKitLib.getBrowser()) {
		case 'gecko':
		case 'opera':
			document.addEventListener("DOMContentLoaded", totalListener, false);
			break;
		case 'IE':
			var temp = document.createElement('div');
			(function() {
				try {
					temp.doScroll('left');
				} catch (e) {
					setTimeout(arguments.callee, 100);
					return;
				}
				totalListener();
			})();
			break;
		case 'safari':
			(function() {
				if (document.readyState != 'complete') {
					setTimeout(arguments.callee, 100);
					return;
				}
				totalListener();
			})();
			break;
		default:
			JSKitLib.addEventHandler(window, ['load'], totalListener);
	}
}






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 if (JSKitLib.isGChrome()) {
		doc.body.insertBefore(se, doc.body.firstChild);
	} 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.getStyleProperty = function(el, prop) {
	if (typeof el == 'string') {
		el = document.getElementById(el);
	}
	if (el.currentStyle) {
		return el.currentStyle[prop];
	} else if (window.getComputedStyle) {
		return document.defaultView.getComputedStyle(el, null).getPropertyValue(prop);
	} else {
		return el.style[prop];
	}
}

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.calcCenterPos = function(elmWidth, elmHeight) {
	var doc = (document.compatMode == "BackCompat") ? document.body : document.documentElement;
	var scroll = JSDL.prototype.getCurScroll();
	return [
		scroll.scroll_left + Math.max(0, Math.round((doc.clientWidth - elmWidth)/2)),
		scroll.scroll_top + Math.max(0, Math.round((doc.clientHeight - elmHeight)/2))
	];
}

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;
		} 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) {
		try {child = child.parentNode;}
		catch(e){child = parent;}
	}
	return child === parent;
}

JSKitLib.replaceChildren = function(where, replacement) {
	JSKitLib.removeChildren(where);
	JSKitLib.addChild(where, replacement);
}

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.hasParentNode = function(el) {
	return el && el.parentNode && el.parentNode.nodeType != 11;
}

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 = "'//cdn.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.text = function(text, element, clear) {
	var textNode = document.createTextNode(text);
	if (element) {
		if (clear) JSKitLib.removeChildren(element);
		element.appendChild(textNode);
	}
	return textNode;
}

JSKitLib.attachDescriptors2Elements = function(elements, layoutBlocksPrefix, descriptors, parentStructure) {
	JSKitLib.fmap(elements, function(element, id) {
		var pattern = id.match(layoutBlocksPrefix + "(.*)");
		var name = pattern ? pattern[1] : undefined;
		if (name && typeof(descriptors[name]) == "function") {
			var node = descriptors[name](element, parentStructure);
			if (node) element.appendChild(node);
		}
	});
}

JSKitLib.toDOM = function(template, layoutBlocksPrefix, descriptors) {
	var content = JSKitLib.html(template);
	var elements = JSKitLib.mapClass2Object({}, content);
	var structure = {
		"set" : function(name, element) { elements[layoutBlocksPrefix + name] = element; },
		"get" : function(name, ignorePrefix) { return elements[((ignorePrefix) ? "" : layoutBlocksPrefix) + name]; },
		"content" : content
	};
	JSKitLib.attachDescriptors2Elements(elements, layoutBlocksPrefix, descriptors, structure);
	return structure;
}

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.addScript = function(src, content, callback) {
	var sId = "js-kit-script-"+src.replace(/[\/.]/g, '');
	content.jsk$scriptId = sId;
	if(document.getElementById(sId)) {
		if (callback) callback();
		return;
	}
	var s = document.createElement('script');
	s.id = sId;
	s.type ='text/javascript';
	s.charset = 'utf-8';
	s.src = src;
	content.appendChild(s);
	if (callback) {
		s.onload = s.onreadystatechange = function() {
			if (s.readyState && s.readyState != 'loaded' && s.readyState != 'complete') return;
			s.onreadystatechange = s.onload = null;
			callback();
		}
	}
	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.overlapSelectsIE = function(target) {
	var container = document.createElement('div');
	container.innerHTML = '<iframe style="position: absolute; z-index: -1; filter: mask(); border: 0; margin: 0; padding: 0; top: 0; left: 0; width: 9999px; height: 9999px; overflow: hidden;"></iframe>';
	target.appendChild(container.firstChild);
}

JSKitLib.openPopup = function(url, extConfig){
	var target = '_blank';
	var config = { 
		'width' : '960',
		'height' : '800',
		'status' : 'no',
		'menubar' : 'no',
		'toolbar' : 'no',
		'resizable' : 'no',
		'location'  : 'yes',
		'scrollbars' : 'yes',
		'directories': 'no'};

	JSKitLib.fmap(extConfig || [], function(value, key){
		if (key == 'target') target = value; else config[key] = value; 
	});

	var calcScreenDimensions = function(){
		if (JSKitLib.isOpera()) {
			var doc = (document.compatMode == "BackCompat") ? document.body : document.documentElement;
			return {'width': doc.clientWidth,
				'height': doc.clientHeight};
		}
		return {'width': screen.width,
			'height': screen.height};
	};

	var calcCorrections = function() {
		if (JSKitLib.isOpera()) return {'height': 35, 'width': 10, 'top' : 0}; 
		if (JSKitLib.isSafari() && !JSKitLib.isGChrome()) return {'height': 150, 'width': 0, 'top' : 100};
		return {'height': 0, 'width': 0, 'top' : 0};
	};

	var screenDimensions = calcScreenDimensions();
	var corrections = calcCorrections();

	if (config.height > screenDimensions.height - corrections.height) config.height = screenDimensions.height - corrections.height;
	if (config.width > screenDimensions.width - corrections.width) config.width = screenDimensions.width - corrections.width;

	if (!(config.left && config.top) && config.width && config.height) {
		config.left = Math.round((screenDimensions.width - config.width)/2);
		config.top = Math.round((screenDimensions.height - corrections.top - config.height)/2);
	}

	var params = JSKitLib.fmap(config, function(value, key) {return key + "=" + value;}).join(", ");
	return window.open(url, target, params);
}





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.lookup = function(f, arr){
	return JSKitLib.filter(f, arr).shift();
}

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);
	});
}

JSKitLib.merge = function() {
	return Array.prototype.concat.apply([], arguments);
}

JSKitLib.cloneObject = function(obj) {
	return JSKitLib.foldl({}, obj, function(value, acc, key) { acc[key] = value; });
}





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) {
	var wl = window.location;
	return wl.protocol + "//" + self.config.domain + wl.pathname;
}

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

JSKitLib.initWidgets = function(widget_type, request, constructor) {
	var sendRequest = function(domain, multiParams, target) {
		if (!multiParams.length)
			return;
		var wl = window.location;
		request = request || {"extra_params": {}};
		var req = {
			uri: request.base_uri,
			ref: wl.protocol + "//" + domain + wl.pathname,
			epb: window.JSKitEPB ? JSKitEPB.getAsHash() : {},
			request: request.extra_params,
			variableRequest: multiParams,
			transport: 'GET',
			target: target,
			trailer: request.trailer
		};
		new JSRVC(req);
	}

	var els = document.body.getElementsByTagName("div");
	if(!els || !els.length)
		return;

	var multiI = {};
	var multiQ = {};
	var obj;
	var reg = new RegExp('js-kit-' + widget_type + '?');
	for (var i = 0; i < els.length; i++) {
		var m = reg.exec(els[i].className);
		if (!m || !m.length || els[i].jsk$initialized)
			continue;

		obj = constructor(els[i]);
		els[i].jsk$initialized = true;
		if (obj.config.disabled && obj.config.disabled != "no") continue;
		var d = obj.config.domain;

		if (!multiQ[d]) {
			multiQ[d] = [];
			multiI[d] = 0;
		}
		multiQ[d].push(obj.singleRequestParams);
		multiI[d]++;
	}
	JSKitLib.fmap(multiQ, function(v, k){ if (v) sendRequest(k, v, obj.target); });
}





JHI2 = {};
JHI2.create = function(hint, element) {
	element = element || JSKitLib.html("<input 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.onclick = function() {
		if(JSKitLib.isIE()) {
			window.focus();
			element.focus();
		}
		return true;
	}
	element.onblur = function() {
		if (!this.defaultRemoved || JSKitLib.trim(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.set = function(element, value) {
	if (element.onfocus) element.onfocus();
	element.value = value;
}

JHI2.isEmpty = function(element) {
	return (element.hint && !element.defaultRemoved || !element.hint && !element.value);
}

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





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

JSKitFBSDK.prototype.processProfile = function() {
	var s = this;
	s.displayState('process');
	s.fetchUserInfo(['name', 'profile_url', 'pic_big', 'pic_square', 'pic_square_with_logo'], function(data){
		if(!data) {
			s.processLoginStatus();
		} else {
			var session = FB.getSession();
			var params = {
				"profile_data" : JSKitLib.Object2JSON(data),
				"access_token" : session.access_token,
				"expires" : session.expires,
				"api_key" : s.api_key,
				"ref" : s.ref,
				"rnd" : Math.random()
			};
			var url = "http://js-kit.com/api/facebook/process_profile?" +
				JSKitLib.fmap(params, function(value, key) {
					return key + "=" + encodeURIComponent(value);
				}).join("&");
			JSKitLib.addScript(url, s.target);
		}
	});
}

JSKitFBSDK.prototype.fetchUserInfo = function(flds, cb) {
	var s = this;
	var session = FB.getSession();
	if(!session) return(cb(undefined));
	FB.api({
		method: 'Users.getInfo',
		session_key: session.session_key,
		api_key: s.api_key,
		sig: session.sig,
		uids: [session.uid],
		fields: flds,
		v: "1.0"}, function(data){
					cb(data);
				});
}

JSKitFBSDK.prototype.processLogin = function() {
	var slf = this;
	FB.login(function(r){
		if(r.session){
			slf.processLoginStatus();
		} else {
			slf.displayState('login');
		}
	}, {perms:'publish_stream'});
}

JSKitFBSDK.prototype.processLoginStatus = function() {
	var s = this;
	s.displayState('login');
	FB.getLoginStatus(function(response){
		if(response.session){
			s.processProfile();
		} else {
			s.displayState('login');
		}
	}, true);
}

JSKitFBSDK.prototype.createHiddenContainer = function() {
	var div = document.getElementById('fb-root');
	if (div) return div;
	var div = JSKitLib.html('<div id="fb-root" style="position:absolute; top: -10000px; left: -10000px; width: 0px; height: 0px;"></div>');
	document.body.insertBefore(div, document.body.firstChild);
	return div;
}

JSKitFBSDK.prototype.shareComment = function(whiteLabel) {
	var s = this;
	var sd = this.sharedata;
	FB.getLoginStatus(function() {
		var sess = FB.getSession();
		if(sess) {
			s.fetchUserInfo(['name'], function(data) {
				if(data && !data.error_code){
					var al = whiteLabel ? null :
						[{'text': 'Visit JS-Kit', 'href': 'http://js-kit.com/'}];
					FB.api({
						method: 'stream.Publish',
						session_key: sess.session_key,
						api_key: s.api_key,
						sig: sess.sig,
						v: "1.0",
						message: sd.Text,
						attachment: {
							'name': data[0].name + ' participated in a discussion on ' + sd.domain,
							'href': sd.permalink},
						action_links: al
						});
				}
			});
		} else {
			FB.login(function(r){
				if(r.session){
					s.shareComment(whiteLabel);
				}}, {perms:'publish_stream'});
		}
	}, true);
}

JSKitFBSDK.prototype.init = function(cb) {
	var s = this;
	if(!s.api_key || !s.target) return;
	window.jsk$fb_init = true;
	var initFB = function() {
		FB.init({
			appId: s.api_key,
			status: false,
			cookie: true,
			xfbml: true
		});
		if(cb) cb();
	};
	if(!window.FB || !FB.init) {
		JSKitLib.addScript('http://connect.facebook.net/en_US/all.js', s.target, function() { initFB(); });
	} else {
		initFB();
	}
}

JSKitFBSDK.prototype.logout = function() {
	FB.logout();
}

function JSKitFBSDK(ref, api_key, xd_receiver, cb, form_id, sharedata) {
	this.ref = ref;
	this.form_id = form_id;
	this.target = this.createHiddenContainer();
	this.api_key = api_key;
	this.xd_receiver = xd_receiver;
	this.sharedata = sharedata;
	var s = this;
	var f = function() {
		if (cb) cb.apply(s);
	};
	if (window.jsk$fb_init) {
		f();
	} else {
		this.init(f);
	}
}

JSKitFBSDK.prototype.detectXD = function(target) {
	// nothing to do
}





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) {
				window.jsk$gfc_token = securityToken;
				if(cb) cb();
			}
		});
	};
	if(!window.google || !window.opensocial) {
		JSKitLib.addScript('http://www.google.com/friendconnect/script/friendconnect.js?key=notsupplied&v=0.8', s.target, function() { initGFC(); });
	} else {
		initGFC();
	}
}

JSKitGFC.prototype.processProfile = function(profileData) {
	JSKitLib.addScript('//js-kit.com/api/google/process_profile?'
		+'id='+encodeURIComponent(profileData.getId())
		+'&st='+encodeURIComponent(window.jsk$gfc_token)
		+'&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 = $JCL("loggingIn") + profileData.getDisplayName() + '...';
		s.displayState('process');
		s.processProfile(profileData);
	}, function() {
		s.displayState('login');
		google.friendconnect.renderSignInButton({ 'id': 'login-' + s.tgt, 'text' : $JCL("loginWithGFC"), '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 + $JCL("justPostedCommentOn") + ' <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>' + $JCL("poweredBy") + ' <a href="http://js-kit.com/">JS-Kit Echo</a>';
		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() { cb.apply(s); };
	if(window.jsk$gfc_init) {
		f();
	} else {
		this.init(f);
	}
}





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

$JALT = {
	//Authentication methods labels:
	identityLabel_short_epb: "EPB",
	identityLabel_short_gfc: "Google Friend Connect",
	identityLabel_short_home: "My Site",
	identityLabel_short_jskit: "JS-Kit",
	identityLabel_short_yahoo: "Yahoo!",
	identityLabel_short_openid: "Openid",
	identityLabel_short_twitter: "Twitter",
	identityLabel_short_haloscan: "Haloscan",
	identityLabel_short_blogspot: "Blogger",
	identityLabel_short_facebook: "Facebook",
	identityLabel_short_friendfeed: "FriendFeed",

	identityLabel_full_epb: "My EPB Account",
	identityLabel_full_gfc: "My Google Profile",
	identityLabel_full_jskit: "My JS-Kit Account",
	identityLabel_full_yahoo: "My Yahoo! Account",
	identityLabel_full_openid: "My OpenID",
	identityLabel_full_twitter: "My Twitter Account",
	identityLabel_full_haloscan: "My Haloscan Account",
	identityLabel_full_blogspot: "My Blogger Account",
	identityLabel_full_facebook: "My Facebook Profile",
	identityLabel_full_register: "New JS-Kit Account",
	identityLabel_full_friendfeed: "My FriendFeed 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)',
	cookies_are_disabled: 'Unfortunately authentication is not available for you because the cookies are disabled in your browser. Please enable cookies and retry',
	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',
	passwordRecovery_jskit: 'JS-Kit Password Recovery',
	passwordRecovery_haloscan: 'Haloscan 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?',
	registerNewAccount: 'register a new account?',
	sendPassword: 'Send Password',
	authCode: 'Auth Code',
	jskaLogout: 'Logout',
	submit: 'Submit',
	back: 'Back',
	login: 'Login',
	username: 'Username',
	loginWith: 'Login with:',
	loginBtn: 'Login',
	register: 'Register',
	openID: 'OpenID:',
	password: 'Password:',
	retypePassword: 'Re-type Password:',
	loginWith: 'Login with:',
	cancel: 'Cancel',
	loading: 'Loading ...',
	allFieldsAreMandatory: 'All fields are mandatory',
	yourEmail: 'Your Email',
	blogspotUrl: 'Blogspot URL:',
	//EPB
	epb_LoginOrRegisterInHostSiteText: 'Please login or register on this site'
}
$JAL = window.JSKA_Translate || function(t) { return (window.JSKitLabels && window.JSKitLabels[t]) || $JALT[t] || t; }

JSKAuth.prototype.getIdentityLabel = function(type, isfull){
	return $JAL("identityLabel_" + (isfull ? "full_" : "short_") + type);
} 

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) {
	areaName = areaName || this.defaultActiveArea;
	this.setAuthInstance();
	this.showBackdrop();
	var authForm = this.authForm;
	if (this.mode == "popup") {
		var pos = JSKitLib.calcCenterPos(300, 200);
		authForm.style.top = parseInt(pos[1]) + "px";
		authForm.style.left = parseInt(pos[0]) + "px";
	}
	JSKitLib.show(authForm);
	this.authSelector.value = areaName;
	this.setActiveArea(areaName, data);
}

JSKAuth.prototype.loadCss = function() {
        JSKitLib.addCss(
		".jska-backdrop { opacity: 0; background-color: #404040; z-Index: 14500; " +
			(JSKitLib.isPreIE8()
			? "filter:progid:DXImageTransform.Microsoft.Alpha(opacity='0'); position: absolute; top: expression(eval(-(document.body.offsetTop + (document.body.offsetHeight - document.body.clientHeight)/2))); left: expression(eval(-(document.body.offsetLeft + (document.body.offsetWidth - document.body.clientWidth)/2))); height: expression(eval(Math.max(document.body.offsetHeight, document.documentElement.scrollHeight))); width: expression(eval(Math.max(document.body.offsetWidth, document.documentElement.scrollWidth)));"
			: "position: fixed; left: 0; top: 0; height: 100%; width: 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; font-weight: normal; }" +
		".jska-facebookFrame { height: 27px; width: 194px; background-color: transparent; border: none; z-Index: 14000; }" +
		".jska-yahoo { margin-left: auto; margin-right: auto; width:161px; height:22px; cursor:pointer; }" +
		".jska-twitter { margin-left: auto; margin-right: auto; width:176px; height:28px; cursor:pointer; }" +
		".jska-friendfeed { margin-left: auto; margin-right: auto; width:216px; height:28px; cursor:pointer; }" +
		".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-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%; margin-bottom: 2px;}" +
		".jska-leftColumn { float: right; width: 33%; padding: 2px 5px 0 0; text-align: right;}" +
		".jska-label { font-size: 9pt; font-family: Arial; color: #000000 !important; }" +
		".jska-input { border: solid 1px #7f99b9; width: 80%;}" +
		".jska-openidInput { background: url(//cdn.js-kit.com/images/openid-16x16.png) no-repeat; background-position: 0 50%; padding-left: 18px;}" +
		".jska-blogspotInput { background: url(//cdn.js-kit.com/images/blogger-16x16.png) no-repeat; background-position: 0 50%; padding-left: 18px;}" +
		".jska-errorText { color: #FF3030; font: 11px Arial; margin-bottom: 2px; }" +
		".jska-error { color: #FF3030; font: 11px Arial; display: none; }" +
		".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-links, a.jska-links:hover, a.jska-links:visited { 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(//cdn.js-kit.com/images/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(this.identities.auth, function(identity){
		if(identity.group != "third_party") return;
		if(self.areas && self.areas[identity.type] && self.areas[identity.type].rpickup) {
			try{ self.areas[identity.type].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.parentNode;
	if (prn) prn.removeChild(this.authForm);
}

JSKAuth.prototype.prepareAuthForm = function() {
	var self = this;
	var div = self.authForm;
	JSKitLib.hide(div);
	if (self.mode == "popup"){
		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.assemble = function() {
	var self = this;
	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"];

	self.authSelector = self.createAuthSelector(self.defaultActiveArea, function(ev){ self.setActiveArea(this.value); });
	authFormElements["jska-selectorContainer"].appendChild(self.authSelector);

	return authForm;
}

JSKAuth.prototype.createRVCPickupRequest = function(provider, target, area) {
	var self = this;
	var params = {
		'session_nonce': ((new Date()).valueOf() + Math.random()).toString()
	};

	return new JSRVC({
		'uri': self.uriDomain + '/api/server-answer.js',
		'ref': self.ref,
		'request': params,
		'target': target,
		'pickup': true,
		'epb': window.JSKitEPB ? JSKitEPB.getAsHash() : {},
		'onreturn': function (error) 
		{
			if (error == "attempts_number_exceeded") 
			{
				if (provider == "jskit" || provider == "haloscan" || provider == "register")
				{
					try 
					{
						if (window['JSKitAuthInstance']) window['JSKitAuthInstance'].serverCallback(provider, 'cookies_are_disabled');
					} catch(e){}
				}else
				{
					var areaElements = JSKitLib.mapClass2Object({}, area);
					areaElements["js-errorMessageHandle"].innerHTML = $JAL('cookies_are_disabled');
                        		areaElements["js-errorMessageHandle"].style.display = 'block';
				}
			}
		},
		'requestId': provider + '_connect'});
}

JSKAuth.prototype.setActiveArea = function(name, data){
	var self = this;
	self.cancelRequests();
	self.currentArea = name;
	if (name.match(/passwordRecovery/)) JSKitLib.hide(self.selectorContainer); else JSKitLib.show(self.selectorContainer);
	JSKitLib.removeChildren(self.areaContainer);
	self.areas[name] = self.createArea(name, data);
	self.areaContainer.appendChild(self.areas[name]);
	if (self.HNDL && self.HNDL[name] && self.HNDL[name]["input"] && self.HNDL[name]["input"].login){
		self.HNDL[name]["input"].login.blur();	
		self.HNDL[name]["input"].login.focus();
	}

	if (name == "yahoo"){ self.areas["yahoo"].rpickup = self.createRVCPickupRequest("yahoo", self.target, self.areas["yahoo"]); }
	if (name == "gfc"){
		var gfc_cb = function() {
			self.areas["gfc"].rpickup = self.createRVCPickupRequest("gfc", self.target, self.areas["gfc"]);
		};
		var gfc = self.getAuthIdentity("gfc");
		if(gfc && gfc.params.site) {
			var jsk$gfc = new JSKitGFC(
				self.ref,
				self.areas["gfc"].id,
				gfc.params.site,
				function(){
					this.onready = gfc_cb();
					this.processLoginStatus();
				});
		} else {
			gfc_cb();
		}
	}
	if (name == "twitter"){ self.areas["twitter"].rpickup = self.createRVCPickupRequest("twitter", self.target, self.areas["twitter"]); }
	if (name == "friendfeed"){ self.areas["friendfeed"].rpickup = self.createRVCPickupRequest("friendfeed", self.target, self.areas["friendfeed"]); }
	if (name == "facebook" && self.getAuthIdentity("facebook")) {
		var facebook = self.getAuthIdentity("facebook");
		var jsk$fb = new JSKitFBSDK(
			self.ref,
			facebook.params.app_id,
			facebook.params.xd_receiver,
			function() {
				this.processLoginStatus();
				self.areas["facebook"].rpickup = self.createRVCPickupRequest("facebook", self.target, self.areas["facebook"]);
			},
			self.areas["facebook"].id
		);

		var logel = document.getElementById('login-' + self.areas["facebook"].id);
		logel.onclick = function() { jsk$fb.processLogin(); };
	}
}

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(template) {
	return JSKitLib.html(template.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.getIdentityParam = function(name, identity, defaultValue) {
	return (identity.type == 'epb' && identity.params[name]) ? 
		identity.params[name] :
		defaultValue;
}


JSKAuth.prototype.authFormTmpl =
'<div class="jska-wrapper">' +
	'<div class="jska-header">' +
		'<div class="jska-headerText">{Label:authentication}</div>' +
		'<div class="jska-clear"></div>' +
	'</div>' +
	'<div class="jska-selectorContainer jska-label">{Label:loginWith}</div>' +
	'<div class="jska-container"></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 = function(identity_type) {
	return '<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-links 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 name="provider" value="jskit" type="hidden">' +
		'<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.jskitSectionTmpl = JSKAuth.prototype.loginSectionTmpl('jskit');
JSKAuth.prototype.haloscanSectionTmpl = JSKAuth.prototype.loginSectionTmpl('haloscan');

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 class="jska-error js-errorMessageHandle"></div>' +
'<div class="jska-yahoo"></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 class="jska-error js-errorMessageHandle"></div>' +
'<div class="jska-twitter"></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.friendfeedSectionTmpl =
'<div style="text-align: center">' +
'<div class="jska-progressArea js-progressHandle"></div>' +
'<div class="jska-error js-errorMessageHandle"></div>' +
'<div class="jska-friendfeed"></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.epbSectionTmpl = function() {
	var epb = this.identities.auth.epb;
	var auth_prompt = JSKAuth.prototype.getIdentityParam('auth_prompt', epb, '{Label:epb_LoginOrRegisterInHostSiteText}');
	var template = 
'<div style="text-align: center">' +
	'<p class="jska-text">' + auth_prompt + '</p>' +
	'<div class="jska-controls">' +
		'<input value="{Label:cancel}" name=cancelBtn type="button" class="jska-cancelBtn">' +
		'<div class="jska-clear"></div>' +
	'</div>' +
'</div>';
	return template;
}

JSKAuth.prototype.facebookSectionTmpl = function() {
	var tgt = "facebook-" + Math.random();
	return ('<div id="' + tgt + '" style="text-align: center;">' +
'<div class="jska-progressArea js-progressHandle"></div>' +
'<div class="jska-error js-errorMessageHandle"></div>' +
'<div name=' + tgt + '" style="width: 200px; height: 27px; margin: auto; "><div id="wait-' + tgt + '">' + $JCL("askingFacebook") + '</div><div id="login-' + tgt + '" style="display: none; width: 200px; height: 27px; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'//cdn.js-kit.com/images/facebook/connect_white_large_long.gif\', sizingMethod=\'crop\');' : 'background: no-repeat url(//cdn.js-kit.com/images/facebook/connect_white_large_long.gif);') + ' cursor:pointer;"></div><div id="process-' + tgt + '" style="display: none;">' + $JCL("loggingIn") + '<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 gfc = this.identities.auth.gfc;
	var tgt = "gfc-" + Math.random();
return '<div id="' + tgt + '" style="text-align: center">' +
'<div class="jska-progressArea js-progressHandle"></div>' +
'<div class="jska-error js-errorMessageHandle"></div>' +
(gfc && gfc.params.site ? '<div name="' + tgt + '"><div id="wait-' + tgt + '">' + $JCL("askingGoogle") + '</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" scrolling="no"></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-errorText" 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 = function(params) {
	return '<div>' +
	'<p class="jska-text jska-passwordRecoveryText"><b>{Label:passwordRecovery_'+params.provider+'}</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 name="provider" value="jskit" type="hidden">' +
		'<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 = function(params) {
	return '<div>' +
	'<p class="jska-text jska-passwordRecoveryText"><b>{Label:passwordRecovery_'+params.provider+'}</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 name="provider" value="jskit" type="hidden">' +
		'<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 = function(params) {
	return '<div>' +
	'<div class="jska-passwordRecoveryText">' +
		'<p class="jska-text"><b>{Label:passwordRecovery_'+params.provider+'}</b></p>' +
		'<p class="jska-text">New password was set successfully. </p>' +
		'<a class="jska-linkToLogin jska-links 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", this.passwordRecoveryData);break;
			case "passwordRecoverySetPassword" : this.show("passwordRecoverySuccess", this.passwordRecoveryData); 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.blur(); 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.logout = function() {
	var self = this;
	setTimeout(function(){
		new JSRVC({uri: self.uriDomain + '/api/session/logout.js', 'target': self.target, request: {}});
	}, 0);
}

JSKAuth.prototype.createArea = function(name, data) {
	var self = this;
	var sectionTmpl = self[name + "SectionTmpl"];
	var area = self.toDom(typeof(sectionTmpl) == "function" ? sectionTmpl.apply(self, [data]) : 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"]);

	bindOnclick(areaElements["jska-logout"], function(){ self.logout(); self.hide();});
	if (areaElements["jska-logout"] && (!self.loginStatus || JSKitEPB.isExists())) {
		JSKitLib.hide(areaElements["jska-logout"]);
	}

	bindOnclick(areaElements["jska-forgotPassword"], function(){ self.show("passwordRecoveryRequest", {'provider': name}) });
	bindOnclick(areaElements["jska-linkToLogin"], function(){ self.show(data.provider) });
	if (name.match(/passwordRecovery/)) {
		bindOnclick(areaElements["jska-back"], function(){ self.show(data.provider) });
	}

	bindOnclick(areaElements["jska-yahoo"], function(){ JSKitLib.openPopup(self.uriDomain + '/api/oauth/yahoo.html?ref='+encodeURIComponent(self.ref), {height: "450", width: "600", scrollbars: "no"}); });
	bindOnclick(areaElements["jska-twitter"], function(){ JSKitLib.openPopup(self.uriDomain + '/api/oauth/twitter.html?ref='+encodeURIComponent(self.ref), {height: "435", width: "800", scrollbars: "no"}); });
	bindOnclick(areaElements["jska-friendfeed"], function(){ JSKitLib.openPopup(self.uriDomain + '/api/oauth/friendfeed.html?ref='+encodeURIComponent(self.ref), {height: "435", width: "800", scrollbars: "no"}); });
	if (areaElements["jska-yahoo"]) JSKitLib.addPNG(areaElements["jska-yahoo"], "//cdn.js-kit.com/images/yahoo/yos.png");
	if (areaElements["jska-twitter"]) JSKitLib.addPNG(areaElements["jska-twitter"], "//cdn.js-kit.com/images/twitter/twitter.png");
	if (areaElements["jska-friendfeed"]) JSKitLib.addPNG(areaElements["jska-friendfeed"], "//cdn.js-kit.com/images/friendfeed/friendfeed.png");
	var identity = this.getAuthIdentity(name);
	if (identity && identity.group == "third_party") 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,
				type: type};
			if (self.loginReturnUrl) params["returnUrl"] = self.loginReturnUrl;
			if (type == "register") {
				params["retype_password"] = self.HNDL["register"]["input"].password2.value;
				params["email"] = self.HNDL["register"]["input"].email.value;
				params["version"] = "1";
				if (self.registerReturnUrl) {
					params["returnUrl"] = self.registerReturnUrl;
				}
			}
			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", "jskit" : "/user-login", "haloscan" : "/user-haloscan-login"};
			new JSRVC({
					'uri': self.uriDomain + scripts[type],
					'transport': "POST", 
					'target': self.target, 
					'ref': self.ref,
					'request': params,
					'requestId': type + '_connect',
					'onreturn': function () {
						area.rpickup = self.createRVCPickupRequest(type, self.target)
					},	 
					'epb': window.JSKitEPB ? JSKitEPB.getAsHash() : {}
				});
		}
	};

	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 = JSKitLib.openPopup(AuthUrl + '&action=prfl&jsktid=' + PPID);
			} else {
				window.location = AuthUrl + '&action=prfl' + (self.loginReturnUrl ? ("&returnUrl=" + self.loginReturnUrl) : "");
			}
		}
	}

	var constructPasswordRecoveryRequest = function(){
		return function(){
			var loginInputBox = self.HNDL["passwordRecoveryRequest"]["input"].login;
			var provider = self.HNDL["passwordRecoveryRequest"]["input"].provider.value;
			if (loginInputBox.value.length < 1 || !loginInputBox.defaultRemoved) {
				self.showErrorMessage('passwordRecoveryRequest', 'empty_login');
			} else {
				self.passwordRecoveryData["login"] = loginInputBox.value;
				self.passwordRecoveryData["provider"] = provider;
				new JSRVC({uri: self.uriDomain + '/user-password-recovery', 'target': self.target, request: {login: loginInputBox.value, provider: provider}});
			}
		}
	}


	var constructPasswordRecoverySetPassword = function(){
		return function(){
			var inputCollection = self.HNDL["passwordRecoverySetPassword"]["input"]
			var provider = self.HNDL["passwordRecoverySetPassword"]["input"].provider.value;
			var params = {
				step: "set-password",
				provider: provider,
				login: inputCollection.login.value,
				key: JSKitLib.trim(inputCollection.authCode.value),
				password: inputCollection.password.value,
				retype_password: inputCollection.password2.value
			}
			new JSRVC({uri: self.uriDomain + '/user-password-recovery', 'target': self.target, request: params});
		}
	}

	var specificSubmitActions = {
		jskit : createAction("jskit"),
		openid : createOpenidAction("openid"),
		blogspot : createOpenidAction("blogspot"), 
		haloscan : createAction("haloscan"), 
		register: createAction("register"),
		passwordRecoveryRequest     : constructPasswordRecoveryRequest(), 
		passwordRecoverySetPassword : constructPasswordRecoverySetPassword()
	};

	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"],
			provider : areaElements["provider"]}
	};

	if (name != "passwordRecoverySetPassword") JHI2.create( (name == "openid" ? "http://user.myopenid.com" : (name == "blogspot" ? "http://yourblog.blogspot.com" : "Joe.Bloggs")), self.HNDL[name]["input"].login); 

	data = data || {};
	if (name == "jskit" || name == "haloscan")
		data.provider = name;
	JSKitLib.fmap(data, function(value, key){
		if (self.HNDL[name]["input"][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(selected, onchange, includeUserName) {
	var authSelector = this.toDom(
		'<select class="jska-selector">' +   
			JSKitLib.foldl("", this.getAuthOptions(includeUserName), function(text, acc, option) {
				return acc + '<option value="' + option + '"' + ((selected == option) ? ' selected="true"' : '') + '>' + text + '</option>';
			}) +
		'</select>');
	authSelector.onchange = onchange;
	return authSelector;
}

JSKAuth.prototype.getAuthOptions = function(includeUserName) {
	var s = this;
	var calcLogin  = function() {
		var identities = s.getAuthenticatedIdentities();
		var firstLoggedIdentity = identities.length ? identities.shift() : undefined;
		return firstLoggedIdentity
			? (firstLoggedIdentity.name || firstLoggedIdentity.user) + ' @ '
				+ JSKAuth.prototype.getIdentityLabel(firstLoggedIdentity.type)
			: undefined;
	}

	var authOptions = {};
	var login = calcLogin();
	if (includeUserName) {
		authOptions = login
			? {"opt-user": login}
			: {"opt-anonymous": $JCL('guest')};
	}
	JSKitLib.fmap(s.identities.auth, function(v, k) {
		authOptions[k] = JSKAuth.prototype.getIdentityParam('long_label', v, JSKAuth.prototype.getIdentityLabel(k, true));
	});
	return authOptions;
}

JSKAuth.prototype.isLogged = function() {
	var self = this;
	if (this.loginStatus === undefined) {
		JSKitLib.fmap(this.identities.auth, function(identity, type) {
			if (!self.loginStatus) self.loginStatus = !!identity.user;
		});
		this.loginStatus = JSKitEPB.isExists() || this.loginStatus;
	}
	return this.loginStatus;
}

JSKAuth.prototype.isAvailable = function(type) {
	return !!this.identities.auth[type];
}

JSKAuth.prototype.assembleIdentity = function(url, type, group) {
	var identity = this.getAuthIdentity(type);
	return {
		"url": url,
		"type": type,
		"group": group,
		"use_as_from": true,
		"params": identity && identity.params || {}
	};
}

JSKAuth.prototype.appendIdentity = function(identity) {
	if (identity.group == "web") {
		this.identities.web.push(identity);
	} else {
		this.identities.auth[identity.type] = identity;
	}
}

JSKAuth.prototype.getAuthIdentity = function(type) {
	return this.identities.auth[type];
}

JSKAuth.prototype.getIdentities = function(group) {
	return group ? this.identities[group] : this.identities;
}

JSKAuth.prototype.getAuthenticatedIdentities = function() {
	return JSKitLib.fmap(this.getIdentities("auth"), function(identity) {
		if (identity.user) return identity;
	});
}

JSKAuth.prototype.getFirstAuthIdentity = function() {
	var identities = this.getIdentities("auth");
	for (var key in identities) {
		if (identities.hasOwnProperty(key)) return identities[key];
	}
}

JSKAuth.prototype.readIdentities = function(identities) {
	identities = identities || [];
	return JSKitLib.foldl({"auth": {}, "web": []}, identities,
		function(identity, accumulator) {
			if (identity.group == "web") accumulator.web.push(identity);
			else {
				identity.params = identity.params || {};
				accumulator.auth[identity.type] = identity;
			}
		}
	);
}

JSKAuth.prototype.setWebIdentities = function(identities) {
	this.identities.web = identities;
}

JSKAuth.prototype.identityServerAction = function(action, identity, newData, onSuccess) {
	newData = newData || {};
	var self = this;
	var f = function(eventName) {
		switch (action) {
			case "unbind":
				if (identity.group == "web") {
					self.identities.web = JSKitLib.filter(function(i) {
						return i.url != identity.url;
					}, self.identities.web);
				} else {
					identity.user = undefined;
					identity.use_as_from = false;
				}
				break;
			case "bind":
				self.appendIdentity(identity);
				break;
			case "update":
				identity.url = newData.url;
				break;
		}
		JSKW$Events.deRegisterEventCallback(eventContext, f, eventName);
		if (onSuccess) onSuccess();
	}
	var eventContext = JSKW$Events.registerEventCallback(undefined, f, "JSKitAuth_identityAction");
	var params = {
		'action': action,
		'type': identity.type,
		'group': identity.group,
		'url': identity.url
	}
	if (action == "update") params.newurl = newData.url;
	new JSRVC({uri: this.uriDomain + '/user-identity-action',
		'ref': this.ref,
		'epb': window.JSKitEPB ? JSKitEPB.getAsHash() : {},
		'target': this.target, request: params});
}

JSKAuth.prototype.actualizeGFCprofileURL = function(url, domain, siteID) {
	url = url.replace(/\/\/js-kit.com/, "//" + domain);
	url = url.replace(/site=(.*)/, "site=" + siteID);
	return url;
}

JSKAuth.prototype.drawSelector = function(container) {
	if (!container) return;
	var self = this;
	var selector = this.createAuthSelector(0, function() {
		if (this.selectedIndex == 0) return;
		self.show(this.value);
	}, true);
	JSKitLib.removeChildren(container);
	container.appendChild(selector);
}

function JSKAuth(config) {
	this.areas = {};
	this.uriDomain = (window.location.protocol.substr(0, 4) != 'http' ? 'http:' : '') + '//js-kit.com';
	this.passwordRecoveryData = {};
	JSKitLib.fmap.call(this, config, function(v, k){ this[k] = v; });
	this.identities = this.readIdentities(config.identities);
	var firstIdentity = this.getFirstAuthIdentity();
	this.defaultActiveArea = firstIdentity && firstIdentity.type;
	this.authForm = this.assemble();
	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
       || JSKitLib.getStyleProperty(this.elmParent, '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 JSKAvatars(config) {
	JSKitLib.fmap.call(this, config, function(value, key) { this[key] = value; });
	this.controls = this.controls || [];
	this.avatarPreviewImgs = {};
	this.avatars = this.getAsHash(this.avatars);
	this.menuItems = this.prepareMenuItems(this.identities, this.avatars);
	this.activateEvents();
	this.loadCSS();
}

JSKAvatars.prototype._labels = {
	"anonymousAvatar": "No avatar",
	"jskitAvatar": "My computer",
	"gravatarEmail": "Gravatar email",
	"useAvatarFrom": "Use my avatar from...",
	"clickToEditAvatars": "Click to edit avatars",
	"actionUploadAvatar": "Click to upload avatar from your computer",
	"actionEditGravatarEmail": "Click to edit Gravatar email"
}

JSKAvatars.prototype.label = function(name) {
	return this.labels && this.labels(name) != name && this.labels(name) || this._labels[name] || name;
}

JSKAvatars.prototype.getAsHash = function(avatars) {
	return JSKitLib.foldl({}, avatars, function(avatar, acc) { acc[avatar.type] = avatar; });
}

JSKAvatars.prototype.getAvatarByType = function(type) {
	return this.avatars[type] || this.anonymousAvatarData();
}

JSKAvatars.prototype.formatMenuItem = function(type, descriptors, extraParams, icon, title) {
	var self = this;
	var avatar = this.getAvatarByType(type);
	var item = {
		"type": "Radio",
		"icon": icon || ("//cdn.js-kit.com/images/favicons/" + type + ".png"),
		"title": self.assembleMenuItemTitle(type, avatar, title, descriptors),
		"state": avatar.chosen ? "checked" : "unchecked",
		"avatarType": type,
		"extend": {
			"setState": function() {
				if (this.endingNode) JSKitLib.show(this.endingNode);
			},
			"renderEnding": function(element) {
				JSKitLib.addClass(element, "jskit-AvatarMenuItemEnding");
				self.avatarPreviewImgs[type] = element;
				self.setPreviewImage(type, avatar);
			}
		},
		"oncheck": function(title) {
			self.updateActiveAvatar(self.getAvatarByType(type));
			if (self.autoSave) {
				self.saveAvatarState();
				JSKW$Events.syncBroadcast("JSKitAvatars_replaceAvatars",
					[self.getAvatarByType(type)], undefined, self.id);
			}
			if (extraParams["oncheckCallback"]) {
				extraParams["oncheckCallback"].call(this);
			}
		}
	};
	return JSKitLib.foldl(item, extraParams || {}, function(value, acc, key) { acc[key] = value; });
}

JSKAvatars.prototype.saveAvatarState = function() {
	var activeAvatar = this.getActiveAvatar();
	this.sendServerRequest("activate", activeAvatar ? {"name": activeAvatar.name} : {});
}

JSKAvatars.prototype.prepareMenuItems = function(identities, avatars) {
	var self = this;
	var itemsEPB = JSKitLib.fmap(avatars, function(avatar, type) {
		if (!type.match(/^http:\/\/.*/)) return;
		var params = avatars[type].params || {};
		var item = self.formatMenuItem(
			type,
			{},
			{"state": self.getAvatarByType(type).chosen ? "checked" : "unchecked"},
			params.favicon || '//cdn.js-kit.com/images/favicons/default.png',
			params.long_label || JSKAuth.prototype.getIdentityLabel('epb')
		);
		return item;
	});
	var itemsThirdParty = JSKitLib.fmap(identities, function(identity, type) {
		if (identity.authenticated && !avatars[type]) return;
		return self.formatMenuItem(type, {}, {
			"state": identity.authenticated ?
				self.getAvatarByType(type).chosen ? "checked" : "unchecked" :
				"disabled",
			"action": identity.action ? function() { identity.action(); } : undefined 
		}, undefined, identity.title);
	});
	return JSKitLib.merge(
		{"title": JSKitLib.html('<div class="js-kit-avatars-menu-title">' + this.label("useAvatarFrom") + '</div>'), "type": "HTML"},
		this.assembleAnonymousFormItem(),
		this.assembleUploadFormItem(),
		itemsEPB,
		itemsThirdParty,
		this.assembleGravatarsForm(),
		{"title": JSKitLib.html('<div class="js-kit-avatars-menu-footer"></div>'), "type": "HTML"}
	);
}

JSKAvatars.prototype.anonymousAvatarData = function() {
	return {"name": "gxpA99f0jKlohF_DgthroT.png", "type": "anonymous", "width": "100", "height": "100"};
}

JSKAvatars.prototype.classifyAvatarType = function(type) {
	return type.match(/^http:\/\//) ? 'epb' : type;
}

JSKAvatars.prototype.assembleMenuItemTitle = function(type, avatar, title, descriptors) {
	type = this.classifyAvatarType(type);
	var template =
	'<div class="js-kit-avatars-itemTitleContainer js-kit-avatars-itemTitleCnt-' + type + '">' +
		'<div class="js-kit-avatars-itemTitle">' + (title || this.label(type + "Avatar")) + '</div>' +
	'</div>';
	return JSKitLib.toDOM(template, "js-kit-avatars-", descriptors || {}).content;
}

JSKAvatars.prototype.assembleAnonymousFormItem = function() {
	return this.formatMenuItem("anonymous", {}, {
		"state": this.getActiveAvatar() ? "unchecked" : "checked"
	}, "//cdn.js-kit.com/images/favicons/noname.png");
}

JSKAvatars.prototype.assembleUploadFormItem = function() {
	var self = this;
	var descriptor = function(element, dom) {
		dom.get("itemTitle").title = self.label("actionUploadAvatar");
		self.uploadForm = self.assembleUploadForm(element);
		self.uploadForm.label = dom.get("itemTitle");
		JSKitLib.addChild(element, self.uploadForm.content);
		JSKitLib.hide(self.uploadForm.content);
		element.onclick = function() {
			render("form");
		};
	};
	var render = function(element) {
		var isFormVisible = element == "form";
		JSKitLib.hide(self.uploadForm[isFormVisible ? "label" : "content"]);
		JSKitLib.show(self.uploadForm[isFormVisible ? "content" : "label"]);
	};
	JSKW$Events.registerEventCallback(self.eventsCtx, function() {
		render("label");
	}, "JSMenu-CollapseAll");
	return this.formatMenuItem("jskit", {"itemTitleContainer": descriptor}, {
		"onuncheck": function() { render("label"); },
		"oncheckCallback": function() { if (!self.avatars["jskit"]) render("form"); }
	}, "//cdn.js-kit.com/images/favicons/default.png");
}

JSKAvatars.prototype.assembleGravatarsForm = function() {
	var self = this;
	var descriptor = function(element) {
		self.gravatarControlContainer = element;
		self.renderGravatarControl();
	};
	return this.formatMenuItem("gravatar", {"itemTitle": descriptor}, {
		"onuncheck": function() {
			if (!self.gravatarEmail) self.gravatarEmailIPE.displayMode();
		},
		"oncheckCallback": function() {
			if (!self.gravatarEmail) self.gravatarEmailIPE.editMode();
		}
	});
}

JSKAvatars.prototype.setDefaultGravatar = function() {
	var anonymous = this.anonymousAvatarData();
	this.avatars["gravatar"] = anonymous;
	this.setPreviewImage("gravatar", anonymous);
	this.updateActiveAvatar(anonymous);
}

JSKAvatars.prototype.renderGravatarControl = function() {
	var self = this;
	var size = this.splitAvatarDim(this.size);
	var anonymous = this.anonymousAvatarData();
	var defaultUrl = this.avatarURL(this.calcAvatarDim(size, anonymous).name);
	this.gravatarEmailIPE = new JSIPE2({
		"obj": self,
		"property": "gravatarEmail",
		"title": self.label("actionEditGravatarEmail"),
		"width": "120px",
		"maxLength": 50,
		"hideApplyBtn": true,
		"defaultText": self.label("gravatarEmail"),
		"textModeDisplayCSS": "block",
		"editModeEventEnabled": true,
		"jsk$wasEdited": function() {
			self.setPreviewImage("gravatar");
			var params = self.gravatarEmail ? {
				"email": self.gravatarEmail,
				"defaultUrl": defaultUrl,
				"rating": "X",
				"size": 64
			} : {};
			if (!self.gravatarEmail) {
				self.setDefaultGravatar();
			}
			if (self.autoSave) {
				JSKW$Events.syncBroadcast("JSKitAvatars_gravatarEmailUpdated",
						self.gravatarEmail, undefined, self.id);
			}
			self.sendServerRequest("update_gravatar", params);
		}
	});
	JSKitLib.replaceChildren(self.gravatarControlContainer, self.gravatarEmailIPE.div);
}

JSKAvatars.prototype.setPreviewImage = function(type, avatar) {
	if (!this.avatarPreviewImgs[type]) return;
	var loading = {
		"name": "//cdn.js-kit.com/images/loading.gif",
		"width": "16",
		"height": "16"
	};
	this.assembleAvatar({
		"instance": this.avatarPreviewImgs[type],
		"width": "24",
		"height": "24"
	}, avatar || loading);
}

JSKAvatars.prototype.getGravatarURL = function(gravatarID, size) {
        if (!gravatarID || gravatarID.match(/^https?:\/\//)) return gravatarID;
        var defaultUrl = this.calcAvatarDim(size, this.anonymousAvatarData()).name;
        return 'http://www.gravatar.com/avatar.php?' 
                + 'gravatar_id=' + gravatarID
                + '&default=' + this.avatarURL(defaultUrl)
                + '&rating=X'
                + '&size=' + size.width + 'x' + size.height;
}

JSKAvatars.prototype.splitAvatarDim = function(dim) {
	var re = /(\d+)x(\d+)/;
	var size = re.exec(dim) || ['96x96', '96', '96'];
	return {"width": size[1], "height": size[2]};
}

JSKAvatars.prototype.calcAvatarDim = function(size, avatar) {
	if (!size || typeof(size) != "object") size = this.splitAvatarDim(size);
	var width = parseInt(avatar.width);
	var height = parseInt(avatar.height);
	var MW = parseInt(size.width || 96);
	var MH = parseInt(size.height || 96);
	if(avatar.name.match(/https?:\/\//)) {
		return {'width': width, 'height': height, 'name': avatar.name};
	} else if ((MW>=96)&&(MH>=96)&&(width<=100)&&(height<=100)){
		return {'width': width, 'height': height, 'name': avatar.name};
	} 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);
		var Name = (avatar.name.match(/https?:\/\//)) ?
			avatar.name :
			avatar.name.substr(0,avatar.name.length-4)+'-'+DW.toString()+'x'+DH.toString()+avatar.name.substr(avatar.name.length-4);
		return {'width': DW, 'height': DH, 'name': Name};
	} else {
		return {'width': width,'height': height,'name': avatar.name};
	}
}

JSKAvatars.prototype.assembleAvatarArea = function(container) {
	if (!container) return;
	this.container = this.updateActiveAvatar(this.getActiveAvatar() || this.anonymousAvatarData());
	if (this.yours) {
		this.menu = JSMenu(this.container, this.menuItems, "HTML", this.layer);
		var wrapper = this.menu.firstChild;
		wrapper.title = this.label("clickToEditAvatars");
		JSKitLib.addClass(wrapper, "js-kit-avatars-avatarWrapper");
		JSKitLib.addChild(container, this.menu);
		JSKitLib.addClass(container, "js-kit-avatars-wrapper");
	} else {
		JSKitLib.replaceChildren(container, this.container);
	}
}

JSKAvatars.prototype.assembleAvatar = function(container, avatar) {
	if (!avatar) avatar = this.getActiveAvatar();
	var setSize = function(element, dims) {
		JSKitLib.addStyle(element,
			"width: " + dims.width + "px;" +
			"height: " + dims.height + "px;");
	};
	var wrapper = container.instance || JSKitLib.html('<div></div>');
	var image = JSKitLib.html('<img src="' + this.avatarURL(avatar.name) + '" />');
	if (avatar.onerror) {
		image.onerror = avatar.onerror;
	}
	var adjustedAvatar = this.calcAvatarDim(container, avatar);
	var getMinSize = function(dim) {
		return Math.min(adjustedAvatar[dim], container[dim]);
	};
	var getSizeDiff = function(dim) {
		return Math.max(0, container[dim] - adjustedAvatar[dim])/2;
	};
	setSize(image, {
		"width": getMinSize("width"),
		"height": getMinSize("height")
	});
	setSize(wrapper, container);
	JSKitLib.addStyle(image,
		"margin-top: " + getSizeDiff("height") + "px;" +
		"margin-left: " + getSizeDiff("width") + "px;");
	JSKitLib.replaceChildren(wrapper, image);
	return wrapper;
}

JSKAvatars.prototype.updateActiveAvatar = function(avatar) {
	var size = this.splitAvatarDim(this.size);
	var data = this.calcAvatarDim(size, avatar);
	var container = {
		"instance": this.container,
		"width": size.width,
		"height": size.height
	};
	JSKitLib.fmap(this.avatars, function(avt) { avt.chosen = avt.type == avatar.type; });
	return this.assembleAvatar(container, data);
}

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

JSKAvatars.prototype.getActiveAvatar = function() {
	return JSKitLib.foldl(undefined, this.avatars || [], function(avatar) {
		if (avatar.chosen) return avatar;
	});
}

JSKAvatars.prototype.avatarURL = function(avatar) {
	if(avatar.match(/^(https?:)*\/\//)) {
		return JSKitLib.htmlUnquote(avatar);
	} else if(avatar.match(/^[^/]+$/)) {
		return this.uriAvatar + avatar;
	} else return "";
}

JSKAvatars.prototype.sendServerRequest = function(action, params) {
	JSKitLib.fmap.call(this, ["id", "ref"], function(name) { params[name] = this[name]; });
	new JSRVC({"uri": this.uriAvatar + action, "request": JSKitEPB.getAsHash(params)});
}

JSKAvatars.prototype.replaceAvatars = function(avatars) {
	if (!avatars.length) return;
	var avatar = JSKitLib.cloneObject(avatars[0]);
	this.avatars[avatar.type] = avatar;
	if (!this.menu) return;
	this.setPreviewImage(avatar.type, avatar);
	this.updateActiveAvatar(avatar);
	this.updateMenuItemsStatus(avatar);
}

JSKAvatars.prototype.updateMenuItemsStatus = function(avatar) {
	JSKitLib.fmap(this.menu.items, function(item) {
		if (avatar.type == item.avatarType) item.setActiveState();
	});
}

JSKAvatars.prototype.activateEvents = function() {
	var self = this;
	var handlers = {
		"replaceAvatars": function(avatars) {
			self.replaceAvatars(avatars);
		},
		"gravatarEmailUpdated" : function(gravatarEmail) {
			self.gravatarEmail = gravatarEmail;
			self.renderGravatarControl();
			if (!self.gravatarEmail) {
				self.setDefaultGravatar();
			}
		}
	};
	JSKitLib.fmap(handlers, function(handler, name) {
		JSKW$Events.registerEventCallback(self.eventsCtx, function(name, data, id, callerId) {
			if (!self.yours) return;
			if ((id && (id == self.id || id.match(/profile/))) || (callerId && callerId != self.id)) handler(data);
		}, "JSKitAvatars_" + name);
	});
}

JSKAvatars.prototype.deActivateEvents = function() {
	if (this.eventsCtx) JSKW$Events.invalidateContext(this.eventsCtx);
}

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

JSKAvatars.prototype.assembleUploadForm = function(container) {
	var self = this;
	var template =
	'<form class="js-kit-avatars-upload-form" method="POST" enctype="multipart/form-data" action="' + this.uriAvatar + 'add">' +
		'<input type="file" name="image" class="js-kit-avatars-upload-control" />' +
	'</form>';
	var setControlsState = function(state) {
		JSKitLib.fmap(self.controls, function(control) {
			if (control && !control.btnLocked) control.disabled = (state == "lock") ? "true" : "";
		});
	}
	var descriptors = {
		"form": function(element) {
			JSKitLib.fmap(JSKitEPB.getAsHash({"ref": self.ref}), function(v, k) {
				element.appendChild(JSKitLib.html('<input type="hidden" name="' + k + '" value="' + encodeURIComponent(v) + '">'));
			});
			container.appendChild(element);
		},
		"control": function(element, dom) {
			var form = dom.get("form");
			var onload = function() {
				setControlsState("unlock");
				form.reset();
				self.sendServerRequest("list", {"onlyjskit": "true"});
			};
			self.controls.push(element);
			element.onchange = function() {
				self.setPreviewImage("jskit");
				if (!form.target) {
					var tgt = 'js-ifrm-' + Math.random();
					JSKitLib.createHiddenIframe(tgt, self.target, onload, false);
					form.target = tgt;
				}
				form.submit();
				setControlsState("lock");
			}
		}
	};
	return JSKitLib.toDOM(template, "js-kit-avatars-upload-", descriptors);
}

JSKAvatars.prototype.loadCSS = function() {
	JSKitLib.addCss(
		".js-kit-avatars-wrapper { cursor: pointer; }" +
		".js-kit-avatars-wrapper .jskit-MenuItemTitle { margin: 1px; }" +
		".js-kit-avatars-wrapper div.jskit-MenuRootHTML { text-align: left; }" +
		".js-kit-avatars-avatarWrapper { text-align: left; " + (JSKitLib.isPreIE8() ? "zoom: 1;" : "") + "}" +
		".js-kit-avatars-itemTitleContainer { margin: 4px 5px 0px 0px; }" +
		".js-kit-avatars-itemTitleCnt-jskit, .js-kit-avatars-itemTitleCnt-gravatar { margin-top: 0px; line-height: 20px; }" +
		".js-kit-avatars-menu-title { font-size: 10px; font-weight: bold; font-family: Lucida grande,Tahoma,Verdana,Arial; margin: 5px 8px; }" +
		".js-kit-avatars-menu-footer { margin-top: 8px; }" +
		".js-kit-avatars-upload-form { margin: 0px; }" +
		".js-kit-clear { clear: both; }", "avatars"
	);
}





function JSTabsManager(tabs, areas, config) {
	var self = this;
	if (tabs.length < 1 || !areas) return;
	JSKitLib.fmap({
		"tabs" : tabs,
		"areas" : areas,
		"config": config || {}
	}, function(value, key) { self[key] = value; });
	this.loadCSS();
	this.setActiveTab(this.getActiveTab());
	this.displayTabs(tabs, this.areas.titles);
}

JSTabsManager.prototype.displayTabs = function(tabs, container) {
	JSKitLib.removeChildren(container);
	JSKitLib.fmap.call(this, tabs, function(tab) { container.appendChild(this.initFromData(tab)); });
	container.appendChild(JSKitLib.html('<div class="js-kit-clear"></div>'));
	if (tabs.length == 1) JSKitLib.addClass(container, "js-kit-tabs-singleTab");
	var activeTab = this.getActiveTab();
	if (this.config.mode != "toggle" || activeTab) this.displayTab(activeTab);
	else if (!activeTab) JSKitLib.hide(this.areas.content);
}

JSTabsManager.prototype.initFromData = function(tab) {
	var self = this;
	var prefix = "js-kit-tab-";
	var descriptors = {
		"icon": function(element) {
			if (tab.icon) JSKitLib.addPNG(element, tab.icon); else JSKitLib.hide(element);
		},
		"title": function(element) {
			if (typeof(tab.title) == "string") tab.title = JSKitLib.text(tab.title);
			element.appendChild(tab.title);
			JSKitLib.preventSelect(element);
		}
	};
	var dom = JSKitLib.toDOM(this.config.template || this.template, prefix, descriptors);
	if (this.config.descriptors) {
		var elements = JSKitLib.foldl({}, this.config.descriptors, function(value, acc, key) { if (dom.get(key)) acc[prefix + key] = dom.get(key); });
		JSKitLib.attachDescriptors2Elements(elements, prefix, this.config.descriptors);
	}
	dom.content.onclick = function(e) {
		if (self.config.mode == "toggle" && tab.active) {
			tab.active = false;
			self.renderView();
			self.processCallback(tab, "Closed");
			JSKitLib.hide(self.areas.content);
		} else {
			if (tab.active) return;
			self.processCallback(self.activeTab, "Closed");
			self.setActiveTab(tab);
			self.displayTab(tab);
		}
		JSKitLib.stopEventPropagation(e);
	}
	if (tab.name) JSKitLib.addClass(dom.content, prefix + tab.name);
	tab.cache = {"title" : dom.content};
	return dom.content;
}

JSTabsManager.prototype.processCallback = function(tab, action) {
	if (tab && tab.callbacks && tab.callbacks["onTab" + action]) tab.callbacks["onTab" + action](tab);
}

JSTabsManager.prototype.getActiveTab = function() {
	return JSKitLib.foldl(undefined, this.tabs, function(tab, result) { if (tab.active) return tab; }) || (this.config.mode != "toggle" ? this.tabs[0] : undefined);
}

JSTabsManager.prototype.setActiveTab = function(tab) {
	if (!tab) return;
	if (this.activeTab) this.activeTab.active = false;
	this.activeTab = tab;
	this.activeTab.active = true;
}

JSTabsManager.prototype.renderView = function() {
	var area = this.areas.content;
	var activeTabPosition;
	JSKitLib.removeClass(area, "js-kit-lastTabActive");
	JSKitLib.removeClass(area, "js-kit-firstTabActive");
	JSKitLib.fmap.call(this, this.tabs, function(tab, idx) {
		if (tab.cache.title) JSKitLib[(tab.active ? "add" : "remove") + "Class"].call(this, tab.cache.title, "js-kit-tab-active");
		if (tab.active) activeTabPosition = (idx == this.tabs.length - 1) ? "last" : (idx == 0 ? "first" : undefined);
	});
	if (activeTabPosition) JSKitLib.addClass(area, "js-kit-" + activeTabPosition + "TabActive");
}

JSTabsManager.prototype.displayTab = function(tab) {
	var area = this.areas.content;
	this.renderView();
	if (this.config.mode == "toggle") JSKitLib.show(area);
	if (!tab.cache.content || this.config.nocache) tab.cache.content = tab.content(area);
	JSKitLib.replaceChildren(area, tab.cache.content);
	this.processCallback(tab, "Opened");
}

JSTabsManager.prototype.collapseTabs = function() {
	if (this.config.mode != "toggle") return;
	if (this.activeTab) {
		this.activeTab.active = false;
		delete this.activeTab;
	}
	this.renderView();
	JSKitLib.hide(this.areas.content);
}

JSTabsManager.prototype.template =
 '<div class="js-kit-tab">' +
   '<div class="js-kit-tab-icon"></div>' +
   '<div class="js-kit-tab-title"></div>' +
   '<div class="js-kit-clear"></div>' +
 '</div>';

JSTabsManager.prototype.loadCSS = function() {
	JSKitLib.addCss(
		".js-kit-tab { " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " float: left; cursor: pointer; margin: 0; font-size: 14px; background: transparent; padding: 5px 10px " + (JSKitLib.isIE() ? "0" : "5") + "px 10px; }" +
		".js-kit-tab-icon { float: left; width: 17px; height: 17px; margin: 0px 5px 0 0; }" +
		".js-kit-tab-title { font-size: 12px; float: left; }" +
		".js-kit-tab-active { font-weight: bold; cursor: text; background: #FFFFFF; }" +
		".js-kit-tabs-singleTab { display: none; }" +
		".js-nsgecko { -moz-user-select: none; }" + 
		".js-kit-clear { clear: both; }", "tabsManagement");
}





function JSKitMiniProfile(target, data, config) {
	var self = this;
	this.data = data;
	this.target = target;
	this.config = this.merge(config, {
		"mode": "popup",
		"template": this.template,
		"cssPrefix": "js-kit-miniProfileWrap",
		"elmPrefix": "js-kit-miniProfile-",
		"descriptors": {}
	});
	this.loadCSS();
	if (this.config.mode == "popup")
		JSKW$Events.registerEventCallback(undefined, function() { self.hide(); }, "miniProfile_collapseAll");
	this.assemble();
}

JSKitMiniProfile.prototype.assemble = function() {
	var self = this;
	this.descriptors = {
		"name": function() { return JSKitLib.html('<span>' + JSKitLib.trim(self.data.Name) + '</span>'); },
		"viewDetails": function() { return JSKitLib.text(self.label("viewDetails")); },
		"siteLinksIcons": function(element) { return self.assembleSiteLinks("icons", element); },
		"siteLinksExtended": function(element) { return self.assembleSiteLinks("extended", element); }
	};
	this.dom = JSKitLib.toDOM(this.config.template, this.config.elmPrefix, this.descriptors);
	JSKitLib.addClass(this.dom.content, this.config.cssPrefix + " " + this.config.elmPrefix + this.config.mode);
	var elements = JSKitLib.foldl({}, this.config.descriptors, function(descriptor, container, name) {
		if (self.dom.get(name)) container[name] = self.dom.get(name);
	});
	JSKitLib.attachDescriptors2Elements(elements, "", this.config.descriptors);
	this.display();
}

JSKitMiniProfile.prototype.display = function(target) {
	if (!this.dom) return;
	if (this.config.mode == "popup") JSKW$Events.syncBroadcast("miniProfile_collapseAll");
	JSKitLib.addChild(target || this.target, this.dom.content);
	this.dom.content.onclick = function(e) { JSKitLib.stopEventPropagation(e); };
	this.isVisible = true;
}

JSKitMiniProfile.prototype.render = function(block, data) {
	var self = this;
	var element = this.dom.get(block);
	if (!element) return;
	JSKitLib.removeChildren(element);
	this.data = this.merge(data, this.data);
	var name = this.config.elmPrefix + block;
	var replacement = {};
	replacement[name] = element.cloneNode(true);
	JSKitLib.fmap([self, self.config], function(obj) {
		JSKitLib.attachDescriptors2Elements(replacement, self.config.elmPrefix, obj.descriptors || {});
	});
	element.parentNode.replaceChild(replacement[name], element);
	this.dom.set(block, replacement[name]);
}

JSKitMiniProfile.prototype.hide = function() {
	if (!this.isVisible || !this.dom) return;
	this.isVisible = false;
	this.dom.content.parentNode.removeChild(this.dom.content);
}

JSKitMiniProfile.prototype.getContent = function() {
	return this.dom ? this.dom.content : undefined;
}

JSKitMiniProfile.prototype.assembleSiteLinks = function(mode, element) {
	var self = this;
	var auth = JSKitLib.fmap(self.data.identities.auth, function(identity) {
		if (identity.user) return identity;
	});
	var identities = JSKitLib.merge(auth, self.data.identities.web);
	if (identities.length < 1) return JSKitLib.hide(element); else JSKitLib.show(element);
	var setAction = function(element, type, url, domain, identity, isLogin) {
		var isExternalProfile = isLogin && !!url && !type.match(/jskit|haloscan|openid/);
		var isDisabled = isLogin && !isExternalProfile && self.config.isNativeProfileDisabled;
		element.onclick = function() {
			if (isLogin && !isExternalProfile) {
				if (!isDisabled) self.config.openFullProfile();
				return;
			}
			if (isLogin) {
				// validation of old format profile URLs
				if ((type == "gfc" && !url.match(/canvas.html/))
				|| (type == "yahoo" && !url.match(/profiles.yahoo.com\/u\//))) {
					element.title = self.label("openFullProfile");
					self.config.openFullProfile();
					return;
				}
				if (type == "gfc" && identity.params.site) {
					url = JSKAuth.prototype.actualizeGFCprofileURL(url, identity.params.domain, identity.params.site);
				}
			}
			window.open(url.replace(/\ /g, "%20"));
		};
		if (isDisabled) {
			JSKitLib.addClass(element, "js-kit-miniProfile-profileDisabled");
		} else {
			var title = isExternalProfile ? "ext_profile_" + type : "openFullProfile";
			element.title = isLogin ? self.label(title) : url;
		}
	};
	var container = JSKitLib.html('<div class="js-kit-miniProfile-linksContainer"></div>');
	var specificTemplate = mode == "icons" ?
		'<div class="js-kit-clear"></div>':
		'<div class="js-kit-linksContainerTitle">' + this.label("visitMeOn") + '</div>';
	container.appendChild(JSKitLib.html(specificTemplate));
	JSKitLib.fmap.call(this, mode == "icons" ? identities.reverse() : identities, function(identity) {
		if (!identity.use_as_from) return;
		var isLogin = identity.group != "web";
		var type = isLogin ? identity.type : "default";
		var url = '';
		var domain = '';
		if (identity.url) {
			url = (isLogin || identity.url.match(/^(https?:)*\/\//) ? "" : "http://") + identity.url;
			domain = JSKitLib.extractDomain(url);
		}
		var title = !isLogin ? domain : JSKAuth.prototype.getIdentityParam('short_label', identity, JSKAuth.prototype.getIdentityLabel(type)) || domain;
		var template =
		'<div class="js-kit-linksItem">' +
		    '<div class="js-kit-linksItem-icon"></div>' +
		    '<div class="js-kit-linksItem-link">' + title + '</div>' +
		    '<div class="js-kit-clear"></div>' +
		'</div>';
		var descriptors = {
			"icon": function(element) {
				JSKitLib.addPNG(element, JSKAuth.prototype.getIdentityParam('favicon', identity, "//cdn.js-kit.com/images/favicons/" + type + ".png"));
				setAction(element, type, url, domain, identity, isLogin);
			},
			"link": function(element) {
				if (mode == "icons") JSKitLib.hide(element); else setAction(element, type, url, domain, identity, isLogin);
			}
		};
		JSKitLib.addChild(container, JSKitLib.toDOM(template, "js-kit-linksItem-", descriptors).content, mode == "icons");
	});
	return container;
}

JSKitMiniProfile.prototype.label = function(name) { return this.config.labels("miniProf_" + name); }

JSKitMiniProfile.prototype.merge = function(masterObj, slaveObj) {
	var merge = function(cnt, obj) { return JSKitLib.foldl(cnt, obj || {}, function(v, acc, k) { acc[k] = v; }); };
	return merge(merge({}, slaveObj), masterObj);
}

JSKitMiniProfile.prototype.template =
  '<div class="js-kit-miniProfile">' +
      '<div class="js-kit-miniProfile-avatar"></div>' +
      '<div class="js-kit-miniProfileDataContainer">' +
          '<div class="js-kit-miniProfileDataWrap">' +
              '<div class="js-kit-miniProfile-name"></div>' +
              '<div class="js-kit-miniProfile-stats"></div>' +
              '<div class="js-kit-miniProfile-details">' +
	          '<span class="js-kit-miniProfile-viewDetails"></span>' +
              '</div>' +
          '</div>' +
      '</div>' +
      '<div class="js-kit-clear"></div>' +
      '<div class="js-kit-miniProfile-siteLinksExtended"></div>' +
  '</div>';

JSKitMiniProfile.prototype.loadCSS = function() {
	var dims = this.config.avatarSize;
	var zoom = JSKitLib.isIE() ? "zoom: 1;" : "";
	var prefix = "." + this.config.cssPrefix.match(/[^\ ]*/);
	var margin = parseInt(dims.width) + 10;
	JSKitLib.addCss(
		prefix + " .js-kit-miniProfileDataWrap { " + zoom + "margin-left: " + margin + "px; }" +
		prefix + " .js-kit-miniProfile-avatar { float: left; margin-right: -" + margin + "px; width: " + dims.width + "px; height: " + dims.height + "px; }", "miniProfile-" + this.config.cssPrefix.replace(/[^a-zA-Z-]/g, "-"));
	JSKitLib.addCss(
		".js-kit-miniProfile { padding: 7px; text-align: left; font-weight: normal; cursor: default; background: #FFFFFF; }" +
		".js-kit-miniProfile-popup { position: absolute; z-index: 13490; width: 275px; border: 2px solid #d6e2e9; -moz-border-radius: 5px; -webkit-border-radius: 5px; }" +
		".js-kit-miniProfile-embedded { border: 1px solid #BBBBBB; }" +
		".js-kit-miniProfile-avatar { position: relative; }" +
		".js-kit-miniProfile-embedded .js-kit-miniProfile-avatar { border: 1px solid #BBBBBB; }" +
		".js-kit-miniProfileDataContainer { float: left; width: 100%; }" +
		".js-kit-miniProfile-stats { color: #0066CC; font-size: 10px; }" +
		".js-kit-miniProfile-viewDetails { color: #0066CC; font-size: 10px; }" +
		".js-kit-miniProfile-name { font-size: 18px; color: #000000; }" +
		".js-kit-miniProfile-siteLinksExtended { margin-top: 5px; font-size: 20px; border-top: 2px dotted #E4E4E4; }" +
		".js-kit-miniProfile-siteLinksIcons { border-top: 2px dotted #7d7d7d; }" +
		".js-kit-miniProfile-siteLinksIcons .js-kit-linksItem { width: 16px; height: 16px; float: left; }" +
		".js-kit-linksItem { margin: " + (JSKitLib.isIE() ? "3px 3px" : "4px 6px") + " 0px 0px; line-height: 16px; }" +
		".js-kit-linksItem-link  { float: left; " + zoom + " color: #476CB8 !important; margin-left: 5px; font-size: 12px; cursor: pointer; }" +
		".js-kit-linksItem-icon { float: left; width: 16px; height: 16px; margin: 0px " + (JSKitLib.isIE() ? "5" : "3") + "px 0px 0px; font-size: 12px; padding: 0px; cursor: pointer; }" +
		".js-kit-linksContainerTitle { margin: 7px 3px; color: #000000; font-size: 12px; font-weight: bold; }" +
		".js-kit-miniProfile-profileDisabled { cursor: default; }" +
		".js-kit-clear { clear: both; }", "miniProfile");
}





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$validate	callback, validates the value before applying
	jsk$wasEdited	callback, called at the end of editing 
	readonly:	readonly mode
	
	example: 
	var jsipe = new JSIPE2({obj: elem,
				property: 'descr',
				title: 'Description',
				defaultText: 'Add caption',
				width: '90px',
				maxLength: 12,
				jsk$wasEdited: function(){...},
				readonly: true
	});

*/

	for(var i in obj)
		this[i] = obj[i];
	var div = JSKitLib.cr();
	div.title = this.readonly ? "" : (this.title || $JCL("clickToEdit"));
	var defaultText = this.readonly ? "" : (this.defaultText || $JCL("clickToEditEmpty"));
	var maxTextLength = this.maxLength || 256;
	var isFocused = false;

	var self = this;

	var textDivDisplayCSS = typeof(self.textModeDisplayCSS) != "undefined" ? self.textModeDisplayCSS : "inline";
	var textDiv = JSKitLib.cr({style:{display:textDivDisplayCSS}});
	var textValue = (JSKitLib.trim(self.obj[self.property]).length > 0) ? self.obj[self.property] : defaultText;
	var text = JSKitLib.text(textValue);
	textDiv.appendChild(text);
	div.appendChild(textDiv);

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

	if (!this.hideApplyBtn) {
		var applyDiv = JSKitLib.cr();
		JSKitLib.addClass(applyDiv, "jsipe-applyButton");
		applyDiv.title = "Apply";
		JSKitLib.addPNG(applyDiv, "//cdn.js-kit.com/images/tick.png");
		editDiv.appendChild(applyDiv);
	}

	this.div = div;

	if (this.readonly) return;

	textDiv.onmouseover = function() { JSKitLib.addClass(textDiv, "jsipe-onmouseover"); }
	textDiv.onmouseout  = function() { JSKitLib.removeClass(textDiv, "jsipe-onmouseover"); }

	this.displayMode = function() {
		JSKitLib.show(textDiv, textDivDisplayCSS);
		JSKitLib.hide(editDiv);
		textDiv.removeChild(text);
		text = JSKitLib.text(self.obj[self.property] || defaultText);
		textDiv.appendChild(text);
	}

	this.editMode = function(e) {
		if(!self.editModeEventEnabled) JSKitLib.stopEventPropagation(e);
		JSKitLib.hide(textDiv);
		JSKitLib.show(editDiv, "inline");
		edit.focus();
		edit.select();
	}

	var applyChanges = function() {
		if(typeof self.jsk$validate == "function" && !self.jsk$validate(edit.value)) return;
		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);
		if(isFocused) edit.blur();
		self.displayMode();
		if(self.jsk$wasEdited) self.jsk$wasEdited();
	}

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

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

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

	if(this.dblclick)
		textDiv.ondblclick = this.editMode;
	else
		textDiv.onclick = this.editMode;
	edit.onblur = function() { applyChanges(); isFocused = false; };
	edit.onfocus = function() { isFocused = true; };
	edit.onclick = function(e) { JSKitLib.stopEventPropagation(e); }
	if (!this.hideApplyBtn) applyDiv.onmousedown = applyChanges;

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

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="//cdn.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) {
	var items = this.getItems(sIdx, Cnt);
	var res = 0;
	JSKitLib.fmap(this.getItems(sIdx, Cnt), function(e) {
		res += (e && e.obj && 
			e.obj.status!='D' && e.obj.status!='DT') ? 1 : 0;
			});
	this.items.splice(sIdx, Cnt);
	this.itemsCount -= Cnt;
	return res;
}

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);
	var res = 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();
	return res;
}

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) {
	return 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]
// [trailer: specifies the name of parameter which should terminate
//						each sub-request of multi-request]

function JSRVC(requestObj) {
	var s = this;
	s.requestId = requestObj.requestId || s.generateRequestId();
	s.requestsInProgress = 0;
	s.requestsQueue = [];
	s.trailer = requestObj.trailer;
	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;
	if(s.timeoutTimer) clearTimeout(s.timeoutTimer);
	s.timeoutTimer = setTimeout(function() { s.timeoutExpired(); }, s.requestObj.timeout);
}

JSRVC.prototype.timeoutExpired = function() {
	this.timeoutTimer = undefined;
	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) {
	var s = this;
	var toString = function(k, v) {
		return encodeURIComponent(k) + (prefix || '') + "=" + encodeURIComponent(v);
	};
	var request = JSKitLib.fmap(obj, function(v, k) {
		if (s.trailer != k) return toString(k, v);
	});
	if (s.trailer && typeof(obj[s.trailer]) != "undefined") {
		request.push(toString(s.trailer, obj[s.trailer]));
	}
	return request.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;
		JSKitLib.timedRetry({
				timeout: 100,
				maxRetries: 50,
				onSuccess: function() {
						doc.body.appendChild(f); },
				pred: function() { return !!doc.body; }
			});
		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++;
		JSKitLib.timedRetry({
				timeout: 100,
				maxRetries: 50,
				onSuccess: function() {
						form.submit(); },
				pred: function() {
					return (form.parentNode &&
						form.parentNode.nodeType!=11); }
			});
	}
	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);
			s.timeoutTimer = undefined;
		}
		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;
	case "exceeded": 
		this.error = "attempts_number_exceeded";
		this.returnAnswer(); 
		break;
	}
}

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





function JSKitModalDialog(content, config) {
	this.config = config;
	this.content = content;
	this.backdrop = JSKitLib.html('<div class="js-kit-modal-dialog-backdrop"></div>');
	this.loadCSS();
	JSKitLib.hide(this.backdrop);
	JSKitLib.addChild(document.body, this.backdrop, true);
	JSKitLib.setOpacity(this.backdrop, 0.5);
}

JSKitModalDialog.prototype.open = function() {
	if (!this.container) {
		var pos = JSKitLib.calcCenterPos(this.config.width, this.config.height);
		this.container = JSKitLib.html('<div class="' + this.config.cssClass + ' js-kit-modal-dialog-container"></div>');
		JSKitLib.addStyle(this.container,
			"width: " + this.config.width + "px;" +
			"height: " + this.config.height + "px;" + 
			"left: " + pos[0] + "px;" + 
			"top: " + pos[1] + "px;");
		JSKitLib.addChild(this.container, this.content);
		JSKitLib.addChild(document.body, this.container, true);
	}
	JSKitLib.show(this.backdrop);
	JSKitLib.show(this.container);
}

JSKitModalDialog.prototype.close = function() {
	JSKitLib.hide(this.container);
	JSKitLib.hide(this.backdrop);
}

JSKitModalDialog.prototype.loadCSS = function() {
	JSKitLib.addCss(
		".js-kit-modal-dialog-container { position: absolute; z-index: 12000; background: #FFFFFF; }" +
		".js-kit-modal-dialog-backdrop { opacity: 0; background-color: #404040; z-Index: 11500; " +
			(JSKitLib.isPreIE8()
			? "filter:progid:DXImageTransform.Microsoft.Alpha(opacity='0'); position: absolute; top: expression(eval(-(document.body.offsetTop + (document.body.offsetHeight - document.body.clientHeight)/2))); left: expression(eval(-(document.body.offsetLeft + (document.body.offsetWidth - document.body.clientWidth)/2))); height: expression(eval(Math.max(document.body.offsetHeight, document.documentElement.scrollHeight))); width: expression(eval(Math.max(document.body.offsetWidth, document.documentElement.scrollWidth)));"
			: "position: fixed; left: 0; top: 0; height: 100%; width: 100%; -webkit-transition: opacity 0.5s ease-out;" ) +
		"", "modalDialog");
}





function JSKitUniversalObject() {}

JSKitUniversalObject.prototype.applyProperties = function(properties, sourceObject) {
	var obj = sourceObject || this;
	JSKitLib.fmap(properties || {}, function(value, name) { obj[name] = value; });
}

JSKitUniversalObject.prototype.applyConfig = function() {
	var self = this;
	var args = arguments;
	this._config = JSKitLib.foldl({}, ["basic", "local", "global"], function(name, container, idx) { container[name] = args[idx] || {}; });
	return {
		"set" : function(key, value) { self._config.local[key] = value; },
		"get" : function(key, defaultValue) { return self._config.local[key] || self._config.global[key] || defaultValue || self._config.basic[key] || ""; }
	};
}

JSKitUniversalObject.prototype.assemble = function(template, layoutBlocksPrefix, descriptors) {
	var content = JSKitLib.html(template);
	var components = JSKitLib.mapClass2Object({}, content);
	var structure = {
		"get" : function(name, noPrefix) { return components[((noPrefix) ? "" : layoutBlocksPrefix + "-") + name]; },
		"content" : content
	};
	JSKitLib.fmap(components, function(component, id) {
		var pattern = id.match(layoutBlocksPrefix + "-(.*)");
		var descriptor = (pattern) ? pattern[1] : undefined;
		if (descriptor && typeof(descriptors[descriptor]) == "function") {
			var node = descriptors[descriptor](component);
			if (node) component.appendChild(node);
		}
	});
	return structure;
}

JSKitUniversalObject.prototype.data2DOM = function(data, target) {
	var dom;
	switch (typeof(data)) {
		case "function" : dom = data(target); break;
		case "string"   : dom = JSKitLib.html("<div>" + data + "</div>"); break;
		default : dom = data;
	}
	return dom;
}

JSKitUniversalObject.prototype.processCallback = function(name, sourceObject) {
	var obj = sourceObject || this;
	if (obj.callbacks && obj.callbacks.hasOwnProperty(name)) obj.callbacks[name]();
}

JSKitUniversalObject.prototype.append = function(element, content) {
	JSKitLib.removeChildren(element);
	element.appendChild(content);
	return element;
}

JSKitUniversalObject.prototype.mergeObjects = function(master, slave) {
	return JSKitLib.foldl.call(this, master, slave, function(value, acc, name) {
		if (typeof(value) == "object") { 
			if (!master[name]) master[name] = {};
			this.mergeObjects(master[name], slave[name]); 
		} else { if (!acc[name]) acc[name] = value; }
	});
}





function JSKitUniversalContainer(content, options, callbacks, target) {
	if (!target) target = document.createElement("DIV");
	if (!target.parentNode) JSKitLib.addChild(document.body, target, true);
	this.config = this.applyConfig({
		"mode" : "popup",
		"size" : {"width" : "550", "height" : "500"},
		"title" : "Untitled",
		"opacity" : false,
		"backdrop" : "yes",
		"resizable" : "yes",
		"cssPrefix" : "",
		"sizeLimit" : {"width" : "550", "height" : "450"},
		"whiteLabel" : false,
		"contentOverflow" : "auto"
	}, options);
	this.applyProperties({
		"target" : target,
		"isOpen" : true,
		"callbacks" : callbacks || {},
		"imagesPath" : "//cdn.js-kit.com/images/container/"
	});
	this.loadCSS();
	this.render(content);
}

JSKitUniversalContainer.prototype = new JSKitUniversalObject();

JSKitUniversalContainer.prototype.render = function(content, title, isRerendering) {
	var self = this;
	this.applyProperties({
		"title" : title || self.config.get("title"),
		"content" : content || document.createElement("DIV")
	});
	this.dom = this.assemble(this.template, "jskit-container", this.prepareDescriptors());
	this.append(this.target, this.dom.content);
	JSKitLib.addClass(this.target, this.config.get("cssPrefix") + " js-kit-widgetsContainer js-kit-widgetsContainer-" + this.config.get("mode"));
	var dimensions = this.config.get("size", {
		"width" : self.dom.get("main").offsetWidth,
		"height" : self.dom.get("main").offsetHeight
	});
	if (!isRerendering) JSKitLib.addStyle(this.target, "width: " + parseInt(dimensions.width) + "px; height: " + parseInt(dimensions.height) + "px;");
	this.dom.get("content").style.overflow = this.config.get("contentOverflow");
	if (this.config.get("whiteLabel")) JSKitLib.hide(this.dom.get("poweredBy"));

	if (this.config.get("mode") == "popup") {
		new JSDL(this.target, [this.dom.get("header"), this.dom.get("footer")]);
		var opacity = this.config.get("opacity");
		if (opacity) {
			this.target.jsk$on_start_drag = function(e) { JSKitLib.setOpacity(this, opacity); };
			this.target.jsk$on_stop_drag = function(e) { JSKitLib.setOpacity(this, "1"); };
		}
		if (!isRerendering) {
			var calcPos = JSKitLib.calcCenterPos(dimensions.width, dimensions.height);
			var pos = this.config.get("position", {x: calcPos[0], y: calcPos[1]});
			JSKitLib.addStyle(this.target, "left: " + parseInt(pos.x) + "px; top: " + parseInt(pos.y) + "px;");
		}

		// make container resizable
		if (this.config.get("resizable") == "yes")
			this.makeResizableContainer(this.target, this.dom.get("resizeControl"), this.dom.get("content"));

		// display backdrop
		if (this.config.get("backdrop") == "yes") {
			if (!this.containerBackdrop) {
				this.containerBackdrop = JSKitLib.html('<div class="js-kit-containerBackdrop"></div>');
				JSKitLib.addChild(document.body, this.containerBackdrop, true);
			}
			JSKitLib.show(this.containerBackdrop);
			JSKitLib.setOpacity(this.containerBackdrop, 0.3);
		}
	}
	this.processCallback("onContainerOpened");
}

JSKitUniversalContainer.prototype.updateTitle = function(title) {
	this.append(this.dom.get("title"), this.data2DOM(title || this.config.get("title")));
}

JSKitUniversalContainer.prototype.makeResizableContainer = function(target, resizeCtrl, stretchBlock) {
	var self = this;
	var data;
	var limit = this.config.get("sizeLimit");
	var opacity = this.config.get("opacity");
	var useStretchBlock = JSKitLib.isPreIE7() || (JSKitLib.isIE() && document.compatMode == "BackCompat");
	var getMousePos = function(e) {
		var scroll = JSDL.prototype.getCurScroll();
		var mousePos = JSKitLib.getMousePosition(e);
		return {"x" : mousePos.x + scroll.scroll_left, "y" : mousePos.y + scroll.scroll_top};
	};
	var onStartResize = function(e) {
		data = {"pos" : getMousePos(e), "size" : {"width" : target.offsetWidth, "height" : target.offsetHeight}};
		JSKitLib.stopEventPropagation(e);
		JSKitLib.preventDefaultEvent(e);
		if (opacity) JSKitLib.setOpacity(target, opacity);
		JSKitLib.addHandlers(document, onResize, onEndResize);
	};
	var onResize = function(e) {
		var mousePos = getMousePos(e);
		target.style.width = Math.max(limit.width, data.size.width + mousePos.x - data.pos.x) + "px";
		target.style.height = Math.max(limit.height, data.size.height + mousePos.y - data.pos.y) + "px";
		if (useStretchBlock && stretchBlock) stretchBlock.style.width = target.style.width;
		JSKitLib.preventDefaultEvent(e);
	};
	var onEndResize = function(e) {
		data = undefined;
		if (JSKitLib.isOpera() || JSKitLib.isIE()) 
			target.style.width = (((useStretchBlock && stretchBlock) ? stretchBlock : target).offsetWidth - 1) + "px";
		if (opacity) JSKitLib.setOpacity(target, "1");
		JSKitLib.removeHandlers(document, onResize, onEndResize);
	};
	JSKitLib.addEventHandler(resizeCtrl, ["mousedown"], onStartResize);
}

JSKitUniversalContainer.prototype.close = function() {
	this.processCallback("onContainerBeforeClose");
	this.target.parentNode.removeChild(this.target);
	// Remove backdrop
	if (this.containerBackdrop) {
		JSKitLib.setOpacity(this.containerBackdrop, 0);
		JSKitLib.hide(this.containerBackdrop);
	}
	this.isOpen = false;
	this.processCallback("onContainerClosed");
}

JSKitUniversalContainer.prototype.getElement = function(name) { return this.dom ? this.dom.get(name) : false; }

JSKitUniversalContainer.prototype.prepareDescriptors = function() {
	var self = this;
	return {
		"title" : function() { return self.data2DOM(self.title || self.config.get("title")); },
		"content" : function() { return self.content; },
		"closeButton" : function(element) { self.assembleCloseButton(element); },
		"resizeControl" : function(element) { self.assembleResizeControl(element); },
		"closeButtonImg" : function(element) { if (self.config.get("mode") != "embedded") JSKitLib.addPNG(element, self.imagesPath + "closeWindow.png"); }
	};
}

JSKitUniversalContainer.prototype.assembleCloseButton = function(element) {
	var self = this;
	if (this.config.get("mode") != "embedded") {
		JSKitLib.notDraggable(element);
		element.onclick = function(e) {
			self.close();
			JSKitLib.stopEventPropagation(e);
		}
	} else JSKitLib.hide(element);
}

JSKitUniversalContainer.prototype.assembleResizeControl = function(element) {
	if (this.config.get("mode") != "embedded" && this.config.get("resizable") == "yes") {
		JSKitLib.addPNG(element, this.imagesPath + "resizeHandle.png");
		return;
	}
	JSKitLib.hide(element);
}

JSKitUniversalContainer.prototype.template =
 '<div class="jskit-container-main">' +
     '<div class="jskit-container-wrapper">' +
 	'<div class="jskit-container-header">' +
 	    '<div class="jskit-container-title"></div>' +
 	    '<div class="jskit-container-closeButton">' +
		'<div class="jskit-container-closeButtonImg"></div>' +
	    '</div>' +
 	    '<div class="js-kit-clear"></div>' +
 	'</div>' +
 	'<div class="jskit-container-content"></div>' +
 	'<div class="jskit-container-footer">' +
 	    '<div class="jskit-container-footerArea"></div>' +
	    '<div class="jskit-container-poweredBy"><a href="//js-kit.com/" target="_blank">Powered by JS-Kit</a></div>' +
 	    '<div class="js-kit-clear"></div>' +
 	'</div>' +
     '</div>' +
     '<div class="jskit-container-resizeControl">&nbsp;&nbsp;&nbsp;</div>' +
 '</div>';

JSKitUniversalContainer.prototype.loadCSS = function() {
	var oldStyleIE = JSKitLib.isPreIE8() || (JSKitLib.isIE() && !JSKitLib.isPreIE8() && document.compatMode == "BackCompat");
	JSKitLib.addCss(
		".js-kit-containerBackdrop { opacity: 0; background-color: #404040; z-Index: 13800; width: 100%; " + (oldStyleIE ? "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;" ) + "}" +
		".js-kit-widgetsContainer { " + (oldStyleIE ? "width: " + parseInt(this.config.get("size").width) + "px; height:" + parseInt(this.config.get("size").height) + "px;" : "") + " cursor: default; text-align: left; line-height: normal; color: #000000; font-weight: normal; }" +
		"div.js-kit-widgetsContainer a, div.js-kit-widgetsContainer a:visited { background-color: transparent; font-weight: normal; }" +
		".js-kit-widgetsContainer-embedded {}" +
		".js-kit-widgetsContainer-popup { position: absolute; -webkit-box-shadow: 0px 10px 50px #222; " + (JSKitLib.isGChrome() ? "" : "-webkit-border-radius: 7px;") + " z-Index: 14000; }" +
		".jskit-container-main { position: relative; font-family: Helvetica, sans-serif; background: #dfebf2; padding: 0px; " + (JSKitLib.isGChrome() ? "" : "-moz-border-radius: 7px; -webkit-border-radius: 7px;") + " border: 1px solid #C4CFD5; height: 100%; }" +
		".jskit-container-wrapper { " + (oldStyleIE ? "position: relative; border: 0px; height: 100%;" : "position: absolute; top: 0px; bottom: 0px; left: 0px; right: 0px; border: 5px solid #DFEBF2;") + " -moz-border-radius: 7px; -webkit-border-radius: 7px; }" +
		".jskit-container-header { height: 27px; " + (oldStyleIE ? "margin-top: 5px;" : "") + "}" +
		".jskit-container-title { float: left; font-size: 18px; font-weight: bold; margin: 0px 0px 2px 5px; color: #424242; width: 90%; overflow: hidden; height: 23px; }" +
		".jskit-container-closeButton { width: 18px; height: 18px; float: right; margin: 1px " + (JSKitLib.isIE() ? (JSKitLib.isPreIE7() ? "0" : "5") : "1") + "px 0px; color: #95a0a9; cursor: pointer; }" +
		".jskit-container-closeButtonImg { width: 10px; height: 10px; margin: 4px; }" +
		".jskit-container-content { " + (oldStyleIE ? "zoom: 1; position: relative; height: expression(eval(this.parentNode.offsetHeight - 63) + 'px'); width: expression(eval(this.parentNode.offsetWidth - 10) + 'px'); margin: 0px 5px;" : "position: absolute; top: 0px; bottom: 0px; margin : 32px 0px 25px 0px; width: 100%; -moz-border-radius: 5px;") + " padding: 0px; background: #FFFFFF; }" +
		".jskit-container-footer { " + (oldStyleIE ? "margin-right: 5px;" : "position: absolute; bottom: 0px; right: 0px;") + " width: 100%; }" +
		".jskit-container-footerArea { float: left; }" +
		".jskit-container-poweredBy { float: right; border: 0px; cursor: pointer; font-size: 10px; color: #808080; margin: 6px " + (JSKitLib.isPreIE7() ? "5" : "20") + "px 5px 0px; }" +
		"div.jskit-container-poweredBy a, div.jskit-container-poweredBy a:hover { font-size: 10px; color: #808080; text-decoration: none; background-color: transparent; }" +
		".jskit-container-resizeControl { position: absolute; " + (JSKitLib.isPreIE7() ? "top: expression(eval(this.parentNode.offsetHeight - 14) + 'px');" : "bottom: 0px;" ) + " right: 0px; width: 12px; height: 12px; cursor: se-resize; font-size: 10px; }" +
		".js-SettingsWindow { z-index: 16000 !important; }" +
		".js-kit-clear { clear: both; }", "universalContainer");
}





function jskEchoInit(ref, target) {
	return (window.JSK$Echo || (window.JSK$Echo = new JSKEcho(ref, target)));
}

function JSKEcho(ref, target) {
	var s = this;
	s.ref = ref;
	s.target = target;
	s.existingRenderers = [];
	s.subscribers = [];
	s.subscribeRequest = [];
	s.uriDomain = '//js-kit.com';
}

JSKEcho.prototype.getRendererById = function(rendererId) {
	var rs = this.existingRenderers;
	var rsl = rs.length;
	for(var i=0; i<rsl; i++) {
		if(rs[i].id==rendererId) return rs[i];
	}
}

JSKEcho.prototype.createSubscribeRequest = function() {
	var s = this;
	var existingRenderersIds = JSKitLib.fmap(s.existingRenderers,
		function(renderer){
			return renderer.id;
		});
	JSKitLib.fmap(s.subscribeRequest, function(el) {
			el.requestRange = s.subscribers[el.id].requestRange;
		});
	return {
			'uri': s.uriDomain + '/api/echo/subscribe',
			'target': s.target,
			'onreturn': function(){
				s.subscribeAnswer.apply(s, arguments) },
			'pickup': true,
			'ref': s.ref,
			'epb': window.JSKitEPB ? JSKitEPB.getAsHash() : {},
			'request': {existingRenderers:
				JSKitLib.Object2JSON(existingRenderersIds)},
			'variableRequest': s.subscribeRequest,
			'trailer': 'id',
			'timeout': 60000
		};
}

JSKEcho.prototype.subscribeAnswer = function(error, data) {
	var s = this;
	var restartRequest = function() {
		s.jsrvcSubscribe.processRequest(s.createSubscribeRequest());
	}
	if(error=="timeout") {
		s.jsrvcSubscribe.requestsInProgress--;
		restartRequest();
		return;
	}
	if(error!="data"){
		alert(error);
		return;
	}
	JSKitLib.map(function(requestRange) {
		s.subscribers[requestRange.id].requestRange=requestRange.value;
	}, data.requestRanges);
	JSKitLib.map(function(renderer) {
		var er = s.existingRenderers;
		var erl = s.existingRenderers.length;
		var r = s.getRendererById(renderer.id);
		eval('var f = ' + renderer.content);
		if(!r) {
			er.push({'id': renderer.id});
			r = er[er.length-1];
		}
		r.content = f;
	}, data.renderers);
	JSKitLib.map(function(item){
		var subscriberId = item.id;
		var echoItems = item.echoItems;
		JSKitLib.map(function(echoItem) {
			var renderer = s.getRendererById(echoItem.renderer);
			if(renderer)
				echoItem.dom = renderer.content(echoItem);
		}, echoItems);
		s.subscribers[subscriberId].callback(echoItems);
	}, data.items);
	if(data.items.length) {
		restartRequest();
	} else {
		setTimeout(function(){
			restartRequest();
		}, data.timeout || 5000);
	}
}

JSKEcho.prototype.subscribe = function(multiParams) {
	var s = this;
	s.subscribeRequest = s.subscribeRequest.concat(
		JSKitLib.fmap(multiParams, function(param){
			var subscriber = {
				id: param.id || s.subscribers.length,
				callback: param.callback,
				requestRange: param.requestRange || 0
			};
			s.subscribers.push(subscriber);
			param.request.id = subscriber.id;
			param.request.requestRange =
				param.request.requestRange ||
							subscriber.requestRange;
			return param.request;
		})
	);
	if(!s.jsrvcSubscribe)
		s.jsrvcSubscribe = new JSRVC(s.createSubscribeRequest());
}

JSKEcho.prototype.publish = function(multiParams, callback) {
	var s = this;
	var publishRequest = JSKitLib.fmap(multiParams, function(param){
		return {operation: param.operation,
			echoItem: JSKitLib.Object2JSON(param.echoItem)};
	});
	new JSRVC({
		'uri': s.uriDomain + '/api/echo/publish',
		'target': s.target,
		'onreturn': callback,
		'request': {},
		'ref': s.ref,
		'epb': window.JSKitEPB ? JSKitEPB.getAsHash() : {},
		'variableRequest': publishRequest
	});
}





function JSKEchoPGC(itemsPerPage) {
	this.itemsPerPage = itemsPerPage;
	this.invalidate();
}

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

JSKEchoPGC.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;
}

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

JSKEchoPGC.prototype.deleteItem = function (itemId) {
	var itemIdx = this.getItemIdxById(itemId);
	if(typeof itemIdx == 'undefined') return 0;

	var r = 0;
	var self = this;
	var item = this.items[itemIdx];
	if(item.obj && item.obj.thread) {
		JSKitLib.fmap(item.obj.thread,
			function(c) {
				r += self.deleteItem(c.ID);
			});
	}
	if(item.obj && item.obj.status!='D' && item.obj.status!='DT') r++;
	if(itemIdx <= this.displayItemIdx) {
		this.displayItemIdx--;
		var div = item.div;
		if(div && div.parentNode) div.parentNode.removeChild(div);
	}
	this.items.splice(itemIdx, 1);
	this.itemsCount--;
	return r;
}

JSKEchoPGC.prototype.getPageByItemId = function(itemId) {
	var itemIdx = this.getItemIdxById(itemId);
	return (itemIdx <= this.displayItemIdx) ||
		(!itemIdx && this.displayItemIdx == -1) ? 0 : 1;
}

JSKEchoPGC.prototype.invalidateItemView = function (itemId) {
	var itemIdx = this.getItemIdxById(itemId);
	if(itemIdx <= this.displayItemIdx) {
		delete this.items[itemIdx].html;
		this.invalidVisualization = true;
	}
}

JSKEchoPGC.prototype.invalidatePagesView = function (pageIdx, Cnt) {
	if(!pageIdx) this.invalidVisualization = true;
}

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

JSKEchoPGC.prototype.getPageItemsCnt = function(pageIdx) {
	return pageIdx ? undefined : this.displayItemIdx + 1;
}

JSKEchoPGC.prototype.invalidate = function () {
	this.invalidData = true;
	this.invalidVisualization = true;
	this.items = [];
	this.itemsCount = 0;
	this.displayItemIdx = -1;
}

JSKEchoPGC.prototype.getItemsToDisplay = function () {
	return this.getItems(0, this.displayItemIdx + 1);
}

JSKEchoPGC.prototype.getPageVisualization = function (pageIdx, cb) {
	var self = this;
	var getPageFunc = function(){ self.getPageVisualization(pageIdx, cb); };
	var getMore = (this.itemsPerPage + this.displayItemIdx) >= this.itemsCount && pageIdx && this.echo_after ? true : false;
	if(this.invalidData || getMore) {
		this.invalidVisualization = true;
		return this.dataRequest(0, getMore, this.echo_after, cb);
	}
	if(this.invalidVisualization || pageIdx) {
		this.displayItemIdx = this.itemsCount-1;
		this.invalidVisualization = false;
		return this.dataVisualizator(this.getItemsToDisplay(), getPageFunc);
	}
	return cb(this.target, true);
}

JSKEchoPGC.prototype.getPlaceIdxByTS = function(TS) {
	var items = this.getItems(0, this.itemsCount);
	for(var i=0; i<this.itemsCount; i++) {
		if(TS>=items[i].obj.TS) return items[i].obj.ID;
	}
	return 0;
}

JSKEchoPGC.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;
};

JSKEchoPGC.prototype.addNewItem = function (obj, itemId, isPrepend) {
	var item = this.newItem({'obj': obj});
	var itemIdx = itemId ? this.getItemIdxById(itemId) + (isPrepend ? 0 : 1) : this.itemsCount;
	this.items.splice(itemIdx, 0, item);
	this.itemsCount++;
	if(itemIdx<=this.displayItemIdx ||
		(!obj.paginated && itemIdx==this.displayItemIdx+1) ||
		(!itemIdx && this.displayItemIdx == -1)) {
		this.displayItemIdx++;
		this.invalidVisualization = true;
	}
}

JSKEchoPGC.prototype.newData = function (newData, echo_after) {
	var s = this;
	s.$old_echo_after = s.echo_after;
	s.echo_after = echo_after;
	JSKitLib.fmap(newData, function(o) {
		var itemIdx = s.getItemIdxById(o.ID);
		if(typeof itemIdx != 'undefined') {
			JSKitLib.fmap(s.items[itemIdx].obj, function(v, k){
					s.items[itemIdx].obj[k] = o[k]; });
			if(itemIdx<=s.displayItemIdx) {
				delete s.items[itemIdx].html;
				s.invalidVisualization = true;
			}
		} else {
			s.items[s.itemsCount++] = s.newItem({'obj': o});
		}
	});
	this.displayItemIdx = this.itemsCount - 1;
	this.invalidData = false;
	this.loading = false;
}





if(!window.JSFSearch) JSFSearch = { threshold: 0.9 };

JSFSearch.get_hash_list = function(s) {
	return s.split(/[ \t]+/);
}

JSFSearch.normalize = function(s) {
	return s.toLowerCase().replace(/<wbr><\/wbr>/g, '').replace(/<[^<]*>/g,' ');
}

JSFSearch.make_hash = function(s) {
	var hash_list = JSFSearch.get_hash_list(JSFSearch.normalize(s));
	var hash_length = JSKitLib.foldl(0, hash_list,
				function(v, acc){ return acc + v.length });
	return {'hash_length': hash_length, 'hash_list': hash_list.sort()};
}

JSFSearch.get_hash_info = function(obj) {
	if(!obj.$hash_info)
		obj.$hash_info = JSFSearch.make_hash(obj.Text);
	return obj.$hash_info;
}

JSFSearch.compare_hash_lists$ = function(hash1, hash2, cnt1, cnt2, matched_count, mismatched1, mismatched2) {
	var hl1 = hash1.length;
	var hl2 = hash2.length;
	if(cnt1 >= hl1 && cnt2 >= hl2)
		return {'matched_count': matched_count,
			'mismatched1': mismatched1, 'mismatched2': mismatched2};
	if(cnt1 >= hl1) {
		mismatched2.push(hash2[cnt2]);
		cnt2++;
	} else
	if(cnt2 >= hl2) {
		mismatched1.push(hash1[cnt1]);
		cnt1++;
	} else
	if(hash1[cnt1] == hash2[cnt2]) {
		matched_count += hash1[cnt1].length;
		cnt1++;
		cnt2++;
	} else
	if(hash1[cnt1] <= hash2[cnt2]) {
		mismatched1.push(hash1[cnt1]);
		cnt1++;
	} else {
		mismatched2.push(hash2[cnt2]);
		cnt2++;
	}
	return JSFSearch.compare_hash_lists$(hash1, hash2, cnt1, cnt2,
			 matched_count, mismatched1, mismatched2);

}

JSFSearch.compare_hash_lists = function(hash1, hash2) {
	return JSFSearch.compare_hash_lists$(hash1, hash2, 0, 0, 0, [], []);
}

JSFSearch.get_avg = function(hash) {
	var flat_list = hash.join('');
	var sum = 0;
	var len = flat_list.length;
	for(var i=0; i<len; i++) {
		sum += flat_list.charCodeAt(i);
	}
	var avg = len ? sum/len : 0;
	return {'avg': avg, 'list': flat_list};
}

JSFSearch.corr_coeff = function(avg1, avg2) {
	var sum1 = sum2 = sum3 = 0;
	var calc_summs = function(e1, e2) {
		var d1 = e1 - avg1.avg;
		var d2 = e2 - avg2.avg;
		sum1 += d1 * d2;
		sum2 += d1 * d1;
		sum3 += d2 * d2;
	}
	var l1 = avg1.list.length;
	var l2 = avg2.list.length;
	var l = Math.max(l1, l2);
	while (l > 0) {
		l--;
		if(l>=l1) calc_summs(0, avg2.list.charCodeAt(l))
		else if(l>=l2) calc_summs(avg1.list.charCodeAt(l), 0)
		else calc_summs(avg1.list.charCodeAt(l),avg2.list.charCodeAt(l));
	}
	return {'sum1': sum1, 'sum2': sum2, 'sum3': sum3};
}

JSFSearch.calc_distance = function(hash1, hash2) {
	var avg_info1 = JSFSearch.get_avg(hash1);
	var avg_info2 = JSFSearch.get_avg(hash2);
	var sums = JSFSearch.corr_coeff(avg_info1, avg_info2);
	return ((sums.sum2 < 0.1 || sums.sum3 < 0.1) ? 0 :
		sums.sum1/Math.sqrt(sums.sum2)/Math.sqrt(sums.sum3));
}

JSFSearch.compare_hashes = function(hash1, hash2) {
	var hl1 = hash1.hash_length;
	var hl2 = hash2.hash_length;
	if(hl1 == 0 && hl2 == 0) return 1;
	var compare_info = JSFSearch.compare_hash_lists(hash1.hash_list,
							hash2.hash_list);
	var total_len = (hl1 + hl2) / 2;
	var matched_pcnt = compare_info.matched_count / total_len;
	if(total_len - compare_info.matched_count < 0.1) return 1;
	if(compare_info.matched_count < total_len/2) return 0;
	if(matched_pcnt > JSFSearch.threshold) return 0.99;
	if(matched_pcnt > 0.75 && compare_info.matched_count > hl1 * 0.9)
		return 0.99;
	if(matched_pcnt > 0.75 && compare_info.matched_count > hl2 * 0.9)
		return 0.99;
	return (matched_pcnt +
		Math.abs(JSFSearch.calc_distance(
			compare_info.mismatched1, compare_info.mismatched2)) *
		(total_len - compare_info.matched_count) / total_len);
}

JSFSearch.compare_obj = function(obj1, obj2) {
	return (JSFSearch.compare_hashes(JSFSearch.get_hash_info(obj1),
			JSFSearch.get_hash_info(obj2)) > JSFSearch.threshold);
}

JSFSearch.search = function(items, obj) {
	if(!obj.event_publisher || obj.ParentID || obj.depth || !obj.Text)
		return obj.ParentID;
	for (var i=0; i<items.length; i++) {
		var curobj = items[i].obj;
		if(curobj.event_publisher && !curobj.depth && curobj.Text) {
			if(JSFSearch.compare_obj(obj, curobj))
				return curobj.ID;
		}
	}
}



/* 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/';
JSCC.MINI_PROFILE_TTL = 1000;
JSCC.REPOST_COMMENT_TIMEOUT = 20000;

/* 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";
	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;
	this.extraFormFields = {};
	this.pause = {
		'state': false,
		'queue': [],
		'visible': false,
		'forced': false
	};
	this.moderationCommentsList = {};
	var self = this;

	var groupSingleRequestParams = function(self, obj) {
		var params = obj || {};
		var filter = self.sourceFilter;
		params.jx = self.jcaIndex;
		params.p = self.config.path;
		params.gen = self.gen || 0;
		params.srt = self.config.sort;
		params.sp = params.sp || 1;
		params.skin = self.config.skin || "echo";
		if(self.config.paginate) params.ps = self.config.paginate;
		if(self.config.backwards == 'yes') params.ord = 'desc';
		if(self.config.thread != 'yes') params.prs = 'flat';
		if(self.config.moderate) params.mod = 1;
		if(self.config["display-mode"]) params.dm = self.config["display-mode"];
		if(filter) params[filter.type] = filter.sources.list;
		if(self.config.permalink) params.permalink = self.config.permalink;
		return params;
	}

	var initSourceFilter = function(config) {
		var filter = {};
		JSKitLib.fmap(["include", "exclude"], function(key) {
			if (config[key + "-sources"]) filter.type = key;
		});
		if (!filter.type) return;
		filter.normalize = function(name) {
			return JSKitLib.trim(name.toLowerCase());
		};
		filter.sources = JSKitLib.foldl({"hash": {}, "list": []}, config[filter.type + "-sources"].split(",") || [], function(name, acc) {
			name = filter.normalize(name);
			if (!name || acc.hash[name]) return;
			acc.hash[name] = filter.type == "include";
			acc.list.push(name);
		});
		if (!filter.sources.list.length) return;
		filter.sources.list = filter.sources.list.join(",");
		return filter;
	}

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

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

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

	if(target) {
		this.jcaIndex = $JCA.length;
		$JCA.push(this);

		var cn = target.childNodes;
		for(var n=0;n < cn.length;n++) {
			if(cn[n].className) {
				var arr = String(cn[n].className).split(/[ ]+/);
				JSKitLib.fmap(arr, function(c) {
					if(c.substr(0, 3) == 'js-')
						self.utmpl[c] = JSKitLib.getOuterHTML(cn[n]);
				});
			}
		}

		if(cn.length) target.innerHTML = "";
		var utsc = this.utmpl['js-singleComment'];
		if(utsc) this.dtComment = utsc;
		var utgm = this.utmpl['js-groupModeration'];
		if(utgm) this.dtGroupModeration = utgm;

		// 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($JCL("savingScriptMessage"));
			return;
		}
		JSKitLib.preloadImg('//cdn.js-kit.com/images/loading-yellow.gif');

		var request = {
			base_uri: JSCC.URI + 's-data.js',
			trailer: 'jx',
			extra_params: this.comment_location ? {'jsid': this.comment_location} : {}
		};
		JSKitLib.initWidgets('comments', request, function(div) {
			var obj = new JSCC(div, {'config': {'noDataRequest': true}});
			var params = groupSingleRequestParams(obj); 
			obj.singleRequestParams = params;
			return obj;
		});

		JSKitLib.fmap([
			'comment-deleting',
			'comment-deleted',
			'comment-added',
			'comments-data-loaded',
			'comments-count-updated'
		], function(e) {
			JSKitAPI.subscribe(e, function(eventName, eventParams) {
				$JCA[eventParams.jcaIndex].eventsHandler(eventName, eventParams);
			});
		});
		JSKitLib.fmap({
			'JSKitAuth_logout': 'user-logout',
			'JSKitAuth_success_login': 'user-login'
		}, function(v, k) {
			JSKW$Events.registerEventCallback(undefined, function() {
				JSKitAPI.publish(v, {"nofocus": false});
			}, k);
		});

		return;
	}
	target.jsk$initialized = true;
	target.className = idName;
	target.id = "";

	// Handling user configuration settings
	this.config = JSKitLib.readConfig("comments",
		target,
		this.config,
		'path',
		'display-mode',
		['standalone', 'no'],
		['scoring', 'yes'],
		'paginate',
		'backwards',
		['disabled', 'no'],
		'domain',
		['sort', ['date','karma','name','status','rating']],
		['thread', ['yes','no']],
		'adminBgColor',
		'flashColor',
		'moderate',
		'permalink',
		'skin',
		'noautoexpand',
		'label',
		['smiles', 'no'],
		['editable', 'no'],
		['thread-title', $JCL("defaultThreadTitle")],
		'popup-title',
		'popup-width',
		'popup-height',
		'include-sources',
		'exclude-sources',
		['page-title', document.title]
	);
	if (!this.config.backwards) {
		if (this.config.paginate)
			this.config.backwards = 'yes';
		else
			this.config.backwards = this.config.nolc && !this.IM ? 'yes' : 'no';
	}
	this.uniq = this.config.path;
	this.pathOverride = this.config.path;
	this.sourceFilter = initSourceFilter(this.config);
	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';

	self.target = target;

	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);
		var so = this.serverOptions;
		prms = JSKitLib.appendExternalParams("comments", ext, prms);
		prms.p = this.pathOverride;
		prms.nonce = so && so.nonce || "";
		prms['page-title'] = self.config['page-title'];
		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) {
		self.loading = (new Date()).valueOf();
		var prms = {};
		JSKitLib.fmap(groupSingleRequestParams(self, {sp: sp}), function(v, k) {prms[k + "[0]"] = v;});
		if(ap) JSKitLib.fmap(ap, function(v,k){ prms[k] = v ;});
		self.server("s-data.js", prms);
	}

	JSKitLib.fmap(['user-login', 'user-logout'], function(e) {
		JSKitAPI.subscribe(e, function(eventName, eventParams) {
			self.eventsHandler(eventName, eventParams);
		});
	});

	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="//cdn.js-kit.com/images/welcome/close.png", sizingMethod="crop")' : 'background: no-repeat url(//cdn.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="//cdn.js-kit.com/images/welcome/' + v + '.png", sizingMethod="crop");' : 'background: url(//cdn.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: 5px 0 0 5px; }"
	+ ".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-commentShareCheckbox { float: left; margin: " + (JSKitLib.isIE() ? "-3px" : "1px") + " 0 0 5px; }"
	+ ".js-commentShareLabel { 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="//cdn.js-kit.com/images/yahoo/yoslogo.png", sizingMethod="crop");' : 'background: no-repeat url(//cdn.js-kit.com/images/yahoo/yoslogo.png);') + " }"
	+ ".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: #e8e8e8; 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; }"
	+ ".js-singleCommentCheckbox { float: left; margin: " + (JSKitLib.isIE()?"0":"2") + "px 2px 0px 0px; width: 16px; height: 16px; cursor: pointer; }"
	+ '.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; text-decoration: underline; }"
	+ ".js-singleCommentUrl { margin: 0px 0px 0px 2px; padding: 0px; border: 0px; width: 10px; height: 10px; display: none; vertical-align: top; }"
	+ ".js-singleCommentDate { font-size: 7pt; }"
	+ ".js-singleCommentOrigin { display: inline; 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: inline; 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-singleCommentControl, .js-singleCommentKarmaY, .js-singleCommentKarmaN { cursor: pointer; }"
	+ ".jskit-MenuTitle { cursor:pointer; padding: 3px; white-space: nowrap; color: #476cb8; font-size: 11px; width: 100%; }"
	+ ".jskit-MenuTitleMO { }"
	+ ".jskit-MenuTitlePressed { }"
	+ ".jskit-MenuTitleExpandMarker { width: 16px; height: 16px; margin: 1px 0px 0px -2px; }"
	+ ".jskit-MenuContainer { border: 1px solid #D6E2E9; background-color: #FFFFFF; cursor:pointer; position: absolute; margin-left: -2px; -moz-border-radius: 4px; -webkit-border-radius: 4px; z-index: 20000;}"
	+ ".jsk-MenuAdmin td, .js-kit-miniProfile-addAnotherSite td, .jskit-MenuContainer td, .js-singleCommentMenu td, .jsk-HeaderPauseBox td { padding: 0px !important; vertical-align: middle !important; border-collapse: separate !important; border: 0px solid !important;}"
	+ ".jsk-MenuAdmin table, .js-kit-miniProfile-addAnotherSite table, .jskit-MenuContainer table, .js-singleCommentMenu table, .jsk-HeaderPauseBox table { margin: 0px !important; border-collapse: separate !important; border: 0px solid !important; width: auto !important; }"
	+ ".jskit-MenuRootContainer { margin: 2px 0px 0px -3px; }"
	+ ".jskit-MenuRootHTML { float: left; height: 2em; }"
	+ ".jskit-MenuItem { border: 1px 0px solid #FFFFFF; line-height: 14px; }"
	+ ".jskit-MenuItemIcon { width: 16px; height: 16px; margin: 4px 6px;" + (JSKitLib.isIE() ? " zoom: 1;" : " float: left;" ) + " }"
	+ ".jskit-MenuItemCheckboxCnt, .jskit-MenuItemRadioCnt { height: 24px; width: 65px; float: left; white-space: nowrap; margin: 0px; line-height: 14px;" + (JSKitLib.isIE() ? "zoom: 1;" : "") + "}"
	+ ".jskit-MenuItemTitle { margin: 5px 20px 4px 0px; color: #000000; font: 12px Arial; text-decoration: none; white-space: nowrap; zoom: 1;}"
	+ ".jskit-MenuItemEnding { height: 16px; margin: 2px; font-size: 14px; color: #000000; display: inline; font-family: Arial; }"
	+ "div.jskit-AvatarMenuItemEnding { display: block; margin: 1px 3px; }"
	+ ".jskit-MenuItemMO { background-color: #EDEDED; }"
	+ ".jskit-MenuItemMO .jskit-MenuDeleteButton { visibility: visible; }"
	+ ".jskit-MenuDelimeter { margin: 2px 0px; height: 1px; width: 100%; background-color: #CCCCCC; font-size: 1px; width: 100%; }"
	+ ".jskit-MenuItemInput { line-height: 16px; font: 12px Arial; padding: 0px; border: 1px solid #AAAAAA; height: 16px; margin: " + (JSKitLib.isIE() ? "3px" : "3px") + " 0px; width: 120px; position: absolute; }"
	+ ".jskit-MenuItemCheckbox, .jskit-MenuItemRadio { margin: 4px 4px 4px 10px; padding: 0px 8px; line-height: 16px; height: 16px; float: left; }"
	+ ".jskit-MenuDeleteButton { width: 16px; height: 16px; margin: 7px 0px 0px 2px; display: block; visibility: hidden; }"
	+ 'div.js-singleCommentEdit, div.js-singleCommentReply, div.js-singleCommentDelete, div.js-singleCommentModerate { background: right top url(//cdn.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(//cdn.js-kit.com/images/button-clear.png) no-repeat; height: 16px; padding: 2px 4px 0px 5px; position: relative; left: -1px; float: left; }'
	+ ".js-kit-lcf-miniProfile { " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " }"
	+ ".js-kit-singleCmtProfileEnabled .js-kit-miniProfile-avatar, .js-kit-singleCmtProfileEnabled .js-kit-miniProfile-stats, .js-kit-singleCmtProfileEnabled .js-kit-miniProfile-viewDetails, .js-kit-singleCmtProfileEnabled .js-kit-miniProfile-name { cursor: pointer; }"
	+ ".js-kit-lcj-miniProfile-name-ipe { cursor: text; }"
	+ ".js-kit-singleCmtProfileDisabled .js-kit-miniProfile-viewDetails { display: none; }"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfileNameWrap { padding-bottom: 5px; }"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfile-name, .js-kit-lcf-miniProfile .js-kit-miniProfile-siteLinksIcons { float: left; }"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfileSitesWrap { border-top: 2px dotted #E4E4E4; padding-top: 5px; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " }"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfile-addAnotherSite { float: left; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + "margin: 1px 0px 0px 0px; cursor: pointer; }"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfile-addAnotherSite span.text { color: #0066CC; margin-right: 5px; }"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfile-siteLinksIcons { border: 0px; }"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfile-name-ipe { margin-right: 70px; height: 24px; line-height: 20px; font-size: 16px; border: 0px; outline: 0px;}"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfile-logout { " + (JSKitEPB.isExists() ? "display: none" : "float: right; margin: 1px 0px 0px -70px; cursor: pointer; color: #0066CC; font-size: 10px;") + "}"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfile-logoutIcon { float: left; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " margin: 2px 0px 0px 5px; padding: 0px 5px; font-size: 8px; width: 10px; height: 10px; }"
	+ ".js-kit-lcf-miniProfile .js-kit-miniProfile-logoutLink { float: left; " + (JSKitLib.isIE() ? "zoom: 1; padding-bottom: 2px;" : "") + " }"
	+ ".js-kit-lcf-extraControlsMenuWrapper { float: left; }"
	+ ".js-kit-relative { position: relative; }"
	+ ".js-CreateComment .js-kit-tabs-singleTab { display: block; }"
	+ ".js-CreateComment .js-kit-tab { padding: 5px 0px 5px 0px; margin-right: 20px; background: transparent; cursor: pointer; }"
	+ ".js-CreateComment .js-kit-tab-title { color: #0066CC; }"
	+ ".js-CreateComment .js-kit-tab .js-kit-tab-expandMarker { float: left; width: 16px; height: 16px; }"
	+ ".js-kit-lcf-extraControlsMenuContent { border: 1px solid #BBBBBB; background: #FFFFFF; margin-top: 10px; color: #3a3a3a;}"
	+ ".js-kit-images-wrapper, .js-kit-follow-wrapper { padding: 10px; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " }"
	+ ".js-kit-images-form { margin: 20px 0px; }"
	+ ".js-kit-images-form .js-uploadImageForm { display: inline; }"
	+ ".js-kit-images-form .js-uploadImageInputLabel { display: inline; margin-right: 5px; font-size: 12px; }"
	+ ".js-kit-images-form .js-kit-images-imgSizeSpec { display: none; }"
	+ ".js-kit-follow-openingProfile { cursor: default; text-decoration: none; }"
	+ ".js-kit-follow-activeNotifyMode-noemail { background: none; }"
	+ ".js-kit-follow-activeNotifyMode-email, .js-kit-follow-activeNotifyMode-anymails { background: #fffea9; }"
	+ ".js-kit-follow-notifyOptionRadio { float: left; width: 16px; height: 16px; cursor: pointer; }"
	+ ".js-kit-follow-notifyOptionLabel { float: left; margin-left: 3px; font-size: 12px; cursor: pointer; }"
	+ ".js-kit-follow-emailAddress { margin: 0px 5px; }"
	+ ".js-kit-follow-leftColumn { float: left; margin-right: -26px; position: relative; width: 26px; }"
	+ ".js-kit-follow-rightColumnWrapper { float: left; width: 100%; }"
	+ ".js-kit-follow-rightColumn { margin-left: 26px; }"
	+ ".js-kit-follow-emailContainer { " + (JSKitLib.isPreIE8() ? "zoom: 1; margin-left: 5px;" : "") + " font-size: 12px; margin-bottom: 10px; }"
	+ ".js-kit-follow-rssContainer { " + (JSKitLib.isPreIE8() ? "zoom: 1;" : "") + " }"
	+ ".js-kit-follow-rightSubColumn { float: right; position: relative; margin-left: -95px; width: 85px; }"
	+ ".js-kit-follow-leftSubColumnWrapper { float: right; width: 100%; }"
	+ ".js-kit-follow-leftSubColumn { margin-right: 95px; }"
	+ ".js-kit-follow-notifyModeSelector { margin: 5px 0px; }"
	+ ".js-kit-follow-rssThreadButton { padding: 0px; margin-left: 5px; cursor: pointer; }"
	+ ".js-kit-follow-label { font-size: 12px; font-weight: bold; }"
	+ ".js-kit-follow-emailIcon, .js-kit-follow-rssIcon { width: 16px; height: 16px; }"
	+ ".js-kit-follow-input { width: " + (JSKitLib.isIE() ? "98%" : "100%") + "; }"
	+ ".js-kit-exp-banner-container { background: #fffac3; border: 1px solid #fee747; position: absolute; z-index: 20100; width: 320px; height: 200px; margin: 0px; padding: 15px 20px; font-size: 12px; line-height: 120%; text-align: left; }"
	+ ".js-kit-exp-banner-header { margin-bottom: 10px; text-align: center; }"
	+ ".js-kit-exp-banner-title { font-weight: bold; }"
	+ ".js-kit-exp-banner-label { font-weight: bold; margin-right: 5px; }"
	+ ".js-kit-exp-banner-button-container { text-align: center; margin-top: 20px; }"
	+ ".js-kit-exp-banner-button { background-color: transparent; background-image: url('//cdn.js-kit.com/images/common/continue.png'); border: none; cursor: pointer; margin: 0; padding: 0; width: 112px; height: 39px; }"
	+ ".js-kit-replies-expand-container { padding: 10px 0px; cursor: pointer; text-align: center; background: url(//cdn.js-kit.com/images/replies-expand-bg.png) repeat-x center; }"
	+ ".js-kit-replies-expand-wrapper { display: inline; padding: 0px 10px; }"
	+ ".js-kit-replies-expand-label { display: inline; background: url(//cdn.js-kit.com/images/whirlpool-comments.png) center left no-repeat; padding-left: 15px; }"
	+ ".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; color: #808080; font-size: 7pt; font-family: Verdana, Helvetica; }"
	+ ".js-poweredBy A, .js-poweredBy A .js-poweredBy-text { text-decoration: none; color: #8080a0 !important; cursor: pointer; }"
	+ ".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(//cdn.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(//cdn.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-CommentsSkin-wireframe .js-commentAvatar { background: #FFFFFF; border: 1px solid #c0c0c0; width: 96px; height: 96px; margin: 0px 0px 5px 0px; }"
	+ ".js-CommentsSkin-smoothgray .js-commentAvatar { background: #FFFFFF; position: relative; float: right; margin-left: -102px; border: 1px solid #c0c0c0; width: 96px; height: 96px; }"
	+ ".js-kit-lcf-avatarsManagerWrapper { float: left; position: relative; width: 64px; height: 64px; margin-right: 10px; margin-right: -75px; overflow: visible !important; }"
	+ ".js-kit-basicUserInfoWrap { float: left; width: 100%; }"
	+ ".js-kit-lcf-userInfoWrapper { " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " }"
	+ ".js-kit-nonLoggedUserInfo .js-kit-lcf-fromMenuAnonymous, .js-kit-nonLoggedUserInfo .js-kit-lcf-toMenu, .js-kit-nonLoggedUserInfo .js-kit-fromMenuAnonymous { margin-left: 75px; }"
	+ ".js-kit-from-to-menu-title { margin: 5px 8px 0px 8px; font-weight: bold; font-size: 10px; }"
	+ ".js-kit-from-to-menu-footer { margin-top: 8px; }"
	+ ".js-kit-lcf-toMenu { margin: 9px 0px; }"
	+ ".js-kit-lcf-toField, .js-kit-from-menuAnonymousWrap { background-color: #FFFFFF; border: 1px solid #BBBBBB; }"
	+ ".js-kit-from-menuAnonymousWrap { " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " }"
	+ ".js-kit-lcf-toField .jskit-MenuRootHTML { cursor: pointer; }"
	+ ".js-kit-lcf-toField { cursor: pointer; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " }"
	+ ".jskit-MenuRootHTML { cursor: pointer; }"
	+ ".js-kit-from-control { float: left; margin-right: -85px; position: relative; }"
	+ ".js-kit-from-field { float: left; width: 100%; height: 26px; cursor: text; }"
	+ ".js-kit-from-name { margin: 5px 0px 0px " + (JSKitLib.isIE() ? "85" : "81") + "px; font-size: 14px; border: 0px; cursor:text; width: 15em; line-height: 14px; outline: 0px;}"
	+ ".js-kit-from-name input.jsipe-input { margin: 0px; padding: 0px; border: 0px; background: #FFFFFF; outline: 0px; font-size: 14px !important; }"
	+ ".js-kit-disabledNameField { background-color: #fffea9; cursor: pointer; }"
	+ ".js-kit-disabledNameField .js-kit-from-name, .js-kit-disabledNameField .js-kit-miniProfile-name-ipe { width: auto; cursor: pointer; }"
	+ ".js-kit-loggedUserInfo { margin-left: 0px; }"
	+ ".js-CmtSpam { background: url(//cdn.js-kit.com/images/bio-hazard.gif) bottom right repeat-x !important; background-color: #ffffe0 !important; color: #404040; }"
	+ (JSKitLib.isIE() ? ".js-CreateComment { zoom: 1; }" : "")
        + ".js-previewImageDescr { width: 102px; left: 0px; bottom: 0px; }"
	+ ".js-previewImage { position: relative; text-align: center; margin: 4px; float: left; width: 102px; }"
	+ ".js-all-previewImages {margin-top: 15px; border-top: 1px solid #ececec; border-bottom: 1px solid #ececec; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + "}"
	+ ".js-all-previewImages .js-previewImage { position: static; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + " }"
	+ ".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; }"
	+ ".js-CommentsPopupLink { cursor: pointer; }"
	+ ".js-kit-popupComments { z-index: 13900 !important; }"
	+ ".js-kit-popupComments .js-CommentsArea { padding: 7px }"
	+ ".js-kit-popupComments .js-LeaveComment { font-family: Arial; font-size: 11pt; }"
	+ ".js-kit-follow-popup-container { border: 4px solid #CBCBCB; text-align: left; }"
	+ ".js-kit-follow-popup-header { font-family: Verdana, Helvetica; font-weight: bold; font-size: 12pt; color: gray; }"
	+ ".js-kit-follow-popup-header, .js-kit-follow-popup-footer { padding: 10px; background: #ECECEC; }"
	+ ".js-kit-follow-popup-editNotifications { float: left; cursor: pointer; font-size: 14px; padding-top: 3px; }"
	+ ".js-kit-follow-popup-cancelButtonContainer, .js-kit-follow-popup-doneButtonContainer { float: right; }"
	+ ".js-kit-follow-popup-cancelButton { margin-right: 5px; }"
	+ ".js-kit-clickable { cursor: pointer; }"
	, '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; }"
	+ ".js-CommentsSkin-smoothgray .js-singleCommentBg { zoom: 1; padding: 0.3em; position: relative; }"
	, "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");

	// new skin layout
	JSKitLib.addCss(''
	+ '.js-CommentsSkin-echo .jsk-ThreadWrapper { margin-bottom: 1em; padding: 10px; -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; ' + (JSKitLib.isIE() ? 'zoom:1;' : '') + ' }'
	+ '.js-CommentsSkin-echo .jsk-StreamWrapper { margin-bottom: 1em; background: url(//cdn.js-kit.com/images/dot-gray.png) repeat-x bottom; }'
	+ '.js-CommentsSkin-echo .jsk-HeaderWrapper { padding-top: 1em; padding-bottom: 1em; }'
	+ '.js-CommentsSkin-echo textarea.js-CmtText-noWYSIWYG, .js-CommentsSkin-echo textarea.js-CmtTextEdit-noWYSIWYG { border: 0px; background: #FFFFFF; padding: 0px; }'
	+ '.js-CommentsSkin-echo .jsk-CommentFormBody-noWYSIWYG, .js-CommentsSkin-echo .jsk-CommentEditFormBody-noWYSIWYG { ' + (JSKitLib.isIE() ? "zoom: 1;" : "") + ' border: 1px solid #BBBBBB; padding: 5px 7px; background: #FFFFFF; }'
	+ '.js-CommentsSkin-echo .js-commentTool { display: none; }'
	+ ".js-CommentsSkin-echo .js-singleCommentAvatar { background-position: center; }"
	+ ".js-PageMore { text-align: center; border: solid 1px #E4E4E4; padding: 10px; -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; cursor: pointer; font-weight: bold; background-color: #FFFFFF; " + (JSKitLib.isIE() ? "zoom: 1;" : "") + "}"
	+ '.jsk-HeaderInfoBox { float: left; }'
	+ '.jsk-HeaderInfoBoxImg { float: left; padding: 0px; width: 16px; height: 16px; }'
	+ '.jsk-CommentsCountWrap { float: left; ' + (JSKitLib.isIE() ? "zoom: 1;" : "") + ' padding: 0px; margin-left: 5px; line-height: normal !important; }'
	+ '.jsk-CommentsCount { font-weight: bold !important; }'
	+ '.jsk-HeaderMenu { float: right; }'
	+ '.jsk-HeaderPauseBox { display: none; margin: 0px; padding: 3px; float: right; vertical-align: middle;}'
	+ '.jsk-HeaderPauseBoxImg { float: left; width: 16px; margin-right: 2px; }'
	+ '.jsk-MenuAdmin { float: right; }'
	+ '.jsk-MenuAdmin .jskit-MenuItem { text-align: left; }'
	+ '.jsk-ItemWrapper { padding-bottom: 1em; padding-top: 1em; background: url(//cdn.js-kit.com/images/dot-gray.png) repeat-x top; line-height: 150%; }'
	+ '.jsk-ItemWrapper-borderless { background: none; }'
	+ '.jsk-ItemUserAvatarWrapper { float: left; padding: 2px; }'
	+ '.jsk-ItemContentWrapper { margin-left: 10px }'
	+ '.jsk-ItemFooter { text-align: left; }'
	+ '.jsk-ItemAttachmentsTitle { float: left; line-height: 100%; font-size: 0.8em; padding: 1px; }'
	+ '.jsk-ItemAttachmentIconWrapper { padding: 5px; border: 1px solid #ECECEC; }'
	+ '.jsk-ItemAttachmentWrapper { float: left; margin: 0px; margin: 5px 12px 5px 12px; text-align: center; width: 110px; }'
	+ '.js-singleCommentAdminStar { border: 0; width: 16px; height: 16px; vertical-align: middle; display: none; }'

	+ ".jsk-CommentFormSurface { zoom: 1; -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; border: 1px solid #dddddd; padding: 11px; line-height: normal; }"
	+ ".jsk-CommentFormAvatar { float: left; }"
	+ ".jsk-CommentFormFooter { margin-top: 11px; width: 100%; }"
	+ ".jsk-CommentFormAvatarsArea { border: 1px solid #bbbbbb; margin: 0em 0em 0.6em 0em; padding: 0.3em; }"
	+ ".jsk-CommentFormAvatarsArea .jsk-avt-section-label { font-weight: bold; font-size: 12px; }"
	+ ".jsk-CommentFormAvatarsArea .jsk-avt-upload-label { font-size: 8pt; }"
	+ ".jsk-CommentFormInputsWrapper { padding-left: 113px; margin-bottom: 11px; }"
	+ ".jsk-CommentFormButton { margin-left: 0.5em; }"
	+ ".jsk-CommentFormWrapper { margin-bottom: 1em; }"

	// new pager
	+ '.jsk-PagerWrapper { width: 100%; text-align: center; padding: 0.75em 0px; }'
	+ '.jsk-Pager { border: 0; margin: 0; padding: 0; display: inline; }'
	+ '.jsk-Pager li { border:0; margin:0; padding:0; list-style:none; display: inline; margin-left: 3px; }'
	+ '.jsk-Pager a { border: solid 1px #DDDDDD; }'
	+ '.jsk-Pager .jsk-PrevOff, .jsk-Pager .jsk-NextOff { color:#666666; padding: 5px 8px; }'
	+ '.jsk-Pager .jsk-Prev a, .jsk-Pager .jsk-Next a { border:solid 1px #DDDDDD; }'
	+ '.jsk-Pager .jsk-Active { color:#ff0084; font-weight:bold; padding: 5px 8px; }'
	+ '.jsk-Pager a:link, .jsk-Pager a:visited { color:#0063e3; padding: 4px 7px; text-decoration:none; }'
	+ '.jsk-Pager a:hover { border:solid 1px #666666; }'
	+ '.jsk-PagerItemHover { background-color: #E4E4E4; }'

	// new skin theme
	// colors:
	+ '.jsk-PrimaryBackgroundColor { background-color: #FFFFFF; }'
	+ '.jsk-SecondaryBackgroundColor { background-color: #f4f4f4; }'
	+ '.jsk-TrinaryBackgroundColor { background-color: #ECEFF5; }'
	+ '.jsk-PrimaryHighlightColor { color: #fffea9; }'
	+ '.jsk-SecondaryHighlightColor { color: #ffff00; }'
	+ '.jsk-PrimaryFontColor { color: #3a3a3a; }'
	+ '.jsk-SecondaryFontColor, .jsk-ThreadWrapper a.jsk-SecondaryFontColor { color: #c6c6c6; }'
	+ '.jsk-ThreadWrapper a, .jsk-LinkColor { color: #476cb8; }'
	+ '.jsk-H1Color { color: #878487; }'
	// fonts:
	+ '.jsk-PrimaryFont, .jsk-PrimaryFont a:hover, .jsk-CommentFormSurface input, .js-kit-follow-popup-container input { font-family: Lucida grande, Tahoma, Verdana, Arial; }'
	+ '.jsk-PrimaryFont { font-size: 8pt; font-weight: normal; }'
	+ '.jsk-H1Font { font-size: 1.38em; font-weight: bold; line-height: 1.4em; }'
	+ '.jsk-LinkFont, .jsk-ThreadWrapper a, .jsk-ThreadWrapper a:hover { text-decoration: none; font-weight: normal; }'

	// other skin's properties
	+ '.jsk-DisabledFontColor { color: #9c9c9c; }'
	+ '.jsk-ItemName { font-weight: bold; }'
	+ 'input.jsk-CommentFormButton { font-size: 1.25em; }'
	+ '.jsk-HeaderMenu table td { border-spacing: 0; padding: 0; margin: 0; vertical-align: middle; height: 16px; }'
	+ '.jsk-HeaderMenu table td .js-singleCommentMenuTitleExpandMarker { margin: 0; padding: 0; }'
	+ '.jsk-HeaderMenu .js-singleCommentMenuTitle { padding: 0; margin: 0; }'
	+ '.js-CommentsSkin-echo .js-poweredBy { font-family: Arial; font-size: 9px; color: #bbbbbb; margin-top: 1.2em; white-space: nowrap; line-height: normal; text-align: right; }'
	+ '.js-CommentsSkin-echo .js-poweredBy-wrapper { float: right; }'
	+ '.js-CommentsSkin-echo .js-poweredBy-logo { ' + (JSKitLib.isPreIE8() ? "zoom: 1;" : "") + ' border: none; margin-left: 5px; height: 14px; width: 25px; float: right; }'
	+ '.js-CommentsSkin-echo .js-poweredBy-text { ' + (JSKitLib.isIE() ? "zoom: 1; padding-bottom: 3px;" : "") + 'float: right; }'
	+ '.js-CommentsSkin-echo .js-commentAvatar { margin: 0; }'
	+ ".js-CommentsSkin-echo .js-commentFieldInput { outline: 0px; border: 0px solid; width: 100%; }"
	+ ".js-CommentsSkin-echo .js-commentFieldLabel { clear: none; margin: 0; }"
	+ ".js-CommentsSkin-echo .js-authSelector { float: none; }"
	+ '.js-CommentsSkin-echo .js-singleComment { border: none; }'
	+ '.js-CommentsSkin-echo .js-singleCommentBg { padding: 0; position: static; }'
	+ '.js-CommentsSkin-echo .jsk-ItemChildrenMarker { border-color: transparent transparent #ECEFF5; border-width: 0px 11px 11px; border-style: solid; margin: 3px 0px 0px 67px; height: 1px; width: 0px; display: none;' + (JSKitLib.isIE() ? ' font-size: 1px; line-height: 1px; filter: chroma(color=black);' : '') + ' }' // This is magic "arrow up". Only color and margins could be changed
	+ '.js-CommentsSkin-echo .jsk-ItemWrapperThread { padding-bottom: 1px; }'
	+ '.js-CommentsSkin-echo .jsk-ItemWrapperThread .jsk-ItemChildrenMarker { display: block; }'
	+ '.js-CommentsSkin-echo .jsk-ItemWrapperChild { padding: 10px; margin: 0px 20px 2px 0px; background-image: none; }'
	+ '.js-CommentsSkin-echo .js-singleCommentCtls { float: left; white-space: normal; }'
	+ '.js-CommentsSkin-echo .js-singleCommentDate { font-size: 1em; }'
	+ '.js-CommentsSkin-echo .js-previewImageDescr { width: 110px; }'
	+ '.js-CommentsSkin-echo .jsk-ItemAge { float: left; margin: 0 0.5em 0 0; }'
	+ '.js-CommentsSkin-echo .js-CommentWaitSubmit { position: absolute; left: 11px; bottom: 3px; }'
	+ '.js-CommentsSkin-echo .js-CommentWaitSubmitImg { margin-bottom: -3px; }'
	+ '.js-CommentsSkin-echo .js-CommentWaitSubmitLabel { margin-left: 5px; color: #000000; }'
	+ '.js-CommentsSkin-echo .js-CommentWaitSubmitRetry { display: none; }'
	+ '.js-CommentsSkin-echo .js-CommentWaitSubmitMsg { position: relative; -moz-border-radius: 0.5em; -webkit-border-radius: 0.7em; background-color: #FFFF99; border: solid 1px #C6C677; padding: 10px; margin: 0 40px; }'
	+ '.js-CommentsSkin-echo .js-CommentWaitSubmitWrapper { background-color: #FFFFFF; position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-transition: opacity 0.5s ease-out; -moz-border-radius: 0.5em; -webkit-border-radius: 0.7em; vertical-align : middle; text-align: center; }'
	+ '.js-singleViaLinkWrapper { text-align: right; float: right; margin-right: 7px; }'
	+ '.js-singleCommentViaIcon { ' + (JSKitLib.isIE() ? "zoom: 1;": "") + ' border: 0; margin: 0.1em 0.3em 0 0.3em; width: 16px; height: 16px; float: right; }'
	+ '.js-singleViaText { ' + (JSKitLib.isIE() ? "zoom: 1;": "") + ' margin-bottom: 0.5em; white-space: nowrap; float: right; }'
	+ 'table.mceToolbar { width: auto !important; }'
	+ 'table.mceLayout td { padding: 0px !important; }'
	+ (JSKitLib.isIE() && !JSKitLib.isPreIE8() ? 'table.mceLayout a { display: none; }' : '') // hiding <a> with empty text

	, 'comments-skin-echo');

	JSKitLib.addCss(""
	+ ".js-kit-lcf-Border { border: 1px solid #BBBBBB; overflow: hidden; }"
	+ ".jskit-GoogleLikeMenuBar { width: " + (JSKitLib.isIE() ? "79" : "75") + "px; height: 26px; border-right: 1px solid #BBBBBB; font-size: 12px; line-height: 26px; cursor: pointer; text-align: right; white-space: nowrap; background: url(//cdn.js-kit.com/images/google-like-button.png);}"
	+ ".jskit-GoogleLikeMenuBarExpandMarker { float: right; line-height: 12px; height: 10px; width: 10px; margin: 9px 5px 0px 5px; }"
	+ ".jskit-GoogleLikeMenuBarText { float: right; font-weight: bold; color: #3a3a3a; }"
	+ ".jskit-Dogtag { background-color: #E2E9FF; float: left; margin: 1px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border: 1px solid #88AADD; white-space: nowrap; height: 22px; cursor: default; }"
	+ ".jskit-DogtagIcon { width: 16px; height: 16px; margin: 3px; float: left; }"
	+ ".jskit-DogtagCross { width: 10px; height: 10px; margin: 6px 5px 6px 0px; float: left; cursor: pointer; line-height: 10px; }"
	+ ".jskit-DogtagText { float: left; margin: 4px 7px 3px 2px; font-size: 11px; " + (JSKitLib.isIE() && document.compatMode == "BackCompat" ? "line-height: 22px; margin-top: 0px;" : "") + " }"
	+ ".js-nsgecko { -moz-user-select: none; }");
}

JSCC.prototype.setStreamState = function(paused, forced) {
	if (!forced && this.pause.forced) return;
	this.pause.state = paused;
	this.pause.forced = !!forced;
	this.renderPauseIndicator();
	if(!paused) {
		if(this.pause.queue.length > 0) {
			var events = this.pause.queue;
			this.pause.queue = [];
			this.renderSubscribeEvents(events);
		}
		this.renderPauseCounter();
	}
}

JSCC.prototype.renderPauseIndicator = function() {
	if(!this.pause.visible) return;
	JSKitLib.show(this.TC["jsk-HeaderPauseBox"], 'block');
	var state = this.pause.state;
	if(!this.pause.forced && !this.pause.visible) {
		this.pause.state = false;
	}
	JSKitLib.setStyle(this.TC["jsk-HeaderPauseBoxImg"], "background: url('//cdn.js-kit.com/images/control_" + (state ? "pause" : "play") + ".png') no-repeat center center");
	JSKitLib.text($JCL(state ? 'statePaused' : 'stateLive'), this.TC["jsk-HeaderPauseBoxName"], true);
	JSKitLib.preventSelect(this.TC["jsk-HeaderPauseBoxName"]);
}

JSCC.prototype.renderPauseCounter = function() {
	if(!this.pause.visible) return;
	JSKitLib.text(this.pause.queue.length == 0 ? '' : 
		'(' + this.pause.queue.length + ' ' + $JCL('itemsNew') + ')', this.TC["jsk-HeaderPauseBoxCount"], true);
	JSKitLib.preventSelect(this.TC["jsk-HeaderPauseBoxCount"]);
}

JSCC.prototype.setDefaultField = function(name,value) {
	JSKitLib.fmap.call(this, ["fieldDfl", "extraFormFields"], function(section) {
		this[section][name] = JSKitEPB.getValue(name) || value || "";
	});
}

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.div = function(id) {
	var self = this;
	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 arr = String(id).split(/[ ]+/);
		JSKitLib.map(function(el) {
			if(el.substr(0, 3) == 'js-')
				self.TC[el] = div;
		}, arr);
	}
	return div;
}

JSCC.prototype.dtComment
 = '<div class="js-singleComment">'
 + '<div class="js-singleCommentBg">'
 + '<div class="js-singleCommentAvatar"></div>'
 + '<d੩