
try { if(navigator.appVersion.match(/[34]\.[.0-9 ]+Safari/)) {
	var d = document.createElement('div');
	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 11739 2009-03-03 19:07:14Z jskit $
 */

if(!window.$JCA) {
  var $JCA = [];
  var $JCLT = {
	leaveComment: 'Dejar un comentario',
	leaveCommentAs: 'Dejar un comentario como:',
	guest: 'Invitado',
	/*existingJSKitProfile: 'Existing JS-Kit profile',
	newJSKitProfile: 'New JS-Kit profile',
	existingHaloscanProfile: 'Existing Haloscan profile',
	usingOpenID: 'Using OpenID',
	connectFacebook: 'Connect with Facebook account',
	connectYahoo: 'Connect with Yahoo account',
	login: 'Login',
	loginBtn: 'Login',
	register: 'Register',
	password: 'Password:',
	retypePassword: 'Re-type Password:',
	haloscanLogin: 'Haloscan login',
	haloscanPassword: 'Haloscan password:',
	openID: 'OpenID:',
	nameLabel: 'Your name:',*/
	nicknameLabel: 'Nombre (requerido):',
	nicknameRequired: 'El Nombre es un campo requerido',
	emailLabel: 'Enviar respuestas al correo electrónico:',
	emailNote: '(si se proporciona, el e-mail no se mostrara ni compartira)',
	ratingLabel: 'Rating:',
	commentLabel: 'Comment:',
	submit: 'Submit comment',
	save: 'Save',
	cancel: 'Cancel',
	tooShort: 'Your message is too short',
	tooLong: 'Message size should not exceed {maxCommentLength} bytes',
	junkCtl: 'Junk control',
	byVotes: 'by',
	selectedAvatar: 'Avatar seleccionado',
	uploadAvatar: 'Subir nuevo avatar:',
	removeAvatar: 'Remover Avatar',
	removeAvatarConfirm: 'Remover este avatar?',
	openidLabel: 'Your OpenID URL:',
	openidNote: '(OpenID 1.1 providers only)',
	openidLogin: 'Logged via',
	jskitAccount: 'JS-Kit as: ',
	haloscanAccount: 'Haloscan as: ',
	logout: 'logout',
	less: 'less',
	more: 'more',
	optionsU: 'Options &#x25b2;',
	optionsD: 'Options &#x25bc;',
	isJunkVote: 'Is this inappropriate junk or SPAM message?',
	editAvatarsBtnLabel: 'Click para gestionar avatar',
	deleteAvatarsBtnLabel: 'Click para eliminar avatar',
	avatarsManagementLabel: 'Gestion de Avatares:',
	noAvatarsMessage: 'Sin avatares subido. Por favor, utilice el formulario que aparece a continuaci&oacute;n para agregar avatares.',
	loading: 'Cargando ...',
	submitPM: 'Leave private message',
	welcomeToComments: 'Welcome to JS-Kit Comments &mdash; we\'re very happy to see you!',
	adminNote: 'Administration Note - JS-Kit Comments widget',
	openWelcome: 'Open Administration Panel',
	closeWelcome: 'Close Administration Panel',
	contactSupport: 'Contact our support team',
	editProfile: 'Edit your public profile',
	readFAQ: 'Read our FAQ',
	customizeLook: 'Customize the look and feel',
	adminDashboard: 'Admin Dashboard',
	followTwitter: 'Follow us on Twitter',
	checkWidgets: 'Check out our other widgets',
	requireAuth: 'This site requires registration before you can leave a comment. Select an authentication option under the "Leave a comment as" menu',
	deleteImage: 'Eliminar imagen',
	editImage: 'Editar descripion',
	bigImage: 'La imagen que trata subir es muy grande.',
	uploadImage: 'Subir nueva imagen (hasta 10 MB):',
	addPicText: 'A&ntilde;adir imagen',
	picTitle: 'PICTURES',
	checkWidgets: 'Check out our other widgets',
	commentMoveNotice: "Page reload will cause your comment to move according to your sorting and ordering preferences.",
	shareYahoo: "Share via "
  };
  var $JCL = window.JSCC_Translate || function(t, tmpl) {
	var text = (window.$JCLTL ? $JCLTL[t] : false) || $JCLT[t] || t;
	if(tmpl) JSKitLib.fmap(tmpl,
		function(v,k){text=text.replace(new RegExp('{'+k+'}','g'),v);});
	return text;
  }
}


if(!window.JSKitAPI) JSKitAPI = {};
JSKitAPI.allowed_event_names = { "comment-submit": true };
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.deRegisterEventCallback(token);
}
JSKitAPI.publish = function(kit_event) {
	var base = { 'this': this, returns: [] };
	JSKW$Events.syncBroadcast("STABLE-API-" + kit_event, base, arguments);
	return base.returns;
}
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;
}



function JSKitAvatarsManagement(config) {
        for (var i in config) { this[i] = config[i]; }

        this.chosenAvatar = this.getChosenAvatarFromList(config.avatars);
        this.controlButton = { width : "30px", height : "30px", imgLocation : this.uriDomain + "/images/" };
        this.anonymousAvatar = { name : "gxpA99f0jKlohF_DgthroT.png", width : "96px", height : "96px" };
}

JSKitAvatarsManagement.prototype.bindServerRequestFunction = function(serverRequest) {
        this.serverRequest = serverRequest;
}

JSKitAvatarsManagement.prototype.refreshAvatars = function() {
	this.serverRequest('s-data.js', {'avt': 'true', 'jx': this.widgetIndex, 'rnd': Math.random()});
}

JSKitAvatarsManagement.prototype.changeAvatarsListStatus = function() {
        var avatarsListStyle = this.avatarsListArea.style;
        avatarsListStyle.display = (avatarsListStyle.display == 'none') ? 'block' : 'none';
}

JSKitAvatarsManagement.prototype.removeAvatar = function(avatarName) {

        this.removeAvatarFromServer(avatarName);
        var index = this.getAvatarByName(avatarName, true);
        if (index != null) {
                this.avatars.splice(index, 1);
        }
}

JSKitAvatarsManagement.prototype.replaceAvatars = function(avatars) {

        var self = this;
        var area = this.avatarsListContainer;

        this.avatars = avatars;

        var onmousemove = function(avatar, outer, sel, rem) {
                rem.style.display = '';
                sel.style.display = 'none';
        };
        var onmouseout = function(avatar, outer, sel, rem) {
                rem.style.display = 'none';
                if(self.chosenAvatarOuter && self.chosenAvatarOuter[1] == outer)
                        sel.style.display = '';
        };
        var onmousedown = function(avatar, outer, sel, rem) {
                if (confirm(self.getLangLabelText('removeAvatarConfirm'))) {
                        outer.parentNode.removeChild(outer);

                        /* check whether current avatar was deleted */
                        if (self.chosenAvatarOuter && self.chosenAvatarOuter[0].name == avatar.name) {
                                self.updateCurrentAvatar("unselect");
                        }
                        self.removeAvatar(avatar.name);

                        if (self.avatars.length == 0) self.showNoAvatarsMessage();
                }
        };
       var outeronmousedown = function(avatar, outer, sel, rem, noUpdateCall) {
                if(self.chosenAvatarOuter) {
                        JSKitLib.removeClass(self.chosenAvatarOuter[1], 'js-showBorder');
                        JSKitLib.addClass(self.chosenAvatarOuter[1], 'js-hideBorder');
                        self.chosenAvatarOuter[2].style.display = 'none';
                        self.chosenAvatarOuter[3].style.display = 'none';
                        self.noAvatarSelected = true;

                        if (!noUpdateCall) self.updateCurrentAvatar("unselect");
                }
                if(self.chosenAvatarOuter && self.chosenAvatarOuter[1] == outer) {

                        self.chosenAvatarOuter = null;

                        if (!noUpdateCall) self.updateCurrentAvatar("unselect");

                } else {

                        JSKitLib.removeClass(outer, 'js-hideBorder');
                        JSKitLib.addClass(outer, 'js-showBorder');

                        self.chosenAvatarOuter = [avatar, outer, sel, rem];

                        sel.style.display = '';
                        rem.style.display = 'none';

                        self.noAvatarSelected = false;

                        if (!noUpdateCall) self.updateCurrentAvatar("select");

                }
                if (noUpdateCall) {

                        self.chosenAvatar = avatar;
                        self.chosenAvatar.chosen = true;

                        self.updateCurrentAvatar("select");

                }
                return 0;
        };
        var settext = function(div, label) {
                while(div.hasChildNodes()) div.removeChild(div.firstChild);
                div.appendChild(document.createTextNode(self.getLangLabelText(label)));
        };

        function base() {
                this.cr = function(tag) { return document.createElement(tag); }
        }
        var s = new base();

        if (!this.avatarsListArea.sectionLabel) {
                var label = document.createTextNode(self.getLangLabelText('avatarsManagementLabel'));
                this.avatarsListArea.sectionLabel = label;
                this.avatarsListArea.insertBefore(label, this.avatarsListArea.firstChild);
        }

        if(self.oldAvatars && self.oldAvatars.length
        && (self.oldAvatars.length + 1) == avatars.length) {
                var a1 = self.oldAvatars.pop();
                var a2 = avatars[avatars.length-2];

                if(a1.name === a2.name) {
                        var a = JSKitLib.mkAvatar(s, avatars[avatars.length-1], self.uriAvatar, onmousemove, onmouseout, onmousedown, outeronmousedown, settext);
                        area.insertBefore(a, area.firstChild);
                        self.oldAvatars = avatars;

                        return;
                }
        }
        self.oldAvatars = avatars;
	JSKitLib.removeChildren(area);
        for (var i = avatars.length - 1; i >= 0; i--) {

                if (self.noAvatarSelected) avatars[i].chosen = false;
                area.appendChild(JSKitLib.mkAvatar(s, avatars[i], self.uriAvatar, onmousemove, onmouseout, onmousedown, outeronmousedown, settext));

        }
        if (self.getChosenAvatarFromList(avatars) == null) self.updateCurrentAvatar("unselect");

        if (avatars.length == 0) this.showNoAvatarsMessage();

}

JSKitAvatarsManagement.prototype.showNoAvatarsMessage = function() {
        this.avatarsListContainer.innerHTML = "&nbsp;&nbsp; <small><i>" + this.getLangLabelText('noAvatarsMessage') + "</i></small>";
}

JSKitAvatarsManagement.prototype.getChosenAvatarFromList = function(avatars) {
    for (var i=0; i<avatars.length; i++) {
        if (avatars[i].chosen == true) return avatars[i];
    }
    return null;
}

JSKitAvatarsManagement.prototype.getAvatarByName = function(name, onlyIndex) {

        var avatars = this.avatars;
        for (var i=0; i<avatars.length; i++) {

                if (avatars[i].name == name) return (onlyIndex) ? i : avatars[i];

        }
        return null;
}

JSKitAvatarsManagement.prototype.avatarURL = function(name) {
	if(/^http:\/\//.test(name)) return name;
	else return this.uriAvatar + name;
}

JSKitAvatarsManagement.prototype.updateCurrentAvatar = function(type) {

        var avatarName = (type == "unselect") ? this.anonymousAvatar.name : this.chosenAvatarOuter[0].name;
        this.chosenAvatar = this.getAvatarByName(avatarName);

        if (this.avatarArea) {
                this.avatarArea.style.background = "url('"+this.avatarURL(avatarName)+"') no-repeat center center";
        }
}

JSKitAvatarsManagement.prototype.buildAvatarArea = function() {

    var avatarArea = this.avatarArea;
    if (!avatarArea) return false;

    var self = this;

    var onMouseOver = function(e) {
            this.editButton.style.display = "inline";
            if (self.chosenAvatar) this.deleteButton.style.display = "inline";
    }
    var onMouseOut = function(e) {
            this.editButton.style.display = this.deleteButton.style.display = "none";
    }
    var onEditButtonClick = function() {
            self.changeAvatarsListStatus();
    }
    var onDeleteButtonClick = function() {

            if (confirm(self.getLangLabelText('removeAvatarConfirm'))) {
                   var outer = self.chosenAvatarOuter[1];
                   outer.parentNode.removeChild(outer);

                   self.removeAvatar(self.chosenAvatar.name);

                   if (self.avatars.length == 0) self.showNoAvatarsMessage();

                   self.updateCurrentAvatar("unselect");
           }
    }

    var avatarName = (this.chosenAvatar) ? this.chosenAvatar.name : this.anonymousAvatar.name;

    JSKitLib.setStyle(avatarArea, "border:1px solid #c0c0c0; width:100px; height:100px; background:url('" + this.avatarURL(avatarName) + "') no-repeat center center;");

    var editButton   = this.createAvatarControlButton("edit",   {top: 60, left: 15}, onEditButtonClick);
    var deleteButton = this.createAvatarControlButton("delete", {top: 60, left: 55}, onDeleteButtonClick);

    /* Appending buttons to the avatar area */
    avatarArea.appendChild(editButton);
    avatarArea.appendChild(deleteButton);

    /* Adding links for buttons to the container for easy accessing */
    avatarArea.editButton   = editButton;
    avatarArea.deleteButton = deleteButton;

    avatarArea.onmouseover = onMouseOver;
    avatarArea.onmouseout  = onMouseOut;
}

JSKitAvatarsManagement.prototype.createAvatarControlButton = function(type, position, onButtonClick) {

    var button = document.createElement("DIV");
    JSKitLib.setStyle(button, "display:none; background:transparent; position: absolute; padding:0; margin:0; "
                            + "width:" + this.controlButton.width + "; height:" + this.controlButton.height + "; "
                            + "top:" + position.top + "px; left:" + position.left + "px;");

    button.onmouseover = function(e) { this.style.cursor = "pointer"; }
    button.onclick = onButtonClick;
    button.title = this.getLangLabelText(type + "AvatarsBtnLabel");

    var avatarUrl = this.controlButton.imgLocation + "avatar-" + type + ".png";

    JSKitLib.addPNG(button, avatarUrl);

    return button;

}

JSKitAvatarsManagement.prototype.buildAvatarsListArea = function(baseClass) {

        var self = this;
        var adiv = self.avatarsListArea;
	if (!adiv) return false;

        if(!adiv._uploadform) {

                  var aarea = document.createElement('div');

                  /* saving reference to the avatars list div */
                  self.avatarsListContainer = aarea;

                  adiv.appendChild(aarea);

                  var frm = document.createElement('form');
                  JSKitLib.setStyle(frm, "clear: both;");
                  JSKitLib.addClass(frm, "js-uploadAvatarForm");
                  frm.method = 'post';
                  frm.encoding = 'multipart/form-data';
                  frm.action = self.uriAvatar + 'add';

                  var lbl = document.createElement('div');
                  lbl.style.paddingTop = "5px";
                  var lblChange = function(mode) {
                        while(lbl.hasChildNodes())
                               lbl.removeChild(lbl.firstChild);
                               lbl.appendChild(document.createTextNode(
                                        mode ? self.getLangLabelText("loading")
                                             : self.getLangLabelText('uploadAvatar')));
                   }

                   var lockControls = function(disabled) {
                        for (var i in self.controls) {
				 if (self.controls[i].btnLocked) return;
                                self.controls[i].disabled = (disabled == true) ? "true" : "";
                        }
                   }

                   lblChange(0);
                   frm.appendChild(lbl);

                   var upf = document.createElement('input');
                   upf.type = 'file';
                   upf.name = 'image';
		    self.uploadControl = upf;
                   self.controls.unshift(upf);
                   var f = function() { 
			   baseClass.onCancel();
			   if (!self.noAvatarsRefresh) self.refreshAvatars();
			   self.noAvatarsRefresh = false;
		   }
		   var createIFrame = function(target) {
			var tgt = 'js-ifrm-' + self.widgetIndex + Math.random();
			var d = document.createElement("DIV");
			d.innerHTML = '<iframe id="' + tgt + '" name="' + tgt + '" src="about:blank" width=0 height=0 style="border: none"></iframe>';
			target.appendChild(d);
			var ifr = d.firstChild;
			ifr.onreadystatechange = ifr.onload = function(){
				if(ifr.readyState && ifr.readyState != 'loaded' && ifr.readyState != 'complete') return;
				f();
			};
			return tgt;
		   }

                   upf.onchange = function() {
                           lblChange(1);
			   if(!frm.target) frm.target = createIFrame(adiv);
                           frm.submit();
                           lockControls(true);
                   }
                   frm.appendChild(upf);
                   adiv.appendChild(frm);
                   baseClass.onCancel = function() {
                           lockControls(false);
                           lblChange(0);
                           frm.reset();
                   }
                   adiv._uploadform = frm;
        }

        adiv.style.display = 'none';

}



if(!window.JSKitEPB){
	var JSKitEPB = new JSKitEPBLib();
}

function JSKitEPBLib() {
	this.JSK$EPB = window.JSK$EPB ? window.JSK$EPB : {};
}

JSKitEPBLib.prototype.isAdmin = function(Path) {
	var arrIndexOf = function(arr, Val) {
		var ValLC = Val.toLowerCase();
		for(var i = arr.length - 1; i >= 0; i--) {
			var v = arr[i];
			if(typeof(v) == "string")
				v = v.toLowerCase();
			if(v == ValLC) return i;
		}
		return -1;
	}
	return this.JSK$EPB.mac && this.JSK$EPB.profile && this.JSK$EPB.profile.owner && arrIndexOf(this.JSK$EPB.profile.owner,Path) != -1 ? 1 : 0;
}

JSKitEPBLib.prototype.getValue = function(ValueName) {
	return !this.JSK$EPB.profile || !this.JSK$EPB.mac || this.JSK$EPB.profile[ValueName] == undefined ? undefined : this.JSK$EPB.profile[ValueName];
}

JSKitEPBLib.prototype.getElement = function(Pref,El,ArrKey) {
	var rslt = [];
	if(typeof(El) == 'object') {
		if(El instanceof Array) {
			if(ArrKey) {
				var len = El.length;
				for(var i=0; i<len; i++)
					rslt = rslt.concat(this.getElement(Pref,El[i],ArrKey));
			}
		} else {
			for(var i in El)
				rslt = rslt.concat(this.getElement(Pref,El[i],i));
		}
	} else {
		if(ArrKey) {
			rslt.push({'Name': Pref+ArrKey, 'Value': El});
		}
	}
	return rslt;
}

JSKitEPBLib.prototype.getAsObj = function() {
	var rslt = [];
	var pref = "epb-";
	var epb = this.JSK$EPB;
	if(!epb.profile || !epb.mac) return rslt;
	rslt.push({'Name': pref+"mac",'Value': epb.mac});
	return rslt.concat(this.getElement(pref,epb.profile));
}

JSKitEPBLib.prototype.getURIEncodedSerialize = function() {
	var ser = this.getAsObj();
	var ar = [];
	for(var i=0; i<ser.length; i++) {
		ar.push(ser[i].Name + "=" + encodeURIComponent(ser[i].Value));
	}
	return ar.join("&");
}

JSKitEPBLib.prototype.getAsHash = function(obj) {
	var ser = this.getAsObj();
	JSKitLib.fmap(ser, function(v) { obj[v.Name] = v.Value; });
	return obj;
}



if(!window.JSKitLib) JSKitLib = {vars:{}};



JSKitLib.cr = function(arg) {
	if(!arg) return document.createElement("div");
	arg.t = arg.t || "div";
	var div = document.createElement(arg.t);
	div.className = arg.className;
	JSKitLib.fmap(arg.style, function(value, key) { div.style[key] = value; });
	return div;
}

JSKitLib.deleteProperty = function(obj, prop) {
	if (typeof obj[prop] == 'function') {
		obj[prop] = null;
	} else {
		try {
			delete obj[prop];
		} catch (e) {
			obj[prop] = null;
		}
	}
}

JSKitLib.trim = function(str) {
	if (typeof(str) != "string") return "";
	var str = str.replace(/^\s\s*/, ''), ws = /\s/, i = str.length;
	while (ws.test(str.charAt(--i)));
	return str.slice(0, i + 1);
}

JSKitLib.encodeJSONLiteral = function(string) {
	var replacements = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'};
	return string.replace(/[\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff\\]/g, 
		function (a) { return (replacements.hasOwnProperty(a)) ? replacements[a] : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); });
}

JSKitLib.Object2JSON = function(obj) {
	var out;
	switch (typeof(obj)) {
		case "number"  : out = obj; break; 
		case "string"  : out = '"' + JSKitLib.encodeJSONLiteral(obj) + '"'; break;	
		case "boolean" : out = '"' + obj.toString() + '"'; break;
		default :
			if (obj instanceof Array) {
				var container = JSKitLib.fmap(obj, function(element) { return JSKitLib.Object2JSON(element); });
				out = '[' + container.join(",") + ']';
			} else if(obj instanceof Object) {
				var source = obj.exportProperties || obj;
				var container = JSKitLib.fmap(source, function(value, property) {
					if (source instanceof Array) { property = value; value = obj[property]; } 
					return '"' + property + '":' + JSKitLib.Object2JSON(value);
				});
	      			out = '{' + container.join(",") + '}';
			}
	}
	return out;
}

JSKitLib.dataTransport = function(action, data, config) {
	if (!data) data = {};
	if (!config.pathOverride) config.pathOverride = "";
	if (!config.target) config.target = document.body;
	if (typeof(config.ajax) == "undefined") config.ajax = true; 

	// append "ref" parameter	
	if (config.ref) data.ref = config.ref;

	// transport functions
	var serverGET = function(actionURL, dataGET) {
		var script = document.createElement("script");
		script.setAttribute("charset", "utf-8");
		script.setAttribute("src",  actionURL + "?" + dataGET);
		config.target.appendChild(script);
		return false;
	}

	var serverPOST = function(actionURL, dataPOST) {

		var getPOSTForm = function(doc, action, postdata) {
			var frm = doc.createElement('FORM');
			frm.method  = 'POST';
			frm.enctype = "application/x-www-form-urlencoded";
			frm.action  = action;
			JSKitLib.fmap(postdata, function(value, key) {
				var frmel = doc.createElement("INPUT");
				frmel.type = "hidden";
				frmel.name = key;
				frmel.value = value;
				frm.appendChild(frmel);
			});
			doc.body.appendChild(frm);
			return frm;
		}

		if (config.ajax) {

			var d = document.createElement("DIV");
			var tgt = 'jsk-ifrmpost-' + Math.random();

			d.innerHTML = '<iframe id="' + tgt + '" name="' + tgt + '" src="about:blank" width=0 height=0 style="border: none"></iframe>';
			document.body.appendChild(d);
			var ifrpost = 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.contentDocument : FEl.document;
			}

			ifrpost.onreadystatechange = function() {
				if((ifrpost.readyState) && (ifrpost.readyState != 'complete')){
					return;
				}
				var iDOC = getFrameDoc(tgt);
				var td = iDOC.createElement('div');
				var tgtch = 'jsk-ifrmpostch-' + Math.random();
				td.innerHTML = '<iframe id="' + tgtch + '" name="' + tgtch + '" src="" width=0 height=0 style="border: none"></iframe>';
				iDOC.body.appendChild(td);
				var pfr = td.firstChild;
				pfr.onreadystatechange = function() {
					if((pfr.readyState) && (pfr.readyState != 'complete')){
						return;
					}
					var iDOC = getFrameDoc(tgtch, tgt);
					var frm  = getPOSTForm(iDOC, actionURL, dataPOST);

					var getFrameLocation = function(FrameName, Parent) {
						var fr = getFrameDoc(FrameName, Parent);
						return decodeURIComponent(fr.location.href);
					};

					var processpfronload = function () {
						if((pfr.readyState) && (pfr.readyState != 'complete')){
							return;
						}
						var js;
						if(JSKitLib.isIE()){
							var curfr=getFrame(tgt);
							js=decodeURIComponent(curfr.document.title);
						} else if(navigator.userAgent.indexOf("Opera") != -1){
							js=decodeURIComponent(this.location.hash).substr(1);
						} else if(navigator.userAgent.indexOf("Safari") != -1){
							js=decodeURIComponent(frames[tgt].frames[tgtch].location.hash).substr(1);
						} else {
							js=getFrameLocation(tgt).substr(12);
						}
						if(js){
							var sc  = document.createElement("SCRIPT");
							sc.text = js;
							config.target.appendChild(sc);
						}
					};
					pfr.onreadystatechange = processpfronload;
					pfr.onload = processpfronload;
					frm.submit();
				};
				pfr.onload = pfr.onreadystatechange;
				if(!JSKitLib.isIE()){
					pfr.onload();
				}
			};
			ifrpost.onload = ifrpost.onreadystatechange;
			if(!JSKitLib.isIE()){
				ifrpost.onload();
			}

		} else {
			var frm = getPOSTForm(document, actionURL, dataPOST);
			frm.submit();
		}
	}

	// prepare data
	var actionURL = config.uri + action + config.pathOverride;

	// analyze request length -> select transport method
	var dataGET = JSKitLib.fmap(data, function(value, key) { 
		return key + "=" + encodeURIComponent(value); 
	}).join("&");

	var transportProtocol = (actionURL.length + dataGET.length > 1700) ? "POST" : "GET";

	switch (transportProtocol) {
		case "GET"  : serverGET(actionURL, dataGET); break;
		case "POST" : serverPOST(actionURL, data); break;
	}

	return false;
}



JSKitLib.isPreIE7 = function() {
	if (document.body.filters && parseInt(navigator.appVersion.split("MSIE") [1]) < 7)
		return true;
}

JSKitLib.isIE = function() {
	if (document.body.filters && navigator.appVersion.match(/MSIE/))
		return true;
}

JSKitLib.getBrowser = function() {
	if (JSKitLib.vars.browser) return JSKitLib.vars.browser;
	if (document.body.filters && navigator.appVersion.match(/MSIE/)) {
			JSKitLib.vars.browser = "IE";
	} else if ((navigator.appCodeName.toLowerCase()=="mozilla") 
		&& (navigator.appName.toLowerCase()=="netscape") 
		&& (navigator.product.toLowerCase()=="gecko") 
	) {
		if (navigator.userAgent.toLowerCase().indexOf("safari")!=-1) {
			JSKitLib.vars.browser = "safari";
		} else if (navigator.userAgent.toLowerCase().indexOf("firefox")!=-1) {
			JSKitLib.vars.browser = "gecko";
		}
	} else if (navigator.product && navigator.product.toLowerCase()=="gecko") {
		JSKitLib.vars.browser = "gecko";
	}
	return JSKitLib.vars.browser;
}

JSKitLib.isFF3 = function() {
	return (navigator.userAgent.indexOf("Firefox/3") != -1);
}

JSKitLib.isGChrome = function() {
	return (navigator.userAgent.toLowerCase().indexOf('chrome') != -1);
}

JSKitLib.isSafari = function() {
	if (navigator.appVersion.match(/Safari/)) {
		return true;
	}
}

JSKitLib.isOpera = function() {
	if (navigator.appName.match(/Opera/)) {
		return true;
	}
}



JSKitLib.addEventHandler = function(obj, eventNames, eventHandler, capture) {
	JSKitLib.fmap(eventNames, function(e) {
		if (obj.addEventListener) {
			obj.addEventListener(e, eventHandler, !!capture);
		} else if (obj.attachEvent) {
			if (capture) {
				obj.setCapture();
				obj.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) {
				obj.detachEvent('onlosecapture', eventHandler);
				obj.releaseCapture();
			}
			obj.detachEvent('on' + e, eventHandler);
		}
	});
}

JSKitLib.stopEventPropagation = function(e) {
	if (!e) e = window.event;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
}

JSKitLib.preventDefaultEvent = function(e) {
  if (!e) e = window.event;
  e.returnValue = false;
  if (e.preventDefault) e.preventDefault();
}

JSKitLib.deferCall = function(func, onlyIE) {
	if (!JSKitLib.vars.windowOnLoadFired && (!onlyIE || (onlyIE && JSKitLib.isIE() && !window.$JSKitNoDeferCallIfIE))) {
		JSKitLib.addEventHandler(window, ['load'], func);
	} else {
		func();
	}
}

JSKitLib.addHandlers = function(obj, moveHandler, upHandler, capture) {
	JSKitLib.addEventHandler(obj, ['mousemove'], moveHandler, capture);
	JSKitLib.addEventHandler(obj, ['mouseup'], upHandler, capture);
}

JSKitLib.removeHandlers = function(obj, moveHandler, upHandler, capture) {
	JSKitLib.removeEventHandler(obj, ['mousemove'], moveHandler, capture);
	JSKitLib.removeEventHandler(obj, ['mouseup'], upHandler, capture);
}

JSKitLib.notDraggable = function(element) {
	element.onselectstart = function(ev) { JSKitLib.stopEventPropagation(ev); return true; }
	element.onmousedown = JSKitLib.stopEventPropagation;
	return element;
}

JSKitLib.getMousePosition = function(e) {
	if (!e) var e = window.event;
	if (e.clientX || e.clientY) {
		return {x:e.clientX, y:e.clientY};
	} else {
		return {x:e.pageX, y:e.pageY};
	}
}

JSKitLib.preventSelect = function(element, exceptions) {
	var browser = JSKitLib.getBrowser();
	var prevent = function() {
		if (browser == 'IE' || browser == 'safari') {
			element.onselectstart = function() { return false; }
		} else if (browser == 'gecko') {
			JSKitLib.addClass(element, 'js-nsgecko');
		}
	}
	if (typeof exceptions == 'object') {
		var include = exceptions.include || [];
		var exclude = exceptions.exclude || [];
		// Do not handle for certain browsers
		if (exclude.length) {
			for (var i=0; i < exclude.length; i++) {
				if (exclude[i] != browser) {
					prevent();
				}
			}
		}
		// Handle for certain browsers
		if (include.length) {
			for (var i=0; i < include.length; i++) {
				if (include[i] == browser) {
					prevent();
				}
			}
		}
	} else {
		prevent();
	}
}



JSKitLib.addCss = function(cssCode, name, content) {
	var doc = content || document;
	if(name) {
		name = "js-" + name + "-css";
		if (doc.getElementById(name)) return;
	}
	var se = doc.createElement("style");
	se.type = "text/css";
	if(name) se.id = name;
	if (se.styleSheet) se.styleSheet.cssText = cssCode;
	else se.appendChild(doc.createTextNode(cssCode));
	var hd = doc.getElementsByTagName("head");
	if(hd && hd[0]) hd[0].appendChild(se);
	else doc.write('<style>'+cssCode+'</style>');
}

JSKitLib.getElementsByClass = function(node, searchClass, tag) {
	var classElements = [];
	node = node || document;
	tag = tag || '*';
	var tagElements = node.getElementsByTagName(tag);
	var regex = new RegExp("(^|\\s)" + searchClass + "(\\s|$)");
	for (var i=0, j=0; i < tagElements.length; i++) {
		if (regex.test(tagElements[i].className)) {
			classElements[j] = tagElements[i];
			j++;
		}
	}
	return classElements;
};

JSKitLib.mapClass2Object = function(ctl, e) {
        if(e.className) {
                var arr = String(e.className).split(/[ ]+/);
                JSKitLib.map(function(el) { ctl[el] = e }, arr);
        }
        if(e.name) ctl[e.name] = e;
        try {
                var self = this;
                JSKitLib.map(function(child) {
                        JSKitLib.mapClass2Object(ctl, child);
                }, e.childNodes);
        } catch(e){}
        return ctl;
}

JSKitLib.hasClass = function(element, className) {
	return element.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
}

JSKitLib.addClass = function(element, className) {
	if (!JSKitLib.hasClass(element, className)) {
		element.className += ' ' + className;
	}
}

JSKitLib.removeClass = function(element, className) {
	if (JSKitLib.hasClass(element, className)) {
		var regex = new RegExp('(\\s|^)' + className + '(\\s|$)');
		element.className = element.className.replace(regex, ' ');
	}
}



JSKitLib.removeChildren = function(element) {
	while(element && element.hasChildNodes())
		element.removeChild(element.firstChild);
}

JSKitLib.visible = function(element) {
	return element.style.display != 'none';
}

JSKitLib.show = function(element) {
	element.style.display = '';
}

JSKitLib.hide = function(element) {
	element.style.display = 'none';
}

JSKitLib.toggle = function(element) {
	(element.style.display == 'none') ? JSKitLib.show(element) :  JSKitLib.hide(element);
}

JSKitLib.getStyle = function(element) {
	if (typeof element.style.cssText != "undefined") {
		return element.style.cssText;
	} else {
		return element.getAttribute("style");
	}
}

JSKitLib.setStyle = function(element, style) {
	if (typeof element.style.cssText != "undefined") {
		element.style.cssText = style;
	} else {
		element.setAttribute("style", style);
	}
}

JSKitLib.addStyle = function(element, style) {
	var oldStyle = JSKitLib.getStyle(element);
	JSKitLib.setStyle(element, oldStyle + '; ' + style); // IE needs ;
}

JSKitLib.findPos = function(obj) {
	var origObj = obj;
	var curleft = curtop = curright = curbottom = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		}
	}
	curright = curleft + origObj.offsetWidth;
	curbottom = curtop + origObj.offsetHeight;
	return [curleft,curtop,curright,curbottom];
}

JSKitLib.getJSKitBodyElement = function() {
	var be = document.getElementById('js-kit-body-element');
	if (!be) {
		be = document.createElement('div');
		be.id = "js-kit-body-element";
		document.body.appendChild(be);
	}
	return be;
}

JSKitLib.isChildNodeOf = function(parent, child) {
	if (parent === child) 
		return false
	while (child && child !== parent) {
		child = child.parentNode;
	}
	return child === parent;
}

JSKitLib.addChild = function(to, what) {
        if (typeof(to) != 'object')
                return;
        if(arguments.length == 3 && arguments[2])
                to.insertBefore(what, to.firstChild);
        else
                to.appendChild(what);
}

JSKitLib.setOpacity = function(div, val) {
	if(document.body.filters) {
		if(val == 1) div.style.filter = '';
		else div.style.filter = 'alpha(opacity: ' + Math.round(val * 100) + ')';
	} else {
		div.style.opacity = val;
	}
}



JSKitLib.addPNG = function(node, imageURL) {
	if (JSKitLib.isIE()) {
		var cp = $JSKitGlobal.cachedPngs;
		for(var j=0; j<cp.length; j++) {
			k = 0;
			while(k<length(cp[j].nodes)) {
				if(cp[j].nodes[k]==node) {
					cp[j].nodes.splice(k, 1);
				} else {
					k++;
				}
			}
		}
		if(cp[imageURL]) {
			if(cp[imageURL].loaded) {
				node.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageURL + "', sizingMethod='crop')"
			} else {
				cp[imageURL].nodes.push(node);
			}
		} else {
			cp[imageURL] = {nodes:[node]};
			var tPng = document.createElement("IMG");
			tPng.style.display = "none";
			tPng.onload = function() {
				cp[imageURL].loaded = true;
				var n = cp[imageURL].nodes;
				for(var i=0; i<n.length; i++) {
					n[i].runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageURL + "', sizingMethod='crop')";
				}
				cp[imageURL].nodes = [];
			};
			node.appendChild(tPng);
			tPng.src = imageURL;
		}
	} else {
		node.style.backgroundImage = 'url(' + imageURL + ')';
		node.style.backgroundRepeat = 'no-repeat';        
	}
	return node;
}

JSKitLib.preloadImg = function(imgURL) { 
	if (!JSKitLib.preloadImgList) JSKitLib.preloadImgList = {};
	if (!JSKitLib.preloadImgList[imgURL]) {
		(new Image()).src = imgURL; 
		JSKitLib.preloadImgList[imgURL] = true;
	}
};

