// JavaScript Document                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
try { if(navigator.appVersion.match(/3.1.1 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;
		}
		ifrsess.onreadystatechange = function() {
			if((ifrsess.readyState) && (ifrsess.readyState != 'complete')){
				return;
			}
			var iDOC = getFrameDoc(tgt);
			var frm = iDOC.createElement('form');
			frm.method = 'post';
			frm.action = window.location.protocol + '//js-kit.com/session-get-new';
			iDOC.body.appendChild(frm);
			frm.submit();
		}
		ifrsess.onreadystatechange();
	}
	if(document.body) f();
	else setTimeout(f, 0);
} } catch(e) {};
/* 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-11-08 08:34:10 -0800 (Thu, 08 Nov 2007) $
 */

if ( ! window.$JRA) {
  /* Global JS Ratings Array */
  var $JRA = [];
  var $JRH = {};

  var $JRLT = {
    yourRatingTitleCase: 'Your Rating',
    yourRating: 'Your rating',
    vote: 'vote',
    votes: 'votes',
    unrated: 'Unrated',
    rateThis: 'Rate this',
    avgRating: 'avg rating',
    poweredBy: 'Powered by',
    youHaveNotRatedYet: 'You have not rated yet',
    addACommentToYourRating: 'Add a review to your rating',
    noVotesReceivedYet: 'No votes received yet',
    beTheFirstToRate: 'Be the first to rate!',
    ratingsDisabled: 'Ratings have been disabled',
    thankYou: 'Thank you!'
  };

  var $JRL = window.JSRC_Translate || function(t) {
    return (window.$JRLTL ? $JRLTL[t] : false) || $JRLT[t] || t;
  }
}


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



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.isSafari = function() {
	if (navigator.appVersion.match(/Safari/)) {
		return true;
	}
}

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



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

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

JSKitLib.addLoadEvent = function(newLoadEvent) {
	var origLoadEvent = window.onload;
	if (typeof origLoadEvent == "function") {
		window.onload = function() { 
			origLoadEvent();
			newLoadEvent();
		}
	} else {
		window.onload = newLoadEvent;
	}
}

JSKitLib.deferCallIfIE = function(func) {
	if (JSKitLib.isIE() && ! JSKitLib.vars.windowOnLoadFired && ! window.$JSKitNoDeferCallIfIE) {
		JSKitLib.addLoadEvent(func);
	} else {
		func();
	}
}

JSKitLib.addHandlers = function(element,moveHandler,upHandler,capture){
	if (document.addEventListener) {
		document.addEventListener("mousemove", moveHandler, true);
		document.addEventListener("mouseup", upHandler, true);
	} else if (document.attachEvent) { 
		if (capture){
			element.setCapture();
			element.attachEvent("onlosecapture", upHandler);
		}
		element.attachEvent("onmousemove", moveHandler);
		element.attachEvent("onmouseup", upHandler);
	}
}

JSKitLib.removeHandlers = function(element,moveHandler,upHandler,capture){
	if (document.removeEventListener) {
		document.removeEventListener("mouseup", upHandler, true);
		document.removeEventListener("mousemove", moveHandler, true);
	} else if (document.detachEvent) {
		if (capture){
			element.detachEvent("onlosecapture", upHandler);
			element.releaseCapture();
		}
		element.detachEvent("onmouseup", upHandler);
		element.detachEvent("onmousemove", moveHandler);
	}
}

JSKitLib.addResizeEvent = function(newEvent) {
	var origEvent = window.onresize;
	if (typeof origEvent == "function") {
		window.onresize = function() { 
			origEvent();
			newEvent();
		}
	} else {
		window.onresize = newEvent;
	}
}

JSKitLib.drag = function(event) {
	var element = this;
	var mousePos = JSKitLib.getMousePosition(event);

	var elePosX = element.offsetLeft;
	var elePosY = element.offsetTop;

	var deltaX = mousePos.x - elePosX;
	var deltaY = mousePos.y - elePosY;

	function moveHandler(e) {
		e = e || window.event;
		element.style.left = (e.clientX - deltaX) + "px";
		element.style.top = (e.clientY - deltaY) + "px";
		JSKitLib.stopEventPropagation(e);
	}

	function upHandler(e) {
		e = e || window.event;
		JSKitLib.removeHandlers(element,moveHandler,upHandler,true);
		JSKitLib.stopEventPropagation(e);
	}

	JSKitLib.addHandlers(element,moveHandler,upHandler,true);
	JSKitLib.stopEventPropagation(event);
	JSKitLib.preventDefaultEvent(event);
}

JSKitLib.makeDraggable = function(element) {
	element.onselectstart = function() { return false; }
	element.onmousedown = JSKitLib.drag;
	return element;
}

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) {
	if(name) {
		name = "js-" + name + "-css";
		if (document.getElementById(name)) return;
	}
	var se = document.createElement("style");
	se.type = "text/css";
	if(name) se.id = name;
	if (se.styleSheet) se.styleSheet.cssText = cssCode;
	else se.appendChild(document.createTextNode(cssCode));
	var hd = document.getElementsByTagName("head");
	if(hd && hd[0]) hd[0].appendChild(se);
	else document.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.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.addPNG = function(node, imageURL) {
	if (JSKitLib.isIE()) {
		node.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageURL + "', sizingMethod='crop')"
	} 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.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.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.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.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);
	});
}



// rounds number to x decimal places
JSKitLib.round = function(number, x) {
	x = (!x ? 2 : x);
	return Math.round(number*Math.pow(10,x))/Math.pow(10,x);
}

JSKitLib.zeroPad = function(number, x) {
	number = JSKitLib.round(number, x);
	var text = new String(number);
	var matches = text.match(/(\d*)(\.(\d*))?/) || [];
	var decimal = matches[3] || '';
	if (!decimal) {
		text += '.';
	}
	var count = x - decimal.length;
	for (var i=0; i<count; i++) {
		text += '0';
	}
	return text;
}



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


// Detect wether window.onload has fired
var JSKitWindowOnLoadFired = false;
JSKitLib.addLoadEvent(function() { JSKitWindowOnLoadFired = true; });


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


/* JS Rating Class */
function JSRC() {

  this.jraIndex = $JRA.length;
  $JRA.push(this);
  var self = this;

  this.cr = function(tag) { return document.createElement(tag) };

  this.pathOverride = '';
  this.config = {};
  this.raterInc = 2;  // Increment ratio of rateable v. displayable
  this.scale    = 10; // Points on rating scale

  this.onRate = []; // Callbacks for post rating processing

  this.isStandalone = function() {
    return (this.config.standalone == 'yes') ? true : false;
  }

  this.starWidth       = 16;
  this.starHeight      = 15;
  this.miniStarWidth   = 9;
  this.miniStarHeight  = 9;
  this.totalWidth; //The total width of the visible widget

  var wl = window.location;

  var idName = 'js-kit-rating';

  var target = arguments.length ? arguments[0] : document.getElementById(idName);
  var options = arguments[1] || {};

  if (target) {

    this.target = target;

    // Handling user configuration settings
    this.config.path = options.path || target.getAttribute('path');
    this.config.uniq = options.uniq || target.getAttribute('uniq') || '';
    this.config.standalone = options.standalone || target.getAttribute('standalone') || 'no';
    this.config.view = options.view || target.getAttribute('view') || 'combo';
    this.config.commentprompt = options.commentprompt || target.getAttribute('commentprompt') || true;
    this.config.starcolor = options.starcolor || (target.getAttribute('starcolor')||"").toLowerCase();
    this.config.usercolor = options.usercolor || (target.getAttribute('usercolor')||"").toLowerCase();
    this.config.imageurl  = options.imageurl  || target.getAttribute('imageurl');
    this.config.imagesize = options.imagesize || (target.getAttribute('imagesize')||"");
    this.config.title = options.title || target.getAttribute('title') || '';
    this.config.notop = options.notop || target.getAttribute('notop') || '';
    this.config.permalink = options.permalink || target.getAttribute('permalink') || '';
    this.config.freeze = options.freeze || target.getAttribute('freeze') || 'no';
    this.config.menu = options.menu || 'yes';

    // Special menu handling for particular sites
    if (wl.host.match(/icanhascheezburger.com/)) { this.config.menu = 'no'; }

    if(this.config.imageurl && this.config.imagesize) {
	var dim = self.config.imagesize.match(/(\d+)([^\d]+(\d+))?/);
	if(dim) {
		self.starWidth = dim[1];
		self.starHeight = dim[3] || self.starWidth;
	}
    }
    this.ratingBarWidth  = this.scale / this.raterInc * this.starWidth; 
    this.ratingBarHeight = this.starHeight;

    if (this.config.path) {
        var path = String(this.config.path);
        var ar = path.match(/^https?:\/\/[^\/]+(.*)/);
        if(ar) this.pathOverride = ar[1];
        else this.pathOverride = path.replace(/^([^\/]+)/, wl.pathname + "/$1");
    }

    this.path = this.pathOverride || wl.pathname;
    this.uniq = this.config.uniq || this.path;
    if ( ! $JRH[this.uniq]) {
      $JRH[this.uniq] = [];
    }
    $JRH[this.uniq].push(this);

    this.defineIcons();
    JSKitLib.preloadImg(JSRC.WINDOW_BG_IMG);
    JSKitLib.preloadImg(JSRC.INFO_IMG);

    if (options.newRating) {
        this.newRating(options.newRating.objSum, options.newRating.objNum, options.newRating.userRating);
    }

    this.myref = function() {
	if(arguments.length) return self.path;
	return encodeURIComponent(wl.protocol + "//" + wl.host
          + (self.pathOverride.length ? "/" : wl.pathname));
    }

    this.server = function(ext, data) {
      var sc = self.cr("script");
      sc.setAttribute("charset", "utf-8");
      sc.src = JSRC.URI + ext + self.pathOverride
		+ "?ref=" + self.myref() + "&" + data;
      self.target.appendChild(sc);
      return false;
    }
    if(options.autorequest) {
	var mr = this.myref('path');
	this.server('-data.js', 'p[0]=' + encodeURIComponent(mr)
		+ ((mr == this.uniq) ? ''
			: ('&u[0]=' + encodeURIComponent(this.uniq)))
		+ '&jx[0]=' + this.jraIndex);
    }
  } else {

    /* Iterate and find all rating divs */
    var els = document.getElementsByTagName('div');
    if (els && els.length) {
      $JRA.shift();
      var multiQ = '';
      var multiI = 0;
      var reqMulti = function(atext) {
        if(!atext.length) return;
	var sc = self.cr("script");
        sc.src = JSRC.URI + "-data.js?ref="
	  + encodeURIComponent(wl.protocol + "//" + wl.host + wl.pathname)
	  + atext;

        $JRA[0].target.appendChild(sc);

      }
      for (var i=0; i < els.length; i++) {
        if (els[i].className.match(/js-kit-rating/)) {
          var r = new JSRC(els[i]);
	  var mr = r.myref('path');
	  multiQ += "&p["+multiI+"]=" + encodeURIComponent(mr)
			+ ((mr == r.uniq) ? ''
			    : ("&u["+multiI+"]=" + encodeURIComponent(r.uniq)))
			+ "&jx[" + multiI + "]=" + r.jraIndex;
	  if(multiQ.length > 700) {
		reqMulti(multiQ);
		multiQ = '';
		multiI = 0;
	  } else {
		multiI ++;
	  }
        }
      }
      reqMulti(multiQ);
      if ($JRA.length) {
        return;
      }
    }
    /* Handling for single line entry */
  }

}

/* Constants */
JSRC.DOMAIN = (window.location.protocol.substr(0, 4) != 'http' ? 'http:' : '')
              + '//js-kit.com';
JSRC.URI = JSRC.DOMAIN + '/rating';
JSRC.BASE_STAR_URI = JSRC.DOMAIN + '/images/stars/';
JSRC.INFO_IMG = JSRC.DOMAIN + '/images/i-wg.png';
JSRC.INFO_IMG_ALERT = JSRC.DOMAIN + '/images/i-wg-green.png';
JSRC.INFO_IMG_WIDTH = 15;
JSRC.INFO_IMG_OFFSET = 7;
JSRC.INFOBOX_WINDOW_WIDTH = 200;
JSRC.CSS = {
	'js-rating-labelText': 'padding-top: 2px; font-size: 11px; text-align: center; cursor: default; -moz-user-select: none;',
	'js-rating-afterRating': 'width: 100px; font-size: 12px; text-align: center; padding: .3em;',
	'js-rating-infoBox': 'color: black; text-align:left; -moz-user-select: none;',
	'js-rating-infoBoxStats': 'line-height: 12pt; padding: 0.5em 0.8em 0.2em 0.8em; font-family: Arial, Helvetica, sans-serif; font-size: 10pt;',
	'js-rating-infoBoxPoweredBy': 'font-size: 9pt;',
	'js-rating-infoBoxRatingsDisabled': 'font-size: 9pt; color: #a00;'
}


