PDA

View Full Version : [1.1] Ext.ux.form.Rater - Get ext-rated!



K0bo
8 Aug 2007, 7:54 PM
Just out of curiosity I created this little widget to explore the Ext Framework.

It works standalone or in a form. Ajax can be added.

Right now I'm trying to get it working in a GridEditor (If there is need for its usage there)

Feel free to comment or suggest improvements.

updates in v0.2:
- added events beforeRating and rate
- displaying initial value without setting the value using the config: .displayValue
- reworked the code so .show(), .hide(), setDisabled(true/false) works.

updates in v0.3b
- added function reInit(config) to re-initialize the star
- added config .ratedValue to display final rating on initialization.
- added config .animate to display ratings with animation.
- reworked internal workings for smaller code print and to enable reInit()
- disable/enable in v0.2 did incorrectly

Examples:
1) create simple rater:


var rater = new Ext.ux.form.Rater();
rater.render('container');


2) apply to existing textfield:


var rater = new Ext.ux.form.Rater();
rater.applyTo('textfield');


3) set initial value to display and adjusting stars to show:


var rater = new Ext.ux.form.Rater({displayValue:3.4, maxValue:10});
rater.applyTo('textfield');


4) Youtube style rating with text above/beneath the stars and text change when hovering the stars:


var rater = new Ext.ux.form.Rater({topText:'Rate this:', bottomText:'2234 ratings', topHoverText:['Poor','Nothing special','OK','Pretty cool','Awesome!']});
rater.applyTo('textfield');


5) Using events:


var rater = new Ext.ux.form.Rater();
rater.applyTo('textfield');

rater.on('beforerating', doSomething);
rater.on('rate', function(){
this.setBottomText('<b>Thank you for rating!</b>');
});

JorisA
9 Aug 2007, 2:27 AM
Thank you, looks great. I think I can use it in one of my apps.

tobiu
9 Aug 2007, 3:29 AM
hi K0bo,

the screenshot and code looks nice,
but i do not get it to work.

the only change i made was to fix the ext-lib paths.

i always get the firebug error-message:

this.getStars().getCount is not a function

which seems to be in the constructor of the rater:



createStars : function(){
if(this.getStars().getCount() > 0){
return;
}


any idea?


thanks and kind regards, tobiu

tobiu
9 Aug 2007, 3:49 AM
ok, found out what the problem was :)

or at least i think so:

i guess you wanted to use the public method "getValue()" which is defined in Field (so also available in NumberField).

if i replace all getCount() with getValue(), the demo works and looks nice!


kind regards, tobiu

tobiu
9 Aug 2007, 6:18 AM
in your second example, you use the config:


topHoverText:['Poor','Nothing special','OK','Pretty cool','Awesome!']

well, i don't see a hover-text anywhere on the stars.

if you display a text like "2234 ratings", i would increment the number on client side right after rating. (the server-logic should do this too, for sure).

what would be really nice, is a config option, where you can show, how the rater shall look after rating. in a form it is nice to see the value one has voted, but in the second and 3rd example, it would be nicer to see the overall result again. so a switch option for one of both would be cool.

in my application, i will need a star rater too, but i guess i will user a "smaller" one (not sure yet).

i will need multiple raters for one subject. as a virtual example:
imagine a song list. each song can be rated in the points

quality (5 stars)
sound (5 stars)
like it? (5 stars)
text (5 stars)
...

i want to submit each rating via ajax, because it should be possible to vote for "like it?" without the others.

what would work is a form, with a listener for each rater, onRate submit().
but in that case ALL rater values are submitted. the listener could reset all other values.

the other solution is an own form for each rater of this rater-list, which is somehow oversized.

i would like to implement, that after rating a single rater, the ajax-request gets the new overall rating value and shows it right in place (new average rating etc.). and displaying an icon, which shows that the user already voted (and cannot do it again), like http://www.famfamfam.com/lab/icons/silk/previews/index_abc.png -> accept-icon.


any ideas for my case?

i hope i will find some time in the next days for coding this, kind reagards, tobiu

tobiu
9 Aug 2007, 7:34 AM
still working with this.
i hope you can summarize my points on your own *g*



Ext.ux.form.Rater = function(config){
Ext.ux.form.Rater.superclass.constructor.call(this, config);
this.addEvents({
'rate' : true
});
}


