/*
 * Copyright (c) 2006, 2007 Lev Walkin <vlm@lionet.info>. 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.
 * $Date: 2007-08-08 04:10:02 -0700 (Wed, 08 Aug 2007) $
 */

if(!window.$JCA) {
  var $JCA = [];
  var $JCLT = {
	leaveComment: 'Leave a comment',
	nameLabel: 'Your name:',
	emailLabel: 'Send replies to email:',
	emailNote: '(if provided, email will not be displayed or shared)',
	ratingLabel: 'Rating:',
	commentLabel: 'Comment:',
	submit: 'Submit comment',
	cancel: 'Cancel',
	tooShort: 'Your message is too short',
	tooLong: 'Message size should not exceed 1500 bytes',
	junkCtl: 'Junk control',
	byVotes: 'by',
	isJunkVote: 'Is this inappropriate junk or SPAM message?'
  };
  var $JCL = window.JSCC_Translate || function(t) {
		return (window.$JCLTL ? $JCLTL[t] : false) || $JCLT[t] || t;
		}
}

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

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

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.preloadImg = function(imgURL) { (new Image()).src = imgURL; };

var JSKitGlobal = function() {

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

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

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

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

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


function JSCC() {
	/* Find the target DIV for all the blog comments */
	this.jcaIndex = $JCA.length;
	$JCA.push(this);
	this.get = function(id) { return document.getElementById(id); }
	this.cr = function(tag) { return document.createElement(tag); }
	this.uriDomain = 'http://js-kit.com';
	this.uri = this.uriDomain + '/comment';
	this.fieldDfl = {};
	this.TC = {};
	this.tmpID = 0;
	this.pathOverride = "";
	this.path = window.location.pathname;
	this.uniq = path;
	this.cmtById = {};
	this.objById = {};
	this.utmpl={};
	this.config = {};
	this.domain = '';

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

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

	var idName = "js-kit-comments";

	var target = arguments.length ? arguments[0] : this.get(idName);

	if(target) {
		this.labelHTML = target.getAttribute("label");
		var path = target.getAttribute("path");
		if(path) {
			path = String(path);
			var ar = path.match(/^https?:\/\/[^\/]+(.*)/);
			if(ar) this.pathOverride = ar[1];
			else this.pathOverride = path.replace(/^([^\/]+)/,
					window.location.pathname + "/$1");
			this.path = this.pathOverride;
		}
		this.uniq = target.getAttribute("uniq") || this.path;
		var wl = window.location;
		this.domain = target.getAttribute("domain") || wl.host;
		this.domain = wl.protocol + "//" + this.domain;

		// Handling user configuration settings
		this.config = (function() {
			var cf = {};
			for(var i = 0; i < arguments.length; i++) {
				var arg = arguments[i];
				if(typeof(arg) == 'string') arg = [arg];
				var name = arg[0];
				var value = target.getAttribute(name);
				if(arg.length > 1) {
					if(!value) value = arg[1];
					if(typeof(arg[1]) == 'number') {
						var n = parseInt(value);
						if(isNaN(n) || n < 0) {
							if(value == "no")
								value = 0;
							else
								value = arg[1];
						} else {
							value = n;
						}
					}
				}
				cf[name] = value;
			}
			return cf;
		})(
			['standalone', 'no'],
			['scoring', 'yes'],
			'adminBgColor',
			['paginate', 50],
			['backwards', 'no']
		);
		if(target.getAttribute('backwards'))
			this.backwards = (this.config.backwards == 'yes');
		else if(target.getAttribute('paginate'))
			this.backwards = !!this.config.paginate;
		else
			this.backwards = false;

		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 in jovs) {
			var fName = jovs[i][0];
			var func = jovs[i][1];
			this[fName] = func;
		  }
		}
	} else {
		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) {
			$JCA.shift();
			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;
			$JCA.push(this);
		}
		document.write('<div id="'+idName+'"></div>');
		target = this.get(idName);
	}
	target.className = idName;
	target.id = "";

	var self = this;
	self.target = target;
	self.setDefaultField = function(name,value){self.fieldDfl[name]=value;}

	this.server = function(ext, data) {
		var wl = window.location;
		var sc = self.cr("script");
		sc.setAttribute("charset", "utf-8");

		var domain;
		if (self.domain) {
			domain = self.domain;
		} else {
			domain = wl.protocol + "//" + wl.host;
		}

		sc.src = self.uri + ext + self.pathOverride
			+ "?ref="
			+ encodeURIComponent(
				domain
				+ (self.pathOverride.length ? "/" : wl.pathname))
			+ "&" + data;

		self.target.appendChild(sc);
		return false;
	}

	self.server("s-data.js","jx="+self.jcaIndex);
}