JSRC.prototype.defineIcons = function() {

  var self = this;
  this.fullStar  = [];
  this.halfStar  = [];
  this.emptyStar = [];
  this.miniFullStar  = [];
  this.miniEmptyStar = [];

  var genstar = function(confColor, defColor, type) {
	var acceptedColors = { blue:1, yellow:1, gold:1, golden:1,
			green:1, violet:1, emerald:1, indigo:1, red:1, ruby:1 };
	var color = (confColor && acceptedColors[confColor])
			? confColor : defColor;
	var starURI = JSRC.BASE_STAR_URI;
	if(self.config.imageurl) {
		starURI = self.config.imageurl + '/';
		color = type;
	}
	var size = '';

	self.fullStar[type]  = starURI + color + size + '.png';
	self.halfStar[type]  = starURI + color + size + '-half.png';
	self.emptyStar[type] = starURI + size + 'gray.png';

	if ( ! self.config.imageurl) {
		self.miniFullStar[type]  = starURI + color + '-tiny.png';
		self.miniEmptyStar[type] = starURI + 'gray-tiny.png';
		self.miniStarWidth = 9;
		self.miniStarHeight = 9;
	} else {
		self.miniFullStar[type]  = self.fullStar[type];
		self.miniEmptyStar[type] = self.emptyStar[type];
		self.miniStarWidth = self.starWidth;
		self.miniStarHeight = self.starHeight;
	}

	JSKitLib.preloadImg(self.fullStar[type]);
	JSKitLib.preloadImg(self.halfStar[type]);
	JSKitLib.preloadImg(self.emptyStar[type]);
	JSKitLib.preloadImg(self.miniFullStar[type]);
	JSKitLib.preloadImg(self.miniEmptyStar[type]);

  }

  genstar(this.config.starcolor, 'ruby', 'star');
  genstar(this.config.usercolor, 'gold', 'user');
}

/* Init a single JSRC object */
if ( ! $JRA.length) {
  new JSRC();
  $JSKitGlobal.setRatingsAppAvailable();
}

JSRC.writeCSS = function() {
	var css = '';
	for (prop in JSRC.CSS) {
		css += '.' + prop + ' {' + JSRC.CSS[prop] + '}';
	}
	JSKitLib.addCss(css, 'jsrc');
}

JSRC.writeCSS();

JSRC.prototype.dtInfoBox
 = '<div class="js-rating-infoBox" onselectstart="return false">'
  + '<div class="js-rTopDetailFont" style="color: black; background-color:#ffa; margin: .5em .8em 0 .8em; padding: 2px 5px; text-align:center;">About this rated object</div>'
 +  '<div class="js-rating-infoBoxStats">'
 +   '<div class="js-rating-infoBoxRatingsDisabled" style="display:none;">{Label:ratingsDisabled}<br></div>' // only freeze
 +   '<span class="js-ratingInfoBoxTotalVotes">{totalVotes}</span>'
 +   ' <span class="js-ratingInfoBoxAvgRating" style="white-space: nowrap">{avgStarRating}</span>'
 +   '<br>'
 +   '<span class="js-ratingInfoBoxUserRatingMsg">{userRatingMsg}</span>'
 +  '</div>'
 + '</div>'
 ;

JSRC.prototype.html = function(text) {
	var div = this.cr("div");
	div.innerHTML = text;
	var ch = div.firstChild;
	div = null;
	return ch;
}

JSRC.prototype.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) {
			self.mapClass2Object(ctl, child);
		}, e.childNodes);
	} catch(e){}
	return ctl;
}

JSRC.prototype.gtmpl = function(t) {
	var lowercase = function(a, m) { return String(m).toLowerCase(); }
	t = t.replace(/^[^<]*(<.*>)[^>]*$/m, "$1");
	t = t.replace(/(<[\/]?[A-Z]+)/g, lowercase);
	t = t.replace(/{Label:([^}]*)}/g,function(a,m){return $JRL(m);});
	return t;
}

JSRC.prototype.tmpl = function(t, obj) {
	var self = this;
	t = self.gtmpl(t);
	t = t.replace(/{([A-Za-z0-9]+)}/g,function(a,m){return obj.hasOwnProperty(m)?obj[m]:'{'+m+'}';});
	return t;
}

/* Will add a callback for post rating processing */
JSRC.prototype.addOnRate = function(action) {
  this.onRate.push(action);
}

JSRC.prototype.processOnRate = function() {
  for (var i=0; i < this.onRate.length; i++) {
    this.onRate[i]();
  }
}

JSRC.prototype.table = function(content) {
  var self = this;
  var a = function(n, w) {var o=self.cr(n);o.appendChild(w);return o;}
  var t = a('table', a('tbody', a('tr', a('td', content))));
  var z = function(a) {t.setAttribute(a, '0')}
  z('cellSpacing');
  z('cellPadding');
  z('border');
  return t;
}

JSRC.prototype.display = function() {

  var self = this;

  // wrapper for our floated elements
  var wrapper = this.cr('div');
  wrapper.style.margin = '3px';
  wrapper.style.position = 'relative';
  wrapper.onselectstart = function() { return false; }

  var actionable = (this.config.freeze == "yes") ? false : true;

  if (this.config.view.match(/(combo|user)/) && this.config.freeze == "yes") {
      this.userRatingBar = this.initRating(this.objEffRating, 'star', false);
  } else {
      this.userRatingBar = this.initRating(this.userRating, 'user', actionable);
  }

  this.userRatingDiv = this.cr('div');
  this.userRatingDiv.appendChild(this.userRatingBar);

  this.textTotal = this.cr('div');
  this.textTotal.className = 'js-rating-labelText';
  this.refreshTextTotal();

  if (this.config.view.match(/split/)) {
    // split view : community and user ratings
    this.defaultView = 'user';

    var starRatingBar = this.initRating(this.objEffRating, 'star', false);
    var starRatingDiv = this.cr('div');
        starRatingDiv.className = 'js-rating-splitObjectRating';
    JSKitLib.addStyle(starRatingDiv, 'margin-right:10px; float:left; width:' + this.ratingBarWidth + 'px');
    starRatingDiv.appendChild(starRatingBar);
    starRatingDiv.appendChild(this.textTotal);

    wrapper.appendChild(starRatingDiv);

    this.userRatingDiv.style.cssFloat = 'left';
    this.userRatingDiv.style.styleFloat = 'left';
    this.userRatingDiv.style.width = this.ratingBarWidth + 'px';

    this.textRating = this.cr('div');
    this.textRating.className = 'js-rating-labelText';
    this.refreshTextRating();
    this.userRatingDiv.appendChild(this.textRating);

    this.activeText = this.textRating;
    this.totalWidth = this.ratingBarWidth + this.ratingBarWidth + 10;

    wrapper.appendChild(this.userRatingDiv);

  } else if (this.config.view.match(/user/)) {
    // single star set, only shows current user's rating
    this.defaultView = 'user';

    this.userRatingDiv.style.cssFloat = 'left';
    this.userRatingDiv.style.styleFloat = 'left';

    this.textRating = this.cr('div');
    this.textRating.className = 'js-rating-labelText';
    this.refreshTextRating();
    this.userRatingDiv.appendChild(this.textRating);

    this.activeText = this.textRating;

    this.totalWidth = this.ratingBarWidth;
    wrapper.appendChild(this.userRatingDiv);

  } else {
    // single star set, defaults to community rating
    this.defaultView = 'star';

    this.userRatingDiv.style.cssFloat = 'left';
    this.userRatingDiv.style.styleFloat = 'left'; 

    this.userRatingDiv.appendChild(this.textTotal);
    this.activeText = this.textTotal;

    this.totalWidth = this.ratingBarWidth;

    wrapper.appendChild(this.userRatingDiv);
  }

  // Set our total width
  wrapper.style.width = this.totalWidth + 'px';

  /* Rating Menu */
  if (this.config.menu != 'no') {
    wrapper.style.width = (this.totalWidth + 10 + JSRC.INFO_IMG_WIDTH) + 'px';
    var menuArrow = this.createMenuArrow();
    this.prepMenu(); // 'i' and infobox
    wrapper.appendChild(menuArrow);

  }

  // Set the target width
  var targetMinWidth = parseInt(wrapper.style.width) + 6; // 3px margin
  var targetWidth = this.target.style.width || targetMinWidth;
  if (parseInt(targetWidth) <= targetMinWidth) {
    this.target.style.width = targetMinWidth + 'px';
  }

  if (( ! this.isStandalone()) && this.config.commentprompt != 'no') {

    var addCommentPrompt = function() {

      var afterRatingA = document.createElement('a');
      afterRatingA.appendChild(document.createTextNode($JRL('addACommentToYourRating')));
      afterRatingA.onclick = function() { 
        self.getCommentsAppObject().ShowCommentDialog(null);
        return false;
      };
      afterRatingA.href = 'javascript:void(0);';
  
      var afterRatingDiv = document.createElement('div');
      afterRatingDiv.appendChild(afterRatingA);
      afterRatingDiv.className = 'js-rating-afterRating';

      var afterRating = self.createWindow(afterRatingDiv);
      afterRating.style.position ='absolute';
      afterRating.style.left = (self.totalWidth + 5) + 'px';
      afterRating.style.top = '-4px';
      afterRating.style.zIndex = '110'; // above menuArrow
      JSKitLib.hide(afterRating);

      self.addOnRate(function() { 
        JSKitLib.show(afterRating);
        setTimeout(function() { JSKitLib.hide(afterRating); }, 5000);
      });

  
      wrapper.appendChild(afterRating);
    }
    $JSKitGlobal.tryCommentsAppObjectAction(this.uniq, addCommentPrompt); 
  }

  this.target.appendChild(this.table(wrapper)); // stars

  if ( ! this.config.view.match(/split/)) {
    this.refreshRating();  
  }

}

// generic jskit body tag fror absolutely position elements
JSRC.prototype.createBodyElement = function() {
  if ( ! document.getElementById('js-kit-body-element')) {
    var be = this.cr('div');
    be.id = "js-kit-body-element";
    document.body.appendChild(be);
  }
}

// Adds the 'i' button and infobox
JSRC.prototype.prepMenu = function() {
  var self = this;
  var prepMenu = function() {
    self.createBodyElement();

    var infoBoxWrapper = self.cr('div');
    self.infoBoxWrapper = infoBoxWrapper;

    document.getElementById('js-kit-body-element').appendChild(infoBoxWrapper);

    var infobox1Show = infobox2Show = false;

    var infoBoxMouseover = function() {
      clearTimeout(self.ratingMenuTimer);
    }

    self.target.onmouseover = function() { 
      infobox1Show = true; 
      infoBoxMouseover(); 
      JSKitLib.show(self.menuArrow);
    }
    self.infoBoxWrapper.onmouseover = function() { infobox2Show = true; infoBoxMouseover(); }

    var infoBoxMouseout = function() {

      if (infobox1Show || infobox2Show) 
        return;

      self.ratingMenuTimer = setTimeout(function() {
        self.ratingMenuTimer = null;
          self.hideInfoBox();
          JSKitLib.hide(self.menuArrow);
      }, 1500);
    }

    self.target.onmouseout = function() { infobox1Show = false;  infoBoxMouseout(); }
    self.infoBoxWrapper.onmouseout = function() { infobox2Show = false; infoBoxMouseout(); } 

  };

  // document.body.append functionality can only happen after window.onload in IE
  JSKitLib.deferCallIfIE(prepMenu);

}

JSRC.prototype.doAdminAlert = function() {
	if (this.isAdmin && !this.target.getAttribute('permalink')) {
		var alertEndDate = new Date();
		alertEndDate.setFullYear(2008, 3, 22);
		var today = new Date();
		if (today < alertEndDate) {
			return true;
		}
	}
	return false;
}