is a good idea, but if the event never fires, useless.



rate : function(e){
this.beforeRate(); //execute function after rating

this.setTopText(this.topText); //revert to default text if set
this.setBottomText(this.bottomText); //revert to default text if set

this.__displayFinalRating = true; //used in displayRating
this.removeHover(e);
this.removeListeners();
this.onBlur();
this.rated = true;
this.el.dom.readOnly = true //set to readonly

this.setValue(this.hoverValue);
this.displayRating();

this.fireEvent("rate", this, this.rated);

this.afterRate(); //execute function after rating


this is the position, where i would fire it.
as it is the same point like "this.afterRate()", i would leave that function completely.

i would also replace this.beforeRate() with
this.fireEvent("beforeRate", this, false);

and put it into
this.addEvents({
'beforeRate' : true,
'rate' : true
});

so that we are working only with listeners and not direct functions.


kind regards, tobiu

K0bo
9 Aug 2007, 11:27 AM
Hi tobiu

this.getStars().getCount is not a function
Don't know why you get it. You can safely remove the if-statement surrounding it. I added it to prevent the stars being created twice or more should it somehow getting rendered more than once.

- Hovering tekst not showing
This was a bug, got it fixed (My guess you didn't set a .topText while using .topHoverText)
Now it will work with .topHoverText set without .topText
The fix:


//set the hover text - top
if(this.topHoverText instanceof Array){
var stars = this.getStars();

if(this.topText == undefined || this.topText == ''){
this.topText = '&nbsp;';
this.setTopText(this.topText);
}
for (var i = 0; i < stars.getCount(); i++){
stars.item(i).on('mouseover', function(){this.setTopText(this.topHoverText[this.hoverValue-1])}, this, {delay:5} ); //delayed so hovervalue gets set
stars.item(i).on('mouseout', function(){this.setTopText(this.topText)}, this );
}
}

//set the hover text - bottom
if(this.bottomHoverText instanceof Array){
var stars = this.getStars();

if(this.bottomText == undefined || this.bottomText == ''){
this.bottomText = '&nbsp;';
this.setBottomText(this.bottomText);
}
for (var i = 0; i < stars.getCount(); i++){
stars.item(i).on('mouseover', function(){this.setBottomText(this.bottomHoverText[this.hoverValue-1])}, this, {delay:5} ); //delayed so hovervalue gets set
stars.item(i).on('mouseout', function(){this.setBottomText(this.bottomText)}, this );
}
}



- Incrementing number in text after rating
The text could be used for anything and maybe you can update the text by putting a function in .afterRate config to update the counter


rater.afterRate = function(){
//perform ajax calls and get new ammount of rating
this.setBottomText('#text with new counter#');
}

- how the rater shall look after rating
Not a bad idea, i'll put it on the list to do.


- using smaller stars (or larger)
if you have the stars picture, adjusting the widget is done within a minute.

- submitting each rating individually with ajax
Can be done by putting the ajax functionality in the .afterRate or .beforeRate config (I think)
Unless there are better ideas


what would work is a form, with a listener for each rater, onRate submit().
but in that case ALL rater values are submitted. the listener could reset all other values.
I'll see how this can be worked out. But than again, it can be done using the .afterRate




this.addEvents({
'rate' : true
});


About those events... I haven't figured out yet how they actually work and how they should be used. Is there any good explanation on it?

tobiu
9 Aug 2007, 11:51 AM
hi K0bo,

to the listeners: as mentioned above:


this.fireEvent("rate", this, this.rated);

setting a listener means, that you can write code in the form:


var rater = new Ext.ux.form.Rater({
name: 'r1',
fieldLabel: 'test'
});

rater.on("rate", function (){
ratingForm.submit();
}, this);

which means, that a function will be executed upon the rate event.
but this event must be defined somewhere in the original code.
so i put in the line of code above (see my last post in details).

i found out, that you were working with the input value for initialising, how thick the yellow stars will be. this is a no go. when the rater is initialised with a value of 2, for showing two yellow stars and the user submits the form, the value of 2 gets submitted, although the user has not voted at all.

i fixed this with another config option and many other things too, like showing the yellow stars after rating + an optional icon.

i'm sorry, that i do not have the time to tell you today, what exact changes i made and what they do. i will explain it tomorrow, but post my update already, so you can work with it too.

Rater.js


*see page 2*

tobiu
9 Aug 2007, 12:01 PM
a democase could be:
(sorry for german names, no more time)
check out each rater, some differ

ext-rater.js


*see page 2*

and here the modified ext-rater.html (almost no html-code)


*see page 2*

as mentioned two post above, you need a 16*16px accept icon (link posted there too).
i will write more tomorrow, promised! cu, tobiu

K0bo
9 Aug 2007, 2:14 PM
Those events are genius! Still can't figure out how the passed args in the fireEvent is used.

I added the 'beforerating' and correctly implemented 'rate'-event as suggested.
With that I remove the functions beforeRating and afterRating, which are unnecessary now.

You're right about the initial display value being set in the value. I will take the advise and implement it correctly. Though I think displayValue is more descriptive than ratedValue. If you don't mind I'm going for displayValue.

I still don't know about .showResultImg. Guess I'll have to wait till tomorrow :)

tobiu
10 Aug 2007, 8:42 AM
sorry, you will have to wait another day...

though, i worked with this class again and added animation to the stars and the possibility to use one rater multiple times (e.g. for different songs to be voted in one category).

i will give a backup tomorrow!


cu, tobiu

tobiu
11 Aug 2007, 7:32 AM
hello together,

my new version is ready.
the re-initialization works fine now, with animation of stars (they move out to the left and come back with an bounce easing.

i build a democase to. to test it, just install the normal extension and put my files into it (replacing the old ones) and open ext-rater.html.

here is the code:

Rater.js


Ext.namespace("Ext.ux.form");

Ext.ux.form.Rater = function(config){
Ext.ux.form.Rater.superclass.constructor.call(this, config);
this.addEvents({
'beforeRate': true,
'rate' : true
});
}

Ext.extend(Ext.ux.form.Rater, Ext.form.NumberField, {
//public configs
unit : 20, // default size (px) of each star
disabled : false,
maxValue : 5, // default number of stars
displayValue : 0, // initialise overall voted-value
ratedValue : 0, // initialise user-voting
countVotings : 0, // count of user-votings for this rater
showResult : true, // true: show the result of the vote
// false: show the initial value
showResultImg : false, // true: show img for vote confirmation
topText : undefined, // default text above the stars
bottomText : undefined, // default text beneath the stars
topHoverText : undefined, // array with text when hovering over stars displayed above the stars
bottomHoverText : undefined, // arrayarray with text when hovering over stars displayed beneath the stars

//private configs
rated : false, // true after getting rated
allowNegative : false, // don't allow negative values

/** css config **/
wrapClass : 'ux-form-rater-wrap', // container class to hold rater
starsClass : 'ux-form-rater-stars', // container class to hold stars
hoverClass : 'ux-form-rater-hover', // class when star get hovered
voteClass : 'ux-form-rater-vote', // class for displaying current rating
votedClass : 'ux-form-rater-voted', // class for displaying user rated rating

textTopClass : 'ux-form-rater-text-top', //class for top text container
textBottomClass : 'ux-form-rater-text-bottom', //class for bottom text container

autoSize: Ext.emptyFn,

// private
onRender : function(ct, position){
Ext.ux.form.Rater.superclass.onRender.call(this, ct, position);

if (this.ratedValue > 0)this.disabled = true;

this.wrap = this.el.wrap({cls: this.wrapClass});
//this.wrap.setSize(this.unit * this.maxValue, this.unit); //dunno if this one should have the dimensions set
if(Ext.isIE) this.wrap.setHeight(this.unit); //fix for ie using in dynamic form
this.el.addClass('x-hidden');

this.createStars();
this.createTextContainers();

// correct out of bound values

if (this.displayValue > this.maxValue) {
this.displayValue = this.maxValue;
}

//display yellow stars
if(this.displayValue > 0){
this.displayRating();
}

if (this.ratedValue > 0)this.showRatedImage();

},

// private
createStars : function(){
if(this.getStars().getValue() > 0){
return;
}

var ul = this.wrap.createChild({tag:'ul', cls:this.starsClass}).setSize(this.unit * this.maxValue, this.unit);

//**** focus blur might be the problem and not working as editor
ul.on('mouseover', this.onFocus, this); //maintain focus while hovering stars - useful in editor
ul.on('click', this.onFocus, this); //maintain focus while hovering stars - useful in editor
ul.on('mouseout', this.onBlur, this); //blur when not hovering stars - useful in editor


//append to rating container
var tplr = new Ext.Template('<li class="rating"></li>'); //template for displaying the rating (yellow)
var tpls = new Ext.Template('<li class="star"></li>'); //template for each rating (star)

tplr.append(ul, [], true).setHeight(this.unit) //append rating to its ul container

this.stars = new Array();

for (var i = this.maxValue; i > 0; i--){
this.stars[i] = tpls.append(ul, [], true); //append star to its ul container
this.stars[i].setSize(this.unit * i, this.unit); //dimensions of the stars - declines in size, overlapping each other

//attach events on the stars
this.enableStar(this.stars[i]);
}

this.alignStars();
},

//private
createTextContainers : function (){
var ct = this.getStarsContainer();

if (!this.textTopContainer) this.textTopContainer = Ext.DomHelper.insertBefore(ct, {tag:"div", cls:this.textTopClass}, true);
if (!this.textBottomContainer)this.textBottomContainer = Ext.DomHelper.insertAfter(ct, {tag:"div", cls:this.textBottomClass}, true);

//hide the containers on default
this.textTopContainer.addClass('x-hidden');
this.textBottomContainer.addClass('x-hidden');

//set the text
if(this.topText) this.setTopText(this.topText);
if(this.bottomText) this.setBottomText(this.bottomText);

//set the hover text - top
if(this.topHoverText instanceof Array){
var stars = this.getStars();
for (var i = 0; i < stars.getValue(); i++){
stars.item(i).on('mouseover', function(){this.setTopText(this.topHoverText[this.hoverValue-1])}, this, {delay:5} ); //delayed so hovervalue gets set
stars.item(i).on('mouseout', function(){this.setTopText(this.topText)}, this );
}
}

//set the hover text - bottom
if(this.bottomHoverText instanceof Array){
var stars = this.getStars();
for (var i = 0; i < stars.getValue(); i++){
stars.item(i).on('mouseover', function(){this.setBottomText(this.bottomHoverText[this.hoverValue-1])}, this, {delay:5} ); //delayed so hovervalue gets set
stars.item(i).on('mouseout', function(){this.setBottomText(this.bottomText)}, this );
}
}
},

/**
* Return true/false when Rater is rated or not
*/
isRated : function(){
return this.rated;
},

/**
* Returns the text in the top text container
*/
getTopText : function(){
return this.textTopContainer.dom.innerHTML;
},

/**
* Returns the text in the bottom text container
*/
getBottomText : function(){
return this.textBottomContainer.dom.innerHTML;
},

/**
* Sets the text in the top text container
*/
setTopText : function(t){
this.textTopContainer.dom.innerHTML = t;
(t == null || t == '') ? this.textTopContainer.addClass('x-hidden') : this.textTopContainer.removeClass('x-hidden') ;
},

/**
* Sets the text in the bottom text container
*/
setBottomText : function(t){
this.textBottomContainer.dom.innerHTML = t;
(t == null || t == '') ? this.textBottomContainer.addClass('x-hidden') : this.textBottomContainer.removeClass('x-hidden') ;
},

// private
getStarsContainer : function(){
return this.wrap.select('.'+this.starsClass, true).item(0);;
},

// private
getRating : function(){
return this.wrap.select("li.rating", true);
},

// private
getStars : function(){
return this.wrap.select("li.star", true);
},

alignStars : function(){
var ct = this.getStarsContainer();
var rating = this.getRating();
var stars = this.getStars();
var leftOffset = Ext.fly(document.body).getAlignToXY(ct)[0]; //left absolute positioning of rating and stars
var isInForm = (ct.findParent('.x-form-item', 5)) ? true : false; //used to fix weird aligning problem - dont't have a nice solution yet
var isInEditor = (ct.findParent('.x-editor', 5)) ? true : false; //used to fix weird aligning problem - dont't have a nice solution yet

if(!isInForm && !isInEditor){ //left offset of the rating <li> (yellow stars)
rating.setLeft(leftOffset);
stars.setLeft(leftOffset);
}else{
rating.alignTo(ct, 'tl');
stars.alignTo(ct, 'tl');
}
},

// private
displayHover : function(e){
var target = Ext.get(e.getTarget()); //get originating element from the event
target.addClass(this.hoverClass); //add class show the hover stars

var stars = this.getStars();
var i = 0;

//loop star till originating star to get the value and store it in hoverValue for later use
while (stars.item(i) != null){
if(stars.item(i) == target){
this.hoverValue = this.maxValue - i;
return;
}
i++;
}
},

// private
displayRating : function(){
var el = this.getRating(); //get <li> for displaying the value (yellow star)

if (this.__displayFinalRating && this.showResult){
el.setWidth(this.hoverValue * this.unit); //set width according to the hovered value
el.removeClass(this.voteClass); //remove yellow stars
el.addClass(this.votedClass); //show dark stars
return;
}
el.setWidth(this.displayValue * this.unit); //set width according to the value
el.addClass(this.voteClass); //show yellow stars
},

// private
rate : function (e) {
this.fireEvent("beforeRate", this, false);

this.setTopText(this.topText); //revert to default text if set
this.setBottomText(this.bottomText); //revert to default text if set

this.__displayFinalRating = true; //used in displayRating
this.removeHover(e);
this.removeListeners();
this.onBlur();
this.rated = true;
this.el.dom.readOnly = true

this.setValue(this.hoverValue);
this.displayRating();

this.fireEvent("rate", {"name":this.name, "value":this.hoverValue}, this);

},

// private
removeHover : function(e){
var el = e.getTarget();
Ext.fly(el).removeClass(this.hoverClass);
},

// private
removeListeners : function(){
this.wrap.select("*", true).removeAllListeners();
},

// private
onDisable : function(){
Ext.ux.form.Rater.superclass.onDisable.call(this);
this.removeListeners();
},

// private
enableStar : function(star){
if (this.disabled != true){
star.on('mouseover', this.displayHover, this);
star.on('mouseout', this.removeHover, this, {delay:5}); //delayed for anti-flicker
star.on('click', this.rate, this);
}
},

// private
enableAllStars : function(){
for (var i = this.maxValue; i > 0; i--) {
this.enableStar(this.stars[i])
}
},

// public
reInitializeStars : function (countVotings, displayValue, ratedValue) {
this.countVotings = countVotings;
this.displayValue = displayValue;
this.ratedValue = ratedValue;
this.hideStars();

if (this.ratedValue > 0) {
this.disabled = true;
this.removeListeners();
this.showRatedImage();
} else {
this.disabled = false;
this.enableAllStars();
this.hideRatedImage();
}
},

// private
displayStars : function () {
var el = this.getRating();

el.removeClass(this.votedClass); // remove dark stars
el.addClass(this.voteClass); // show yellow stars

el.setWidth(this.displayValue * this.unit, {
duration: .7,
easing: 'bounceOut',
scope: this
});
},

// private
hideStars : function () {
var el = this.getRating();
el.setWidth(0, {
duration: .7,
easing: 'bounceIn',
callback: this.displayStars,
scope: this
});
},

// private
hideRatedImage : function () {
if (this.showResultImg != true)return;

this.votedImg.switchOff({
easing: 'easeIn',
duration: .3,
remove: true
});
this.showResultImg = false;
},

// private
renewRatedImage : function () {
if (this.showResultImg != true)return;

this.votedImg.switchOff({
easing: 'easeIn',
duration: .3,
remove: true,
callback: this.showRatedImage,
scope: this
});
this.showResultImg = false;
},

// private
showRatedImage : function () {
if (this.showResultImg != false) {
this.renewRatedImage();
return;
}

var imgMarginLeft = this.maxValue * this.unit + 5;
var imgMarginTop = - 17;
this.votedImg = Ext.DomHelper.insertAfter(this.getStarsContainer(),
'<img id="img'+this.name+'" '+
'style="position:absolute; margin-left:' + imgMarginLeft +'px; margin-top:' + imgMarginTop +'px; width:16px; height:16px" '+
'src="/images/icons/accept.png" '+
'ext:qtip="<b>You voted '+this.ratedValue+' stars!" '+
'ext:width="100">', true);
this.showResultImg = true;
}

});

ext-rater.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<title>Ext Rater Widget</title>
<link rel="stylesheet" type="text/css" href="/extJS/resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="/starRater/Rater.css" />
<link rel="stylesheet" type="text/css" href="/extJS/resources/css/xtheme-vista.css">

<script type="text/javascript" src="/extJS/adapter/ext/ext-base.js.php"></script>
<script type="text/javascript" src="/extJS/ext-all.js.php"></script>



<script type="text/javascript" src="/starRater/Rater3.js"></script>
<script type="text/javascript" src="/starRater/ext-rater4.js"></script>


<style media="screen" type="text/css">
/* global css */
body {
font: normal 12px arial, helvetica, sans-serif;
}

fieldset {
margin:1em .3em;
padding:.4em;
}

</style>
<script>
function reInitialsieRater1() {

rater['r1'].reInitializeStars(200, 4, 0);
rater['r2'].reInitializeStars(200, 0, 1);
rater['r3'].reInitializeStars(200, 4.4, 0);
rater['r4'].reInitializeStars(200, 0, 0);
rater['r5'].reInitializeStars(200, 3.2, 3);
}

function reInitialsieRater2() {

rater['r1'].reInitializeStars(200, 3, 0);
rater['r2'].reInitializeStars(200, 0, 0);
rater['r3'].reInitializeStars(200, 0, 0);
rater['r4'].reInitializeStars(200, 1, 2);
rater['r5'].reInitializeStars(200, 3, 0);
}
</script>
</head>

<body style="margin:200px;">
<div id="container" style="width:305px;"></div>
<input type="button" value="song 1" style="margin-top:20px;" ONCLICK="reInitialsieRater1()">
<input type="button" value="song 2" style="margin-top:20px; margin-left:10px;" ONCLICK="reInitialsieRater2()">
</body>
</html>

ext-rater.js


function ajaxRateHandler(data) {

var songId = "23";

Ext.Ajax.request ({
url: '/ajaxHandler/ajaxRateSong.php',
method:'POST',
params: {
songId : songId,
ratingCategory : data.name,
ratedValue : data.value
},
callback: ajaxRateSongsCallback});
}


function ajaxRateSongsCallback(opts, success, response){
if(success != true)return false;
aData = eval('('+response.responseText+')');

rater[aData["name"]].reInitializeStars(aData["countVotings"], aData["displayValue"], aData["ratedValue"]);
}


Ext.onReady(function(){

Ext.QuickTips.init();

var ratingForm = new Ext.form.Form({
labelWidth: 157
});

function createRater (fieldLabel, name, displayValue, ratedValue) {

return new Ext.ux.form.Rater({
name: name,
displayValue: displayValue,
ratedValue: ratedValue,
fieldLabel: fieldLabel,
listeners: {
'rate' : ajaxRateSongsHandler,
scope : this
}
});
}

rater = new Array();

ratingForm.fieldset(
{legend:'rate this song:'},
rater['r1'] = createRater ('Sound', 'r1', 4, 0),
rater['r2'] = createRater ('Melody', 'r2', 0, 1),
rater['r3'] = createRater ('Artist', 'r3', 4.4, 0),
rater['r4'] = createRater ('Quality', 'r4', 0, 0),
rater['r5'] = createRater ('Text', 'r5', 3.2, 3)
)

ratingForm.render("container");
});

i added a screenshot, however forgot how to display the mouse-cursor in it *g* imagine one above the green icon =)


kind regards, tobiu

tobiu
11 Aug 2007, 7:37 AM
in my example, there is a server-side ajax-handler.

if you use php, you can use this one for the demo-case:


<?php

$songId = $_REQUEST["songId"];
$ratingCategory = $_REQUEST["ratingCategory"];
$ratedValue = $_REQUEST["ratedValue"];

echo '{"name":"'.$ratingCategory.'", "displayValue":"3.6", "ratedValue":"'.$ratedValue.'", "countVotings":"124", "songId":"'.$songId.'"}';
?>

it always returns 3.6 as the new average value -> there should be a server logic with a database for your special cases.

tobiu
11 Aug 2007, 7:56 AM
@K0bo and others, who would like to help improving this rater:

points for a roadmap:


countVotings above the stars
numeric icons instead of the accept.png (showing the value, the user has voted)
Ext Quicktips when hovering the stars, like "good", "average",...


in my latest version, there is the hover-text fix still missing, but i would recomment, that you continue working with my version, because there are really many changes in the basic code.


king regards, tobiu

K0bo
12 Aug 2007, 6:00 AM
With the screenshot I can see the usage of your 'accept-icon'.
My whole idea is to give the user visual feedback when the Rater gets rated is to display their rating in dark stars. Like on IMDB.com or YouTube.com

I don't know about the countVotings config should be in the Rater. If the Rater is ajax enabled, my idea is that the server sends the updated voteCount to the Rater after a succesful ajax call and use .setTopText() to update the text accordingly.

I like the idea of re-initiating a rater to be able to use it multiple times.
Also I would like to implement the animation and make it optional.

Since 0.2 a couple of important updates are made so enable()/disable() and show()/hide() work like the rest of the Components. Also re-initiating will be nicer, I promise ;)

