
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: 2009-02-12 02:34:43 -0800 (Thu, 12 Feb 2009) $
 */

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

  var $JRLT = {
    yourRatingTitleCase: 'Il tuo voto',
    yourRating: 'Il tuo voto',
    vote: 'voto',
    votes: 'voti',
    unrated: 'Senza voto',
    rateThis: 'Vota',
    avgRating: 'voto medio',
    avgRatingExtend: 'Media dei voti',
    poweredBy: 'Powered by',
    youHaveNotRatedYet: 'Non hai ancora votato',
    addACommentToYourRating: 'Aggiungi un commento al tuo voto',
    noVotesReceivedYet: 'Voti non ancora ricevuti',
    beTheFirstToRate: 'Vota per primo!',
    ratingsDisabled: 'Votazioni chiuse',
    thankYou: 'Grazie!',
    thank: 'Grazie',
    scoreThis: 'Assegna un punteggio',
    yourScore: 'Il tuo punteggio',
    up: 'su',
    down: 'gił',
    "My": "Miei",
    "My recent top ratings": "I miei voti pił recenti",
    "Sitewide top rated objects": "I pił votati del sito",
    "Sitewide hot objects": "I pił hot del sito",
    "About this rated object": "Info su questo oggetto"

  };

  var $JRL = window.JSRC_Translate || function(t) {
        return $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.getOuterHTML = function(node) {
	var clone = node.cloneNode(true);
	var parent = document.createElement('div');
	parent.appendChild(clone);
	var ihtml = parent.innerHTML;

    // ff converts sp characters inside of href to hex ascii
	var ihtmlHref = ihtml.match(/href\s*=\s*"[^"]*(%7B|%7D)[^"]*"/g) || [];
	for (var i=0; i< ihtmlHref.length; i++) {
		var a = ihtmlHref[i];
		var b = a.replace(/%7B/g, '{');
		b = b.replace(/%7D/g, '}');
		ihtml = ihtml.replace(a, b);
	}
	return ihtml;
};

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

JSKitLib.htmlQuote = function (newValue, param) {
	newValue = newValue.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")
	param = param || {};
	if(!param.title)
		newValue = newValue.replace(/ /,"&nbsp;");
	if(param.attribute)
		newValue = newValue.replace(/"/g,"&quot;");
	return newValue;
}

JSKitLib.htmlUnquote = function (newValue) {
	return newValue.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&");
}

JSKitLib.addJS = function(src,content) {
	var sId = "js-kit-script-"+src.replace(/[\/.]/g, '');
	content.jsk$scriptId = sId;
	if(document.getElementById(sId)) {
		return;
	}
	var s = document.createElement('script');
	s.id = sId;
	s.type ='text/javascript';
	s.src = src;
	content.appendChild(s);
}

JSKitLib.stripTags = function(text) {
	var r = /<\/?(a|em|strong|i|b|u|sup|sub|object|param|embed|span|pre|p)(.|\n)*?>/gi;
	text = text.replace(/<object(.|\n)+?<\/object>/gi,"[video]");
	text = text.replace(r,"");
	return (text.length > 150) ? text.slice(0,150) + "..." : text;
}




JSKitLib.addEventHandler = function(obj, eventNames, newHandler, newFirst) {
	var doc = window.addEventListener || window.attachEvent ? window : document.addEventListener ? document : null;
	JSKitLib.map(function(e) {
		if(doc) {
			if(doc.addEventListener)
				doc.addEventListener(e, newHandler, false)
			else
			if(doc.attachEvent) doc.attachEvent(e, newHandler)
		} else {
			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, content) {
	var doc = content || document;
	if(name) {
		name = "js-" + name + "-css";
		if (doc.getElementById(name)) return;
	}
	var se = doc.createElement("style");
	se.type = "text/css";
	if(name) se.id = name;
	if (se.styleSheet) se.styleSheet.cssText = cssCode;
	else se.appendChild(doc.createTextNode(cssCode));
	var hd = doc.getElementsByTagName("head");
	if(hd && hd[0]) hd[0].appendChild(se);
	else doc.write('<style>'+cssCode+'</style>');
}

JSKitLib.getElementsByClass = function(node, searchClass, tag) {
	var classElements = [];
	node = node || document;
	tag = tag || '*';
	var tagElements = node.getElementsByTagName(tag);
	var regex = new RegExp("(^|\\s)" + searchClass + "(\\s|$)");
	for (var i=0, j=0; i < tagElements.length; i++) {
		if (regex.test(tagElements[i].className)) {
			classElements[j] = tagElements[i];
			j++;
		}
	}
	return classElements;
};

JSKitLib.mapClass2Object = function(ctl, e) {
        if(e.className) {
                var arr = String(e.className).split(/[ ]+/);
                JSKitLib.map(function(el) { ctl[el] = e }, arr);
        }
        if(e.name) ctl[e.name] = e;
        try {
                var self = this;
                JSKitLib.map(function(child) {
                        JSKitLib.mapClass2Object(ctl, child);
                }, e.childNodes);
        } catch(e){}
        return ctl;
}

JSKitLib.hasClass = function(element, className) {
	return element.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
}

JSKitLib.addClass = function(element, className) {
	if (!JSKitLib.hasClass(element, className)) {
		element.className += ' ' + className;
	}
}

JSKitLib.removeClass = function(element, className) {
	if (JSKitLib.hasClass(element, className)) {
		var regex = new RegExp('(\\s|^)' + className + '(\\s|$)');
		element.className = element.className.replace(regex, ' ');
	}
}



JSKitLib.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.addChild = function(to, what) {
        if (typeof(to) != 'object')
                return;
        if(arguments.length == 3 && arguments[2])
                to.insertBefore(what, to.firstChild);
        else
                to.appendChild(what);
}

JSKitLib.setOpacity = function(div, val) {
	if(document.body.filters) {
		if(val == 1) div.style.filter = '';
		else div.style.filter = 'alpha(opacity: ' + Math.round(val * 100) + ')';
	} else {
		div.style.opacity = val;
	}
}


// 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.replace(window.location.hash,'');
}

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



if(!window.JSKW$Events){
        var JSKW$Events = new JSEC();
}

/////////////////////////////////////
// JS Event Class
/////////////////////////////////////
function JSEC() {
	this.contextHandles = [];
}

JSEC.prototype.registerEventCallback = function (contextHandle, eventHandle, eventName) {
	if(!contextHandle) {
		contextHandle = new JSECC(eventHandle, eventName);
		this.contextHandles.push(contextHandle);
		contextHandle.cHdlId = this.contextHandles.length - 1;
	} else {
		contextHandle.registerEventCallback(eventHandle, eventName);
	}
	return contextHandle;
}

JSEC.prototype.deRegisterEventCallback = function (contextHandle, eventHandle, eventName) {
	contextHandle.deRegisterEventCallback(eventHandle, eventName);
}

JSEC.prototype.syncBroadcast = function (eventName) {
	var args = arguments;
	JSKitLib.fmap(this.contextHandles, function(c){
		if(c) c.broadCast.apply(c, args);
	});
}

JSEC.prototype.asyncBroadcast = function (eventName) {
	var self = this;
	var args = arguments;
	setTimeout(function(){
		self.syncBroadcast.apply(self, args);
	}, 0);
}

JSEC.prototype.invalidateContext = function (contextHandle) {
	contextHandle.invalidateContext();
	delete this.contextHandles[contextHandle.cHdlId];
}

/////////////////////////////////////
// JS Event Context Class
/////////////////////////////////////
function JSECC(eventHandle, eventName) {
	this.registeredCallbacks = [];
	if(eventName || eventHandle) this.registerEventCallback(eventHandle, eventName);
}

JSECC.prototype.registerEventCallback = function (eventHandle, eventName) {
	var ev = eventName || '';
	if(!this.registeredCallbacks[ev]) this.registeredCallbacks[ev] = [];
	this.registeredCallbacks[ev].push(eventHandle);
}

JSECC.prototype.deRegisterEventCallback = function (eventHandle, eventName) {
	var ev = eventName || '';
	var self = this;
	if(!eventHandle) {
		delete this.registeredCallbacks[ev];
		return;
	}
	JSKitLib.fmap(this.registeredCallbacks[ev], function(evHdl, i){
		if(eventHandle==evHdl) {
			delete self.registeredCallbacks[ev][i];
		}
	});
	if(!this.registeredCallbacks[ev].length) delete this.registeredCallbacks[ev];
}

JSECC.prototype.invalidateContext = function () {
	this.registeredCallbacks = [];
	try {
		if(this.jsk$invalidate) this.jsk$invalidate();
	} catch(e) { ; };
}

JSECC.prototype.broadCast = function (eventName) {
	var self = this;
	var ar = [''];
	var args = arguments;
	if(eventName!='') ar.push(eventName);
	JSKitLib.fmap(ar, function(ev){
		if(self.registeredCallbacks[ev]) JSKitLib.fmap(self.registeredCallbacks[ev], function(evHdl){
			evHdl.apply(self, args);
		});
	});
}



//////////////////// JSRVC
// requestObj
// request: {uri: someuri, param1: val1, param2: val2, ...}
// [transport: ("GET" | "POST")]
// [target: some_DOM_element]
// [variableRequest: [{param1_1: val1_1, param1_2: val1_2, ...},
//			{param2_1: val2_1, param2_2: val2_2,...}, ...]]
// [form: some_form]
// [onreturn: some_callback]
// [randevu : (true | false)]
// [requestId: some request identity]

function JSRVC(requestObj) {
	var s = this;
	s.requestId = requestObj.requestId || s.generateRequestId();
	s.requestsInProgress = 0;
	s.requestsQueue = [];
	s.processRequest(requestObj);
}

JSRVC.prototype.generateRequestId = function() {
	return ((new Date()).valueOf() + Math.random()).toString();
}

JSRVC.prototype.processRequest = function(requestObj) {
	var s = this;
	s.error = undefined;
	if(s.requestsInProgress) {
		s.requestsQueue.push(requestObj);
		return;
	}
	s.requestObj = requestObj;
	if(s.requestObj.pickup && !s.eventCtx) s.eventCtx = JSKW$Events.registerEventCallback(s.eventCtx, function() {s.eventCallback.apply(s, arguments);}, "randevu_answer");
	var req = s.requestObj;
	s.preProcessRequest();
	if(!req.transport)
		req.transport = req.form ? "POST" : s.getRequestTransport();
	req.target = req.target || document.body;
	var onCompleteCB = req.timeout ? function() {
		s.startTimeoutTimer.call(s);
	} : undefined;
	var handlers = {'onload': s.onLoadRequest, 'onreadystatechange': s.onLoadRequest};
	switch(req.transport) {
	case "GET":
		s.processGETRequest(onCompleteCB, handlers);
		break;
	case "POST":
		s.processPOSTRequest(onCompleteCB, handlers);
		break;
	}
}

JSRVC.prototype.preProcessRequest = function() {
	var req = this.requestObj;
	if(!req.request) req.request = {};
	req.request.randevuId = this.requestId;
	if(!req.variableRequest) req.variableRequest = [];
	if(req.pickup) req.request.randevuRnd = Math.random();
}

JSRVC.prototype.calcGetRequest = function() {
	var s = this;
	var req = s.requestObj;
	var reqvar = req.variableRequest;
	var permGETReq = s.serializeRequest(req.request);
	var varGETReq = JSKitLib.fmap(reqvar, function(el, idx){
		return s.serializeRequest(el, '[' + idx + ']');
	});
	return [permGETReq, varGETReq];
}

JSRVC.prototype.getRequestTransport = function() {
	var ser = this.calcGetRequest();
	var permReq = ser[0];
	var varReq = ser[1];
	var firstReqLen = permReq.length +
		(varReq.length>0 ? varReq[0].length : 0);
	var totalReqLen = 0;
	for(var i=0; i<varReq.length; i++)
		totalReqLen += varReq[i].length;

	return ((firstReqLen > 1700) || (totalReqLen > 3400) ?
		"POST" : "GET");
}

JSRVC.prototype.startTimeoutTimer = function() {
	var s = this;
	s.timeoutTimer = setTimeout(function() { s.timeoutExpired(); }, s.requestObj.timeout);
}

JSRVC.prototype.timeoutExpired = function() {
	this.error = "timeout";
	this.returnAnswer();
}

JSRVC.prototype.returnAnswer = function(answerData) {
	var s = this;
	answerData = answerData || {};
	if(answerData.script) {
		var script = document.createElement('script');
		script.text = answerData.script;
		this.requestObj.target.appendChild(script);
	}
	if(s.requestObj.onreturn) {
		s.requestObj.onreturn.call(s, s.error || "data", answerData.data);
	}
}

JSRVC.prototype.serializeRequest = function(obj, prefix) {
	return JSKitLib.fmap(obj, function(v, k) {
		return encodeURIComponent(k) + (prefix || '') + "=" + encodeURIComponent(v);
       }).join("&");
}

JSRVC.prototype.setElementAttributes = function(obj, attrs) {
	var s = this;
	JSKitLib.fmap(attrs, function(v, k) {
		obj[k] = function() { v.call(s, obj) };
	});
}

JSRVC.prototype.runScript = function(src, data, handlers) {
	var script = document.createElement('script');
	this.setElementAttributes(script, handlers);
	script.setAttribute("charset", "utf-8");
	script.setAttribute("src",  src + (data ? '?' + data : ''));
	this.requestsInProgress++;
	this.requestObj.target.appendChild(script);
	this.script = script;
}

JSRVC.prototype.processGETRequest = function(onCompleteCB, handlers) {
	var s = this;
	var ser = s.calcGetRequest();
	var reqperm = ser[0];
	var reqpermlen = reqperm.length;
	var reqvar = ser[1];
	var reqvarlen = reqvar.length;
	var currequest = '';
	for(var i=0; i<reqvarlen; i++) {
		currequest += reqvar[i];
		if(currequest.length + reqpermlen +
			(i+1<reqvarlen ? reqvar[i+1].length : 0) > 2000) {
			s.runScript(s.requestObj.uri,
				reqperm + '&' + currequest, handlers);
			currequest = '';
		}
	}
	if((currequest) || (!reqvarlen))
		s.runScript(s.requestObj.uri,
			reqperm + '&' + currequest, handlers);
	if(onCompleteCB) onCompleteCB();
}

JSRVC.prototype.processPOSTRequest = function(onCompleteCB, handlers) {
	var s = this;
	var req = s.requestObj.request;
	var reqvar = s.requestObj.variableRequest;
	var reqvarlen = s.requestObj.variableRequest.length;
	var createForm = function() {
		var iframe = 'js-ifrm-' + Math.random();
		var div = document.createElement('DIV');
		div.innerHTML = '<iframe id="' +iframe+ '" name="'+iframe+'" width=0 height=0 style="border: none"></iframe>';
		s.requestObj.target.appendChild(div);
		var ifr = div.firstChild;
		var doc = ifr.contentDocument ? ifr.contentDocument : ifr.document;
		var f = doc.createElement('FORM');
		f.doc = doc;
		if(JSKitLib.isIE()) doc.charset = "utf-8";
		f.method  = 'POST';
		f.enctype = "application/x-www-form-urlencoded";
		f.acceptCharset = 'UTF-8';
		f.action  = s.requestObj.uri;
		f.target = iframe;
		doc.body.appendChild(f);
		return f;
	};
	var getForm = function() {
		return (s.form && !reqvarlen) ?
			s.form : createForm();
	}
	var fillForm = function(form, obj) {
		JSKitLib.fmap(obj, function(v, k) {
			var frmel = (form.doc || document).createElement('INPUT');
			frmel.type = "hidden";
			frmel.name = k;
			frmel.value = v;
			form.appendChild(frmel);
		});
	}
	var postRequest = function(pobj, vobj) {
		var form = getForm();
		fillForm(form, pobj);
		if(vobj) fillForm(form, vobj);
		s.setElementAttributes(document.getElementById(form.target), handlers);
		JSKitLib.fmap(handlers, function(v, k) {
			form[k] = v;
		});
		s.requestsInProgress++;
		form.submit();
	}
	JSKitLib.fmap(reqvar, function(v) {
		postRequest(req, v);
	});
	if(!reqvarlen) postRequest(req);
	if(onCompleteCB) onCompleteCB();
}

JSRVC.prototype.onLoadRequest = function(el) {
	var s = this;
	if(el.readyState && el.readyState != 'loaded'
		&& el.readyState != 'complete') return;
	el.onreadystatechange = el.onload = null;
	if(!s.requestObj.pickup) {
		s.requestObj.checked = true;
		s.requestsInProgress--;
	}
	s.postProcessRequest();
}

JSRVC.prototype.postProcessRequest = function(source, data) {
	var s = this;
	if(s.requestObj.pickup && source!="pickup") return;
	if(s.requestObj.randevu && !s.error && s.requestObj.transport == "POST") {
		s.processRequest({
			'uri': '//js-kit.com/api/server-answer.js',
			'pickup': true,
			'onreturn': s.requestObj.onreturn,
			'target': s.requestObj.target});
		return;
	}
	s.returnAnswer(data);
	if(!s.requestsInProgress) {
		if(s.timeoutTimer) clearTimeout(s.timeoutTimer);
		if(s.requestsQueue.length && !s.error)
			s.processRequest(s.requestsQueue.pop());
	}
}

JSRVC.prototype.eventCallback = function(eventName, randevuId, status, data) {
	if(this.requestId != randevuId) return;
	this.requestsInProgress--;
	if(this.script && this.script.parentNode) {
		this.script.parentNode.removeChild(this.script);
		this.script = undefined;
	}
	switch(status) {
	case "ready":
		if(this.eventCtx) {
			JSKW$Events.invalidateContext(this.eventCtx);
			this.eventCtx = undefined;
		}
		this.postProcessRequest("pickup", data);
		break;
	case "timeout":
		if(this.error) {
			this.returnAnswer(data);
		} else {
			this.processRequest(this.requestObj);
		}
		break;
	}
}

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


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

	this.config.isExtend = (this.config.partnerID == 'Userplane');

	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-ratingsExtend .js-rating-labelText': 'padding-top: '+(JSKitLib.isIE()?2:4)+'px; font-size: 11px; text-align: left; 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;',

	//new Extend skin
	'.js-ratingsExtend .js-rating-infoBoxStats': 'line-height: 12pt; padding: 0; font-size: 10pt; color: #c2c2c2;'
}

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;">Info su questo oggetto</div>'
 +  '<div class="js-rating-infoBoxStats">'
 +   '<div class="js-rating-infoBoxRatingsDisabled" style="display:none;">{Label:ratingsDisabled}<br></div>'
 +   '<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.dtInfoBoxExtended
 = '<div class="js-rating-infoBox" onselectstart="return false">'
 +  '<div class="js-rating-infoBoxStats">'
 +   '<div class="js-rating-infoBoxRatingsDisabled" style="display:none;">{Label:ratingsDisabled}<br></div>'
 +   '<span class="js-ratingInfoBoxTotalVotes">{avgStarRating}</span>'
 +   '<span class="js-ratingInfoBoxAvgRating" style="white-space: nowrap">{totalVotes}</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.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;
	var target = this.target;
	// wrapper for our floated elements
	var wrapper = this.cr('div');
	wrapper.className = "js-ratingWrapper";
	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();
	}

	var rating;
	var text;
	if(this.config.isExtend){
		var tmpl = JSKitLib.html(this.tmpl(this.dtExtend, []));
		var ctls = JSKitLib.mapClass2Object({}, tmpl);
		target = ctls["js-RatingStars"];
		this.extendTarget = target;
		if(this.target.getAttribute('title')) {
			this.target.setAttribute('title', '');
			var table = ctls["js-RatingStarsView"];
			if(table)
				table.setAttribute('title', this.config.title);
		}
		var nav = ctls["js-RatingNavView"];
		this.infoBox = new JSRTC(nav, { 'count': 3 }, this, {'skin': 'Extend'});
		text = ctls["js-RatingText"];
		rating = ctls["js-Rating"];
		var ads = ctls["js-RatingNavAd"];

		var div = document.createElement('div');
		var adId = Math.floor(Math.random()*99999999999);
		var ifrId = 'userplane-ad' + adId;
		div.innerHTML = '<iframe id="' + ifrId + '" name="' + ifrId + '" frameborder="0" marginwidth="0" marginheight="0" width="100%" height="0" src="about:blank"></iframe>';
		ads.appendChild(div);
		var iframe = div.firstChild;
		iframe.onreadystatechange = function() {
			if (iframe.readyState && iframe.readyState != 'loaded' && iframe.readyState != 'complete') {
				return;
			}
			iframe.contentWindow.location.href =  JSRC.DOMAIN + '/userplane_ad/' + adId;
			iframe.onreadystatechange = function() {
				if (iframe.readyState && iframe.readyState != 'loaded' && iframe.readyState != 'complete') {
					return;
				}
				iframe.onload = iframe.onreadystatechange = null;

				var onUserplaneAd = function(error, data) {
					if (error != "data") return;
					iframe.height = data.height;
				}
				new JSRVC({uri: JSRC.DOMAIN + '/api/server-answer.js', 'target': target, 'onreturn': onUserplaneAd, 'pickup': true, 'requestId': 'userplanead' + adId});
			};
			iframe.onload = iframe.onreadystatechange;
		}
		iframe.onload = iframe.onreadystatechange;
	}
	if (this.config.view.match(/split/)) {
		// split view : community and user ratings
		this.defaultView = 'user';
		var starRatingBar = this.initRating(this.objEffRating, 'star', false);
		var starRatingDiv = this.cr('div');
		starRatingDiv.className = 'js-starRatingDiv';
		starRatingDiv.style.width = this.ratingBarWidth + 'px';
		starRatingDiv.appendChild(starRatingBar);
		if(this.config.isExtend) text.appendChild(this.textTotal)
		else 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();
			if(this.config.isExtend) {
				text.appendChild(this.textRating)
				this.textRating.style.marginTop = '7px';
			} else this.userRatingDiv.appendChild(this.textRating);
			this.activeText = this.textRating;
		}
		if(this.config.isExtend) this.totalWidth = this.ratingBarWidth;
		else this.totalWidth = 2 * 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.config.isExtend) {
			this.textRating = this.cr('div');
			this.addClassStyle(this.textRating, 'js-rating-labelText');
			this.refreshTextRating();
			 if(this.config.isExtend) text.appendChild(this.textRating)
			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/)) {
				if(this.config.isExtend) text.appendChild(this.textTotal)
				else this.userRatingDiv.appendChild(this.textTotal);
			} else {
				this.userRatingBar.style.top = this.starHeight + 'px';
				this.textTotal.style.height = this.starHeight + 'px';
				if (this.config.isExtend) {
					this.userRatingDiv.style.height = this.starHeight + 'px';
					text.appendChild(this.textTotal);
				} else {
					this.userRatingDiv.style.height = 2 * 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' && !this.config.isExtend) {
		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 = target.style.width || targetMinWidth;
		if (parseInt(targetWidth) <= targetMinWidth)
			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";
	JSKitLib.addChild(target, tableWrapper); // stars
	if(rating) JSKitLib.addChild(this.target, rating);

	if(this.config.view.match(/score/)){
		this.totalWidth=6+2*this.starWidth+this.contentBoxElUp.offsetWidth+this.contentBoxElDown.offsetWidth;
		var targetMinWidth;
		if(this.config.isExtend)
			targetMinWidth = this.totalWidth;
		else 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 = target.style.width || targetMinWidth;
		if (parseInt(targetWidth) <= targetMinWidth)
			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();
	}

	var trIfrId = 'jsk-ifrtr-r';
	JSKitLib.addEventHandler(window, ['onload'], function() {
		if (document.getElementById(trIfrId)) return;
		var div = self.cr('div');
		div.innerHTML = '<iframe id="' + trIfrId + '" name="' + trIfrId + '" src="' + JSRC.DOMAIN + '/api/static/landing.html" frameborder="0" height="0" width="0"></iframe>';
		self.target.appendChild(div);
	});
}

// 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.config.isExtend) {
	JSKitLib.removeChildren(this.infoBox.target);
	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(JSKitLib.html(content));

  } else {
    box.appendChild(content);
  }

  wrapper.appendChild(box);


  return wrapper;

}