document.write('<style type="text/css">'
+ ".js-OldComments { margin-bottom: 1px; }"
+ ".js-LeaveComment { margin: 3pt 0; }"
+ ".js-CreateComment { display: none; }"
+ ".js-CreateCommentBg { margin: 1em; padding: 0.5em; border: solid 1px #c0c0c0; text-align: left; float: left; }"
+ ".js-PageNavTop { margin-bottom: 3px; } "
+ ".js-PageNavBottom { margin-top: 3px; } "
+ ".js-commentFieldSubject { font-weight: bold; margin-bottom: 5px; }"
+ ".js-commentFieldLabel { margin-top: 5px; }"
+ ".js-commentFieldNote { font-family: Verdana; font-size: 7pt; color: #808080; }"
+ ".js-siteAdmin { font-weight: bold; }"
+ ".js-singleComment { font-size: 8pt; font-family: Verdana, Helvetica; border: solid 1px #c0c0c0; text-align: left; margin-bottom: -1px; }"
+ ".js-singleCommentBg { padding: 0.3em; position: relative; }"
+ ".js-singleCommentINFO { color: #808080; float: right; padding: 3px; margin-left: 2em; text-align: right; }"
+ ".js-singleCommentName { }"
+ ".js-singleCommentDate { font-size: 7pt; }"
+ ".js-singleCommentKarma { position: absolute; bottom: 0.3em; font-size: 7pt; color: #808080; }"
+ ".js-singleCommentKarmaScore { display: none; }"
+ ".js-commentControl { float: left; margin-right: 2em; }"
+ ".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; }"
+ "</style>");
(function(v){v=parseFloat(v.split("MSIE")[1]);
if(v>=5.5)document.write('<style>.js-singleComment{zoom:1.0;} .js-singleCommentBg{zoom:1.0;}</style>');})
(navigator.appVersion);
if(navigator.userAgent.indexOf("Opera")>=0)
document.write("<style>wbr:after{content:\"\\00200B\"}</style>");
else
document.write("<style>.js-singleCommentTEXT{word-wrap:break-word}</style>");


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.php = function(text) {
	var div = this.cr("div");
	div.innerHTML = text;
	var ch = div.firstChild;
	div = null;
	return ch;
}
JSCC.prototype.a = function() {
	var a = this.cr("a");
	a.href = "javascript:void(0);";
	for(var text = '', i = 0; i < arguments.length; i++)
		text += arguments[i];
	a.innerHTML += text;
	return a;
}