JSRC.prototype.createMenuArrow = function() {
  this.menuArrow = document.createElement('div');
  JSKitLib.addStyle(this.menuArrow, 'width:15px; height:15px; margin-left:' + JSRC.INFO_IMG_OFFSET + 'px; cursor:pointer; float: left;');
  JSKitLib.hide(this.menuArrow);

	if (this.doAdminAlert()) {
		JSKitLib.addPNG(this.menuArrow, JSRC.INFO_IMG_ALERT);
	} else {
		JSKitLib.addPNG(this.menuArrow, JSRC.INFO_IMG);
	}

  this.infoBoxImg = this.menuArrow;
  var self = this;
  this.menuArrow.onclick = function() { 
    self.toggleInfoBox();
  }

  return this.menuArrow;
}

JSRC.prototype.showInfoBox = function() {

	// Only one infobox should be displayed at a time
	JSKitLib.map(function(obj) { obj.hideInfoBox(); }, $JRA);

	var div = this.cr('div');
	var pos = JSKitLib.findPos(this.target);
	JSKitLib.setStyle(div, 'width: ' + JSRC.INFOBOX_WINDOW_WIDTH + 'px; position: absolute; top: ' + (pos[3] + 3) + 'px; z-index:10000;');

	// If rating widget is too close to left side, show on the right side
	if (pos[0] > JSRC.INFOBOX_WINDOW_WIDTH || this.totalWidth >= JSRC.INFOBOX_WINDOW_WIDTH) {
		div.style.left = (pos[2] - JSRC.INFOBOX_WINDOW_WIDTH - 6) + 'px'; // 3px margin
	} else {
		div.style.left = pos[0] + 'px'; // 3px margin
	}

	this.infoBoxWrapper.appendChild(div);
	var infoBox = new JSRTC(div, { count: 3 }, this);

	this.infoBox = infoBox;

}

JSRC.prototype.hideInfoBox = function() {
  if (this.infoBox) {
	this.infoBox.removeChildren();
	this.infoBox = null;
  }
}

JSRC.prototype.toggleInfoBox = function() {
  if (this.infoBox) {
    this.hideInfoBox();
  } else {
    this.showInfoBox();
  }
}

JSRC.prototype.refreshInfoBox = function() {
  if (this.infoBox) {
    this.hideInfoBox();
    this.showInfoBox();
  }
}

JSRC.prototype.createWindow = function(content, opts) {

  if (typeof opts != 'object') {
    opts = {};
  }

  var wrapper = document.createElement('div');
  wrapper.className = 'js-rating-windowWrapper';

  var box = document.createElement('div');
  box.className = 'js-rating-window';
  
  if (typeof content == 'string') {
    box.appendChild(this.html(content));

  } else {
    box.appendChild(content);
  }

  wrapper.appendChild(box);


  return wrapper;

}

JSRC.prototype.createInfoBox = function() {

	var self = this;
	var vars = {
		totalVotes: this.getTextForTotalVotes(this.objNum),
		avgStarRating: this.objAvgStarRating > 0
			? ('(' + JSKitLib.zeroPad(this.objAvgStarRating, 2) + '&nbsp;' + $JRL('avgRating') + ')')
			: '',
		userRatingMsg: (function() {
			if (self.userRating) {
				return $JRL('yourRating') + ': ' + (self.userRating / self.raterInc);
			} else {
				if (self.config.freeze != 'yes') {
					return (self.objNum) ? $JRL('youHaveNotRatedYet') : $JRL('beTheFirstToRate');
				} else {
					return '';
				}
			}
		})()
	};

	var tmpl = this.html(this.tmpl(this.dtInfoBox, vars));
	var ctls = this.mapClass2Object({}, tmpl);

	if (this.config.freeze == "yes") {
		JSKitLib.show(ctls['js-rating-infoBoxRatingsDisabled']);
	}

	return tmpl;

}

/* Process all rating objects with the same ID */
JSRC.prototype.processSiblings = function(handler) {
  for (var i=0; i < $JRH[this.uniq].length; i++) {
    handler($JRH[this.uniq][i]);
  }
}

JSRC.prototype.rate = function(givenRating) {
  var oldRating = this.userRating;
  this.setUserRating(givenRating);
  var objSum = this.objSum;
  var objNum = this.objNum;
  if(oldRating) {
    objSum -= oldRating;
    objNum --;
  }
  this.setTmpText($JRL('thankYou'));

  // Update all ratings for this ID
  this.processSiblings(function(sibling) {
    sibling.newRating(objSum + givenRating, objNum + 1, givenRating);
  });


  // Handle any callbacks
  this.processOnRate();

  var title = this.config.title || "";
  this.server(".put", "rating=" + givenRating
	+ (title ? ("&title=" + encodeURIComponent(title)) : "")
	+ (this.config.notop ? "&notop=true" : "")
	+ (this.config.permalink ? "&permalink=" + encodeURIComponent(this.config.permalink) : "")
	);
}

JSRC.prototype.setUserRating = function(rating) {
  this.userRating = rating;
}

// Returns: an array of actionable rating icons 
JSRC.prototype.getRatingIcons = function() {

  if (this._ratingIcons && this._ratingIcons.length > 0) {
    return this._ratingIcons;
  }

  this._ratingIcons = this._getIcons('js-kit-rater');
  return this._ratingIcons;
}

JSRC.prototype.getObjIcons = function() {

  if (this._objIcons && this._objIcons.length > 0) {
    return this._objIcons;
  }

  this._objIcons = this._getIcons('js-kit-objIcon');
  return this._objIcons;
}

JSRC.prototype._getIcons = function(iconClass) {

  var divs = this.target.getElementsByTagName('div');
  var icons = [];
  for (var i=0; i < divs.length; i++) {
    if (divs[i].className && divs[i].className.indexOf(iconClass) >= 0) {
      icons.push(divs[i]);
    }
  }
  return icons;
}

JSRC.prototype.getTextForTotalVotes = function(votes) {
  var text;
  switch(votes) {
    case  1: text = votes + ' ' + $JRL('vote');  break;
    default: text = votes + ' ' + $JRL('votes'); break;
  }
  return text;
}

JSRC.prototype.getTextForUserRating = function(rating) {
  var text = $JRL('yourRatingTitleCase') + ': ' + rating;
  return text;
}

JSRC.prototype.refreshTextTotal = function() {
  var text = (this.objNum) ? this.getTextForTotalVotes(this.objNum) : $JRL('unrated');
  this.setTextTotal(text);
}

JSRC.prototype.refreshTextRating = function(text) {
  if (this.userRating) {
    var text = this.getTextForUserRating(this.userRating / this.raterInc);
  } else { 
    var text = $JRL('yourRatingTitleCase');
  }
  this.setTextRating(text);
}

JSRC.prototype.setTextRating = function(text) {
  this._setText(this.textRating, text);
}

JSRC.prototype.setTextTotal = function(text) {
  this.lastSetText = text;
  if(this.tmpTextTimer)
	return;
  this._setText(this.textTotal, text);
}

JSRC.prototype.setActiveText = function(text) {
  this._setText(this.activeText, text);
}

JSRC.prototype.setTmpText = function(text) {
  var self = this;
  if(this.tmpTextTimer)
    clearTimeout(this.tmpTextTimer);
  this.tmpTextTimer = setTimeout(function() {
	self.tmpTextTimer = null;
	self.setTextTotal(self.lastSetText);
    }, 1000);
  this._setText(this.textTotal, text);
}

JSRC.prototype._setText = function(node, text) {
  if ( ! node) {
    return;
  }
  while (node.hasChildNodes()) {
    node.removeChild(node.firstChild);
  }
  node.appendChild(document.createTextNode(text));
}

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

	JSKitLib.addPNG(star, imageURL);    
}

// Handles the hover state for the actionable stars
JSRC.prototype.hover = function(index) {

  if(this.tmpTextTimer) return;

  // The text which is under the hover state
  this.setActiveText($JRL('rateThis') + ': ' + (index / this.raterInc));

  var icons = this.getRatingIcons();
  for (var i=0; i < icons.length; i++) {
    if (index > (i * this.raterInc)) {
	this.setImage(icons[i], this.fullStar['user']);
    } else {
	this.setImage(icons[i], this.emptyStar['user']);
    }
  }

}

JSRC.prototype.refreshObjRating = function() {
  var icons = this.getObjIcons();
  this._refreshRating('star', this.objEffRating, icons);
}

// Resets the user rating view to their actual rating
JSRC.prototype.refreshRating = function() {

  if (this.defaultView == 'star') {
    var type = 'star';
    var comparison = this.objEffRating;
  } else {
    var type = 'user';
    var comparison = this.userRating;
  }

  var icons = this.getRatingIcons();

  this._refreshRating(type, comparison, icons);

  if (this.defaultView == 'star') {
    this.refreshTextTotal();
  } else {
    this.refreshTextRating();
  }
}

JSRC.prototype._refreshRating = function(type, comparison, icons) {

  for (var i=0; i < icons.length; i++) {
    if (comparison > (i * this.raterInc)) {
      if (i * this.raterInc + (this.raterInc / 2) == comparison) {
        this.setImage(icons[i], this.halfStar[type]);
      } else {
        this.setImage(icons[i], this.fullStar[type]);
      }
    } else {
      this.setImage(icons[i], this.emptyStar[type]);
    }
  }
}  

JSRC.prototype.initRating = function(rating, type, actionable) {
  var self = this;
  var node = this.cr('div');
  node.style.width = this.ratingBarWidth + 'px';
  node.style.height = this.ratingBarHeight + 'px';

  var inf = function() {
	if(self.refreshScheduled)
		clearTimeout(self.refreshScheduled);
  }
  var outf = function() {
	if(self.refreshScheduled)
		clearTimeout(self.refreshScheduled);
	self.refreshScheduled = setTimeout(
		function(){self.refreshScheduled=null;
		self.refreshRating()}, 300);
  }

  node.onmouseover = function() {
			if(self.refreshScheduled)
				clearTimeout(self.refreshScheduled);
		}
  node.onmouseout = outf;

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

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

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

    if (rating + this.raterInc > i) {
      if (rating + this.raterInc - i >=  this.raterInc) {
	this.setImage(star, this.fullStar[type]);
      } else {
	this.setImage(star, this.halfStar[type]);
      }
    } else {
      this.setImage(star, this.emptyStar[type]);
    }

    if (actionable) {
     (function(i) {
      star.className += ' js-kit-rater';
      star.onmouseover = function() { inf(); self.hover(i); }
      star.onmouseout  = outf;
      star.onclick     = function() { self.rate(i); }
     })(i);
    } else {
      star.className += ' js-kit-objIcon';
    }
    node.appendChild(star);
  }

  if (actionable) {
    node.style.cursor = 'pointer';
  }

  return node;
}


JSRC.prototype.getCommentsAppObject = function() {
  if (this.isStandalone()) {
    return null; 
  } else {
    return $JSKitGlobal.getCommentsAppObject(this.uniq);
  }
}

JSRC.prototype.hasCommentsAppObject = function() {
  return this.getCommentsAppObject() ? true : false;
}

JSRC.prototype.clone = function(node, options) {
  if ( ! options) {
    options = {};
  }

  var clone = new JSRC(node, {
    'newRating' : {
      'objSum' : this.objSum,
      'objNum' : this.objNum,
      'userRating' : this.userRating
    },
    'path' : options.path || this.config.path,
    'uniq' : options.uniq || this.config.uniq,
    'view' : options.view || this.config.view,
    'notop' : options.notop || this.config.notop,
    'commentprompt' : options.commentprompt || this.config.commentprompt,
    'starcolor' : options.starcolor || this.config.starcolor,
    'usercolor' : options.usercolor || this.config.usercolor,
    'imageurl' : options.imageurl || this.config.imageurl,
    'imagesize' : options.imagesize || this.config.imagesize,
    'menu' : options.menu || this.config.menu

  });

  return clone;
}

JSRC.prototype.newRating = function(sum, num, userRating) {
  this.objSum = sum;
  this.objNum = num;
  this.userRating = userRating;
  this.objAvgStarRating = JSKitLib.round((sum / num) / this.raterInc, 1);
  this.objEffRating = Math.round(sum / num);  // Used for star display purposes

  if(this.refreshScheduled) {
	clearTimeout(this.refreshScheduled);
	this.refreshScheduled = null;
  }

  if (this.constructed) {
    this.refreshTextTotal();
    this.refreshObjRating();
    this.refreshRating();
  } else {
    this.constructed = true;
    this.display();
  }
}


