ratyrate 1.2.0.alpha → 1.2.2.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afb9049229e09fc34ff2b76ce661361b05914316
4
- data.tar.gz: 97b29e7fd7793f1355e76ebdb8480dc7b2b804c7
3
+ metadata.gz: b53d45f2998157baf412e9ac7da13833e6a2c7d0
4
+ data.tar.gz: 4170bf59fdc9ade44406793d3fb20468858717ab
5
5
  SHA512:
6
- metadata.gz: 137685240d3d6f07ec47aed48a9790ee7e8cbcd48133d6194fc1e416c0ebc8a717451ab8ecac41510c19b870db8c88d010533746e927d601ab3203b226d017e0
7
- data.tar.gz: 5cd42119f1040208e7fb3c5b59ac926fc5712d03935d8fd8e794f808e09803778f0010c5480155af15de93984fe8e8dc1245e6f362daf9fd099ff8f2a2c7167a
6
+ metadata.gz: af7091138333e866d7cbf9e8a2fd2fc54033205e9a0a46fb53d95893563860b70f5c2b532884e924891a0281c221a6efe1a2e93d5c512083d503a30fb7e01a6b
7
+ data.tar.gz: 02bfd2f72a059d73fbe1482841ae05f2fc8bd65b189c2072f2eb93051f2c3f49b9d7bd8ffe48dfaecbfdc6179b90bb6504f72b0fbdfded5f1cdfd8f934044453
data/Gemfile CHANGED
@@ -4,5 +4,7 @@ gem 'jquery-rails', '>= 3.1.1'
4
4
 
5
5
  ruby '2.1.0'
6
6
 
7
- # Specify your gem's dependencies in ratyrate.gemspec
7
+ # gem 'rspec'
8
+
9
+ # Specify your gem's dependencies in letsrate.gemspec
8
10
  gemspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ratyrate (1.0.9)