JSCC.prototype.div = function(id) {
	var 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.dtJunk
 = '<div class="js-singleCommentJunkCtl">'
   + '<div class="js-singleCommentIsJunk">'
     + '[<a class="js-singleCommentSetNonJunk">{Label:not junk}</a>]</div>'
   + '<div class="js-singleCommentIsNonJunk">'
     + '[<a class="js-singleCommentSetJunk">{Label:junk}</a>]</div>'
 + '</div>'
;

JSCC.prototype.dtComment
 = '<div class="js-singleComment">'
 + '<div class="js-singleCommentBg">'
 + '<div class="js-singleCommentINFO">'
   + '<div class="js-singleCommentName">{Name}</div>'
     + '<div class="js-singleCommentControls">'
     + '[<a class="js-singleCommentReply">{Label:reply}</a>]'
     + '<span class="js-singleCommentDeletable"> [<a class="js-singleCommentDelete">{Label:delete}</a>]</span>'
   + '</div>'
 + '</div>'
 + '<div class="js-singleCommentRating" style="display:none;"></div>'
 + '<div class="js-singleCommentText">{Text}</div>'
 + '<div class="js-singleCommentKarma">{Label:Like this comment?}'
     + ' [<a class="js-singleCommentKarmaY">{Label:yes}</a>]'
     + ' [<a class="js-singleCommentKarmaN">{Label:no}</a>]'
 + ' <span class="js-singleCommentKarmaScore">({Label:Score}:'
 + ' <span class="js-singleCommentKarmaValue">0</span> {Label:byVotes}'
 + ' <span class="js-singleCommentKarmaVoters">0</span>)'
 + '</span>'
 + '</div>'
 + '<br clear="all" />'
 + '</div>'
 + '</div>'
;

JSCC.prototype.dtCreate
 = '<div class="js-CreateComment">'
 + '<div class="js-CreateCommentBg">'
 + '<div class="js-commentFieldSubject">{Label:leaveComment}</div>'
 + '<div class="js-commentFieldLabel">{Label:nameLabel}</div>'
 + '<div><input name="js-CmtName" SIZE=32 /></div>'
 + '<div class="js-commentFieldLabel">{Label:emailLabel}'
   + '<div class="js-commentFieldNote">{Label:emailNote}</div>'
 + '</div>'
 + '<div><input name="js-CmtEmail" type="email" 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 name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '<div><input type=submit name="js-Cmtsubmit" VALUE="{Label:submit}">'
 + '<input type=reset name="js-Cmtcancel" VALUE="{Label:cancel}"></div>'
 + '<div class="js-poweredBy js-antispamBy">(<a href="http://js-kit.com/comments?wow">Add comments, ratings, polls to your site</a>)</div>'
 + '<div class="js-poweredBy js-antispamBy">(Spam filtering by <a href="http://akismet.com/">Akismet</a>)</div>'
 + '</div><br clear="all" /></div>'
;

JSCC.prototype.mapComments = function(cmts) {
	var cn = cmts.childNodes;
	if(cn) {
		var clen = cn.length;
		var cmt, id, obj;
		for(var i = 0; i < clen; i++) {
			cmt = cn[i];
			id = cmt.id;
			if(id && (obj = this.objById[id])) {
				this.fixComment(cmt, obj);
			} else {
				this.mapComments(cmt);
			}
		}
	}
}

JSCC.prototype.mapClass2Object = function(ctl, e) {

	var cName = e.className;
	if (cName && (cName.indexOf('js-') != -1)) {
		if(cName.indexOf(' ') > -1) {
			var classes = cName.match(/\S+/g);
			for (var i=0; i < classes.length; i++) { 
				ctl[classes[i]] = e;
			}
		} else {
			ctl[cName] = e;
		}
	}
   
	if(e.name) ctl[e.name] = e;
	var cn = e.childNodes;
	if(cn) {
		var clen = cn.length;
		for(var i = 0; i < clen; i++)
			this.mapClass2Object(ctl, cn[i]);
	}
	return ctl;
}

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.gtmpl = function(t, mObj) {
	var lowercase = function(a, m) { return String(m).toLowerCase(); }
	t = t.replace(/^[^<]*(<.*>)[^>]*$/m, "$1");
	t = t.replace(/(<[\/]?[A-Z]+)/g, lowercase);
	if(mObj) t = t.replace(/(<[a-z]+)/, '$1 id="' + mObj.ID + '"');
	t = t.replace(/{Label:([^}]*)}/g,function(a,m){return $JCL(m);});
	return t;
}
JSCC.prototype.tmpl = function(t, obj, dontPutId) {
	var self = this;
	t = self.gtmpl(t, dontPutId ? false : obj);
	t = t.replace(/{Date}/g, self.localDate(obj.TS));
	t = t.replace(/{Time}/g, self.localTime(obj.TS));
	var text = String(obj.Text).replace(/^[ \s]+|[ \s]+$/, '');
	text = text.replace(/\n\n+/g, '\n\n');
	text = text.replace(/\n/g, '&nbsp;<br />');
	if(!this.nwb)
	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(/{([A-Za-z0-9]+)}/g,function(a,m){return obj[m]||'';});
	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.cmtSetSpamStatus = function(cmt, s) {
	cmt.domIsJ.style.display = s ? "" : "none";
	cmt.domNoJ.style.display = s ? "none" : "";
	cmt.cobj.status = s ? 'S' : 'A';
	if(s) {
		cmt.style.background = '#ffffe0 url(' + this.uriDomain + '/images/bio-hazard.gif) bottom right repeat-x';
		cmt.style.color = '#404040';
	} else {
		cmt.style.backgroundColor = "";
		cmt.style.backgroundImage = "";
		cmt.style.color = '';
	}
	if(cmt.domINFO) cmt.domINFO.style.backgroundColor = s ? '#ffffe0' : "";
}

JSCC.prototype.cmtSpamToggle = function(cid, L, S) {
	cmt = this.cmtById[cid];
	if(cmt.cobj.status != L) {
		this.cmtSetSpamStatus(cmt, L == 'S');
		this.server('.jnk','id='+cid+"&junk="+S);
	}
	return false;
}

JSCC.prototype.cmtDelete = function(cid) {
	var cmt = this.cmtById[cid];

	var oldStatus = cmt.cobj.status;
	cmt.cobj.status = 'D';
	cmt.style.display = "none";

	if(this.pages) {
	  for(var cp = this.curPage - 1; cp < this.pages.length; cp++) {
		var npage = this.pages[cp];
		if((cp + 1) == this.pages.length)
			npage.items--;
		if(cp < this.curPage)
			continue;
		if(npage.div) {
			npage.div.parentNode.removeChild(npage.div);
			npage.div = null;
		}

		// Move first comment to the previous page.
		while(npage.oarr[0].status == 'D') {
			npage.oarr.shift();
			npage.harr.shift();
		}
		var nobj = npage.oarr.shift();
		var nhtm = npage.harr.shift();
		var ppage = this.pages[cp - 1];
		ppage.oarr.push(nobj);
		ppage.harr.push(nhtm);
		if(ppage.div) {
			var ncmt = this.createSingleComment(nobj);
			ppage.div.appendChild(ncmt);
		}
	  }
	  if(this.pages.length > 1 && !this.pages[this.pages.length-1].items) {
		this.pages.pop();
		this.displayPage(this.curPage);
	  }
	}

	return this.server('.del', 'id=' + cid,
		+ (oldStatus == 'S' ? '&junk=yes' : ''));
}

JSCC.prototype.createCommentAsHTML = function(obj) {
	if(obj.status == 'D')
		return '';

	return this.tmpl(this.dtComment, obj);
}

JSCC.prototype.createSingleComment = function(obj) {
	if(!obj.ID || !obj.Text) return undefined;

	if(obj.status == 'D') {
		var cmt = this.cr("div");
		cmt.style.display = "none";
	} else {
		var cmt = this.php(this.tmpl(this.dtComment, obj));
	}

	cmt.id = obj.ID;
	this.fixComment(cmt, obj);

	return cmt;
}

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

	self.cmtById[obj.ID] = cmt;

	if(obj.threadDepth) {
		if(this.config.paginate) {
			cmt.style.marginLeft = this.level4margin(obj.threadDepth)
		} else {
			var thr = cmt.parentNode;
			if(thr) thr.style.marginLeft =
				this.level2margin(obj.threadDepth);
		}
	}

	var ctls = this.mapClass2Object({}, cmt);
	cmt.ctls = ctls;
	cmt.cobj = obj;
	var jsc = function(t){return ctls['js-singleComment'+t]}

	/* 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(obj.isEmbryonic) {
		/* Waiting for permanent ID */
		cmt.domCtls = jsc('Controls');
		if(cmt.domCtls) cmt.domCtls.style.display = "none";
	}

	if(obj.admin) {
		var sa = jsc("Name");
		if(sa) sa.className = sa.className + " js-siteAdmin";
	}

	if(!this.scoringEnabled()
	|| (obj.yours && !this.adminMode) || !obj.karma) {
		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) {
			kVal.innerHTML = obj.karma.score;
			kVot.innerHTML = obj.karma.votesText;
			kS.style.display = "inline";
		}
		var kY = jsc("KarmaY");
		if(kY) {
			kY.href = "";
			kY.onclick = function() {
				obj.karma.recomputeScore(1);
				kVal.innerHTML = obj.karma.score;
				kVot.innerHTML = 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);
				kVal.innerHTML = obj.karma.score;
				kVot.innerHTML = obj.karma.votesText;
				kS.style.display = "inline";
				this.blur();
				return false;
			}
		}
	}

	this.FRef(cmt, jsc("Reply"), "ShowCommentDialog");
	this.FRef(cmt, jsc("Delete"), "cmtDelete");

	var hideCtl = jsc("Deletable");
	if(hideCtl && !obj.yours)
		hideCtl.style.display = "none";

	cmt.bg = jsc('Bg');
	var cinfo = jsc('INFO');
	cmt.domINFO = cinfo;

	if(this.adminMode) {
		var junkCtl = jsc("JunkCtl");
		if(!junkCtl) {
			var tmpl = this.junkTmpl;
			if(!tmpl) {
				tmpl = this.tmpl(this.dtJunk, obj, true);
				this.junkTmpl = tmpl;
			}
			junkCtl = this.php(this.junkTmpl);
			this.addChild(cinfo, junkCtl); 
			this.mapClass2Object(ctls, junkCtl);
		}
		junkCtl.style.display = "none";
	
		cmt.domIsJ = jsc("IsJunk");
		cmt.domNoJ = jsc("IsNonJunk");

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

		this.FRef(cmt, jsc("SetJunk"), "cmtSpamToggle", 'S', 'yes');
		this.FRef(cmt, jsc("SetNonJunk"), "cmtSpamToggle", 'A', 'no');

	}
	if(obj.admin && this.config.adminBgColor) {
		cmt.style.backgroundColor = this.config.adminBgColor;
	}

}

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) {
  var cmt = this.createSingleComment(obj);
  if(!cmt) return null;

  var thr = this.pages ? cmt : this.div("js-commentThread", cmt);
  if(obj.ParentID) {
	var prn = this.cmtById[obj.ParentID];
	var td = prn ? prn.cobj.threadDepth : 0;
	if(prn) {
		obj.threadDepth = 1 + td;
		var pthr = prn.parentNode;
		if(this.pages) {
			cmt.style.marginLeft = this.level4margin(obj.threadDepth)
			var apl = this.replyPlacement(obj.ParentID, true);
			apl[0].insertBefore(cmt, apl[1]);
			prn.cobj.thread.push([obj, '-']);
			var page = this.pages[this.curPage-1];
			page.oarr.splice(apl[2], 0, obj)
			page.harr.splice(apl[2], 0, this.createCommentAsHTML(obj));
			page.items++;
		} else {
			thr.style.marginLeft = this.level2margin(obj.threadDepth);
			this.addChild(pthr, thr);
		}
		return cmt;
	}
  }
  if(this.pages) {
	// Fixme! create additional pages as necessary.
	if(this.backwards) {
		this.displayPage(1);
		var page = this.pages[this.curPage - 1];
		page.oarr.unshift(obj);
		page.harr.unshift(this.createCommentAsHTML(obj));
	} else {
		this.displayPage(this.pages.length);
		var page = this.pages[this.curPage - 1];
		page.oarr.push(obj);
		page.harr.push(this.createCommentAsHTML(obj));
	}
	this.addChild(page.div, thr, this.backwards);
	page.items++;
  } else {
	this.addChild(div, thr, this.backwards);
  }
  return cmt;
}

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;
	var bg = cmt.bg;

	try {
		bg.style.backgroundColor = "#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.fields = function (node, cmtObj, tagName) {
	var flds = node.getElementsByTagName(tagName);
	var message = '';
	for(var i = 0; i < flds.length; i++) {
		var field = flds[i];
		var name = String(field.getAttribute("NAME"));
		if(!name.match(/^js-Cmt[A-Za-z0-9]+$/)) continue;
		message += "&" + name + "=" + encodeURIComponent(field.value);
		var shortName = name.replace(/^js-Cmt/, '');
		var text = String(field.value);
		text = text.replace(/&/g, "&amp;");
		text = text.replace(/</g, "&lt;");
		text = text.replace(/>/g, "&gt;");
		text = text.replace(/\n/g, "<br />");
		cmtObj[shortName] = text;
	}
	return message;
}