/*
 * Copyright (c) 2007 JS-Kit.com. All rights reserved.
 * $Date: 2007-10-28 23:53:06 -0800 (Sun, 28 Oct 2007) $
 */

if(!window.$JCA) {
  var $JCA = [];
  var $JCLT = {
	leaveComment: 'Leave a comment',
	leaveCommentReview: 'Post your comments about the book',
	leaveCommentReply: 'Leave a comment',
	nameLabel: 'Your name:',
    cityLabel: 'Your city, country:',
	emailLabel: 'Send replies to email:',
	emailNote: '(if provided, email will not be displayed or shared)',
	ratingLabel: 'Rating:',
	commentLabel: 'Comment:',
	commentLabelReview: 'Review:',
	commentLabelReply: 'Comment:',
	submit: 'Submit comment',
	submitReview: 'Submit review',
	submitReply: '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?',
        'Like this comment?Review': 'Was this review helpful?'
  };
  var $JCL = window.JSCC_Translate || function(t) {
    return (window.$JCLTL ? $JCLTL[t] : false) || $JCLT[t] || t;
  } 
}

/* 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); }
	var wl = window.location;
	this.uriDomain = (wl.protocol.substr(0, 4) != 'http' ? 'http:' : '')
				+ '//js-kit.com';
	this.uri = this.uriDomain + '/comment';
	this.fieldDfl = {};
	this.TC = {};
	this.tmpID = 0;
	this.pathOverride = "";
	this.uniq = wl.pathname;
	this.cmtById = {};
	this.objById = {};
	this.utmpl={};
	this.config = {};
	this.gen = 0;
	this.ctag = null;
	this.czidx = 300;

	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(/^([^\/]+)/,
					wl.pathname + "/$1");
			path = this.pathOverride;
		} else { path=wl.pathname; }
		this.uniq = target.getAttribute("uniq") || path;

		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 {
		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) {
			$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 = "";

	// 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(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;
	})(
		['standalone', 'no'],
		['scoring', 'yes'],
		['paginate', 50],
		['backwards', 'yes'],
		['domain', wl.host],
		['sort', ['karma','date','name','status','rating']],
		['thread', ['yes','no']],
		'adminBgColor',
		'moderate',
		'permalink'
	);
	this.config.permalink = target.getAttribute('permalink') || '';
	this.config.domain = this.config.moderate || this.config.domain;
	if(this.config.paginate <= 0) this.config.paginate = 200;
	if (this.config.backwards == 'yes')
		this.backwards = true;
	else if(target.getAttribute('backwards'))
		this.backwards = (this.config.backwards == 'yes');
	else if(target.getAttribute('paginate'))
		this.backwards = !!this.config.paginate;
	else
		this.backwards = false;
	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;
	self.setDefaultField = function(name,value){self.fieldDfl[name]=value;}

	this.server = function(ext, data) {
		var sc = this.cr("script");
		sc.setAttribute("charset", "utf-8");
		sc.src = this.uri + ext + "?ref=" + wl.protocol + '//'
			+ encodeURIComponent(
				this.config.domain
				+ (this.pathOverride || wl.pathname))
			+ (this.config.moderate?'&mod':'')
			+ (this.config.permalink ? ('&permalink=' + encodeURIComponent(this.config.permalink)) : '')
			+ "&rvy=1&" + data;

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

	this.getpages = function(sp, ap) {
		var preq = self.preq;
		if(!sp) sp = preq.sp;
		self.loading = (new Date()).valueOf();
		self.server("s-data.js", "jx="+self.jcaIndex
			+ "&gen=" + self.gen
			+ "&srt=" + preq.srt
			+ "&ord=" + preq.ord
			+ (preq.thr=='yes'?'':"&prs=flat")
			+ "&sp="+ sp + "&pn="+ preq.pn + "&ps="+ preq.ps
			+ (ap?ap:''));
	}

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

        this.getRatingsAppObject = function() {
            if (this.isStandalone()) {
                return null;
            } else {
                return $JSKitGlobal.getRatingsAppObject(this.uniq);
            }
        }
		
        this.withRatings = this.getRatingsAppObject()!=null;

        this.JCL = function(m) {
            if(this.withRatings) {
                var nm = m + 'Review';
                var r = $JCL(nm);
                return r==nm?$JCL(m):r;
            } else {
                return $JCL(m);
            }
        }

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

	this.getpages();
}

JSKitLib.addCss(''
+ ".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-singleCommentCity { font-size: 7pt; }"
+ ".js-singleCommentDate { font-size: 7pt; }"
+ ".js-singleCommentKarma, .js-singleCommentOrigin { 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; }"
+ ".js-Progress { position: absolute; visibility: hidden; right: 5px; top: 5px; width: 15px; height: 15px; }"
+ ".js-SettingsWindow { position: absolute; margin: 2px; padding: 0.3em; border: solid 1px #cccccc; color: #404040; }"
, 'cmt');
(function(v){v=parseFloat(v.split("MSIE")[1]);
if(v>=5.5)JSKitLib.addCss('.js-singleComment{zoom:1} .js-singleCommentBg{zoom:1}', 'zoom');})
(navigator.appVersion);
if(navigator.userAgent.indexOf("Opera")>=0)
JSKitLib.addCss('wbr:after{content:"\\00200B"}', 'wbr');
else
JSKitLib.addCss(".js-singleCommentTEXT{word-wrap:break-word}", 'wbr');


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.html = 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.dtComment
 = '<div class="js-singleComment">'
 + '<div class="js-singleCommentBg">'
 + '<div class="js-singleCommentINFO">'
   + '<div class="js-singleCommentName">{Name}</div>'
   + '<div class="js-singleCommentCity">{City}</div>'
   + '<div class="js-singleCommentDate">{Date}</div>'
   + '<div class="js-singleCommentControls">'
     + '<span class="js-singleCommentReplyable">[<a class="js-singleCommentReply">{Label:reply}</a>]</span>'
     + '<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 js-commentSubject" style="display:none">{Label:leaveComment}</div>'
 + '<div class="js-commentFieldSubject js-commentSubjectReply" style="display:none">{Label:leaveCommentReply}</div>'
 + '<div class="js-commentFieldLabel">{Label:nameLabel}</div>'
 + '<div><input name="js-CmtName" SIZE=32 /></div>'
 + '<div class="js-commentFieldLabel js-commentCity">{Label:cityLabel}</div>'
 + '<div><input name="js-CmtCity" SIZE=32 /></div>'
 + '<div class="js-commentInputEmail">'
 + '<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>'
 + '<div class="js-commentFieldLabel js-commentRatingDisplay">{Label:ratingLabel}</div>'
 + '<div class="js-commentFieldRating js-commentRatingDisplay"></div>'
 + '<div class="js-commentFieldLabel js-commentLabel">{Label:commentLabel}</div>'
 + '<div class="js-commentFieldLabel js-commentLabelReply" style="display:none">{Label:commentLabelReply}</div>'
 + '<div><textarea name="js-CmtText" ROWS=4 COLS=32></textarea></div>'
 + '<div><input type=submit name="js-Cmtsubmit" VALUE="{Label:submit}">'
 + '<input type=submit name="js-CmtsubmitOrig" style="display:none" value="{Label:submit}">'
 + '<input type=submit name="js-CmtsubmitReply" style="display:none" value="{Label:submitReply}">'
 + '<input type=reset name="js-Cmtcancel" VALUE="{Label:cancel}"></div>'
 + '<div class="js-poweredBy js-antispamBy">(<a href="http://js-kit.com/comments?wow">Powered by JS-kit</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 self = this;
	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 self.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);
	if ((obj.status == 'M' || obj.status == 'H')
		&& (this.serverOptions.mmode == 'pre' || (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(!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.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.blockAction = function(action) {
	var s = this;
	var cid = s.ctBlock.forId;
	var cmt = s.cmtById[cid];
	s.hideSettingsWindow('ctBlock');
	switch(action) {
	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+"&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.server('.blk','id='+cid+"&by="+action);
		s.cmtDelete(cid, 'delete');
		break;
	}
}

JSCC.prototype.cmtBlock = function(cid) {}
JSCC.prototype.cmtApprove = function(cid) {
	var cmt = this.cmtById[cid];
	if(cmt.cobj.status == 'S') {
		this.cmtSetSpamStatus(cmt, false);
		cmt.cobj.status = 'S'; // cmtDelete's deal
	}
	this.cmtDelete(cid, 'message');
}
JSCC.prototype.cmtApproveUser = function(cid) {
	var cmt = this.cmtById[cid];
	if(cmt.cobj.status == 'S') {
		this.cmtSetSpamStatus(cmt, false);
		cmt.cobj.status = 'S'; // cmtDelete's deal
	}
	this.cmtDelete(cid, 'user');
}

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

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

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

	var flushSS = false;

	// Shift the comments one to the left.
	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;

		// Propagate "get from the server side" status.
		if(npage.ss) {
			this.pages[cp - 1].ss = true;
			flushSS = true;
			continue;
		} else if(flushSS) {
			npage.ss = true;
			continue;
		}

		npage.rmdiv();

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

	if(this.config.moderate)
		this.pathOverride = cmt.cobj.path;
	switch(approvalMode) {
	case 'message':
		this.server('.del', 'id=' + cid + '&apr=message'
			+ (oldStatus == 'S' ? '&junk=no' : '')); break;
	case 'user':
		this.server('.del', 'id=' + cid + '&apr=user'
			+ (oldStatus == 'S' ? '&junk=no' : '')); break;
	case 'delete':
		this.server('.del', 'id=' + cid); break;
	case 'ignore':
		/* Just delete from screen */
	default:
	}

	var p = this.pages[this.curPage - 1];
	if(p.ss) {
		this.ctag = null;
		this.czidx = 300;
		var pageNo = this.curPage;
		this.curPage = 0;
		this.displayPage(pageNo);
	}

}

