app/assets/javascripts/ext/src/ext-core/examples/rating/rating.js
/*!
* Ext JS Library 3.3.0
* Copyright(c) 2006-2010 Ext JS, Inc.
* licensing@extjs.com
* http://www.extjs.com/license
*/
Ext.ns('Ext.ux');
Ext.ux.Rating = Ext.extend(Ext.util.Observable, {
// Configuration options
starWidth: 16,
split: 1,
resetValue: '',
defaultSelected: -1,
selected: -1,
showTitles: true,
// Our class constructor
constructor : function(element, config) {
Ext.apply(this, config);
Ext.ux.Rating.superclass.constructor.call(this);
this.addEvents(
'change',
'reset'
);
this.el = Ext.get(element);
this.init();
},
init : function() {
var me = this;
// Some arrays we are going to store data in
this.values = [];
this.titles = [];
this.stars = [];
// We create a container to put all our stars into
this.container = this.el.createChild({
cls: 'ux-rating-container ux-rating-clearfix'
});
if(this.canReset) {
this.resetEl = this.container.createChild({
cls: 'ux-rating-reset',
cn: [{
tag: 'a',
title: this.showTitles ? (this.resetTitle || 'Reset your vote') : '',
html: 'Reset'
}]
});
this.resetEl.visibilityMode = Ext.Element.DISPLAY;
this.resetEl.hover(function() {
Ext.fly(this).addClass('ux-rating-reset-hover');
}, function() {
Ext.fly(this).removeClass('ux-rating-reset-hover');
});
this.resetEl.on('click', this.reset, this);
}
// We use DomQuery to select the radio buttons
this.radioBoxes = this.el.select('input[type=radio]');
// Then we can loop over the CompositeElement using each
this.radioBoxes.each(this.initStar, this);
// We use DomHelper to create our hidden input
this.input = this.container.createChild({
tag: 'input',
type: 'hidden',
name: this.name,
value: this.values[this.defaultSelected] || this.resetValue
});
// Lets remove all the radio buttons from the DOM
this.radioBoxes.remove();
this.select(this.defaultSelected === undefined ? false : this.defaultSelected)
if(this.disabled) {
this.disable();
} else {
// Enable will set up our event listeners
this.enable();
}
},
initStar : function(item, all, i) {
var sw = Math.floor(this.starWidth / this.split);
// We use the name and disabled attributes of the first radio button
if(i == 0) {
this.name = item.dom.name;
this.disabled = item.dom.disabled;
}
// Saving the value and title for this star
this.values[i] = item.dom.value;
this.titles[i] = item.dom.title;
if(item.dom.checked) {
this.defaultSelected = i;
}
// Now actually create the star!
var star = this.container.createChild({
cls: 'ux-rating-star'
});
var starLink = star.createChild({
tag: 'a',
html: this.values[i],
title: this.showTitles ? this.titles[i] : ''
});
// Prepare division settings
if(this.split) {
var odd = (i % this.split);
star.setWidth(sw);
starLink.setStyle('margin-left', '-' + (odd * sw) + 'px');
}
// Save the reference to this star so we can easily access it later
this.stars.push(star.dom);
},
onStarClick : function(ev, t) {
if(!this.disabled) {
this.select(this.stars.indexOf(t));
}
},
onStarOver : function(ev, t) {
if(!this.disabled) {
this.fillTo(this.stars.indexOf(t), true);
}
},
onStarOut : function(ev, t) {
if(!this.disabled) {
this.fillTo(this.selected, false);
}
},
reset : function(ev, t) {
this.select(-1);
},
select : function(index) {
if(index === false || index === -1) {
// remove current selection in el
this.value = this.resetValue;
this.title = "";
this.input.dom.value = '';
if(this.canReset) {
this.resetEl.setOpacity(0.5);
}
this.fillNone();
if(this.selected !== -1) {
this.fireEvent('change', this, this.values[index], this.stars[index]);
}
this.selected = -1;
}
else if(index !== this.selected) {
// Update some properties
this.selected = index;
this.value = this.values[index];
this.title = this.titles[index];
// Set the value of our hidden input so the rating can be submitted
this.input.dom.value = this.value;
if(this.canReset) {
this.resetEl.setOpacity(0.99);
}
// the fillTo() method will fill the stars up until the selected one
this.fillTo(index, false);
// Lets also not forget to fire our custom event!
this.fireEvent('change', this, this.values[index], this.stars[index]);
}
},
fillTo : function(index, hover) {
if (index != -1) {
var addClass = hover ? 'ux-rating-star-hover' : 'ux-rating-star-on';
var removeClass = hover ? 'ux-rating-star-on' : 'ux-rating-star-hover';
// We add a css class to each star up until the selected one
Ext.each(this.stars.slice(0, index+1), function() {
Ext.fly(this).removeClass(removeClass).addClass(addClass);
});
// And then remove the same class from all the stars after this one
Ext.each(this.stars.slice(index+1), function() {
Ext.fly(this).removeClass([removeClass, addClass]);
});
}
else {
this.fillNone();
}
},
fillNone : function() {
this.container.select('.ux-rating-star').removeClass(['ux-rating-star-hover', 'ux-rating-star-on']);
},
enable : function() {
if(this.canReset) {
this.resetEl.show();
}
this.input.dom.disabled = null;
this.disabled = false;
this.container.removeClass('ux-rating-disabled');
// We will be using the technique of event delegation by listening
// for bubbled up events on the container
this.container.on({
click: this.onStarClick,
mouseover: this.onStarOver,
mouseout: this.onStarOut,
scope: this,
delegate: 'div.ux-rating-star'
});
},
disable : function() {
if(this.canReset) {
this.resetEl.hide();
}
this.input.dom.disabled = true;
this.disabled = true;
this.container.addClass('ux-rating-disabled');
this.container.un({
click: this.onStarClick,
mouseover: this.onStarOver,
mouseout: this.onStarOut,
scope: this,
delegate: 'div.ux-rating-star'
});
},
getValue : function() {
return this.values[this.selected] || this.resetValue;
},
destroy : function() {
this.disable();
this.container.remove();
this.radioBoxes.appendTo(this.el);
if(this.selected !== -1) {
this.radioBoxes.elements[this.selected].checked = true;
}
}
});