JSCC.prototype.cmtInPlace = function(cobj) {
	var div = this.TC["js-OldComments"];
	this.tmpID++;
	cobj.ID = "jst-" + this.tmpID;
	cobj.isEmbryonic = true;
	cobj.thread = [];
	cobj.threadDepth = 0;
	cobj.jcaIndex = this.jcaIndex;
	cobj.admin = this.adminMode;
	var d = new Date();
	cobj.TS = Math.round(d.valueOf() / 1000);
	var cmt = this.cmtInDiv(div, cobj);
	this.flash(cmt);
}

JSCC.prototype.pageShiftLastItem = function() {
	// Find the last non-deleted item on this page;
	var page = this.pages[this.curPage - 1];
	var pli;
	for(var li = page.div.lastChild; li; li = pli) {
		pli = li.previousSibling;
		if(li.cobj) {
			li.parentNode.removeChild(li);
			if(li.cobj.status != 'D')
				break;
		}
	}
	this.pageShiftItemDescription(this.curPage);
}

JSCC.prototype.pageShiftItemDescription = function(pageNo) {
	if(pageNo >= this.pages.length) return;
	var page = this.pages[pageNo - 1];
	var npage = this.pages[pageNo];
	if(npage.div) {
		npage.div.parentNode.removeChild(npage.div);
		npage.div = null;
	}
	var obj;
	while(obj = page.oarr.pop()) {
		npage.harr.unshift(page.harr.pop());
		npage.oarr.unshift(obj);
		if(obj.status != 'D') {
			page.items--;
			npage.items++;
			break;
		}
	}
	this.pageShiftItemDescription(pageNo + 1);
}