JSRC.prototype.createInfoBox = function() {

	var self = this;
	var ext = self.config.isExtend;
        var vars = {
                totalVotes: this.getTextForTotalVotes(this.objNum),
                avgStarRating: (function() {
                	if(self.config.view.match(/score/)){
                		if(self.objNum){
					var up = (self.objSum-self.objNum*self.raterInc)/(self.scale-self.raterInc);
					var down = self.objNum-((self.objSum-self.objNum*self.raterInc)/(self.scale-self.raterInc));
                			return (ext?$JRL('avgRatingExtend')+': '+$JRL('up')+': <b>'+up+'</b>, '+$JRL('down')+': <b>'+down+'</b> by '
						    : '('+$JRL('up')+': '+up+', '+$JRL('down')+': '+down+')');
                		} else {
                			return '';
                		}
                	} else {
                		return self.objAvgStarRating > 0
					? (ext?$JRL('avgRatingExtend')+' <b>'+JSKitLib.zeroPad(self.objAvgStarRating, 2)+'</b> by '
					      :'(' + 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 = JSKitLib.html(this.tmpl(this.config.isExtend ? JSRC.prototype.dtInfoBoxExtended : JSRC.prototype.dtInfoBox, vars));
	var ctls = JSKitLib.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 self = this;
  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) : "")
	);
  setTimeout(function(){
	if(!self.infoBox) return;
	var data = "app=mininav&jx="+self.infoBox.jtaIndex+"&count="
			+self.infoBox.config.inline.count;
	self.infoBox.server("bestof", "-data.js", data)}
  , 1000);
}

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 if(this.config.isExtend) {
		var text = (this.objAvgStarRating && this.objNum) ?
		  "Rated "+JSKitLib.zeroPad(this.objAvgStarRating,2)+" ("+this.getTextForTotalVotes(this.objNum)+")" : $JRL('unrated');
		this.setTextTotal(text);
	} 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 target = self.extendTarget || self.target;
	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=JSKitLib.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=JSKitLib.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.isExtend)
                        targetMinWidth = this.totalWidth;
		else 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 = target.style.width || targetMinWidth;
		if(delta>0) {
			if (parseInt(targetWidth) <= targetMinWidth) {
				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) {
				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;
  this.config.isExtend = this.config.isExtend || community.isExtend;
  if(this.config.isExtend) JSKitLib.addClass(this.target, "js-ratingsExtend");

  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-ratingWrapper': 'position: relative; margin: 3px;',
	'.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': '',
	'.js-starRatingDiv': 'float: left; margin: 0px 10px 0px 0px;',

	// 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;',

	// New Extend skin .js-ratingsExtend

	'.js-Rating': 'border: 3px solid #ececec; font-family: sans-serif; background-color: #FFFFFF;',
	'.js-RatingData': 'padding: 7px;',
	'.js-RatingData table': 'border: 0px; border-collapse: collapse;',
	'.js-RatingData table td': 'padding: 0px;',
	'.js-RatingText': 'margin-left: 5px; color: #a3a3a3',
	'.js-RatingNavAd': 'font-size: 9pt; margin-top: 5px; zoom: 1;',
	'.js-RatingNavView': 'margin-top: 13px;',
	'.js-ratingsExtend .js-ratingWrapper': 'position: relative; margin: 3px 3px 3px 0px;',
	'.js-ratingsExtend .js-rTopNav': 'border-bottom: 1px solid #ebebeb; font-size: 8pt; font-weight: normal;',
	'.js-ratingsExtend .js-rTopNavTabActive': 'background-color: #ebebeb; color: #767676;',
	'.js-ratingsExtend .js-rTopNavTab': 'padding: 2px 4px; height: auto; margin: 0px; border: none; background-image: none;',
	'.js-ratingsExtend .js-rTopNavTabWrap': 'float:none;',
	'.js-ratingsExtend .js-rTop': 'padding: 0px; border: none; font-size: 9pt',
	'.js-ratingsExtend .js-rTopView': 'background: none; margin: 0px; padding: 0px',
	'.js-ratingsExtend .js-rTopBody': 'border-bottom: 1px solid #ebebeb; padding: 5px 0px 7px 0px;',
	'.js-ratingsExtend .js-rTopFrame': 'background: transparent; border: none; padding: 0; margin: 0; -moz-user-select: none; -webkit-box-shadow: none; ',
	'.js-ratingsExtend .js-starRatingDiv': 'margin: 0px 0px 7px 0px;',


	// New Extend skin Top rated .js-ratingsExtend
	'.js-ratingsExtend .js-rTopItem': 'padding: 0px;',
	'.js-ratingsExtend .js-rTopItem table': 'table-layout: fixed; width: 100%;',
	'.js-ratingsExtend .js-rTopItemRating': 'color: #c2c2c2; margin-left: 5px;',
	'.js-ratingsExtend .js-rTopItemLink': 'white-space: nowrap; margin-right: 5px; color: #3366ff; font-size: 9pt; text-decoration: none',

	// New Extend skin Hot
	'.js-ratingsExtend .js-rTopHotItem': 'padding: 0px;',
	'.js-ratingsExtend .js-rTopHotItemInfo': 'color: #c2c2c2',
	'.js-ratingsExtend .js-rTopHotItemLink': 'white-space: nowrap; color: #3366ff; font-size: 9pt; text-decoration: none',

	// New Extend Top Score .js-ratingsExtend
	'.js-ratingsExtend .js-rTopScoreItem': 'color: #3d6883; padding: 0px;',
	'.js-ratingsExtend .js-rTopScoreItemInfo': 'font-size: 8pt;',
	'.js-ratingsExtend .js-rTopScoreItemStars': 'margin-right: 5px;',
	'.js-ratingsExtend .js-rTopScoreItemRate': 'width: 30px; margin-top: 3px',
	'.js-ratingsExtend .js-rTopScoreItemLink': 'white-space: nowrap; color: #3366ff; text-decoration: none',
	'.js-ratingsExtend .js-rTopItemScoreRating': 'margin-left: 5px; color: #c2c2c2',

	//New Extend skin Footter in navigator .js-ratingsExtend
	'.js-ratingsExtend .js-rTopFooter': 'display: none;',
	'.js-ratingsExtend .js-RatingPoweredBy': 'width: 100%; text-align: right; background-color: #fbfbfb; font-size:8pt; padding: 3px 0;',
	'.js-ratingsExtend .js-rTopPoweredByLink': 'color: #c7c7c7; font-family: Arial; padding-right: 5px; text-decoration: 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;',
	'div.js-rTopItem table': 'border: 0px; border-collapse: collapse;',
	'div.js-rTopItem table td': 'padding: 0px;',
	'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; font-size:12pt; font-weight: bold;',
	'div.js-rTopBodyAdminMsgBody': '',

	'.js-ratingsExtend .js-rTopBodyAdminMsgHeader': 'font-size:9pt;',
	'.js-ratingsExtend .js-rTopFont': 'font-size:9pt;'

}

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

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

}

JSRC.prototype.dtExtend
 = '<div class="js-Rating">'
     +'<div class="js-RatingData">'
       + '<table class="js-RatingStarsView"><tbody><tr>'
         + '<td><div class="js-RatingStars"></div></td>'
         + '<td><div class="js-RatingText"></div></td>'
       + '</tbody></tr></table>'
       + '<div class="js-RatingNavView"></div>'
       + '<div class="js-RatingNavAd"></div>'
     +'</div>'
     + '<div class="js-RatingPoweredBy">'
       + '<a class="js-rTopPoweredByLink" target="_blank" href="http://www.userplane.com/index.cfm?fuseaction=apps.partners">Powered by JS-Kit</a>'
     + '</div>'
'</div>';

// TODO: templates should all be dynamic
JSRTC.prototype.getMainTemplate = function(skin) {
	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>'
	   + '<div style="clear:both;"></div>'
	  + '</div>'  // js-rTopBg
	 + '</div>'  // js-rTop
	+ '</div>' ;
	return html;
}

JSRTC.prototype.dtBodyAdminMsg
 = '<div class="js-rTopBodyAdminMsg">'
  + '<div class="js-rTopBodyAdminMsgHeader">'
   + '<span>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.getdtBodyTop = function(){
	var html;
	if(this.xOpts.skin == "Extend")
		html
		 = '<div class="js-rTopTop">'
		  + '<div class="js-rTopItems">'
		   + '<div class="js-rTopItem">'
		     + '<table><tbody><tr>'
		      + '<td style="width: 50px"><div class="js-rTopItemStars"></div></td>'
		      + '<td><div style="overflow:hidden; width:100%; white-space:nowrap; '+(JSKitLib.isIE()?'height: 1.3em;':'')+'"><a class="js-rTopItemLink" href="{url}">{title}</a></div></td>'
		      + '<td style="width:75px;"><span class="js-rTopItemRating js-rTopDetailFont">{rating}&nbsp;({votes})</span></td>'
		     + '</tr></tbody></table>'
		   + '</div>'
		  + '</div>'
		 + '</div>';
	else
		html
		 = '<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;">I pił votati del sito</div>'
		  + '<div class="js-rTopItems">'
		   + '<div class="js-rTopItem">'
		    + '<a class="js-rTopItemLink js-rTopFont" href="{url}">{title}</a>'
		    + '<div class="js-rTopItemInfo">'
		     + '<table><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>';
	return html;
}

