                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
try { if(navigator.appVersion.match(/3\..\.. 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/api/session/refresh.js';
			iDOC.body.appendChild(frm);
			frm.submit();
		}
		ifrsess.onreadystatechange();
	}
	if(document.body) f();
	else setTimeout(f, 0);
} } catch(e) {};
/*
 * Copyright (c) 2007 JS-Kit.com. All rights reserved.
 * $Date: 2008-12-30 03:39:01 -0800 (Tue, 30 Dec 2008) $
 */

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 comment to your rating',
    noVotesReceivedYet: 'No votes received yet',
    beTheFirstToRate: 'Be the first to rate!',
    ratingsDisabled: 'Voting Closed',
    thankYou: 'Thank\u00a0you!',
    thank: 'Thanks',
    scoreThis: 'Score\u00a0this',
    yourScore: 'Your score',
    up: 'up',
    down: 'down'
  };

  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.isFF3 = function() {
	return (navigator.userAgent.indexOf("Firefox/3") != -1);
}

JSKitLib.isGChrome = function() {
	return (navigator.userAgent.toLowerCase().indexOf('chrome') != -1);
}

JSKitLib.isSafari = function() {
	if (navigator.appVersion.match(/Safari/)) {
		return true;
	}
}

JSKitLib.isOpera = function() {
	if (navigator.appName.match(/Opera/)) {
		return true;
	}
}



JSKitLib.addEventHandler = function(obj, eventNames, newHandler, newFirst) {
	JSKitLib.map(function(e) {
		var origEvent = obj[e];
		if(typeof origEvent == "function") {
			obj[e] = function() { 
				if(newFirst) { newHandler(); origEvent(); }
				else { origEvent(); newHandler(); } 
			}
		} else obj[e] = newHandler;
	}, eventNames);
}

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.deferCallIfIE = function(func) {
	if (JSKitLib.isIE() && ! JSKitLib.vars.windowOnLoadFired && ! window.$JSKitNoDeferCallIfIE) {
		JSKitLib.addEventHandler(window, ["onload"], 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.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.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;
}

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()) {
		var cp = $JSKitGlobal.cachedPngs;
		for(var j=0; j<cp.length; j++) {
			k = 0;
			while(k<length(cp[j].nodes)) {
				if(cp[j].nodes[k]==node) {
					cp[j].nodes.splice(k, 1);
				} else {
					k++;
				}
			}
		}
		if(cp[imageURL]) {
			if(cp[imageURL].loaded) {
				node.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageURL + "', sizingMethod='crop')"
			} else {
				cp[imageURL].nodes.push(node);
			}
		} else {
			cp[imageURL] = {nodes:[node]};
			var tPng = document.createElement("IMG");
			tPng.style.display = "none";
			tPng.onload = function() {
				cp[imageURL].loaded = true;
				var n = cp[imageURL].nodes;
				for(var i=0; i<n.length; i++) {
					n[i].runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imageURL + "', sizingMethod='crop')";
				}
				cp[imageURL].nodes = [];
			};
			node.appendChild(tPng);
			tPng.src = imageURL;
		}
	} else {
		node.style.backgroundImage = 'url(' + imageURL + ')';
		node.style.backgroundRepeat = 'no-repeat';        
	}
	return node;
}

JSKitLib.preloadImg = function(imgURL) { 
	if (!JSKitLib.preloadImgList) JSKitLib.preloadImgList = {};
	if (!JSKitLib.preloadImgList[imgURL]) {
		(new Image()).src = imgURL; 
		JSKitLib.preloadImgList[imgURL] = true;
	}
};

JSKitLib.pngBar = function(color, div, fixed) {
	var str;
	var url = "'//js-kit.com/images/bars/bar-" + color + ".png'";
	if(document.body.filters) {
		str = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src="
			+ url + ", sizingMethod='"+(fixed?'crop':'scale')+"')";
		if(div) div.runtimeStyle.filter = str;
		return "filter: " + str + ";";
	} else {
		str = "url(" + url + ")";
		if(div) div.style.backgroundImage = str;
		return "background: " + str + ";";
	}
};

JSKitLib.createMiniStarObject = function(rating, scale, specs) {
	var fullStar = specs.full;
	var emptyStar = specs.empty;
	var starWidth = specs.width;
	var starHeight = specs.height;

	var setImage = function(star, imageURL) {
		if(star.imageURL == imageURL)
			return; // Already set and we know it

		star.imageURL = imageURL;
		JSKitLib.addPNG(star, imageURL);
	}

	var obj = document.createElement('div');
	var objWidth = 0;
	var objHeight = starHeight;

	/* Increment by Full Star Ratings */
	for (var i=2; i <= scale; i += 2) {
		var star = document.createElement('div');

		star.style.cssFloat   = 'left';
		star.style.styleFloat = 'left';
		star.style.width    = starWidth + 'px';
		star.style.height   = starHeight + 'px';
		star.style.fontSize = starHeight + 'px'; // ie6

		objWidth += starHeight;

		if (rating >= i) {
			setImage(star, fullStar);
		} else {
			setImage(star, emptyStar);
		}

		obj.appendChild(star);
	}

	JSKitLib.setStyle(obj, "height: " + objHeight + "px; width: " + objWidth + "px; float: left; margin-right: 5px;");

	return obj;
}

JSKitLib.mkAvatar = function(s, avatar, uriAvatar, onmousemove, onmouseout, onmousedown, outeronmousedown, settext) {
	var outer = s.cr('div');
	JSKitLib.setStyle(outer, "float: left;");
	outer.style.display = "inline-block";
	outer.onselectstart = function() {return false;}
	outer.style.margin = "2px";
	JSKitLib.addClass(outer, "js-hideBorder");
	var WH = {'width': avatar.width,'height': avatar.height,'name':avatar.name};
	outer.style.width = "118px";
	outer.style.align = "center";
	var div = s.cr('div');
	div.style.margin = "2px";
	div.style.width = "114px";
	div.style.height = "114px";
	div.style.backgroundPosition = 'top center';
	var img = s.cr('div');
	img.style.width = WH['width'] + 'px';
	img.style.height = WH['height'] + 'px';
	img.style.left=((114-WH['width'])/2)+'px';
	img.style.position = "relative";
	JSKitLib.addPNG(img, JSKitAvatarsManagement.prototype.avatarURL.call({uriAvatar: uriAvatar}, WH['name']));
	var sub = s.cr('div');
	sub.style.padding = "2px 5px 0px 5px";
	sub.style.fontFamily = "Helvetica, Verdana";
	sub.style.fontSize = "8pt";
	sub.style.height = "14px";
	var sel = s.cr('div'); settext(sel, 'selectedAvatar');
	sel.style.display = 'none';
	sel.style.textAlign = 'center';
	var rem = s.cr('div'); settext(rem, 'removeAvatar');
	rem.style.display = 'none';
	rem.style.textDecoration = 'underline';
	rem.style.textAlign = 'center';
	rem.style.cursor = 'pointer';
	sub.onmouseover = function() {
		return onmousemove(avatar, outer, sel, rem);
	}
	sub.onmouseout = function() {
		return onmouseout(avatar, outer, sel, rem);
	}
	rem.onmousedown = function(e) {
		JSKitLib.stopEventPropagation(e || window.event);
		return onmousedown(avatar, outer, sel, rem);
	}
	sub.appendChild(rem);
	sub.appendChild(sel);
	div.appendChild(img);
	div.appendChild(sub);
	outer.appendChild(div);
	outer.onmousedown = function() {
		return outeronmousedown(avatar, outer, sel, rem);
	}
	if(avatar.chosen) outeronmousedown(avatar, outer, sel, rem, true);
	return outer;
}



JSKitLib.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.removeChildren = function(element) {
	while(element && element.hasChildNodes())
		element.removeChild(element.firstChild);
}

JSKitLib.visible = function(element) {
	return element.style.display != 'none';
}

JSKitLib.show = function(element) {
	element.style.display = '';
}

JSKitLib.hide = function(element) {
	element.style.display = 'none';
}

JSKitLib.toggle = function(element) {
	(element.style.display == 'none') ? JSKitLib.show(element) :  JSKitLib.hide(element);
}

