function createRating(slot,url,canRate){
   bindMethods(this);
   if(!$(slot))
       slot = SPAN(null)
   this.rate = 0;
   this.call_backs = {}
   this.prefix = slot;
   this.slot = $(slot); 
   this.url = url
   if (canRate)
       this.canRate = true;
   else
       this.canRate = false;
   this.stars = [];

   for(i = 1; i< 6 ; i++){
       if ( i <= this.rate)
           img = "ajax_images/star_on.gif"
       else
           img = "ajax_images/star_off.gif"
       this.stars[i] = IMG({'id':this.prefix+'-star-'+i,'src':img,'class':i})
       appendChildNodes(this.slot,this.stars[i])
       if (this.canRate){
           addToCallStack(this.stars[i],'onclick',this.setRating)
           addToCallStack(this.stars[i],'onmouseover',this.changeRating)
           addToCallStack(this.stars[i],'onmouseout',this.changeRating)
       }
   }
   this.message = SPAN({'id':this.prefix+'message','class':'rating-message'}, 'Loading ...')
   appendChildNodes(this.slot,this.message)
   this.getRating();
}


createRating.prototype.changeRating = function (event){
    if(window.event)
        event = window.event
    if (event.type == 'mouseover'){
        if(event.target){
            ele = event.target;
        }
        else if (event.srcElement){
            ele = event.srcElement;            
        }
        else{
            return;
        }
        if (ele.className){
            rate = ele.className;
        }else{
            rate = ele.getAttribute('class');
        }
        if (rate)
           rate = rate.split(',');
        for (i = 0; i <rate.length;i++){
            if (rate[i]>0 && rate[i]<6) {
                this.updateStars(Number(rate[i]));
                break;
            }
        }
    }
    else if (event.type == 'mouseout'){
        this.updateStars(this.rate);
    }
}
createRating.prototype.render = function () {
    return this.slot
}
createRating.prototype.setRating = function (event){
    if(window.event)
        event = window.event
    if(event.target){
        ele = event.target;
    }
    else if (event.srcElement){
        ele = event.srcElement;            
    }
    else{
        return;
    }
    if (ele.className){
       rate = ele.className;
    }else{
        rate = ele.getAttribute('class');
    }
    this.old_rate = this.rate
    if (rate)
    rate = rate.split(',');
    for (i = 0; i <rate.length;i++){
        if (Number(rate[i])) {
            this.rate = Number(rate[i]);
            this.updateStars(this.rate);
            break;
        }
    }
    this.submit(); 
}

createRating.prototype.getRating= function (){
    if (!this.url)
        return;
    this.req = loadJSONDoc(this.url+'/getRate')
    this.req.addCallback(this.processInit);
    this.req.addErrback(this.processError);
}


createRating.prototype.processInit= function (rate){
    this.rate = rate;
    this.updateStars(this.rate);
    swapDOM($(this.prefix+'message'),SPAN({'id':this.prefix+'message','class':'rating-message'},''))
}

createRating.prototype.submit= function (){
    if (!this.message){
        this.message = SPAN({'id':this.prefix+'message','class':'rating-message'},'')
         appendChildNodes = (slot,this.message);
    }
    swapDOM($(this.prefix+'message'),SPAN({'id':this.prefix+'message','class':'rating-message'}, 'Submitting ...'))
    this.req = loadJSONDoc(this.url+'/submitRating?rating='+this.rate)
    this.req.addCallback(this.processSubmit);
    this.req.addErrback(this.processError);
}
createRating.prototype.registerCallback = function (ev,func){
    
    if (func && typeof func == 'function'){
        if (!this.call_backs[ev]){
            this.call_backs[ev] = []
        }
        this.call_backs[ev][this.call_backs[ev].length] = func
    }

}
createRating.prototype.processError = function (err){
    logFatal(err);
}

createRating.prototype.processSubmit = function (result){
    if ( result.done  == 'true' ){
        swapDOM($(this.prefix+'message'),SPAN({'id':this.prefix+'message','class':'rating-message'}, 'Your rating has been submitted successfully'))
    }
    else{
        swapDOM($(this.prefix+'message'),SPAN({'id':this.prefix+'message','class':'rating-message'}, 'There was some error while submitting'))
        if (this.old_rate){
            this.rate = this.old_rate;
            this.updateStars(this.rate);
        }
    }
    /* running all callbacks */
    if (this.call_backs['process_submit']){
        for (var i = 0 ; i < this.call_backs['process_submit'].length ; i++){
            this.call_backs['process_submit'][i]()
        }
    }
}

createRating.prototype.updateStars = function (rate){
    rate = Number(rate);
    for (i =1; i< 6 ; i++){
        if ( i <= rate){
            img = "ajax_images/star_on.gif"
        }
        else{
            img = "ajax_images/star_off.gif"
        }
        this.stars[i].src = img;
    }
}


function createAvgRating(slot,url){
    logDebug("createAvgRating")
   bindMethods(this);
   if(!$(slot))
       slot = SPAN(null)
   this.rate = 0;
   this.prefix = slot;
   this.slot = $(slot); 
   this.url = url

   this.stars = [];

   for(i = 1; i< 6 ; i++) {
       if ( i <= this.rate)
           img = "ajax_images/star_on.gif"
       else
           img = "ajax_images/star_off.gif"
       this.stars[i] = IMG({'id':this.prefix+'-star-'+i,'src':img,'class':i})
       appendChildNodes(this.slot,this.stars[i])
    }
   this.getRating();
}

createAvgRating.prototype.getRating= function (){
    if (!this.url)
        return;
    this.req = loadJSONDoc(this.url+'/getAvgRate')
    this.req.addCallback(this.processInit);
    this.req.addErrback(this.processError);
}

createAvgRating.prototype.processInit= function (rate){
    this.rate = rate;
    this.updateStars(this.rate);
    swapDOM($(this.prefix+'message'),SPAN({'id':this.prefix+'message','class':'rating-message'},''))
}

createAvgRating.prototype.render = function () {
    return this.slot
}
createAvgRating.prototype.updateStars = function (rate){
    rate = Number(rate);
    for (i =1; i< 6 ; i++){
        if ( i <= rate){
            img = "ajax_images/star_on.gif"
        }
        else{
            img = "ajax_images/star_off.gif"
        }
        this.stars[i].src = img;
    }
}