JSCC.prototype.objppc = function() {}
JSCC.prototype.createCommentAsHTML = function(obj) {
	if(obj.status == 'D')
		return '';
	this.objppc(obj);
	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.html(this.createCommentAsHTML(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.depth) {
		cmt.style.marginLeft = this.level4margin(obj.depth)
	} else {
		obj.depth = 0;
	}

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

	jsc('').className += " js-singleCommentReply" + (obj.depth || 0);

        /* Handle review specific fields here */
		var cityDisp = (!this.isStandalone() && this.withRatings && obj.depth === 0) ? '' : 'none';
        cmt.city = jsc('City');
        if (cmt.city) cmt.city.style.display = cityDisp;
        cmt.label = jsc('cityLabel');
        if (cmt.label) cmt.label.style.display = cityDisp;

	/* 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.visibility = "hidden";
	}

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

	if(!this.scoringEnabled()
	|| (obj.yours && !this.adminMode) || !obj.karma || obj.depth) {
		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;
			}

		}
	}

    /* 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") {
		var rb = jsc("Replyable");
		if(rb) rb.style.display = "none";
	}

	this.FRef(cmt, jsc("Reply"), "ShowCommentDialog");
	this.FRef(cmt, jsc("Delete"), "cmtDelete");
	this.FRef(cmt, jsc("Block"), "cmtBlock");
	this.FRef(cmt, jsc("Approve"), "cmtApprove");
	this.FRef(cmt, jsc("ApproveUser"), "cmtApproveUser");

	var au = jsc("ApproveUser");
	if (au)
	{
		 au.style.display = (mmode == "onhold") ? "inline" :  "none";
	}

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

	cmt.bg = jsc('Bg');
	if(this.czidx < 10) this.czidx = 300; else this.czidx--;
	cmt.bg.style.zIndex = this.czidx;
	var cinfo = jsc('INFO');
	cmt.domINFO = cinfo;

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

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

  if(obj.ParentID) {
	var prn = this.objById[obj.ParentID];
	var td = prn ? prn.depth : 0;
	if(prn) {
		obj.depth = 1 + td;
		cmt.style.marginLeft = this.level4margin(obj.depth)

		this.replyPlacement(obj.ParentID, true, function(immed, apl) {
			if(apl) apl[0].insertBefore(cmt, apl[1]);
			prn.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++;
			try { this.czidx = 300;
				for(var i = 0; i < page.oarr.length; i++) {
				var sbl = this.cmtById[page.oarr[i].ID];
				sbl.bg.style.zIndex = this.czidx--;
				//alert('some zindex['+i+']= ' + sbl.bg.style.zIndex + ' hz='+ sbl.bg.currentStyle.hasLayout);
			}
			//alert('my zindex = ' + cmt.bg.style.zIndex + ' ' + cmt.bg.className + '/' + cmt.bg.currentStyle.hasLayout);
			} catch(e){alert(e);}
			fincb.apply(this, [cmt]);
		});
		return;
	}
  }

  // Fixme! create additional pages as necessary.
  if(this.preq.ord == 'desc') {
	this.displayPage(1, function(immed) {
		var page = this.pages[0];
		page.oarr.unshift(obj);
		page.harr.unshift(this.createCommentAsHTML(obj))
  		this.addChild(page.div, cmt, true);
	  	page.items++;
		fincb.apply(this, [cmt]);
	});
  } else {
	this.displayPage(this.pages.length, function(immed) {
		var page = this.pages[this.curPage - 1];
		page.oarr.push(obj);
		page.harr.push(this.createCommentAsHTML(obj));
  		this.addChild(page.div, cmt, false);
	  	page.items++;
		fincb.apply(this, [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 = '';
	var map = {'&':'&amp;','<':'&lt;','>':'&gt;','\n':'<br />'};
	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(/([&<>\n])/g,
			function(a,m) { return map[m]; });
		cmtObj[shortName] = text;
	}
	return message;
}

JSCC.prototype.cmtInPlace = function(cobj, fincb) {
	var div = this.TC["js-OldComments"];
	this.tmpID++;
	cobj.ID = "jst-" + this.tmpID;
	cobj.isEmbryonic = true;
	cobj.thread = [];
	cobj.depth = 0;
	cobj.jcaIndex = this.jcaIndex;
	cobj.admin = this.adminMode;
	var d = new Date();
	cobj.TS = Math.round(d.valueOf() / 1000);
	this.cmtInDiv(div, cobj, function(cmt) {
		if(cmt) this.flash(cmt);
		fincb.apply(this, [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, flush) {
	if(pageNo >= this.pages.length) return;
	var page = this.pages[pageNo - 1];
	var npage = this.pages[pageNo];
	npage.rmdiv();
	var obj;

	if(flush) {
		npage.ss = 0;
		npage.rmdiv();
		npage.items = 0;
		return this.pageShiftItemDescription(pageNo + 1, flush);
	}

	while(obj = page.oarr.pop()) {
		var html = page.harr.pop();
		if(npage.ss) {
			flush = true;
		} else {
			npage.harr.unshift(html);
			npage.oarr.unshift(obj);
		}
		if(obj.status != 'D') {
			page.items--;
			if(!flush) npage.items++;
			break;
		}
	}
	this.pageShiftItemDescription(pageNo + 1, flush);
}

// Search for a proper place for a reply
JSCC.prototype.replyPlacement = function(msgId, finalPlace, plcb) {
	if(!msgId) { plcb.apply(this, [true, null]); }
	var pobj = this.objById[msgId];
	if(!pobj) return null;

	var shiftF = function(imm, cmt, arridx, cb) {
		if(this.pages[this.curPage - 1].items >= this.config.paginate) {
			if(this.curPage == this.pages.length)
				this.pages.push(this.pages.empty());
			// 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.
				this.pageShiftLastItem();
			} else {
				this.displayPage(this.curPage + 1, function(immed) {
					var pdiv = this.pages[this.curPage - 1].div;
					var r = [pdiv, pdiv.firstChild, 0];
					cb.apply(this, [immed, r]);
				});
				return;
			}
		}
		/* Reply's place is right beside the entry */
		var r = [cmt.parentNode, cmt.nextSibling, arridx];
		cb.apply(this, [imm, r]);
	}

	// Find the last reply to this comment
	var lreplyObj = null;
	while(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 = pobj;

	// 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) {
		var pcmt = this.get(msgId);
		return plcb.apply(this, [true, [pcmt.parentNode, pcmt.nextSibling, 0]]);
	}

	// Show the page corresponding to that page index
	this.displayPage(pdx+1, function(immed) {
		// Insert right before the last recorded reply
		var prevReply = this.get(lreplyObj.ID);
		if(finalPlace)
			shiftF.apply(this, [immed, prevReply, idx + 1, plcb]);
		else
			plcb.apply(this, [immed, [prevReply.parentNode, prevReply.nextSibling]]);
	});
}

JSCC.prototype.ShowCommentDialog = function(msgId) {

	this.forMsg = this.objById[msgId||''];

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

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

	this.replyPlacement(msgId, false, function(immediate, apl) {
		if(apl) apl[0].insertBefore(ccd, apl[1]);

		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"];

				/* review specific stuff */
				var hideReviewSpecific = isReply || ! this.withRatings || this.isStandalone();
				var reviewDisp = hideReviewSpecific ? "none" : ''; 
				var city = this.TC["js-CmtCity"];
				if (city) city.style.display = reviewDisp;
				var cityLabel = this.TC["js-commentCity"];
				if (cityLabel) cityLabel.style.display = reviewDisp;

				var commentLabel = this.TC["js-commentLabel"];
				var commentLabelReply = this.TC["js-commentLabelReply"];
				var commentSubject = this.TC["js-commentSubject"];
				var commentSubjectReply = this.TC["js-commentSubjectReply"];
				if (hideReviewSpecific) {
					commentLabel.style.display = 'none';
					commentLabelReply.style.display = '';
					commentSubject.style.display = 'none';
					commentSubjectReply.style.display = '';
				} else {
					commentLabel.style.display = '';
					commentLabelReply.style.display = 'none';
					commentSubject.style.display = '';
					commentSubjectReply.style.display = 'none';
				}
				var subOrig = this.TC["js-CmtsubmitOrig"];
				var subDepth = this.TC["js-CmtsubmitReply"];
				sub.value = isReply ? subDepth.value : subOrig.value;
	
			/* 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(city && !city.eFilled && this.fieldDfl["City"]) {
                            city.focus();
                            city.value = this.fieldDfl["City"];
                        }

			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(this.JCL("tooShort"));
		return false;
	}
	if(cmtObj.Text.length > 1700) {
		alert(this.JCL("tooLong"));
		return false;
	}
	var prn = this.forMsg;
	if(prn) {
		cmtObj.ParentID = prn.ID;
		cmtObj.path = prn.path;
	}
	this.CommentCancelled();
	/* Attach message */
	this.cmtInPlace(cmtObj, function() {
		this.controls.reveal();
		/* Kick in message submission */
		var puturl = message + '&tid=' + cmtObj.ID
		  + (cmtObj.ParentID ? ('&js-CmtParentID=' + cmtObj.ParentID) : '');
		if(this.config.moderate)
			this.pathOverride = this.forMsg.path;
		return this.server('.put', puturl);
	});
}

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

function JSReplyMSGId(tmpid, msgId) {
	try {
		var cmt = document.getElementById(tmpid);
		var cobj = cmt.cobj;
		var self = $JCA[cobj.jcaIndex];
		delete self.cmtById[cmt.id];
		delete cobj.isEmbryonic;
		cobj.ID = msgId;
		cmt.id = msgId;
		self.cmtById[msgId] = cmt;
		self.objById[msgId] = cobj;
		var aux = arguments.length > 2 ? arguments[2] : {};
		if(aux.status == 'H')
			cobj.status = aux.status;
		if(aux.hasOwnProperty('Text')) {
			cmt.ctls['js-singleCommentText'].innerHTML = aux.Text;
			cobj.Text = aux.Text;
		}
		cmt.domCtls.style.visibility = "";
	} 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(so, items_ho) {
	var srv = so.pages;
	var cpp = this.preq.ps;
	var hitems = items_ho[0];
	var oitems = items_ho[1];
	var replace = (this.ctag != so.tag);
	this.curPage = 0;

	var f = function() {
		var div = this.div;
		if(div) {
			this.div = null;
			if(div.parentNode) div.parentNode.removeChild(div);
		}
	}

	if(this.pages) {
		if(replace) {
			for(var i = this.pages.length; i; i--) {
				var p = this.pages[i-1];
				p.rmdiv();
			}
			this.pages = [];
		}
	} else {
		this.pages = [];
		replace = true;
	}
	this.pages.empty = function(sv) {
		return {ss:(sv?true:false),harr:[],oarr:[],items:0,div:null,rmdiv:f}};

	if(replace) {
		for(var i = srv.sp; i > 1; i--)
			this.pages.push(this.pages.empty(true));
	}
	var i = srv.sp - 1;
	for(var start = 0; start < hitems.length; start += cpp, i++) {
		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, rmdiv: f };
		if(replace) {
			this.pages.push(page);
		} else {
			var p = this.pages[i];
			p.rmdiv();
			p.harr = page.harr;
			p.oarr = page.oarr;
			p.items = page.items;
			p.ss = false;
		}
	}
	var togo = srv.tp - (srv.sp + srv.pn - 1);
	if(replace) {
		for(var i = togo; i > 0; i--)
			this.pages.push(this.pages.empty(true));
	}
	if(this.pages.length == 0)
		this.pages.push(this.pages.empty());
}

JSCC.prototype.htmlPaginate = function(thread) {
	this.icount = 0;	/* Page item count */
	return this.htmlPaginator(thread, [], []);
}

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

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.pages.length)
		pageNo = this.pages.length;

	var immediate = true;

	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.ss) page.rmdiv();
		if(page.div) {
			page.div.style.display = '';
		} else {
			var oc = this.TC["js-OldComments"];
			page.div = this.cr('div');
			if(page.ss) {
				page.div.innerHTML = this.JCL("Loading...");
				immediate = false;
				this.dataLoader = function() {
					this.curPage = 0;
					this.displayPage(pageNo);
					if(cb) cb.apply(this, [immediate]);
				}
				if(this.preq.pn < 10)
					this.preq.pn += 5;
				this.getpages(pageNo - Math.ceil(this.preq.pn / 2));
			} else {
				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' : '');
	}
	if(immediate && cb) cb.apply(this, [immediate]);
}

