/*
 * Copyright (c) 2007 JS-Kit.com. All rights reserved.
 * $Date: 2007-08-03 17:01:48 -0700 (Fri, 03 Aug 2007) $
 */

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

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

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

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

JSKitLib.preloadImg = function(imgURL) { (new Image()).src = imgURL; };

var JSKitGlobal = function() {

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

  this._isAppAvailable = function(app) {
    return (this._appAvailable[app]) ? true : false;
  }
    
  this.isRatingsAppAvailable = function() {
    return this._isAppAvailable('ratings');
  }

  this.isCommentsAppAvailable = function() {
    return this._isAppAvailable('comments');
  }

  this._setAppAvailable = function(app) {
    this._appAvailable[app] = true;
    /* index this app */
    this.indexAppObjects(app);
    /* execute any queued actions */
    this.executeAppObjectActions(app);
  }

  this.setRatingsAppAvailable = function() {
    this._setAppAvailable('ratings');
  }
  this.setCommentsAppAvailable = function() {
    this._setAppAvailable('comments');
  }

  this.indexAppObjects = function(app) {

    if (app == 'ratings') {
      var appArray = $JRA;
    } else if (app == 'comments') {
      var appArray = $JCA;
    } else {
      alert('Attempt to index invalid app type');
      return;
    }

    for (var i=0; i < appArray.length; i++) {
      // Check that it's not standalone
      if (appArray[i].isStandalone()) {
        continue;
      }
      var uniq = appArray[i].uniq;
      if ( ! this._appObjects[uniq] ) {
        this._appObjects[uniq] = {};
      }
      if ( ! this._appObjects[uniq][app]) {
        this._appObjects[uniq][app] = [];
      }
      this._appObjects[uniq][app].push(appArray[i]);
    }
  }

  this.executeAppObjectActions = function(app) {
    if (this._appObjectActions[app]) {
      for (var i=0; i < this._appObjectActions[app].length; i++) {
        var uniq = this._appObjectActions[app][i].uniq;
        if (this._getAppObject(app, uniq)) {
          this._appObjectActions[app][i].action();
        }
      }
    }
  }

  this._getAppObject = function(app, uniq) {
    if (this._appObjects[uniq] && this._appObjects[uniq][app]) {
      return this._appObjects[uniq][app][0];  // Return only the first
    }
    return null;
  }

  this.getCommentsAppObject = function(uniq) {
    return this._getAppObject('comments', uniq);
  }

  /* Returns a Ratings Object */
  this.getRatingsAppObject = function(uniq) {
    return this._getAppObject('ratings', uniq);
  }

  this.copyRatingsAppObject = function(uniq, node) {
    if ( ! this.isRatingsAppAvailable()) {
      return;
    }

    var oldObj = this.getRatingsAppObject(uniq);
    var newObj = oldObj.clone(node, { 'view' : 'user', 'commentprompt' : 'no' } );

    return newObj;
  }

  this._tryAppObjectAction = function(app, uniq, action) {
    if (this._isAppAvailable(app)) {
      if (this._getAppObject(app, uniq)) {
        action();
      }
    } else {

      if ( ! this._appObjectActions[app]) {
        this._appObjectActions[app] = [];
      }
      this._appObjectActions[app].push( { 'uniq' : uniq, 'action' : action } );
    }
  }

  this.tryRatingsAppObjectAction = function(uniq, action) {
    this._tryAppObjectAction('ratings', uniq, action);
  }

  this.tryCommentsAppObjectAction = function(uniq, action) {
    this._tryAppObjectAction('comments', uniq, action);
  }

}

/* Singleton-like handler */
JSKitGlobal.getInstance = function() {
  if ( ! window.JSKitGlobalInstance) {
    JSKitGlobalInstance = new JSKitGlobal();
  }
  return JSKitGlobalInstance;
}


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

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

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

  this.uri = 'http://js-kit.com/rating';
  this.baseStarURI = 'http://js-kit.com/images/stars/';
  this.pathOverride = '';
  this.config = {};
  this.raterInc = 2;  // Increment ratio of rateable v. displayable
  this.scale    = 10; // Points on rating scale

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

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

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

  var idName = 'js-kit-rating';

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

  if (target) {

    this.target = target;

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

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

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

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

    this.defineIcons();

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

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

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

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

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

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

}

JSRC.prototype.defineIcons = function() {

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

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

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

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

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

  }

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

/* Create our global JSKit object */
$JSKitGlobal = JSKitGlobal.getInstance();

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


/* CSS Stylings */
document.write('<style type="text/css">'
  + '.js-rating-labelText { padding-top: 2px; font-size: 11px; text-align: center; cursor: default }'
  + '.js-rating-splitObjectRating { margin-right: 10px; }'
  + '.js-rating-afterRating { background-color: #eee; margin-left: 10px; float: left; width: 100px; font-size: 12px; text-align: center; border: 1px solid #aaa; padding: 2px 0;}'
  + '</style>'
);