JSKitLib.getStyle = function(element) {
	if (typeof element.style.cssText != "undefined") {
		return element.style.cssText;
	} else {
		return element.getAttribute("style");
	}
}

JSKitLib.setStyle = function(element, style) {
	if (typeof element.style.cssText != "undefined") {
		element.style.cssText = style;
	} else {
		element.setAttribute("style", style);
	}
}

JSKitLib.addStyle = function(element, style) {
	var oldStyle = JSKitLib.getStyle(element);
	JSKitLib.setStyle(element, oldStyle + '; ' + style); // IE needs ;
}

JSKitLib.findPos = function(obj) {
	var origObj = obj;
	var curleft = curtop = curright = curbottom = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		}
	}
	curright = curleft + origObj.offsetWidth;
	curbottom = curtop + origObj.offsetHeight;
	return [curleft,curtop,curright,curbottom];
}

JSKitLib.getJSKitBodyElement = function() {
	var be = document.getElementById('js-kit-body-element');
	if (!be) {
		be = document.createElement('div');
		be.id = "js-kit-body-element";
		document.body.appendChild(be);
	}
	return be;
}

JSKitLib.isChildNodeOf = function(parent, child) {
	if (parent === child) 
		return false
	while (child && child !== parent) {
		child = child.parentNode;
	}
	return child === parent;
}

JSKitLib.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
if ( ! JSKitLib.vars.windowOnLoadFired) JSKitLib.vars.windowOnLoadFired = false;
JSKitLib.addEventHandler(window, ["onload"], function() { JSKitLib.vars.windowOnLoadFired = true; });


JSKitLib.setThumbImage = function(args) {

	if (typeof args != 'object')
		return;

	var element     = args.element;
	var ud          = args.ud;
	var actionable  = args.actionable;
	var imageURL    = args.imageURL;
	var ignoreEmpty = args.ignoreEmpty;
	var numVotes    = args.numVotes; 
	var thumbWidth  = args.thumbWidth;
	var thumbHeight = args.thumbHeight;

	if(element.imageURL != imageURL){
		element.imageURL = imageURL
		JSKitLib.addPNG(element, imageURL);
	}

	var offsetTop=0;
	var offsetLeft=0;
	if(ud == 'down') offsetLeft=-thumbWidth;
	if((!actionable)||(!numVotes && !ignoreEmpty)) offsetTop=-thumbHeight;
	if(JSKitLib.isIE() && !JSKitLib.isPreIE7()){
		element.parentNode.parentNode.style.left=offsetLeft+'px';
		element.parentNode.parentNode.style.top=offsetTop+'px';
	} else {
		element.parentNode.style.left=offsetLeft+'px';
		element.parentNode.style.top=offsetTop+'px';
	}
}

// Returns an single div with a specified thumb image
JSKitLib.createThumbImage = function(args) {

	if (typeof args != 'object')
		return;

	var ud = args.ud;
	var actionable = args.actionable;
	var imageURL = args.imageURL;
	var ignoreEmpty = args.ignoreEmpty;
	var numVotes = args.numVotes;
	var thumbWidth = args.thumbWidth;
	var thumbHeight = args.thumbHeight;

	var div1 = document.createElement('div');
	var div2 = document.createElement('div');
	var div3 = document.createElement('div');

	div3.style.position = 'relative';
	div3.style.width = thumbWidth + 'px';
	div3.style.height = thumbHeight + 'px';
	div3.style.overflow = 'hidden';

	div2.style.position = 'absolute';
	div2.style.width = thumbWidth + 'px';
	div2.style.height = thumbHeight + 'px';

	// div1 is full size of all thumb images, and uses offset and 
	// overflow of its parents to show specific thumb image
	div1.style.width = (thumbWidth * 2) + 'px';
	div1.style.height = (thumbHeight * 2) + 'px';

	if(JSKitLib.isIE() && !JSKitLib.isPreIE7()){
		var divtmp = document.createElement('div');
		divtmp.style.width = (thumbWidth * 2) + 'px';
		divtmp.style.height = (thumbHeight * 2) + 'px';
		div3.appendChild(div2);
		div2.appendChild(divtmp);
		divtmp.appendChild(div1);
	} else {
		div2.appendChild(div1);
	}

	div3.appendChild(div2);

	JSKitLib.setThumbImage( { element: div1, ud: ud, actionable: actionable, imageURL: imageURL, ignoreEmpty: ignoreEmpty, numVotes: numVotes, thumbWidth: thumbWidth, thumbHeight: thumbHeight } );

	return div3;

}



var JSKitGlobal = function() {

	this._appAvailable = {};
	this._appObjects = {};  // Specific objects of an application type 
	this._appObjectActions = {}; // app.object.actions
	
	this.cachedPngs = {};

	this._isAppAvailable = function(app) {
		return (this._appAvailable[app]) ? true : false;
	}

	this.isRatingsAppAvailable = function() {
		return this._isAppAvailable('ratings');
	}

	this.isCommentsAppAvailable = function() {
		return this._isAppAvailable('comments');
	}

	this._setAppAvailable = function(app) {
		this._appAvailable[app] = true;
		/* index this app */
		this.indexAppObjects(app);
		/* execute any queued actions */
		this.executeAppObjectActions(app);
	}

	this.setRatingsAppAvailable = function() {
		this._setAppAvailable('ratings');
	}

	this.setCommentsAppAvailable = function() {
		this._setAppAvailable('comments');
	}

	this.indexAppObjects = function(app) {
		if (app == 'ratings') {
			var appArray = $JRA;
		} else if (app == 'comments') {
			var appArray = $JCA;
		} else {
			alert('Attempt to index invalid app type');
			return;
		}
		for (var i=0; i < appArray.length; i++) {
			// Check that it's not standalone
			if (appArray[i].isStandalone()) {
				continue;
			}
			var uniq = appArray[i].uniq;
			if ( ! this._appObjects[uniq] ) {
				this._appObjects[uniq] = {};
			}
			if ( ! this._appObjects[uniq][app]) {
				this._appObjects[uniq][app] = [];
			}
			this._appObjects[uniq][app].push(appArray[i]);
		}
	}

	this.executeAppObjectActions = function(app) {
		if (this._appObjectActions[app]) {
			for (var i=0; i < this._appObjectActions[app].length; i++) {
				var uniq = this._appObjectActions[app][i].uniq;
				if (this._getAppObject(app, uniq)) {
					this._appObjectActions[app][i].action();
				}
			}
		}
	}

	this._getAppObject = function(app, uniq) {
		if (this._appObjects[uniq] && this._appObjects[uniq][app]) {
			return this._appObjects[uniq][app][0];  // Return only the first
		}
		return null;
	}

	this.getCommentsAppObject = function(uniq) {
		return this._getAppObject('comments', uniq);
	}

	/* Returns a Ratings Object */
	this.getRatingsAppObject = function(uniq) {
		return this._getAppObject('ratings', uniq);
	}

	this.copyRatingsAppObject = function(uniq, node) {
		if ( ! this.isRatingsAppAvailable()) {
			return;
		}
		var oldObj = this.getRatingsAppObject(uniq);
		var newObj = oldObj.clone(node, { 'view':'user', 'commentprompt':'no', 'menu':'no'  } );
		return newObj;
	}

	this._tryAppObjectAction = function(app, uniq, action) {
		if (this._isAppAvailable(app)) {
			if (this._getAppObject(app, uniq)) {
				action();
			}
		} else {
			if ( ! this._appObjectActions[app]) {
				this._appObjectActions[app] = [];
			}
			this._appObjectActions[app].push( { 'uniq' : uniq, 'action' : action } );
		}
	}

	this.tryRatingsAppObjectAction = function(uniq, action) {
		this._tryAppObjectAction('ratings', uniq, action);
	}

	this.tryCommentsAppObjectAction = function(uniq, action) {
		this._tryAppObjectAction('comments', uniq, action);
	}
}

/* Singleton-like handler */
JSKitGlobal.getInstance = function() {
	if ( ! window.JSKitGlobalInstance) {
		JSKitGlobalInstance = new JSKitGlobal();
	}
	return JSKitGlobalInstance;
}