JSCC.prototype.pageNavigator = function(pages, cur) {
	var self = this;
	var arr = [self.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;', self.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;', 'Page-' + 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;', 'Page-' + 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;', self.JCL('Next page'),
		pages == cur ? this.setOpacity(null, 0.3) : ''));
	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"
	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.style.zIndex = 400;
		div.innerHTML = html;
	} else {
		div.style.width = '20em';
		div.appendChild(html);
	}
	var pgr = this.cr('div');
	pgr.className = "js-Progress";
	pgr.style.backgroundImage = 'url('+this.uriDomain+'/images/progress-wg.png)';
	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;
	atDiv.appendChild(div);
	nohide();
}

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

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

	var cc = s.html(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 = s.JCL('email is ' + (so.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 labelHTML = s.labelHTML || s.JCL('leaveComment');

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

	var jmg = d('js-commentControl js-commentTool', s.html('<font face="Webdings">&#64;&nbsp;</font>'), s.a(s.JCL("Controls")));
	jmg.onclick = function() {
		var srt = ["date", "name"];
		if(!s.config.moderate) 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":"")+'>'
				+s.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":"")+'>'
				+s.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":"")+'>'
				+s.JCL(prs[i])+'</option>');
		}
		s.settingsWindow('ctWnd', this,
			"<table border=0 cellpadding=4>"
			+ "<tr><td align=right>" + s.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>" + s.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>" + s.JCL("Threading") + '</td><td align=left><select name="jss-prs" onchange="$JCA['+s.jcaIndex+'].viewControl(this);return true;">'
			+ prsOpts.join("")
			+ "</select></td></tr>"
			+ (so.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 comments</a></td></tr>'):'')
			+ "</table>"
		);
		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 = s.html('<a href="http://js-kit.com/comments?wow">Powered by JS-Kit</a>');
		var prop = d('', "(", propLink, ")");
		prop.style.position = 'relative';
		var pb = d("js-commentControl js-poweredBy", prop);
	}

	var ca = d("js-CommentsArea",
		d("js-LeaveComment", s.config.moderate?null:lca, jmg, pb,
			s.html('<br clear="all"/>')),
		tc["js-CreateComment"]);
	s.addChild(ca, d(null, d('js-PageNavTop'), d("js-OldComments"), d('js-PageNavBottom')), !s.backwards);
	s.displayPage(so.pages.sp);
	ca.onclick = function() {
		s.hideSettingsWindow('ctWnd');
		s.hideSettingsWindow('ctBlock');
	}
	s.addChild(s.target, ca);
}


/* Must be last to support Opera */
JSCC.prototype.newData = function(arr, so) {
	var s = this;
	s.serverOptions = so;
	s.adminMode = !!so.adminMode;
	s.nwb = !!so.nwb;

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

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

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

	var flat = s.preq.thr != 'yes';

	var ttt = []; // top level thread
	var nc = 0;
	for(var i = 0; i < arr.length; i++) {
		var obj = arr[i];
		if(!obj.ID || !obj.Text) continue;
		if(flat) {
			delete(obj.ParentID);
			delete(obj.depth);
		}
		s.objById[obj.ID] = obj;
		obj.thread = [];
		obj.karma = new JSCCKarma(obj.votes, obj, this);
		if(obj.status != 'D') nc++;
		var cmtHTML = s.createCommentAsHTML(obj);
		var prn = s.objById[obj.ParentID];
		if(prn) {
			prn.thread.push([obj, cmtHTML]);
		} else {
			ttt.push([obj, cmtHTML]);
		}
	}
	s.divPages(so, s.htmlPaginate(ttt));

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


if(!window.$JRTA) {
  var $JRTA = [];
  var $JRTLT = { 
    vote: 'vote',
    votes: 'votes',
    msgNoHotItems: 'There are currently no Hot items on this site.',
    msgNoUserItems: 'Rating this will add it to your profile.',
    msgNoTopItems: 'There are currently no Top Rated items on this site.',
    adminMsgPermalinkHelp: 'This new "My" tab will allow your users to build their own personal list of their favorite content on your site.<br><br>All you need to do is to implement permalinks and titles on your rateable content.<br><br>For instructions, see item #8 on <a href="http://js-kit.com/ratings/custom.html">this page</a>, or feel free to contact <a href="mailto:support@js-kit.com">support@js-kit.com</a> for assistance.',
    adminMsgNoRatings: 'There are currently no items in your Top Rated view.  Listings will be displayed when enough votes have been collected.',
    adminMsgNoRatingsNoHot: 'There are currently no items in your Hot view.  Listings will be displayed when enough data has been collected.',
    adminMsgAlert: 'Testing',
    hotInProgress: 'JS-Kit is measuring raters\' activity to present the most popular items here. Please allow some time for meaningful data to be collected.'
  };
  var $JRTL = window.JSRTC_Translate || function(t) { return $JRTLT[t] || t; }
}

/* Constants */

JSRTC.DOMAIN = (window.location.protocol.substr(0, 4) != 'http' ? 'http:' : '')
              + '//js-kit.com';
JSRTC.IMG_DIR = JSRTC.DOMAIN + '/images/top';
JSRTC.SKIN_DIR = JSRTC.IMG_DIR + '/skins';

/* CSS Base Style */
// Note: This differs from JSRC.CSS in that the keys here are complete
JSRTC.CSS = {

	// User Generic
	'.js-rTopFont': 'font-family: Arial, Helvetica, sans-serif; font-size: 10pt;',
	'.js-rTopTitleFont': 'font-weight: bold;',
	'.js-rTopTabFont': 'font-weight: bold;',
	'.js-rTopDetailFont': 'font-family: Arial, Helvetica, sans-serif; font-size: 8pt;',
	'.js-rTopRowColor1': '', 
	'.js-rTopRowColor2': '',

	// General 
	'div.js-rTop': 'margin: 0; padding: 0;', 

	'div.js-rTopBg': 'width: 100%;', // width needed for ie redraw
	'div.js-rTopView': 'border-left: 1px solid #e0e0e0; border-right: 1px solid #e0e0e0; margin: 0; padding: 0 0 1px 0; zoom: 1;',
	'div.js-rTopBody': 'margin: 0;',
	'div.js-rTopTop': 'margin: 0;',
	'div.js-rTopHot': 'margin: 0;',
	'.js-nsgecko': '-moz-user-select: none;',

	// Tab Navigation
	'div.js-rTopNav': 'margin: 0;',
	'div.js-rTopNavTabWrap': 'float: left;',
	'div.js-rTopNavTab': 'height: 1.6em; padding-top: 0.4em; text-align: center; cursor: pointer; margin-top: 1px; border-left: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0;',
	'div.js-rTopNavTabActive': 'border-bottom: none; cursor: default;',
	'div.js-rTopNavTabLeft': 'border-left: none;',
	'div.js-rTopNavTabRight': 'border-right: none;',

	// Top Rated
	'div.js-rTopItems': 'margin: 0; text-align: left;',
	'div.js-rTopItem': 'padding: 0.3em 0.6em 0 0.6em; overflow: auto;',
	'span.js-rTopItemCounter': 'margin-right: .3em;',
	'div.js-rTopItemInfo': 'margin-top: 0.3em;',
	'a.js-rTopItemLink': 'zoom: 1;',
	'div.js-rTopItemStars': 'float: left;',
	'span.js-rTopItemRating': 'margin: 0; white-space: nowrap',

	// Hot
	'div.js-rTopHotItems': 'margin: 0; text-align: left;',
	'div.js-rTopHotItem': 'padding: 0.3em 0.6em 0 0.6em;',
	'span.js-rTopHotItemInfo': 'margin: 0.3em .4em .3em 0;',
	'a.js-rTopHotItemLink': 'zoom: 1;',

	// Top Rated
	'div.js-rTopUserItems': 'margin: 0; text-align: left;',
	'div.js-rTopUserItem': 'padding: 0.3em 0.6em 0 0.6em; overflow: auto;',
	'div.js-rTopUserItemInfo': 'margin: 0.3em 0;',
	'a.js-rTopUserItemLink': 'zoom: 1;',
	'div.js-rTopUserItemStars': 'float: left;',

	// Footer
	'div.js-rTopFooter': 'padding: 0; border: 1px solid #e0e0e0; border-top: none; xheight: 16px; margin: 0; overflow: hidden; position: relative; zoom: 1;',
	'div.js-rTopPoweredBy': 'text-align:right; cursor: pointer; font-size:8pt; padding-bottom: 3px; padding-right:5px;',
	'div.js-rTopPoweredByLink': 'font-family: Arial; text-decoration: none;',
	'div.js-rTopBodyMsg': 'padding: 0.7em 0.5em 0.3em 0.5em;',
	'div.js-rTopBodyAdminMsg': 'padding: 0.7em 0.5em;',
	'div.js-rTopBodyAdminMsgHeader': 'padding-bottom: 0.3em;',
	'div.js-rTopBodyAdminMsgBody': ''  

}

JSRTC.writeCSS = function() {
	var css = '';
	for (prop in JSRTC.CSS) {
		css += prop + ' {' + JSRTC.CSS[prop] + '}';
	}
	JSKitLib.addCss(css, 'jsrtc');
}

JSRTC.writeCSS();

/* Object and Methods */

// TODO: how do we want to handle skins, etc?
JSRTC.writeSkinCSS = function() {

	var titleFont = '';
	var tabFont = '';
	var navTab = '';
	var detailFont = '';
	var msgBody = '';

	var skin = 'ice';

	if (skin != 'none') {
		var skinDir = JSRTC.SKIN_DIR + '/' + skin;
		var header = 'background: url(' + skinDir + '/navi-header-bg.gif) -20px top repeat; border: none;';
		var footer = 'background-color: #fff';
		var view = 'background: #ffffff url(' + JSRTC.IMG_DIR + '/navi-tab-front-bg.gif) top repeat-x;';
		var rowColor2 = "background: #f8f8f8;";
		var navTab = "background: url(" + JSRTC.IMG_DIR + "/navi-tab-back-bg.gif) 0 -1px repeat-x;";
		var adminNote = 'color: #009933';
		switch (skin) {
			case 'default':
				titleFont = ' color: #435362';
				tabFont = ' color: #003366';
				detailFont = ' color: #435362';
				msgBody = ' color: #435362';
				break;
			case 'ice':
				titleFont = ' color: #3d6883';
				tabFont = ' color: #003366';
				detailFont = ' color: #3d6883';
				msgBody = ' color: #3d6883';
				break;
			case 'silver':
				titleFont = ' color: #5d5954';
				tabFont = ' color: #003366';
				detailFont = ' color: #5d5954';
				msgBody = ' color: #5d5954';
				break;
			case 'suede':
				titleFont = ' color: #603a13';
				tabFont = ' color: #9a6329';
				detailFont = ' color: #603a13';
				msgBody = ' color: #603a13';
				break;
			default:
				break;
		}
	} else {
		var skinDir = JSRTC.SKIN_DIR + '/none';
		var poweredBy = 'background: url(' + skinDir + '/navi-footer-buttons.gif) -20px -32px no-repeat;';
	}

	JSKitLib.addCss(''
		+ "div.js-rTopHeader {" + header + "}"
		+ ".js-rTopTitleFont {" + titleFont + "}"
		+ "div.js-rTopView {" + view + "}"
		+ ".js-rTopTabFont {" + tabFont + "}"
		+ "div.js-rTopNavTab {" + navTab + "}"
		+ ".js-rTopDetailFont {" + detailFont + "}"
		+ "div.js-rTopFooter {" + footer + "}"
		+ "div.js-rTopPoweredByLink {" + tabFont + "}"
		+ ".js-rTopRowColor2 {" + rowColor2 + "}"
		+ "div.js-rTopBodyMsgBody {" + msgBody + "}"
		+ "div.js-rTopBodyAdminMsgBody {" + msgBody + "}"
		+ "div.js-rTopNavTabActive { background: none; }"
		+ "a.js-rTopItemLink {" + tabFont + "}"
		+ "a.js-rTopHotItemLink {" + tabFont + "}"
		+ "a.js-rTopUserItemLink {" + tabFont + "}"
		+ "div.js-rTopBodyAdminMsgHeader {" + adminNote + "}"
	, 'top');
}

JSRTC.writeSkinCSS();


/* Class JSRTC */
function JSRTC(target, options, parentObj) {
	this.jtaIndex = $JRTA.length;
	$JRTA.push(this);
	this.cr = function(tag) { return document.createElement(tag); }
	var wl = window.location;

	this.parentObj = parentObj;
	this.target = target;


	// Tab/Body data
	this.views = [];

	this.part = {}; // TR, HH, HD, HW parent object

	this.starWidth = 9;
	this.starHeight = 9;

	var self = this;

	/* Config */
	this.config = {};
	this.config.inline = {};
	this.config.server = {}; // config from server, or recently saved
	this.config.get = function(key) { return self.config.inline[key] || self.config.server[key] }; 
	this.config.getInline = function(key) { return self.config.inline[key] }; 
	this.config.getServer = function(key) { return self.config.server[key] }; 

	// TODO: change over to standard config function
	var iConfig = {};
	iConfig.skin = options["skin"] || 'default';
	iConfig.target = options["target"] || '';
	iConfig.category = options["category"] || '';
	if (options["count"]) 
		iConfig.count = options["count"];

	this.config.inline = iConfig;

	this.domain = target.getAttribute("site") || wl.host;
	this.domain = this.domain.replace(/^[a-z]+:\/\//, '');
	this.domain = wl.protocol + "//" + this.domain;

	this.server = function(smod, 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;
		}
		
		var categ =  self.config.get('category') ? "&category=" + self.config.get('category') : "";
		sc.src = JSRTC.DOMAIN + '/' + smod + ext
			+ "?ref="
			+ encodeURIComponent(domain + "/")
			+ "&" + data
			+ categ
		self.target.appendChild(sc);
		return false;
	}
	this.serverPut = function(ext, data) { return self.server("navapi.cgi/", ext, data); }

	var maxAdSize = function(prepend) {
	  var styleVar = function(name) {
		var cs = self.target.currentStyle
		|| document.defaultView.getComputedStyle(self.target, null);
		var v = cs[name] || self.target.style[name] || 0;
		var a = String(v).match(/^([0-9]+)px/);
		return a ? a[1] : 0;
	  }
	  var ww = styleVar('width');    
	  var w = self.target.offsetWidth;
	  var h = 0;
	  return prepend + w + "x" + h;
	}

	self.server("bestof", "-data.js","app=mininav&jx="+self.jtaIndex+"&count="+self.config.get('count'));

}

// TODO: templates should all be dynamic
JSRTC.prototype.getMainTemplate = function() {

  var html  
   = '<div style = "word-wrap:break-word">'

    + '<div class="js-rTop">' 
     + '<div class="js-rTopBg">' 
      + '<div class="js-rTopHeader">' 
      + '</div>'

      // View is instance of a Tab/Body 
      + '<div class="js-rTopView">'
       + '<div class="js-rTopNav js-rTopTabFont"></div>'  // Tab Navigation
       + '<div class="js-rTopBody"></div>' // Body 
      + '</div>'
  
      // Top Footer
      + '<div class="js-rTopFooter">'
       + '<div class="js-rTopPoweredBy"><a class="js-rTopPoweredByLink" target="_blank" href="http://js-kit.com/?wow_mn">Powered by JS-Kit</a></div>'
       + '<div style="clear:both;"></div>'
      + '</div>'
  
     + '</div>'  // js-rTopBg
    + '</div>'  // js-rTop

   + '</div>'
  ;

	return html;
} 

JSRTC.prototype.dtBodyAdminMsg
 = '<div class="js-rTopBodyAdminMsg">'
  + '<div class="js-rTopBodyAdminMsgHeader">'
   + '<span style="font-size:12pt; font-weight: bold;">Hello admin:</span>'
  + '</div>'
  + '<div class="js-rTopBodyAdminMsgBody js-rTopFont"></div>'
 + '</div>'
;

JSRTC.prototype.dtBodyMsg
 = '<div class="js-rTopBodyMsg">'
  + '<div class="js-rTopBodyMsgBody js-rTopFont"></div>'
 + '</div>'
;
 
JSRTC.prototype.dtBodyTop 
 = '<div class="js-rTopTop">'
  + '<div class="js-rTopDetailFont" style="color: black; background-color:#ffa; margin: .5em .8em 0 .8em; padding: 2px 5px; text-align:center;">Sitewide top rated objects</div>'
  + '<div class="js-rTopItems">'
   + '<div class="js-rTopItem">'
    + '<a class="js-rTopItemLink js-rTopFont" href="{url}">{title}</a>'
    + '<div class="js-rTopItemInfo">'
     + '<div class="js-rTopItemStars"></div>'
     + '<div style="float: left;"><span class="js-rTopItemRating js-rTopDetailFont">{rating}&nbsp;({votes})</span></div>'
     + '<div style="clear: left;"></div>'
    + '</div>'
   + '</div>'
  + '</div>'
 + '</div>'
;

JSRTC.prototype.dtBodyHot
 = '<div class="js-rTopHot">'
  + '<div class="js-rTopDetailFont" style="color: black; background-color:#ffa; margin: .5em .8em 0 .8em; padding: 2px 5px; text-align:center;">Sitewide hot objects</div>'
   + '<div class="js-rTopHotItems">'
    + '<div class="js-rTopHotItem">'
     + '<a class="js-rTopHotItemLink js-rTopFont" href="{url}">{title}</a>'
     + '<br><span class="js-rTopHotItemInfo js-rTopDetailFont"> ({votes})</span>'
    + '</div>'
   + '</div>'
  + '</div>'
;

JSRTC.prototype.dtBodyUser
 = '<div class="js-rTopUser">'
  + '<div class="js-rTopDetailFont" style="color: black; background-color:#ffa; margin: .5em .8em 0 .8em; padding: 2px 5px; text-align:center;">My recent top ratings</div>'
  + '<div class="js-rTopUserItems">'
   + '<div class="js-rTopUserItem">'
    + '<a class="js-rTopUserItemLink js-rTopFont" href="{url}">{title}</a>'
    + '<div class="js-rTopUserItemInfo">'
     + '<div class="js-rTopUserItemStars"></div>'
    + '</div>'
   + '</div>'
  + '</div>'
 + '</div>'
;

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

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

JSRTC.prototype.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) {
			self.mapClass2Object(ctl, child);
		}, e.childNodes);
	} catch(e){}
	return ctl;
}