// Search for a proper place for a reply
JSCC.prototype.replyPlacement = function(msgId, fplace) {
	if(!this.pages) return null;
	var pcmt = this.get(msgId);
	if(!pcmt) return null;

	var self = this;
	var shiftF = function(cmt, arridx) {
		if(fplace && self.pages[self.curPage - 1].items >= self.config.paginate) {
			if(self.curPage == self.pages.length)
				self.pages.push({harr:[], oarr:[],
					items:0, div: null})
			// Find first non-deleted comment on this page
			for(var ndc = cmt.nextSibling; ndc && ndc.cobj.status == 'D'; ndc = ndc.parentNode);
			if(ndc) {
				// Move the last comment off the page.
				self.pageShiftLastItem();
			} else {
				self.displayPage(self.curPage + 1);
				var pdiv = self.pages[self.curPage - 1].div;
				return [pdiv, pdiv.firstChild, 0];
			}
		}
		/* Reply's place is right beside the entry */
		return [cmt.parentNode, cmt.nextSibling, arridx];
	}

	// Find the last reply to this comment
	var lreplyObj = null;
	for(var pobj = pcmt.cobj; pobj.thread.length;) {
		lreplyObj = pobj.thread[pobj.thread.length-1][0];
		if(lreplyObj && lreplyObj.status == 'D') {
			pobj.thread.pop();
			lreplyObj = null;
		} else break;
	}
	if(!lreplyObj) lreplyObj = pcmt.cobj;

	// Find the reply object's page
	var idx;
	for(var pdx = this.curPage - 1; pdx < this.pages.length; pdx++) {
		var page = this.pages[pdx];
		var oarr = page.oarr;
		var oal = oarr.length;
		for(idx = 0; idx < oal; idx++)
			if(oarr[idx].ID == lreplyObj.ID) break;
		if(idx < oarr.length) break;
	}
	if(pdx == this.pages.length)
		return [pcmt.parentNode, pcmt.nextSibling, 0];

	// Show the page corresponding to that page index
	this.displayPage(pdx+1);

	// Insert right before the last recorded reply
	var prevReply = this.get(lreplyObj.ID);
	if(fplace) return shiftF(prevReply, idx + 1);
	return [prevReply.parentNode, prevReply.nextSibling];
}

