1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
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); } };
Usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
<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.
Javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
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(); } }); } }); }
View
1 2 3 4 5 6 7 8 9 10 11
<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.
Javascript
1 2
// 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