/* 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.display = function() {

  this.userRatingBar = this.initRating(this.userRating, 'user', true);
  this.userRatingBar.style.cursor = 'pointer';

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

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

  // wrapper for our floated elements
  var wrapper = this.cr('div');
  wrapper.style.margin = '3px';
  wrapper.style.position = 'relative';
  wrapper.style.cssFloat = 'left'; 
  wrapper.style.styleFloat = 'left'; 

  if (this.config.view.match(/split/)) {
    /* Side by Side Ratings */
    this.defaultView = 'user';

    var starRatingBar = this.initRating(this.objEffRating, 'star', false);
    var starRatingDiv = this.cr('div');
        starRatingDiv.className = 'js-rating-splitObjectRating';
        starRatingDiv.style.cssFloat = 'left';
        starRatingDiv.style.styleFloat = 'left';
        starRatingDiv.style.width = this.ratingBarWidth + 'px';
        starRatingDiv.appendChild(starRatingBar);
        starRatingDiv.appendChild(this.textTotal);

    wrapper.appendChild(starRatingDiv);

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

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

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

    wrapper.appendChild(this.userRatingDiv);

  } else if (this.config.view.match(/user/)) {
    this.defaultView = 'user';

    this.userRatingDiv.style.width = this.ratingBarWidth + 'px';

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

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

    wrapper.appendChild(this.userRatingDiv);

  } else {
    /* Single Rating View */
    this.defaultView = 'star';

    this.userRatingDiv.style.width = this.ratingBarWidth + 'px';

    this.userRatingDiv.appendChild(this.textTotal);
    this.activeText = this.textTotal;
    this.totalWidth = this.ratingBarWidth + 10;

    wrapper.appendChild(this.userRatingDiv);
  }

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

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

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

    var self = this;
    var addCommentPrompt = function() {
      var afterRatingA = document.createElement('a');
      afterRatingA.appendChild(document.createTextNode('Add a comment to your rating'));
      afterRatingA.onclick = function() { 
        self.getCommentsAppObject().ShowCommentDialog(null);
        return false;
      };
      afterRatingA.href = '';
  
      var afterRatingDiv = document.createElement('div');
      afterRatingDiv.appendChild(afterRatingA);
      afterRatingDiv.className = 'js-rating-afterRating';
      afterRatingDiv.style.display = 'none';
      afterRatingDiv.style.position = 'absolute';

      afterRatingDiv.style.left = self.totalWidth + 'px';
      afterRatingDiv.style.top = '-3px';
      
      self.addOnRate(function() { 
        afterRatingDiv.style.display = ''; 
        setTimeout(function() { afterRatingDiv.style.display = 'none'; }, 5000);
      });
  
      wrapper.appendChild(afterRatingDiv);
    }
    $JSKitGlobal.tryCommentsAppObjectAction(this.uniq, addCommentPrompt); 
  }

  // Clear our floats
  var clear = this.cr('div');
  clear.style.clear = 'both';

  this.target.appendChild(wrapper);
  this.target.appendChild(clear);

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

  
}

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

JSRC.prototype.rate = function(givenRating) {
  var oldRating = this.userRating;
  this.setUserRating(givenRating);
  var objSum = this.objSum;
  var objNum = this.objNum;
  if(oldRating) {
    objSum -= oldRating;
    objNum --;
  }
  this.setTmpText('Thank you!');

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

  // Handle any callbacks
  this.processOnRate();

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

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

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

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

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

JSRC.prototype.getObjIcons = function() {

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

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

JSRC.prototype._getIcons = function(iconClass) {

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


JSRC.prototype.refreshTextTotal = function() {
  var text = this.objNum;
  switch(this.objNum) {
  case 0: text = "Unrated"; break;
  case 1: text += " user vote"; break;
  default: text += " user votes"; break;
  }
  if(this.userRating && 0) {
	text += "; yours: " + (this.userRating / this.raterInc);
  }
  this.setTextTotal(text);
}

JSRC.prototype.refreshTextRating = function(text) {
  if (this.userRating) {
    var text = 'Your Rating: ' + (this.userRating / this.raterInc);
  } else { 
    var text = 'Your Rating';
  }
  this.setTextRating(text);
}

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

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

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

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

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

}

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

	if(document.body.filters) {
		star.runtimeStyle.filter
		= "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
		+ imageURL + "', sizingMethod='crop')"
	} else {
		star.style.backgroundImage = 'url(' + imageURL + ')';
	}
}

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

  if(this.tmpTextTimer) return;

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

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

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

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

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

  var icons = this.getRatingIcons();

  this._refreshRating(type, comparison, icons);

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

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

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

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

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

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

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

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

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

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

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

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

  return clone;
}

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

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

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

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