tobiu
12 Aug 2007, 6:28 AM
hi K0bo,

please take the time to install the 3 files (+ajax-Answer) and run my demo ;)

if you do not get it to work, i can install a demo link too.

at the moment, the rater works like this:

you hover the stars and they get light blue (like in your original code).
after rating they get blue and the ajax-request is fired.
when the serverside answer comes in, the blue stars move out to the left with animation.
after that, they move in again, right to the new average value. by passing the parameter countVotings, you can display, that for example the number of total votings went from 3 to 4 and the average from 3.4 to 3.7. 3.7 would be the new value, the yellow stars show + the icon, that you have voted and a disabled rater (this icon should be "numeric", see roadmap).

when you switch from song 1 to song 2, the rater get reInitialsed. Again, all stars move out to the left side and come back to the new value + a switchOff for the green icons. raters can be enabled / disabled after each change.

6epcepk
17 Oct 2007, 11:12 PM
Does anybody run star-rating with EditorGrid?
I'm try to use this with editor- and renderer-functions, but if I use editor-function, user must dblclick on cell to show stars. If I use renderer-function I don't know what i must return:

function raterShow(val) {

var rater = new Ext.ux.form.Rater();

return ???;

}

K0bo
22 Oct 2007, 5:29 AM
It doesn't work with the editorgrid in the current version.
I never got it working with the editorgrid. I couldn't figure out the problem...