JSRTC.prototype.getdtBodyTopScore = function(){
        var html;                                                                                                                             if(this.xOpts.skin == "Extend")
		html
		 = '<div class="js-rTopTopScore">'
		  + '<div class="js-rTopScoreItems">'
		   + '<div class="js-rTopScoreItem">'
		    + '<div class="js-rTopScoreItemInfo">'
		     + '<table cellspacing="0" cellpadding="0" border="0"><tbody><tr>'
		       + '<td valign="middle"><div class="js-rTopScoreItemStars"></div></td>'
		       + '<td><div class="js-rTopScoreItemRate"><b>{rating}</b></div></td>'
		       + '<td><a class="js-rTopScoreItemLink js-rTopFont" href="{url}">{title}</a></td>'
		      + '<td><span class="js-rTopItemScoreRating js-rTopDetailFont">({votes})</span></td>'
		     + '</td></tr></tbody></table>'
		    + '</div>'
		   + '</div>'
		  + '</div>'
		 + '</div>';
	else
		html
		 = '<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;">I pił votati del sito</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>';
	return html;
}

JSRTC.prototype.getdtBodyHot = function(){
        var html;
        if(this.xOpts.skin == "Extend")
		html
		 = '<div class="js-rTopHot">'
		   + '<div class="js-rTopHotItems">'
		    + '<div class="js-rTopHotItem">'
		     + '<a class="js-rTopHotItemLink js-rTopFont" href="{url}">{title}</a>'
		     + '<span class="js-rTopHotItemInfo js-rTopDetailFont"> ({votes})</span>'
		    + '</div>'
		   + '</div>'
		  + '</div>'
	else
		html
		 = '<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;">I pił Hot del sito</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>';
	return html;
}

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;">Il mio voto</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;">I miei voti pił recenti</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;">Il mio voto</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;">I miei voti pił recenti</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.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:"Miei", active:((this.xOpts.skin=="Extend")?false: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 skin = this.xOpts.skin || "";
	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 skin = this.xOpts.skin || "";
	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');
		if(skin!="Extend") td.setAttribute('width', width + '%');

		var tabWrap = this.cr('div');
		tabWrap.className = "js-rTopNavTabWrap";
		if(skin!="Extend") 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) {
			if(skin!="Extend") 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);
	if(skin!="Extend") 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 skin = this.xOpts.skin || "";
	var body = JSKitLib.html(this.getdtBodyTop());
	var ctls = JSKitLib.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 = JSKitLib.html(self.tmpl(tTemplate, item));
		if (idx % 2 != 0 && skin != "Extend") JSKitLib.addClass(idiv, "js-rTopRowColor2");
		var ictls = JSKitLib.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) {
			JSKitLib.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 skin = this.xOpts.skin || "";
	var body = JSKitLib.html(this.getdtBodyTopScore());
	var ctls = JSKitLib.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 = JSKitLib.html(self.tmpl(tTemplate, item));
		if (skin!="Extend" && idx % 2 != 0) JSKitLib.addClass(idiv, "js-rTopRowColor2");
		var ictls = JSKitLib.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) {
			JSKitLib.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 = JSKitLib.html(this.dtBodyUser);
	var ctls = JSKitLib.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 = JSKitLib.html(self.tmpl(tThisTemplate, item));
		var ictls = JSKitLib.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 = JSKitLib.html(self.tmpl(tTemplate, item));
		if (idx % 2 != 0) JSKitLib.addClass(idiv, "js-rTopRowColor2");
		var ictls = JSKitLib.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)
				JSKitLib.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)
				JSKitLib.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 = JSKitLib.html(this.dtBodyUserScore);
	var ctls = JSKitLib.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 = JSKitLib.html(self.tmpl(tThisTemplate, item));
		var ictls = JSKitLib.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 = JSKitLib.html(self.tmpl(tTemplate, item));
		if (idx % 2 != 0) JSKitLib.addClass(idiv, "js-rTopRowColor2");
		var ictls = JSKitLib.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)
				JSKitLib.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)
				JSKitLib.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 = JSKitLib.html(this.dtBodyAdminMsg);
	var ctls = JSKitLib.mapClass2Object({}, body);

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

	msgBody.innerHTML = msg;

	return body;
}

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

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

	msgBody.innerHTML = msg;

	return body;
}

JSRTC.prototype.createBodyHot = function(navData) {

	var self = this;
	var skin = this.xOpts.skin || "";

	var body = JSKitLib.html(this.getdtBodyHot());
	var ctls = JSKitLib.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 = JSKitLib.html(self.tmpl(hTemplate, item));
		if (skin!="Extend" && idx % 2 != 0) JSKitLib.addClass(idiv, "js-rTopRowColor2");
		var ictls = JSKitLib.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) {
			JSKitLib.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 skin = this.xOpts.skin || "";

	var template = this.getMainTemplate(skin);

	var pdiv = JSKitLib.html(this.tmpl(template, navData));
	var ctls = JSKitLib.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 = '';
	JSKitLib.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);

}
