var Rating = Class.create();
Rating.prototype = {
initialize: function(element, rating, options) {
this.element = $(element);
this.rating = rating;
this.maxRating = 5;
this.options = options || {};
this.bindedOnHover = this.onHover.bindAsEventListener(this);
this.bindedOnExit = this.onExit.bindAsEventListener(this);
this.bindedOnClick = this.onClick.bindAsEventListener(this);
Event.observe(this.element, 'mouseover', this.bindedOnHover);
Event.observe(this.element, 'mouseout', this.bindedOnExit);
Event.observe(this.element, 'click', this.bindedOnClick);
this.instanciateStars();
this.showStarts(this.rating);
},
instanciateStars: function() {
this.maxRating.times(function() {
var img = document.createElement('img');
this.element.appendChild(img);
}.bind(this));
},
showStarts: function(number) {
var stars = this.getStars();
$R(0, number-1).each (function(position) {
stars[position].src = '/images/star_full.png';
});
$R(number, this.maxRating-1).each (function(position) {
stars[position].src = '/images/star_empty.png';
});
},
getStars: function() {
return this.element.getElementsBySelector('img');
},
onHover: function(event) {
var element = Event.element(event);
if (element.tagName == 'IMG') {
this.showStarts(this.findRatingFromEvent(element));
}
},
onExit: function(event) {
this.showStarts(this.rating);
},
onClick: function(event) {
var element = Event.element(event);
if (element.tagName == 'IMG' && this.options.onClick) {
this.options.onClick.bind(this)(this.findRatingFromEvent(element));
}
},
findRatingFromEvent: function(element) {
var r = 0;
this.getStars().each(function(star) {
r ++;
if (star == element) {
throw $break;
}
});
return r;
},
disable: function() {
Event.stopObserving(this.element, 'mouseover', this.bindedOnHover);
Event.stopObserving(this.element, 'mouseout', this.bindedOnExit);
Event.stopObserving(this.element, 'click', this.bindedOnClick);
}
};
<div class="rating">
<span id="rating_97"></span>
<img alt="Spinner" class="spinner" id="rating_97_spinner" src="spinner.gif" style="display:none" />
<span id="rating_97_count" class="count">
No rating. You haven't rated it!
</span>
</div>
<script type="text/javascript">
var rating_97 = new Rating('rating_97', 0, {
onClick: function(rating) {
$('rating_97_spinner').show();
$('rating_97_count').hide();
this.disable();
new Ajax.Request('/codes/16-extracting-style-from-a-css-file/refactors/97;rate', {
parameters: 'rating=' + rating,
onComplete: function() {
$('rating_97_spinner').hide();
$('rating_97_count').show();
}
});
}
});
</script>
Refactorings
No refactoring yet !
leighmac
September 30, 2007, September 30, 2007 08:09, permalink
I like your ratings class it's easy to understand :). I'm not good enough at javascript to improve your class. But you might improve your view with something like this.
var Rating = Class.create();
// removed to make post more tidy
};
// Ratings helper for view
function rating_ui(id, rating, title) {
var rating = new Rating('rating_'+id, 0, {
onClick: function(rating) {
$('rating_'+id+'_spinner').show();
$('rating_'+id+'_count').hide();
this.disable();
new Ajax.Request('/codes/'+title+'/refactors/'+id+';rate', {
parameters: 'rating=' + rating,
onComplete: function() {
$('rating_'+id+'_spinner').hide();
$('rating_'+id+'_count').show();
}
});
}
});
}
<div class="rating">
<span id="rating_97"></span>
<img alt="Spinner" class="spinner" id="rating_97_spinner" src="spinner.gif" style="display:none" />
<span id="rating_97_count" class="count">
No rating. You haven't rated it!
</span>
</div>
<script type="text/javascript">
rating_ui(97, 0, '16-extracting-style-from-a-css-file')
</script>
macournoyer
September 30, 2007, September 30, 2007 20:04, permalink
Thanks leighmac good idea, I should abtract it a bit more and keep the logic out of the view!
leighmac
September 30, 2007, September 30, 2007 23:05, permalink
No worries :), The only things I could suggest to the next refactorer might be to break up the constructor a little bit more.. add a couple of constants for the strings and some sort of error handling.. if no one else posts I'll have a crack at that.
// my codes did have an error. line 7 should read
var rating = new Rating('rating_'+id, rating, {
Here's the code of the rating system I built for this site.
Have any suggestions on how to improve it ?
Thanks