4
+ ratyrate (1.2.0.alpha)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A Ruby Gem that wrap the functionality of [jQuery Raty](https://github.com/wbotelhos/raty) library, and provides optional IMDB style rating.
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/money-rails.png)](http://badge.fury.io/rb/money-rails)
5
+ [![Gem Version](https://badge.fury.io/rb/ratyrate.svg)](http://badge.fury.io/rb/ratyrate)
6
6
  [![Build Status](https://travis-ci.org/wazery/ratyrate.svg)](http://travis-ci.org/wazery/ratyrate)
7
7
  [![Dependency Status](https://gemnasium.com/wazery/ratyrate.svg)](https://gemnasium.com/wazery/ratyrate)
8
8
  [![Code Climate](https://codeclimate.com/github/wazery/ratyrate.png)](https://codeclimate.com/github/wazery/ratyrate)
@@ -31,8 +31,10 @@ This is a fork against the repository [muratguzel/ratyrate](https://github.com/m
31
31
 
32
32
  1. Write RSpec tests for this Gem
33
33
  2. Create a Heroku app to illustrate this Gem's purpose and features (MovieStore)
34
- 3. Add option to show the number of users who gave rates
35
- 4. Add a share helper to Facebook, Twitter
34
+ 3. Write a complete tutorial on SitePoint that illustrates how to use this gem
35
+ 4. Add option to show the number of users who gave rates
36
+ 5. Add a share helper to Facebook, Twitter
37
+ 6. Force refresh after rating when ***disable_after_rate*** and ***imdb_avg*** options is set to true.
36
38
 
37
39
  ## Detailed view of the new features
38
40
 
@@ -51,7 +53,7 @@ gem 'ratyrate'
51
53
  ### Generate
52
54
 
53
55
  ```
54
- rails g ratyrate User
56
+ rails g ratyrate user
55
57
  ```
56
58
 
57
59
  The generator takes one argument which is the name of your existing devise user model UserModelName. This is necessary to bind the user and rating datas.
@@ -68,7 +70,16 @@ rails g devise user
68
70
  rails g ratyrate user # => user is the model generated by devise
69
71
  ```
70
72
 
71
- This generator will create Rate and RatingCache models and link to your user model.
73
+ This generator will create Rate and RatingCache models,
74
+ db/migrations,
75
+ and link to your user model.
76
+
77
+ ### Database Migration
78
+
79
+ Run the migrations:
80
+ ```
81
+ rake db:migrate
82
+ ```
72
83
 
73
84
  ### Prepare
74
85
 
@@ -115,38 +126,44 @@ Speed : <%= rating_for @car, "speed", :star => 10 %>
115
126
  Speed : <%= rating_for @car, "engine", :star => 7 %>
116
127
  Speed : <%= rating_for @car, "price" %>
117
128
  ```
118
- 2- To enable half stars use the option *enable_half*
129
+ 2- If you want to disable/enable the rating after user's first rate use the new option *disable_after_rate*
130
+ ```erb
131
+ Speed : <%= rating_for @car, "speed", :disable_after_rate => true %>
132
+ ```
133
+ To enable changes after first user rate set ```disable_after_rate``` to false
134
+
135
+ 3- To enable half stars use the option *enable_half*
119
136
  ```erb
120
137
  Speed : <%= rating_for @car, "speed", :enable_half => true %>
121
138
  ```
122
- 3- To show or hide the half stars use *half_show*
139
+ 4- To show or hide the half stars use *half_show*
123
140
  ```erb
124
141
  Speed : <%= rating_for @car, "speed", :half_show => true %>
125
142
  ```
126
- 4- To change the path in which the star images (star-on.png, star-off.png, star-half.png, ..etc) are located use
143
+ 5- To change the path in which the star images (star-on.png, star-off.png, star-half.png, ..etc) are located use
127
144
  ```erb
128
145
  Speed : <%= rating_for @car, "speed", :star_path => true %>
129
146
  ```
130
147
 
131
148
  To just change one of the star images choose from these options (star_on, star_off, star_half)
132
149
 
133
- 5- To add the cancel button to the left, or right of the stars use **(default is false)**
150
+ 6- To add the cancel button to the left, or right of the stars use **(default is false)**
134
151
  ```erb
135
152
  Speed : <%= rating_for @car, "speed", :cancel => true %>
136
153
  ```
137
- 6- To change the place of the cancel button (left, or right) use **(default is left)**
154
+ 7- To change the place of the cancel button (left, or right) use **(default is left)**
138
155
  ```erb
139
156
  Speed : <%= rating_for @car, "speed", :cancel_place => left %>
140
157
  ```
141
- 7- To change the hint on the cancel button use **(default is "Cancel current rating!" )**
158
+ 8- To change the hint on the cancel button use **(default is "Cancel current rating!" )**
142
159
  ```erb
143
160
  Speed : <%= rating_for @car, "speed", :cancel_hint => "Cancel this rating!" %>
144
161
  ```
145
- 8- To change the image of the cancel on button use
162
+ 9- To change the image of the cancel on button use
146
163
  ```erb
147
164
  Speed : <%= rating_for @car, "speed", :cancel_on => "cancel-on2.png" %>
148
165
  ```
149
- 9- To change the image of the cancel off use
166
+ 10- To change the image of the cancel off use
150
167
  ```erb
151
168
  Speed : <%= rating_for @car, "speed", :cancel_off => "cancel-off2.png" %>
152
169
  ```
@@ -1,464 +1,760 @@
1
1
  /*!
2
- * jQuery Raty - A Star Rating Plugin - http://wbotelhos.com/raty
3
- * -------------------------------------------------------------------
2
+ * jQuery Raty - A Star Rating Plugin
4
3
  *
5
- * jQuery Raty is a plugin that generates a customizable star rating.
4
+ * The MIT License
6
5
  *
7
- * Licensed under The MIT License
8
- *
9
- * @version 2.4.5
10
- * @since 2010.06.11
11
- * @author Washington Botelho
12
- * @documentation wbotelhos.com/raty
13
- * @twitter twitter.com/wbotelhos
14
- *
15
- * Usage:
16
- * -------------------------------------------------------------------
17
- * $('#star').raty();
18
- *
19
- * <div id="star"></div>
6
+ * @author : Washington Botelho
7
+ * @doc : http://wbotelhos.com/raty
8
+ * @version : 2.7.0
20
9
  *
21
10
  */
22
11
 
23
- ;(function($) {
12
+ ;
13
+ (function($) {
14
+ 'use strict';
15
+
16
+ var methods = {
17
+ init: function(options) {
18
+ return this.each(function() {
19
+ this.self = $(this);
20
+
21
+ methods.destroy.call(this.self);
22
+
23
+ this.opt = $.extend(true, {}, $.fn.raty.defaults, options);
24
+
25
+ methods._adjustCallback.call(this);
26
+ methods._adjustNumber.call(this);
27
+ methods._adjustHints.call(this);
28
+
29
+ this.opt.score = methods._adjustedScore.call(this, this.opt.score);
30
+
31
+ if (this.opt.starType !== 'img') {
32
+ methods._adjustStarType.call(this);
33
+ }
34
+
35
+ methods._adjustPath.call(this);
36
+ methods._createStars.call(this);
37
+
38
+ if (this.opt.cancel) {
39
+ methods._createCancel.call(this);
40
+ }
41
+
42
+ if (this.opt.precision) {
43
+ methods._adjustPrecision.call(this);
44
+ }
45
+
46
+ methods._createScore.call(this);
47
+ methods._apply.call(this, this.opt.score);
48
+ methods._setTitle.call(this, this.opt.score);
49
+ methods._target.call(this, this.opt.score);
50
+
51
+ if (this.opt.readOnly) {
52
+ methods._lock.call(this);
53
+ } else {
54
+ this.style.cursor = 'pointer';
55
+
56
+ methods._binds.call(this);
57
+ }
58
+ });
59
+ },
60
+
61
+ _adjustCallback: function() {
62
+ var options = ['number', 'readOnly', 'score', 'scoreName', 'target'];
63
+
64
+ for (var i = 0; i < options.length; i++) {
65
+ if (typeof this.opt[options[i]] === 'function') {
66
+ this.opt[options[i]] = this.opt[options[i]].call(this);
67
+ }
68
+ }
69
+ },
70
+
71
+ _adjustedScore: function(score) {
72
+ if (!score) {
73
+ return score;
74
+ }
75
+
76
+ return methods._between(score, 0, this.opt.number);
77
+ },
78
+
79
+ _adjustHints: function() {
80
+ if (!this.opt.hints) {
81
+ this.opt.hints = [];
82
+ }
83
+
84
+ if (!this.opt.halfShow && !this.opt.half) {
85
+ return;
86
+ }
87
+
88
+ var steps = this.opt.precision ? 10 : 2;
89
+
90
+ for (var i = 0; i < this.opt.number; i++) {
91
+ var group = this.opt.hints[i];
92
+
93
+ if (Object.prototype.toString.call(group) !== '[object Array]') {
94
+ group = [group];
95
+ }
96
+
97
+ this.opt.hints[i] = [];
98
+
99
+ for (var j = 0; j < steps; j++) {
100
+ var
101
+ hint = group[j],
102
+ last = group[group.length - 1];
103
+
104
+ if (last === undefined) {
105
+ last = null;
106
+ }
107
+
108
+ this.opt.hints[i][j] = hint === undefined ? last : hint;
109
+ }
110
+ }
111
+ },
112
+
113
+ _adjustNumber: function() {
114
+ this.opt.number = methods._between(this.opt.number, 1, this.opt.numberMax);
115
+ },
116
+
117
+ _adjustPath: function() {
118
+ this.opt.path = this.opt.path || '';
119
+
120
+ if (this.opt.path && this.opt.path.charAt(this.opt.path.length - 1) !== '/') {
121
+ this.opt.path += '/';
122
+ }
123
+ },
124
+
125
+ _adjustPrecision: function() {
126
+ this.opt.half = true;
127
+ },
128
+
129
+ _adjustStarType: function() {
130
+ var replaces = ['cancelOff', 'cancelOn', 'starHalf', 'starOff', 'starOn'];
131
+
132
+ this.opt.path = '';
133
+
134
+ for (var i = 0; i < replaces.length; i++) {
135
+ this.opt[replaces[i]] = this.opt[replaces[i]].replace('.', '-');
136
+ }
137
+ },
138
+
139
+ _apply: function(score) {
140
+ methods._fill.call(this, score);
141
+
142
+ if (score) {
143
+ if (score > 0) {
144
+ this.score.val(score);
145
+ }
146
+
147
+ methods._roundStars.call(this, score);
148
+ }
149
+ },
150
+
151
+ _between: function(value, min, max) {
152
+ return Math.min(Math.max(parseFloat(value), min), max);
153
+ },
154
+
155
+ _binds: function() {
156
+ if (this.cancel) {
157
+ methods._bindOverCancel.call(this);
158
+ methods._bindClickCancel.call(this);
159
+ methods._bindOutCancel.call(this);
160
+ }
161
+
162
+ methods._bindOver.call(this);
163
+ methods._bindClick.call(this);
164
+ methods._bindOut.call(this);
165
+ },
166
+
167
+ _bindClick: function() {
168
+ var that = this;
169
+
170
+ that.stars.on('click.raty', function(evt) {
171
+ var
172
+ execute = true,
173
+ score = (that.opt.half || that.opt.precision) ? that.self.data('score') : (this.alt || $(this).data('alt'));
174
+
175
+ if (that.opt.click) {
176
+ execute = that.opt.click.call(that, +score, evt);
177
+ }
178
+
179
+ if (execute || execute === undefined) {
180
+ if (that.opt.half && !that.opt.precision) {
181
+ score = methods._roundHalfScore.call(that, score);
182
+ }
183
+
184
+ methods._apply.call(that, score);
185
+ }
186
+ });
187
+ },
188
+
189
+ _bindClickCancel: function() {
190
+ var that = this;
191
+
192
+ that.cancel.on('click.raty', function(evt) {
193
+ that.score.removeAttr('value');
194
+
195
+ if (that.opt.click) {
196
+ that.opt.click.call(that, null, evt);
197
+ }
198
+ });
199
+ },
200
+
201
+ _bindOut: function() {
202
+ var that = this;
203
+
204
+ that.self.on('mouseleave.raty', function(evt) {
205
+ var score = +that.score.val() || undefined;
206
+
207
+ methods._apply.call(that, score);
208
+ methods._target.call(that, score, evt);
209
+ methods._resetTitle.call(that);
210
+
211
+ if (that.opt.mouseout) {
212
+ that.opt.mouseout.call(that, score, evt);
213
+ }
214
+ });
215
+ },
216
+
217
+ _bindOutCancel: function() {
218
+ var that = this;
219
+
220
+ that.cancel.on('mouseleave.raty', function(evt) {
221
+ var icon = that.opt.cancelOff;
222
+
223
+ if (that.opt.starType !== 'img') {
224
+ icon = that.opt.cancelClass + ' ' + icon;
225
+ }
226
+
227
+ methods._setIcon.call(that, this, icon);
228
+
229
+ if (that.opt.mouseout) {
230
+ var score = +that.score.val() || undefined;
231
+
232
+ that.opt.mouseout.call(that, score, evt);
233
+ }
234
+ });
235
+ },
236
+
237
+ _bindOver: function() {
238
+ var that = this,
239
+ action = that.opt.half ? 'mousemove.raty' : 'mouseover.raty';
240
+
241
+ that.stars.on(action, function(evt) {
242
+ var score = methods._getScoreByPosition.call(that, evt, this);
243
+
244
+ methods._fill.call(that, score);
245
+
246
+ if (that.opt.half) {
247
+ methods._roundStars.call(that, score, evt);
248
+ methods._setTitle.call(that, score, evt);
249
+
250
+ that.self.data('score', score);
251
+ }
252
+
253
+ methods._target.call(that, score, evt);
254
+
255
+ if (that.opt.mouseover) {
256
+ that.opt.mouseover.call(that, score, evt);
257
+ }
258
+ });
259
+ },
260
+
261
+ _bindOverCancel: function() {
262
+ var that = this;
263
+
264
+ that.cancel.on('mouseover.raty', function(evt) {
265
+ var
266
+ starOff = that.opt.path + that.opt.starOff,
267
+ icon = that.opt.cancelOn;
268
+
269
+ if (that.opt.starType === 'img') {
270
+ that.stars.attr('src', starOff);
271
+ } else {
272
+ icon = that.opt.cancelClass + ' ' + icon;
273
+
274
+ that.stars.attr('class', starOff);
275
+ }
276
+
277
+ methods._setIcon.call(that, this, icon);
278
+ methods._target.call(that, null, evt);
279
+
280
+ if (that.opt.mouseover) {
281
+ that.opt.mouseover.call(that, null);
282
+ }
283
+ });
284
+ },
285
+
286
+ _buildScoreField: function() {
287
+ return $('<input />', { name: this.opt.scoreName, type: 'hidden' }).appendTo(this);
288
+ },
289
+
290
+ _createCancel: function() {
291
+ var icon = this.opt.path + this.opt.cancelOff,
292
+ cancel = $('<' + this.opt.starType + ' />', { title: this.opt.cancelHint, 'class': this.opt.cancelClass });
293
+
294
+ if (this.opt.starType === 'img') {
295
+ cancel.attr({ src: icon, alt: 'x' });
296
+ } else {
297
+ // TODO: use $.data
298
+ cancel.attr('data-alt', 'x').addClass(icon);
299
+ }
300
+
301
+ if (this.opt.cancelPlace === 'left') {
302
+ this.self.prepend('&#160;').prepend(cancel);
303
+ } else {
304
+ this.self.append('&#160;').append(cancel);
305
+ }
306
+
307
+ this.cancel = cancel;
308
+ },
309
+
310
+ _createScore: function() {
311
+ var score = $(this.opt.targetScore);
312
+
313
+ this.score = score.length ? score : methods._buildScoreField.call(this);
314
+ },
315
+
316
+ _createStars: function() {
317
+ for (var i = 1; i <= this.opt.number; i++) {
318
+ var
319
+ name = methods._nameForIndex.call(this, i),
320
+ attrs = { alt: i, src: this.opt.path + this.opt[name] };
321
+
322
+ if (this.opt.starType !== 'img') {
323
+ attrs = { 'data-alt': i, 'class': attrs.src }; // TODO: use $.data.
324
+ }
325
+
326
+ attrs.title = methods._getHint.call(this, i);
327
+
328
+ $('<' + this.opt.starType + ' />', attrs).appendTo(this);
329
+
330
+ if (this.opt.space) {
331
+ this.self.append(i < this.opt.number ? '&#160;' : '');
332
+ }
333
+ }
334
+
335
+ this.stars = this.self.children(this.opt.starType);
336
+ },
337
+
338
+ _error: function(message) {
339
+ $(this).text(message);
340
+
341
+ $.error(message);
342
+ },
24
343
 
25
- var methods = {
26
- init: function(settings) {
27
- return this.each(function() {
28
- var self = this,
29
- $this = $(self).empty();
344
+ _fill: function(score) {
345
+ var hash = 0;
30
346
 
31
- self.opt = $.extend(true, {}, $.fn.raty.defaults, settings);
347
+ for (var i = 1; i <= this.stars.length; i++) {
348
+ var
349
+ icon,
350
+ star = this.stars[i - 1],
351
+ turnOn = methods._turnOn.call(this, i, score);
32
352
 
33
- $this.data('settings', self.opt);
353
+ if (this.opt.iconRange && this.opt.iconRange.length > hash) {
354
+ var irange = this.opt.iconRange[hash];
34
355
 
35
- if (typeof self.opt.number == 'function') {
36
- self.opt.number = self.opt.number.call(self);
37
- } else {
38
- self.opt.number = methods.between(self.opt.number, 0, 20)
39
- }
356
+ icon = methods._getRangeIcon.call(this, irange, turnOn);
40
357
 
41
- if (self.opt.path.substring(self.opt.path.length - 1, self.opt.path.length) != '/') {
42
- self.opt.path += '/';
43
- }
358
+ if (i <= irange.range) {
359
+ methods._setIcon.call(this, star, icon);
360
+ }
44
361
 
45
- if (typeof self.opt.score == 'function') {
46
- self.opt.score = self.opt.score.call(self);
47
- }
362
+ if (i === irange.range) {
363
+ hash++;
364
+ }
365
+ } else {
366
+ icon = this.opt[turnOn ? 'starOn' : 'starOff'];
48
367
 
49
- if (self.opt.score) {
50
- self.opt.score = methods.between(self.opt.score, 0, self.opt.number);
51
- }
368
+ methods._setIcon.call(this, star, icon);
369
+ }
370
+ }
371
+ },
52
372
 
53
- for (var i = 1; i <= self.opt.number; i++) {
54
- $('<img />', {
55
- src : self.opt.path + ((!self.opt.score || self.opt.score < i) ? self.opt.starOff : self.opt.starOn),
56
- alt : i,
57
- title : (i <= self.opt.hints.length && self.opt.hints[i - 1] !== null) ? self.opt.hints[i - 1] : i
58
- }).appendTo(self);
373
+ _getFirstDecimal: function(number) {
374
+ var
375
+ decimal = number.toString().split('.')[1],
376
+ result = 0;
59
377
 
60
- if (self.opt.space) {
61
- $this.append((i < self.opt.number) ? '&#160;' : '');
62
- }
63
- }
378
+ if (decimal) {
379
+ result = parseInt(decimal.charAt(0), 10);
64
380
 
65
- self.stars = $this.children('img:not(".raty-cancel")');
66
- self.score = $('<input />', { type: 'hidden', name: self.opt.scoreName }).appendTo(self);
381
+ if (decimal.slice(1, 5) === '9999') {
382
+ result++;
383
+ }
384
+ }
67
385
 
68
- if (self.opt.score && self.opt.score > 0) {
69
- self.score.val(self.opt.score);
70
- methods.roundStar.call(self, self.opt.score);
71
- }
386
+ return result;
387
+ },
72
388
 
73
- if (self.opt.iconRange) {
74
- methods.fill.call(self, self.opt.score);
75
- }
389
+ _getRangeIcon: function(irange, turnOn) {
390
+ return turnOn ? irange.on || this.opt.starOn : irange.off || this.opt.starOff;
391
+ },
76
392
 
77
- methods.setTarget.call(self, self.opt.score, self.opt.targetKeep);
393
+ _getScoreByPosition: function(evt, icon) {
394
+ var score = parseInt(icon.alt || icon.getAttribute('data-alt'), 10);
78
395
 
79
- var space = self.opt.space ? 4 : 0,
80
- width = self.opt.width || (self.opt.number * self.opt.size + self.opt.number * space);
396
+ if (this.opt.half) {
397
+ var
398
+ size = methods._getWidth.call(this),
399
+ percent = parseFloat((evt.pageX - $(icon).offset().left) / size);
81
400
 
82
- if (self.opt.cancel) {
83
- self.cancel = $('<img />', { src: self.opt.path + self.opt.cancelOff, alt: 'x', title: self.opt.cancelHint, 'class': 'raty-cancel' });
401
+ score = score - 1 + percent;
402
+ }
84
403
 
85
- if (self.opt.cancelPlace == 'left') {
86
- $this.prepend('&#160;').prepend(self.cancel);
87
- } else {
88
- $this.append('&#160;').append(self.cancel);
89
- }
404
+ return score;
405
+ },
90
406
 
91
- width += (self.opt.size + space);
92
- }
407
+ _getHint: function(score, evt) {
408
+ if (score !== 0 && !score) {
409
+ return this.opt.noRatedMsg;
410
+ }
93
411
 
94
- if (self.opt.readOnly) {
95
- methods.fixHint.call(self);
412
+ var
413
+ decimal = methods._getFirstDecimal.call(this, score),
414
+ integer = Math.ceil(score),
415
+ group = this.opt.hints[(integer || 1) - 1],
416
+ hint = group,
417
+ set = !evt || this.move;
96
418
 
97
- if (self.cancel) {
98
- self.cancel.hide();
99
- }
100
- } else {
101
- $this.css('cursor', 'pointer');
419
+ if (this.opt.precision) {
420
+ if (set) {
421
+ decimal = decimal === 0 ? 9 : decimal - 1;
422
+ }
102
423
 
103
- methods.bindAction.call(self);
104
- }
105
-
106
- $this.css('width', width);
107
- });
108
- }, between: function(value, min, max) {
109
- return Math.min(Math.max(parseFloat(value), min), max);
110
- }, bindAction: function() {
111
- var self = this,
112
- $this = $(self);
113
-
114
- $this.mouseleave(function() {
115
- var score = self.score.val() || undefined;
116
-
117
- methods.initialize.call(self, score);
118
- methods.setTarget.call(self, score, self.opt.targetKeep);
119
-
120
- if (self.opt.mouseover) {
121
- self.opt.mouseover.call(self, score);
122
- }
123
- });
124
-
125
- var action = self.opt.half ? 'mousemove' : 'mouseover';
126
-
127
- if (self.opt.cancel) {
128
- self.cancel.mouseenter(function() {
129
- $(this).attr('src', self.opt.path + self.opt.cancelOn);
130
-
131
- self.stars.attr('src', self.opt.path + self.opt.starOff);
132
-
133
- methods.setTarget.call(self, null, true);
134
-
135
- if (self.opt.mouseover) {
136
- self.opt.mouseover.call(self, null);
137
- }
138
- }).mouseleave(function() {
139
- $(this).attr('src', self.opt.path + self.opt.cancelOff);
140
-
141
- if (self.opt.mouseover) {
142
- self.opt.mouseover.call(self, self.score.val() || null);
143
- }
144
- }).click(function(evt) {
145
- self.score.removeAttr('value');
146
-
147
- if (self.opt.click) {
148
- self.opt.click.call(self, null, evt);
149
- }
150
- });
151
- }
152
-
153
- self.stars.bind(action, function(evt) {
154
- var value = parseInt(this.alt, 10);
155
-
156
- if (self.opt.half) {
157
- var position = parseFloat((evt.pageX - $(this).offset().left) / self.opt.size),
158
- diff = (position > .5) ? 1 : .5;
159
-
160
- value = parseFloat(this.alt) - 1 + diff;
161
-
162
- methods.fill.call(self, value);
163
-
164
- if (self.opt.precision) {
165
- value = value - diff + position;
166
- }
167
-
168
- methods.showHalf.call(self, value);
169
- } else {
170
- methods.fill.call(self, value);
171
- }
172
-
173
- $this.data('score', value);
174
-
175
- methods.setTarget.call(self, value, true);
176
-
177
- if (self.opt.mouseover) {
178
- self.opt.mouseover.call(self, value, evt);
179
- }
180
- }).click(function(evt) {
181
- self.score.val((self.opt.half || self.opt.precision) ? $this.data('score') : this.alt);
182
-
183
- if (self.opt.click) {
184
- self.opt.click.call(self, self.score.val(), evt);
185
- }
186
- });
187
- }, cancel: function(isClick) {
188
- return $(this).each(function() {
189
- var self = this,
190
- $this = $(self);
191
-
192
- if ($this.data('readonly') === true) {
193
- return this;
194
- }
195
-
196
- if (isClick) {
197
- methods.click.call(self, null);
198
- } else {
199
- methods.score.call(self, null);
200
- }
201
-
202
- self.score.removeAttr('value');
203
- });
204
- }, click: function(score) {
205
- return $(this).each(function() {
206
- if ($(this).data('readonly') === true) {
207
- return this;
208
- }
209
-
210
- methods.initialize.call(this, score);
211
-
212
- if (this.opt.click) {
213
- this.opt.click.call(this, score);
214
- } else {
215
- methods.error.call(this, 'you must add the "click: function(score, evt) { }" callback.');
216
- }
217
-
218
- methods.setTarget.call(this, score, true);
219
- });
220
- }, error: function(message) {
221
- $(this).html(message);
222
-
223
- $.error(message);
224
- }, fill: function(score) {
225
- var self = this,
226
- number = self.stars.length,
227
- count = 0,
228
- $star ,
229
- star ,
230
- icon ;
231
-
232
- for (var i = 1; i <= number; i++) {
233
- $star = self.stars.eq(i - 1);
234
-
235
- if (self.opt.iconRange && self.opt.iconRange.length > count) {
236
- star = self.opt.iconRange[count];
237
-
238
- if (self.opt.single) {
239
- icon = (i == score) ? (star.on || self.opt.starOn) : (star.off || self.opt.starOff);
240
- } else {
241
- icon = (i <= score) ? (star.on || self.opt.starOn) : (star.off || self.opt.starOff);
242
- }
243
-
244
- if (i <= star.range) {
245
- $star.attr('src', self.opt.path + icon);
246
- }
247
-
248
- if (i == star.range) {
249
- count++;
250
- }
251
- } else {
252
- if (self.opt.single) {
253
- icon = (i == score) ? self.opt.starOn : self.opt.starOff;
254
- } else {
255
- icon = (i <= score) ? self.opt.starOn : self.opt.starOff;
256
- }
257
-
258
- $star.attr('src', self.opt.path + icon);
259
- }
260
- }
261
- }, fixHint: function() {
262
- var $this = $(this),
263
- score = parseInt(this.score.val(), 10),
264
- hint = this.opt.noRatedMsg;
265
-
266
- if (!isNaN(score) && score > 0) {
267
- hint = (score <= this.opt.hints.length && this.opt.hints[score - 1] !== null) ? this.opt.hints[score - 1] : score;
268
- }
269
-
270
- $this.data('readonly', true).css('cursor', 'default').attr('title', hint);
271
-
272
- this.score.attr('readonly', 'readonly');
273
- this.stars.attr('title', hint);
274
- }, getScore: function() {
275
- var score = [],
276
- value ;
277
-
278
- $(this).each(function() {
279
- value = this.score.val();
280
-
281
- score.push(value ? parseFloat(value) : undefined);
282
- });
283
-
284
- return (score.length > 1) ? score : score[0];
285
- }, readOnly: function(isReadOnly) {
286
- return this.each(function() {
287
- var $this = $(this);
288
-
289
- if ($this.data('readonly') === isReadOnly) {
290
- return this;
291
- }
292
-
293
- if (this.cancel) {
294
- if (isReadOnly) {
295
- this.cancel.hide();
296
- } else {
297
- this.cancel.show();
298
- }
299
- }
300
-
301
- if (isReadOnly) {
302
- $this.unbind();
303
-
304
- $this.children('img').unbind();
305
-
306
- methods.fixHint.call(this);
307
- } else {
308
- methods.bindAction.call(this);
309
- methods.unfixHint.call(this);
310
- }
311
-
312
- $this.data('readonly', isReadOnly);
313
- });
314
- }, reload: function() {
315
- return methods.set.call(this, {});
316
- }, roundStar: function(score) {
317
- var diff = (score - Math.floor(score)).toFixed(2);
318
-
319
- if (diff > this.opt.round.down) {
320
- var icon = this.opt.starOn; // Full up: [x.76 .. x.99]
321
-
322
- if (diff < this.opt.round.up && this.opt.halfShow) { // Half: [x.26 .. x.75]
323
- icon = this.opt.starHalf;
324
- } else if (diff < this.opt.round.full) { // Full down: [x.00 .. x.5]
325
- icon = this.opt.starOff;
326
- }
327
-
328
- this.stars.eq(Math.ceil(score) - 1).attr('src', this.opt.path + icon);
329
- } // Full down: [x.00 .. x.25]
330
- }, score: function() {
331
- return arguments.length ? methods.setScore.apply(this, arguments) : methods.getScore.call(this);
332
- }, set: function(settings) {
333
- this.each(function() {
334
- var $this = $(this),
335
- actual = $this.data('settings'),
336
- clone = $this.clone().removeAttr('style').insertBefore($this);
337
-
338
- $this.remove();
339
-
340
- clone.raty($.extend(actual, settings));
341
- });
342
-
343
- return $(this.selector);
344
- }, setScore: function(score) {
345
- return $(this).each(function() {
346
- if ($(this).data('readonly') === true) {
347
- return this;
348
- }
349
-
350
- methods.initialize.call(this, score);
351
- methods.setTarget.call(this, score, true);
352
- });
353
- }, setTarget: function(value, isKeep) {
354
- if (this.opt.target) {
355
- var $target = $(this.opt.target);
356
-
357
- if ($target.length == 0) {
358
- methods.error.call(this, 'target selector invalid or missing!');
359
- }
360
-
361
- var score = value;
362
-
363
- if (!isKeep || score === undefined) {
364
- score = this.opt.targetText;
365
- } else {
366
- if (this.opt.targetType == 'hint') {
367
- score = (score === null && this.opt.cancel)
368
- ? this.opt.cancelHint
369
- : this.opt.hints[Math.ceil(score - 1)];
370
- } else {
371
- score = this.opt.precision
372
- ? parseFloat(score).toFixed(1)
373
- : score;
374
- }
375
- }
376
-
377
- if (this.opt.targetFormat.indexOf('{score}') < 0) {
378
- methods.error.call(this, 'template "{score}" missing!');
379
- }
380
-
381
- if (value !== null) {
382
- score = this.opt.targetFormat.toString().replace('{score}', score);
383
- }
384
-
385
- if ($target.is(':input')) {
386
- $target.val(score);
387
- } else {
388
- $target.html(score);
389
- }
390
- }
391
- }, showHalf: function(score) {
392
- var diff = (score - Math.floor(score)).toFixed(1);
393
-
394
- if (diff > 0 && diff < .6) {
395
- this.stars.eq(Math.ceil(score) - 1).attr('src', this.opt.path + this.opt.starHalf);
396
- }
397
- }, initialize: function(score) {
398
- score = !score ? 0 : methods.between(score, 0, this.opt.number);
399
-
400
- methods.fill.call(this, score);
401
-
402
- if (score > 0) {
403
- if (this.opt.halfShow) {
404
- methods.roundStar.call(this, score);
405
- }
406
-
407
- this.score.val(score);
408
- }
409
- }, unfixHint: function() {
410
- for (var i = 0; i < this.opt.number; i++) {
411
- this.stars.eq(i).attr('title', (i < this.opt.hints.length && this.opt.hints[i] !== null) ? this.opt.hints[i] : i);
412
- }
413
-
414
- $(this).data('readonly', false).css('cursor', 'pointer').removeAttr('title');
415
-
416
- this.score.attr('readonly', 'readonly');
417
- }
418
- };
419
-
420
- $.fn.raty = function(method) {
421
- if (methods[method]) {
422
- return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
423
- } else if (typeof method === 'object' || !method) {
424
- return methods.init.apply(this, arguments);
425
- } else {
426
- $.error('Method ' + method + ' does not exist!');
427
- }
428
- };
429
-
430
- $.fn.raty.defaults = {
431
- cancel : false,
432
- cancelHint : 'cancel this rating!',
433
- cancelOff : 'cancel-off.png',
434
- cancelOn : 'cancel-on.png',
435
- cancelPlace : 'left',
436
- click : undefined,
437
- half : false,
438
- halfShow : true,
439
- hints : ['bad', 'poor', 'regular', 'good', 'gorgeous'],
440
- iconRange : undefined,
441
- mouseover : undefined,
442
- noRatedMsg : 'not rated yet',
443
- number : 5,
444
- path : 'img/',
445
- precision : false,
446
- round : { down: .25, full: .6, up: .76 },
447
- readOnly : false,
448
- score : undefined,
449
- scoreName : 'score',
450
- single : false,
451
- size : 16,
452
- space : true,
453
- starHalf : 'star-half.png',
454
- starOff : 'star-off.png',
455
- starOn : 'star-on.png',
456
- target : undefined,
457
- targetFormat : '{score}',
458
- targetKeep : false,
459
- targetText : '',
460
- targetType : 'hint',
461
- width : undefined
462
- };
424
+ hint = group[decimal];
425
+ } else if (this.opt.halfShow || this.opt.half) {
426
+ decimal = set && decimal === 0 ? 1 : decimal > 5 ? 1 : 0;
427
+
428
+ hint = group[decimal];
429
+ }
430
+
431
+ return hint === '' ? '' : hint || score;
432
+ },
433
+
434
+ _getWidth: function() {
435
+ var width = this.stars[0].width || parseFloat(this.stars.eq(0).css('font-size'));
436
+
437
+ if (!width) {
438
+ methods._error.call(this, 'Could not get the icon width!');
439
+ }
440
+
441
+ return width;
442
+ },
443
+
444
+ _lock: function() {
445
+ var hint = methods._getHint.call(this, this.score.val());
446
+
447
+ this.style.cursor = '';
448
+ this.title = hint;
449
+
450
+ this.score.prop('readonly', true);
451
+ this.stars.prop('title', hint);
452
+
453
+ if (this.cancel) {
454
+ this.cancel.hide();
455
+ }
456
+
457
+ this.self.data('readonly', true);
458
+ },
459
+
460
+ _nameForIndex: function(i) {
461
+ return this.opt.score && this.opt.score >= i ? 'starOn' : 'starOff';
462
+ },
463
+
464
+ _resetTitle: function(star) {
465
+ for (var i = 0; i < this.opt.number; i++) {
466
+ this.stars[i].title = methods._getHint.call(this, i + 1);
467
+ }
468
+ },
469
+
470
+ _roundHalfScore: function(score) {
471
+ var integer = parseInt(score, 10),
472
+ decimal = methods._getFirstDecimal.call(this, score);
473
+
474
+ if (decimal !== 0) {
475
+ decimal = decimal > 5 ? 1 : 0.5;
476
+ }
477
+
478
+ return integer + decimal;
479
+ },
480
+
481
+ _roundStars: function(score, evt) {
482
+ var
483
+ decimal = (score % 1).toFixed(2),
484
+ name ;
485
+
486
+ if (evt || this.move) {
487
+ name = decimal > 0.5 ? 'starOn' : 'starHalf';
488
+ } else if (decimal > this.opt.round.down) { // Up: [x.76 .. x.99]
489
+ name = 'starOn';
490
+
491
+ if (this.opt.halfShow && decimal < this.opt.round.up) { // Half: [x.26 .. x.75]
492
+ name = 'starHalf';
493
+ } else if (decimal < this.opt.round.full) { // Down: [x.00 .. x.5]
494
+ name = 'starOff';
495
+ }
496
+ }
497
+
498
+ if (name) {
499
+ var
500
+ icon = this.opt[name],
501
+ star = this.stars[Math.ceil(score) - 1];
502
+
503
+ methods._setIcon.call(this, star, icon);
504
+ } // Full down: [x.00 .. x.25]
505
+ },
506
+
507
+ _setIcon: function(star, icon) {
508
+ star[this.opt.starType === 'img' ? 'src' : 'className'] = this.opt.path + icon;
509
+ },
510
+
511
+ _setTarget: function(target, score) {
512
+ if (score) {
513
+ score = this.opt.targetFormat.toString().replace('{score}', score);
514
+ }
515
+
516
+ if (target.is(':input')) {
517
+ target.val(score);
518
+ } else {
519
+ target.html(score);
520
+ }
521
+ },
522
+
523
+ _setTitle: function(score, evt) {
524
+ if (score) {
525
+ var
526
+ integer = parseInt(Math.ceil(score), 10),
527
+ star = this.stars[integer - 1];
528
+
529
+ star.title = methods._getHint.call(this, score, evt);
530
+ }
531
+ },
532
+
533
+ _target: function(score, evt) {
534
+ if (this.opt.target) {
535
+ var target = $(this.opt.target);
536
+
537
+ if (!target.length) {
538
+ methods._error.call(this, 'Target selector invalid or missing!');
539
+ }
540
+
541
+ var mouseover = evt && evt.type === 'mouseover';
542
+
543
+ if (score === undefined) {
544
+ score = this.opt.targetText;
545
+ } else if (score === null) {
546
+ score = mouseover ? this.opt.cancelHint : this.opt.targetText;
547
+ } else {
548
+ if (this.opt.targetType === 'hint') {
549
+ score = methods._getHint.call(this, score, evt);
550
+ } else if (this.opt.precision) {
551
+ score = parseFloat(score).toFixed(1);
552
+ }
553
+
554
+ var mousemove = evt && evt.type === 'mousemove';
555
+
556
+ if (!mouseover && !mousemove && !this.opt.targetKeep) {
557
+ score = this.opt.targetText;
558
+ }
559
+ }
560
+
561
+ methods._setTarget.call(this, target, score);
562
+ }
563
+ },
564
+
565
+ _turnOn: function(i, score) {
566
+ return this.opt.single ? (i === score) : (i <= score);
567
+ },
568
+
569
+ _unlock: function() {
570
+ this.style.cursor = 'pointer';
571
+ this.removeAttribute('title');
572
+
573
+ this.score.removeAttr('readonly');
574
+
575
+ this.self.data('readonly', false);
576
+
577
+ for (var i = 0; i < this.opt.number; i++) {
578
+ this.stars[i].title = methods._getHint.call(this, i + 1);
579
+ }
580
+
581
+ if (this.cancel) {
582
+ this.cancel.css('display', '');
583
+ }
584
+ },
585
+
586
+ cancel: function(click) {
587
+ return this.each(function() {
588
+ var self = $(this);
589
+
590
+ if (self.data('readonly') !== true) {
591
+ methods[click ? 'click' : 'score'].call(self, null);
592
+
593
+ this.score.removeAttr('value');
594
+ }
595
+ });
596
+ },
597
+
598
+ click: function(score) {
599
+ return this.each(function() {
600
+ if ($(this).data('readonly') !== true) {
601
+ score = methods._adjustedScore.call(this, score);
602
+
603
+ methods._apply.call(this, score);
604
+
605
+ if (this.opt.click) {
606
+ this.opt.click.call(this, score, $.Event('click'));
607
+ }
608
+
609
+ methods._target.call(this, score);
610
+ }
611
+ });
612
+ },
613
+
614
+ destroy: function() {
615
+ return this.each(function() {
616
+ var self = $(this),
617
+ raw = self.data('raw');
618
+
619
+ if (raw) {
620
+ self.off('.raty').empty().css({ cursor: raw.style.cursor }).removeData('readonly');
621
+ } else {
622
+ self.data('raw', self.clone()[0]);
623
+ }
624
+ });
625
+ },
626
+
627
+ getScore: function() {
628
+ var score = [],
629
+ value ;
630
+
631
+ this.each(function() {
632
+ value = this.score.val();
633
+
634
+ score.push(value ? +value : undefined);
635
+ });
636
+
637
+ return (score.length > 1) ? score : score[0];
638
+ },
639
+
640
+ move: function(score) {
641
+ return this.each(function() {
642
+ var
643
+ integer = parseInt(score, 10),
644
+ decimal = methods._getFirstDecimal.call(this, score);
645
+
646
+ if (integer >= this.opt.number) {
647
+ integer = this.opt.number - 1;
648
+ decimal = 10;
649
+ }
650
+
651
+ var
652
+ width = methods._getWidth.call(this),
653
+ steps = width / 10,
654
+ star = $(this.stars[integer]),
655
+ percent = star.offset().left + steps * decimal,
656
+ evt = $.Event('mousemove', { pageX: percent });
657
+
658
+ this.move = true;
659
+
660
+ star.trigger(evt);
661
+
662
+ this.move = false;
663
+ });
664
+ },
665
+
666
+ readOnly: function(readonly) {
667
+ return this.each(function() {
668
+ var self = $(this);
669
+
670
+ if (self.data('readonly') !== readonly) {
671
+ if (readonly) {
672
+ self.off('.raty').children('img').off('.raty');
673
+
674
+ methods._lock.call(this);
675
+ } else {
676
+ methods._binds.call(this);
677
+ methods._unlock.call(this);
678
+ }
679
+
680
+ self.data('readonly', readonly);
681
+ }
682
+ });
683
+ },
684
+
685
+ reload: function() {
686
+ return methods.set.call(this, {});
687
+ },
688
+
689
+ score: function() {
690
+ var self = $(this);
691
+
692
+ return arguments.length ? methods.setScore.apply(self, arguments) : methods.getScore.call(self);
693
+ },
694
+
695
+ set: function(options) {
696
+ return this.each(function() {
697
+ $(this).raty($.extend({}, this.opt, options));
698
+ });
699
+ },
700
+
701
+ setScore: function(score) {
702
+ return this.each(function() {
703
+ if ($(this).data('readonly') !== true) {
704
+ score = methods._adjustedScore.call(this, score);
705
+
706
+ methods._apply.call(this, score);
707
+ methods._target.call(this, score);
708
+ }
709
+ });
710
+ }
711
+ };
712
+
713
+ $.fn.raty = function(method) {
714
+ if (methods[method]) {
715
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
716
+ } else if (typeof method === 'object' || !method) {
717
+ return methods.init.apply(this, arguments);
718
+ } else {
719
+ $.error('Method ' + method + ' does not exist!');
720
+ }
721
+ };
722
+
723
+ $.fn.raty.defaults = {
724
+ cancel : false,
725
+ cancelClass : 'raty-cancel',
726
+ cancelHint : 'Cancel this rating!',
727
+ cancelOff : 'cancel-off.png',
728
+ cancelOn : 'cancel-on.png',
729
+ cancelPlace : 'left',
730
+ click : undefined,
731
+ half : false,
732
+ halfShow : true,
733
+ hints : ['bad', 'poor', 'regular', 'good', 'gorgeous'],
734
+ iconRange : undefined,
735
+ mouseout : undefined,
736
+ mouseover : undefined,
737
+ noRatedMsg : 'Not rated yet!',
738
+ number : 5,
739
+ numberMax : 20,
740
+ path : undefined,
741
+ precision : false,
742
+ readOnly : false,
743
+ round : { down: 0.25, full: 0.6, up: 0.76 },
744
+ score : undefined,
745
+ scoreName : 'score',
746
+ single : false,
747
+ space : true,
748
+ starHalf : 'star-half.png',
749
+ starOff : 'star-off.png',
750
+ starOn : 'star-on.png',
751
+ starType : 'img',
752
+ target : undefined,
753
+ targetFormat : '{score}',
754
+ targetKeep : false,
755
+ targetScore : undefined,
756
+ targetText : '',
757
+ targetType : 'hint'
758
+ };
463
759
 
464
760
  })(jQuery);