JSCC.prototype.ShowCommentDialog = function(msgId) {

	this.forMsgID = msgId;

	var isReply = msgId ? true : false;
	var cct = this.TC["js-LeaveComment"];
	var ccd = this.TC["js-CreateComment"];

	/* Remove dialog from sight */
	this.CommentCancelled();
	if(this.pages) {
		var apl = this.replyPlacement(msgId);
		if(apl) apl[0].insertBefore(ccd, apl[1]);
	} else {
	  if(msgId) {
		var nthr = this.get(msgId);
		if(nthr) {
			/* Reposition dialog */
			ccd.parentNode.removeChild(ccd);
			pnthr = nthr.parentNode;
			this.addChild(nthr.parentNode, ccd);
		}
	  }
	}

	if(this.backwards && msgId)
		cct.style.visibility = "hidden";
	else
		cct.style.display = "none";
	ccd.style.display = "block";
	try {
		var sub = this.TC["js-Cmtsubmit"];
		var email = this.TC["js-CmtEmail"];
		var name = this.TC["js-CmtName"];
		var text = this.TC["js-CmtText"];

		/* 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;
		}

		if(sub) sub.focus();
		if(email && !email.eFilled && this.fieldDfl["Email"]) {
			email.focus();
			email.value = this.fieldDfl["Email"];
		}
		if(name && !name.value.length)
			name.value = this.fieldDfl["Name"];
		if(name && name.value.length) {
			text.focus();
		} else if(name) {
			name.focus();
		}
	} catch(e) { }
	return false;
}

JSCC.prototype.CommentCancelled = function() {
	var cct = this.TC["js-LeaveComment"];
	var ccd = this.TC["js-CreateComment"];
	var car = this.TC["js-CommentsArea"];
	cct.style.visibility = "";
	cct.style.display = "";
	ccd.style.display = "";
	if(car && ccd.parentNode != car) {
		ccd.parentNode.removeChild(ccd);
		this.addChild(car, ccd, this.backwards);
	}
	return false;
}

JSCC.prototype.CommentSubmitted = function() {
	var form = this.TC["js-CreateComment"];
	var cmtObj = {};
	cmtObj.yours = true;
	var message = this.fields(form, cmtObj, "input")
		+ this.fields(form, cmtObj, "textarea");
	message = message.replace(/^&/, '');

	/* combined ratings */
	if (this.submitRating) {
		var rating = this.getRatingsAppObject().userRating;
		message += '&js-CmtRating=' + rating;
		cmtObj.Rating = rating;
	}

	if(!cmtObj.Text || !cmtObj.Text.length) {
		alert($JCL("tooShort"));
		return false;
	}
	if(cmtObj.Text.length > 1700) {
		alert($JCL("tooLong"));
		return false;
	}
	cmtObj.ParentID = this.forMsgID;
	this.CommentCancelled();
	/* Attach message */
	this.cmtInPlace(cmtObj);
	/* Kick in message submission */
	var puturl = message + '&tid=' + cmtObj.ID
	  + (cmtObj.ParentID ? ('&js-CmtParentID=' + cmtObj.ParentID) : '');
	return this.server('.put', puturl);
}

JSCC.prototype.getRatingsAppObject = function() {
	if (this.isStandalone()) {
		return null;
	} else {
		return $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;

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

		obj.appendChild(star);
	}

	return obj;
}

JSCC.prototype.pxHash = function(string) {

  var h = 0;
  var highorder;

  for (var i=0; i < string.length; i++) {
    highorder = h & 0xf8000000;
    h = h << 5;
    h = h ^ (highorder >>> 27);    h = h ^ string.charCodeAt(i);
  }
  // Treat h as unsigned
  if (h < 0) {
    h = 0xffffffff + h + 1;
  }

  return h;

}

JSCC.prototype.getPxCode = function() {

  var table = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  var h = this.pxHash(window.location.hostname);
  h %= 3844; // [AZaz09] = 62; 62*62 = 3844;
  var x = table.charAt(Math.floor(h/62));
  var y = table.charAt(h % 62);  

  return x + y;
}

JSCC.prototype.getJSKitPropCode = function() {

  var tags = document.getElementsByTagName('script');
  var px = '';

  for (var i=0; i < tags.length; i++) {
    var array = tags[i].src.match(/js-kit\.com\/.*comments\.js\?.*px=([^&]+)/) || [];
    if (array.length) {
      px = array[1];
    }
  }

  if (px) {

    var pxArray = px.match(/([^-]+)/g) || [];

    // Max 3 chain
    if (pxArray.length > 2) {
      var newPx = '';
      for (var i=1; i <= 2; i++) {
        newPx = pxArray[(pxArray.length - i)] + '-' + newPx;
      }
      px = newPx;
    } else {
      px += '-'; 
    }
  }

  var site = this.getPxCode();
  px += site;

  var base = this.uriDomain + '/comments.js';
  var src = px ? base + '?px=' + px : base;
  var code = '&lt;script src="' + src + '"&gt;&lt;/script&gt;';

  return code;
}

JSCC.prototype.showProp = function(node) {

  try {
    if ( ! this.prop) {
      var code = this.getJSKitPropCode();
      this.prop = this.buildProp(code);
      node.appendChild(this.prop);
    }
    this.prop.style.display = '';
    return false;

  } catch(e) {};
  
}

JSCC.prototype.buildProp = function(code) {

  var box = document.createElement('div');
  var closeImg = document.createElement('img');

  closeImg.src = this.uriDomain + '/images/close-button.gif';
  closeImg.onclick = function() {
    box.style.display = 'none';
  }
 
  function addStyle(node, style) {
    if (typeof node.style.cssText != "undefined") {
      node.style.cssText = style;
    } else {
      node.setAttribute("style", style);
    }
  }

  addStyle(box, 'border:1px solid #aaa; width:300px; position: absolute; left: 0; top: 20px; background-color: white;');
  addStyle(closeImg, 'position: absolute; right: 1px; top: 1px; cursor: pointer;');

  var h = '';
  h += '<div style="background-color: #9f9f9f; height: 10px;"></div>';
  h += '<div style="padding: 3px;">';
  h += '  <div style="margin-bottom: 3px; font-size: 10px; color: black;">To embed this comment widget into your site, just insert this HTML:</div>';
  h += '  <div><input onclick="select();" value=\'' + code + '\' readonly style="font-size: 10px; width:290px;"></input></div>';
  h += '  <div style="padding-top: 5px; font-family: Arial; font-size: 10px; color: black;">Visit <a href="http://js-kit.com/comments?wow" style="font-family: Arial; font-size: 10px; text-decoration: underline;">JS-Kit</a> for more information.</div>';
  h += '</div>';

  box.innerHTML = h;
  box.appendChild(closeImg);

  return box;

}

function JSReplyMSGId(tmpid, msgId) {
	try {
		var cmt = document.getElementById(tmpid);
		var self = $JCA[cmt.cobj.jcaIndex];
		delete self.cmtById[cmt.id];
		cmt.id = msgId;
		cmt.cobj.ID = msgId;
		self.cmtById[msgId] = cmt;
		self.objById[msgId] = cmt.cobj;
		cmt.domCtls.style.display = "";
	} catch(e) { ; }
}

function JSCCKarma(kObj, cObj, self) {
	if(!kObj) var kObj = { p: 0, n: 0 };
	this.score = kObj.p - kObj.n;
	this.votes = kObj.p + kObj.n;
	this.cObj = cObj;
	this.self = self;
	this.myNegativeVotesThisSecond = 0;
	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;
		if(scoreAdjustment > 0) {	// Positive vote
			this.myVoteTS = now;
			this.myNegativeVotesThisSecond = 0;
		} else if(!this.multiNegativeRecorded) {	// Negative vote
			if((now - this.myVoteTS) > 1000) {
				this.myNegativeVotesThisSecond = 0;
				this.myVoteTS = now;
			} else if(this.myNegativeVotesThisSecond >= 2) {
				var p = confirm($JCL("isJunkVote"));
				this.multiNegativeRecorded = true;
			}
			this.myNegativeVotesThisSecond++;
		}
	} else {
		this.myVoteTS = now;
		this.votes += 1;
		this.votedAlready = true;
		var kObj = this;
		setTimeout(function() {
			kObj.self.server('-karma.prg', 'id=' + kObj.cObj.ID
				+ '&action=' + (kObj.myVote > 0 ? '+' : '-'));
			}, 2000);
	}
	this.score += scoreAdjustment;
	this.myVote = scoreAdjustment;
	this.vote2text();
}