/* JSKitGlobal  object */
$JSKitGlobal = JSKitGlobal.getInstance();



JSKitLib.getPermalink = function(target) {
	return target.getAttribute('permalink') || window.location.href;
}

JSKitLib.getTitle = function(target) {
	return target.getAttribute('title') || document.title;
}

JSKitLib.getRef = function(self, ignorePath) {
	var wl = window.location;
	return wl.protocol + '//'
		+ (self.pathOverride
			? (self.config.domain.replace(/\/.*/, '')
				+ (ignorePath ? '' : self.pathOverride))
			: (self.config.domain + wl.pathname));
}

JSKitLib.getPath = function(self) {
	return self.path;
}

JSKitLib.getConfig = function(target, getValue, cf) {
	for(var i = 3; i < arguments.length; i++) {
		var arg = arguments[i];
		if(typeof(arg) == 'string') arg = [arg];
		var name = arg[0];
		var value = getValue.call(this, name, 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;
}


/* Class Functions */

// Initialize instances of JSRC objects
JSRC.init = function() {

    /* Iterate and find all rating divs */
	// js-kit-rating and js-kit-ratings qualify
	var els = JSKitLib.filter(function(el) {
		return (el.className.match(/^js-kit-rating/)); }, document.getElementsByTagName('div'));

	if (!els.length) return;

	var multiQ = '';
	var multiI = 0;
	var partnerID = '';

	var reqMulti = function(atext, partnerID) {
		if(!atext.length) return;

		var wl = window.location;
		var sc = document.createElement("script");
		sc.src = JSRC.URI + '-data.js' + "?ref="
			+ encodeURIComponent(wl.protocol + "//" + wl.host + wl.pathname)
			+ (partnerID ? "&partnerID=" + partnerID : "")
			+ atext;

		$JRA[$JRA.length-1].target.appendChild(sc);
	}


	for (var i=0; i < els.length; i++) {

		// Check to see if this div has already been processed
		if(els[i].jk$initialized) 
			continue;

		els[i].jk$initialized = true;

		var r = new JSRC(els[i]);
		var mr = JSKitLib.getPath(r);

		multiQ += "&p["+multiI+"]=" + encodeURIComponent(mr)
			+ ((mr == r.uniq) ? ''
			: ("&u["+multiI+"]=" + encodeURIComponent(r.uniq)))
			+ (r.config.property ? "&pr["+multiI+"]=" + encodeURIComponent(r.config.property) : '')
			+ (r.config.category ? "&cg["+multiI+"]=" + encodeURIComponent(r.config.category) : '')
			+ "&jx[" + multiI + "]=" + r.jraIndex;

		if (!partnerID && r.config.partnerID) {
			partnerID = r.config.partnerID
		}
		if(multiQ.length > 700) {
			reqMulti(multiQ, partnerID);
			multiQ = '';
			multiI = 0;
		} else {
			multiI ++;
		}
	}

	reqMulti(multiQ, partnerID);
}

// External API
JSRC.reinit = function() {
	$JRA = []; 
	JSRC.init();
}          

JSRC.prototype.addClassStyle = function(element, className) {
	JSKitLib.addClass(element, className);
}

JSRC.prototype.setPath = function(path) {
	this.path = path;
	this.pathOverride = path;    
}

JSRC.prototype.getRatingDataFromServer = function() {
	var mr = JSKitLib.getPath(this);
	this.server('-data.js', 'p[0]=' + encodeURIComponent(mr)
		+ ((mr == this.uniq) ? '' : ('&u[0]=' + encodeURIComponent(this.uniq)))
		+ (this.config.property ? '&pr[0]=' + encodeURIComponent(this.config.property) : '')
		+ (this.config.category ? '&cg[0]=' + encodeURIComponent(this.config.category) : '')
		+ '&jx[0]=' + this.jraIndex);
}

/* CSS Stylings */
JSRC.writeCSS = function() {
	var css = '';
	for (prop in JSRC.CSS) {
		css += '.' + prop + ' {' + JSRC.CSS[prop] + '}';
	}
	JSKitLib.addCss(css, "js-RatingsCssText");
}

/* JS Rating Class */
function JSRC(target) {

	this.jraIndex = $JRA.length;
	$JRA.push(this);
	var self = this;

	var options = arguments[1] || {};

	this.cr = function(tag) { return document.createElement(tag) };

	this.pathOverride = '';
	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;

	this.target = target;

	/* Configuration */

	// Handle block level config
	var bConfig = {}; // block level config
	var bcels = target.getElementsByTagName('span') || [];
	if (bcels.length) {
		for (var i=0; i < bcels.length; i++) {
			var bcMatch = (bcels[i].className.match(/^js-kit-config-(.*)$/)); 
			if (bcMatch.length) {
				var bcKey = bcMatch[1].toLowerCase();
				var bcVal = bcels[i].innerHTML;
				bConfig[bcKey] = bcVal;
			}
		}
	}

	target.innerHTML = "";
	JSKitLib.show(target);

	this.config = JSKitLib.getConfig(
		target,
		function(N, V) { return options[N] || V || bConfig[N]},
		{},
		'unique',
		'path',
		'uniq', 
		['standalone', 'no'],
		['view', 'combo'],
		['commentprompt', true],
		'imageurl',
		'imagesize',
		'title',
		'notop',
		'permalink',
		['domain', wl.host],
		['freeze', 'no'],
		['menu', 'yes'],
		['subtext', 'yes'],
		'property',
		'category',
		'starcolor',
		'usercolor',
		'thumbnail',
		['thumbsize', 'normal'],
		'showinfoonrate',
		'partnerID'
	);

	this.config.permalink = JSKitLib.getPermalink(target);
	this.config.title = JSKitLib.getTitle(target);
	if (this.config.starcolor) this.config.starcolor = this.config.starcolor.toLowerCase();
	if (this.config.usercolor) this.config.usercolor = this.config.usercolor.toLowerCase();

	if(this.config.view.match(/score/)){
		if(this.config.thumbsize.match(/small/)){
			this.starWidth       = 10;
			this.starHeight      = 12;
		} else if(this.config.thumbsize.match(/large/)){
			this.starWidth       = 15;
			this.starHeight      = 18;
		} else {
			this.config.thumbsize     = 'normal';
			this.starWidth       = 12;
			this.starHeight      = 15;
		}
	}

	// Handle defaults for showinfoonrate attribute
	if ( ! this.config.showinfoonrate) {
		if (this.config.view.match(/score/)) {
			this.config.showinfoonrate = "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 = this.config.imagesize.match(/(\d+)([^\d]+(\d+))?/);
		if(dim) {
			this.starWidth = dim[1];
			this.starHeight = dim[3] || this.starWidth;
		}
	}

	// Unique takes precedence over path
	if (this.config.unique) {
		this.config.path = '/' + this.config.unique;
	}

	if(this.config.view.match(/score/)){
		this.ratingBarWidth  = 2 * this.starWidth;
		this.ratingBarHeight = this.starHeight;
	} else {
		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.INFO_IMG);

	if (options.newRating) {
		//TODO
		this.newRating({ Sum: options.newRating.objSum, Num: options.newRating.objNum, Votes: options.newRating.objVotes }, { Sum: options.newRating.userRating});
	}

	this.server = function(ext, data) {
		var sc = self.cr("script");
		sc.setAttribute("charset", "utf-8");
		var partner = self.config.partnerID ? "&partnerID=" + self.config.partnerID : "";
		sc.src = JSRC.URI + ext + self.pathOverride
			+ "?ref=" + encodeURIComponent(JSKitLib.getRef(self, true)) + partner + "&" + data;
		self.target.appendChild(sc);
		return false;
	}

	if(options.autorequest) {
		this.getRatingDataFromServer();
	}

}

/* 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-labelTextUp': 'padding-top: 2px; font-size: 11px; text-align: center; cursor: default; -moz-user-select: none;',
	'js-rating-labelTextDown': '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-ratings-tableWrapper' : 'background: transparent;',
	'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 = [];

  this.Thumb = [];

  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]);

  }

  var genthumb = function(type) {
	var thumbURI = JSRC.BASE_STAR_URI;
	if(self.config.imageurl) {
		thumbURI = self.config.imageurl;
		self.Thumb[type]  = thumbURI;
	} else {
		self.Thumb[type]  = thumbURI + type + '-thumb.png';
	}

	JSKitLib.preloadImg(self.Thumb[type]);
  }

  if(this.config.view.match(/score/)){
    genthumb(this.config.thumbsize);
  } else {
    genstar(this.config.starcolor, 'ruby', 'star');
    genstar(this.config.usercolor, 'gold', 'user');
  }
}

JSRC.writeCSS();

/* Init a single call to init */
if ( ! $JRA.length) {
  JSRC.init();
  $JSKitGlobal.setRatingsAppAvailable();
} else {
  JSRC.init();
}


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.contentBoxUp
= '<div style="padding-right: 7px; padding-left: 3px;"><span class="js-rating-labelTextUp"><nobr>{votedUp}</nobr></span></div>';
JSRC.prototype.contentBoxDown
= '<div style="padding-left: 3px;"><span class="js-rating-labelTextDown"><nobr>{votedDown}</nobr></span></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);

if (this.config.subtext != 'no') {
  this.textTotal = this.cr('div');
  this.addClassStyle(this.textTotal, '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');
    JSKitLib.addStyle(starRatingDiv, 'margin-right:10px; float:left; width:' + this.ratingBarWidth + 'px');
    starRatingDiv.appendChild(starRatingBar);
    starRatingDiv.appendChild(this.textTotal);

    wrapper.appendChild(starRatingDiv);

    JSKitLib.addStyle(this.userRatingDiv, 'float:left; width:' + this.ratingBarWidth + 'px');

if (this.config.subtext != 'no') {
    this.textRating = this.cr('div');
    this.addClassStyle(this.textRating, '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'; 

if (this.config.subtext != 'no') {
    this.textRating = this.cr('div');
    this.addClassStyle(this.textRating, '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';

if (this.config.subtext != 'no') {
    if(!this.config.view.match(/score/)) {
      this.userRatingDiv.appendChild(this.textTotal);
    } else {
      this.userRatingBar.style.top=this.starHeight+'px';
      this.userRatingDiv.style.height=2*this.starHeight+'px';
      this.textTotal.style.height=this.starHeight+'px';
      this.userRatingDiv.insertBefore(this.textTotal,this.userRatingDiv.firstChild);
    }
    this.activeText = this.textTotal;
}

    this.totalWidth = this.ratingBarWidth;

    wrapper.appendChild(this.userRatingDiv);
  }

  // Set our total width
  if(!this.config.view.match(/score/))
    wrapper.style.width = this.totalWidth + 'px';

  /* Rating Menu */
  if (this.config.menu != 'no' && this.config.freeze != 'yes') {
    if(!this.config.view.match(/score/)) 
      wrapper.style.width = (this.totalWidth + 10 + JSRC.INFO_IMG_WIDTH) + 'px';

    var menuArrow = this.createMenuArrow();

    this.prepMenu(); // 'i' and infobox

    if((this.config.view.match(/score/)) && (this.config.subtext != 'no')) 
        menuArrow.style.marginTop = (2*this.starHeight-16)+'px';

    // Show mininav when score is rated
    if (this.config.showinfoonrate == 'yes') {
      var self = this;
      this.addOnRate(function() { self.hideInfoBox(); self.showInfoBox(); });
    }
    wrapper.appendChild(menuArrow);

  }


  // Set the target width
  if(!this.config.view.match(/score/)){
    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);
      self.addClassStyle(afterRatingDiv, '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); 
  }

  var tableWrapper = this.table(wrapper);
  tableWrapper.className = "js-ratings-tableWrapper";
  this.target.appendChild(tableWrapper); // stars

  if(this.config.view.match(/score/)){
    this.totalWidth=6+2*this.starWidth+this.contentBoxElUp.offsetWidth+this.contentBoxElDown.offsetWidth;
    var targetMinWidth;
    if (this.config.menu != 'no' && this.config.freeze != 'yes') {
      targetMinWidth = this.totalWidth + 6 + 10 + JSRC.INFO_IMG_WIDTH;
    } else {
      targetMinWidth = this.totalWidth + 6;
    }
    var targetWidth = this.target.style.width || targetMinWidth;
    if (parseInt(targetWidth) <= targetMinWidth) {
      this.target.style.width = targetMinWidth + 'px';
    }
    wrapper.style.width = targetMinWidth + 'px';
    this.userRatingDiv.style.width = (this.totalWidth) + 'px';
    if(this.textTotal) {
      this.textTotal.style.width = (this.totalWidth) + 'px';
    }
    this.userRatingBar.style.width = (this.totalWidth) + 'px';
    this.wrapper = wrapper;
  }

  if(!this.config.view.match(/split/) && !this.config.view.match(/user/)){
    this.userRatingDiv.style.cssFloat = 'left';
    this.userRatingDiv.style.styleFloat = 'left';
  }

  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);
    }

    // Initial time to hide box after mouseout
    self.infoBoxLifeTime = 1500;
 
    self.infoBoxWrapper.onmouseover = function() { 
      infobox2Show = true; 
      // If user is active in window, increase time before hiding
      self.infoBoxLifeTime = 3000;  
      infoBoxMouseover(); 
    }


    var infoBoxMouseout = function() {

      if (infobox1Show || infobox2Show) 
        return;

      self.ratingMenuTimer = setTimeout(function() {
        self.ratingMenuTimer = null;
          self.hideInfoBox();
          JSKitLib.hide(self.menuArrow);
      }, self.infoBoxLifeTime);
    }

    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.config.permalink && !window.$JSKitViaHaloScan) {
		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.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');
  JSKitLib.addStyle(wrapper, 'border: 1px solid #ccc;');

  var box = document.createElement('div');
  JSKitLib.addStyle(box, 'background: #ffc; border: none; filter: alpha(opacity=90); opacity: 0.9; padding: .3em;');
  
  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: (function() {
                	if(self.config.view.match(/score/)){
                		if(self.objNum){
                			return '('+$JRL('up')+': '+((self.objSum-self.objNum*self.raterInc)/(self.scale-self.raterInc))+', '+
                				$JRL('down')+': '+(self.objNum-((self.objSum-self.objNum*self.raterInc)/(self.scale-self.raterInc)))+')';
                		} else {
                			return '';
                		}
                	} else {
                		return self.objAvgStarRating > 0
					? ('(' + JSKitLib.zeroPad(self.objAvgStarRating, 2) + '&nbsp;' + $JRL('avgRating') + ')')
					: ''
                	}
                })(),
                userRatingMsg: (function() {
                        if (self.userRating) {
                        	if(self.config.view.match(/score/)){
                                	return $JRL('yourScore') + ': ' + (self.userRating==self.raterInc? '-1' : '+1');
                        	} else {
                                	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++) {
    // property must match as well
    if (this.config.property || $JRH[this.uniq][i].config.property) {
      if ($JRH[this.uniq][i].config.property == this.config.property) {
        handler($JRH[this.uniq][i]);
      }
	} else if (this.config.category || $JRH[this.uniq][i].config.category) {
      if ($JRH[this.uniq][i].config.category == this.config.category) {
        handler($JRH[this.uniq][i]);
      }
    } else {
        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;
  var objVotes = this.objVotes;
  if(oldRating) {
    objSum -= oldRating;
    objNum --;
  }
  if(this.config.view.match(/score/) && (this.config.thumbsize=='small' || this.config.thumbsize=='normal')){
    this.setTmpText($JRL('thank'));
  } else { 
    this.setTmpText($JRL('thankYou'));
  }

  // Update all ratings for this ID
  this.processSiblings(function(sibling) {
    //TODO: determine if current user increments objVotes count
    sibling.newRating({ Sum: objSum + givenRating, Num: objNum + 1, Votes: objVotes }, { Sum: givenRating });
  });

  // Handle any callbacks
  this.processOnRate();

  // TODO: parametric rating
  if (window.$J$PRA && typeof $J$PRA == 'object') {
    for (var i=0; i < $J$PRA.length; i++) {
      if ($J$PRA[i].path == this.path) {
        $J$PRA[i].onRate();
      }
    }
  }

  var title = this.config.title;
  this.server(".put", "rating=" + givenRating
    + (this.config.property ? "&property=" + this.config.property : "")
    + (this.config.category ? "&category=" + this.config.category : "")
	+ (title ? ("&title=" + encodeURIComponent(title)) : "")
	+ (this.config.notop ? "&notop=true" : "")
	+ (this.config.permalink ? "&permalink=" + encodeURIComponent(this.config.permalink) : "")
	+ (this.config.thumbnail ? "&thumbnail=" + encodeURIComponent(this.config.thumbnail) : "")
	+ (this.config.view ? "&view=" + encodeURIComponent(this.config.view) : "")
	);
}

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 $JRL(text);
}

JSRC.prototype.getTextForUserRating = function(rating) {
  var text = $JRL('yourRatingTitleCase') + ': ' + rating;
  return text;
}

JSRC.prototype.refreshTextTotal = function() {
  if(this.config.view.match(/score/)){
    this.setTextTotal("");
  } else {
    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);
    }, 3000);
  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);    
}

JSRC.prototype.setThumbImage = function(element, ud, actionable, imageURL, ignoreEmpty) {

	JSKitLib.setThumbImage( { element: element, ud: ud, actionable: actionable, imageURL: imageURL, ignoreEmpty: ignoreEmpty, numVotes: this.objNum, thumbWidth: this.starWidth, thumbHeight: this.starHeight } );

}


// Returns an single div with a specified thumb image
JSRC.prototype.createThumbImage = function(ud, actionable, imageURL, ignoreEmpty) {

	return JSKitLib.createThumbImage({ ud: ud, actionable: actionable, imageURL: imageURL, ignoreEmpty: ignoreEmpty, numVotes: this.objNum, thumbWidth: this.starWidth, thumbHeight: this.starHeight });

}

// Handles the hover state for the actionable stars
JSRC.prototype.hover = function(index) {

  if(this.tmpTextTimer) return;

  var icons = this.getRatingIcons();

  if(this.config.view.match(/score/)){
    this.setActiveText($JRL('scoreThis'));

    this.contentBoxElUp.style.opacity="0";
    this.contentBoxElUp.style.filter="alpha(opacity:0)";
    this.contentBoxElDown.style.opacity="0";
    this.contentBoxElDown.style.filter="alpha(opacity:0)";

    if(icons.length>=2){
        this.setThumbImage(icons[0],'up',1,this.Thumb[this.config.thumbsize],1);
        this.setThumbImage(icons[1],'down',1,this.Thumb[this.config.thumbsize],1);
	this.setThumbOpacity(icons[0],1);
	this.setThumbOpacity(icons[1],1);
    }
  } else {
    this.setActiveText($JRL('rateThis') + ': ' + (index / this.raterInc));
    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);
}

JSRC.prototype.calcScore = function() {
	return(this.objNum ? (this.objSum-6*this.objNum)/4 : 0);
}

JSRC.prototype.setScoreOpacity = function(icons) {
  var isfreeze=this.config.freeze=='yes'? true : false;
  var curscore=this.calcScore();
  if(icons.length>=2){
    this.setThumbImage(icons[0],'up',!isfreeze,this.Thumb[this.config.thumbsize]);
    this.setThumbImage(icons[1],'down',!isfreeze,this.Thumb[this.config.thumbsize]);
    var setTextOpacity = function(el, opacity) {
	el.style.opacity=opacity;
	el.style.filter='alpha(opacity:'+(100*opacity)+')';
    }
    if(isfreeze){
	this.setThumbOpacity(icons[0],0.6);
	this.setThumbOpacity(icons[1],0.6);
	setTextOpacity(this.contentBoxElUp, 1);
	setTextOpacity(this.contentBoxElDown, 1);
    } else if(this.objNum){
	if(curscore>0){
		this.setThumbOpacity(icons[0],1);
		this.setThumbOpacity(icons[1],0.6);
		setTextOpacity(this.contentBoxElUp, 1);
		setTextOpacity(this.contentBoxElDown, 0.6);
	} else if(curscore<0){
		this.setThumbOpacity(icons[1],1);
		this.setThumbOpacity(icons[0],0.6);
		setTextOpacity(this.contentBoxElDown, 1);
		setTextOpacity(this.contentBoxElUp, 0.6);
	} else {
		this.setThumbOpacity(icons[0],1);
		this.setThumbOpacity(icons[1],1);
		setTextOpacity(this.contentBoxElUp, 1);
		setTextOpacity(this.contentBoxElDown, 1);
	}
    } else {
	this.setThumbOpacity(icons[0],1);
	this.setThumbOpacity(icons[1],1);
	setTextOpacity(this.contentBoxElUp, 1);
	setTextOpacity(this.contentBoxElDown, 1);
    }
  }
}

JSRC.prototype.refreshUDRating = function() {
  var icons = this.getRatingIcons();
  this.setScoreOpacity(icons);
  if (this.config.view.match(/score/)){
    this.refreshContentBox('all');
  }
  if (this.defaultView == 'star') {
    this.refreshTextTotal();
  } else {
    this.refreshTextRating();
  }
}

// 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 isfreeze=this.config.freeze=='yes'? true : false;
  var icons = isfreeze? this.getObjIcons() : this.getRatingIcons();
  if(this.config.view.match(/score/)){
    this.setScoreOpacity(icons);
  } else {
    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.refreshContentBox = function (refreshobj,uptext,downtext) {
	var oldTotalWidth = this.totalWidth;

	var self=this;
	var vars={
		votedDown: downtext? downtext : (function(){
				return (self.objNum-((self.objSum-self.objNum*self.raterInc)/(self.scale-self.raterInc)))
			})(),
		votedUp: uptext? uptext : (function(){
				return ((self.objSum-self.objNum*self.raterInc)/(self.scale-self.raterInc))
			})()
	};
	if(refreshobj=='all' || refreshobj=='up'){
	  var contentUp=this.html(this.tmpl(this.contentBoxUp,vars));
	  if(this.contentBoxElUp.hasChildNodes()){
		this.contentBoxElUp.firstChild.innerHTML=contentUp.innerHTML;
	  } else {
	  	this.contentBoxElUp.appendChild(contentUp);
	  }
	}
	if(refreshobj=='all' || refreshobj=='down'){
	  var contentDown=this.html(this.tmpl(this.contentBoxDown,vars));
	  if(this.contentBoxElDown.hasChildNodes()){
		this.contentBoxElDown.firstChild.innerHTML=contentDown.innerHTML;
	  } else {
	  	this.contentBoxElDown.appendChild(contentDown);
	  }
	}

	if(this.userRatingBar){
		this.totalWidth=6+2*this.starWidth+this.contentBoxElUp.offsetWidth+this.contentBoxElDown.offsetWidth;
		var delta = this.totalWidth - oldTotalWidth;
		var targetMinWidth;
		if (this.config.menu != 'no' && this.config.freeze != 'yes') {
			targetMinWidth = this.totalWidth + 6 + 10 + JSRC.INFO_IMG_WIDTH;
		} else {
			targetMinWidth = this.totalWidth + 6;
		}
		var targetWidth = this.target.style.width || targetMinWidth;
		if(delta>0) {
			if (parseInt(targetWidth) <= targetMinWidth) {
				this.target.style.width = targetMinWidth + 'px';
			}
			this.wrapper.style.width = targetMinWidth + 'px';
			this.userRatingDiv.style.width = (this.totalWidth) + 'px';
			if(this.textTotal) {
				this.textTotal.style.width = (this.totalWidth) + 'px';
			}
			this.userRatingBar.style.width = (this.totalWidth) + 'px';
		} else {
			this.userRatingBar.style.width = (this.totalWidth) + 'px';
			if(this.textTotal) {
				this.textTotal.style.width = (this.totalWidth) + 'px';
			}
			this.userRatingDiv.style.width = (this.totalWidth) + 'px';
			this.wrapper.style.width = targetMinWidth + 'px';
			if (parseInt(targetWidth) <= targetMinWidth) {
				this.target.style.width = targetMinWidth + 'px';
			}
		}
	}
}

JSRC.prototype.setThumbOpacity = function(element, curopacity) {
	if (JSKitLib.isPreIE7()) {
		element.parentNode.style.filter='alpha(opacity:'+(100*curopacity)+')';
	} else if (JSKitLib.isIE()) {
		element.parentNode.style.filter='progid:DXImageTransform.Microsoft.Alpha(opacity:'+(100*curopacity)+')';
	} else {
		element.style.opacity=curopacity;
	}
}

JSRC.prototype.initRating = function(rating, type, actionable) {
  var self = this;
  var node = this.cr('div');
  if(!this.config.view.match(/score/)){
    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);
	if(self.config.view.match(/score/)){
		self.refreshScheduled = setTimeout(
			function(){self.refreshScheduled=null;
			self.refreshUDRating()}, 300);
	} else {
		self.refreshScheduled = setTimeout(
			function(){self.refreshScheduled=null;
			self.refreshRating()}, 300);
	}
  }

  node.onmouseover = function() {
			if(self.refreshScheduled)
				clearTimeout(self.refreshScheduled);
		}
  node.onmouseout = outf;

  var star;

  if(this.config.view.match(/score/)){
    star = this.cr('div');
    star.style.cssFloat   = 'left';
    star.style.styleFloat = 'left';
    star.style.width    = this.starWidth + 'px';
    star.style.height   = this.starHeight + 'px';
    star.style.position = 'relative';
    star.style.overflow = 'hidden';
    star.title = '+1';

    var upThumb = this.cr('div');
    upThumb.style.width = (this.starWidth * 2)+'px';
    upThumb.style.height = (this.starHeight * 2)+'px';
    if (actionable) {
      upThumb.className += ' js-kit-rater';
      star.onmouseover = function() { inf(); self.hover(self.scale); }
      star.onmouseout  = outf;
      star.onclick     = function() { self.rate(self.scale); }
    } else {
      upThumb.className += ' js-kit-objIcon';
    }
    var startmp= this.cr('div');
    startmp.style.position='absolute';
    startmp.style.width    = this.starWidth + 'px';
    startmp.style.height   = this.starHeight + 'px';
    var startmp2;
    if(JSKitLib.isIE() && !JSKitLib.isPreIE7()){
	    startmp2=this.cr('div');
	    startmp2.style.width    = (this.starWidth * 2) + 'px';
	    startmp2.style.height   = (this.starHeight * 2)  + 'px';
	    startmp2.appendChild(upThumb);
	    startmp.appendChild(startmp2);
	    this.setThumbImage(upThumb,'up',actionable,this.Thumb[this.config.thumbsize]);
    } else {
	    startmp.appendChild(upThumb);
	    this.setThumbImage(upThumb,'up',actionable,this.Thumb[this.config.thumbsize]);
    }
    star.appendChild(startmp);
    node.appendChild(star);

    star = this.cr('div');
    star.style.cssFloat   = 'left';
    star.style.styleFloat = 'left';
    star.style.height = this.ratingBarHeight + 'px';
    this.contentBoxElUp=star;
    node.appendChild(star);

    star = this.cr('div');
    star.style.cssFloat   = 'left';
    star.style.styleFloat = 'left';
    star.style.width    = this.starWidth + 'px';
    star.style.height   = this.starHeight + 'px';
    star.style.position = 'relative';
    star.style.overflow = 'hidden';
    star.style.marginTop = '1px';
    star.title = '-1';

    var downThumb = this.cr('div');
    downThumb.style.width = (this.starWidth * 2)+'px';
    downThumb.style.height = (this.starHeight * 2)+'px';
    if (actionable) {
      downThumb.className += ' js-kit-rater';
      star.onmouseover = function() { inf(); self.hover(self.raterInc); }
      star.onmouseout  = outf;
      star.onclick     = function() { self.rate(self.raterInc); }
    } else {
      downThumb.className += ' js-kit-objIcon';
    }
    startmp= this.cr('div');
    startmp.style.position='absolute';
    startmp.style.width    = this.starWidth + 'px';
    startmp.style.height   = this.starHeight + 'px';
    if(JSKitLib.isIE() && !JSKitLib.isPreIE7()){
	    startmp2=this.cr('div');
	    startmp2.style.width    = (this.starWidth * 2) + 'px';
	    startmp2.style.height   = (this.starHeight * 2) + 'px';
	    startmp2.appendChild(downThumb);
	    startmp.appendChild(startmp2);
	    this.setThumbImage(downThumb,'down',actionable,this.Thumb[this.config.thumbsize]);
    } else {
	    startmp.appendChild(downThumb);
	    this.setThumbImage(downThumb,'down',actionable,this.Thumb[this.config.thumbsize]);
    }
    star.appendChild(startmp);
    node.appendChild(star);

    star = this.cr('div');
    star.style.cssFloat   = 'left';
    star.style.styleFloat = 'left';
    star.style.height = this.ratingBarHeight + 'px';
    this.contentBoxElDown=star;
    node.appendChild(star);

    this.refreshContentBox('all');
  } else {
    /* Increment by Full Star Ratings */
    for (var i=this.raterInc; i <= this.scale; i += this.raterInc) {

      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;
}

// Part of externally useable API
JSRC.prototype.rerender = function() {
	this.getRatingDataFromServer();    
}

JSRC.prototype.newRating = function() {
  var args = arguments;
  if(typeof args[0] != 'object')
    args = [ args[3], args[4], args[5] || {} ];
  var community = args[0];
  var user = args[1] || { Sum: 0 };
  var opts = args[2] || { admin: false};

  this.isAdmin = opts.admin;

  if(user.frozen) this.config.freeze = "yes";


  this.objSum = community.Sum;
  this.objNum = community.Num;
  this.objVotes = community.Votes || community.Num;
  this.userRating = user.Sum;
  if(this.config.view.match(/score/)){
    if(this.objNum){
      this.objAvgStarRating = JSKitLib.round(((this.objSum / this.objNum)-(this.scale+this.raterInc)/2)/ this.raterInc, 2);
    } else {
      this.objAvgStarRating = 0;
    }
  } else {
    this.objAvgStarRating = JSKitLib.round((this.objSum / this.objNum) / this.raterInc, 2);
  }
  this.objEffRating = Math.round(this.objSum / this.objNum) || 0;  // Used for star display purposes

  if(this.refreshScheduled) {
	clearTimeout(this.refreshScheduled);
	this.refreshScheduled = null;
  }

  if (this.constructed) {
    this.refreshTextTotal();
    this.refreshObjRating();
    if(this.config.view.match(/score/)){
      this.refreshUDRating();
    } else {
      this.refreshRating();
    }
  } else {
    this.constructed = true;
    this.display();
  }

  // TODO: use JSKitGlobal
  if (window.$J$PRA && typeof $J$PRA == 'object') {
    for (var i=0; i < $J$PRA.length; i++) {
        $J$PRA[i].updateComposite();
    }
  }

}

JSRC.prototype.showInfoBox = function(xOpts) {

	// 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:15500;');

	// 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, xOpts);

	this.infoBox = infoBox;

}

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-rTopFrame': 'background: #f8f8f8; border: solid 1px #e0e0e0; padding: 0; margin: 0.5em; -moz-user-select: none; -webkit-box-shadow: 0px 10px 50px #222; cursor: default; z-Index: 15000;', 
	'div.js-rTop': 'cursor: default; border: solid 1px #f8f8f8; padding:1px;', 
	'div.js-rTopBg': 'width: 100%;', // width needed for ie redraw
	'div.js-rTopView': 'margin: -2pt -2px 0px; 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;',
	'span.js-rTopItemCounter': 'margin-right: .3em;',
	'a.js-rTopItemLink': 'zoom: 1;',
	'span.js-rTopItemRating': 'margin: 0; white-space: nowrap',

	// User Top Rated
	'div.js-rTopUserItems': 'margin: 0; text-align: left;',
	'div.js-rTopUserItem': 'padding: 0.3em 0.6em;',
	'a.js-rTopUserItemLink': 'zoom: 1;',

	'div.js-rTopUserThisItems': 'margin: 0; text-align: left;',
	'div.js-rTopUserThisItem': 'padding: 0.3em 0.6em;',
	'a.js-rTopUserThisItemLink': 'zoom: 1;',

	// Top Scored
	'div.js-rTopScoreItems': 'margin: 0; text-align: left;',
	'div.js-rTopScoreItem': 'padding: 0.3em 0.6em 0.3em 0.6em;',
	'span.js-rTopScoreItemCounter': 'margin-right: .3em;',
	'div.js-rTopScoreItemInfo': 'margin-top: 0.0em;',
	'a.js-rTopScoreItemLink': 'zoom: 1;',
	'span.js-rTopScoreItemRating': 'margin: 0; white-space: nowrap',

	// Hot
	'div.js-rTopHotItems': 'margin: 0; text-align: left;',
	'div.js-rTopHotItem': 'padding: 0.3em 0.6em;',
	//'span.js-rTopHotItemInfo': 'margin: 0.2em .4em .3em 0;',
	'a.js-rTopHotItemLink': 'zoom: 1;',

	// User Top Scored
	'div.js-rTopUserScoreItems': 'margin: 0; text-align: left;',
	'div.js-rTopUserScoreItem': 'padding: 0.3em 0.6em 0.3em 0.6em;',
	'div.js-rTopUserScoreItemInfo': 'margin: 0.2em 0;',
	'a.js-rTopUserScoreItemLink': 'zoom: 1;',

	'div.js-rTopUserThisScoreItems': 'margin: 0; text-align: left;',
	'div.js-rTopUserThisScoreItem': 'padding: 0.3em 0.6em 0.3em 0.6em;',
	'div.js-rTopUserThisScoreItemInfo': 'margin: 0.2em 0;',
	'a.js-rTopUserThisScoreItemLink': 'zoom: 1;',

	// Footer
	'div.js-rTopFooter': 'padding: 0; 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, "js-RatingsTopCssText");
}

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;';
	}

	var css 
		= "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-rTopScoreItemLink {" + tabFont + "}"
		+ "a.js-rTopHotItemLink {" + tabFont + "}"
		+ "a.js-rTopUserItemLink {" + tabFont + "}"
		+ "a.js-rTopUserScoreItemLink {" + tabFont + "}"
		+ "div.js-rTopBodyAdminMsgHeader {" + adminNote + "}"
		;
	JSKitLib.addCss(css, "js-RatingsTopSkinCss");
}

JSRTC.writeSkinCSS();

/* Class JSRTC */
function JSRTC(target, options, parentObj, xOpts) {
	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;
	}

	// Process xOpts (additional values we may need passed in by callee)
	this.xOpts = (typeof xOpts == 'object') ? xOpts : {};

	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" class="js-rTopFrame">'

    + '<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">'
     + '<table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="middle">'
      + '<div class="js-rTopItemStars"></div>'
     + '</td><td>'
      + '<span class="js-rTopItemRating js-rTopDetailFont">{rating}&nbsp;({votes})</span>'
     + '</td></tr></tbody></table>'
    + '</div>'
   + '</div>'
  + '</div>'
 + '</div>'
;

JSRTC.prototype.dtBodyTopScore 
 = '<div class="js-rTopTopScore">'
  + '<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-rTopScoreItems">'
   + '<div class="js-rTopScoreItem">'
    + '<a class="js-rTopScoreItemLink js-rTopFont" href="{url}">{title}</a>'
    + '<div class="js-rTopScoreItemInfo">'
     + '<table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="middle">'
      + '<div class="js-rTopScoreItemStars" style="padding-right:5px;"></div>'
     + '</td><td>'
      + '<span class="js-rTopItemScoreRating js-rTopDetailFont"><b>{rating}</b>&nbsp;({votes})</span>'
     + '</td></tr></tbody></table>'
    + '</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>'
     + '<table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="middle">'
      + '<span class="js-rTopHotItemInfo js-rTopDetailFont"> ({votes})</span>'
     + '</td></tr></tbody></table>'
    + '</div>'
   + '</div>'
  + '</div>'
;

JSRTC.prototype.dtBodyUser
 = '<div class="js-rTopUser">'
  + '<div class="js-rTopUserThis" style="display: none">'
  + '<div class="js-rTopDetailFont" style="color: black; background-color:#ffa; margin: .5em .8em 0 .8em; padding: 2px 5px; text-align:center;">My vote on this object</div>'
  + '<div class="js-rTopUserThisItems">'
   + '<div class="js-rTopUserThisItem">'
    + '<a class="js-rTopUserThisItemLink js-rTopFont" href="{url}">{title}</a>'
    + '<div class="js-rTopUserThisItemInfo">'
     + '<table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="middle">'
      + '<div class="js-rTopUserThisItemStars"></div>'
     + '</td><td>'
      + '<span class="js-rTopItemRating js-rTopDetailFont">&nbsp;</span>' // Needed for even spacing with dtBodyTop
     + '</td></tr></tbody></table>'
    + '</div>'
   + '</div>'
  + '</div>'
 + '</div>'
  + '<div class="js-rTopUserOther" style="display: none">'
  + '<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">'
     + '<table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="middle">'
      + '<div class="js-rTopUserItemStars"></div>'
     + '</td><td>'
      + '<span class="js-rTopItemRating js-rTopDetailFont">&nbsp;</span>' // Needed for even spacing with dtBodyTop
     + '</td></tr></tbody></table>'
    + '</div>'
   + '</div>'
  + '</div>'
 + '</div>'

 + '</div>'
;

JSRTC.prototype.dtBodyUserScore
 = '<div class="js-rTopUserScore">'
  + '<div class="js-rTopUserThisScore" style="display: none">'
  + '<div class="js-rTopDetailFont" style="color: black; background-color:#ffa; margin: .5em .8em 0 .8em; padding: 2px 5px; text-align:center;">My vote on this object</div>'
  + '<div class="js-rTopUserThisScoreItems">'
   + '<div class="js-rTopUserThisScoreItem">'
    + '<table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="top">'
     + '<div class="js-rTopUserThisScoreItemStars" style="padding-right: 5px; padding-top: .2em;"></div>'
    + '</td><td>'
     + '<div><a class="js-rTopUserThisScoreItemLink js-rTopFont" href="{url}">{title}</a></div>'
    + '</td></tr></tbody></table>'
   + '</div>'
  + '</div>'
  + '</div>'
  + '<div class="js-rTopUserOtherScore" style="display: none">'
  + '<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-rTopUserScoreItems">'
   + '<div class="js-rTopUserScoreItem">'
    + '<table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="top">'
     + '<div class="js-rTopUserScoreItemStars" style="padding-right: 5px; padding-top: .2em;"></div>'
    + '</td><td>'
     + '<div><a class="js-rTopUserScoreItemLink js-rTopFont" href="{url}">{title}</a></div>'
    + '</td></tr></tbody></table>'
   + '</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;
}

JSRTC.prototype.getMiniThumb = function(score) {

	var thumbImage = JSRTC.DOMAIN + '/images/stars/small-thumb.png';

	var upDown = score >=0 ? 'up' : 'down';
	var miniThumb = JSKitLib.createThumbImage({ ud: upDown, actionable: true, imageURL: thumbImage, ignoreEmpty: true, thumbWidth: 10, thumbHeight: 12 });

	return miniThumb; 
}

/*
 * 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();

	var isScore = (this.parentObj.config.view.match(/score/));
	var myTab = { type:(isScore ? "US": "UR"), title:"My", active: true };

	this.views = [];
	if (this.parentObj.config.permalink) {
		this.views.push(myTab);
		if (dataTypes['TR'] || dataTypes['TS'] || this.isAdmin) {
			this.views.push({ type:(isScore ? "TS" : "TR"), title:"Top", active: true });
			this.views.push({ type:"HT", title:"Hot", active: true });
		}
	} else if (dataTypes[myTab.type]) {
		this.views.push(myTab);
	}
	this.views.push({ 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 "US":
				var content = this.createBodyUserScore(navData);
				break;
			case "AA":
				var content = this.createBodyAdminMsg($JRTL('adminMsgAlert'));
				break;
			case "TR":
				var content = this.createBodyTop(navData);
				JSKitLib.preventSelect(content);
				break;
			case "TS":
				var content = this.createBodyTopScore(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.createBodyTopScore = function(navData) {

	var self = this;

	var body = this.html(this.dtBodyTopScore);
	var ctls = this.mapClass2Object({}, body);

	/* Top TS */
	var tip = ctls['js-rTopScoreItems'];
	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-rTopScoreItemLink'];
		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-rTopScoreItemStars'];
		stars.appendChild(item.stars);
		return idiv;
	}

	if (navData.part.TS.items.length) {    
		JSKitLib.map(function(item, i, items) {
			self.addChild(tip, topItem(items, i));
		}, navData.part.TS.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 tipthis = ctls['js-rTopUserThisItems'];
	var tTemplate = tip.innerHTML;
	var tThisTemplate = tipthis.innerHTML;
	tip.innerHTML = '';
	tipthis.innerHTML = '';

	var existOther = 0;

	var isThis = function(item) {
		return (String(item.path || '').toLowerCase() == String(self.parentObj.config.path || '').toLowerCase());
	};

	var userThisItem = function(pObj) {
		var p = pObj.config.permalink || pObj.path;
		var item = {url: p,title: pObj.config.title || p};
		var idiv = self.html(self.tmpl(tThisTemplate, item));
		var ictls = self.mapClass2Object({}, idiv);
		var link = ictls['js-rTopUserThisItemLink'];
		if (item.url && item.url.match(/^[a-z]+:\/\//)) {
			link.href = item.url;
		} else {
			link.href = self.domain + (item.url ? item.url : '');
		}
		if (self.config.get('target')) {
			link.target = self.config.get('target');
		}    
		var stars = ictls['js-rTopUserThisItemStars'];
		var istars = self.getMiniStars(pObj.userRating, 10);
		stars.appendChild(istars);
		return idiv;
	}

	var userItem = function(items, idx) {
		var item = items[idx];
		if(isThis(item)) return undefined;
		existOther = 1;
		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 || self.parentObj.userRating) {    
		if(self.parentObj.userRating){
			var cd = userThisItem(self.parentObj);
			if(cd)
				self.addChild(tipthis, cd);
			ctls['js-rTopUserThis'].style.display = 'block';
		} else {
			ctls['js-rTopUserThis'].style.display = 'none';
		}
		JSKitLib.map(function(item, i, items) {
			var cd = userItem(items, i);
			if(cd)
				self.addChild(tip, cd);
		}, navData.part.UR.items);
		if(existOther){
			ctls['js-rTopUserOther'].style.display = 'block';
		} else {
			ctls['js-rTopUserOther'].style.display = 'none';
		}
	} else {
		if (this.isAdmin) {        
			if (this.parentObj.config.permalink) {
				ctls['js-rTopUserOther'].style.display = 'block';
				tip.appendChild(this.createBodyMsg($JRTL('msgNoUserItems')));
			} else {
				ctls['js-rTopUserOther'].style.display = 'block';
				tip.appendChild(this.createBodyAdminMsg($JRTL('adminMsgPermalinkHelp')));
			}
		} else {
			ctls['js-rTopUserOther'].style.display = 'block';
			tip.appendChild(this.createBodyMsg($JRTL('msgNoUserItems')));
		}
	}

	return body;

}

JSRTC.prototype.createBodyUserScore = function(navData) {

	var self = this;

	var body = this.html(this.dtBodyUserScore);
	var ctls = this.mapClass2Object({}, body);

	/* Top UR */
	var tip = ctls['js-rTopUserScoreItems'];
	var tipthis = ctls['js-rTopUserThisScoreItems'];
	var tTemplate = tip.innerHTML;
	var tThisTemplate = tipthis.innerHTML;
	tip.innerHTML = '';
	tipthis.innerHTML = '';

	var existOther = 0;

	var isThis = function(item) {
		return (String(item.path || '').toLowerCase() == String(self.parentObj.config.path || '').toLowerCase());
	};

	var userThisItem = function(pObj) {
		var p = pObj.config.permalink || pObj.path;
		var item = {url: p, title: pObj.config.title || p};
		var idiv = self.html(self.tmpl(tThisTemplate, item));
		var ictls = self.mapClass2Object({}, idiv);
		var link = ictls['js-rTopUserThisScoreItemLink'];
		if (item.url && item.url.match(/^[a-z]+:\/\//)) {
			link.href = item.url;
		} else {
			link.href = self.domain + (item.url ? item.url : '');
		}
		if (self.config.get('target')) {
			link.target = self.config.get('target');
		}    
		var stars = ictls['js-rTopUserThisScoreItemStars'];
		var istars = self.getMiniThumb(pObj.calcScore());
		stars.appendChild(istars);
		return idiv;
	}

	var userItem = function(items, idx) {
		var item = items[idx];
		if(isThis(item)) return undefined;
		existOther = 1;
		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-rTopUserScoreItemLink'];
		if (item.url && item.url.match(/^[a-z]+:\/\//)) {
			link.href = item.url;
		} else {
			link.href = self.domain + (item.url ? item.url : '');
		}
		if (self.config.get('target')) {
			link.target = self.config.get('target');
		}    
		var stars = ictls['js-rTopUserScoreItemStars'];
		stars.appendChild(item.stars);
		return idiv;
	}

	if (navData.part.US.items.length || self.parentObj.userRating) {    
		if(self.parentObj.userRating){
			var cd = userThisItem(self.parentObj);
			if(cd)
				self.addChild(tipthis, cd);
			ctls['js-rTopUserThisScore'].style.display = 'block';
		} else {
			ctls['js-rTopUserThisScore'].style.display = 'none';
		}
		JSKitLib.map(function(item, i, items) {
			var cd = userItem(items, i);
			if(cd)
				self.addChild(tip, cd);
		}, navData.part.US.items);
		if(existOther){
			ctls['js-rTopUserOtherScore'].style.display = 'block';
		} else {
			ctls['js-rTopUserOtherScore'].style.display = 'none';
		}
	} else {
		if (this.isAdmin) {        
			if (this.parentObj.config.permalink) {
				ctls['js-rTopUserOtherScore'].style.display = 'block';
				tip.appendChild(this.createBodyMsg($JRTL('msgNoUserItems')));
			} else {
				ctls['js-rTopUserOtherScore'].style.display = 'block';
				tip.appendChild(this.createBodyAdminMsg($JRTL('adminMsgPermalinkHelp')));
			}
		} else {
			ctls['js-rTopUserOtherScore'].style.display = 'block';
			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.getTextForTotalScoreVotes = function(votes) {
	return $JRTL('by') + ' ' + this.getTextForTotalVotes(votes);
}

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;
}

JSRTC.prototype.prepTopScoreItems = 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 score icons
	for (var i=0; i < items.length; i++) {

		items[i].rating = JSKitLib.round(items[i].val1>0 ? '+'+items[i].val1 : items[i].val1);
		items[i].votes = this.getTextForTotalScoreVotes(items[i].val2); 
		var upDown = items[i].rating <= 0 ? 'down' : 'up';
		//items[i].stars = this.parentObj.createThumbImage(upDown, 1, this.parentObj.Thumb[this.parentObj.config.thumbsize],1);
		items[i].stars = this.getMiniThumb(items[i].rating);
	}    

	return items;
}
JSRTC.prototype.prepUserScoreItems = 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 score icons
	for (var i=0; i < items.length; i++) {

		var upDown = items[i].rating == this.parentObj.raterInc ? -1 : 1;
		items[i].stars = this.getMiniThumb(upDown);
	}    

	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.addEventHandler(window, ["onload","onresize"], 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.processDataTopScore = function(navData) {

	var TS = JSKitLib.filter(
		function(o) { return (o.type === "TS" && o.title.length); },
			navData.data);

	navData.part.TS.items = this.prepTopScoreItems(TS) || [];
}

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.processDataUserScore = function(navData) {

	var US = JSKitLib.filter(
		function(o) { return (o.type === "US"); },
			navData.data);

	navData.part.US.items = this.prepUserScoreItems(US) || [];
}

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: {},
		TS: {},
		HH: {},
		HD: {},
		HW: {},
		HT: {},  // Composite of HH, HD, HW
		UR: {},
		US: {}
	};

	this.processDataTop(navData);
	this.processDataTopScore(navData);
	this.processDataHot(navData);
	this.processDataUser(navData);
	this.processDataUserScore(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);
	}
}