JSRTC.prototype.gtmpl = function(t) {
	var lowercase = function(a, m) { return String(m).toLowerCase(); }
	t = t.replace(/^[^<]*(<.*>)[^>]*$/m, "$1");
	t = t.replace(/(<[\/]?[A-Z]+)/g, lowercase);
	t = t.replace(/{Label:([^}]*)}/g,function(a,m){return $JRTL(m);});
	return t;
}

JSRTC.prototype.tmpl = function(t, obj) {
	var self = this;
	t = self.gtmpl(t);
	var purify = function(text) {
		var text = String(text).replace(/^[ \s]+|[ \s]+$/, '');
		text = text.replace(/([^&<>\s]{12})([^&<>\s]{12})/g, '$1<wbr></wbr>$2');
		text = text.replace(/[ \t\r\n]+/g, ' ');
		return text;
	}
	t = t.replace(/{([A-Za-z0-9]+)}/g,function(a,m){return obj.hasOwnProperty(m)?purify(obj[m]):'{'+m+'}';});
	return t;
}

JSRTC.prototype.getMiniStars = function(rating, scale) {

	rating = Math.round(rating);

	var fullStar = this.config.get('image1url') || JSRTC.DOMAIN + '/images/stars/gold-tiny.png';
	var emptyStar = this.config.get('image2url') || JSRTC.DOMAIN + '/images/stars/gray-tiny.png';

	var stars = JSKitLib.createMiniStarObject(rating, scale, { full: fullStar, empty: emptyStar, width: this.starWidth, height: this.starHeight });

	return stars;
}

/*
 * Extract all info from our config and place in our object
 */
JSRTC.prototype.processConfig = function(config) {

	// Note: Until BestOf is ensured of having permalinks, we will 
	//       base our tab selection on whether or not a particular
	//       rating div has a permalink or not
	var dataTypes = this.getServerDataTypes();

	if (this.parentObj.target.getAttribute('permalink')) {
		if (dataTypes['TR'] || this.isAdmin) {
			this.views = [ 
				{ type:"UR", title:"My", active: true },
				{ type:"TR", title:"Top", active: true },
				{ type:"HT", title:"Hot", active: true },
				{ type:"RI", title:"Info", active: true }
			];
		} else {
			this.views = [ 
				{ type:"UR", title:"My", active: true },
				{ type:"RI", title:"Info", active: true }
			];
		}
	} else if (dataTypes['UR'] || this.isAdmin) {
		this.views = [ 
			{ type:"UR", title:"My", active: true },
			{ type:"RI", title:"Info", active: true }
		];
	} else {
		this.views = [ 
			{ type:"RI", title:"Info", active: true },
		];
	}

}

// Returns a hash of server provided data types
JSRTC.prototype.getServerDataTypes = function() {

	var data = this.serverData[0].data;
	var dataTypes = {};
	for (var i=0; i < data.length; i++) {
		dataTypes[data[i].type] = true;
	}

	return dataTypes;
}

JSRTC.prototype.toggleViews = function(id) {
	// Iterate through hide/unactivate as necessary
	var views = this.getActiveViews();
	if (!views.length) return;

	for (var i=0; i < views.length; i++) {
		if (i != id) {
			JSKitLib.removeClass(views[i].tab, "js-rTopNavTabActive");
			JSKitLib.hide(views[i].content);
		}
	}
	// Now display the proper view
	JSKitLib.addClass(views[id].tab, "js-rTopNavTabActive");
	JSKitLib.show(views[id].content);
}

JSRTC.prototype.table = function(tr) {
  var self = this;
  var a = function(n, w) {var o=self.cr(n);o.appendChild(w);return o;}
  var t = a('table', a('tbody', tr));
  var z = function(a) {t.setAttribute(a, '0')}
  z('cellSpacing');
  z('cellPadding');
  z('border');
  return t;
}

JSRTC.prototype.getViews = function() {
	return this.views;
}

JSRTC.prototype.getActiveViews = function() {
	var views = this.views;
	var aViews = [];
	for (var i=0; i < views.length; i++) {
		if (typeof views[i] == 'object' && views[i].active) {
			aViews.push(views[i]);
		}
	}
	return aViews;
}

JSRTC.prototype.isViewActive = function(type) {
	var views = this.getActiveViews();    
	for (var i=0; i < views.length; i++) {
		if (typeof views[i] == 'object' && (views[i].type == type) && views[i].active) {
			return true;
		}
	}
	return false;
}

JSRTC.prototype.createTabs = function() {
	var self = this;
	var views = this.getActiveViews();

	var numTabs = views.length;

	// TODO: Show no tab if only one

	// Calculate the width of each tab
	var width = Math.floor(100/numTabs);
	var adjWidth = (numTabs * width != 100) ? (100 - ((numTabs - 1) * width)) : width;


    var tr = this.cr('tr');

	for (var i=0; i < views.length; i++) {
		var td = this.cr('td');
		td.setAttribute('width', width + '%');

		var tabWrap = this.cr('div');
		tabWrap.className = "js-rTopNavTabWrap";
		tabWrap.style.width = '100%';

		var tabMain = this.cr('div');
		tabMain.className = "js-rTopNavTab";
		JSKitLib.preventSelect(tabMain); // preventSelect for tabs titles

		// Left, Right
		if (i==0) { 
			td.setAttribute('width', adjWidth + '%');
			JSKitLib.addClass(tabMain, "js-rTopNavTabLeft");
			JSKitLib.addClass(tabMain, "js-rTopNavTabActive"); 
		} else {
			if (i == (views.length - 1)) {
				JSKitLib.addClass(tabMain, "js-rTopNavTabRight");
			}
		}

		var divTitle = document.createElement("div");
		divTitle.style.display = "inline";
		divTitle.innerHTML = views[i].title;

		(function(i) {
			tabMain.onclick = function() { 
				self.toggleViews(i); 
				self.positionAffiliate();
			};
		})(i);
    
		tabMain.appendChild(divTitle);
		tabWrap.appendChild(tabMain);

		views[i].tab = tabMain; // Obj ref to tab node

		td.appendChild(tabWrap);
		tr.appendChild(td);
	}

	var table = this.table(tr);
	table.setAttribute('width', '100%');
    
	return table;

}

JSRTC.prototype.createBody = function(navData) {

	var self = this;
	var views = this.getActiveViews();
	var contentDiv = this.cr('div');

	for (var i=0; i < views.length; i++) {
		switch (views[i].type) {
			/* Rating Info */
			case "RI":
				var content = this.parentObj.createInfoBox();
				break;
			/* User Ratings */
			case "UR":
				var content = this.createBodyUser(navData);
				break;
			case "AA":
				var content = this.createBodyAdminMsg($JRTL('adminMsgAlert'));
				break;
			case "TR":
				var content = this.createBodyTop(navData);
				JSKitLib.preventSelect(content);
				break;
			case "HT":
				var content = this.createBodyHot(navData);
				JSKitLib.preventSelect(content);
				break;
			case "EP" :
				/* Not handling EP */            
				break;
			case "PL" :
				var content = this.cr("div");
				content.className = "js-kit-poll";

		}
		if (typeof content == 'object') {
			views[i].content = content;
			contentDiv.appendChild(content);
		}
	}

	return contentDiv;
}