JSKitLib.pngBar = function(color, div, fixed) {
	var str;
	var url = "'//js-kit.com/images/bars/bar-" + color + ".png'";
	if(document.body.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.mkAvatar = function(s, avatar, uriAvatar, onmousemove, onmouseout, onmousedown, outeronmousedown, settext) {
	var outer = s.cr('div');
	JSKitLib.setStyle(outer, "float: left;");
	outer.style.display = "inline-block";
	outer.onselectstart = function() {return false;}
	outer.style.margin = "2px";
	JSKitLib.addClass(outer, "js-hideBorder");
	var WH = {'width': avatar.width,'height': avatar.height,'name':avatar.name};
	outer.style.width = "118px";
	outer.style.align = "center";
	var div = s.cr('div');
	div.style.margin = "2px";
	div.style.width = "114px";
	div.style.height = "114px";
	div.style.backgroundPosition = 'top center';
	var img = s.cr('div');
	img.style.width = WH['width'] + 'px';
	img.style.height = WH['height'] + 'px';
	img.style.left=((114-WH['width'])/2)+'px';
	img.style.position = "relative";
	JSKitLib.addPNG(img, JSKitAvatarsManagement.prototype.avatarURL.call({uriAvatar: uriAvatar}, WH['name']));
	var sub = s.cr('div');
	sub.style.padding = "2px 5px 0px 5px";
	sub.style.fontFamily = "Helvetica, Verdana";
	sub.style.fontSize = "8pt";
	sub.style.height = "14px";
	var sel = s.cr('div'); settext(sel, 'selectedAvatar');
	sel.style.display = 'none';
	sel.style.textAlign = 'center';
	var rem = s.cr('div'); settext(rem, 'removeAvatar');
	rem.style.display = 'none';
	rem.style.textDecoration = 'underline';
	rem.style.textAlign = 'center';
	rem.style.cursor = 'pointer';
	sub.onmouseover = function() {
		return onmousemove(avatar, outer, sel, rem);
	}
	sub.onmouseout = function() {
		return onmouseout(avatar, outer, sel, rem);
	}
	rem.onmousedown = function(e) {
		JSKitLib.stopEventPropagation(e || window.event);
		return onmousedown(avatar, outer, sel, rem);
	}
	sub.appendChild(rem);
	sub.appendChild(sel);
	div.appendChild(img);
	div.appendChild(sub);
	outer.appendChild(div);
	outer.onmousedown = function() {
		return outeronmousedown(avatar, outer, sel, rem);
	}
	if(avatar.chosen) outeronmousedown(avatar, outer, sel, rem, true);
	return outer;
}



JSKitLib.getOuterHTML = function(node) {
	var clone = node.cloneNode(true);
	var parent = document.createElement('div');
	parent.appendChild(clone);
	var ihtml = parent.innerHTML;

    // ff converts sp characters inside of href to hex ascii
	var ihtmlHref = ihtml.match(/href\s*=\s*"[^"]*(%7B|%7D)[^"]*"/g) || [];
	for (var i=0; i< ihtmlHref.length; i++) {
		var a = ihtmlHref[i];
		var b = a.replace(/%7B/g, '{');
		b = b.replace(/%7D/g, '}');
		ihtml = ihtml.replace(a, b);
	}
	return ihtml;
};

JSKitLib.html = function() {
        var div = document.createElement("div");
        for(var text = '', i = 0; i < arguments.length; i++)
                text += arguments[i];
        div.innerHTML = text;
        var ch = div.firstChild;
        div = null;
        return ch;
}

JSKitLib.htmlQuote = function (newValue, param) {
	newValue = newValue.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")
	param = param || {};
	if(!param.title)
		newValue = newValue.replace(/ /,"&nbsp;");
	if(param.attribute)
		newValue = newValue.replace(/"/g,"&quot;");
	return newValue;
}

JSKitLib.htmlUnquote = function (newValue) {
	return newValue.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&");
}

JSKitLib.addJS = function(src,content) {
	var sId = "js-kit-script-"+src.replace(/[\/.]/g, '');
	content.jsk$scriptId = sId;
	if(document.getElementById(sId)) {
		return;
	}
	var s = document.createElement('script');
	s.id = sId;
	s.type ='text/javascript';
	s.src = src;
	content.appendChild(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.map = function(f, arr) {
	if(arr) for(var i = 0; i < arr.length; i++) f(arr[i], i, arr);
	return arr;
}

JSKitLib.filter = function(f, arr) {
	var newArr = [];
	if(arr)
		for(var i = 0; i < arr.length; i++)
			if(f(arr[i], i, arr))
				newArr.push(arr[i]);
	return newArr;
}

JSKitLib.fmap = function(o,f) {
	var r, a = [], l = o.length;
	if(l > 0 || l === 0)
		for(var i = 0; i < l; i++) {
			r = f.call(this,o[i],i,arguments);
			if(r !== undefined) a.push(r);
		}
	else
		for(var i in o)
			if(o.hasOwnProperty(i)) {
				r = f.call(this,o[i],i,arguments);
				if(r !== undefined) a.push(r);
			}
	return a;
}

JSKitLib.foldl = function(acc,o,f) {
	var r, l = o.length;
	if(l > 0 || l === 0)
		for(var i = 0; i < l; i++) {
			r = f.call(this,o[i],acc,i);
			if(r != undefined) acc = r;
		}
	else
		for(var i in o)
			if(o.hasOwnProperty(i)) {
				r = f.call(this,o[i],acc,i);
				if(r != undefined) acc = r;
			}
	return acc;
}

JSKitLib.intersperse = function(f) {
	return JSKitLib.foldl([], this, function(e, acc, i) {
		if(acc.length) acc.push(f);
		acc.push(e);
	});
}



if (typeof JSKitLib.vars.windowOnLoadFired == 'undefined') {
        JSKitLib.vars.windowOnLoadFired = false;
        JSKitLib.addEventHandler(window, ['load'], function(){ JSKitLib.vars.windowOnLoadFired = true; });
}



var JSKitGlobal = function() {

	this._appAvailable = {};
	this._appObjects = {};  // Specific objects of an application type 
	this._appObjectActions = {}; // app.object.actions
	
	this.cachedPngs = {};

	this._isAppAvailable = function(app) {
		return (this._appAvailable[app]) ? true : false;
	}

	this.isRatingsAppAvailable = function() {
		return this._isAppAvailable('ratings');
	}

	this.isCommentsAppAvailable = function() {
		return this._isAppAvailable('comments');
	}

	this._setAppAvailable = function(app) {
		this._appAvailable[app] = true;
		/* index this app */
		this.indexAppObjects(app);
		/* execute any queued actions */
		this.executeAppObjectActions(app);
	}

	this.setRatingsAppAvailable = function() {
		this._setAppAvailable('ratings');
	}

	this.setCommentsAppAvailable = function() {
		this._setAppAvailable('comments');
	}

	this.indexAppObjects = function(app) {
		if (app == 'ratings') {
			var appArray = $JRA;
		} else if (app == 'comments') {
			var appArray = $JCA;
		} else {
			alert('Attempt to index invalid app type');
			return;
		}
		for (var i=0; i < appArray.length; i++) {
			// Check that it's not standalone
			if (appArray[i].isStandalone()) {
				continue;
			}
			var uniq = appArray[i].uniq;
			if ( ! this._appObjects[uniq] ) {
				this._appObjects[uniq] = {};
			}
			if ( ! this._appObjects[uniq][app]) {
				this._appObjects[uniq][app] = [];
			}
			this._appObjects[uniq][app].push(appArray[i]);
		}
	}

	this.executeAppObjectActions = function(app) {
		if (this._appObjectActions[app]) {
			for (var i=0; i < this._appObjectActions[app].length; i++) {
				var uniq = this._appObjectActions[app][i].uniq;
				if (this._getAppObject(app, uniq)) {
					this._appObjectActions[app][i].action();
				}
			}
		}
	}

	this._getAppObject = function(app, uniq) {
		if (this._appObjects[uniq] && this._appObjects[uniq][app]) {
			return this._appObjects[uniq][app][0];  // Return only the first
		}
		return null;
	}

	this.getCommentsAppObject = function(uniq) {
		return this._getAppObject('comments', uniq);
	}

	/* Returns a Ratings Object */
	this.getRatingsAppObject = function(uniq) {
		return this._getAppObject('ratings', uniq);
	}

	this.copyRatingsAppObject = function(uniq, node) {
		if ( ! this.isRatingsAppAvailable()) {
			return;
		}
		var oldObj = this.getRatingsAppObject(uniq);
		var newObj = oldObj.clone(node, { 'view':'user', 'commentprompt':'no', 'menu':'no'  } );
		return newObj;
	}

	this._tryAppObjectAction = function(app, uniq, action) {
		if (this._isAppAvailable(app)) {
			if (this._getAppObject(app, uniq)) {
				action();
			}
		} else {
			if ( ! this._appObjectActions[app]) {
				this._appObjectActions[app] = [];
			}
			this._appObjectActions[app].push( { 'uniq' : uniq, 'action' : action } );
		}
	}

	this.tryRatingsAppObjectAction = function(uniq, action) {
		this._tryAppObjectAction('ratings', uniq, action);
	}

	this.tryCommentsAppObjectAction = function(uniq, action) {
		this._tryAppObjectAction('comments', uniq, action);
	}
}

/* Singleton-like handler */
JSKitGlobal.getInstance = function() {
	if ( ! window.JSKitGlobalInstance) {
		JSKitGlobalInstance = new JSKitGlobal();
	}
	return JSKitGlobalInstance;
}



/* JSKitGlobal  object */
$JSKitGlobal = JSKitGlobal.getInstance();



JSKitLib.getRef = function(self, ignorePath) {
	var wl = window.location;
	return wl.protocol + '//'
		+ (self.pathOverride
			? (self.config.domain.replace(/\/.*/, '')
				+ (ignorePath ? '' : self.pathOverride))
			: (self.config.domain + wl.pathname));
}

JSKitLib.readConfig = function(wtype, target, cf) {
	var gtags = JSKitLib.parseConfigTags(document, wtype, 'span');
	var ltags = JSKitLib.parseConfigTags(target, '', 'span');
	for(var i = 3; i < arguments.length; i++) {
		var arg = arguments[i];
		if(typeof(arg) == 'string') arg = [arg];
		var name = arg[0];
		var value = target.getAttribute(name) || ltags[name] || gtags[name];
		var wl = window.location;
		switch (name) {
			case 'path': value = JSKitLib._normPath(target, value || cf[name]); break;
			case 'permalink': value = value || cf[name] || wl.href.replace(wl.hash,''); break;
			case 'title': value = value || cf[name] || document.title; break;
			case 'domain': value = value || cf[name] || wl.host; break;
			default: value = value || cf[name];
		}
		if(arg.length > 1) {
			if(typeof(arg[1]) == 'number') {
				if(value) {
					var n = parseInt(value);
					if(isNaN(n) || n < 0) {
						if(value == "no") value = 0;
						else value = arg[1];
					} else value = n;
				} else value = arg[1];
			} else if(typeof(arg[1]) == 'object') {
				for(var j=arg[1].length; j; j--)
					if(arg[1][j-1] == value) break;
				if(!j) value = arg[1][j];
			} else {
				if(!value) value = arg[1];
			}
		}
		cf[name] = value;
	}
	return cf;
}

JSKitLib.parseConfigTags = function(target, wtype, tag) {
	var cache = document._widgets_config;
	if (wtype && cache && cache[wtype])
		return cache[wtype];
	var regp = wtype ? wtype+'?-' : '';
	var nodes = target.getElementsByTagName(tag);
	var config = {};
	for (var i = 0; i < nodes.length; i++) {
		var reg = RegExp("^js-kit-config-"+regp+"(.*)$");
		var m = reg.exec(nodes[i].className);
		if (m && m.length) {
			config[m[1].toLowerCase()] = nodes[i].innerHTML;
			nodes[i].style.display = 'none';
		}
	}
	if (wtype) {
		document._widgets_config = document._widgets_config || {};
		document._widgets_config[wtype] = config;
	}
	return config;
}

JSKitLib._normPath = function(target, path) {
	var wl = window.location;
	var uniq = String(target.getAttribute("uniq") || target.getAttribute("unique") || '');
	/* trim uniq */
	var uniq = uniq.replace(/^\s\s*/, ''), ws = /\s/, i = uniq.length;
	while (ws.test(uniq.charAt(--i)));
	uniq = uniq.slice(0, i + 1);
	/* end of trim */
	var plus = true;
	if (uniq) {
		plus = uniq.match(/^\+\/*(.*)/);
		if (plus) path = plus[1];
		else path = uniq;
	}
	if(path) {
		path = String(path);
		var ar = path.match(/^https?:\/\/[^\/]+(.*)/);
		if(ar) path = ar[1];
		else path = path.replace(/^([^\/]+)/, (plus ? wl.pathname : "") + "/$1");
		path = path.replace(/^\/+/, "/");
	} else { path=wl.pathname; }
	return path;
}



JHI2 = {};
JHI2.create = function(hint, element) {
	if (!element) {
		element = document.createElement("input");
		element.type = "text";
	}
	element.origColor = element.style.color || 'black';
	element.hint = hint;
	element.defaultRemoved = !!element.value;
	if (!element.value) {
		element.style.color = 'gray';
		element.value = element.hint;
	}
	element.onblur = function() {
		if (!this.defaultRemoved || this.value == '') {
			this.defaultRemoved = false;
			this.style.color = 'gray';
			this.value = this.hint;
		}
	}
	element.onfocus = function() {
		if (!this.defaultRemoved) {
			this.defaultRemoved = true;
			this.style.color = this.origColor;
			this.value = '';
		}
	}
	return element;
}

JHI2.remove = function(element) {
	if (!element || !element.hint) return;
	element.onfocus();
	JSKitLib.fmap(['origColor', 'hint', 'defaultRemoved', 'onblur', 'onfocus'], function(v){ JSKitLib.deleteProperty(element, v); });
}



function JSKitAuth(mode, uriDomain) {
        this.HNDL = [];
	this.mode = mode || "profile";
	this.uriDomain = uriDomain || "";
}

JSKitLib.addCss(''
 + ".jsk-Button { float: left; padding: 1px 4px; margin-left: 8px; background-color: #d8d8d8; border: solid 1px #bbbbbb; -moz-border-radius: 4px; -webkit-border-radius: 4px; font-size: " + (JSKitLib.isIE() ? "12px" : "14px") + "; -moz-user-select: none; cursor: pointer; }"
 + "dl.jsk-SectionLoginInput { position: relative; }"
 + "dt.jsk-SectionLoginInput { clear: both; font-weight: bold; width: 9em; float: left; margin-left: 1em; }"
 + "select.jsk-SectionLoginInput {}"
 + "dd.jsk-SectionLoginInput { float: left; margin-left: 0.5em; width: 15em; }"
 + "input.jsk-SectionLoginInput { width: 100%; " + (JSKitLib.isPreIE7() ? "" : (JSKitLib.isIE() ? "margin-left: -1.5em;" : "")) + (JSKitLib.isIE() ? "margin-top: -1px;" : "") + "}"
 + "input.jsk-SectionPasswordInput { display: none; }"
 + ".jsk-SectionLoginProgress { display: none; }"
 + ".jsk-SectionLoginProgressPic { display: inline; float: left; margin-right: 0.2em; margin-left: 1em; margin-top: 0.5em; width: 15px; height: 15px; background-image: url(//js-kit.com/images/progress-wg.png); }"
 + ".jsk-SectionLoginProgressLbl { display: inline; margin-top: 0.5em; float: left; }"
 + ".jsk-SectionLoginProgressFooter { clear: both; }"
 + ".jsk-SectionLoginMessage { color: #FF3030; font-size: 11px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 2px; margin-left: 2px; }"
 + ".jsk-SectionLoginMessageFull { color: #403030; font-size: 11px; font-family: Arial, Helvetica, sans-serif; margin-bottom: 2px; margin-left: 2px; }"
 + ".jsk-SectionLoginRegister { margin-top: 5em; }"
 + "dt.jsk-SectionRegisterInput { clear: both; font-weight: bold; width: 9em; float: left; margin-left: 1em; text-align: right; }"
 + ".jsk-SectionLoginInputJSKit { color: #808080; }"
 + ".jsk-SectionLoginInputOpenID { color: #808080; }"
 + ".jsk-SectionLoginLogout { font-weight: normal; font-size: 13px; }"
 + ".js-authContainer {" + (JSKitLib.isIE() ? "zoom: 1;" : ";") + "}"
 + ".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-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; ") + "}"
 + ".js-authButton { margin-top: 0.3em; }"
 + ".js-authArea {background-color: #e5e5e5; clear: both; overflow: hidden; display: none; padding: 5px; }"
 + ".js-commentFieldNote { display: none; }"
, 'jskit-auth');

JSKitAuth.prototype.getMessage = function(errCode) {
	var errorDescription = {
		error : {bind: 'login', desc: 'Error'},
		long_login : {bind: 'login', desc: 'Login is too long (should be not more 63 characters)'},
		empty_login : {bind: 'login', desc: 'Enter your login'},
		short_login : {bind: 'login', desc: 'Login is too short (should be at least 6 characters)'},
		empty_openid : {bind: 'login', desc: 'Enter your OpenID URL'},
		empty_password : {bind: 'password', desc: 'Enter your password'},
		empty_password2 : {bind: 'password2', desc: 'Enter your password'},		
		incorrect_login : {bind: 'login', desc: 'Login must begin with a letter and contain 6 or more characters, including numbers, a dash and a dot.'},
		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: John.Smith',
		password_is_short : {bind: 'password', desc: 'Password is too short (should be at least 6 characters)'},
		user_already_logged : {bind: 'login', desc: 'You are already signed in with this login'},
		login_is_already_used : {bind: 'login', desc: 'Login name is already taken by someone else'},
		incorrect_login_or_password : {bind: 'login', desc: 'Login or password is incorrect'},
		user_already_has_other_login : {bind: 'login', desc: 'You are logged in already'},
		password2_isnot_equal_password1 : {bind: 'password', desc: 'Passwords do not match'}
	};
	return errorDescription[errCode] || errorDescription[error];
}

JSKitAuth.prototype.processControls = function(name, type, func){
	JSKitLib.fmap(this.HNDL[name][type], func);	
}

JSKitAuth.prototype.addKeyHandler = function(mode) {
	var self = this;
	var button = self.HNDL[mode]["button"].button;
	this.processControls(mode, "input", function(V){
		if(JSKitLib.isIE() || JSKitLib.isOpera()) V.onkeydown = function(ev) { return self.keyHandler(ev, button);}
		else V.onkeypress = function(ev) { return self.keyHandler(ev, button);}
	});	
}

JSKitAuth.prototype.hideMessages = function(mode) {
	this.processControls(mode, "message", function(V){V.style.display = 'none'});
}

JSKitAuth.prototype.disableControls = function(mode, value) {
	this.processControls(mode, "input", function(V){V.disabled = value});
	this.processControls(mode, "button", function(V){V.disabled = value});
}

JSKitAuth.prototype.clearInputFields = function(mode) {
	this.processControls(mode, "input", function(V){V.value = ""});
}


JSKitAuth.prototype.toDom = function(area) {
	return JSKitLib.html(area);
}

JSKitAuth.prototype.autoComplete = (JSKitLib.getBrowser() == 'gecko' ? ' autocomplete="Off"' : '');

JSKitAuth.prototype.keyHandler = function(e, button){
	var self=this;
	e = e || window.event;
	switch(e.keyCode) {
		case 10: case 13:
			JSKitLib.preventDefaultEvent(e);
			button.click();
		break;
	}
}

JSKitAuth.prototype.progressAreaTmpl =
'<div class="jsk-SectionLoginProgress js-progressHandle">' +
	'<div class="jsk-SectionLoginProgressPic"></div>' +
	'<div class="jsk-SectionLoginProgressLbl">Cargando...</div>' +
	'<div class="jsk-SectionLoginProgressFooter"></div>' +
'</div>';

JSKitAuth.prototype.loginAreaTmpl =
'<div style="clear: both;">' +
	JSKitAuth.prototype.progressAreaTmpl +
	'<dl class="jsk-SectionLoginInput">' +
		'<dt class="jsk-SectionRegisterInput js-loginLblHandle">Login</dt>' +
		'<dd class="jsk-SectionLoginInput">' +
			'<input class="jsk-SectionLoginInput jsk-SectionLoginInputOpenID" tabindex=2 name="jsk-User-login-login"' + JSKitAuth.prototype.autoComplete +'>' +
			'<div class="jsk-SectionLoginMessage js-loginMessageHandle"></div>' +
		'</dd>' +
		'<input value="Login" name="Login" class="jsk-Button" type="button">' +
		'<dt class="jsk-SectionRegisterInput js-passwordLblHandle">Password</dt>' +
		'<dd class="jsk-SectionLoginInput">' +
			'<input class="jsk-SectionLoginInput" name="jsk-User-login-password" tabindex=3 type="password">' +
			'<div class="jsk-SectionLoginMessage js-passwordMessageHandle"></div>' +
		'</dd>' +
	'</dl>' +
'</div>';

JSKitAuth.prototype.openIdAreaTmpl =
'<div style="clear: both;">' +
	JSKitAuth.prototype.progressAreaTmpl +
	'<dl class="jsk-SectionLoginInput">' +
		'<dt class="jsk-SectionRegisterInput js-loginLblHandle">OpenID</dt>' +
		'<dd class="jsk-SectionLoginInput">' +
			'<input class="jsk-SectionLoginInput jsk-SectionLoginInputOpenID" tabindex=1 name="jsk-User-login-login"' + JSKitAuth.prototype.autoComplete +'>' +
			'<div class="jsk-SectionLoginMessage js-loginMessageHandle"></div>' +
		'</dd>' +
		'<input value="Login" name="Login" class="jsk-Button" type="button">' +
	'</dl>' +
'</div>';

JSKitAuth.prototype.facebookAreaTmpl =
'<div style="width: 194px; height: 27px;"><iframe src="http://js-kit.com/api/facebook/connect-button" height="700" width="600" allowtransparency="true" style="background-color: transparent; border: none; position: absolute; z-Index: 14000;" frameborder="0"></iframe></div>';

JSKitAuth.prototype.yahooAreaTmpl = function() {
return '<div onclick="window.open(\'http://js-kit.com/api/oauth/yahoo.html\',\'_blank\',\'status=no, menubar=no, resizable=no, scrollbars=yes, toolbar=no, location=yes, directories=no\')" style="width:161px; height:22px; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'//js-kit.com/images/yahoo/yos.png\', sizingMethod=\'crop\');' : 'background: no-repeat url(//js-kit.com/images/yahoo/yos.png);') + ' cursor:pointer;"></div>';
}

JSKitAuth.prototype.registerAreaTmpl =
'<div style="clear: both;">'+
	JSKitAuth.prototype.progressAreaTmpl +
	'<dl class="jsk-SectionLoginInput">' +
		'<dt class="jsk-SectionRegisterInput">Login</dt>' +
		'<dd class="jsk-SectionLoginInput">' +
			'<input class="jsk-SectionLoginInput jsk-SectionLoginInputJSKit" tabindex=4 name="jsk-User-login-reglogin"' + JSKitAuth.prototype.autoComplete +'>' +
			'<div class="jsk-SectionLoginMessage js-loginMessageHandle"></div>' +
		'</dd>' +
		'<input value="Register" name="Register" class="jsk-Button" type="button">' +
		'<dt class="jsk-SectionRegisterInput">Password</dt>' +
		'<dd class="jsk-SectionLoginInput">' +
			'<input class="jsk-SectionLoginInput jsk-SectionRegPasswordInput" tabindex=5 name="jsk-User-login-regpassword" type="password">' +
			'<div class="jsk-SectionLoginMessage js-passwordMessageHandle"></div>' +
		'</dd>' +
		'<dt class="jsk-SectionRegisterInput">Re-type Password</dt>' +
		'<dd class="jsk-SectionLoginInput jsk-SectionRegPasswordInput">' +
			'<input class="jsk-SectionLoginInput jsk-SectionRegPasswordInput" tabindex=6 name="jsk-User-login-regpassword2" type="password">' +
			'<div class="jsk-SectionLoginMessage js-password2MessageHandle"></div>' +
		'</dd>' +
	'</dl>' +
'</div>';

JSKitAuth.prototype.createFacebookArea = function(onSuccessOIDLoginAction, template) {
	var self = this;
	var facebookArea = self.toDom( template || self.openIdAreaTmpl);
	self.HNDL["facebook"] = {
		container : facebookArea
	}
	return self.HNDL["facebook"];
}

JSKitAuth.prototype.createYahooArea = function(onSuccessOIDLoginAction, template) {
	var self = this;
	var yahooArea = self.toDom( template || self.openIdAreaTmpl);
	self.HNDL["yahoo"] = {
		container : yahooArea
	}
	return self.HNDL["yahoo"];
}

JSKitAuth.prototype.createOpenIdArea = function(onSuccessOIDLoginAction, template) {
	var self = this;

	self.eventsCtx = JSKW$Events.registerEventCallback(self.eventsCtx, onSuccessOIDLoginAction, 'JSKitAuth_successOpenIdLogin');

	var processMessage = function(errCode, data) {
		self.disableControls("openid", false);
		if(errCode=='success') {
			JSKW$Events.syncBroadcast('JSKitAuth_successOpenIdLogin', data);
			self.clearInputFields("openid");
		} else {
			var errObj = self.getMessage(errCode);
			if(errObj.bind) {
				var inputHandle = self.HNDL["openid"]["input"].openId;
				var errorMessageHandle = self.HNDL["openid"]["message"].openIdMsg;
				if (inputHandle) inputHandle.focus();
				if (errorMessageHandle) {
					errorMessageHandle.innerHTML = errObj.desc;
					errorMessageHandle.style.display = 'block';
				}
			}
		}
	};

	var openIdCallback = function(errCode, data) {
		self.HNDL["openid"].progress.style.display = "none";
		processMessage(errCode, data);
	}

	var random = function() {return Math.floor(Math.random() * 10000000000); }
	var PPID = 'prfl_' + random() + '-' + random() + '-' + random();

	var submitOpenId = function() {
		self.hideMessages("openid");
		var params = {
			jsktid: PPID,
			mode: self.mode,
			callback: openIdCallback};
		if (self.LoginWindow && !self.LoginWindow.closed) {
			self.LoginWindow.focus();
			self.serverRequest(self.uriDomain + '/openid-auth-prolongate', params);
			return false;
		}
		var OpenID = self.HNDL["openid"]["input"].openId;
		if(OpenID.value.length < 1 || !OpenID.defaultRemoved) {
			openIdCallback('empty_openid');
			return false;
		}
		self.serverRequest(self.uriDomain + '/openid-auth-wait-for-completion', params);
		self.LoginWindow = window.open('http://js-kit.com/settings/auth.cgi?action=prfl&jsktid=' +
			PPID + '&openid_url=' + OpenID.value, '_blank',
			'status=no, menubar=no, resizable=no, scrollbars=yes, toolbar=no, location=yes, directories=no');
		self.hideMessages("openid", true);
		self.disableControls("openid", false);
		return false;
	}

	var openIdArea = self.toDom( template || self.openIdAreaTmpl);
	var openIdAreaDesc = JSKitLib.mapClass2Object({}, openIdArea);

	self.HNDL["openid"] = {
		message : 
			{openIdMsg : openIdAreaDesc["js-loginMessageHandle"]},
		input : 
			{openId : openIdAreaDesc["jsk-User-login-login"]},
		button : 
			{button : openIdAreaDesc["Login"]},
		progress : openIdAreaDesc['js-progressHandle'],
		container : openIdArea,
		openIdLbl : openIdAreaDesc["js-loginLblHandle"].firstChild}

	JHI2.create("http://username.myopenid.com", self.HNDL["openid"]["input"].openId);
	self.HNDL["openid"]["button"].button.onclick = submitOpenId;
	this.addKeyHandler("openid");
	return self.HNDL["openid"];
}

JSKitAuth.prototype.createLoginArea = function(onSuccessLoginAction, template, extra) {
	var self = this;
	extra = extra || {};
	var handleName = (extra.isHaloscan ? 'haloscanLogin' : 'login');

	var loginArea = self.toDom( template || self.loginAreaTmpl );
	var loginAreaDesc = JSKitLib.mapClass2Object({}, loginArea);

	var handle = self.HNDL[handleName] = {
		message : 
			{loginMsg : loginAreaDesc["js-loginMessageHandle"],
			passwordMsg : loginAreaDesc["js-passwordMessageHandle"]},
		input : 
			{login : loginAreaDesc["jsk-User-login-login"],
			password : loginAreaDesc["jsk-User-login-password"]},
		button : 
			{button : loginAreaDesc["Login"]},
		loginLbl : loginAreaDesc["js-loginLblHandle"].firstChild,
		progress : loginAreaDesc['js-progressHandle'],
		container : loginArea,
		passwordLbl : loginAreaDesc["js-passwordLblHandle"]}

	self.eventsCtx = JSKW$Events.registerEventCallback(self.eventsCtx, onSuccessLoginAction, extra.isHaloscan ? 'JSKitAuth_successHaloscanLogin' : 'JSKitAuth_successLogin');

	var processMessage = function(errCode, data) {
		self.disableControls(handleName, false);
		if(errCode=='success') {
			JSKW$Events.syncBroadcast('JSKitAuth_successLogin', data);
			self.clearInputFields(handleName);
		} else {
			var errObj = self.getMessage(errCode);
			if(errObj.bind) {
				var inputHandle = null;
				var errorMessageHandle = null;
				switch (errObj.bind){
					case 'login':
						inputHandle = handle.input.login;
						errorMessageHandle = handle.message.loginMsg;
					break;
					case 'password':
						inputHandle = handle.input.password;
						errorMessageHandle = handle.message.passwordMsg;
					break;
				}
				if (inputHandle) inputHandle.focus();
				if (errorMessageHandle) {
					errorMessageHandle.innerHTML = errObj.desc;
					errorMessageHandle.style.display = 'block';
				}
			}
		}
	};

	var loginCallback = function(errCode, data) {
		handle.progress.style.display = "none";
		processMessage(errCode, data);
	}

	var submitLogin = function() {
		self.hideMessages(handleName);
		var auth = {
			login: handle.input.login.value,
			password: handle.input.password.value, 
			callback: loginCallback,
			mode: self.mode};
		if (auth['login'].length < 1 || !handle.input.login.defaultRemoved) {
			loginCallback('empty_login');
			return false;
		}
		if (auth['password'].length < 1) {
			loginCallback('empty_password');
			return false;
		}
		var url = self.uriDomain + (extra.isHaloscan ? '/user-haloscan-login' : '/user-login');
		self.serverRequest(url, auth);
		self.disableControls(handleName, true);
		handle.progress.style.display = "inline";
		return false;
	}

	JHI2.create("John.Smith", handle.input.login);
	handle.button.button.onclick = submitLogin;
	this.addKeyHandler(handleName);
	return handle;
}

JSKitAuth.prototype.createRegisterArea = function(onSuccessReg, template) {
	var self = this;

	self.eventsCtx = JSKW$Events.registerEventCallback(self.eventsCtx, onSuccessReg, 'JSKitAuth_successReg');

	var processMessage = function(errCode, data) {
		self.disableControls("register", false);
		if (errCode == "success"){
			JSKW$Events.syncBroadcast('JSKitAuth_successReg', data);
			self.clearInputFields("register");
		} else {
			var errObj = self.getMessage(errCode);
			if(errObj.bind) {
				switch (errObj.bind){
					case 'login':
						var inputHandle = self.HNDL["register"]["input"].login;
						var errorMessageHandle = self.HNDL["register"]["message"].loginMsg;
					break;
					case 'password':
						var inputHandle = self.HNDL["register"]["input"].password;
						var errorMessageHandle = self.HNDL["register"]["message"].passwordMsg;
					break;
					case 'password2':
						var inputHandle = self.HNDL["register"]["input"].password2;
						var errorMessageHandle = self.HNDL["register"]["message"].password2Msg;
					break;
				}
				if (inputHandle) inputHandle.focus();
				if (errorMessageHandle) {
					errorMessageHandle.innerHTML = errObj.desc;
					var span = self.buildShowMore();
					errorMessageHandle.appendChild(span);
					errorMessageHandle.style.display = 'block';
				}
			}
		}
	};

	var submitRegister = function() {
		self.hideMessages("register");
		var auth = {
			login: self.HNDL["register"]["input"].login.value, 
			password: self.HNDL["register"]["input"].password.value, 
			retype_password: self.HNDL["register"]["input"].password2.value, 
			callback: registerCallback,
			mode: self.mode};
		if(auth['login'].length<1 || !self.HNDL["register"]["input"].login.defaultRemoved) {
			registerCallback('empty_login');
			return false;
		}
		if(auth['password'].length<1) {
			registerCallback('empty_password');
			return false;
		}
		if(auth['retype_password'].length<1) {
			registerCallback('empty_password2');
			return false;
		}
		self.serverRequest(self.uriDomain + '/user-registration', auth);
		self.disableControls("register", true);
		self.HNDL["register"].progress.style.display = "inline";
		return false;
	}

	var registerCallback = function(errCode, data) {
		self.HNDL["register"].progress.style.display = "none";
		if(data && data.yours) data.yours.newUser = true;
		processMessage(errCode, data);
	}

	var registerArea = self.toDom( template || self.registerAreaTmpl);

	var registerAreaDesc = JSKitLib.mapClass2Object({}, registerArea);

	self.HNDL["register"] = {
		message : 
			{loginMsg : registerAreaDesc["js-loginMessageHandle"],
			passwordMsg : registerAreaDesc["js-passwordMessageHandle"],
			password2Msg : registerAreaDesc["js-password2MessageHandle"]},
		input : 
			{login : registerAreaDesc["jsk-User-login-reglogin"],
			password : registerAreaDesc["jsk-User-login-regpassword"],
			password2 : registerAreaDesc["jsk-User-login-regpassword2"]},
		button : 
			{button : registerAreaDesc["Register"]}, 
		progress : registerAreaDesc['js-progressHandle'],
		container : registerArea}

	JHI2.create("John.Smith", self.HNDL["register"]["input"].login);
	self.HNDL["register"]["button"].button.onclick = submitRegister;
	this.addKeyHandler("register");
	return self.HNDL["register"];
}

JSKitAuth.prototype.buildHeaderPart = function(mode, currentLogin, onLogoutAction) {
	var self = this;

	if (mode == 'login') {
		var headerMsg = "Existing account";
		var subHeaderMsg = "(sign in using OpenID or JS-Kit account)";
	} else {
		var headerMsg = "Don't have a JS-Kit account?";
		var subHeaderMsg = "(create a new JS-Kit account)";
	}

	var logoutTmpl = 
	'<span>Existing account (' +
		'<span class="jsk-SectionLoginLogout">' +
			'<a class="js-logoutHandle" href="javascript:void(0);">Sign out of ' + currentLogin + '</a>' +
		'</span>)' +
	'</span>';

	var headerText = currentLogin ? logoutTmpl : headerMsg;

	var headerTmpl = 
	'<div style="clear: both;">' +
		'<div class="jsk-SectionChapter">' + headerText + '</div>' +
		'<div class="jsk-SectionChapterSub">' + subHeaderMsg + '</div>' +
	'</div>'; 

	var container = self.toDom(headerTmpl);

	if (currentLogin) {
		self.eventsCtx = JSKW$Events.registerEventCallback(self.eventsCtx, onLogoutAction, 'JSKitAuth_logout');
		var containerDesc =JSKitLib.mapClass2Object({}, container);	
		containerDesc["js-logoutHandle"].onclick = function() {
			setTimeout(function(){
                                self.serverRequest('/api/session/logout.js', {});
                        }, 0);
			return false;
		}
	}
	return container;
}

JSKitAuth.prototype.buildShowMore = function() {
	var self = this;

	var template = 
	'<span class="jsk-SectionLoginMessageFull"> (' + 
		'<a class="js-fullDescLink" href="javascript:void(0);">Learn more...</a>)' +
		'<div style="display: none;" class="js-fullDescDiv">' + self.getMessage('full_description') + '</div>' 
	'</span>';

	var span = self.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 span;
}

JSKitAuth.prototype.bindServerRequestFunction = function(serverRequest) {
	this.serverRequest = serverRequest;
}

JSKitAuth.prototype.reDrawSelector = function(selector, options) {
	if (selector && options) {
		while (selector.hasChildNodes()) selector.removeChild(selector.firstChild);
		JSKitLib.fmap(options, function(opt) {
			if(opt.guard && !opt.guard()) return;
			var option = document.createElement('option');
			var optionText = document.createTextNode((typeof(opt.text) == "function") ? opt.text() : opt.text);
			option.value = opt.value;
			option.appendChild(optionText);
			selector.appendChild(option);
		});
	}
}

JSKitAuth.prototype.createAuthSelector = function(options, selectedIndex, onchange) {
	var authSelector = document.createElement('select');
	authSelector.className = 'jsk-SectionLoginInput';
	authSelector.name = 'jsk-User-login-type';
	JSKitAuth.prototype.reDrawSelector(authSelector, options);
	authSelector.onchange = onchange;
	authSelector.selectedIndex = selectedIndex;
	return authSelector;
}

JSKitAuth.prototype.replaceElementWSelect = function(element, options, selectedIndex, onchange) {
	var authSelector = JSKitAuth.prototype.createAuthSelector(options, selectedIndex, onchange);
	element.parentNode.replaceChild(authSelector, element);
	return authSelector;
}



function JSDL(elmParent, arrDragElms) {
       var self = this;
       self.isIE = JSKitLib.isIE();
       var drgElms = arrDragElms || [elmParent];
       for(var i=0; i<drgElms.length; i++) {
               self.addDraggableChild(drgElms[i]);
       }
       self.elmParent = elmParent;
       self.setParent = 1;
}

JSDL.prototype.reSetDragParent = function () {
       if(!this.setParent) return;
       if(this.elmParent.parentNode!=document.body || this.elmParent.style.position!='absolute') {
               var elmPos;
               if(this.elmParent.parentNode) {
                       elmPos = this.getElmAbsPos(this.elmParent, false);
                       this.elmParent.parentNode.removeChild(this.elmParent);
               }
               document.body.appendChild(this.elmParent);
               this.elmParent.style.position = 'absolute';
               if(elmPos) {
                       this.elmParent.style.left = elmPos.x + "px";
                       this.elmParent.style.top = elmPos.y + "px";
               }
       }
       this.setParent = 0;
}

JSDL.prototype.getCurScroll = function() {
       var scroll_left=0,scroll_top=0;
       if(self.pageXOffset){
               scroll_left=self.pageXOffset;
       } else {
               if(document.documentElement&&document.documentElement.scrollLeft){
                       scroll_left=document.documentElement.scrollLeft;
               } else {
                       if(document.body){
                               scroll_left=document.body.scrollLeft;
                       }
               }
       }
       if(self.pageYOffset){
               scroll_top=self.pageYOffset;
       } else {
               if(document.documentElement&&document.documentElement.scrollTop){
                       scroll_top=document.documentElement.scrollTop;
               } else {
                       if(document.body){
                               scroll_top=document.body.scrollTop;
                       }
               }
       }
       return {"scroll_left":scroll_left,"scroll_top":scroll_top};
}

JSDL.prototype.getElmAbsPos = function (element, usescroll){
       var x=0;
       var y=0;
       var e=element;
       var scroll_left=0,scroll_top=0,cur_scroll;
       if(usescroll){
               cur_scroll=this.getCurScroll();
               scroll_left=cur_scroll.scroll_left;
               scroll_top=cur_scroll.scroll_top;
       }
       if(!this.isIE){
               while(e){
                       x+=e.offsetLeft;
                       y+=e.offsetTop;
                       e=e.offsetParent;
               }
               e=element;
               while(e && e!=document.body && e!=document.documentElement){
		       x -= e.scrollLeft || 0;
		       y -= e.scrollTop || 0;
                       e=e.parentNode;
               }
               if(usescroll){
                       x-=scroll_left;
                       y-=scroll_top;
               }
               return {x:x,y:y};
       }
       e=element;
       while(e){
               var left_border=0;
               var top_border=0;
               if(e!=element){
                       var left_border = parseInt(e.style.borderLeftWidth) || 0;
                       var top_border = parseInt(e.style.borderTopWidth) || 0;
               }
               if(document.compatMode == "BackCompat"){
                       x+=e.offsetLeft-left_border;
                       y+=e.offsetTop-top_border;
               } else {
                       x+=e.offsetLeft+left_border;
                       y+=e.offsetTop+top_border;
               }
               try {
                       e=e.offsetParent;
               } catch(err) { e=null; };
       }
       if(usescroll){
               x-=scroll_left;
               y-=scroll_top;
       }
       return {x:x,y:y};
}

JSDL.prototype.addDraggableChild = function(dragElm) {
       var self = this;
       dragElm.style.cursor = "move";
       dragElm.onmousedown = function(e){self.onStartDragHandler(e);}
}

JSDL.prototype.onStartDragHandler = function (e) {
       var self = this;
       self.reSetDragParent();
       e=e || window.event;
       var elmPos = self.getElmAbsPos(this.elmParent, false);
       var mousePos = JSKitLib.getMousePosition(e);
       self.startx = mousePos.x - elmPos.x;
       self.starty = mousePos.y - elmPos.y;
       var maxLeft = document.body.clientWidth - self.elmParent.offsetWidth -
               (parseInt(self.elmParent.style.marginLeft) || 0) -
               (parseInt(self.elmParent.style.marginRight) || 0);

       var onMoveDragHandler = function(event) {
               event = event || window.event;
               var mousePos = JSKitLib.getMousePosition(event);
               var left = mousePos.x - self.startx;
	       self.elmParent.style.left = (left >= maxLeft ? maxLeft : (left < 0 ? 0 : left)) + "px";
               self.elmParent.style.top = (mousePos.y - self.starty < 0) ? 0 : (mousePos.y - self.starty) + "px";
       }

       var onStopDragHandler = function(event) {
               event = event || window.event;
               JSKitLib.removeHandlers(self.elmParent, onMoveDragHandler,
                       onStopDragHandler, true);
               JSKitLib.stopEventPropagation(event);
               if(self.elmParent.jsk$on_stop_drag) self.elmParent.jsk$on_stop_drag(e);
       }

       JSKitLib.addHandlers(self.elmParent, onMoveDragHandler,
               onStopDragHandler, true);
       JSKitLib.stopEventPropagation(e);
       JSKitLib.preventDefaultEvent(e);
       if(self.elmParent.jsk$on_start_drag) self.elmParent.jsk$on_start_drag(e);
}



function JSKbdHandler(element, events) {

	this.kbdCallback = function(e) {
		var event = e || window.event;
		var key = event.charCode || event.keyCode;
		if (key == 9 || key == 13 || key == 27) JSKitLib.preventDefaultEvent(event);
		if(JSKitLib.isSafari()) JSKitLib.stopEventPropagation(event);
		for(var i = 0; i < events.length; i++) {
			for(var j = 0; j < events[i].keys.length; j++) {
				if(typeof(events[i].keys[j]) == "string") events[i].keys[j] = String.charCodeAt(events[i].keys[j]);
				var shiftCondition = (events[i].shift != undefined) ? events[i].shift == event.shiftKey : true; 
				if (events[i].keys[j] == key && shiftCondition) {
					if(!events[i].args)
						(events[i].action)();
					else
						events[i].action.apply(events[i], events[i].args);
				}
			}
		}
	}

	if(element.addEventListener) {
		if(JSKitLib.isSafari()) element.addEventListener("keydown", this.kbdCallback, false);
		else if(JSKitLib.isOpera()) element.addEventListener("keydown", this.kbdCallback, false);
		else element.addEventListener("keypress", this.kbdCallback, false);
	} else {
		element.onkeydown = this.kbdCallback;
	}
}



function JSIPE2(obj) {
/* 
	JSIPE2 API

	obj:		object contains property
	title: 		hint
	defaultText:	default text in created div
	property:	property where save the result
	maxLength:	max string length
	width: 		input width
	jsk$wasEdited	callback, called at the end of editing 
	
	example: 
	var jsipe = new JSIPE2({obj: elem,
				property: 'descr',
				title: 'Description',
				defaultText: 'Añadir titulo',
				width: '90px',
				maxLength: 12,
				jsk$wasEdited: function(){...}
	});

*/

	for(var i in obj)
		this[i] = obj[i];
	var div = JSKitLib.cr();
	div.title = this.title || "Click para editar";
	var defaultText = this.defaultText || "Empty value (click para editar)";
	var maxTextLength = this.maxLength || 256;

	var self = this;

	var textDiv = JSKitLib.cr({style:{display:"inline"}});
	textValue = (JSKitLib.trim(self.obj[self.property]).length > 0) ? self.obj[self.property] : defaultText;
	var text = document.createTextNode(textValue);
	textDiv.onmouseover = function() { JSKitLib.addClass(textDiv, "jsipe-onmouseover"); }
	textDiv.onmouseout  = function() { JSKitLib.removeClass(textDiv, "jsipe-onmouseover"); }
	textDiv.appendChild(text);
	div.appendChild(textDiv);

	var editDiv = JSKitLib.cr({style:{display:"none"}});
	div.appendChild(editDiv);
	var edit = JSKitLib.cr({t:"input", type:"edit", style:{width: (self.width || "150px")}});
	edit.value = this.obj[this.property];
	editDiv.appendChild(edit);

	var applyDiv = JSKitLib.cr();
	JSKitLib.addClass(applyDiv, "jsipe-applyButton");
	applyDiv.title = "Apply";
	JSKitLib.addPNG(applyDiv, "//js-kit.com/images/tick.png");
	editDiv.appendChild(applyDiv);
	
	this.displayMode = function() {
		textDiv.style.display = "inline";
		editDiv.style.display = "none";
		textDiv.removeChild(text);
		text = document.createTextNode(self.obj[self.property] || defaultText);
		textDiv.appendChild(text);
		if(self.jsk$wasEdited) self.jsk$wasEdited();
	}

	this.editMode = function(e) {
		textDiv.style.display = "none";
		editDiv.style.display = "inline";
		edit.focus();
		edit.select();
	}

	var applyChanges = function() {
		if(edit.value == self.obj[self.property]) { self.displayMode(); return;}
		if(edit.value.length > maxTextLength) {
			alert("The text you entered cannot exceed "+ maxTextLength +" symbols");
			resetChanges();
			return;
		}
		self.obj[self.property] = edit.value = JSKitLib.trim(edit.value);
		edit.blur();
		self.displayMode();
	}

	var resetChanges = function() {
		edit.value = self.obj[self.property];
		edit.blur();
		self.displayMode();
	}

	var jumpNextSibling = function() {
		edit.blur();
		if(self.nextSib)
			self.nextSib.editMode();
	}

	var jumpPrevSibling = function() {
		edit.blur();
		if(self.prevSib)
			self.prevSib.editMode();
	}

	if(this.dblclick)
		textDiv.ondblclick = this.editMode;
	else
		textDiv.onclick = this.editMode;
	edit.onblur = applyChanges;
	applyDiv.onmousedown = applyChanges;

	var KbdHandler = new JSKbdHandler(edit, [
					{action:applyChanges, keys:[10,13]}
					,{action:resetChanges, keys:[27]}
					,{action:jumpNextSibling, keys:[9], shift:false}
					,{action:jumpPrevSibling, keys:[9], shift:true}
					]);

	this.div = div;
}

JSIPE2.prototype.addNextSibling = function(next) {
	if (next) {
		this.nextSib = next;
		next.prevSib = this;
	}
}



function JSIPE(obj) {
	var self = this;
	self.obj = obj;
	var form = this.makeForm(obj.title);
	var inp = form.input;
	self.form = form;

	form.cleaner.onmousedown = function(e){
		inp.value = "";
		form.cleaner.style.visibility = "hidden";
		inp.focus();
		JSKitLib.preventDefaultEvent(e || window.event);
	}
	
	var keyHandler = function(e) {
		e = e || window.event;
		setTimeout(function(){
			form.cleaner.style.visibility = (inp.value.length != 0) ? "visible" : "hidden";
			if(obj.type == "Tab" || obj.type == "Image") form.cleaner.style.display = "none";
		}, 0);
		switch(e.keyCode || e.which) {
			case 27:
				JSKitLib.preventDefaultEvent(e);
				if(obj.mode == "full") self.finishEditing(obj.field, obj.field.lastValue);
				if(obj.jsk$on_cancel_exit) obj.jsk$on_cancel_exit();
			break;
			case 10: case 13:
				JSKitLib.preventDefaultEvent(e);
				if (inp.value && obj.mode == "full")
					self.finishEditing(obj.field, inp.value);
				if(obj.jsk$on_submit_exit) obj.jsk$on_submit_exit(inp.value);
			break;
			case 9:
				JSKitLib.preventDefaultEvent(e);
				if (obj.siblings) obj.siblings[(obj.field.pos+1)%obj.siblings.length].tabKeyHandler();
			break;
		}
	}
	self.addKeyHndl(keyHandler);		
	if (obj.inpSize) inp.style.width = obj.inpSize;
	form.cleaner.style.visibility = "hidden";
	if(obj.mode == "form") return form;

	if(!window.jsipe$glob) window.jsipe$glob = {};
	var glob = window.jsipe$glob;
	obj.field.style.cursor = "pointer";
	if(obj.siblings) obj.field.pos = obj.siblings.length;

	this.finishEditing = function(field, newValue) {
		if(!field.input) return;
		glob.isEditing = false;
		field.input.onblur = JSKitLib.isOpera() ? undefined : "";
		field.input.onkeypress = JSKitLib.isOpera() ? undefined : "";
		field.input = null;
		field.wasEdited(newValue);
		field.style.textDecoration = field.oldDecoration;
	}

	var onclickHandler = function() {
		if(obj.field.input) return false;
		if(obj.jsipe$start && !obj.jsipe$start()) return false;
		if(glob.stopEditing) glob.stopEditing();
		if(obj.containerElement.tId) {
			clearTimeout(obj.containerElement.tId);
			obj.containerElement.tId = 0} 
		obj.field.oldDecoration = obj.field.style.textDecoration;
		obj.field.isHtmlLink = obj.field.firstChild.tagName == 'A';
		obj.field.lastValue = obj.itemObject[obj.Property];
		obj.field.ondblclick = JSKitLib.isOpera() ? undefined : "";
		inp.type = 'text';
		inp.value = obj.itemObject[obj.Property];
		self.addKeyHndl(keyHandler);		

		inp.onblur = function(e) {
			if(self.form.input.value) {
				self.finishEditing(self.obj.field, self.form.input.value);
				if (obj.field.lastValue == self.form.input.value) {
					if(obj.jsk$on_cancel_exit) obj.jsk$on_cancel_exit(self.form.input.value)}
				else{
					if(obj.jsk$on_submit_exit) obj.jsk$on_submit_exit(self.form.input.value)}
			};
			//Do not close field until non-empty
		}

		obj.field.input = inp;
		glob.stopEditing = function() {
			glob.stopEditing = null;
			if((obj.field.input)&&obj.field.input.value) self.finishEditing(obj.field, obj.field.input.value);
		}
		JSKitLib.removeChildren(obj.field);
		obj.field.appendChild(form.main);
		obj.field.style.textDecoration = "none";
		form.cleaner.style.visibility = (inp.value.length != 0) ? "visible" : "hidden";
		if(obj.type == "Tab"  || obj.type == "Image") form.cleaner.style.display = "none";
		inp.onselectstart = function(e) {
			JSKitLib.stopEventPropagation(e || window.event);
			return true;
		};
		obj.containerElement.onselectstart = function(e) { return true };
		inp.focus();
		inp.select();
		glob.isEditing = true;
		return false;
	}

	var ondblclickHandler = function() {
		if(0 && obj.field.isHtmlLink)
			window.location.href = this.firstChild.value;
	}

	switch(obj.type) {
	case "Tab":
		obj.field.ondblclick = onclickHandler;
		break;
	case "Others":
                obj.field.onclick = onclickHandler;
                obj.field.tabKeyHandler = onclickHandler;
                obj.field.ondblclick = ondblclickHandler;
		break;
	case "Search": case "Image":
		obj.field.onclick = onclickHandler;
		break;
	}
}

JSIPE.prototype.addKeyHndl = function(keyHandler){
	var inp = this.form.input;
        switch(this.obj.type) {
        case "Tab":
                if (JSKitLib.isIE()) inp.onkeydown = keyHandler;
                else if(JSKitLib.isSafari()) inp.onkeyup = keyHandler;
                else inp.onkeypress = keyHandler;
                break;
        case "Others": case "Image":
		if(JSKitLib.isOpera()) inp.onkeypress = keyHandler;
		else inp.onkeydown = keyHandler;
                break;
        case "Search":
		if (JSKitLib.isIE() || JSKitLib.isSafari())
			inp.onkeydown = keyHandler;
		else inp.onkeypress = keyHandler;
                break;
        }
}

JSIPE.prototype.makeForm = function(title){
	var text = this.dtContent.replace(/TITLE/, title || "");
	var div = JSKitLib.html(text);
	var ctls = JSKitLib.mapClass2Object({}, div);
	if(!title) ctls['js-JSIPETitle'].style.display = "none";
	return {'main': div,'input': ctls['js-JSIPEInput'], 'cleaner':ctls['js-JSIPECleaner']};
}

JSIPE.prototype.dtContent
='<table border=0 style="padding: 0px; display: inline" cellspacing="0px" cellpadding="0px">'
+'      <tr>'
+'              <td class="js-JSIPETitle" style="padding:0px 4px 0px 0px; cursor: text;"><b>TITLE</b></td>'
+'              <td style="padding: 0px;">'
+'                      <input class="js-JSIPEInput" style="vertical-align:middle; padding: 0px;"></input></td>'
+'              <td style="padding: 0px;">'
+'                      <img class="js-JSIPECleaner" style="margin-left: 4px; vertical-align:bottom; cursor: pointer;" src="http://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) {
	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;
	}
	JSKitLib.fmap(this.registeredCallbacks[ev], function(evHdl, i){
		if(eventHandle==evHdl) {
			delete self.registeredCallbacks[ev][i];
		}
	});
	if(!this.registeredCallbacks[ev].length) delete this.registeredCallbacks[ev];
}

JSECC.prototype.invalidateContext = function () {
	this.registeredCallbacks = [];
	try {
		if(this.jsk$invalidate) this.jsk$invalidate();
	} catch(e) { ; };
}

JSECC.prototype.broadCast = function (eventName) {
	var self = this;
	var ar = [''];
	var args = arguments;
	if(eventName!='') ar.push(eventName);
	JSKitLib.fmap(ar, function(ev){
		if(self.registeredCallbacks[ev]) JSKitLib.fmap(self.registeredCallbacks[ev], function(evHdl){
			evHdl.apply(self, args);
		});
	});
}



function JSPGC(itemsCount, itemsPerPage) {
	this.itemsPerPage = itemsPerPage;
	this.items = [];
	this.itemsCount = 0;
	this.pages = [];
	this.pageCount = 0;
	this.setPageCount(this.getPageCntByItemCnt(itemsCount), itemsCount);
}

JSPGC.prototype.newItem = function(item) {
	var newItem = { obj: undefined, html: undefined, div: undefined };
	if(item) JSKitLib.fmap(item, function(V,K){ newItem[K] = V; });
	return newItem;
};

JSPGC.prototype.setItems = function (sIdx, Cnt, itemsArr) {
	for(var i=sIdx; i<sIdx+Cnt; i++) {
		this.items[i] = itemsArr[i-sIdx];
	}
}

JSPGC.prototype.addItem = function (item, sIdx) {
	this.items.splice(sIdx, 0, item);
	this.itemsCount++;
}

JSPGC.prototype.getItems = function (sIdx, Cnt) {
	return (sIdx>=0 && Cnt) ? this.items.slice(sIdx, sIdx+Cnt) : [];
}

JSPGC.prototype.deleteItems = function (sIdx, Cnt) {
	this.items.splice(sIdx, Cnt);
	this.itemsCount -= Cnt;
}

JSPGC.prototype.setItemsCount = function (newItemsCount) {
	if(newItemsCount<this.itemsCount) {
		this.deleteItems(newItemsCount, this.itemsCount-newItemsCount);
	} else {
		if(newItemsCount>0) this.items[newItemsCount-1] = undefined;
		this.itemsCount = newItemsCount;
	}
}

JSPGC.prototype.getItemIdxById = function (itemId) {
	var itemIdx;
	for(var i=0; i<this.itemsCount; i++) {
		if(this.items[i] && this.items[i].obj.ID==itemId) {
			itemIdx = i;
			break;
		}
	}
	return itemIdx;
}

JSPGC.prototype.invalidateItemsAttr = function(itemIdx, Cnt, Attr) {
	JSKitLib.fmap(this.getItems(itemIdx, Cnt), function(item) {
		item[Attr] = undefined;
	});
}

JSPGC.prototype.invalidateItems = function(itemIdx, Cnt) {
	var items = this.getItems(itemIdx, Cnt);
	JSKitLib.fmap(items, function(V,K) {
		items[K] = undefined;
	});
}

JSPGC.prototype.newPage = function (page) {
	var newPage = {invalidVisualization: true, invalidData: true};
	if(page) JSKitLib.fmap(page, function(V,K){ newPage[K] = V; });
	return newPage;
}

JSPGC.prototype.addPage = function (page) {
	this.pages[this.pages.length] = page || this.newPage();
	this.pageCount++;
}

JSPGC.prototype.deletePage = function () {
	delete this.pages[this.pages.length];
	this.pageCount--;
}

JSPGC.prototype.getPages = function (pageIdx, Cnt) {
	return (pageIdx>=0 && Cnt) ? this.pages.slice(pageIdx, pageIdx+Cnt) : [];
}

JSPGC.prototype.getPage = function (pageIdx) {
	var pageArr = this.getPages(pageIdx, 1);
	return (pageArr.length>0) ? pageArr[0] : undefined;
}

JSPGC.prototype.getStartPageItem = function (pageIdx) {
	return pageIdx * this.itemsPerPage;
}

JSPGC.prototype.setPageCount = function (newPageCount, newItemsCount) {
	while(this.pageCount<newPageCount) this.addPage();
	while(this.pageCount-newPageCount>0) this.deletePage();
	this.pageCount = newPageCount;
	this.setItemsCount(newItemsCount);
	if(!newItemsCount && newPageCount) this.setPageAttr(0, 1, {invalidData: false});
}

JSPGC.prototype.getPageAttr = function (pageIdx, Attr) {
	var page = this.getPage(pageIdx);
	return page ? page[Attr] : undefined;
}

JSPGC.prototype.setPageAttr = function (pageIdx, Cnt, Attrs) {
	JSKitLib.fmap(this.getPages(pageIdx, Cnt),
		function(curPage) {
			JSKitLib.fmap(Attrs, function(V,K){ curPage[K] = V }) 
		});
}

JSPGC.prototype.getPageByItemIdx = function(index) {
	return Math.floor(index/this.itemsPerPage);
}

JSPGC.prototype.getPageCntByItemCnt = function(itemCnt) {
	return Math.ceil(itemCnt/this.itemsPerPage);
}

JSPGC.prototype.setPageItems = function (startPage, newData) {
	var pageCount = this.getPageCntByItemCnt(newData.length);
	this.setPageAttr(startPage, pageCount, {invalidData: false, invalidVisualization: true});
	var startItem = this.getStartPageItem(startPage);
	var self = this;
	this.setItems(startItem, newData.length, JSKitLib.fmap(newData, function(C){ return self.newItem({obj: C}); }));
}

JSPGC.prototype.addPageItem = function (item, itemIdx) {
	if(this.pageCount*this.itemsPerPage==this.itemsCount) {
		this.addPage();
		this.setPageAttr(this.pageCount-1, 1, {invalidData: false});
	}
	var idx = (typeof itemIdx == "undefined") ? this.itemsCount : itemIdx;
	this.addItem(item, idx);
	var insertPageIdx = this.getPageByItemIdx(idx);
	this.setPageAttr(insertPageIdx, this.pageCount-insertPageIdx, { invalidVisualization: true});
	for(var i=insertPageIdx+1; i<this.pageCount; i++) {
		if(!this.getPageAttr(i, 'invalidData')) {
			if(!(this.getPageItems(i)[0])) {
				this.setPageAttr(i, 1, {invalidData: true});
			}
		}
	}
}

JSPGC.prototype.deletePageItem = function (itemIdx) {
	var deletePageIdx = this.getPageByItemIdx(itemIdx);
	this.deleteItems(itemIdx, 1);
	this.setPageAttr(deletePageIdx, this.pageCount-deletePageIdx, { invalidVisualization: true});
	for(var i=deletePageIdx; i<this.pageCount-1; i++) {
		if(!this.getPageAttr(i, 'invalidData')) {
			var itemsCnt = this.getPageItemsCnt(i);
			if(!(this.getPageItems(i)[itemsCnt-1])) {
				this.setPageAttr(i, 1, {invalidData: true});
			}
		}
	}
	if((this.pageCount-1)*this.itemsPerPage==this.itemsCount && this.pageCount>1) this.deletePage();
}

JSPGC.prototype.getPageItems = function (pageIdx) {
	var startItem = this.getStartPageItem(pageIdx);
	var itemsCnt = this.getPageItemsCnt(pageIdx);
	return this.getItems(startItem, itemsCnt);
}

JSPGC.prototype.invalidatePagesView = function (pageIdx, Cnt) {
	this.setPageAttr(pageIdx, Cnt, {invalidVisualization: true});
}

JSPGC.prototype.invalidatePages = function (pageIdx, Cnt) {
	for(var i=0; i<Cnt; i++) {
		var startItem = this.getStartPageItem(pageIdx+i);
		var itemsCnt = this.getPageItemsCnt(pageIdx+i);
		this.invalidateItems(startItem, itemsCnt);
	}
	this.setPageAttr(pageIdx, Cnt, {invalidData: true, invalidVisualization: true});
}

JSPGC.prototype.newData = function (newItemsCount, startPage, newData) {
	var newPageCount = this.getPageCntByItemCnt(newItemsCount);
	this.setPageCount(newPageCount || 1, newItemsCount);
	this.setPageItems(startPage, newData);
}

JSPGC.prototype.addNewItem = function (obj, itemId, isPrepend) {
	var item = this.newItem();
	item.obj = obj;
	this.addPageItem(item, itemId ? this.getItemIdxById(itemId) + (isPrepend ? 0 : 1) : undefined);
}

JSPGC.prototype.deleteItem = function (itemId) {
	this.deletePageItem(this.getItemIdxById(itemId));
}

JSPGC.prototype.getPageVisualization = function (pageIdx, cb) {
	var self = this;
	if(pageIdx<0 || pageIdx>=this.pageCount) return cb(undefined);
	var curPage = this.getPage(pageIdx);
	var getPageFunc = function(){ self.getPageVisualization(pageIdx, cb); };
	if(this.getPageAttr(pageIdx, 'invalidData'))
		return this.dataRequest(pageIdx, curPage, cb);
	if(this.getPageAttr(pageIdx, 'invalidVisualization')) {
		curPage.invalidVisualization = false;
		return this.dataVisualizator(this.getStartPageItem(pageIdx), this.getPageItems(pageIdx), curPage, getPageFunc);
	}
	return cb(this.getPage(pageIdx).target, true);
}

JSPGC.prototype.getPageItemsCnt = function(pageIdx) {
	if(pageIdx<0 || pageIdx>=this.pageCount) return 0;
	return (pageIdx==this.pageCount-1 ? (this.itemsCount-pageIdx*this.itemsPerPage) : this.itemsPerPage);
}

JSPGC.prototype.getItemById = function(itemId) {
	var itemsArr = this.getItems(this.getItemIdxById(itemId), 1);
	return (itemsArr.length>0) ? itemsArr[0] : undefined;
}

JSPGC.prototype.getPageByItemId = function(itemId) {
	return this.getPageByItemIdx(this.getItemIdxById(itemId));
}

JSPGC.prototype.getFirstItem = function () {
	if(this.itemsCount) {
		var itemsArr = this.getItems(0, 1);
		return (itemsArr.length>0) ? itemsArr[0] : undefined;
	} else {
		return undefined;
	}
}

JSPGC.prototype.invalidateItemView = function (itemId) {
	var itemIdx = this.getItemIdxById(itemId);
	this.invalidateItemsAttr(itemIdx, 1, 'html');
	var pageIdx = this.getPageByItemIdx(itemIdx);
	this.invalidatePagesView(pageIdx, 1);
}

JSPGC.prototype.invalidate = function () {
	this.invalidatePages(0, this.pageCount);
}



//////////////////// JSRVC
// requestObj
// request: {uri: someuri, param1: val1, param2: val2, ...}
// [transport: ("GET" | "POST")]
// [target: some_DOM_element]
// [variableRequest: [{param1_1: val1_1, param1_2: val1_2, ...},
//			{param2_1: val2_1, param2_2: val2_2,...}, ...]]
// [form: some_form]
// [onreturn: some_callback]
// [randevu : (true | false)]
// [requestId: some request identity]

function JSRVC(requestObj) {
	var s = this;
	s.requestId = requestObj.requestId || s.generateRequestId();
	s.requestsInProgress = 0;
	s.requestsQueue = [];
	s.processRequest(requestObj);
}

JSRVC.prototype.generateRequestId = function() {
	return ((new Date()).valueOf() + Math.random()).toString();
}

JSRVC.prototype.processRequest = function(requestObj) {
	var s = this;
	s.error = undefined;
	if(s.requestsInProgress) {
		s.requestsQueue.push(requestObj);
		return;
	}
	s.requestObj = requestObj;
	if(s.requestObj.pickup && !s.eventCtx) s.eventCtx = JSKW$Events.registerEventCallback(s.eventCtx, function() {s.eventCallback.apply(s, arguments);}, "randevu_answer");
	var req = s.requestObj;
	s.preProcessRequest();
	if(!req.transport)
		req.transport = req.form ? "POST" : s.getRequestTransport();
	req.target = req.target || document.body;
	var onCompleteCB = req.timeout ? function() {
		s.startTimeoutTimer.call(s);
	} : undefined;
	var handlers = {'onload': s.onLoadRequest, 'onreadystatechange': s.onLoadRequest};
	switch(req.transport) {
	case "GET":
		s.processGETRequest(onCompleteCB, handlers);
		break;
	case "POST":
		s.processPOSTRequest(onCompleteCB, handlers);
		break;
	}
}

JSRVC.prototype.preProcessRequest = function() {
	var req = this.requestObj;
	if(!req.request) req.request = {};
	req.request.randevuId = this.requestId;
	if(!req.variableRequest) req.variableRequest = [];
	if(req.pickup) req.request.randevuRnd = Math.random();
}

JSRVC.prototype.calcGetRequest = function() {
	var s = this;
	var req = s.requestObj;
	var reqvar = req.variableRequest;
	var permGETReq = s.serializeRequest(req.request);
	var varGETReq = JSKitLib.fmap(reqvar, function(el, idx){
		return s.serializeRequest(el, '[' + idx + ']');
	});
	return [permGETReq, varGETReq];
}

JSRVC.prototype.getRequestTransport = function() {
	var ser = this.calcGetRequest();
	var permReq = ser[0];
	var varReq = ser[1];
	var firstReqLen = permReq.length +
		(varReq.length>0 ? varReq[0].length : 0);
	var totalReqLen = 0;
	for(var i=0; i<varReq.length; i++)
		totalReqLen += varReq[i].length;
	
	return ((firstReqLen > 1700) || (totalReqLen > 3400) ?
		"POST" : "GET");
}

JSRVC.prototype.startTimeoutTimer = function() {
	var s = this;
	s.timeoutTimer = setTimeout(function() { s.timeoutExpired(); }, s.requestObj.timeout);
}

JSRVC.prototype.timeoutExpired = function() {
	this.error = "timeout";
	this.returnAnswer();
}

JSRVC.prototype.returnAnswer = function(answerData) {
	var s = this;
	answerData = answerData || {};
	if(answerData.script) {
		var script = document.createElement('script');
		script.text = answerData.script;
		this.requestObj.target.appendChild(script);
	}
	if(s.requestObj.onreturn) {
		s.requestObj.onreturn.call(s, s.error || "data", answerData.data);
	}
}

JSRVC.prototype.serializeRequest = function(obj, prefix) {
	return JSKitLib.fmap(obj, function(v, k) {
		return encodeURIComponent(k) + (prefix || '') + "=" + encodeURIComponent(v);
       }).join("&");
}

JSRVC.prototype.setElementAttributes = function(obj, attrs) {
	var s = this;
	if (!obj) return;
	JSKitLib.fmap(attrs, function(v, k) {
		obj[k] = function() { v.call(s, obj) };
	});
}

JSRVC.prototype.runScript = function(src, data, handlers) {
	var script = document.createElement('script');
	this.setElementAttributes(script, handlers);
	script.setAttribute("charset", "utf-8");
	script.setAttribute("src",  src + (data ? '?' + data : ''));
	this.requestsInProgress++;
	this.requestObj.target.appendChild(script);
	this.script = script;
}

JSRVC.prototype.processGETRequest = function(onCompleteCB, handlers) {
	var s = this;
	var ser = s.calcGetRequest();
	var reqperm = ser[0];
	var reqpermlen = reqperm.length;
	var reqvar = ser[1];
	var reqvarlen = reqvar.length;
	var currequest = '';
	for(var i=0; i<reqvarlen; i++) {
		currequest += reqvar[i];
		if(currequest.length + reqpermlen +
			(i+1<reqvarlen ? reqvar[i+1].length : 0) > 2000) {
			s.runScript(s.requestObj.uri,
				reqperm + '&' + currequest, handlers);
			currequest = '';
		}
	}
	if((currequest) || (!reqvarlen))
		s.runScript(s.requestObj.uri,
			reqperm + '&' + currequest, handlers);
	if(onCompleteCB) onCompleteCB();
}

JSRVC.prototype.processPOSTRequest = function(onCompleteCB, handlers) {
	var s = this;
	var req = s.requestObj.request;
	var reqvar = s.requestObj.variableRequest;
	var reqvarlen = s.requestObj.variableRequest.length;
	var createForm = function() {
		var iframe = 'js-ifrm-' + Math.random();
		var div = document.createElement('DIV');
		div.innerHTML = '<iframe id="' +iframe+ '" name="'+iframe+'" width=0 height=0 style="border: none"></iframe>';
		s.requestObj.target.appendChild(div);
		var ifr = div.firstChild;
		var doc = ifr.contentDocument ? ifr.contentDocument : ifr.document;
		var f = doc.createElement('FORM');
		f.doc = doc;
		if(JSKitLib.isIE()) doc.charset = "utf-8";
		f.target = iframe;
		doc.body.appendChild(f);
		return f;
	};
	var getForm = function() {
		return (s.requestObj.form && !reqvarlen) ?
			s.requestObj.form : createForm();
	}
	var fillForm = function(form, obj) {
		form.method  = 'POST';
		form.enctype = "application/x-www-form-urlencoded";
		form.acceptCharset = 'UTF-8';
		form.action  = s.requestObj.uri;
		JSKitLib.fmap(obj, function(v, k) {
			var frmel = (form.doc || document).createElement('INPUT');
			frmel.type = "hidden";
			frmel.name = k;
			frmel.value = v;
			form.appendChild(frmel);
		});
	}
	var postRequest = function(pobj, vobj) {
		var form = getForm();
		fillForm(form, pobj);
		if(vobj) fillForm(form, vobj);
		if (form.target) s.setElementAttributes(document.getElementById(form.target), handlers);
		JSKitLib.fmap(handlers, function(v, k) {
			form[k] = v;
		});
		s.requestsInProgress++;
		form.submit();
	}
	JSKitLib.fmap(reqvar, function(v) {
		postRequest(req, v);
	});
	if(!reqvarlen) postRequest(req);
	if(onCompleteCB) onCompleteCB();
}

JSRVC.prototype.onLoadRequest = function(el) {
	var s = this;
	if(el.readyState && el.readyState != 'loaded'
		&& el.readyState != 'complete') return;
	el.onreadystatechange = el.onload = null;
	if(!s.requestObj.pickup) {
		s.requestObj.checked = true;
		s.requestsInProgress--;
	}
	s.postProcessRequest();
}

JSRVC.prototype.postProcessRequest = function(source, data) {
	var s = this;
	if(s.requestObj.pickup && source!="pickup") return;
	if(s.requestObj.randevu && !s.error && s.requestObj.transport == "POST") {
		s.processRequest({
			'uri': '//js-kit.com/api/server-answer.js',
			'pickup': true,
			'onreturn': s.requestObj.onreturn,
			'target': s.requestObj.target});
		return;
	}
	s.returnAnswer(data);
	if(!s.requestsInProgress) {
		if(s.timeoutTimer) clearTimeout(s.timeoutTimer);
		if(s.requestsQueue.length && !s.error)
			s.processRequest(s.requestsQueue.pop());
	}
}

JSRVC.prototype.eventCallback = function(eventName, randevuId, status, data) {
	if(this.requestId != randevuId) return;
	this.requestsInProgress--;
	if(this.script && this.script.parentNode) {
		this.script.parentNode.removeChild(this.script);
		this.script = undefined;
	}
	switch(status) {
	case "ready":
		if(this.eventCtx) {
			JSKW$Events.invalidateContext(this.eventCtx);
			this.eventCtx = undefined;
		}
		this.postProcessRequest("pickup", data);
		break;
	case "timeout":
		if(this.error) {
			this.returnAnswer(data);
		} else {
			this.processRequest(this.requestObj);
		}
		break;
	}
}

JSRVC.prototype.cancelRequest = function() {
	this.error = 'canceled';
}


/* JavaScript Comment Class */
new JSCC();

/* JSKitGlobal : App is ready */
$JSKitGlobal.setCommentsAppAvailable();

function JSCC(target, extra) {
	this.get = function(id) { return document.getElementById(id); }
	var idName = "js-kit-comments";
	var target = arguments.length ? arguments[0] : this.get(idName);
	if (target && target.jsk$initialized) return;

	this.cr = function(tag) { return document.createElement(tag); }
	var wl = window.location;
	this.uriDomain = (wl.protocol.substr(0, 4) != 'http' ? 'http:' : '')
				+ '//js-kit.com';
	this.uriAvatar = this.uriDomain + '/avatar/';
	this.uriImage = this.uriDomain + '/image/';
	this.uri = this.uriDomain + '/comment';
	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.isStandalone = function() {
		return (this.config.standalone == 'yes');
	}

	this.scoringEnabled = function() {
		return ((this.config.scoring != 'no') && (this.serverOptions.scoring));
	}

	if(target) {
		this.jcaIndex = $JCA.length;
		$JCA.push(this);
		this.labelHTML = target.getAttribute("label");

		var cn = target.childNodes;
		for(var n=0;n < cn.length;n++) 
			this.utmpl[cn[n].className] = JSKitLib.getOuterHTML(cn[n]);
		if(cn.length) target.innerHTML = "";
		target.style.display = "block";
		target.style.visibility = "visible";
		var utsc = this.utmpl['js-singleComment'];
		if(utsc) this.dtComment = utsc;

		// Override
		var jovs = window.JSKit$Override;
		if(jovs) {
		  for(var i = jovs.length-1; i>=0; i--) {
			var fName = jovs[i][0];
			var func = jovs[i][1];
			this[fName] = func;
		  }
		}
	} else {
		if(!document.body)
			alert("Enclose the script in a <BODY></BODY> tag!");
		var els = document.body.getElementsByTagName(idName);
		var oWay = false;
		if(els && els.length) oWay = true;
		else els = document.body.getElementsByTagName("div");
		if(els && els.length) {
			for(var i=0; i < els.length;i++) {
				if(oWay || els[i].className.match(/js-kit-comments/))
					new JSCC(els[i]);
			}
			if($JCA.length) return;
		}
		this.jcaIndex = $JCA.length;
		$JCA.push(this);
		document.write('<div id="'+idName+'"></div>');
		target = this.get(idName);
	}
	target.jsk$initialized = true;
	target.className = idName;
	target.id = "";

	// Handling user configuration settings
	this.config = JSKitLib.readConfig("comments",
		target,
		this.config,
		'path',
		['avatars', 'yes'],
		['standalone', 'no'],
		['scoring', 'yes'],
		['paginate', 50],
		['backwards', this.config.nolc && !this.IM ? 'yes' : 'no'],
		['disabled', 'no'],
		'domain',
		['sort', ['date','karma','name','status','rating']],
		['thread', ['yes','no']],
		'adminBgColor',
		'flashColor',
		'moderate',
		'permalink',
		'skin',
		'noautoexpand',
		['smiles', 'no'],
		['editable', 'no']
	);
	this.uniq = this.config.path;
	this.pathOverride = this.config.path;
	this.config.thread = this.config.nolc && !this.IM ? 'no' : this.config.thread;
	this.config.domain = this.config.moderate || this.config.domain;
	this.config.noautoexpand = this.config.noautoexpand == 'yes';
	if(this.config.paginate <= 0) this.config.paginate = 200;
	if(target.getAttribute('backwards'))
		this.backwards = (this.config.backwards == 'yes');
	else if(target.getAttribute('paginate'))
		this.backwards = !!this.config.paginate;
	else
		this.backwards = !!this.config.nolc && !this.IM;
	this.preq = {
		srt:this.config.sort,
		ord:(this.backwards?'desc':'asc'),
		thr:this.config.thread,
		sp: 1, pn: 5, ps: this.config.paginate };
	if(!this.preq.ps) this.preq.ps = 100;
	this.preq.pn = Math.round(50 / this.preq.ps);
	if(this.preq.pn < 2) this.preq.pn = 2;

	var self = this;
	self.target = target;

	this.runscr = function(url, args) {
		var sc = this.cr("script");
		sc.setAttribute("charset", "utf-8");
		sc.src = url + (args?"?"+args:"");
		this.target.appendChild(sc);
		return false;
	}

	this.server = function(ext, data, ajax, rvcparams) {
		if((self.serverFilter && !self.serverFilter(ext)) || self.config.disabled == 'yes') return;

		// ensure window.location is current (re:blogspot)
		var wl = window.location;
		var prms = JSKitEPB.getAsHash(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);
		prms.ref = JSKitLib.getRef(self);
		if(self.config.moderate) prms.mod = '1';
		var req = { uri: action, request: prms, target: self.target, randevu: !!ajax };
		if (rvcparams) JSKitLib.fmap(rvcparams, function(v, k) { req[k] = v; });
		new JSRVC(req);
	}

	this.getlocation = function() {
		var wh = String(window.location.href);
		var lp = wh.match(/(.*)#JSKTID=(lapc_[0-9a-f]{10})$/);
		return lp ? {href: lp[1], jsktid: lp[2]}: {href: window.location.href, jsktid: ''};
	}

	this.getpages = function(sp, ap) {
		var preq = self.preq;
		if(!sp) sp = preq.sp;
		self.loading = (new Date()).valueOf();

		var loc = self.getlocation();
		var prms = {"jx": self.jcaIndex,
			"gen": self.gen,
			"srt": preq.srt,
			"ord": preq.ord,
			"sp": sp,
			"pn": preq.pn,
			"ps": preq.ps};
		if(loc.jsktid) prms.jsktid=loc.jsktid;
		if(ap) JSKitLib.fmap(ap, function(v,k){ prms[k] = v ;});
		if(preq.thr!='yes') prms.prs='flat';
		self.server("s-data.js", prms);
	}

	var cl = wl.hash.match(/^#(jsid-[0-9]+-?[0-9]*)$/i);
	this.config.comment_location = cl ? cl[1] : undefined;

	this.getpages(undefined, this.config.comment_location ? {'jsid': this.config.comment_location} : undefined);
}

JSKitLib.addCss(''
+ '.js-WelcomePanel { margin: 0px 0px 10px 0px; font: 12px Arial; text-align: left; }'
+ '.js-WelcomePanelBottom { margin: 10px 0px 0px 0px; }'
+ '.js-WelcomePanelTitle { padding-left: 7px; border-bottom: 1px solid #d1bea4; background: #e4d0b3; color: #fff; font: 14px Arial; font-weight: bold; line-height: 21px; }'
+ '.js-WelcomePanelClose { height: 21px; width: 20px; float: right; cursor: pointer; position: relative; top: 7px; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="//js-kit.com/images/welcome/close.png", sizingMethod="crop")' : 'background: no-repeat url(//js-kit.com/images/welcome/close.png);') + ' }'
+ '.js-WelcomePanelContent { padding: 18px 20px; background-color: #fffae4; color: #2e2e30; line-height: 21px; ' + (JSKitLib.isIE() ? 'zoom: 1' : '') + ' }'
+ '.js-WelcomePanelContentBlock a, .js-WelcomePanelContentBlock a:link, .js-WelcomePanelContentBlock a:visited, .js-WelcomePanelContentBlock a:hover, .js-WelcomePanelContentBlock a:active { text-decoration: none; color: #2e2e30; font: 12px Arial; white-space: nowrap; }'
+ '.js-WelcomePanelContentBlock a:hover, .js-WelcomePanelContentBlock a:active { text-decoration: underline; }'
+ '.js-WelcomePanelHeader { font: 16px Arial; font-weight: bold; color: #2e2e30; padding: 0px; ' + (JSKitLib.isIE() ? 'zoom: 1' : '') + ' }'
+ '.js-WelcomePanelContentBlock { float: left; padding-bottom: 5px; ' + (JSKitLib.isIE() ? 'zoom: 1' : '') + '}'
+ '.js-WelcomePanelContentBlock table img { vertical-align: middle; }'
+ '.js-WelcomePanelCtls { float: left; text-align: center; margin-top: 9px; line-height: 15px; }'
+ '.js-WelcomePanelCtls a, .js-WelcomePanelCtls a:active, .js-WelcomePanelCtls a:visited, .js-WelcomePanelCtls a:hover { color: #2e2e30; font: 11px Arial; }'
+ '.js-WelcomePanelArrow { height: 12px; }'
+ JSKitLib.fmap({Info: 'information', Reg: 'pencil', Profile: 'edit_profile', Help: 'help', Custom: 'bullet_wrench', Dashboard: 'dashboard', Twitter: 'twitter', Support: 'support', Widgets: 'widgets', Panel: 'admin_panel' }, function(v, k) {
	var paddingTop = (k == 'Info' || k == 'Reg' ? 4 : 1);
	var paddingLeft = (k == 'Info' || k == 'Reg' ? 23 : 25) - (JSKitLib.isIE() ? 2 : 0);
	return '.js-WelcomeImg' + k + ' { height: 16px; line-height: 16px; padding: ' + paddingTop + 'px 0px 0px ' + paddingLeft + 'px; float: left; ' + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="//js-kit.com/images/welcome/' + v + '.png", sizingMethod="crop");' : 'background: url(//js-kit.com/images/welcome/' + v + '.png) no-repeat left center;') + ' }';
}).join('')
, 'welcome');

// Optionally leave all CSS up to template
if (!window.$JSKitNoCommentCss) {
	JSKitLib.addCss(''
	+ ".js-OldComments { margin-bottom: 1px; clear:both;}"
	+ ".js-LeaveComment { margin: 3pt 0; }"
	+ ".js-CreateComment, .js-EditComment { text-align: left; display: none; }"
	+ ".js-commentInputOpenID, .js-commentOpenID { display: none; }"
	+ ".js-OpenIDError { color: #F00; display: block; max-width: 250px;}"
	+ ".js-CCMore { padding-left: 3px }"
	+ ".js-commentOptions { float: left; }"
	+ ".js-commentPubOptions { float: left; padding: 2px 5px; }"
	+ ".js-commentYahooShareCheckbox { float: left; margin: " + (JSKitLib.isIE() ? "-3px" : "1px") + " 0 0 5px; }"
	+ ".js-commentYahooShareLabel {margin: 1px 3px 0 3px; line-height: 13px; float: left;}"
	+ ".js-commentYahooShareLabelLogo {margin: 1px 0 0 0; float: left; width: 49px; height: 13px; " + (JSKitLib.isIE() ? 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="//js-kit.com/images/yahoo/yoslogo.png", sizingMethod="crop");' : 'background: no-repeat url(//js-kit.com/images/yahoo/yoslogo.png);') + " }"
	+ ".js-commentSubmit { text-align: right; }"
	+ ".js-CreateCommentBg { margin: 1em; padding: 0.5em; border: solid 1px #c0c0c0; text-align: left; float: left; }"
	+ ".js-EditComment .js-CreateCommentBg { float: none; border: none; padding: 0; }"
	+ ".js-CreateCommentArea { -moz-border-radius: 7px; -webkit-border-radius: 7px; padding: 5px 5px 5px 9px; }"
	+ ".js-CommentsArea .js-CreateCommentArea { background-color: #cbcbcb; }"
	+ ".js-OldComments { background-color: transparent; }"
	+ ".js-CreateCommentFieldsWrap { margin-left: -4px; background-color: #ececec; border: solid 1px #b0b0b0; padding: 4px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }"
	+ '.js-CreateCommentFields {zoom: 1; color: #404040; background-color: #f8f8f8; padding: 4px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }'
	+ ".js-PageNavTop { margin-bottom: 3px; }"
	+ ".js-PageNavBottom { margin-top: 3px; }"
	+ ".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-commentOpenID { margin-top: 5px; }"
	+ ".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-commentOpenIDURL { margin-left: 3px; padding-left: 19px; min-height: 16px; background: url('//js-kit.com/images/openid-16x16.png') no-repeat 0 -2px; font-weight: bold; }"
	+ ".js-commentFieldNote { font-family: Verdana; font-size: 7pt; color: #808080; }"
	+ ".js-siteAdmin { font-weight: bold; }"
	+ ".js-singleComment { zoom: 1; font-size: 8pt; font-family: Verdana, Helvetica; border: solid 1px #c0c0c0; text-align: left; margin-bottom: -1px; }"
	+ ".js-singleCommentBg { zoom: 1; padding: 0.3em; position: relative; }"
	+ '.js-singleCommentHeader { color: #484848; margin: 3px 0; }'
	+ '.js-singleCommentBody { clear: both; color: #404040; background-color: #fefefe; padding: 4px 4px 4px 8px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }'
	+ 'table.js-singleCommentBodyT { margin: 0; padding: 0; font-family: Verdana, Helvetica; text-align: left; font-size: 8pt; color: #404040; }'
	+ '.js-singleCommentQuote { position:relative; top: 4px; font-family: "Times New Roman"; font-size: 32px; line-height: 24px; padding-right: 1px; display: none; }'
	+ ".js-singleCommentINFO { color: #808080; float: right; padding: 3px; margin-left: 2em; text-align: right;}"
	+ ".js-singleCommentAvatar { float: right; }"
	+ ".js-singleCommentText { padding-top: " + (JSKitLib.isIE()?"0":"4") + "px; }"
	+ ".js-singleCommentName { font-weight: bold; }"
	+ ".js-singleCommentDate { font-size: 7pt; }"
	+ ".js-singleCommentOrigin { position: absolute; display: none; bottom: 0.3em; font-size: 7pt; color: #808080; }"
	+ ".js-singleCommentKarmaComMod { clear: both; }"
	+ ".js-singleCommentKarma { float: left; font-size: 7pt; color: #808080; margin-right: 1em; padding-top: 3px; }"
	+ ".js-singleCommentKarmaShow { float: left; font-size: 7pt; color: #808080; margin-right: 2em; padding-top: 3px; display: none; }"
	+ ".js-singleCommentKarmaScore { display: none; }"
	+ ".js-singleCommentComMod { float: left; font-size: 7pt; color: #808080; display: none; padding-top: 3px; margin-right: 1em; }"
	+ ".js-singleCommentCtls { float: right; white-space: nowrap; }"
	+ 'div.js-singleCommentEdit { font-size: 8pt; background: url(http://js-kit.com/images/button-clear.gif) no-repeat; width: 72px; height: 16px; line-height: 9px; text-align: center; color: #404040; padding-top: 2px; float: left; cursor: pointer; margin: 0 0.5em 0 4px; }'
	+ 'div.js-singleCommentReply { font-size: 8pt; background: url(http://js-kit.com/images/button-clear.gif) no-repeat; width: 72px; height: 16px; line-height: 9px; text-align: center; color: #404040; padding-top: 2px; float: left; cursor: pointer; margin: 0 0.5em 0 4px; }'
	+ 'div.js-singleCommentDelete { font-size: 8pt; background: url(http://js-kit.com/images/button-clear.gif) no-repeat; width: 72px; height: 16px; line-height: 9px; text-align: center; color: #404040; padding-top: 2px; float: left; cursor: pointer; margin: 0 0.5em 0 4px; }'
	+ 'div.js-singleCommentModerate { font-size: 8pt; background: url(http://js-kit.com/images/button-clear.gif) no-repeat; width: 72px; height: 16px; line-height: 9px; text-align: center; color: #404040; padding-top: 2px; float: left; cursor: pointer; margin: 0 0.5em 0 4px; }'
	+ ".js-singleCommentNotice { color: #ff0000; font-size: 8pt; }"
	+ ".js-commentControl { float: left; margin-right: 2em; }"
	+ '.js-commentFieldInput { border: solid 1px #7f99b9; width:' +(JSKitLib.isPreIE7()?'98%':'100%')+';}'
	+ '.js-commentFieldInputProfile { border: solid 1px #7f99b9; width:' +(JSKitLib.isIE()?'98%':'100%')+' !important;}'
	+ ".js-CmtButton { margin-right: 0.5em }"
	+ ".js-CCButtons { margin: 0.3em 0 0.5em 0 }"
	+ ".js-CCButtons INPUT { font-size: 8pt; }"
	+ ".js-poweredBy { margin-top: 2pt; margin-right: 2pt; color: #808080; font-size: 7pt; font-family: Verdana, Helvetica; }"
	+ ".js-poweredBy A { text-decoration: none; color: #8080a0 }"
	+ ".js-antispamBy { text-align: right; }"
	+ ".js-Progress { position: absolute; visibility: hidden; right: 5px; top: 5px; width: 15px; height: 15px; }"
	+ ".js-SettingsWindow { padding: 0.3em; border: solid 1px #cccccc; color: #404040; white-space: normal; font-family: Verdana, Helvetica; font-size: small; z-index: 400; }"
	+ ".js-SettingsWindowNolc { z-index: 14400 }"
	+ ".js-SettingsWindowHeader { text-align:center; padding: 5px 0; margin-bottom: 5px; background-color: #e6e9ec; font-size: 10pt; font-family: Verdana, Helvetica; color: #435362}"
	+ ".js-ControlBlockText, .js-ControlBlockTextDisabled {font-size: 8pt; text-align: left;}"
	+ ".js-ControlBlockButton {font-size: 8pt;}"
	+ ".js-ControlBlockTextDisabled {color: #808080}"
        + ".js-showBorder {border:ridge 2px #a0a0a0;}"
	+ ".js-hideBorder {border:solid 2px #fefefe;}"
	+ ".js-SearchTitle {margin-right: 5px;}"
	+ ".js-SearchWords {padding: 0px; margin-right: 5px; border-bottom: 1px dashed #0000ff}"
	+ ".js-uploadAvatarForm {margin-top: 0px;}"
	+ ".js-singleCommentConversationHead {padding: 0.3em; " + (JSKitLib.isIE() ? "margin-top: 36px !important;" : "margin-top: 26px !important;") + "}"
	+ ".js-singleCommentConversationChild {padding: 0.3em; margin-top: -1px !important}"
	+ ".js-Conversation {padding: 0.3em; position: relative; top: -20px; display: inline; }"
	+ ".js-ConversationWrapper { height: 0px; " + (JSKitLib.isIE() ? "overflow: hidden;" : "") + "}"
	+ ".js-TornPageTop { margin-left: -5px; margin-right: -5px; " + (JSKitLib.isIE() ? "" : "height: 11px; margin-top: -5px; background: url(//js-kit.com/images/tornPaperT.gif) no-repeat;") + " }"
	+ ".js-TornPageBottom { margin-left: -5px; margin-right: -5px; " + (JSKitLib.isIE() ? "" : "height: 11px; margin-bottom: -5px; background: url(//js-kit.com/images/tornPaperB.gif) no-repeat;") + " }"
	+ ".js-TornPageTopImg { margin-top: -5px; height: 11px; width: 100%; }"
	+ ".js-TornPageBottomImg { margin-bottom: -5px; height: 11px; width: 100%; }"
	+ ".js-TornPageDivider { margin-left: -5px; margin-right: -5px;" + (JSKitLib.isPreIE7()?"":"margin-bottom: -1px;") + " height: 22px; background-color: #CBCBCB; }"
	+ ".js-TornPageDividerTop { height: 10px; background-color: #ECECEC; border: solid 1px #b0b0b0; border-top-width: 0; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; margin-bottom: 6px; }"
	+ ".js-TornPageDividerBottom { height: 10px; background-color: #ECECEC; border: solid 1px #b0b0b0; border-bottom-width: 0; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; }"
	+ ".js-commentBodyLabel { clear: both; }"
        + ".js-CreateCommentFieldsBaseInfo { float: right; margin-bottom : 5px; width: 100%; }"
	+ ".js-commentCmtTextarea { clear: both; }"
	+ ".js-commentAvatar { position: relative; float: right; margin-left : -102px; }"
	+ ".js-commentAvatarArea { clear: both; margin : 5px 0px 10px 0px; }"
	+ ".js-CmtSpam { background: url(//js-kit.com/images/bio-hazard.gif) bottom right repeat-x; background-color: #ffffe0 !important; color: #404040; }"
	+ (JSKitLib.isIE() ? ".js-CreateComment { zoom: 1; }" : "")
        + ".js-imageWrap { width: 102px; height: 102px; margin-bottom: 3px;}"
        + ".js-previewImageDescr { width: 102px; left: 0px; bottom: 0px; }"
        + ".js-previewImage {position: relative; text-align: center; margin: 4px; float: left; width: 102px; }"

	+ ".js-all-previewImages {position: relative; margin-top: 15px; border-top: 1px solid #ececec; border-bottom: 1px solid #ececec;}"
	+ ".js-uploadImageButton { float: left; color: blue; cursor: pointer; }"
	+ ".js-previewImageTitle { background-color: #ececec; font-size: 7pt; float: left;}"
	+ ".js-uploadImageInputWrapper2 { margin: 0; padding: 0; position: absolute; top: 0px; left 0px;}"
	+ ".js-uploadImageInputWrapper1 {position: relative;}"
	+ ".js-uploadGreyDescr { color: #c0c0c0; }"
	+ ".js-uploadImageIcon { height: 16px; vertical-align: "+(JSKitLib.isSafari()?"sub":"middle")+"; margin-right: 5px; }"
	, 'cmt');
	if(JSKitLib.isOpera()) JSKitLib.addCss("wbr:after{content:\"\\00200B\"}", 'wbr');
	else JSKitLib.addCss(".js-singleCommentTEXT{word-wrap:break-word}", 'wbr');

	JSKitLib.addCss(""
	+ ".js-CommentsSkin-smoothgray .js-OldCommentsWrap {zoom:1; margin-bottom: 1px; clear: both; background-color: #cbcbcb; -moz-border-radius: 7px; -webkit-border-radius: 7px; padding: 5px; }"
	+ ".js-CommentsSkin-smoothgray .js-OldComments { "+(JSKitLib.isIE() ? "zoom:1;":"")+" background-color: #ececec; border: solid 1px #b0b0b0; padding: 4px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }"
	+ ".js-CommentsSkin-smoothgray .js-singleComment { border-style: none; margin: 0px; " + (JSKitLib.isIE() ? "zoom:1;" : "") + "; background: transparent; }"
	+ ".js-CommentsSkin-smoothgray .js-PageNOther { font-weight: bold; color: #0066cc; text-decoration: none; } "
	+ ".js-CommentsSkin-smoothgray .js-PageNCur { color: #fe9600; } "
	+ ".js-CommentsSkin-smoothgray .js-OldComments .js-CreateCommentArea { background-color: transparent; }"
	+ ".js-CommentsSkin-smoothgray .js-OldComments .js-singleCommentName { color: #0066cc; }"
	+ ".js-CommentsSkin-smoothgray .js-singleCommentBody { clear: both; color: #404040; background-color: #fefefe; padding: 4px 4px 4px 8px; -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; " + (JSKitLib.isIE() ? "zoom:1;" : "") + "}"
	+ ".js-CommentsSkin-smoothgray .js-singleCommentCtls { float: right; }"
	, "comments-skin-smoothgray");
	JSKitLib.addCss(".js-CommentsSkin-haloscan .js-singleComment { font-size: 11px; font-family: Verdana, Helvetica; border: none; zoom: 0; }"
	+ ".js-CommentsSkin-haloscan .js-singleCommentCtls { float: right; white-space: nowrap; }"
	+ ".js-CommentsSkin-haloscan .js-singleCommentAvatar { padding-bottom: 1em }"
	+ ".js-CommentsSkin-haloscan .js-LeaveComment { text-align: center; }"
	+ ".js-CommentsSkin-haloscan .js-commentControl, .js-CommentsSkin-haloscan .js-commentTool, .js-CommentsSkin-haloscan .js-poweredBy, .js-CommentsSkin-haloscan .js-poweredBy div { display: inline; float: none; }"
	+ ".js-CommentsSkin-haloscan .js-antispamBy { display: block; }"
	+ ".js-CommentsSkin-haloscan .js-CreateCommentBg { width: 30em; margin-top: 1em; margin-left: auto; margin-right: auto; padding: 0.5em; text-align: left; float: none; border: none; }"
	+ ".js-CommentsSkin-haloscan .js-singleCommentBg { padding: 0em }"
	, "comments-skin-haloscan");
}

JSCC.prototype.setDefaultField = function(name,value) {
	var epbval = JSKitEPB.getValue(name);
	this.fieldDfl[name]= epbval == undefined ? value : epbval;
}

JSCC.prototype.addChild = function(to, what) {
	if (typeof(to) != 'object')
		return;

	if(arguments.length == 3 && arguments[2])
		to.insertBefore(what, to.firstChild);
	else
		to.appendChild(what);
}

JSCC.prototype.a = function() {
	var a = this.cr("a");
	a.href = "javascript:void(0);";
	for(var text = '', i = 0; i < arguments.length; i++)
		text += arguments[i];
	a.innerHTML += text;
	return a;
}

JSCC.prototype.text = function(div, text) {
	if(div.tagName == "INPUT") {
		div.value = text;
	} else {
		JSKitLib.removeChildren(div);
		div.appendChild(document.createTextNode(text));
	}
	return div;
}

JSCC.prototype.div = function(id) {
	var div = this.cr("div");
	for(var i = 1; i < arguments.length; i++) {
		var arg = arguments[i];
		switch(typeof(arg)) {
		case "string":
			this.addChild(div, document.createTextNode(arg));
			break;
		case "undefined":
			break;
		default:
		case "object":
			if(!arg) break;
			this.addChild(div, arg);
			break;
		}
	}
	if(id) {
		div.className = id;
		var idText = String(id);
		if(idText.charCodeAt(3) < 91)
			this.TC[idText] = div;
	}
	return div;
}

JSCC.prototype.dtComment
 = '<div class="js-singleComment">'
 + '<div class="js-singleCommentBg">'
 + '<div class="js-singleCommentAvatar"></div>'
 + '<div class="js-singleCommentINFO">'
   + '<div class="js-singleCommentName" style="clear:both">{Name}</div>'
   + '<div class="js-singleCommentDate">{Date}</div>'
 + '</div>'
 + '<div class="js-singleCommentRating" style="display:none;"></div>'
 + '<div class="js-singleCommentText">{Text}</div>'
 + '<div style="clear: both"></div>'
 + '<div class="js-singleCommentNotice">{Notice}</div>'
 + '<div class="js-singleCommentPreviewImage"></div>'
 /* + '<div class="js-singleCommentKarmaComMod">'
     + '<div class="js-singleCommentKarma">{Label:Like this comment?}'
         + ' [<a class="js-singleCommentKarmaY">{Label:yes}</a>]'
         + ' [<a class="js-singleCommentKarmaN">{Label:no}</a>]'
     + ' <span class="js-singleCommentKarmaScore">({Label:Score}:'
     + ' <span class="js-singleCommentKarmaValue">0</span> {Label:byVotes}'
     + ' <span class="js-singleCommentKarmaVoters">0</span>)'
     + '</span>'
     + '</div>' */
     + '<div class="js-singleCommentKarmaShow">{Label:Community assigned karma score}:'
     + ' <span class="js-singleCommentKarmaValueShow">0</span> {Label:byVotes}'
     + ' <span class="js-singleCommentKarmaVotersShow">0</span>'
     + '</div>'
     + '<div class="js-singleCommentComMod">'
         + '{Label:Mark as} <a class="js-singleCommentComModMark">{Label:offensive}</a>'
     + '</div>'
   + '<div class="js-singleCommentCtls">'
     + '<span class="js-singleCommentReplyable">[<a class="js-singleCommentReply">{Label:reply}</a>]</span>'
     + '<span class="js-singleCommentDeletable"> [<a class="js-singleCommentDelete">{Label:delete}</a>]</span>'
     + '<span class="js-singleCommentEditable"> [<a class="js-singleCommentEdit">{Label:edit}</a>]</span>'
     + '<span class="js-singleCommentModeratable"> [<a class="js-singleCommentModerate">{Label:moderate}</a>]</span>'
   + '</div>'
 + '<div class="js-singleCommentOrigin"><a href="{link}">{displayPath}</a></div>'
 + '</div>'
 + '<br clear="all" />'
 + '</div>'
 + '</div>'
;

JSCC.prototype.dtComment2
 = '<div class="js-singleComment">'
 + '<div class="js-singleCommentBg">'
 + '<div class="js-singleCommentHeader">'
 + '<div style="float: left;"><span class="js-singleCommentName">{Name}</span> {Label::depth?responde:dice}:</div>'
 + '<div class="js-singleCommentDate" style="float: right;">{Age}</div>'
 + '<div style="clear: both"></div>'
 + '</div>'
 + '<div class="js-singleCommentBody">'
 + '<table border="0" width="100%" cellspacing="0" cellpadding="0" class="js-singleCommentBodyT">'
 + '<tr style="vertical-align: top"><td colspan="2" style="padding-bottom: 8px;">'
 + '<div class="js-singleCommentRating" style="display:none;"></div>'
 + '<div class="js-singleCommentText"><span class="js-singleCommentQuote">&#x201C;</span>{Text}</div>'
 + '<div class="js-singleCommentNotice">{Notice}</div>'
 + '<div class="js-singleCommentPreviewImage"></div>'
 + '</td><td width="{SO:maxAvatarWidth+4}" align="right" rowspan="2">'
 + '<div class="js-singleCommentAvatar"></div>'
 + '</td></tr><tr><td style="vertical-align: bottom">'
    /* + '<div class="js-singleCommentKarma"><span>{Label:Like this comment?}</span>'
         + ' [<a class="js-singleCommentKarmaY">{Label:yes}</a>]'
         + ' [<a class="js-singleCommentKarmaN">{Label:no}</a>]'
     + ' <span class="js-singleCommentKarmaScore">({Label:Score}:'
     + ' <span class="js-singleCommentKarmaValue">0</span> {Label:byVotes}'
     + ' <span class="js-singleCommentKarmaVoters">0</span>)'
     + '</span>'
     + '</div>'*/
     + '<div class="js-singleCommentKarmaShow">{Label:Community assigned karma score}:'
     + ' <span class="js-singleCommentKarmaValueShow">0</span> {Label:byVotes}'
     + ' <span class="js-singleCommentKarmaVotersShow">0</span>'
     + '</div>'
     + '<div class="js-singleCommentComMod">'
         + '{Label:Mark as} <a class="js-singleCommentComModMark">{Label:offensive}</a>'
     + '</div>'
 + '</td><td style="vertical-align: bottom;">'
   + '<div class="js-singleCommentCtls">'
     + '<span class="js-singleCommentReplyable"><div class="js-singleCommentReply">{Label:reply}</div></span>'
     + '<span class="js-singleCommentDeletable"><div class="js-singleCommentDelete">{Label:delete}</div></span>'
     + '<span class="js-singleCommentEditable"><div class="js-singleCommentEdit">{Label:edit}</div></span>'
     + '<span class="js-singleCommentModeratable"><div class="js-singleCommentModerate">{Label:moderate}</div></span>'
   + '</div>'
 + '</td></tr><tr><td colspan="3">'
 + '<div class="js-singleCommentOrigin"><a href="{link}">{displayPath}</a></div>'
 + '</td></tr></table>'
 + '</div>'	// Body
 + '</div>'
 + '</div>'
;

JSCC.prototype.dtComment3
 = '<div class="js-singleComment"><div class="js-singleCommentBg">'
 + '<div class="MessageCell">'
 + '<a name="{ID}"></a>'
 + '<div class="former_p"><div class="js-singleCommentAvatar"></div>'
 + '<span class="js-singleCommentText">{Text}</span><br />'
 + '<span class="byline"><span class="js-singleCommentName">{Name}</span> '
 + '<span class="js-singleCommentEditable">'
 + '<a href="" class="js-singleCommentEdit" title="Edit comment">'
 + '<img src="http://js-kit.com/images/halo-button-edit.png" title="Edit comment" alt="Edit comment" border="0">'
 + '</a>'
 + '</span>'
 + '<span class="js-singleCommentModeratable">'
 + '<a href="" class="js-singleCommentDelete" title="Delete comment">'
 + '<img src="http://js-kit.com/images/halo-button-delete.png" title="Delete comment" alt="Delete comment" border="0">'
 + '</a>'
 + '</span>'
 + ' <span class="js-singleCommentUrl" style="display:none;"><a href="{Url}">Homepage</a> |</span>'
 + '<span class="js-singleCommentDate">{Date}</span> - <span class="js-singleCommentDate">{Time}</span> | <a href="#{ID}" title="Link to this comment">#</a>'
 + '</span></div>'
 + '</div></div><div style="clear: both;"><hr /></div></div>'
;

JSCC.prototype.dtCreate
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentBg">'
 + '<div class="js-commentFieldSubject">{Label:leaveComment}</div>'
 + '<div class="js-AuthAreaWrap"></div>'
 + '<div class="js-commentFieldLabel">{Label:nicknameLabel}</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtName" size="32" maxlength="100"/></div>'
 + '<div class="js-commentInputEmail">'
 + '<div class="js-commentFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtEmail" type="email" SIZE=32 /></div>'
 + '</div>'
 + '<div class="js-commentFieldLabel js-commentRatingDisplay">{Label:ratingLabel}</div>'
 + '<div class="js-commentFieldRating js-commentRatingDisplay"></div>'
 + '<div class="js-commentFieldLabel">{Label:commentLabel}</div>'
 + '<div><textarea class="js-commentFieldInput" name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-commentAvatarArea"></div>'
 + '<div class="js-commentImageArea"></div>'
 + '<div class="js-uploadImageInput"></div>'
 + '<div class="js-CCButtons">'
   + '<input type="submit" name="js-Cmtsubmit" class="js-CmtButton" VALUE="{Label:submit}">'
   + '<input type="reset" name="js-Cmtcancel" class="js-CmtButton" VALUE="{Label:cancel}">'
   + '<span class="js-CCMore">[<a class="js-commentMore">{Label:more}</a>]</span>'
 + '</div>'
 //+ '<div class="js-poweredBy js-antispamBy">(<a href="http://js-kit.com/comments?wow" target="js-kit">Powered by JS-kit</a>)</div>'
 //+ '<div class="js-poweredBy js-antispamBy">(Spam filtering by <a href="http://akismet.com/" target="akismet">Akismet</a>)</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.dtCreate2
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentArea">'
 + '<div class="js-commentFieldSubject" style="margin: 0">{Label:leaveComment}</div>'
 + '<div class="js-CreateCommentFieldsWrap">'
 + '<div class="js-CreateCommentFields">'
 + '<div class="js-commentAvatar"></div>'
 + '<div class="js-CreateCommentFieldsBaseInfo">'
 + '<div class="js-AuthAreaWrap"></div>'
 + '<div class="js-commentInputName">'
 + '<div class="js-commentFieldLabel">{Label:nicknameLabel}</div>'
 + '<div class="js-authContainer"><input class="js-commentFieldInput" name="js-CmtName" size="32" maxlength="100"/></div>'
 + '</div>'
 + '<div class="js-commentInputEmail">'
 + '<div class="js-commentFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div class="js-authContainer"><input class="js-commentFieldInput" name="js-CmtEmail" type="email" SIZE=32 /></div>'
 + '</div>'
 + '</div>'
 + '<div class="js-commentAvatarArea"></div>'
 + '<div class="js-commentFieldLabel js-commentRatingDisplay">{Label:ratingLabel}</div>'
 + '<div class="js-commentFieldRating js-commentRatingDisplay"></div>'
 + '<div class="js-commentFieldLabel js-commentBodyLabel">{Label:commentLabel}</div>'
 + '<div class="js-commentCmtTextarea"><textarea class="js-commentFieldInput" name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-commentImageArea"></div>'
 + '</div>' // Fields
 + '<div class="js-CCButtons">'
   + '<div class="js-uploadImageButton">'
    + '<img class="js-uploadImageIcon" src="//js-kit.com/images/picture_add.png"></img>{Label:addPicText}'
   + '</div>'
   + '<div class="js-commentPubOptions"></div>'
   + '<div class="js-commentOptions"><input type="button" class="js-commentMore" value="{Label:optionsD}" less="{Label:optionsU}" more="{Label:optionsD}"></input></div>'
   + '<div class="js-commentSubmit">'
   + '<input type="reset" name="js-Cmtcancel" class="js-CmtButton" VALUE="{Label:cancel}">'
   + '<input type="submit" name="js-Cmtsubmit" class="js-CmtButton" VALUE="{Label:submit}">'
 + '</div>'
 + '<div style="clear: both"></div>'
 + '</div>'
 + '<div class="js-uploadImageInputWrapper1">'
   + '<div class="js-uploadImageInputWrapper2">'
     + '<div class="js-uploadImageInput"></div>'
   + '</div>'
 + '</div>'
 //+ '<div class="js-poweredBy js-antispamBy">(<a href="http://js-kit.com/comments?wow" target="js-kit">Powered by JS-kit</a>)</div>'
 //+ '<div class="js-poweredBy js-antispamBy">(Spam filtering by <a href="http://akismet.com/" target="akismet">Akismet</a>)</div>'
 + '</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.dtCreate3
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentBg">'
 + '<div class="js-commentFieldSubject">{Label:leaveComment}</div>'
 + '<div class="js-AuthAreaWrap"></div>'
 + '<div class="js-commentFieldLabel">{Label:nicknameLabel}</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtName" size="32" maxlength="100"/></div>'
 + '<div class="js-commentInputEmail">'
 + '<div class="js-commentFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtEmail" type="email" SIZE=32 /></div>'
 + '</div>'
 + '<div class="js-commentFieldLabel">URL:</div>'
 + '<div><input class="js-commentFieldInput" name="js-CmtUrl" SIZE=32 /></div>'
 + '<div class="js-commentFieldLabel js-commentRatingDisplay">{Label:ratingLabel}</div>'
 + '<div class="js-commentFieldRating js-commentRatingDisplay"></div>'
 + '<div class="js-commentFieldLabel">{Label:commentLabel}</div>'
 + '<div><textarea class="js-commentFieldInput" name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-commentAvatarArea"></div>'
 + '<div class="js-CCButtons"><input type="submit" name="js-Cmtsubmit" class="js-CmtButton" VALUE="{Label:submit}">'
 + '<input type="reset" name="js-Cmtcancel" class="js-CmtButton" VALUE="{Label:cancel}">'
 + '<span class="js-CCMore">[<a class="js-commentMore">{Label:more}</a>]</span>'
 + '</div>'
 //+ '<div class="js-poweredBy js-antispamBy">(<a href="http://js-kit.com/comments?wow" target="js-kit">Powered by JS-kit</a>)</div>'
 //+ '<div class="js-poweredBy js-antispamBy">(Spam filtering by <a href="http://akismet.com/" target="akismet">Akismet</a>)</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.dtProfileCreate
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentArea">'
 + '<div class="js-commentFieldSubject" style="margin: 0">{Label:leaveComment}</div>'
 + '<div class="js-CreateCommentFieldsWrap">'
 + '<div class="js-CreateCommentFields">'
 + '<div class="js-AuthAreaWrap"></div>'
 + '<div class="js-pmFieldLabel">{Label:nicknameLabel}</div>'
 + '<div><input class="js-commentFieldInputProfile" name="js-CmtName" size="32" maxlength="100"/></div>'
 + '<div>'
 + '<div class="js-pmFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div><input class="js-commentFieldInputProfile" name="js-CmtEmail" type="email" SIZE=32 /></div>'
 + '</div>'
 + '<div class="js-pmFieldLabel">{Label:commentLabel}</div>'
 + '<div><textarea class="js-commentFieldInputProfile" name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '</div>' // Fields
 + '<div class="js-CCButtons">'
 + '<div class="js-commentSubmit">'
 + '<input type="reset" name="js-Cmtcancel" class="js-CmtButton" VALUE="{Label:cancel}">'
 + '<input type="submit" name="js-Cmtsubmit" class="js-CmtButton" VALUE="{Label:submitPM}">'
 + '</div>'
 + '<div style="clear: both"></div>'
 + '</div>'
 + '</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.dtEditComment
 = '<div class="js-EditComment" style="display: none">'
 + '<div class="js-CreateCommentBg">'
 + '<div><textarea name="js-CmtTextEdit" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-CCButtons"><input type="submit" name="js-CmtsubmitEdit" class="js-CmtButton" VALUE="{Label:save}">'
 + '<input type="reset" name="js-CmtcancelEdit" class="js-CmtButton" VALUE="{Label:cancel}">'
 + '</div></div></div>'
;

JSCC.prototype.dtEditComment2
 = '<div class="js-EditComment" style="display: none">'
 + '<div class="js-CreateCommentArea">'
 + '<div class="js-CreateCommentFieldsWrap">'
 + '<div><textarea class="js-commentFieldInput" name="js-CmtTextEdit" ROWS=4 COLS=32></textarea></div>'
 + '<div class="js-CCButtons">'
 + '<div class="js-commentSubmit">'
 + '<input type="reset" name="js-CmtcancelEdit" class="js-CmtButton" VALUE="{Label:cancel}">'
 + '<input type="submit" name="js-CmtsubmitEdit" class="js-CmtButton" VALUE="{Label:save}">'
 + '</div>'
 + '<div style="clear: both"></div>'
 + '</div></div></div></div>'
;

JSCC.prototype.dtConversation
 = '<div class="js-ConversationWrapper">'
 + '<div class="js-Conversation">'
 + '{Label}<span class="js-ConversationName"><b>{Name}</b></span>'
 + '</div>'
 + '</div>'
;

JSCC.prototype.localDate = function(t) {
	if(!t) return "";
	var d = new Date(t * 1000);
	return d.toLocaleDateString();
}

JSCC.prototype.localTime = function(t) {
	if(!t) return "";
	var d = new Date(t * 1000);
	return d.toLocaleTimeString();
}

JSCC.prototype.localAge = function(t) {
	if(!t) return "";
	if(t)
	var d = new Date(t * 1000);
	var offset = d.getTimezoneOffset() * 60;
	var day = Math.ceil(((new Date()).valueOf() - offset * 1000) / 86400000) * 86400;
	var when = Math.floor((day - t + offset) / 86400);
	switch(when) {
	case 0: when = $JCL("Hoy"); break;
	case 1: when = $JCL("Ayer"); break;
	default:
		if(when > 0 && when < 6)
			when = when + $JCL(" dias atras");
		else
			when = d.toLocaleDateString();
	}
	return when + ", " + d.toLocaleTimeString();
}

JSCC.prototype.JCL = function(v) {
	return $JCL(
		(v == 'leaveComment') ? (this.labelHTML || v) : v
	);
}

JSCC.prototype.gtmpl = function(t, mObj) {
	var s = this;
	var lowercase = function(a, m) { return String(m).toLowerCase(); }
	t = t.replace(/^[^<]*(<[\s\S]*>)[^>]*$/, "$1");
	t = t.replace(/(<[\/]?[A-Z]+)/g, lowercase);
	if(mObj && mObj.ID) t = t.replace(/(<[a-z]+)/, '$1 id="' + mObj.ID + '"');
	t = t.replace(/{Label:([^:}]+[^}]*)}/g,
		function(a, m) { return s.JCL(m); });
	return t;
}
JSCC.prototype.tmpl = function(t, obj, dontPutId) {
	var self = this;
	t = self.gtmpl(t, dontPutId ? false : obj);
	t = t.replace(/{Age}/g, self.localAge(obj.TS));
	t = t.replace(/{Date}/g, self.localDate(obj.TS));
	t = t.replace(/{Time}/g, self.localTime(obj.TS));
	var text = String(obj.Text);
	if ((obj.status == 'M' || obj.status == 'H')
		&& (this.serverOptions.mmode == 'pre' || this.serverOptions.mmode == 'onhold' || (obj.msgtype && obj.msgtype.match(/T|P/)))) {
		text += (this.serverOptions.mtext || '');
	}
	text = text.replace(/^[ \s]+|[ \s]+$/, '');
	text = text.replace(/\n\n+/g, '\n\n');
	text = text.replace(/\n/g, '&nbsp;<br />');
	if(text.indexOf('<') == -1)
	text = text.replace(/([^&<>\s]{12})([^&<>\s]{12})/g, '$1<wbr></wbr>$2');
	text = text.replace(/{/g, '&#123;');
	t = t.replace(/{Text}/g, text);
	t = t.replace(/{Label:(:([a-z]+)\?([^:}]*):([^}]*))?([^}]*)}/g,
		function(a,b,p,f,s,m){
			if(p) m = (obj[p]?f:s)+m;
			return $JCL(m);
		});
	var d = {"SO:":this.serverOptions,"":obj};
	t = t.replace(/{([A-Z]+:)?([A-Za-z0-9]+)(\+\d+)?}/g,
		function(a,t,m,p){ var v = ((d[t]||obj)[m])||''; if(p) v = parseInt(v) + parseInt(p); return v; });
	return t;
}

JSCC.prototype.FRef = function(cmt, tgt, funcName) {
	if(!cmt || !tgt) return;

	var self = this;
	var args = arguments;

	tgt.href = "";
	tgt.onclick = function() {
	  try {
		var arr = [];
		if(cmt) arr.push(cmt.id);
		for(var i = 3; i < args.length; i++) arr.push(args[i]);
		self[funcName].apply(self, arr);
	  } catch(e) { ; }
		return false;
	}
}
JSCC.prototype.setCommentStyle = function(cmt, className) {
	var el = cmt.ctls['js-singleCommentBody'] || cmt;
	if(el) JSKitLib.addClass(el,className);
}

JSCC.prototype.cmtSetSpamStatus = function(cmt, s) {
	cmt.cobj.status = s ? 'S' : 'A';
	if(s) {
		this.setCommentStyle(cmt, "js-CmtSpam");
	} else {
		cmt.style.backgroundColor = "";
		cmt.style.backgroundImage = "";
		cmt.style.color = '';
	}
	if(cmt.domINFO) cmt.domINFO.style.backgroundColor = s ? '#ffffe0' : "";
}

JSCC.prototype.cmtSetOffensiveStatus = function(cmt, s) {
	cmt.cobj.status = s ? 'O' : 'A';
	if(s) {
		this.setCommentStyle(cmt, "js-CmtSpam");
	} else {
		cmt.style.backgroundColor = "";
		cmt.style.backgroundImage = "";
		cmt.style.color = '';
	}
	if(cmt.domINFO) cmt.domINFO.style.backgroundColor = s ? '#ffffe0' : "";
}

JSCC.prototype.blockAction = function(action) {
	var s = this;
	var cid = s.ctBlock.forId;
	var cmt = s.jspg.getItemById(cid).div;
	s.hideSettingsWindow('ctBlock');
	switch(action) {
	case "approve":
		s.cmtApprove(cid);
		break;
	case "approveuser":
		s.cmtApproveUser(cid);
		break;
	case "delete":
		s.cmtDelete(cid, 'delete');
		break;
	case "spam":
		s.cmtSetSpamStatus(cmt, true);
		if(s.config.moderate)
			s.pathOverride = cmt.cobj.path;
		s.server('.jnk',{'id': cid, 'jx': this.jcaIndex, "junk": "yes"});
		setTimeout(function() { // screen del
			s.cmtDelete(cid, 'ignore');
		}, 1000);
		break;
	case "ip":
	case "user":
		if(s.config.moderate)
			s.pathOverride = cmt.cobj.path;
		s.cmtDelete(cid, 'block_by_action', action);
		break;
	case "unban":
		if(s.config.moderate)
			s.pathOverride = cmt.cobj.path;
		s.cmtDelete(cid, action);
	}
}

JSCC.prototype.cmtBlock = function(cid) {
	var s = this;
	var cmt = s.jspg.getItemById(cid).div;
	var status = cmt.cobj.status;
	var msgtype = cmt.cobj.msgtype || '';
	var cmtreason;
	if (status && status=='S' && cmt.cobj.reason) {
		switch (cmt.cobj.reason) {
		case 'Blocked by User':
		case 'User':
			cmtreason = 'User';
			break;
		case 'IP':
		case 'Blocked by IP':
			cmtreason = 'IP';
			break;
		}
	}
	if(s.ctBlock) { s.hideSettingsWindow('ctBlock'); return; }
	if(!s.blockDom) { s.blockDom = {}; }
	if(!s.blockDom[status]) { s.blockDom[status] = {}; }
	if(!s.blockDom[status][cmtreason]) { var jca = '$JCA[' + s.jcaIndex + '].blockAction';
	var cb = function(a, d) {
		return '" class="js-ControlBlockButton" '+(d ? 'disabled="on"' : '')+'" onclick="this.blur();'+jca+"('"+a+'\');return false;" /></span></td></tr>';}
	var trth =  '<tr><td style="font-size: 9pt; background-color: #8192a2; color: #ffffff;"align=left><nobr>';
	var trtd = '</nobr></td></tr><tr><td class="js-ControlBlockText">';
	var trtdd = '</nobr></td></tr><tr><td class="js-ControlBlockTextDisabled">';
	var tinp = '<span style="float:right"><input type=submit value="';

	var mtrt = trtd, aumsg, ammsg;
	switch(status) {
	case 'A':
		mtrt = trtdd;
		aumsg = "This user has a trusted status";
		ammsg = "The message is not blocked";
		break;
	case 'S':
		aumsg = "Approve this and future messages from this user";
		ammsg = "This message is not spam or junk";
		break;
	case 'O':
		aumsg = "Approve this message";
		ammsg = "This message is not spam or junk";
	default: // M/H
		aumsg = "Approve future messages from this user";
		ammsg = "Accept this message as good";
	}

	var unbantext = trth + 'Unblock this commenter'
		+ trtd + 'Lift ban from this user/IP'
		+ tinp + 'Unban User'+cb('unban');

	s.blockDom[status][cmtreason] = JSKitLib.html('<table border="0" cellpadding="4" cellspacing="0">'
	+ (s.serverOptions.mmode != 'onhold' ? '' : (
		trth + 'Approve user' + trtd + aumsg
		+ tinp + 'Approve user' + cb('approveuser')))
	+ trth + 'Approve message'
	+ mtrt + ammsg
	+ tinp + 'Approve message' + cb('approve')
	+ trth + 'Delete unwanted comment'
	+ trtd + 'Get rid of comment without prejudice'
	+ tinp + 'Delete' + cb('delete')
	+ ((cmtreason == 'User' || cmtreason == 'IP') ?
		'' :
		trth + 'Flag as Spam or Junk'
		+ trtd + 'Train <a href="http://akismet.com">Akismet</a> to flag similar comments in the future'
		+ tinp + 'Spam/Junk' + cb('spam'))
	+ ((cmtreason == 'User') ?
		unbantext
		: trth + 'Block this commenter'
		+ trtd + 'Make comments from this user invisible to other users'
		+ tinp + 'Block User'+cb('user'))
	+ ((cmtreason == 'IP') ?
		unbantext
		: trth + 'Block commenter\'s IP'
		+ trtd + 'Make comments from this IP invisible to other users'
		+ tinp + 'Block IP'+cb('ip'))
	+ "</table>");
	}
	s.settingsWindow('ctBlock', cmt.domCtls || cmt.domINFO, s.blockDom[status][cmtreason]);
	s.ctBlock.forId = cid;
}
JSCC.prototype.cmtApprove = function(cid) {
	var cmt = this.jspg.getItemById(cid).div;
	if(cmt.cobj.status == 'S') {
		this.cmtSetSpamStatus(cmt, false);
		cmt.cobj.status = 'S'; // cmtDelete's deal
	}
	if(cmt.cobj.status == 'O') {
		this.cmtSetOffensiveStatus(cmt, false);
		cmt.cobj.status = 'O';
	}
	this.cmtDelete(cid, 'message');
}

JSCC.prototype.cmtApproveUser = function(cid) {
	var cmt = this.jspg.getItemById(cid).div;
	if(cmt.cobj.status == 'S') {
		this.cmtSetSpamStatus(cmt, false);
		cmt.cobj.status = 'S'; // cmtDelete's deal
	}
	this.cmtDelete(cid, 'user');
}

JSCC.prototype.routeMsg = function(fname, args) {
	var myRef = JSKitLib.getRef(this);
	var a = [this];
	var rtShared = {};
	for(var i = 0; i < $JCA.length; i++) {
		if($JCA[i].jcaIndex != this.jcaIndex
		&& JSKitLib.getRef($JCA[i]) == myRef &&
		!this.IM && !$JCA[i].IM)
			a.push($JCA[i]);
	}
	for(var i = 0; i < a.length; i++) {
		var e = a[i];
		e.rtShared = rtShared;
		if(i) e.serverFilter = function(n) {
			return (n == 's-data.js'); }
		e[fname].apply(e, args);
		delete e.serverFilter;
	}
}

JSCC.prototype.cmtDelete = function(cid, approvalMode) {
	this.routeMsg("cmtDeleteAct", arguments);
}

JSCC.prototype.cmtDeleteAct = function(cid, approvalMode, action) {
	var cmt = this.jspg.getItemById(cid).div;
	if(!cmt) {
		(this.objById[cid]||{}).status = 'D';
		this.jspg.deleteItem(cid);
		this.reCalcPages();
		return;
	}

	if(arguments.length == 1) approvalMode = 'delete';

	var oldStatus = cmt.cobj.status;
    
	if(this.config.moderate || (this.config.nolc && !this.IM))
		this.pathOverride = cmt.cobj.path;
	if(this.config.nolc && !this.IM)
		this.config.domain = cmt.cobj.domain;
	var prms = {'id': cid, 'jx': this.jcaIndex};
	if(this.inlineModeration) prms.inln = 1;
	switch(approvalMode) {
	case 'message':
		if(this.config.permalink) prms.permalink = this.config.permalink;
		if (!this.inlineModeration) {
			this.preHandlerDelete(cmt);
		}
		if(oldStatus == 'S') {
			prms.junk = 'no';
			this.server('.jnk', prms);
			cmt.cobj.action = 'unban';
		} else if(oldStatus == 'O') {
			this.server('-appr.cgi', prms);
		} else {
			prms.apr = 'message';
			this.server('.del', prms);
		}
		if (this.inlineModeration) this.postHandlerModerate(cid);
		break;
	case 'user':
		if (!this.inlineModeration) {
			this.preHandlerDelete(cmt);
		}
		prms.apr = 'user';
		if(oldStatus == 'S') prms.junk = 'no';
		this.server('.del', prms);
		if (this.inlineModeration) this.postHandlerModerate(cid);
		break;
	case 'delete':
		this.preHandlerDelete(cmt);
		delete prms.inln;
		this.server('.del', prms);
		break;
	case 'block_by_action':
		this.preHandlerDelete(cmt);
		prms.by = action;
		this.server('.blk', prms);
		cmt.cobj.action = 'ban';
		break;
	case 'unban':
		if (!this.inlineModeration) {
			this.preHandlerDelete(cmt);
		}
		if(this.config.permalink) prms.permalink = this.config.permalink;
		prms.unban = 1;
		this.server('-appr.cgi', prms);
		cmt.cobj.action = 'ban';
		if (this.inlineModeration) this.postHandlerModerate(cid);
		break;
	case 'ignore':
		/* Just delete from screen */
	default:
		this.removeComment(cmt, true);
	}
}

JSCC.prototype.preHandlerDelete = function(cmt) {
	JSKW$Events.syncBroadcast("comments_serverRequest_deleting", this.jcaIndex, cmt.cobj.ID);
}

JSCC.prototype.postHandlerDelete = function(cmt) {
	JSKW$Events.syncBroadcast("comments_serverRequest_deleted", this.jcaIndex, cmt.cobj.ID);
}

JSCC.prototype.removeComment = function(cmt, useRecursion) {
	var cobj = cmt.cobj;
	var deletedPageIdx = this.jspg.getPageByItemId(cobj.ID);
	if(cobj.ParentID && this.objById[cobj.ParentID]) {
		var prn = this.objById[cobj.ParentID];
		this.jspg.invalidateItemView(cobj.ParentID);
		var parentPageIdx = this.jspg.getPageByItemId(cobj.ParentID);
		this.jspg.invalidatePagesView(parentPageIdx, deletedPageIdx-parentPageIdx);
	} else {
		if(deletedPageIdx && cobj.ParentID) this.jspg.invalidatePagesView(deletedPageId-1, 1);
	}
	if(cobj.cedge) {
		var curItemIdx = this.jspg.getItemIdxById(cobj.ID);
		if((cobj.cedge==1 && !this.IM && typeof curItemIdx!='undefined') || (cobj.cedge==2 && typeof curItemIdx!='undefined')) {
			var itemIdxD = cobj.cedge==1 ? 1 : -1;
			var items = this.jspg.getItems(curItemIdx+itemIdxD, 1);
			if(items.length && items[0]) items[0].obj.cedge += cobj.cedge;
		}
	}
	var self = this;
	if(this.IM) {
		var cnt = 0;
		var deletedPageItems = this.jspg.getPageItems(deletedPageIdx);
		JSKitLib.fmap(deletedPageItems, function(V){
			if(V.obj.status!='D' && V.obj.status!='DT' && V.obj.conversation==cobj.conversation) cnt++;
		});
		if(cnt>1) {
			if(cmt.cobj.hasCnvs) {
				cmt.cobj.status = 'DT';
				this.jspg.invalidateItemView(cobj.ID);
			} else {
				this.jspg.deleteItem(cmt.cobj.ID);
			}
		} else if(cnt<=1){
			JSKitLib.fmap(deletedPageItems, function(V){
					if(V.obj.conversation==cobj.conversation) self.jspg.deleteItem(V.obj.ID);
			});
		}
	} else {
		this.jspg.deleteItem(cobj.ID);
		this.reCalcPages();
	}
	this.ctag = null;
	var pageNo = this.curPage;
	this.curPage = 0;
	this.displayPage(pageNo, function(immed){
			if(immed) {
				if(useRecursion && this.jspg.getItemById(cmt.cobj.ID)) {
					self.removeComment(cmt);
				}
			}
	});
}

JSCC.prototype.postHandlerModerate = function(cid) {
	var cmt = this.jspg.getItemById(cid).div;
	cmt.cobj.status = 'A';
	this.jspg.invalidateItemView(cid);
	var pageNo = this.curPage;
	this.curPage = 0;
	this.displayPage(pageNo);
}

JSCC.prototype.createCommentAsHTML = function(obj) {
	if(obj.status == 'D') return '';
	if(this.objppc) this.objppc(obj);
	return this.tmpl(this.dtComment, obj);
}

JSCC.prototype.markOffensive = function(cid) {
	var p = confirm($JCL("isJunkVote"));
	if(p) {
		if ((this.adminMode) && (!this.inlineModeration)) {
			this.cmtDelete(cid);
		} else {
			this.server('-mark.off',{'id': cid});
		}
	}
}

JSCC.prototype.showProfile = function(av, obj, profileLevel) {
	if((!obj.profile && !obj.ProfileURL) || !this.serverOptions.showProfile) return;
	if(obj.ProfileURL) {
		window.location = obj.ProfileURL;
		return;
	}
	av.cmtTarget = this.target;
	av.targetRef = JSKitLib.getRef(this);
	if(window.JSKW$Prof) {
		JSKW$openProfile(obj.profile, av, profileLevel);
	} else {
		window.jsk$prof$tgt = av;
		this.server(this.uriDomain + '/api/profile/get',
			{'target': 'jsk$prof$tgt', 'profile': obj.profile});
       }
}

JSCC.prototype.fixComment = function(cmt, obj, pageIdx, globalIdx, itemsOnPage) {
	var self = this;

	self.objById[obj.ID] = obj;
	if(obj.status == 'D') {
		cmt.style.display = 'none';
		return;
	}

	if(obj.depth) {
		cmt.style.marginLeft = this.level4margin(obj.depth)
	} else {
		obj.depth = 0;
	}

	var ctls = JSKitLib.mapClass2Object({}, cmt);
	cmt.ctls = ctls;
	cmt.cobj = obj;
	var imgArea = cmt.ctls["js-singleCommentPreviewImage"];
	if (imgArea && cmt.cobj.imgs && cmt.cobj.imgs.length && self.config.uploadImages){ 
		self.addChild(imgArea,self.createImages(cmt.cobj.imgs));
		imgArea.style.display = "block";
	}

	var jsc = function(t){return ctls['js-singleComment'+t]}

	var stripe = jsc('Body') || jsc('');
	stripe.className += " js-singleCommentDepth" + (obj.depth || 0);
	if(!(cmt.style.display.match(/none/))){
		stripe.className += " js-comment-stripe-" + ((globalIdx % this.stripecount) + 1);
	}

	if(self.IM && typeof(obj.conversation)=='number') {
		if(obj.hasCnvs) {
			this.appendConversation(cmt, obj.conversation);
		} else {
			this.appendConversationChild(cmt);
		}
	}

	/* Handle avatars */
	if(obj.status!='DT' && obj.status!='DD') self.placeAvatar(obj, jsc('Avatar'));

	/* Handle if ratings are present */
	if (obj.Rating > 0 && ( ! this.isStandalone()) ) {
		var self = this;
		var action = function() {
			if (jsc('Rating')) {
				jsc('Rating').appendChild(self.createMiniStarObject(obj.Rating, 10));
				jsc('Rating').style.display = '';
				var clear = document.createElement('div');
				clear.style.clear = 'left';
				jsc('Rating').appendChild(clear);
			}
		}
		$JSKitGlobal.tryRatingsAppObjectAction(this.uniq, action);
	} else {
		if (jsc('Rating')) {
			jsc('Rating').style.display = 'none';
		}
	}

	if (jsc('Url') && obj.Url) { jsc('Url').style.display = ''; }

	var sa = jsc("Name");
	if(sa) {
		self.rerenderName(cmt);
		if(obj.admin) sa.className = sa.className + " js-siteAdmin";
	}
	var pl = jsc("ProfileLinkable");
	if(pl) {
		if(!(obj.profile && !this.config.nolc))
			pl.style.display = 'none';
	}

	if(!this.scoringEnabled()
	|| obj.yours || !obj.karma || (obj.msgtype && obj.msgtype.match(/T|P/) && !this.serverOptions.trackbackreply) || this.config.nolc) {
		var kA = jsc("Karma");
		if(kA) kA.style.display = "none";
	}
	var kS = jsc("KarmaScore");
	if(kS && obj.karma) {
		var kVal = jsc("KarmaValue");
		var kVot = jsc("KarmaVoters");
		if(obj.karma.votes) {
			self.text(kVal, obj.karma.score);
			self.text(kVot, obj.karma.votesText);
			kS.style.display = "inline";
		}
		var kY = jsc("KarmaY");
		if(kY) {
			kY.href = "";
			kY.onclick = function() {
				obj.karma.recomputeScore(1);
				self.text(kVal, obj.karma.score);
				self.text(kVot, obj.karma.votesText);
				kS.style.display = "inline";
				this.blur();
				return false;
			}
		}
		var kN = jsc("KarmaN");
		if(kN) {
			kN.href = "";
			kN.onclick = function() {
				obj.karma.recomputeScore(-1);
				self.text(kVal, obj.karma.score);
				self.text(kVot, obj.karma.votesText);
				kS.style.display = "inline";
				this.blur();
				return false;
			}
		}
	}
	var kSS = jsc("KarmaShow");
	if(kSS && obj.karma && obj.yours && obj.karma.votes) {
		kSS.style.display = "inline";
		var kVal = jsc("KarmaValueShow");
		var kVot = jsc("KarmaVotersShow");
		self.text(kVal, obj.karma.score);
		self.text(kVot, obj.karma.votesText);
	}

	if(this.serverOptions.commod && !obj.yours && !this.config.nolc && (!obj.msgtype || !obj.msgtype.match(/T|P/) || this.serverOptions.trackbackreply)){
		var cmO = jsc("ComMod");
		if(cmO){
			cmO.style.display = "inline";
			cmM = jsc("ComModMark");
			if(cmM) {
				cmM.href = "";
				cmM.onclick = function() {
					self.markOffensive(obj.ID);
					return false;
				}
			}
		}
	}

	if(this.config.nolc || this.config.moderate) {
		var cP = jsc("Origin");
		if(cP) {
			cP.style.display = "inline";
		}
	}
    /* FIXME(?) Lev, this.serverOptions are not defined in moderation mode
       but the result is likely as desired, i.e. admin can still reply */
	if (this.serverOptions.mmode == "pause" || (obj.msgtype && obj.msgtype.match(/T|P/) && !this.serverOptions.trackbackreply) || (this.config.nolc && (!this.IM || obj.yours))) {
		var rb = jsc("Replyable");
		if(rb) rb.style.display = "none";
	}

	this.FRef(cmt, jsc('Edit'), 'ShowCommentDialog', {isEditing: true});
	this.FRef(cmt, jsc("Reply"), "ShowCommentDialog");
	this.FRef(cmt, jsc("Delete"), "cmtDelete");
	this.FRef(cmt, jsc("Block"), "cmtBlock");
	this.FRef(cmt, jsc("Moderate"), "cmtBlock");
	this.FRef(cmt, jsc("Approve"), "cmtApprove");
	this.FRef(cmt, jsc("ApproveUser"), "cmtApproveUser");

	var au = jsc("ApproveUser");
	if (au && this.serverOptions.mmode != "onhold")
		au.style.display = "none";

	var hideCtl = jsc('Editable');
	if (hideCtl && (this.config.editable != 'yes' || this.config.nolc || (!(this.adminMode || JSKitEPB.isAdmin(this.pathOverride)))))
		hideCtl.style.display = 'none';

	var hideCtl = jsc("Deletable");
	if(hideCtl && ((!obj.yours && !this.IM && !JSKitEPB.isAdmin(this.pathOverride)) || (this.adminMode && !this.config.nolc)))
		hideCtl.style.display = "none";

	var hideCtl = jsc("Moderatable");
	if(hideCtl && (!this.adminMode || this.config.nolc))
		hideCtl.style.display = "none";

	cmt.bg = jsc('Bg');
	cmt.bg.style.zIndex = this.czidx - (pageIdx % this.czidx);
	cmt.domINFO = jsc('INFO');
	cmt.domCtls = jsc('Ctls') || jsc('Controls');

	if(obj.isEmbryonic) {
		/* Waiting for permanent ID */
		if(cmt.domCtls) cmt.domCtls.style.visibility = "hidden";
	}

	if(obj.status == 'S')
		this.cmtSetSpamStatus(cmt, true);

	if(obj.status == 'O')
		this.cmtSetOffensiveStatus(cmt, true);

	if(obj.admin) {
		JSKitLib.addClass(cmt, "js-commentByAdmin");
		if(this.config.adminBgColor) {
			cmt.style.backgroundColor = this.config.adminBgColor;
		}
	}

	if(obj.status == 'DT') {
		if(cmt.domINFO) cmt.domINFO.style.display = 'none';
		if(cmt.domCtls) cmt.domCtls.style.display = 'none';
	}
	if(obj.status == 'DD') {
		if(cmt.domCtls) cmt.domCtls.style.display = 'none';
		this.placeProcessAvatar(jsc('Avatar'));
	}
}

JSCC.prototype.level2margin = function(level) {
	if(level < 20) return "10px";
	if(level < 40) return "4px";
	return "0px";
}
JSCC.prototype.level4margin = function(level) {
	if(level <= 20) return (10 * level) + 'px';
	if(level <= 40) return (200 + 4 * level) + 'px';
	return '280px';
}
JSCC.prototype.cmtInDiv = function(div, obj, fincb) {
	JSKW$Events.syncBroadcast("smileys-newCommentInDiv", obj);
	if (!obj.isEditing) {
		var cIdx, insBefore = false;
		if(this.preq.ord == 'desc') {
			var fitem = this.jspg.getFirstItem();
			if(fitem) {
				cIdx = fitem.obj.ID;
				insBefore = true;
			}
		}
		if(this.preq.thr != 'yes') {
			obj.Notice = $JCL('commentMoveNotice');
			cIdx = obj.ParentID || cIdx;
			delete obj.ParentID;
			delete obj.depth;
		}
		obj.cedge = 3;
		if(obj.ParentID) {
			obj.cedge = 0;
			var prn = this.objById[obj.ParentID];
			var td = (prn && prn.depth) ? prn.depth : 0;
			if(prn) {
				if(!obj.depth) {
					prn.thread.push(obj);
					obj.depth = 1 + td;
				}
				if(this.IM && typeof(prn.conversation)=='number') obj.conversation = prn.conversation;
				cIdx = this.getLastReply(obj.ParentID).obj.ID;
				insBefore = false;
				var curItem = this.jspg.getItemById(cIdx);
				if(curItem && curItem.obj.cedge>1) {
					obj.cedge = 2;
					curItem.obj.cedge -= 2; 
					var parentPageIdx = this.jspg.getPageByItemId(obj.ParentID);
					var insertedPageIdx = this.jspg.getPageByItemId(cIdx);
					this.jspg.invalidatePagesView(parentPageIdx, insertedPageIdx-parentPageIdx+1);
				}
			}
		}
	
		if(this.IM) {
			for(var i=0; i<this.conversations.length; i++) {
				if(this.conversations[i].current) {
					obj.conversation = i;
					break;
				}
			}
			if(typeof(obj.conversation)!='number') {
				this.conversations.push({'direction':'out'});
				obj.waitConversation = {cnvsIdx: this.conversations.length-1};
			}
		}
	
		this.jspg.addNewItem(obj, cIdx, insBefore);
	}
	var pn = this.jspg.getPageByItemId(obj.ID);
	var item = this.jspg.getItemById(obj.ID);
	if (obj.isEditing) {
		item.obj.Text = obj.Text;
		item.obj.goesInto = obj.goesInto;
		this.jspg.invalidateItemView(obj.ID);
	}
	if(pn+1==this.curPage) this.curPage = 0;
	var self = this;
	this.displayPage(pn+1, function(immed) {
		if(immed) {
			if(!item.div) {
				self.cmtInDiv(undefined, obj, fincb);
			} else {
				fincb.apply(this, [item.div]);
			}
		}
		delete item.obj.isEditing;
	});
}

JSCC.prototype.setOpacity = function(div, val) {
	if(div) {
		div.style.opacity = val;
		div.style.filter = 'alpha(opacity: ' + Math.round(val * 100) + ')';
	} else {
		if(document.body.filters)
			return 'zoom:1;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=' + Math.round(val * 100) + ');';
		else
			return 'opacity: ' + val + ';';
	}
}

JSCC.prototype.flash = function(cmt) {
	if(!cmt) return;

	var self = this;
	cmt.scrollIntoView(true);
	var bg = cmt.bg;

	try {
		bg.style.backgroundColor = self.config.flashColor || "#ffff00";
		self.setOpacity(bg, 0);
	} catch(e) { return; }

	cmt.cntDown = 3.14 / 2;
	cmt.cntMode = 0;

	cmt.intvl = setInterval(function() {
		cmt.cntDown -= cmt.cntMode ? 0.5 : 0.3;
		if(cmt.cntDown > 0) {
			if(cmt.cntMode)
				var c = Math.sin(cmt.cntDown);
			else
				var c = Math.cos(cmt.cntDown);
			self.setOpacity(bg, c);
		} else if(cmt.cntMode) {
			clearInterval(cmt.intvl);
			cmt.intvl = null;
			bg.style.backgroundColor = "";
			self.setOpacity(bg, 1);
		} else {
			cmt.cntMode = 1;
			cmt.cntDown = 3.14 / 2;
		}
	}, 100);
}

JSCC.prototype.foldInputFields = function(e, acc, f) {
  if(e.getAttribute) {
	var name = e.getAttribute('NAME');
	if(name && (name.substr(0, 6) == 'js-Cmt')) {
		var shortName = name.substr(6);
		acc = f.call(this, e, acc, shortName) || acc;
	}
  }
  var cn = e.childNodes;
  if(cn) {
	var clen = cn.length;
	for(var i = 0; i < clen; i++)
		acc = this.foldInputFields(cn[i], acc, f);
  }
  return acc;
}

JSCC.prototype.inputFieldsMsg = function(ctl, cmtObj, pText) {
	return this.foldInputFields(ctl, [], function(e, a, name){
		var isText = /^Text(Edit)?$/.test(name);
		var text = isText ? pText : e.value;
		if(name == 'OpenID' && this.openID)	// backward-compat.
			text = this.openID;
		a.push({"Name": "js-Cmt" + name, "Value": text});
		if(isText && this.serverOptions.htmlMode)
			text = text.replace(/<[\/]?[a-z]{1,3}(\s+(href)=[^>]+)?>/g, '');
		//text = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
		cmtObj[name] = text;
	});
}

JSCC.prototype.cmtInPlace = function(cobj, fincb) {
	var div = this.TC["js-OldComments"];
	var shar = this.rtShared;
	if(shar) {
		if(shar.goesInto) shar.goesInto.push(this);
		else shar.goesInto = [this];
		cobj.goesInto = shar.goesInto;
	}
	if (!cobj.isEditing) {
		this.tmpID++;
		cobj.ID = "jst-" + this.tmpID;
		cobj.isEmbryonic = true;
	
		cobj.status = 'A';
		if(this.serverOptions.showProfile) cobj.profile = this.serverOptions.profile;
		if(this.avatarsManagement && this.avatarsManagement.chosenAvatar) {	
			var a = this.avatarsManagement.chosenAvatar;
			cobj.avatar = a.name;
			cobj.avatarWidth = a.width;
			cobj.avatarHeight = a.height;
		}
		cobj.thread = [];
		cobj.depth = 0;
		cobj.admin = this.adminMode;
		var d = new Date();
		cobj.TS = Math.round(d.valueOf() / 1000);
	} else {
		cobj.Text = cobj.TextEdit;
		delete cobj.TextEdit;
 	}
	cobj.jcaIndex = this.jcaIndex;
	this.cmtInDiv(div, cobj, function(cmt) {
		if(cmt) this.flash(cmt);
		fincb.apply(this, [cmt]);
	});
}

JSCC.prototype.ShowCommentDialog = function(msgId, extra) {
	msgId = msgId || '';
	this.forMsg = this.objById[msgId];
	extra = extra || {};

	var isReply = !!msgId;
	var cct = this.TC["js-LeaveComment"];

	/* Remove dialog from sight */
	this.CommentCancelled();

	if(this.getSkin()!='smoothgray'){
		this.onAddImgButton(this.imgShow);
	}

	var ccd = this.TC[extra.isEditing ? "js-EditComment" : "js-CreateComment"];
	if (extra.isEditing) {
		this.TC['js-CmtTextEdit'].value = JSKitLib.htmlUnquote(this.forMsg.Text.replace(/<wbr><\/wbr>/g, ''));
		isReply = false;
		if (!this.serverOptions.wysiwyg) {
			JSKW$Events.syncBroadcast("smileys-beforePostNewComment", this.TC['js-CmtTextEdit']);
		}
	}
	this.replyForId = (isReply ? msgId : '');

	var placeDialog = function(immediate, apl) {
		if (!apl) apl = [this.TC["js-CommentsArea"], this.TC["js-CommentsArea"].firstChild];
		if(msgId){
			apl[0].insertBefore(ccd, apl[1]);
		} else if (this.backwards) {
			apl[0].insertBefore(ccd, this.TC['js-WelcomePanel'] ? apl[1].nextSibling : apl[1]);
		} else {
			this.addChild(apl[0], ccd);
		}
		if (extra.isEditing) JSKitLib.hide(apl[1]);

		if(this.backwards && msgId)
			cct.style.visibility = "hidden";
		else
			cct.style.display = "none";
		ccd.style.display = "block";
		try {
			var name_suffix = (extra.isEditing ? 'Edit' : '');
			var text = this.TC["js-CmtText" + name_suffix];
			/* TinyMCE support (A) */
			if(!text.id) text.id = "js-CmtText" + name_suffix + "-" + this.jcaIndex;
			if(!text.richEditor && this.serverOptions.wysiwyg) try {
				var s = this; 
				var addMCECtrl = function(){
					if(s.tmce.foreign) tinyMCE.settings = s.tmce.cfg;
					tinyMCE.execCommand('mceAddControl', false, text.id);
					text.richEditor = true;
					if(text.mceLoadedCtx) {
						JSKW$Events.invalidateContext(text.mceLoadedCtx);
						text.mceLoadedCtx = null;
					}
				}
				if(window.tinyMCE) {
					if(tinyMCE.getInstanceById(text.id) == null) addMCECtrl();
				} else text.mceLoadedCtx = JSKW$Events.registerEventCallback(undefined, addMCECtrl, "mceLoaded");
			} catch(e) {}

			var sub = this.TC["js-Cmtsubmit" + name_suffix];
			var can = this.TC["js-Cmtcancel" + name_suffix];
			var prev = function(e){JSKitLib.stopEventPropagation(e); JSKitLib.preventDefaultEvent(e); return false;}

			if(JSKitLib.isOpera()) {
				var onkey = function(){};
			} else if(JSKitLib.isIE()) {
				var onkey = function(d,f){d.onkeydown=f};
			} else {
				var onkey = function(d,f){d.onkeypress=f};
			}

			/* refresh avatars */
			if (this.avatarsManagement) this.avatarsManagement.refreshAvatars();

			/* combined ratings */
			var commentRatingElements = JSKitLib.getElementsByClass(ccd, "js-commentRatingDisplay");
			var commentRatingDisplay = 'none';
			this.submitRating = false;
			if (this.hasRatingsAppObject() && ( ! isReply)) {
 				if (this.TC["js-commentFieldRating"]) {
 					this.embedRatingsAppObject(this.TC["js-commentFieldRating"]);
 					commentRatingDisplay = '';
					this.submitRating = true;
				}
			}
			for (var i=0; i < commentRatingElements.length; i++) {
				commentRatingElements[i].style.display = commentRatingDisplay;
			}


			var flds = this.foldInputFields(ccd, [],
			function(e, a, name) {
				var dfl = this.fieldDfl[name];
				if(dfl) {
					if(e.jsk$setdfl)
						e.jsk$setdfl(dfl);
					else if(!e.value)
						e.value = dfl;
				}
				var aclen = a.length;
				if(e.richEditor) {
					if (e.value) {
						e.value = e.value.replace(/^\n\n+/, '');
						e.value = e.value.replace(/\n\n+/g, '</p><p>');
						if(!e.value.match(/^<p>(\n|.)*<\/p>$/)) e.value = '<p>' + e.value + '</p>';
					}
					var o = { focus: function() {
						var setupFocusing = function(ed) {
							var focus = function(){tinyMCE.execCommand('mceFocus',false,text.id);};
							var delayFocus = function(){setTimeout(focus, 10)};
							if(!extra.nofocus) {
								if(ed.initialized) focus();
								else ed.onInit.add(delayFocus);
							};
							var keyHandler = function(ed, e) { 
								if(e.keyCode != 9) return true;
								window.focus();
		try {
								a[aclen+(e.shiftKey?-1:1)].focus();
		} catch(ex) { ; }
								return prev(e);
							};
							if (JSKitLib.isIE()) ed.onKeyDown.add(keyHandler); else ed.onKeyPress.add(keyHandler);
						}
						var ed = tinyMCE.getInstanceById(text.id);
						if(ed) {
							setupFocusing(ed);
						} else {
							var t = setInterval(function() {
								var ed = tinyMCE.getInstanceById(text.id);
								if(ed) { clearInterval(t); setupFocusing(ed); }
							}, 100);
						}
					} };
					if(aclen) onkey(a[aclen-1], function(e) { 
						e = e || window.event; 
						if(e.keyCode == 9 && !e.shiftKey) { 
							this.blur();
							o.focus(); 
							return prev(e); 
						}
					});
					a.push(o);
				} else {
					a.push(e);
				}
			});

			var okd = function(offset) { return function(e) {
				e = e || window.event;
				if(e.keyCode != 9) return true;
				this.blur();
				flds[offset+(e.shiftKey?(flds.length-2):0)].focus();
				return prev(e);
			} }

			onkey(flds[flds.length-1], okd(0));
			onkey(flds[0], okd(1));

			// Place initial focus.
			if(!extra.nofocus) {
				for(var i = 0; i < flds.length; i++)
					if(!flds[i].value || flds[i].type == 'submit') {
						flds[i].focus();
						break;
					}
				sub.scrollIntoView(false);
			}
		} catch(e) { }
	};
	if(!msgId) {
		placeDialog.apply(this,[true]);
	} else {
		if (extra.isEditing) {
			var item = this.jspg.getItemById(msgId);
			item.obj.isEditing = true;
			this.editingCmt = item.div.ctls['js-singleCommentText'];
		} else {
			var item = this.getLastReply(msgId);
		}
		var pn = this.jspg.getPageByItemId(item.obj.ID);
		this.displayPage(pn+1, function(immed) {
				if(immed) {
					if (extra.isEditing) {
						placeDialog.apply(this, [true, [this.editingCmt.parentNode, this.editingCmt]]);
					} else {
						var pItem = this.jspg.getItemById(item.obj.ID);
						placeDialog.apply(this, [true, [pItem.div.parentNode, pItem.div.nextSibling]]);
					}
				}
			});
	}
	return false;
}

JSCC.prototype.CommentCancelled = function() {
	if(this.tmce && (this.serverOptions.media || this.serverOptions.smiley)) 
		this.tmce.cfg.closePopups();
	var cct = this.TC["js-LeaveComment"];
	var ccd = [this.TC["js-EditComment"], this.TC["js-CreateComment"]];
	cct.style.visibility = "";
	cct.style.display = "";
	var name_suffix = (this.editingCmt ? 'Edit' : '');
	var text = this.TC["js-CmtText" + name_suffix];
	if(text.richEditor) {
		tinyMCE.execCommand('mceRemoveControl', false, text.id);
		text.richEditor = false;
		if(text.mceLoadedCtx) {
			JSKW$Events.invalidateContext(text.mceLoadedCtx);
			text.mceLoadedCtx = null;
		}
	}
	var s = this;
	JSKitLib.fmap(ccd, function(el, i){
		el.parentNode && el.parentNode.removeChild(el);
	});
	if (this.editingCmt) {
		JSKitLib.show(this.editingCmt);
		delete this.editingCmt;
	}
	return false;
}

JSCC.prototype.smileTag = function(smile) {
	var proto = (/^(http)(.*)/i.test(this.uriDomain) ? '' : 'http:'); 
	return '<img src="' + proto + this.uriDomain + '/extra/tiny_mce/plugins/emotions/img/smiley-' + smile.file + '" title="' + smile.title + '" border="0" alt="' + smile.title + '" />';
}

JSCC.prototype.textSmiles2Graphical = function(text, reverse) {
	var s = this;
	if(window.tinyMCE) tinyMCE.settings.smiley = false;
	var flag = true;
	var orig = text;
	JSKitLib.fmap(s.smiles, function(el, i){
		text = reverse ? text.replace(el.regexpTag, ' ' + i + ' ') : text.replace(el.regexpText, function($0, $1){return ($1 ? $0 : s.smileTag(el));});
		if(window.tinyMCE && flag && (text !== orig)) {
			tinyMCE.settings.smiley = true;
			flag = false;
		}
	});
	return text;
}

JSCC.prototype.CommentSubmitted = function() {
	var prn = this.forMsg;
	var isEditing = prn && prn.isEditing;

	if (!isEditing && !this.TC['js-CmtName'].value) {
		alert($JCL('nicknameRequired'));
		return;
	}
	
	/* TinyMCE support (B) */
	var name_suffix = (isEditing ? 'Edit' : '');
	var text = this.TC["js-CmtText" + name_suffix];
	var textValue;
	if(text.richEditor) {
		tinyMCE.triggerSave(false, false);
		JSKW$Events.syncBroadcast("smileys-beforePostNewComment", text);
		textValue = String(text.value).
                                replace(/(<\/p>)[\r\n]+(<p>)/g, '$1$2').
				replace(/<p>/g, '\n').replace(/<\/p>/g, '').replace(/<br\s?\/?>/g, '\n');
	} else {
		textValue = String(text.value).replace(/&/g, '&amp;');
	}

	var textMsg = encodeURIComponent(textValue);

	if(!textMsg || !textMsg.length) {
		alert($JCL("tooShort"));
		return;
	}

	var mcl = this.serverOptions.maxCommentLength || 3000;
	if(text.value.length > mcl) {
		alert($JCL("tooLong",{"maxCommentLength":mcl}));
		return;
	}

	var form = this.TC[isEditing ? "js-EditComment" : "js-CreateComment"];

        var noavt = (this.avatarsManagement && this.avatarsManagement.chosenAvatar) ? false : true;
        var avt = (this.avatarsManagement) ? this.avatarsManagement.chosenAvatar : null;
	var permalink = this.config.permalink;
	var moderate = this.config.moderate;

	var tmpObj = {yours:true};
	if(prn) {
		if (isEditing) {
			tmpObj.ID = prn.ID;
		} else {
			tmpObj.ParentID = prn.ID;
		}
		tmpObj.path = prn.path;
		if(prn.permalink) {
			tmpObj.permalink = prn.permalink;
			permalink = prn.permalink;
		}
	}

	var message = this.inputFieldsMsg(form, tmpObj, textValue);

	/* combined ratings */
	if (this.submitRating) {
		rating = this.getRatingsAppObject().userRating;
		message.push({'Name': 'js-CmtRating', 'Value': rating});
		tmpObj.Rating = rating;
	}
	if(prn && !isEditing) {
		message.push({'Name': 'js-CmtParentID', 'Value': prn.ID});
		if(this.IM=='own' && prn.profile) {
			message.push({'Name': 'destProfile', 'Value': prn.profile});
		}
	}
	if(permalink) message.push({'Name': 'permalink', 'Value': permalink});
	if (!isEditing) {
		if(noavt) message.push({'Name': 'avatar', 'Value': 'no'});
		if(avt) message.push({'Name': 'avatar', 'Value': avt.name});
	} else {
		tmpObj.isEditing = true;
	}

	if(moderate) this.pathOverride = this.forMsg.path;

	// API: subscriber expects (ConstructedMessageObject[, FormDOM])
	try {
		JSKitAPI.askpublic.call(this, "comment-submit",
			this.getKVListFromMsg(message), form);
	} catch(e) {
		return;
	}
	// Filter out user-defined fields with improper syntax
	message = JSKitLib.filter(function(obj) {
		if(obj.Name.substr(0, 6) != 'js-Cmt'
			|| (obj.Name.charCodeAt(6) > 65
			 && obj.Name.charCodeAt(6) < 90))
			return true;
	}, message);

	this.CommentCancelled();
	this.routeMsg("attachComment",
		[tmpObj, message, textMsg.length > 1700]);

	if (this.TC['js-CmtText' + name_suffix]) {
		this.TC['js-CmtText' + name_suffix].value = '';
	}
	if(this.clearImgs) this.clearImgs();
}

JSCC.prototype.attachComment = function(tmpObj, tmpMsg, longMsg) {
	var s = this;
	var cmtObj = this.cloneObj(tmpObj);
	if(s.images) cmtObj.imgs = s.images;
	var msg = JSKitLib.fmap(tmpMsg, function(e){return e});

	if(cmtObj.ParentID && !this.objById[cmtObj.ParentID]) {
		this.jspg.invalidate();
		return;
	}

	var rtShared = this.rtShared;
	var submitMsg = function() {
		if(rtShared.sent) return;
		rtShared.sent = true;
		/* Kick in message submission */
		msg.push({'Name': 'tid', 'Value': cmtObj.ID});
		s.prepareImgData(msg);
		var src = (cmtObj.isEditing ? '.edit' : '.put');
		var prms = this.getKVListFromMsg(msg);
		this.server(src, prms, longMsg);
	}

	this.cmtInPlace(cmtObj, function() {
		this.controls.reveal();
		this.reCalcPages();
		submitMsg.call(this);
	});
}

JSCC.prototype.getKVListFromMsg = function(msg) {
	var prms = {};
	JSKitLib.fmap(msg, function(v) { prms[v.Name] = v.Value; });
	return prms;
}

JSCC.prototype.cloneObj = function(f) {
	var t = {};
	for(var p in f) t[p] = f[p];
	return t;
}

JSCC.prototype.getRatingsAppObject = function() {
	return this.isStandalone() ? null : $JSKitGlobal.getRatingsAppObject(this.uniq);
}

JSCC.prototype.hasRatingsAppObject = function() {
	return this.getRatingsAppObject() ? true : false;
}

JSCC.prototype.embedRatingsAppObject = function(node) {
	// One time
	if ( ! this.embedRatingsAppObjectCompleted) {
		$JSKitGlobal.copyRatingsAppObject(this.uniq, node);
		this.embedRatingsAppObjectCompleted = true;
	}
}

JSCC.prototype.createMiniStarObject = function(rating, scale) {

	var rao = this.getRatingsAppObject();
	var fullStar = rao.miniFullStar['user'];
	var emptyStar = rao.miniEmptyStar['user'];
	var starWidth = rao.miniStarWidth + 'px';
	var starHeight = rao.miniStarHeight + 'px';

	var setImage = function(star, imageURL) {
		if(star.imageURL == imageURL)
			return; // Already set and we know it

		star.imageURL = imageURL;

		if(document.body.filters) {
			star.runtimeStyle.filter
				= "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
				+ imageURL + "', sizingMethod='crop')"
		} else {
			star.style.backgroundImage = 'url(' + imageURL + ')';
		}
	}

	var obj = document.createElement('div');

	/* Increment by Full Star Ratings */
	for (var i=2; i <= scale; i += 2) {

		var star = this.cr('div');

		star.style.cssFloat   = 'left';
		star.style.styleFloat = 'left';
		star.style.width    = starWidth;
		star.style.height   = starHeight;

		setImage(star, (rating >= i ? fullStar : emptyStar));

		obj.appendChild(star);
	}

	return obj;
}

JSCC.prototype.rerenderName = function(cmt) {
	var self = this;
	var ctls = cmt.ctls;
	var jsc = function(t){return ctls['js-singleComment'+t]};
	var sa = jsc("Name");
	if(sa && cmt.cobj.profile && self.serverOptions.showProfile && !(cmt.cobj.msgtype && cmt.cobj.msgtype.match(/T|P/))) {
		sa.style.textDecoration = 'underline';
		sa.style.cursor = 'pointer';
		sa.onclick = function() {
			self.showProfile(sa, cmt.cobj, self.serverOptions.profileLevel);
			return false;
		}
	}
}

JSCC.prototype.gotPermanentId = function(tmpid, msgId) {
	var self = this;
	var cobj = this.objById[tmpid];
	var cmt = this.jspg.getItemById(tmpid).div;
	delete self.objById[tmpid];
	delete cobj.isEmbryonic;
	cobj.ID = msgId;
	cmt.id = msgId;
	this.jspg.invalidateItemView(msgId);
	self.objById[msgId] = cobj;
	var aux = arguments.length > 2 ? arguments[2] : {};
	var props = {'Text': cobj, 'status': cobj,
		'mtext': self.serverOptions,
		'mmode': self.serverOptions};
	for(var pname in props) {
		if(aux.hasOwnProperty(pname)) {
			props[pname][pname] = aux[pname];
		}
	}
	if (aux.Text) {
		JSKW$Events.syncBroadcast('smileys-loadCommentsWidget', cobj, self.jcaIndex);
	}
	if(self.serverOptions.showProfile && !self.serverOptions.profile && aux.profile) {
		self.serverOptions.profile = aux.profile;
		cobj.profile = aux.profile;
	}
	var cnvsObj = {};
	cnvsObj.Name = cobj.Name;
	if(aux.avatar) {
		cobj.avatar = aux.avatar;
		cobj.avatarWidth = aux.avatarWidth;
		cobj.avatarHeight = aux.avatarHeight;
		cnvsObj.avatar = aux.avatar;
		cnvsObj.avatarWidth = aux.avatarWidth;
		cnvsObj.avatarHeight = aux.avatarHeight;
		self.placeAvatar(cobj);
	}
	if (aux.gravatarId) {
		cobj.GravatarID = aux.gravatarId; 
		self.placeAvatar(cobj);
	}
	if(aux.destName){
		cobj.destName = aux.destName;
		cnvsObj.destName = aux.destName;
	}
	if(aux.destavatar) {
		cobj.destavatar = aux.destavatar;
		cobj.destavatarWidth = aux.destavatarWidth;
		cobj.destavatarHeight = aux.destavatarHeight;
		cnvsObj.destavatar = aux.destavatar;
		cnvsObj.destavatarWidth = aux.destavatarWidth;
		cnvsObj.destavatarHeight = aux.destavatarHeight;
	}
	if(this.IM && cobj.waitConversation) {
		cnvsObj.direction = "out";
		this.conversations[cobj.waitConversation.cnvsIdx] = cnvsObj;
		cobj.conversation = cobj.waitConversation.cnvsIdx;
		cobj.waitConversation = false;
		cobj.hasCnvs = false;
	}
	if(cmt.domCtls) cmt.domCtls.style.visibility = "";
	if(this.jspg.getPageByItemId(msgId)==this.curPage-1) {
		var pageNo = this.curPage;
		this.curPage = 0;
		this.displayPage(pageNo);
	}
}

function JSReplyMSGId(tmpid, msgId) {
	try {
		var cmt = document.getElementById(tmpid);
		var cobj = cmt.cobj;
		if(cobj.goesInto) {
			var args = arguments;
			JSKitLib.fmap(cobj.goesInto,
				function(s){s.gotPermanentId.apply(s,args)});
		} else {
			var self = $JCA[cobj.jcaIndex];
			self.gotPermanentId(tmpid, msgId);
		}
	} catch(e){}
}

function JSDeleteMSGId(msgId, jcaIndex, deletedCount) {
	try {
		var cmt = document.getElementById(msgId);
		if(cmt) {
			var self = $JCA[jcaIndex];
			if(cmt.cobj.action)
				JSKW$Events.syncBroadcast("comments_serverRequest_" + cmt.cobj.action);
			if(deletedCount>1){
				self.tag = null;
				self.jspg.invalidate();
				var pageNo = self.curPage;
				self.curPage = 0;
				self.displayPage(pageNo);
			} else {
				self.postHandlerDelete(cmt);
			}
		}
	} catch(e){}
}

function JSCCKarma(cObj, self) {
	var kObj = { p: cObj.karmaP || 0, n: cObj.karmaN || 0 };
	this.score = kObj.p - kObj.n;
	this.votes = kObj.p + kObj.n;
	this.cObj = cObj;
	this.self = self;
	this.vote2text();
	return this;
}
JSCCKarma.prototype.vote2text = function() {
	this.votesText = this.votes + ' '
			+ ((this.votes == 1) ? $JCL("vote") : $JCL("votes"));
}

JSCCKarma.prototype.recomputeScore = function(scoreAdjustment) {
	var now = new Date();
	if(this.votedAlready) {
		this.score -= this.myVote;
	} else {
		this.votes += 1;
		this.votedAlready = true;
		var kObj = this;
		setTimeout(function() {
			var action = kObj.myVote > 0 ? '+' : '-';
			kObj.self.server('-karma', {'id': kObj.cObj.ID,
					'action': action});
			}, 2000);
	}
	this.score += scoreAdjustment;
	this.myVote = scoreAdjustment;
	this.vote2text();
}

JSCC.prototype.divPages = function(so, items) {
	var srv = so.pages;
	this.curPage = 0;
	var self = this;
	if(!this.jspg) {
		this.jspg = new JSPGC(items.length, this.preq.ps);
		this.jspg.dataRequest = function(pageIdx, pg, cb) {
			var pageNo = pageIdx+1;
			if(!pg.target) pg.target = self.cr('div');
			var tgt = pg.target;
			if(tgt.parentNode) tgt.parentNode.removeChild(tgt);
			self.dataLoader = function() {
				self.curPage = 0;
				self.displayPage(pageNo, function(immed){ cb.apply(self, [undefined, immed])});
                                }
			if(self.preq.pn < 10)
				self.preq.pn += 5;
			self.getpages(pageNo - Math.ceil(self.preq.pn / 2));
			return cb(self.text(tgt, $JCL("Cargando...")), false);
			};
		this.jspg.dataVisualizator = function(sIdx, arr, pg, cb) {
			if(!pg.target) pg.target = self.cr('div');
			var tgt = pg.target;
			if(tgt.parentNode) tgt.parentNode.removeChild(tgt);
			var itemsOnPage = arr.length;
			var cnvs = [];
			var cn = JSKitLib.fmap(arr,function(V,K){
				if(!V.html) {
					var oldN = V.obj.Name;
					V.obj.Name = (self.IM && V.obj.yours) ? 'Me' : oldN;
					var oldT = V.obj.Text;
					if(V.obj.status=='DT') V.obj.Text = 'Deleted';
					if (V.obj.Url && !V.obj.Url.match(/^https?:\/\//) ) {
						V.obj.Url = "http://" + V.obj.Url;
					}
					V.html = self.createCommentAsHTML(V.obj);
					V.obj.Name = oldN;
					V.obj.Text = oldT;
					delete V.div;
				}
				V.div = JSKitLib.html(V.html);
				V.div.id = V.obj.ID;
				V.obj.hasCnvs = !cnvs[V.obj.conversation];
				cnvs[V.obj.conversation] = true;
				self.fixComment(V.div, V.obj, K, K+sIdx, itemsOnPage);
				return V;
			});
			JSKitLib.removeChildren(tgt);
			self.pageHeader(tgt, sIdx, arr, itemsOnPage);
			for(var i=0; i<cn.length; i++) {
				tgt.appendChild(cn[i].div);
				if(!self.IM && (!self.adminMode || self.inlineModeration) && i<cn.length-1 && self.getSkin()=='smoothgray' && cn[i].obj.cedge>1) {
					var crdiv = function(className) {
						var div = self.cr("div");
						div.className = className;
						return div;
					};
					var div = crdiv("js-TornPageDivider");
					var divT = crdiv("js-TornPageDividerTop");
					var divB = crdiv("js-TornPageDividerBottom");
					div.appendChild(divT);
					div.appendChild(divB);
					tgt.appendChild(div);
				}
			}
			self.pageFooter(tgt, sIdx, arr, itemsOnPage);
			return cb(tgt, true);
		};
	}
	this.jspg.newData(srv.tc, srv.sp-1, items);
}

JSCC.prototype.pageHeader = function(target, globalIndex, items, itemsOnPage) {
	if(this.getSkin()=='smoothgray' && itemsOnPage>0 && items.length>0 && (!this.adminMode || this.inlineModeration)) {
		var obj = items[0].obj;
		if(obj.cedge!=3 && obj.cedge!=1) {
			var div = this.cr("div");
			div.className = "js-TornPageTop";
			if(JSKitLib.isIE()) {
				var img = this.cr("img");
				img.className = "js-TornPageTopImg";
				img.src = "//js-kit.com/images/tornPaperT.gif";
				div.appendChild(img);
			}
			target.appendChild(div);
		}
	}
}

JSCC.prototype.pageFooter = function(target, globalIndex, items, itemsOnPage) {
	if(this.getSkin()=='smoothgray' && itemsOnPage>0 && items.length==itemsOnPage && (!this.adminMode || this.inlineModeration)) {
		var obj = items[itemsOnPage-1].obj;
		if(obj.cedge!=3 && obj.cedge!=2) {
			var div = this.cr("div");
			div.className = "js-TornPageBottom";
			if(JSKitLib.isIE()) {
				var img = this.cr("img");
				img.className = "js-TornPageBottomImg";
				img.src = "//js-kit.com/images/tornPaperB.gif";
				div.appendChild(img);
			}
			target.appendChild(div);
		}
	}
}

JSCC.prototype.htmlPaginate = function(thread) {
	return this.htmlPaginator(thread, []);
}

JSCC.prototype.htmlPaginator = function(thread, arr) {
	var tl = thread.length;
	for(var i = 0; i < tl; i++) {
		var obj = thread[i];
		var present = (obj.status == 'D') ? 0 : 1;
		if(present) {
			arr.push(obj);
		}
		this.htmlPaginator(obj.thread, arr);
	}
	return arr;
}

// Part of externally useable API
JSCC.prototype.rerender = function() {
	var pageToDisplay = this.curPage;
	this.curPage = 0;
	this.jspg.invalidatePagesView(pageToDisplay-1, 1);
	this.displayPage(pageToDisplay);
}

JSCC.prototype.setPath = function(path) {
	this.pathOverride = path;    
}

JSCC.prototype.displayPage = function(pageNo, cb) {

	if(this.loading && !cb) {
		var nt = (new Date()).valueOf();
		if((nt - this.loading) > 5000) {
			this.gen++;
		} else  {
			return;
		}
	}

	if(pageNo < 1)
		return;

	if(pageNo > this.jspg.pageCount)
		pageNo = this.jspg.pageCount;

	var immediate = true;

	if(this.curPage != pageNo) {
		try {
			this.CommentCancelled();
			if(this.curPage) {
				var p = this.jspg.getPage(this.curPage - 1);
				if(p && p.target && p.target.parentNode)
					p.target.parentNode.removeChild(p.target);
			}
		} catch(e) { }
		this.curPage = pageNo;
		var oc = this.TC["js-OldComments"];
		var self = this;
		var pcb = function(p, immed) {
			if(p) {
				oc.appendChild(p);
				p.style.display = '';
			}
			if(immed && cb) cb.apply(self, [immed]);
		};
		var newPage = this.jspg.getPageVisualization(this.curPage-1, pcb);
		immediate = false;
	}

	var ocw = this.TC["js-OldCommentsWrap"];
        if (this.jspg.itemsCount != 0)
        {
          JSKitLib.show(ocw);
        }
        else
        {
          JSKitLib.hide(ocw);
        }

	this.rePageNavigator(this.curPage-1);
	if(immediate && cb) cb.apply(this, [immediate]);
}

JSCC.prototype.cutSearchLine = function(text) {
	return (text.length > 15) ? text.slice(0,15) + "..." : text;
}

JSCC.prototype.SearchLine = function() {
	var self = this;	
	var sExit = self.cr('span');
	var title = self.cr('span');
	title.className = 'js-SearchTitle';
	title.innerHTML = '<b>'+$JCL("You searched for")+':</b>';
	sExit.appendChild(title);
	var line = self.cr('span');
	line.className = 'js-SearchWords';
	text = self.cutSearchLine(self.searchString);
	line.insertBefore(document.createTextNode(text),line.firstChild);
	sExit.appendChild(line);
	var del = self.cr('input');
	del.type = 'button';
	del.value = $JCL('Clear Search');
	sExit.appendChild(del);
	var obj={
		 'containerElement':	 	sExit,
		 'field': 			line,
		 'itemObject': 			self,
		 'type':			'Search',
		 'Property': 			'searchString',
		 'title':			$JCL("You searched for")+': ',
		 'mode': 			'full'
		};
	obj.jsipe$start = function(){
		del.style.display = "none";
		line.style.border = "0px";
		title.style.display = "none";
		return true;
	}
	obj.jsk$on_submit_exit = function(value){
		self.searchString = value;	
		self.viewControl({name: "search"});
	}
	line.wasEdited = function(value){
		JSKitLib.removeChildren(line);
		line.appendChild(document.createTextNode(self.cutSearchLine(value)));
		del.style.display = "";
		line.style.borderBottom = "";
		title.style.display = "";
	}
	del.onclick = function(){
		this.name="del-line";
		self.viewControl(this);
	}
	var jsipe = new JSIPE(obj);
	return sExit;
}

JSCC.prototype.navSym = { "prev": "&larr;", "next": "&rarr;" };

JSCC.prototype.rePageNavigator = function(pageIdx) {
	var nav = '';
	var display = this.searchString ? "" : "none";
	if(this.jspg.pageCount > 1){
		display = "";
		nav = this.pageNavigator(this.jspg.pageCount, this.curPage);
	}
	var nvs = ['Top','Bottom'];
	for(var i = 0; i < nvs.length; i++) {
		var bar = this.TC['js-PageNav' + nvs[i]];
		bar.innerHTML = nav ? '<div>' + nav + '</div>' : '';
		bar.onselectstart = function() { return false; }
		bar.style.display = display;
		if(i) bar.style.display = ((pageIdx==undefined || (this.jspg.getPageItemsCnt(pageIdx) <= 5)) ? 'none' : '');
		if(this.searchString) this.addChild(bar, this.SearchLine(), true);
	}
}

JSCC.prototype.pageNavigator = function(pages, cur) {
	var self = this;
	var arr = [$JCL('P&aacute;gina: ')];
	var f = function(i, txt, cmt, cls, cf) {
		return '<a href="#'+cmt+'" onclick="' + (cf || '$JCA['+self.jcaIndex+'].displayPage('+i+');') + ' return false;" onmouseover="window.status='+"'"+cmt+"'"+'; return false;" onmouseout="window.status=\'\'; return true;" class="js-PageNOther'+(cls?' '+cls:'')+'">' + txt + '</a> '; }
	arr.push(f(cur - 1, this.navSym.prev, $JCL('Previous page'),
		'js-PageArrow' + ((cur == 1)?' js-PageArrowCur':'')));
	for(var i = 1; i <= pages; i++) {
		if((i == 4 || i == 3) && (cur - i) > 3) {
			i = Math.floor((cur - i) / 2 + i);
			arr.push(f(i, '&hellip;', 'Page-' + i));
			i = cur - ((pages - cur > 3 || cur == pages) ? 2 : 1);
		}
		if((i == cur + 3) && (pages - cur) > 4) {
			i = Math.floor((pages - cur) / 2 + cur);
			arr.push(f(i, '&hellip;', 'Page-' + i));
			i = pages - 1;
		}
		if(i == cur) {
			arr.push(f(i, i, 'Page-' + i, "js-PageNCur", '$JCA['+self.jcaIndex+'].jspg.invalidate(); $JCA['+self.jcaIndex+'].rerender();'));
		} else {
			arr.push(f(i, i, 'Page-' + i));
		}
	}
	arr.push(f(cur + 1, this.navSym.next, $JCL('Next page'),
		'js-PageArrow' + ((pages == cur)?' js-PageArrowCur':'')));
	return arr.join('');
}

JSCC.prototype.hideSettingsWindow = function(wname) {
	if(this[wname]) this.settingsWindow(wname);
}

JSCC.prototype.showProgress = function(wname, on) {
	if(this[wname]) this[wname].showProgress(on);
}

JSCC.prototype.settingsWindow = function(wname, atDiv, html) {
	var s = this;
	if(s[wname]) {
		if(!s.sWHideable) return;
		s[wname].parentNode.removeChild(s[wname]);
		delete s[wname];
		return;
	}
	var nohide = function() {
		s.sWHideable = false;
		if(s.swsHidt) clearTimeout(s.swsHidt);
		s.swsHidt = setTimeout(function(){s.sWHideable=true}, 100);
	}
	var div = this.cr("div");
	div.className = "js-SettingsWindow";
	if (s.config.nolc) JSKitLib.addClass(div, "js-SettingsWindowNolc");
	div.style.background = '#FFFFFF url('+this.uriDomain
				+'/images/bg-header-gray.png) bottom repeat-x';
	div.onclick = nohide;
	div.onselectstart = function() { return false; }
	if(typeof(html) == 'string') {
		div.innerHTML = html;
	} else {
		if(!html.dropWidth) div.style.width = '20em';
		div.appendChild(html);
	}

	if (wname == 'ctWnd' && s.TC['js-WelcomePanel']) {
		var aoh = s.cr('div');
		aoh.className = 'js-SettingsWindowHeader';
		s.text(aoh, $JCL('Administrator Options'));
		div.appendChild(aoh);
		var wp = s.TC['js-WelcomePanel'];
		var links = JSKitLib.html(''
			+ '<table border=0 cellpadding=4 align=center width="220" style="white-space: nowrap">'
			+ '<tr valign="top"><td class="js-WelcomeOpenPanel"><div class="js-WelcomeImgPanel"><a href="javascript:void(0);">' + $JCL(JSKitLib.visible(wp) ? 'closeWelcome' : 'openWelcome') + '</a></div></td></tr>'
			+ '<tr><td class="js-WelcomeContact"><div class="js-WelcomeImgSupport"><a href="javascript:void(0);">' + $JCL('contactSupport') + '</a></div></td></tr>'
			+ '</table>');
		var tc = JSKitLib.mapClass2Object({}, links);
		div.appendChild(links);
		tc['js-WelcomeOpenPanel'].onclick = function() {
			JSKitLib.toggle(wp);
			s.text(this.lastChild.lastChild, $JCL(JSKitLib.visible(wp) ? 'closeWelcome' : 'openWelcome'));
		};
		tc['js-WelcomeContact'].onclick = function(){location.href = s.uriDomain + '/comments/qa.html';};
	}

	var pgr = this.cr('div');
	pgr.className = "js-Progress";
	var url = this.uriDomain + '/images/progress-wg.png';
	if(document.body.filters) {
                pgr.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + url + ", sizingMethod=crop)";
       	} else pgr.style.backgroundImage = 'url(' + url + ')';
	div.appendChild(pgr);
	div.showProgress = function(on) {
		if(!on) {
			if(div.pIntvl) clearInterval(div.pIntvl);
			div.pIntvl = null;
			pgr.style.visibility  = 'hidden';
			return;
		} else if(div.pIntvl) return;
		var f = function() {
			pgr.vison = !pgr.vison;
			pgr.style.visibility = pgr.vison
				? 'visible' : 'hidden';
		}
		f();
		div.pIntvl = setInterval(f, 500);
	}

	s[wname] = div;
	var swh = this.cr("div");
	swh.className = "js-SettingsWindowHeader";
	this.text(swh, $JCL(wname == 'ctWnd' ? "View Options" : "Moderation"));
	div.insertBefore(swh, div.firstChild);
	div.style.position = "absolute";

	var jsd = new JSDL(div, [swh]);
	document.body.appendChild(div);
	div.style.left = jsd.getElmAbsPos(atDiv, false).x + "px";
	div.style.top =  jsd.getElmAbsPos(atDiv, false).y + atDiv.offsetHeight + "px";

	try {
		if (document.body.clientWidth < jsd.getElmAbsPos(atDiv, false).x + div.offsetWidth)
			div.style.left = document.body.clientWidth - div.offsetWidth -
                        	(parseInt(div.style.marginLeft) || 0) -
                                (parseInt(div.style.marginRight) || 0) + "px";
	} catch(e) {;}
	
	var ifrWr;
	if(JSKitLib.getBrowser() == 'gecko' && !atDiv.notShowIfr) {
                ifrWr = this.cr("div");
                ifrWr.id = "jsk-yIfr";
                var yIfr = this.cr("iframe");
                yIfr.style.position = "absolute";
                yIfr.style.top = 0;
                yIfr.style.left = 0;
                yIfr.style.zIndex = -1;
                yIfr.style.display = "block";
                yIfr.style.height = div.offsetHeight + "px";
                yIfr.style.width = div.offsetWidth + "px";
                yIfr.scrolling = "no";
                yIfr.frameBorder = "0";
                ifrWr.appendChild(yIfr);
                div.appendChild(ifrWr);
	}
	div.jsk$on_start_drag = function(){if(ifrWr) ifrWr.style.display = "none"};
	div.jsk$on_stop_drag = function(){if(ifrWr) ifrWr.style.display = ""};
	nohide();
}

JSCC.prototype.getImages = function(id) {
	var arg = "rnd="+id+"&jx="+this.jcaIndex;
	this.runscr(this.uriDomain + '/api/images/pick-attachments.js', arg);
}

JSCC.prototype.prepareImgData = function(msg) {
	if(this.images){
		JSKitLib.removeChildren(this.imgArea);
		JSKitLib.map(function(elem, i){
			JSKitLib.fmap(['img','orig','width','height','descr','mime'],
				function(E) { msg.push({'Name': 'js-CmtattachFile_'+i+'_'+E, 'Value': elem[E]})}
			);
		},this.images);
	}
}

JSCC.prototype.parseImgData = function(obj) {
	var re = /attachFile_(\d+)_(\w+)/;
	var imgs = [];
	for (var i in obj){
		var keys = re.exec(i);
		if (keys) {
                        if (!imgs[keys[1]]) imgs[keys[1]] = {};
                        imgs[keys[1]][keys[2]] = obj[i];
		}
	}
	return imgs;
}

JSCC.prototype.createImages = function(imgs, isPreview){
	var s = this;
	var d=function(){return s.div.apply(s,arguments);}

	var content = isPreview ? d() :
		      d("js-all-previewImages",d("js-previewImageTitle", $JCL('picTitle')),
			JSKitLib.html('<div style="clear:both;"></div>'));

	var crImg = function(elem, i){
		var img = d("js-previewImage");
		var thumb = s.cr("img");
		elem.descr = elem.descr || '';
		thumb.src = s.uriDomain+"/blob/"+elem.img;
		JSKitLib.setStyle(thumb, "border: 1px solid "+((isPreview)?"#0066cc":"#ececec")+"; padding: 2px;"
					+" width: "+elem.width+"px; height: "+elem.height+"px; cursor: pointer;" 
					+" position: relative; top: "+((96-elem.height)/2)+"px;");
		thumb.onclick = function() { window.open(s.uriDomain+"/blob/"+elem.orig); }
		var text = d("js-previewImageDescr");
		var wrap = d("js-imageWrap");
		s.addChild(wrap, thumb);
		s.addChild(img, wrap);
		if (isPreview) {
			var wasEdited = function(){
				if(elem.descr != "" ) JSKitLib.removeClass(text,"js-uploadGreyDescr");
				else JSKitLib.addClass(text,"js-uploadGreyDescr");
			}
			var jsipe = new JSIPE2({obj: elem,
						property: 'descr',
						title: 'Descripcion',
						defaultText: 'Agregar titulo',
						width: '90px',
						maxLength: 80,
						jsk$wasEdited: wasEdited
			});
			text.appendChild(jsipe.div);
			var onEditBtnClick = function(e){ 
				if(jsipe.editMode) jsipe.editMode();
				JSKitLib.stopEventPropagation(e || window.event); 
			}
			var onDeleteBtnClick = function(e){
				img.parentNode.removeChild(img);
				if(imgs && imgs[i]) imgs.splice(i, 1);
				JSKitLib.stopEventPropagation(e || window.event);
			}		
			var editBtn   = s.crImgCtrl("edit",   {top: "60px", left: "15px"}, onEditBtnClick);
			var deleteBtn = s.crImgCtrl("delete", {top: "60px", left: "57px"}, onDeleteBtnClick);
			var displayMode = function(mode){
				editBtn.style.display = mode;
                                deleteBtn.style.display = mode;
			}
			img.onmouseover = function(e) { displayMode("inline"); }
			img.onmouseout = function(e) { displayMode("none"); }
			s.addChild(img, editBtn);
			s.addChild(img, deleteBtn);
			if(elem.descr == "") JSKitLib.addClass(text,"js-uploadGreyDescr");
		} else {
			text.innerHTML = elem.descr.replace(/</g,"&lt;").replace(/>/g,"&gt;");
		}
		thumb.title = JSKitLib.htmlUnquote(elem.descr);
		s.addChild(img, text);
		s.addChild(content, img);
	}
	JSKitLib.map(crImg,imgs);
	s.addChild(content, JSKitLib.html('<div style="clear:both;"></div>'));

	return content;
}

JSCC.prototype.crImgCtrl = function(type, position, onClick) {
	var btn = this.cr("div");
	var ctrlBtn = { width : "30px", height : "30px", imgWidth :  "30px", imgHeight : "30px" };
	JSKitLib.setStyle(btn, "display:none; background:transparent; position:absolute; float:left; padding:0; margin:0; "
		+ "width:" + ctrlBtn.width + "; height:" + ctrlBtn.height + "; cursor: pointer;"
		+ "top:" + position.top + "; left:" + position.left);
	btn.title = $JCL(type + "Image");
	btn.onclick = onClick;
	imgUrl = this.uriDomain + "/images/" + "avatar-" + type + ".png";
	JSKitLib.addPNG(btn, imgUrl);

	return btn;
}


JSCC.prototype.addImage = function(img) {
	if(this.lbliChange) this.lbliChange(0);
	if (typeof(img) == "object"){
		if(img.error == "bigimg") {
			alert($JCL('bigImage'));
			return;
		}
		if (this.images) this.images.push(img)
		else this.images = [img];
		if (!this.imgArea) return;
		JSKitLib.removeChildren(this.imgArea);
		var content = this.createImages(this.images, true);
		this.addChild(this.imgArea, content);
	}
}

JSCC.prototype.viewControl = function(sel) {
	var s = this;
	var ap = { "usr": "yes"};
	switch(sel.name) {
	case "jss-srt":
		var newSortBy = sel.options[sel.selectedIndex].value;
		if(newSortBy == s.preq.srt) return true;
		s.preq.srt = newSortBy;
		s.showProgress('ctWnd', true);
		break;
	case "jss-rev":
		var newOrder = sel.selectedIndex?'desc':'asc';
		if(s.preq.ord == newOrder) return true;
		s.preq.ord = newOrder;
		s.showProgress('ctWnd', true);
		break;
	case "jss-prs":
		var newPrs = sel.options[sel.selectedIndex].value;
		if(newPrs == s.preq.thr) return true;
		s.preq.thr = newPrs;
		s.showProgress('ctWnd', true);
		break;
        case "search":
                ap.srch = s.searchString;
                break;
        case "del-line":
                break;
	default: return false;
	}
	s.dataLoader = function() {
		this.showProgress('ctWnd', false);
		this.curPage = 0;
		this.displayPage(1); }
	if(this.curPage) {
		var p = this.jspg.getPage(this.curPage - 1);
		if(p && p.target && p.target.parentNode)
			p.target.parentNode.removeChild(p.target);
	}
	s.ctag = null;
	s.getpages(0, ap);
	return true;
}

JSCC.prototype.splitAvatarDim = function(so, dim) {
	var re = /(\d+)x(\d+)/;
	var vl=re.exec(dim) || ['96x96', '96', '96'];
	so.maxAvatarWidth = parseInt(vl[1]);
	so.maxAvatarHeight = parseInt(vl[2]);
}

JSCC.prototype.calcAvatarDim = function (Width, Height, Avatar) {
	var so = this.serverOptions;
	var MW = so.maxAvatarWidth;
	var MH = so.maxAvatarHeight;
	if((MW>=96)&&(MH>=96)&&(Width<=100)&&(Height<=100)){
		return {'width': Width,'height': Height,'name': Avatar};
	} else if((MW<Width)||(MH<Height)){
		var DW = (MW<Width) ? MW/Width : 1;
		var DH = MH<Height ? MH/Height : 1;
		var D = DW < DH ? DW : DH;
		DW = Math.round(Width*D+0.000001);
		DH = Math.round(Height*D+0.000001);
		Name = Avatar.substr(0,Avatar.length-4)+'-'+DW.toString()+'x'+DH.toString()+Avatar.substr(Avatar.length-4);
		return {'width': DW, 'height': DH,'name': Name};
	} else {
		return {'width': Width,'height': Height,'name': Avatar};
	}
}

JSCC.prototype.placeGravatar = function(obj, div) {

	if (this.config.gravatars != 'yes') { return; }

	if (obj.GravatarID) {

		var img = this.cr('img');
		img.style.width = this.config.gravatar_size + 'px';
		img.style.height = this.config.gravatar_size + 'px';
		img.src = 'http://www.gravatar.com/avatar.php?' 
			+ 'gravatar_id=' + obj.GravatarID
			+ '&default=' + this.config.gravatar_default
			+ '&rating=' + this.config.gravatar_rating
			+ '&size=' + this.config.gravatar_size;

		JSKitLib.removeChildren(div);
		div.style.width = img.style.width;
		div.appendChild(img);

	}
}

JSCC.prototype.placeAvatar = function(obj, div) {
	div = div || obj.avatarPlace;
	if(!div) return;

	if(this.config.avatars != 'yes') {
		this.placeGravatar(obj, div);
		return;
	}

	if(!obj.avatar) {
		obj.avatarPlace = div;
		return;
	}
	var img = this.cr('img');
	img.style.visibility = 'hidden';
	var WH = this.calcAvatarDim(obj.avatarWidth,obj.avatarHeight,obj.avatar);
	var imgurl = JSKitAvatarsManagement.prototype.avatarURL.call({uriAvatar: this.uriDomain + '/blob/'}, WH['name']);

	img.style.width = WH['width'] + 'px';
	img.style.height = WH['height'] + 'px';
	img.src = imgurl;
	JSKitLib.removeChildren(div);
	JSKitLib.addPNG(div, imgurl);
	div.style.width = WH['width'] + 'px';
	div.appendChild(img);

	var self = this;
	if(obj.profile && this.serverOptions.showProfile) {
		div.style.cursor = 'pointer';
		div.onclick = function(e) {
			JSKitLib.stopEventPropagation(e);
			JSKitLib.preventDefaultEvent(e);
			self.showProfile(div, obj, self.serverOptions.profileLevel);
			return false;
		}
	}
	return div;
}

JSCC.prototype.placeProcessAvatar = function(div) {
	if(!div) return;
	var img = this.cr("img");
	img.style.visibility = 'hidden';
	JSKitLib.removeChildren(div);
	JSKitLib.addPNG(div, this.uriDomain + '/images/progress-wg.png');
	div.style.width = "15px";
	div.style.height = "15px";
	div.appendChild(img);
}

JSCC.prototype.replaceAvatars = function(avatars) {
        if (this.avatarsManagement) this.avatarsManagement.replaceAvatars(avatars);
}

JSCC.prototype.refreshComments = function() {
	var s = this;
	s.deleteWelcomePanel();
	s.jspg.invalidate();
	if (s.curPage == 1) s.curPage = 0;
	s.displayPage(1, function() {
		if (s.avatarsManagement) s.avatarsManagement.refreshAvatars();
		s.preventAnonymousComments();
		s.makeWelcomePanel();
		s.ShowCommentDialog(s.replyForId);
	});
}

JSCC.prototype.preventAnonymousComments = function() { 
	var s = this;
	var cmtText = s.TC['js-CmtText']; 
	var cmtEmail = s.TC['js-CmtEmail'];
	var cmtUpload = (s.avatarsManagement) ? s.avatarsManagement.uploadControl : undefined;
	var disableCtrls = [cmtText, s.TC['js-Cmtsubmit'], s.TC['js-CmtName'], cmtEmail, cmtUpload, s.imgUpload];
	var lockCtrls = [s.TC['js-Cmtsubmit'], cmtUpload];
	var imgArea = s.TC['js-commentImageArea'];
	var anonymCond = s.anonymousCmt && !(s.openID || (s.serverOptions.facebookLogin && s.serverOptions.facebook) ||
	(s.serverOptions.yahooLogin && s.serverOptions.yahoo));

	JSKitLib.fmap(disableCtrls, function(V){ if (V) V.disabled = (anonymCond) ? true : false; });
	JSKitLib.fmap(lockCtrls, function(V){ if (V) V.btnLocked = (anonymCond) ? "true" : null; });
	if (imgArea) imgArea.disableUpload = anonymCond;
	if (cmtText) { cmtText.value = (anonymCond) ? $JCL('requireAuth') : ""; }
	if (cmtEmail && anonymCond) cmtEmail.value = "";
} 

JSCC.prototype.wrapJSKAuth = function() {
	var s = this;
	var tc = s.TC;

	if (s.config.nolc) return; 

	if (!tc['js-AuthAreaWrap']) {
		s.preventAnonymousComments();
		if (s.openID) {
			var oidurl = tc['js-commentOpenIDURL'];
			if (oidurl) {
				var openid = String(s.openID);
				var m = openid.match(/^http:\/\/(.*?).(js-kit|haloscan).com\/$/);
	                        if(m) {
	       	                        oidurl.innerHTML = (m[2] == "js-kit" ? $JCL("jskitAccount"):
               	                        $JCL("haloscanAccount")) + "<b>" + m[1] + "</b>";
                       		        oidurl.style.fontWeight = 'normal';
        	                        oidurl.style.background = 'none';
                	                oidurl.style.paddingLeft = '0px';
	                        } else {
        	                        oidurl.innerHTML = s.openID;
                	        }
			}
			var oiddiv = tc['js-commentOpenID'];
			if (oiddiv) { oiddiv.style.display = 'block'; }
		}

		var onLogoutAction = function() {
			if (tc['js-CmtName']) JHI2.create($JCL('guest'), tc['js-CmtName']);
			var oiddiv = tc['js-commentOpenID'];
			if (oiddiv) { oiddiv.style.display = 'none'; }
			s.openID = 0;
			var morediv = tc['js-commentMore'];
			oiddiv = tc['js-commentInputOpenID'];
			if (morediv && oiddiv) { 
                                if (s.avatarsManagement && morediv.style.display == "none") {
                                        morediv.style.display = "";
                                }
				oiddiv.style.display = morediv.ashown ? 'block' : 'none';	
			}
			s.refreshComments();
		} 	
		JSKW$Events.registerEventCallback(undefined, onLogoutAction, 'JSKitAuth_logout');
		return;
	}

	var authAreaTmpl =
	'<div>' +
		'<div class="js-commentFieldLabel">{Label:leaveCommentAs}</div>' +
		'<div class="js-authSelector">' + 
			'<span class="js-logoutSpan">[<a class="js-commentOpenIDLogout">{Label:logout}</a>]</span>' +
		'</div>' +
		'<div class="js-authArea"></div>' +
	'</div>';

	var registerTmpl =
	'<div style="clear: both;">'+
		JSKitAuth.prototype.progressAreaTmpl +
		'<div class="js-authLabel">{Label:login}:</div>' +
		'<div class="js-authContainer">' +
			'<input size="32" class="js-commentFieldInput" name="jsk-User-login-reglogin"' + JSKitAuth.prototype.autoComplete +'>' +
			'<div class="jsk-SectionLoginMessage js-loginMessageHandle"></div>' +
		'</div>' +
		'<div class="js-authLabel">{Label:password}</div>' +
		'<div class="js-authContainer">' +
			'<input size="32" class="js-commentFieldInput" name="jsk-User-login-regpassword" type="password">' +
			'<div class="jsk-SectionLoginMessage js-passwordMessageHandle"></div>' +
		'</div>' +
		'<div class="js-authLabel">{Label:retypePassword}</div>' +
		'<div class="js-authContainer">' +
			'<input size="32" class="js-commentFieldInput" name="jsk-User-login-regpassword2" type="password">' +
			'<div class="jsk-SectionLoginMessage js-password2MessageHandle"></div>' +
		'</div>' +
		'<div class="js-authContainer">' +
			'<input value="{Label:register}" name="Register" style="margin-left: 0px;" class="js-authButton" type="button">' +
		'</div>' +
	'</div>';

	var loginTmpl =
	'<div style="clear: both;">' +
		JSKitAuth.prototype.progressAreaTmpl +
		'<div class="js-authLabel js-loginLblHandle">{Label:login}:</div>' +
		'<div class="js-authContainer">' +
			'<input size="32" class="js-commentFieldInput" name="jsk-User-login-login"' + JSKitAuth.prototype.autoComplete +'>' +
			'<div class="jsk-SectionLoginMessage js-loginMessageHandle"></div>' +
		'</div>' +
		'<div class="js-authLabel js-passwordLblHandle">{Label:password}</div>' +
		'<div class="js-authContainer">' +
			'<input size="32" class="js-commentFieldInput" name="jsk-User-login-password" type="password">' +
			'<div class="jsk-SectionLoginMessage js-passwordMessageHandle"></div>' +
		'</div>' +
		'<div class="js-authContainer">' +
			'<input value="{Label:loginBtn}" name="Login" style="margin-left: 0px;" class="js-authButton" type="button">' +
		'</div>' +
	'</div>';

	var haloscanLoginTmpl =
	'<div style="clear: both;">' +
		JSKitAuth.prototype.progressAreaTmpl +
		'<div class="js-authLabel js-loginLblHandle">{Label:haloscanLogin}:</div>' +
		'<div class="js-authContainer">' +
			'<input size="32" class="js-commentFieldInput" name="jsk-User-login-login"' + JSKitAuth.prototype.autoComplete +'>' +
			'<div class="jsk-SectionLoginMessage js-loginMessageHandle"></div>' +
		'</div>' +
		'<div class="js-authLabel js-passwordLblHandle">{Label:haloscanPassword}</div>' +
		'<div class="js-authContainer">' +
			'<input size="32" class="js-commentFieldInput" name="jsk-User-login-password" type="password">' +
			'<div class="jsk-SectionLoginMessage js-passwordMessageHandle"></div>' +
		'</div>' +
		'<div class="js-authContainer">' +
			'<input value="{Label:loginBtn}" name="Login" style="margin-left: 0px;" class="js-authButton" type="button">' +
		'</div>' +
	'</div>';

	var openIdTmpl =
	'<div style="clear: both">' +
		JSKitAuth.prototype.progressAreaTmpl +
		'<div class="js-authLabel js-loginLblHandle">{Label:openID}</div>' +
		'<div class="js-authContainer">' +
			'<input size="32" class="js-commentFieldInput" name="jsk-User-login-login"' + JSKitAuth.prototype.autoComplete + '>' +
			'<div class="jsk-SectionLoginMessage js-loginMessageHandle"></div>' +
		'</div>' +
		'<div class="js-authContainer">' +
			'<input value="{Label:loginBtn}" name="Login" style="margin-left: 0px;" class="js-authButton" type="button">' +
		'</div>' +
	'</div>';

	if (tc['js-CmtName']) tc['js-CmtName'].className = "js-commentFieldInput";
	if (tc['js-CmtEmail']) tc['js-CmtEmail'].className = "js-commentFieldInput";
	if (tc['js-CmtText']) tc['js-CmtText'].className = "js-commentFieldInput";

	if (tc['js-commentInputOpenID']) tc['js-commentInputOpenID'].style.display = "none";

	var authAreaContainer = JSKitLib.html(s.gtmpl(authAreaTmpl));
	tc['js-AuthAreaWrap'].appendChild(authAreaContainer);
	JSKitLib.mapClass2Object(tc, authAreaContainer);

	var serverRequest = function() {
		var prms = {'jx': s.jcaIndex};
		JSKitLib.fmap(arguments[1], function(v, k) {
			if(typeof(v)=='function') {
				if(!s.CB) s.CB = [];
				s.CB.push(v);
				prms[k] = s.CB.length-1;
			} else {
				prms[k] = v;
			}
		});
		arguments[1] = prms;
		return s.server.apply(s, arguments);
	}

	var normalizeOpenID = function(oid) {
		var m = oid.match(/^http:\/\/([a-z0-9\.\-]+?).js-kit.com\/$/);
		if(m) return {type: "jskit", login: m[1]};
		return {type: "openid", login: oid.replace(/https?:\/\/(.*?)\/$/, '$1')};
	}

	var setYahooShare = function() {
		var po = tc["js-commentPubOptions"];
		if(!po) return;
		JSKitLib.removeChildren(po);
		if(!s.serverOptions.yahoo) return;
		var publish = s.serverOptions.yahoo.publish;
		var inp = s.cr("input");
		inp.className = "js-commentYahooShareCheckbox";
		inp.type = "checkbox";
		inp.defaultChecked = !!publish;
		inp.checked = !!publish;
		inp.value = inp.checked ? "on" : "off";
		inp.name = 'js-CmtYahooShare';
		inp.onchange = function() {
			this.value = this.checked ? "on" : "off";
		};
		var divtxt = s.cr("div");
		divtxt.className = "js-commentYahooShareLabel";
		var txt = document.createTextNode($JCL('shareYahoo'));
		divtxt.appendChild(txt);
		var lbl = s.cr("div");
		lbl.className = "js-commentYahooShareLabelLogo";
		po.appendChild(inp);
		po.appendChild(divtxt);
		po.appendChild(lbl);
	}

	var calcLogin  = function(login) {
		var getPostFix = function(type) {
			var r;
			switch(type) {
			case "facebook": r = " @ Facebook"; break;
			case "yahoo": r = " @ Yahoo"; break;
			default: r = "";
			}
			return r;
		}
		var soll = s.serverOptions.lastLogin;
		if(soll && (soll.type != "yahoo" || s.serverOptions.yahoo)
		&& (soll.type != "facebook" || s.serverOptions.facebook)) {
			var normLogin =
				soll.type == "openid" ?
				normalizeOpenID(soll.login).login : soll.login;
			return normLogin
				+ getPostFix(soll.type);
		}
		var rslt;
		if(s.serverOptions.facebook && s.serverOptions.facebookLogin)
			rslt = s.serverOptions.facebook.name
				+ getPostFix("facebook");
		if(s.serverOptions.yahoo && s.serverOptions.yahooLogin)
			rslt = s.serverOptions.yahoo.name
				+ getPostFix("yahoo");
		return (rslt ? rslt + (login ? " / " + login : "") : login );
	}

	var defaultOptions = 
		[{value : "opt-anonymous", 
		text  : function(){ return (calcLogin() || $JCL('guest'));}},
		{value : "opt-login",
		text  : $JCL('existingJSKitProfile')},
		{value : "opt-register",
		text  : $JCL('newJSKitProfile')},
		{value : "opt-haloscan-login",
		text  : $JCL('existingHaloscanProfile')},
		{value : "opt-openid",
		text  : $JCL('usingOpenID')},
		{value : "opt-facebook",
		guard: function(){return s.serverOptions.facebook || !s.serverOptions.facebookLogin ? 0:1;},
		text  : $JCL('connectFacebook')},
		{value : "opt-yahoo",
		guard: function(){return s.serverOptions.yahoo || !s.serverOptions.yahooLogin ? 0:1;},
		text  : $JCL('connectYahoo')}
	];

	var buildLoggedOptions = function(login){ return(
		[{value : "opt-user",  
		text  : calcLogin(login)},
		{value : "opt-login", 
		text  : $JCL('existingJSKitProfile')},
		{value : "opt-haloscan-login",
		text  : $JCL('existingHaloscanProfile')},
		{value : "opt-openid",
		text  : $JCL('usingOpenID')},
		{value : "opt-facebook",
		guard: function(){return s.serverOptions.facebook || !s.serverOptions.facebookLogin ? 0:1;},
		text  : $JCL('connectFacebook')},
		{value : "opt-yahoo",
		guard: function(){return s.serverOptions.yahoo || !s.serverOptions.yahooLogin ? 0:1;},
		text  : $JCL('connectYahoo')}
	]);
	}

	var options = (s.openId ? buildLoggedOptions(s.openId) : defaultOptions);

	var JSKAuth = new JSKitAuth("comments", s.uriDomain);
	JSKAuth.bindServerRequestFunction(serverRequest);

	var onSuccessLoginAction = function(eventName, data) {
		s.serverOptions.lastLogin = {
			'type': 'openid',
			'login': data['yours']['openid-tie']};
		showActualInfo(
			data['yours']['openid-tie'], 
			data['yours']['Name'], 
			data['yours']['Email']);
		s.openID = data['yours']['openid-tie'];	
		s.refreshComments();
	}

	var registerArea = JSKAuth.createRegisterArea(onSuccessLoginAction, s.gtmpl(registerTmpl));
	var openIdArea = JSKAuth.createOpenIdArea(onSuccessLoginAction, s.gtmpl(openIdTmpl));
	var facebookArea = JSKAuth.createFacebookArea(onSuccessLoginAction, s.gtmpl(JSKAuth.facebookAreaTmpl));
	var yahooArea = JSKAuth.createYahooArea(onSuccessLoginAction, s.gtmpl(JSKAuth.yahooAreaTmpl()));
	var loginArea = JSKAuth.createLoginArea(onSuccessLoginAction, s.gtmpl(loginTmpl));
	var haloscanLoginArea = JSKAuth.createLoginArea(onSuccessLoginAction, s.gtmpl(haloscanLoginTmpl), {isHaloscan: true});

	var authArea = tc['js-authArea'];
	if (authArea) {
		JSKitLib.fmap([openIdArea, loginArea, haloscanLoginArea, registerArea], function(el){authArea.appendChild(el.container);});
	}

	var showActualInfo = function(openID, name, email) {
		if (tc['js-CmtName']) {
			JHI2.remove(tc['js-CmtName']);
			tc['js-CmtName'].value = name || '';
		}
		
		if (email) {tc['js-CmtEmail'].value = email} 
		else {
			var o = tc['js-CmtEmail'];
			if(o) {
				o.style.color = '#808080';
				o.value = $JCL('email es ' + (s.adminMode ? 'mandatory for you (admin)' : 'opcional'));
				o.jsk$setdfl = function(val) {
					o.style.color = '';
					o.jsk$setdfl = false;
					o.value = val || '';
				}
				o.onfocus = function() { if(o.jsk$setdfl) o.jsk$setdfl(); }
			}
		}

		if (authArea){
			authArea.style.display = "none";
			authArea.style.border = "";
		}

		if (openID || s.serverOptions.facebook || s.serverOptions.yahoo) {
			var oiddiv = tc['js-logoutSpan'];
			if (oiddiv) oiddiv.style.display = 'inline';
		}
		if (openID) {
			var openid = String(openID);
			var curLogin = normalizeOpenID(openid);
			JSKitAuth.prototype.reDrawSelector(authSelector, buildLoggedOptions(curLogin.login));
		} else {
			JSKitAuth.prototype.reDrawSelector(authSelector, defaultOptions);
		}
		setYahooShare();
	}

	var onYahooLogin = function(error, data) {
		if(error!="data") return;
		if(!data.name) {
			alert("Can not process yahoo data");
			return;
		}
		s.serverOptions.yahoo = { name: data.name, publish: data.publish };
		data = {yours: {
				'Name': data.name,
				'Email': data.email || ''
			}
		};
		s.serverOptions.lastLogin = {
			'type': 'yahoo',
			'login': data['yours']['Name']};
                showActualInfo(
			null,
                        data['yours']['Name'],
                        data['yours']['Email']);
		s.refreshComments();
	}

	var onFacebookLogin = function(error, data) {
		if(error!="data") return;
		s.serverOptions.facebook = { name: data.name };
		data = {yours: {
				'Name': data.name,
				'Email': data.email || ''
			}
		};
		s.serverOptions.lastLogin = {
			'type': 'facebook',
			'login': data['yours']['Name']};
                showActualInfo(
			null,
                        data['yours']['Name'],
                        data['yours']['Email']);
		s.refreshComments();
	}

	var onchange = function(ev) {
		JSKitLib.fmap([openIdArea, facebookArea, yahooArea, loginArea, haloscanLoginArea, registerArea], function(el){if(el.container.parentNode==authArea)el.container.style.display = 'none'; try{el.rpickup.cancelRequest()}catch(e){}; });
		switch (this.value) {
			case "opt-user":
				authArea.style.display = "none";
				authArea.style.border = "";
			break;
			case "opt-anonymous":
				authArea.style.display = "none";
				authArea.style.border = "";
			break;
			case "opt-login":
				var selectedArea = loginArea.container;
			break;
			case "opt-haloscan-login":
				var selectedArea = haloscanLoginArea.container;
			break;
			case "opt-register":
				var selectedArea = registerArea.container;
			break;
			case "opt-openid":
				var selectedArea = openIdArea.container;
			break;
			case "opt-facebook":
				var selectedArea = facebookArea.container;
				if(selectedArea.parentNode!=authArea)
					authArea.appendChild(selectedArea);
				facebookArea.rpickup = new JSRVC({uri: s.uriDomain + '/api/server-answer.js', 'target': this.target, 'onreturn': onFacebookLogin, 'pickup': true, 'requestId': 'facebook_connect'});
			break;
			case "opt-yahoo":
				var selectedArea = yahooArea.container;
				if(selectedArea.parentNode!=authArea)
					authArea.appendChild(selectedArea);
				yahooArea.rpickup = new JSRVC({uri: s.uriDomain + '/api/server-answer.js', 'target': this.target, 'onreturn': onYahooLogin, 'pickup': true, 'requestId': 'yahoo_connect'});
			break;
		}
		
		if (selectedArea) {
			selectedArea.style.display = "block";      
			authArea.style.display = 'block';
			authArea.style.border = "1px solid #7f99b9";
		}
	}

	var authSelector = JSKitAuth.prototype.createAuthSelector(options, 0, onchange);
	tc['js-authSelector'].insertBefore(authSelector, tc['js-logoutSpan']);

	if (s.openID || s.serverOptions.facebook || s.serverOptions.yahoo)
		showActualInfo(s.openID);
	s.preventAnonymousComments();

	var onLogout = function(eventName) {
		JSKitAuth.prototype.reDrawSelector(authSelector, defaultOptions);
		authArea.style.display = "none";
		authArea.style.border = "";
		if (tc['js-CmtName']) {
			JHI2.create($JCL('guest'), tc['js-CmtName']);
			tc['js-CmtName'].value = "";
		}
		if (tc['js-CmtEmail']) tc['js-CmtEmail'].value = "";
		var oiddiv = s.TC['js-logoutSpan'];
		if (oiddiv) { oiddiv.style.display = 'none'; }
		s.openID = 0;
		setYahooShare();
		setTimeout(function(){
			s.refreshComments();
		}, 0);
	}
	JSKAuth.eventsCtx = JSKW$Events.registerEventCallback(JSKAuth.eventsCtx, onLogout, 'JSKitAuth_logout');
}

JSCC.prototype.logoutUser = function(cb) {
	var s = this;
	var clearAndCb = function() {
		s.serverOptions.facebook = undefined;
		s.serverOptions.yahoo = undefined;
		s.serverOptions.lastLogin = undefined;
		s.fieldDfl = [];
		if(cb) cb();
	}
	if(s.serverOptions.facebook) {
		var div = document.createElement('div');
		var tgt = 'jsk-ifrmpost-logout-' + Math.random();
		div.innerHTML = '<iframe id="' + tgt + '" name="' + tgt + '" src="about:blank" width=0 height=0 style="border: none"></iframe>';
		s.target.appendChild(div);
		var iframe = div.firstChild;
		var form = document.createElement('form');
		form.method = 'POST';
		form.action = 'http://www.facebook.com/logout.php';
		form.target = tgt;
		form.enctype = 'application/x-www-form-urlencoded';
		var frmel = document.createElement('INPUT');
		frmel.type = "hidden";
		frmel.name = "confirm";
		frmel.value = "1";
		form.appendChild(frmel);
		div.appendChild(form);
		var f = function() {
			if(iframe.readyState && iframe.readyState != 'loaded'
				&& iframe.readyState != 'complete') return;
			iframe.onload = iframe.onreadystatechange = null;
			clearAndCb();
		}
		iframe.onload = iframe.onreadystatechange = f;
		form.submit();
		return;
	}
	clearAndCb();
}

JSCC.prototype.dataLoader = function(so, nc) {
	var s = this;
	var tc = s.TC;
	var d=function(){return s.div.apply(s,arguments);}
	
	if (this.config.disabled != 'no') return;

	var cc = JSKitLib.html(s.gtmpl(s.utmpl['js-CreateComment'] || (s.config.nolc ? s.dtProfileCreate : s.dtCreate)));
	JSKitLib.mapClass2Object(tc, cc);
	var ec = JSKitLib.html(s.gtmpl(s.dtEditComment));
	JSKitLib.mapClass2Object(tc, ec);
	if(s.config.profileLC) {
		var cin = tc['js-commentInputName'];
		if(cin) cin.style.display = 'none';
		var cie = tc['js-commentInputEmail'];
		if(cie) cie.style.display = 'none';
	}
	var ac = function(name, cb) {
		var o = tc['js-'+name];
		if(!o) return;
		if(o.tagName == 'A') o.href="javascript:void(0);";
		o.style.cursor = 'pointer';
		o.onselectstart = function() { return false; }
		o.onclick = cb;
	}

	var uInp = tc['js-uploadImageInput'];
	var uInpW = tc['js-uploadImageInputWrapper1'];
	
	s.clearImgs = function(){
		JSKitLib.removeChildren(s.imgArea);
		if(uInpW) uInpW.style.paddingTop = '0px';
		if(uInp && uInp.ifri) {
			JSKitLib.removeChildren(uInp);
			JSKitLib.hide(uInp);
			uInp.ifri = undefined;
		}
		if(s.images) delete(s.images);
	}

	JSKitLib.fmap(['', 'Edit'], function(el, i) {
		ac('Cmtsubmit' + el, function() { s.CommentSubmitted(); return false; });
		ac('Cmtcancel' + el, function() { s.clearImgs(); if(s.onCancel) s.onCancel(); return s.CommentCancelled();
		});
	});
	if (JSKitLib.isIE()) {
		var op = tc['js-commentOptions'];
		var sub = tc['js-commentSubmit'];
		if (op) op.style.paddingLeft = "3px";
		if (sub) sub.style.paddingLeft = "3px";
	}
	if (!(s.openID || (s.serverOptions.facebookLogin && s.serverOptions.facebook) || (s.serverOptions.yahooLogin && s.serverOptions.yahoo))) {
		JHI2.create($JCL('guest'), tc['js-CmtName']);
	}
	var n = tc['js-CmtName']; 
	n.jsk$setdfl = function(val) { 
		n.jsk$setdfl = false; 
		n.value = val || ''; 
	}

	var o = tc['js-CmtEmail'];
	if(o) {
		o.style.color = '#808080';
		o.value = $JCL('email es ' + (s.adminMode ? 'mandatory for you (admin)' : 'opcional'));
		o.jsk$setdfl = function(val) {
			o.style.color = '';
			o.jsk$setdfl = false;
			o.value = val || '';
		}
		o.onfocus = function() { if(o.jsk$setdfl) o.jsk$setdfl(); }
	}
	s.anonymousCmt = so.anonymousCmt;

	/* Handling avatars area */
	var avatarArea      = tc["js-commentAvatar"];
	var avatarsListArea = tc["js-commentAvatarArea"];

	var avatars = (this.serverOptions.avatars) ? this.serverOptions.avatars : []; 

	if (this.config.nolc != true && this.config.avatars == 'yes' && avatarsListArea) {

		var self = this;
		var config = { uriDomain  : this.uriDomain, 
				uriAvatar  : this.uriAvatar,
				avatars    : avatars,
				controls   : [ tc["js-Cmtsubmit"] ],
				avatarArea : avatarArea,
				widgetIndex : this.jcaIndex,
				avatarsListArea : avatarsListArea };

		this.avatarsManagement = new JSKitAvatarsManagement(config);
		this.avatarsManagement.useOptionsButton = (avatarArea) ? false : true;
		this.avatarsManagement.getLangLabelText = $JCL;
		this.avatarsManagement.bindServerRequestFunction(function() { return self.server.apply(self, arguments); });
		this.avatarsManagement.removeAvatarFromServer = function(chosenAvatar) { 
			self.runscr(self.uriAvatar + "remove?avrm=" + encodeURIComponent(chosenAvatar));
		};
      		this.avatarsManagement.buildAvatarArea();
		this.avatarsManagement.buildAvatarsListArea(this);

	}

	s.wrapJSKAuth();

	ac('commentOpenIDLogout', function() {
		setTimeout(function(){
			s.logoutUser(function() {
				s.server(s.uriDomain + '/api/session/logout.js', {});
			});
		}, 0);
		return false;
	});

	if(!tc['js-commentMore'] && s.config.avatars != 'yes') { 
		var m = tc['js-CCMore']; 
		if(m) m.style.display = 'none'; 
	} 

	var handler = function(e){
		e = e || window.event;
		if(e.keyCode == 27 || e.which == 27) JSKitLib.preventDefaultEvent(e);
	};
	var blockEsc = function(){
		if (document.addEventListener) 
			document.addEventListener("keydown", handler, true);
		else if (document.attachEvent) 
			document.attachEvent("onkeydown", handler);
	}	
	var unblockEsc = function(){
		if (document.removeEventListener)
			document.removeEventListener("keydown", handler, true);
		else if (document.detachEvent)
			document.detachEvent("onkeydown", handler);
	}

	s.onAddImgButton = function(isShow){
		if(s.config.uploadImages) {
			s.imgArea = tc['js-commentImageArea'];
			if(uInp && s.imgArea) {
				uInp.style.display = isShow ? 'block' : 'none';
				if(uInpW) uInpW.style.paddingTop = isShow ? '15px' : '0px';
				s.imgShow = isShow;
			}
		}
		if (uInp && !uInp.ifri){
			var val;
			var tgti = 'js-ifrm-'+s.jcaIndex + Math.random();
			uInp.innerHTML = '<iframe name="'+tgti+'" width=0 height=0 style="border: none; display:none;"></iframe>';
			var ifri = uInp.firstChild;
			var frmi = s.cr('form');
			JSKitLib.setStyle(frmi, "clear: both;");
			JSKitLib.addClass(frmi, "js-uploadImageForm");
			frmi.method = 'post';
			frmi.acceptCharset = 'UTF-8';
			frmi.encoding = 'multipart/form-data';
			frmi.target = tgti;
			frmi.style.margin = "0px";
			var lbli = s.cr('div');
			s.lbliChange = function(mode) {
				JSKitLib.removeChildren(lbli);
				lbli.appendChild(document.createTextNode(
					mode ? $JCL("Cargando...")
					     : $JCL("uploadImage")));
			}
			s.lbliChange(0);
			var upfi = s.cr('input');
			s.imgUpload = upfi; 
			upfi.disabled = ( s.imgArea && s.imgArea.disableUpload ) ? true : false ;
			upfi.type = 'file';
			upfi.name = 'image';
			upfi.onchange = function() {
				val = (new Date()).getUTCMilliseconds() + "-" + Math.random( );
				frmi.action = s.uriImage+'add?rnd='+val;
				s.lbliChange(1); frmi.submit();
				var subi = s.TC["js-Cmtsubmit"];
				subi.disabled = true;
				upfi.disabled = true;
				blockEsc();
			};
			uInp.appendChild(lbli)
			frmi.appendChild(upfi);
			uInp.appendChild(frmi);
			s.onCancelI = function() {
				var subi = s.TC["js-Cmtsubmit"];
				subi.disabled = false;
				upfi.disabled = false;
				frmi.reset();
				unblockEsc();
			}
			var fi = function() { 
				if(val) {
					s.onCancelI();
					s.getImages(val);
				}
			}
			ifri.onreadystatechange = function() {
				if(ifri.readyState == 'complete') fi();
			}
			ifri.onload = fi;
			uInp.ifri = ifri;
		}
	}
	
	var uImg = tc['js-uploadImageButton'];
	if (uInp) JSKitLib.hide(uInp);
	if(uInp && uImg && !s.config.uploadImages) {
		JSKitLib.hide(uImg);
		JSKitLib.hide(uInp);
	}
	ac('uploadImageButton', function(){
		s.onAddImgButton(!JSKitLib.visible(uInp));
	});
	
	var onCommentMore = function(obj, label) {
		obj.ashown = !obj.ashown;
		if (!s.openID && !tc['js-AuthAreaWrap']) {
			var oiddiv = tc['js-commentInputOpenID'];
			if (oiddiv) {oiddiv.style.display = obj.ashown ? 'block' : 'none';}
		}
		s.text(obj, obj.ashown ? label.less : label.more);
                if (s.avatarsManagement && s.avatarsManagement.useOptionsButton) s.avatarsManagement.changeAvatarsListStatus();
		s.onAddImgButton(obj.ashown);	
		if(!obj.ashown) return false;

		return false;
	};

	ac('commentAddAvatar', function() {
		var label = {'less': '-', 'more': '+'};
		return onCommentMore(this, label);
	});
	ac('commentMore', function() {
		var label = {'less': this.getAttribute("less") || $JCL('less'),
			'more': this.getAttribute("more") || $JCL('more') };
		return onCommentMore(this, label);
	});

	var amCondition = (s.avatarsManagement && s.avatarsManagement.useOptionsButton);
	var authCondition = (tc['js-AuthAreaWrap']) ? true : false;

	if (!amCondition && (s.openID || (!s.openID && authCondition))) {
		JSKitLib.fmap(['js-commentMore', 'js-CCMore'], function(element) { if (tc[element]) JSKitLib.hide(tc[element]); });
	}

	s.labelHTML = s.labelHTML || 'leaveComment';

	if(so.mmode == "pause") {
		var lca = null;
	} else {
		var lca = d('js-commentControl', s.a($JCL(s.labelHTML)));
		lca.onclick = function() { return s.ShowCommentDialog(); };
	}

	var jmg = d('js-commentControl js-commentTool', JSKitLib.html('<font face="Webdings">&#32;&nbsp;</font>'), s.a($JCL("")));
	jmg.onclick = function() {
		var srt = ["date", "name"];
		if(!s.config.moderate && s.scoringEnabled()) srt.push("karma");
		if(s.adminMode) srt.push("status");
		/* s.submitRating check is not good for all the cases */
		if ( $JSKitGlobal.isRatingsAppAvailable() ) srt.push("rating");
		var srtOpts = [];
		for(var i = 0; i < srt.length; i++) {
			srtOpts.push('<option value="'+srt[i] + '"'
				+ (srt[i]==s.preq.srt?" selected":"")+'>'
				+$JCL(srt[i])+'</option>');
		}
		var bkw = ["ascending", "descending"];
		var bkwOpts = [];
		for(var i = 0; i < bkw.length; i++) {
			bkwOpts.push('<option value="'+bkw[i]+'"'
				+ ((!!i) == (s.preq.ord=='desc')?" selected":"")+'>'
				+$JCL(bkw[i])+'</option>');
		}
		var prs = ["on (threaded)", "off (flat)"];
		var prsMap = {'on (threaded)':'yes','off (flat)':'no'}
		var prsOpts = [];
		for(var i = 0; i < prs.length; i++) {
			prsOpts.push('<option value="'+prsMap[prs[i]]+'"'
				+ (prsMap[prs[i]] == s.preq.thr?" selected":"")+'>'
				+$JCL(prs[i])+'</option>');
		}
		var div = s.cr("div");
		div.innerHTML = 
			"<table border=0 cellpadding=4>"
			+ "<tr><td align=right>" + $JCL("Sort by") + '</td><td align=left><select name="jss-srt" onchange="$JCA['+s.jcaIndex+'].viewControl(this);return true;">'
			+ srtOpts.join("")
			+ "</select></td></tr>"
			+ "<tr><td align=right>" + $JCL("Order") + '</td><td align=left><select name="jss-rev" onchange="$JCA['+s.jcaIndex+'].viewControl(this);return true;">'
			+ bkwOpts.join("")
			+ "</select></td></tr>"
			+ "<tr><td align=right>" + $JCL("Threading") + '</td><td align=left><select name="jss-prs" onchange="$JCA['+s.jcaIndex+'].viewControl(this);return true;">'
			+ prsOpts.join("")
			+ "</select></td></tr>"
			+ "<tr><td align=right>" + $JCL("Search") + '</td><td id="js-SearchCell-'+s.jcaIndex+'" align=left></td></tr>'
			+ (s.adminMode && !s.config.moderate?('<tr><td align=center colspan=2><a href="'+s.uriDomain+'/moderate/'+s.config.domain+'" onclick="window.location.href = this.href; return true;">Moderate whole site</a></td></tr>'):'')
			+ "</table>"
		this.notShowIfr = true;
		s.settingsWindow('ctWnd', this, div);
                var obj={'mode': 'form', 'inpSize': '121px', type: 'Search'};
                var form = new JSIPE(obj);
                obj.jsk$on_submit_exit = function(){
                        s.searchString = form.input.value;
                        s.viewControl({name: "search"});
			s.hideSettingsWindow('ctWnd');
                }
		form.input.value = s.searchString || "";
		if (s.searchString) form.cleaner.style.visibility = "visible";
		var sCell = document.getElementById("js-SearchCell-"+s.jcaIndex);
		if (sCell) s.addChild(sCell, form.main);

		return false;
	}
	s.controls = jmg;
	if(nc || s.config.moderate) {
		s.controls.reveal = function(){};
	} else {
		s.controls.style.display = 'none';
		s.controls.reveal = function(){s.controls.style.display=''}
	}

	if(so.subs || so.noJunk) {
		var pb = "";
	} else {
		/*var propLink = JSKitLib.html('<a href="http://js-kit.com/comments?wow" target="js-kit">quite</a>');
		var prop = d('', "(", propLink, ")");
		prop.style.position = 'relative';
		var pb = d("js-commentControl js-poweredBy", prop);*/
	}

	var ca = d("js-CommentsArea",
		(s.config.nolc && !s.IM)?null:d("js-LeaveComment", s.config.moderate || s.IM=='own' ?null:lca, s.IM ? null : jmg, !s.config.nolc ? pb : null,
			JSKitLib.html('<br clear="all"/>')),
		tc["js-CreateComment"], tc["js-EditComment"]);
	this.makeWelcomePanel();

	if (!so.wysiwyg && so.smiley) {
		JSKitLib.fmap(['Text', 'TextEdit'], function(v) {
			var sd = s.cr('div');
			sd.style.margin = '3px 0px 0px 3px';
			var text = tc['js-Cmt' + v];
			var processed = {};
			var index = 0;
			JSKitLib.fmap(s.smiles, function(el, i) {
				if (!processed[el.file]) {
					processed[el.file] = 1;
					var smile = JSKitLib.html(s.smileTag(el));
					smile.style.cursor = 'pointer';
					smile.style.marginRight = '5px';
					smile.onclick = function() {
						text.value += ' ' + i;
						text.focus();
						if (JSKitLib.isSafari()) {
							text.setSelectionRange(text.value.length, text.value.length);
						}
					};
					sd.appendChild(smile);
					if (s.getSkin() != 'smoothgray' && !(++index % 8)) {
						sd.appendChild(JSKitLib.html('<br>'));
					}
				}
			});
			text.parentNode.insertBefore(sd, text.nextSibling);
		});
	}

	var pageNavTop = d('js-PageNavTop');
	var pageNavBottom = d('js-PageNavBottom');
	s.addChild(ca, d(null, pageNavTop, d("js-OldCommentsWrap", d("js-OldComments")), pageNavBottom), !s.backwards);
	var pageToDisplay = so.pages.sp;
	var dpCB;
	if(s.config.comment_location) {
		var obj = s.jspg.getItemById(s.config.comment_location);
		if(obj) {
			pageToDisplay = s.jspg.getPageByItemId(s.config.comment_location) + 1;
			dpCB = function() {
				if(obj.div) s.flash(obj.div);
			};
		}
		delete s.config.comment_location;
	}
	s.displayPage(pageToDisplay, dpCB);

	var closeControlsPopup = function() {
                s.hideSettingsWindow('ctWnd');
                s.hideSettingsWindow('ctBlock');
	}
	JSKW$Events.registerEventCallback(undefined, closeControlsPopup, "comments_closeControlsPopup");

	ca.onclick = function() {
		closeControlsPopup();
	}
	s.addChild(s.target, ca);
	if(lca && ((s.config.nolc && s.IM=='foreign') || (so.expandLeaveCmt && !s.config.noautoexpand)) && !s.config.moderate) {
		s.ShowCommentDialog(undefined, {nofocus: true});
	}

	JSKitLib.deferCall(function() {
		var trIfrId = 'jsk-ifrtr-c' + s.jcaIndex;
		if (document.getElementById(trIfrId)) return;
		var div = s.cr('div');
		div.innerHTML = '<iframe id="' + trIfrId + '" name="' + trIfrId + '" src="' + s.uriDomain + '/api/static/landing.html" frameborder="0" height="0" width="0"></iframe>';
		s.target.appendChild(div);
	});
}

JSCC.prototype.objRerender = function(obj, cmt) {
	cmt.ctls['js-singleCommentText'].innerHTML =
		this.tmpl("{Text}", obj, true);
}

JSCC.prototype.getLastReply = function(pobjId) {
	var pobj = this.jspg.getItemById(pobjId);
	var lreplyObj = null;
	for(var i=pobj.obj.thread.length-1; i>=0; i--){
		if(pobj.obj.thread[i].status!='D') {
			var c = this.jspg.getItemById(pobj.obj.thread[i].ID);
			if(c) {
				lreplyObj = this.getLastReply(c.obj.ID);
				break;
			}
		}
	}
	return lreplyObj || pobj;
}

JSCC.prototype.reCalcPages = function() {
	if(this.curPage>this.jspg.pageCount) this.displayPage(this.jspg.pageCount);
	this.rePageNavigator(this.jspg.pageCount>0 ? this.jspg.pageCount-1 : undefined);
}

JSCC.prototype.appendConversation = function (cmt, conversation) {
	var cnvsObj = {};
	var cnvs = this.conversations[conversation];
	var self = this;
	if(!cnvs) return;
	JSKitLib.fmap(["Name","avatar","avatarHeight","avatarWidth"],
		function(V){ cnvsObj[V] = cnvs.direction=="in" ? cnvs[V] : cnvs["dest"+V] });
	cnvsObj.Label = "Conversation with ";
	var dtc = JSKitLib.html(this.tmpl(this.dtConversation, cnvsObj));
	var ctls = JSKitLib.mapClass2Object({}, dtc);
	var nm = ctls['js-ConversationName'];
	if(nm && this.serverOptions.showProfile) {
		nm.style.textDecoration = 'underline';
		nm.style.cursor = 'pointer';
		nm.onclick = function() {
			self.showProfile(nm, {profile: cnvs.profile}, self.serverOptions.profileLevel);
			return false;
		}
	}
	cmt.insertBefore(dtc, cmt.firstChild);
	JSKitLib.addClass(cmt, "js-singleCommentConversationHead");
}

JSCC.prototype.removeConversation = function (cmt) {
	JSKitLib.removeClass(cmt, "js-singleCommentConversationHead");
	cmt.removeChild(cmt.firstChild);
}

JSCC.prototype.appendConversationChild = function (cmt) {
	JSKitLib.addClass(cmt, "js-singleCommentConversationChild");
}

JSCC.prototype.removeConversationChild = function (cmt) {
	JSKitLib.removeClass(cmt, "js-singleCommentConversationChild");
}

JSCC.prototype.getSkin = function() {
	return this.config.skin==="wireframe" ? "" : (this.config.skin || "");
}

JSCC.prototype.processServerRequestEvent = function(eventName, jcaIndex, cmtId) {
	if(this.jcaIndex!=jcaIndex) return;
	var item = this.jspg.getItemById(cmtId);
	if(!item || !item.div) return;
	var div = item.div;
	var self = this;
	if(eventName=="comments_serverRequest_deleting" ) {
		if(div.domCtls) div.domCtls.style.visibility = "hidden";
		var av = div.ctls['js-singleCommentAvatar'];
		this.placeProcessAvatar(av);
		item.obj.origstatus = item.obj.status;
		item.obj.status = 'DP';
		item.obj.dTimer = setTimeout(function(){
			item.obj.status = 'A';
			if(div.domCtls) div.domCtls.style.visibility = "";
			if(av && item.obj.avatar) self.placeAvatar(item.obj, av);
			delete item.obj.dTimer;
		}, 30000);
	}
	if(eventName=="comments_serverRequest_deleted") {
		if(item.obj.dTimer) clearTimeout(item.obj.dTimer);
		this.removeComment(div, true);
	}
}

JSCC.prototype.makeWelcomePanel = function() {
	var s = this;
	if (s.jcaIndex) return;
	if (!s.adminMode) {
		s.deleteWelcomePanel();
		return;
	}
	if (s.TC['js-WelcomePanel'] || s.config.moderate || s.config.nolc) return;

	var wp_html = ''
	+ '<div class="js-WelcomePanel' + (s.backwards ? '' : ' js-WelcomePanelBottom') + '"' + (s.serverOptions.welcome ? '' : ' style="display: none"') + '>'
		+ '<div class="js-WelcomePanelTitle"><div class="js-WelcomePanelClose"></div>{Label:adminNote}</div>'
		+ '<div class="js-WelcomePanelContent">'
			+ '<div class="js-WelcomePanelHeader"><div class="js-WelcomeImgInfo"></div>{Label:Welcome}</div>'
			+ ((s.serverOptions.welcome || {}).message || $JCL('welcomeToComments'))
			+ '<div>'
			+ '<div class="js-WelcomePanelContentBlock" style="padding-right: 50px">'
				+ '<b>{Label:Get started}:</b>'
				+ '<table border="0" cellspacing="0" cellpadding="0">'
				+ '<tr style="display: none"><td><div class="js-WelcomeImgProfile"><a href="javascript:void(0);" class="js-WelcomeProfileLink">{Label:editProfile}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgHelp"><a href="' + s.uriDomain + '/comments/faq.html">{Label:readFAQ}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgCustom"><a href="' + s.uriDomain + '/comments/custom.html#custom_div">{Label:customizeLook}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgDashboard"><a href="' + s.uriDomain + '/settings/">{Label:adminDashboard}</a></td></div></tr>'
				+ '</table>'
			+ '</div>'
			+ '<div class="js-WelcomePanelContentBlock">'
				+ '<b>{Label:Get involved}:</b>'
				+ '<table border="0" cellspacing="0" cellpadding="0">'
				+ '<tr><td><div class="js-WelcomeImgTwitter"><a href="http://twitter.com/jskit">{Label:followTwitter}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgSupport"><a href="' + s.uriDomain + '/comments/qa.html">{Label:contactSupport}</a></div></td></tr>'
				+ '<tr><td><div class="js-WelcomeImgWidgets"><a href="' + s.uriDomain + '">{Label:checkWidgets}</a></div></td></tr>'
				+ '</table>'
			+ '</div>'
			+ '<br style="clear: both" />'
			+ '</div>'
		+ '</div>'
		+ '<div class="js-WelcomePanelArrow"></div>'
	+ '</div>';
	var wp = JSKitLib.html(s.gtmpl(wp_html));
	JSKitLib.mapClass2Object(s.TC, wp);
	s.TC['js-WelcomePanelClose'].onclick = function() {
		s.TC['js-WelcomePanel'].style.display = 'none';
		if (s.serverOptions.welcome && s.serverOptions.welcome.ts) {
			s.server('s-welcome-close', {'ts': 
					s.serverOptions.welcome.ts});
		}
	}
	s.TC['js-WelcomeProfileLink'].onclick = function() {
		s.showProfile(this, {profile: s.serverOptions.profile});
	}
	JSKitLib.addPNG(s.TC['js-WelcomePanelArrow'], s.uriDomain + "/images/welcome/triangle.png");
	var lc = s.TC['js-LeaveComment'];
	if (lc) lc.parentNode.insertBefore(wp, lc);
}

JSCC.prototype.deleteWelcomePanel = function() {
	if (this.TC['js-WelcomePanel']) {
		this.TC['js-WelcomePanel'].parentNode.removeChild(this.TC['js-WelcomePanel']);
		delete this.TC['js-WelcomePanel'];
	}
}

/* Must be last to support Opera */
JSCC.prototype.newData = function(arr, so) {
	var s = this;
	s.serverOptions = so;
	s.openID = so.openID;
	s.searchString = so.srch;
	s.adminMode = !!so.adminMode;
	s.inlineModeration = (s.adminMode && !s.config.moderate);
	if(this.config.nolc) so.avatardim = '48x48';
	s.splitAvatarDim(so, so.avatardim);

	so.smiley = so.smiley || s.config.smiles == "yes";
	s.config.uploadImages = so.uploadImages;
	s.config.skin = s.hasOwnProperty("dtComment") ? s.config.skin : (s.config.skin || so.skin);

	JSKitLib.addClass(s.target, "js-CommentsSkin-" + (s.getSkin() || "wireframe"));
	if(s.config.skin === "smoothgray") {
		s.navSym = JSKitLib.isIE() ? { "prev": '&larr;', "next": '&rarr;'} : { "prev": '&#x25c0;', "next": '&#x25b6;' };
		if(!s.hasOwnProperty("dtComment")) s.dtComment = JSCC.prototype.dtComment2;
		s.dtCreate = JSCC.prototype.dtCreate2;
		s.dtEditComment = JSCC.prototype.dtEditComment2;
	}
	else if (s.config.skin === "haloscan") {
		s.dtComment = JSCC.prototype.dtComment3;
		s.dtCreate = JSCC.prototype.dtCreate3;
		s.dtEditComment = JSCC.prototype.dtEditComment;
		if (window.JK$HS$haloscan_style)
			JSKitLib.addCss(window.JK$HS$haloscan_style, "comments-skin-haloscan-custom");
	}

	if(!s.eventsCtx) {
		var processServerRequestEvent = function() {
			s.processServerRequestEvent.apply(s, arguments);
		}
		s.eventsCtx = JSKW$Events.registerEventCallback(s.eventsCtx, processServerRequestEvent, "comments_serverRequest_deleting");
		s.eventsCtx = JSKW$Events.registerEventCallback(s.eventsCtx, processServerRequestEvent, "comments_serverRequest_deleted");
	}

	if (so.smiley) {
		s.smiles = {
			"O:-)"  : {file: 'innocent.gif', title: 'Innocent'},
			"&gt;:o": {file: 'yell.gif', title: 'Yell'},
			":)"    : {file: 'smile.gif', title: 'Smile'},
			":-)"   : {file: 'smile.gif', title: 'Smile'},
			";)"    : {file: 'wink.gif', title: 'Wink'},
			";-)"   : {file: 'wink.gif', title: 'Wink'},
			":'("   : {file: 'cry.gif', title: 'Cry'},
			"8-)"   : {file: 'cool.gif', title: 'Cool'},
			":("    : {file: 'frown.gif', title: 'Frown'},
			":-("   : {file: 'frown.gif', title: 'Frown'},
			":*"    : {file: 'kiss.gif', title: 'Kiss'},
			":-*"   : {file: 'kiss.gif', title: 'Kiss'},
			":-D"   : {file: 'laughing.gif', title: 'Laughing'},
			"=-O"   : {file: 'surprised.gif', title: 'Surprised'},
			"=-X"   : {file: 'sealed.gif', title: 'Sealed'},
			":-["   : {file: 'embarassed.gif', title: 'Embarassed'},
			":-$"   : {file: 'money-mouth.gif', title: 'Money mouth'},
			":-P"   : {file: 'tongue-out.gif', title: 'Tongue out'},
			":-E"   : {file: 'foot-in-mouth.gif', title: 'Foot in mouth'},
			"*DONT_KNOW*"   : {file: 'undecided.gif', title: 'Undecided'}
		};
		var f = function(v) { return v.replace(/([\W])/g,"\\$1"); };
		JSKitLib.fmap(s.smiles, function(el, i) {
			/* fix for case ">)" */
			s.smiles[i].regexpText = new RegExp('(&gt|&lt)?' + f(i), 'g');
			s.smiles[i].regexpTag = new RegExp(' ?' + f(s.smileTag(el)) + ' ?', 'g');
		});
	}
	var cb = function(name, obj, jcaIndex) {
		switch(name) {
			case "smileys-onchangeCommentText":
				if(so.smiley && obj && obj.Text) obj.Text = s.textSmiles2Graphical(obj.Text.replace(/&amp;/g, "&")); 
			break;
			case "smileys-beforePostNewComment":
				if(so.smiley && obj && obj.value) obj.value = s.textSmiles2Graphical(obj.value, 1);
			break;
			case "smileys-loadCommentsWidget": 
				if (s.jcaIndex != jcaIndex) return;
			/* no break needed !!! */
			case "smileys-newCommentInDiv":
				var needAutolink = (so.htmlMode || s.config.nolc);
				if ((so.smiley || needAutolink) && obj && obj.Text) {
					obj.Text = obj.Text.split('<wbr></wbr>').join('');
					if (needAutolink) {
						var tags;
						var tags2meta = function(t){tags = []; t = t.replace(/<a href="[^"]+">.*?<\/a>|<.*?>/ig, function(m){tags.push(m); return ' %#HTML_TAG#% ';}); return t;};
						var meta2tags = function(t){JSKitLib.map(function(v){t = t.replace(' %#HTML_TAG#% ', v);}, tags); return t;};
						obj.Text = tags2meta(obj.Text);
						obj.Text = obj.Text.replace(/((?:http|ftp|https):\/\/(?:[a-z0-9#:\/\;\?\-\.\+,@&=%!\*\'(){}\[\]$_|^~`](?!gt;|lt;))+)/ig, '<a href="$1">$1</a>');
						obj.Text = tags2meta(meta2tags(obj.Text));
					}
					obj.Text = obj.Text.replace(/&amp;/g, '&');
					if (so.smiley) obj.Text = s.textSmiles2Graphical(obj.Text);
					if (needAutolink) {
						obj.Text = meta2tags(obj.Text);
					}
					obj.Text = obj.Text.replace(/(<a\s+href="[^">]*)?([^&<>\s\/\-]{12})([^&<>\s\/\-]{12})/ig, function($0, $1, $2, $3){if($1)return $0; return $2+'<wbr></wbr>'+$3;});
				}
			break;
		}
	}
	var ctx = JSKW$Events.registerEventCallback(undefined, cb, "smileys-newCommentInDiv");
	JSKW$Events.registerEventCallback(ctx, cb, "smileys-loadCommentsWidget");
	JSKW$Events.registerEventCallback(ctx, cb, "smileys-beforePostNewComment");
	JSKW$Events.registerEventCallback(ctx, cb, "smileys-onchangeCommentText");

	if(so.req) {
		s.preq.srt = so.req.srt;
		s.preq.ord = so.req.ord;
		s.preq.thr = ((so.req.prs == 'flat') ? 'no' : 'yes');
	}

	if(so.gravatars) {
		s.config.gravatars = 'yes';
		s.config.gravatar_rating = so.gravatar_rating;
		s.config.gravatar_size = so.gravatar_size;
		s.config.gravatar_default = so.gravatar_default;
	}
	if (!so.avatars)
		s.config.avatars = 'no';

	s.gen++;
	s.loading = false;

	if(s.ctag != so.tag) {
		s.objById = {};
		if(s.jspg) s.jspg.invalidate();
	}

	var flat = (s.searchString) ? true : s.preq.thr != 'yes';

	var ttt = []; // top level thread
	var nc = 0;
	var newChilds = {};
	for(var i = 0; i < arr.length; i++) {
		var obj = arr[i];
		if(!obj.ID || !obj.Text) continue;
		if(this.IM && obj.yours) obj.Name = 'Me';
		if(flat) {
			delete(obj.ParentID);
			delete(obj.depth);
		}
		s.objById[obj.ID] = obj;
		obj.thread = [];
		JSKW$Events.syncBroadcast("smileys-loadCommentsWidget", obj, s.jcaIndex);
		obj.karma = new JSCCKarma(obj, this);
		if(obj.status != 'D') nc++;
		var prn = s.objById[obj.ParentID];
		if(prn) {
			if(!newChilds[obj.ParentID]) {
				ttt.push(obj);
			}
			prn.thread.push(obj);
		} else {
			ttt.push(obj);
		}
		newChilds[obj.ID] = 1;
		obj.imgs = s.parseImgData(arr[i]);
	}
	s.divPages(so, s.htmlPaginate(ttt));

	if(this.IM) this.conversations = so.conversations;

	s.ctag = so.tag;
	s.dataLoader(so, nc);

	s.tmce = { foreign: true, cfg: {
		relative_urls: 0,
		remove_script_host: 0,
		uri_domain: s.uriDomain,
		closePopups: function() {
        			var cns = document.body.childNodes;
        			var i = 0;
        			while(i < cns.length) {
                			if(cns[i].id && cns[i].id.match(/^mce_\d+$/) && cns[i].className.match(/clearlooks2/)) document.body.removeChild(cns[i]);
                			else i++;
        			}
			},
		bookMark: function() { 
			tinyMCE.settings.curBM = tinyMCE.activeEditor.selection.getBookmark(); 
			},
		mode: "none",
		plugins: (so.smiley?"emotions":"") + (so.media?",youtube":""),
		theme: "advanced",
		theme_advanced_buttons1: 
			"bold,italic,underline,|,undo,redo,link,unlink"
			+ (so.media?",youtube":"") + (so.smiley?",emotions":""),
		theme_advanced_buttons2: "",
		theme_advanced_buttons3: "",
		theme_advanced_toolbar_location: "top",
		theme_advanced_toolbar_align: "left",
		extended_valid_elements:
			"a[href],b,i,u,em,strong,sup,sub"
			+ (so.media?",object[classid|codebase|width|height|align],param[name|value],embed[quality|type|pluginspage|width|height|src|align|wmode]":"")
			+ (so.smiley?",img[src|title|border|alt]":""),
		setup: (!so.smiley) ? undefined : function(ed) {
			      var mceEvents = ["onClick","onKeyUp"];
			      JSKitLib.map(function(ev) {
				ed[ev].add(function(ed, e){ tinyMCE.settings.bookMark();});
			      }, mceEvents);
			      ed.onKeyUp.add(function(ed, e) {
			      	var content = {Text: ed.getContent({format: 'raw'})};
			      	JSKW$Events.syncBroadcast("smileys-onchangeCommentText", content);
					if(tinyMCE.settings.smiley) { 
						if(JSKitLib.isIE()) {
							ed.setContent(content.Text, {format: 'raw'});
							tinyMCE.execInstanceCommand(ed.id, "selectall");
							ed.selection.collapse(0);
						} else {  
							ed.setContent('', {format: 'raw'});
							ed.execCommand('mceInsertContent', false, content.Text, {format: 'raw'});
						}
					}
			      });
		       }
	}};

	var showCD = function() {
		if(so.ShowSavedCommentDialog)
			so.ShowSavedCommentDialog(s);
	}

	if(so.wysiwyg && !window.tinyMCE) {
		var inittmce = function() {
			s.tmce.foreign = false;
			s.tmce.cfg.plugins = "inlinepopups"+(so.smiley?",emotions":"")+(so.media?",youtube":""); // !inl-pop
			s.tmce.cfg.strict_loading_mode = true;
			tinyMCE.init(s.tmce.cfg);
			showCD();
		}
		var oldcb = window.jsk$tmcecb;
		if(oldcb) {
			jsk$tmcecb = function() { if(oldcb) oldcb(); showCD(); };
		} else {
			jsk$tmcecb = inittmce;
			s.runscr(s.uriDomain + '/extra/tiny_mce/tmce.js');
		}
	} else {
		showCD();
	}

	var f = s.onDataLoad;
	if(f) { s.onDataLoad = null; setTimeout(f, 0); }
	JSKitAPI.publish.call(this, "comment-widget-loaded", this.jcaIndex);
}