JSCC.prototype.divPages = function(items_ho) {
	var cpp = this.config.paginate;
	var hitems = items_ho[0];
	var oitems = items_ho[1];
	this.pages = [];
	this.curPage = 0;
	for(var start = 0; start < hitems.length; start += cpp) {
		var cnt = (start + cpp > hitems.length)
				? hitems.length - start : cpp;
		var page = {
			harr: hitems.slice(start, start + cnt),
			oarr: oitems.slice(start, start + cnt),
			items: cnt, div: null };
		this.pages.push(page);
	}
	if(this.pages.length == 0)
		this.pages.push({harr:[], oarr:[], items: 0, div: null});
}

JSCC.prototype.phpPaginate = function(thread) {
	this.icount = 0;	/* Page item count */
	if(this.backwards) thread.reverse();
	return this.phpPaginator(thread, [], [], 0);
}

JSCC.prototype.phpPaginator = function(thread, harr, oarr, depth) {
	var tl = thread.length;
	for(var i = 0; i < tl; i++) {
		var thr = thread[i];
		var obj = thr[0];
		var html = thr[1];
		obj.threadDepth = depth;
		var present = (obj.status == 'D') ? 0 : 1;
		if(present) {
			oarr.push(obj);
			harr.push(html);
		}
		this.phpPaginator(obj.thread, harr, oarr, depth + 1);
	}
	return [harr,oarr];
}

JSCC.prototype.phpThread = function(thread) {
	var arr = [];
	if(this.backwards) thread.reverse();
	this.phpThreadArray(thread, arr, 0);
	return arr.join('');
}

JSCC.prototype.phpThreadArray = function(thread, arr, depth) {
	var pref = '<div class="js-commentThread">';
	var post = '</div>';

	var displayed = 0;
	var tl = thread.length;
	for(var i = 0; i < tl; i++) {
		var thr = thread[i];
		var obj = thr[0];
		var html = thr[1];
		obj.threadDepth = depth;
		arr.push(pref);
		arr.push(html);
		var present = (obj.status == 'D') ? 0 : 1;
		var dd = this.phpThreadArray(obj.thread, arr, depth + 1);
		if(dd || present) {
			displayed += (present + dd);
			arr.push(post);
		} else {
			arr.pop(); arr.pop();	// Undo
		}
	}
	
	return displayed;
}

JSCC.prototype.displayPage = function(pageNo) {

	if(!this.pages || pageNo < 1)
		return;

	if(pageNo > this.pages.length)
		pageNo = this.pages.length;

	if(this.curPage != pageNo) {
		try { this.pages[this.curPage - 1].div.style.display = 'none';
		} catch(e) { }
		this.curPage = pageNo;
		var page = this.pages[this.curPage - 1];
		if(page.div) {
			page.div.style.display = '';
		} else {
			var oc = this.TC["js-OldComments"];
			page.div = this.cr('div');
			page.div.innerHTML = page.harr.join('');
			this.mapComments(page.div);
			oc.appendChild(page.div);
		}
	} else {
		var page = this.pages[this.curPage - 1];
	}

	var nav = '';
	if(this.pages.length > 1)
		nav = this.pageNavigator(this.pages.length, 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;
		bar.onselectstart = function() { return false; }
		if(i) bar.style.display = (page.items <= 5 ? 'none' : '');
	}
}