JSRTC.prototype.createBodyTop = function(navData) {

	var self = this;

	var body = this.html(this.dtBodyTop);
	var ctls = this.mapClass2Object({}, body);

	/* Top TR */
	var tip = ctls['js-rTopItems'];
	var tTemplate = tip.innerHTML;
	tip.innerHTML = '';

	var topItem = function(items, idx) {
		var item = items[idx];
		var idiv = self.html(self.tmpl(tTemplate, item));
		if (idx % 2 != 0) JSKitLib.addClass(idiv, "js-rTopRowColor2");
		var ictls = self.mapClass2Object({}, idiv);
		var link = ictls['js-rTopItemLink'];
		if (item.url.match(/^[a-z]+:\/\//)) {
			link.href = item.url;
		} else {
			link.href = self.domain + item.url;
		}
		if (self.config.get('target')) {
			link.target = self.config.get('target');
		}    
		var stars = ictls['js-rTopItemStars'];
		stars.appendChild(item.stars);
		return idiv;
	}

	if (navData.part.TR.items.length) {    
		JSKitLib.map(function(item, i, items) {
			self.addChild(tip, topItem(items, i));
		}, navData.part.TR.items);
	} else {
		if (this.isAdmin) {        
			tip.appendChild(this.createBodyAdminMsg($JRTL('adminMsgNoRatings')));
		} else {
			tip.appendChild(this.createBodyMsg($JRTL('msgNoTopItems')));
		}
	}

	return body;

}

JSRTC.prototype.createBodyUser = function(navData) {

	var self = this;

	var body = this.html(this.dtBodyUser);
	var ctls = this.mapClass2Object({}, body);

	/* Top UR */
	var tip = ctls['js-rTopUserItems'];
	var tTemplate = tip.innerHTML;
	tip.innerHTML = '';

	var userItem = function(items, idx) {
		var item = items[idx];
		var idiv = self.html(self.tmpl(tTemplate, item));
		if (idx % 2 != 0) JSKitLib.addClass(idiv, "js-rTopRowColor2");
		var ictls = self.mapClass2Object({}, idiv);
		var link = ictls['js-rTopUserItemLink'];
		if (item.url.match(/^[a-z]+:\/\//)) {
			link.href = item.url;
		} else {
			link.href = self.domain + item.url;
		}
		if (self.config.get('target')) {
			link.target = self.config.get('target');
		}    
		var stars = ictls['js-rTopUserItemStars'];
		stars.appendChild(item.stars);
		return idiv;
	}

	if (navData.part.UR.items.length) {    
		JSKitLib.map(function(item, i, items) {
			self.addChild(tip, userItem(items, i));
		}, navData.part.UR.items);
	} else {
		if (this.isAdmin) {        
			if (this.parentObj.target.getAttribute('permalink')) {
				tip.appendChild(this.createBodyMsg($JRTL('msgNoUserItems')));
			} else {
				tip.appendChild(this.createBodyAdminMsg($JRTL('adminMsgPermalinkHelp')));
			}
		} else {
			tip.appendChild(this.createBodyMsg($JRTL('msgNoUserItems')));
		}
	}

	return body;

}


JSRTC.prototype.createBodyAdminMsg = function(msg) {
	var body = this.html(this.dtBodyAdminMsg);
	var ctls = this.mapClass2Object({}, body);

	var msgBody = ctls["js-rTopBodyAdminMsgBody"];

	msgBody.innerHTML = msg; 

	return body;
}

JSRTC.prototype.createBodyMsg = function(msg) {
	var body = this.html(this.dtBodyMsg);
	var ctls = this.mapClass2Object({}, body);

	var msgBody = ctls["js-rTopBodyMsgBody"];

	msgBody.innerHTML = msg; 

	return body;
}

JSRTC.prototype.createBodyHot = function(navData) {

	var self = this;

	var body = this.html(this.dtBodyHot);
	var ctls = this.mapClass2Object({}, body);

	/* Hot */  
	var hotp = ctls['js-rTopHotItems'];
	var hTemplate = hotp.innerHTML;
	hotp.innerHTML = '';

	var hotItem = function(items, idx) {
		var item = items[idx];
		var idiv = self.html(self.tmpl(hTemplate, item));
		if (idx % 2 != 0) JSKitLib.addClass(idiv, "js-rTopRowColor2");
		var ictls = self.mapClass2Object({}, idiv);
		var link = ictls['js-rTopHotItemLink'];
		if (item.url.match(/^[a-z]+:\/\//)) {
			link.href = item.url;
		} else {
			link.href = self.domain + item.url;
		}
		if (self.config.get('target')) {
			link.target = self.config.get('target');
		}    
		return idiv;
	}

	if (navData.part.HT.items.length) {    
		JSKitLib.map(function(item, i, items) {
			self.addChild(hotp, hotItem(items, i));
		}, navData.part.HT.items);
	} else {
		var dataTypes = this.getServerDataTypes();
		if (dataTypes.TR) {
			hotp.appendChild(this.createBodyMsg($JRTL('hotInProgress')));
		} else {
			if (this.isAdmin) {        
				hotp.appendChild(this.createBodyAdminMsg($JRTL('adminMsgNoRatingsNoHot')));
			} else {
				hotp.appendChild(this.createBodyMsg($JRTL('msgNoHotItems')));
			}
		}
	}

	return body;
}

JSRTC.prototype.displayTop = function(navData, opts) {
	var self = this;
	navData.Title = this.config.get('title');
	var template = this.getMainTemplate();        

	var pdiv = this.html(this.tmpl(template, navData));
	var ctls = this.mapClass2Object({}, pdiv);
	this.ctls = ctls;

	/* Navigation Tabs */
	var topNav = ctls['js-rTopNav'];
	topNav.appendChild(this.createTabs());

	/* Main Content */
	var topBody = ctls['js-rTopBody'];
	topBody.appendChild(this.createBody(navData));

	/* Activate the Main View */
	// TODO: handle for single view
	this.toggleViews(0);

	this.target.innerHTML = '';
	this.addChild(this.target, pdiv);

	if (opts.ad) {
		//this.displayAd(opts.ad);
	}
}


JSRTC.prototype.displayAd = function(ad) {
	/* Ads */
	if (typeof ad == 'object' && ad.data) {
		if (ad.flags && ad.flags.match(/a/)) {
			try {
				eval("ad.data = " + ad.data);
				this.doAffiliateAbsolute(ad);
			} catch(e) {};
		} else {
			if (ad.data.match(/<script/i)) {

				var div = this.cr('div');
				div.style.margin = '9px 0';
				var banner = this.cr('div');
				banner.style.margin = '0 auto';
				banner.style.width = ad.width + 'px';

				var iframe = document.createElement('iframe');
				iframe.frameBorder = 0;
				iframe.scrolling = "no";
				iframe.marginWidth = 0;
				iframe.marginHeight = 0;
				iframe.width = ad.width;
				iframe.height = ad.height;
				iframe.src = 'http://js-kit.com/reflector?html=' + encodeURIComponent('<html><body>' + ad.data + '</body></html>');

				div.appendChild(banner);
				banner.appendChild(iframe);
				this.target.appendChild(div);

			} else {    
				var div = this.cr('div');
				div.style.margin = '9px 0';
				var banner = this.cr('div');
				banner.style.margin = '0 auto';
				div.appendChild(banner);
				banner.innerHTML = ad.data;
				this.target.appendChild(div);
			}
		}

	}

}

JSRTC.prototype.getTextForTotalVotes = function(votes) {
  var text;
  switch(parseInt(votes)) {
    case  1: text = votes + ' ' + $JRTL('vote');  break;
    default: text = votes + ' ' + $JRTL('votes'); break;
  }
  return text;
}

JSRTC.prototype.prepHotItems = function(items) {

	if (!items.length) return;

	// Filter proper number of results
	if (this.config.get('count') < items.length)
		items.length = this.config.get('count');

	// Prepare vote counts
	for (var i=0; i < items.length; i++) {
		items[i].votes = this.getTextForTotalVotes(items[i].val2); 
	}    

	return items;
}

JSRTC.prototype.prepTopItems = function(items) {

	if(!items.length) return;

	// Filter proper number of results
	if (this.config.get('count') < items.length)
		items.length = this.config.get('count');

	// Prepare our stars 
	for (var i=0; i < items.length; i++) {
		items[i].stars = this.getMiniStars(items[i].val1, 10);
		items[i].rating = JSKitLib.zeroPad(JSKitLib.round(items[i].val1 / 2, 2), 2);
		items[i].votes = this.getTextForTotalVotes(items[i].val2); 
		items[i].counter = i + 1;
	}    

	return items;
}

JSRTC.prototype.prepUserItems = function(items) {

	if(!items.length) return;

	// Filter proper number of results
	if (this.config.get('count') < items.length)
		items.length = this.config.get('count');

	// Prepare our stars 
	for (var i=0; i < items.length; i++) {
		items[i].stars = this.getMiniStars(items[i].rating, 10);
		items[i].rating = JSKitLib.zeroPad(JSKitLib.round(items[i].rating / 2, 2), 2);
		items[i].counter = i + 1;
	}    

	return items;
}

/*  
 * Affiliate Code
 */

JSRTC.prototype.getAffiliateAbsoluteContainer = function(ad) {

	var ad_width = ad.width;
	var ad_height = ad.height;

	var d1 = this.cr('div');
	var d2 = this.cr('div');

	JSKitLib.setStyle(d1, "margin-top: 9px; cursor: pointer; height:" + ad_height + "px;");
	JSKitLib.setStyle(d2, "width:" + ad_width + "px; margin:0 auto;");

	d1.appendChild(d2);

	return d1;

}

JSRTC.prototype.processAffiliateAbsolute = function(ad) {
	// Only allowing one absolute ad per Top 
	if (this.jtaIndex != 0) return;

	// Create the container for our affiliate
	this.affContainer = this.getAffiliateAbsoluteContainer(ad);
	this.target.appendChild(this.affContainer);

	// IE allows flash to overflow a container, but we need special
	// handling for non IE browsers
	if (JSKitLib.isIE()) {        
		this.affContainer.firstChild.appendChild(ad.data());
	} else {

		this.affDiv = this.cr('div');
		this.affDiv.style.position = 'absolute';

		this.positionAffiliate();
		this.affDiv.style.zIndex = 1000;
		this.affDiv.appendChild(ad.data());
		JSKitLib.getJSKitBodyElement().appendChild(this.affDiv);

		// Handling repositioning of ad
		var self = this;
		JSKitLib.addLoadEvent(function() { self.positionAffiliate(); } );
		JSKitLib.addResizeEvent(function() { self.positionAffiliate(); });

	}
}

JSRTC.prototype.positionAffiliate = function() {
	if ( ! JSKitLib.isIE() && this.affContainer) {        
		var pos = JSKitLib.findPos(this.affContainer.firstChild);
		this.affDiv.style.left = pos[0]  + 'px';
		this.affDiv.style.top = pos[1] + 'px';
	}
}

// Handles absolutely positioned affiliates
JSRTC.prototype.doAffiliateAbsolute = function(ad) {
	// Run once only
	if ( ! this.didAffiliateAbsolute) {
		if (ad) {
			this.processAffiliateAbsolute(ad);
		}
		this.didAffiliateAbsolute = true;
	}
}


/*
 * Navigator Data Processing 
 */

JSRTC.prototype.processDataTop = function(navData) {

	var TR = JSKitLib.filter(
		function(o) { return (o.type === "TR" && o.title.length); },
			navData.data);

	navData.part.TR.items = this.prepTopItems(TR) || [];
}

JSRTC.prototype.processDataUser = function(navData) {

	var UR = JSKitLib.filter(
		function(o) { return (o.type === "UR"); },
			navData.data);

	navData.part.UR.items = this.prepUserItems(UR) || [];
}

JSRTC.prototype.processDataHot = function(navData) {

	// Hot by Hour
	var HH = JSKitLib.filter(
		function(o) { return (o.type === "HH" && o.title.length); },
			navData.data);

	// Hot by Day
	var HD = JSKitLib.filter(
		function(o) { return (o.type === "HD" && o.title.length); },
			navData.data);

	// Hot by Week
	var HW = JSKitLib.filter(
		function(o) { return (o.type === "HW" && o.title.length); },
			navData.data);

	// For Hot, use HD, and if less than 2 results use HW
	navData.part.HT.items = this.prepHotItems(HD) || [];
	if (navData.part.HT.items.length < 2) {
		navData.part.HT.items = this.prepHotItems(HW) || [];
	}

}

JSRTC.prototype.newAd = function(data) {
	this.displayAd(data);
}

// This must be the last function.
JSRTC.prototype.newData = function(data, opts) {
	opts = opts || {};

	this.serverData = [ data, opts ]; // Saving what was returned by server.  
	this.config.server = data.config || {};
	this.serverTime = opts.serverTime;
	this.isAdmin = opts.admin || false;
	this.isNewSite = opts.newSite || false;

	var navData = {};
	navData.data = data.data;

	// Process Config
	this.processConfig(this.config.server);

	navData.part = { 
		TR: {},
		HH: {},
		HD: {},
		HW: {},
		HT: {},  // Composite of HH, HD, HW
		UR: {}
	};

	this.processDataTop(navData);
	this.processDataHot(navData);
	this.processDataUser(navData);

	// Now parse template and attach node
	this.displayTop(navData, opts);

}

JSRTC.prototype.removeChildren = function() {
	while (this.target.hasChildNodes()) {
		this.target.removeChild(this.target.firstChild);
	}
}



