/**
* @author Ryan Johnson
* @copyright 2008 PersonalGrid Corporation
* @package LivePipe UI
* @license MIT
* @url http://livepipe.net/control/rating
* @require prototype.js, livepipe.js
*/
/*global document, Prototype, Ajax, Class, Event, $, $A, $F, $R, $break, Control */
if(typeof(Prototype) == "undefined") {
throw "Control.Rating requires Prototype to be loaded."; }
if(typeof(Object.Event) == "undefined") {
throw "Control.Rating requires Object.Event to be loaded."; }
Control.Rating = Class.create({
initialize: function(container,options){
Control.Rating.instances.push(this);
this.value = false;
this.links = [];
this.container = $(container);
this.container.update('');
this.options = {
min: 1,
max: 5,
rated: false,
input: false,
reverse: false,
capture: true,
multiple: false,
classNames: {
off: 'rating_off',
half: 'rating_half',
on: 'rating_on',
selected: 'rating_selected'
},
updateUrl: false,
updateParameterName: 'value',
updateOptions : {},
afterChange: Prototype.emptyFunction
};
Object.extend(this.options,options || {});
if(this.options.value){
this.value = this.options.value;
delete this.options.value;
}
if(this.options.input){
this.options.input = $(this.options.input);
this.options.input.observe('change',function(input){
this.setValueFromInput(input);
}.bind(this,this.options.input));
this.setValueFromInput(this.options.input,true);
}
var range = $R(this.options.min,this.options.max);
(this.options.reverse ? $A(range).reverse() : range).each(function(i){
var link = this.buildLink(i);
this.container.appendChild(link);
this.links.push(link);
}.bind(this));
this.setValue(this.value || this.options.min - 1,false,true);
},
buildLink: function(rating){
var link = $(document.createElement('a'));
link.value = rating;
if(this.options.multiple || (!this.options.rated && !this.options.multiple)){
link.href = '';
link.onmouseover = this.mouseOver.bind(this,link);
link.onmouseout = this.mouseOut.bind(this,link);
link.onclick = this.click.bindAsEventListener(this,link);
}else{
link.style.cursor = 'default';
link.observe('click',function(event){
Event.stop(event);
return false;
}.bindAsEventListener(this));
}
link.addClassName(this.options.classNames.off);
return link;
},
disable: function(){
this.links.each(function(link){
link.onmouseover = Prototype.emptyFunction;
link.onmouseout = Prototype.emptyFunction;
link.onclick = Prototype.emptyFunction;
link.observe('click',function(event){
Event.stop(event);
return false;
}.bindAsEventListener(this));
link.style.cursor = 'default';
}.bind(this));
},
setValueFromInput: function(input,prevent_callbacks){
this.setValue($F(input),true,prevent_callbacks);
},
setValue: function(value,force_selected,prevent_callbacks){
this.value = value;
if(this.options.input){
if(this.options.input.options){
$A(this.options.input.options).each(function(option,i){
if(option.value == this.value){
this.options.input.options.selectedIndex = i;
throw $break;
}
}.bind(this));
}else {
this.options.input.value = this.value; }
}
this.render(this.value,force_selected);
if(!prevent_callbacks){
if(this.options.updateUrl){
var params = {}, a;
params[this.options.updateParameterName] = this.value;
a = new Ajax.Request(this.options.updateUrl, Object.extend(
this.options.updateOptions, { parameters : params }
));
}
this.notify('afterChange',this.value);
}
},
render: function(rating,force_selected){
(this.options.reverse ? this.links.reverse() : this.links).each(function(link,i){
if(link.value <= Math.ceil(rating)){
link.className = this.options.classNames[link.value <= rating ? 'on' : 'half'];
if(this.options.rated || force_selected) {
link.addClassName(this.options.classNames.selected); }
}else {
link.className = this.options.classNames.off; }
}.bind(this));
},
mouseOver: function(link){
this.render(link.value,true);
},
mouseOut: function(link){
this.render(this.value);
},
click: function(event,link){
this.options.rated = true;
this.setValue((link.value ? link.value : link),true);
if(!this.options.multiple) {
this.disable(); }
if(this.options.capture){
Event.stop(event);
return false;
}
}
});
Object.extend(Control.Rating,{
instances: [],
findByElementId: function(id){
return Control.Rating.instances.find(function(instance){
return (instance.container.id && instance.container.id == id);
});
}
});
Object.Event.extend(Control.Rating);