Any experts here to solve it? ;)

6epcepk
23 Oct 2007, 8:50 AM
I'm asking in the premium-forum (http://extjs.com/forum/showthread.php?t=15422), but no result =(

6epcepk
24 Oct 2007, 8:17 PM
This is demo (http://img219.imageshack.us/my.php?image=21686223vp6.swf) of grid ratings. But it doesn't work with paginig ...

Column:

{
header: "Оценка",
dataIndex: 'id',
width: 160,
renderer: raterShow
}

Renderer-function:

function raterShow(val) {
count = ids.length;
ids.splice(count, 1, val);
var currentDiv = '<div id="r-' + val + '" style="position: relative"></div>';

return currentDiv;
}

After grid is render must loaded function initRating:

function initRating() {

for (i = 0; i < ids.length; i++) {

var rater = new Ext.ux.form.Rater({
//fieldLabel: 'Рейтинг',
//name: 'rating',
//value: 5,
//maxValue: 5
});

rater.on('rate', function() {
//this.setTopText('<b>You rated: ' + this.getValue() + '</b>');
});

rater.render('r-' + ids[i]);

}

//ids = slice(0, ids.length);
ids = [];

}


I hope, anybody saya why rater doesn't working with padging.
Array ids clears with paging, so rater renders to existing divs.

onlinesaratoga
26 Nov 2007, 1:36 PM
Great add-on. Thank you!

I am using the rating in a form that I wanted to give the opportunity to the user to change the rating. ("I give it a 3. Well...make that a 4.") Took me a bit to figure it out, but this worked for me:

On line 310, replace:

if(this.disabled) return;
with this:


if(this.disabled) {
this.reInit({displayValue:0});
return;
}

auz0bgd
26 Feb 2008, 6:30 AM
first of all, tnx for the rater realy looks great a works, tho i have a question and i need some help, is there a way to automaticly render dark stars and disable onRate event depending on, dunno boolean value, if user already voted?

brikonwall
13 Mar 2008, 12:10 PM
I keep getting the attached error when I am trying to use this extension.

I even get similar error from when I try to use the following:
http://extjs.com/forum/showthread.php?t=11401&highlight=rating

Any kind of help to fix this will be much appreciated.

Thanks....

ZooKeeper
7 May 2008, 5:59 AM
Is this extention supported in 2.1?
Thanks