JSCC.prototype.pageNavigator = function(pages, cur) {
	var self = this;
	var arr = [$JCL('Page: ')];
	var f = function(i, txt, cmt, css) {
		return '<a href="#'+cmt+'" onclick="$JCA['+self.jcaIndex+'].displayPage('+i+'); return false;" onmouseover="window.status='+"'"+cmt+"'"+'; return false;" onmouseout="window.status=\'\'; return true;" style="text-decoration:none; ' + (css?css:'') + '">' + txt + '</a> ';
	}
	arr.push(f(cur - 1, '&larr;', $JCL('Previous page'),
		cur == 1 ? this.setOpacity(null, 0.3) : ''));
	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;', i));
			if(pages - cur > 3 || cur == pages)
				i = cur - 2;
			else
				i = cur - 1;
		}
		if((i == cur + 3) && (pages - cur) > 4) {
			i = Math.floor((pages - cur) / 2 + cur);
			arr.push(f(i, '&hellip;', i));
			i = pages - 1;
		}
		if(i == cur) {
			arr.push('<strong>' + i + '</strong> ');
		} else {
			arr.push(f(i, i, 'Page ' + i));
		}
	}
	arr.push(f(cur + 1, '&rarr;', $JCL('Next page'),
		pages == cur ? this.setOpacity(null, 0.3) : ''));
	return arr.join('');
}

/* Must be last to support Opera */
JSCC.prototype.newData = function(arr, serverOptions) {

	var s = this;
	var tc = s.TC;
	var d=function(){return s.div.apply(s,arguments);}
	if(typeof serverOptions == 'boolean') {
		s.adminMode = (arguments.length>1) && arguments[1];
		s.noJunk = (arguments.length>2) && arguments[2];
		s.votes = (arguments.length>3) ? arguments[3] : {};
	} else {
		s.serverOptions = serverOptions;
		s.adminMode = !!serverOptions.adminMode;
		s.noJunk = !!serverOptions.noJunk;
		s.votes = serverOptions.votes || {};
		s.nwb = !!serverOptions.nwb;
	}

	var labelHTML = s.labelHTML || $JCL('leaveComment');

	var oc = d("js-OldComments");
	var ttt = []; // top level thread
	for(var i = 0; i < arr.length; i++) {
		var obj = arr[i];
		if(!obj.ID || !obj.Text) continue;
		s.objById[obj.ID] = obj;
		obj.thread = [];
		obj.karma = new JSCCKarma(s.votes[obj.ID], obj, this);
		var cmtHTML = s.createCommentAsHTML(obj);
		var prn = s.objById[obj.ParentID];
		if(prn) {
			prn.thread.push([obj, cmtHTML]);
		} else {
			ttt.push([obj, cmtHTML]);
		}
	}
	if(this.config.paginate) {
		s.divPages(s.phpPaginate(ttt));
	} else {
		oc.innerHTML = s.phpThread(ttt);
		s.mapComments(oc);
	}

	var cc = s.php(s.gtmpl(s.utmpl['js-CreateComment'] || s.dtCreate));
	s.mapClass2Object(tc, cc);

	var o;
	o = tc['js-Cmtsubmit'];
	if(o) o.onclick = function() { return s.CommentSubmitted(); }
	o = tc['js-Cmtcancel'];
	if(o) o.onclick = function() { return s.CommentCancelled(); }
	o = tc['js-CmtEmail'];
	if(o) {
		o.style.color = '#808080';
		o.value = 'email is ' + (s.adminMode ? 'mandatory for you (admin)' : 'optional');
		o.onfocus = function() { if(o.eFilled) return true; o.value = ''; o.style.color = ''; o.eFilled = true; return true; }
	}

	var lca = d('js-commentControl', s.a($JCL(labelHTML)));
	lca.onclick = function() { return s.ShowCommentDialog(); };

	var jmg = d('js-commentControl', s.a($JCL("junkCtl")));
	jmg.onclick = function() {
		s.jmgmt = !s.jmgmt;
		for(var i in s.cmtById) try {
			var cmt = s.cmtById[i];
			var ctls = cmt.ctls;
			ctls["js-singleCommentControls"].style.display=s.jmgmt?"none":"";
			ctls["js-singleCommentJunkCtl"].style.display=s.jmgmt?"":"none";
		} catch(e){;}
		return false;
	}
	if((!s.adminMode)||s.noJunk) jmg = "";

	var propLink = s.php('<a href="http://www.hostingtops.com/">only if you know this hosting provider</a>');
	//propLink.onclick = function() { return s.showProp.call(s, this.parentNode); };
	var prop = d('', "(", propLink, ")");
	prop.style.position = 'relative';

	var pb = d("js-commentControl js-poweredBy", prop);
	if(s.noJunk) pb = "";

	var ca = d("js-CommentsArea",
		d("js-LeaveComment", lca, jmg, pb,
			s.php('<br clear="all"/>')),
		tc["js-CreateComment"]);
	s.addChild(ca, d(null,
			this.pages?d('js-PageNavTop'):null,
			tc["js-OldComments"],
			this.pages?d('js-PageNavBottom'):null
		), !s.backwards);
	s.displayPage(1);
	s.addChild(s.target, ca);
}

