solidus_reviews 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +322 -0
  3. data/.travis.yml +27 -14
  4. data/Gemfile +23 -8
  5. data/LICENSE.md +2 -2
  6. data/README.md +9 -11
  7. data/Rakefile +2 -0
  8. data/app/controllers/spree/admin/feedback_reviews_controller.rb +3 -1
  9. data/app/controllers/spree/admin/review_settings_controller.rb +3 -1
  10. data/app/controllers/spree/admin/reviews_controller.rb +9 -6
  11. data/app/controllers/spree/feedback_reviews_controller.rb +25 -19
  12. data/app/controllers/spree/products_controller_decorator.rb +2 -0
  13. data/app/controllers/spree/reviews_controller.rb +11 -7
  14. data/app/helpers/spree/api/api_helpers_decorator.rb +12 -0
  15. data/app/helpers/spree/reviews_helper.rb +15 -5
  16. data/app/models/spree/feedback_review.rb +5 -4
  17. data/app/models/spree/product_decorator.rb +5 -4
  18. data/app/models/spree/review.rb +28 -10
  19. data/app/models/spree/reviews_ability.rb +17 -3
  20. data/app/models/spree/reviews_configuration.rb +16 -8
  21. data/app/models/spree/user_decorator.rb +3 -0
  22. data/app/overrides/add_reviews_after_product_properties.rb +7 -5
  23. data/app/overrides/add_reviews_tab_to_admin.rb +12 -4
  24. data/app/overrides/add_reviews_to_admin_configuration_sidebar.rb +13 -5
  25. data/app/views/spree/admin/feedback_reviews/index.html.erb +9 -9
  26. data/app/views/spree/admin/review_settings/edit.html.erb +64 -35
  27. data/app/views/spree/admin/reviews/_form.html.erb +26 -5
  28. data/app/views/spree/admin/reviews/edit.html.erb +2 -2
  29. data/app/views/spree/admin/reviews/index.html.erb +100 -88
  30. data/app/views/spree/api/reviews/_review.json.jbuilder +8 -0
  31. data/app/views/spree/api/reviews/index.json.jbuilder +6 -0
  32. data/app/views/spree/api/reviews/show.json.jbuilder +3 -0
  33. data/app/views/spree/feedback_reviews/_form.html.erb +5 -5
  34. data/app/views/spree/feedback_reviews/_summary.html.erb +3 -3
  35. data/app/views/spree/feedback_reviews/create.js.erb +2 -2
  36. data/app/views/spree/reviews/_form.html.erb +15 -10
  37. data/app/views/spree/reviews/new.html.erb +2 -2
  38. data/app/views/spree/shared/_rating.html.erb +3 -3
  39. data/app/views/spree/shared/_review.html.erb +29 -19
  40. data/app/views/spree/shared/_review_summary.html.erb +3 -3
  41. data/app/views/spree/shared/_reviews.html.erb +6 -6
  42. data/app/views/spree/shared/_shortrating.html.erb +2 -2
  43. data/bin/rails +4 -2
  44. data/config/initializers/constants.rb +2 -0
  45. data/config/initializers/load_preferences.rb +2 -0
  46. data/config/locales/de-CH.yml +14 -1
  47. data/config/locales/de.yml +14 -1
  48. data/config/locales/en-GB.yml +14 -2
  49. data/config/locales/en.yml +14 -1
  50. data/config/locales/es.yml +14 -2
  51. data/config/locales/fr.yml +14 -2
  52. data/config/locales/it.yml +79 -0
  53. data/config/locales/pl.yml +14 -2
  54. data/config/locales/pt-BR.yml +14 -2
  55. data/config/locales/pt.yml +14 -2
  56. data/config/locales/ro.yml +15 -3
  57. data/config/locales/ru.yml +14 -2
  58. data/config/locales/sv.yml +14 -1
  59. data/config/locales/tr.yml +14 -2
  60. data/config/locales/uk.yml +14 -1
  61. data/config/locales/zh-CN.yml +14 -1
  62. data/config/locales/zh-TW.yml +14 -1
  63. data/config/routes.rb +18 -1
  64. data/db/migrate/20081020220724_create_reviews.rb +4 -2
  65. data/db/migrate/20101222083309_create_feedback_reviews.rb +5 -3
  66. data/db/migrate/20110406083603_add_rating_to_products.rb +7 -5
  67. data/db/migrate/20110606150524_add_user_to_reviews.rb +4 -2
  68. data/db/migrate/20110806093221_add_ip_address_to_reviews.rb +3 -1
  69. data/db/migrate/20120110172331_namespace_tables.rb +3 -1
  70. data/db/migrate/20120123141326_recalculate_ratings.rb +6 -5
  71. data/db/migrate/20120712182514_add_locale_to_reviews.rb +4 -2
  72. data/db/migrate/20120712182627_add_locale_to_feedback_reviews.rb +4 -2
  73. data/db/migrate/20140703200946_add_show_identifier_to_reviews.rb +3 -1
  74. data/db/migrate/20190613165528_add_verified_purchaser_to_reviews.rb +5 -0
  75. data/lib/controllers/spree/api/reviews_controller.rb +111 -0
  76. data/lib/generators/solidus_reviews/install/install_generator.rb +5 -4
  77. data/lib/solidus_reviews.rb +3 -1
  78. data/lib/solidus_reviews/factories.rb +3 -1
  79. data/lib/solidus_reviews/factories/feedback_review_factory.rb +6 -5
  80. data/lib/solidus_reviews/factories/review_factory.rb +19 -9
  81. data/lib/spree_reviews/engine.rb +7 -0
  82. data/solidus_reviews.gemspec +20 -18
  83. data/spec/controllers/admin/feedback_reviews_controller_spec.rb +9 -7
  84. data/spec/controllers/admin/review_settings_controller_spec.rb +18 -16
  85. data/spec/controllers/admin/reviews_controller_spec.rb +18 -16
  86. data/spec/controllers/feedback_reviews_controller_spec.rb +29 -25
  87. data/spec/controllers/products_controller_spec.rb +4 -2
  88. data/spec/controllers/reviews_controller_spec.rb +67 -40
  89. data/spec/controllers/spree/api/reviews_controller_spec.rb +233 -0
  90. data/spec/features/admin_spec.rb +3 -0
  91. data/spec/features/reviews_spec.rb +27 -11
  92. data/spec/helpers/review_helper_spec.rb +3 -2
  93. data/spec/models/feedback_review_spec.rb +19 -17
  94. data/spec/models/product_spec.rb +41 -19
  95. data/spec/models/review_spec.rb +100 -42
  96. data/spec/models/reviews_ability_spec.rb +10 -8
  97. data/spec/models/reviews_configuration_spec.rb +28 -19
  98. data/spec/spec_helper.rb +21 -35
  99. data/vendor/assets/javascripts/jquery.rating.js +389 -376
  100. metadata +108 -59
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  require "cancan/matchers"
@@ -6,9 +8,9 @@ describe Spree::ReviewsAbility do
6
8
  context '.allow_anonymous_reviews?' do
7
9
  it 'should depend on Spree::Reviews::Config[:require_login]' do
8
10
  Spree::Reviews::Config[:require_login] = false
9
- Spree::ReviewsAbility.allow_anonymous_reviews?.should be true
11
+ expect(Spree::ReviewsAbility.allow_anonymous_reviews?).to be true
10
12
  Spree::Reviews::Config[:require_login] = true
11
- Spree::ReviewsAbility.allow_anonymous_reviews?.should be false
13
+ expect(Spree::ReviewsAbility.allow_anonymous_reviews?).to be false
12
14
  end
13
15
  end
14
16
 
@@ -23,8 +25,8 @@ describe Spree::ReviewsAbility do
23
25
 
24
26
  it 'lets anyone create a review or feedback review' do
25
27
  [user_without_email, user_with_email].each do |u|
26
- Spree::ReviewsAbility.new(u).should be_able_to(:create, Spree::Review.new)
27
- Spree::ReviewsAbility.new(u).should be_able_to(:create, Spree::FeedbackReview.new)
28
+ expect(Spree::ReviewsAbility.new(u)).to be_able_to(:create, Spree::Review.new)
29
+ expect(Spree::ReviewsAbility.new(u)).to be_able_to(:create, Spree::FeedbackReview.new)
28
30
  end
29
31
  end
30
32
  end
@@ -35,11 +37,11 @@ describe Spree::ReviewsAbility do
35
37
  end
36
38
 
37
39
  it 'only allows users with an email to create a review or feedback review' do
38
- Spree::ReviewsAbility.new(user_without_email).should_not be_able_to(:create, Spree::Review.new)
39
- Spree::ReviewsAbility.new(user_without_email).should_not be_able_to(:create, Spree::FeedbackReview.new)
40
+ expect(Spree::ReviewsAbility.new(user_without_email)).to_not be_able_to(:create, Spree::Review.new)
41
+ expect(Spree::ReviewsAbility.new(user_without_email)).to_not be_able_to(:create, Spree::FeedbackReview.new)
40
42
 
41
- Spree::ReviewsAbility.new(user_with_email).should be_able_to(:create, Spree::Review.new)
42
- Spree::ReviewsAbility.new(user_with_email).should be_able_to(:create, Spree::FeedbackReview.new)
43
+ expect(Spree::ReviewsAbility.new(user_with_email)).to be_able_to(:create, Spree::Review.new)
44
+ expect(Spree::ReviewsAbility.new(user_with_email)).to be_able_to(:create, Spree::FeedbackReview.new)
43
45
  end
44
46
  end
45
47
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Spree::ReviewsConfiguration do
@@ -5,41 +7,48 @@ describe Spree::ReviewsConfiguration do
5
7
 
6
8
  before do
7
9
  reset_spree_preferences
10
+ subject.preference_store = subject.default_preferences
8
11
  end
9
12
 
10
13
  it 'should have the include_unapproved_reviews preference' do
11
- subject.should respond_to(:preferred_include_unapproved_reviews)
12
- subject.should respond_to(:preferred_include_unapproved_reviews=)
13
- subject.preferred_include_unapproved_reviews.should be false
14
+ expect(subject).to respond_to(:preferred_include_unapproved_reviews)
15
+ expect(subject).to respond_to(:preferred_include_unapproved_reviews=)
16
+ expect(subject.preferred_include_unapproved_reviews).to be false
14
17
  end
15
18
 
16
19
  it 'should have the preview_size preference' do
17
- subject.should respond_to(:preferred_preview_size)
18
- subject.should respond_to(:preferred_preview_size=)
19
- subject.preferred_preview_size.should eq(2)
20
+ expect(subject).to respond_to(:preferred_preview_size)
21
+ expect(subject).to respond_to(:preferred_preview_size=)
22
+ expect(subject.preferred_preview_size).to eq(3)
20
23
  end
21
24
 
22
25
  it 'should have the show_email preference' do
23
- subject.should respond_to(:preferred_show_email)
24
- subject.should respond_to(:preferred_show_email=)
25
- subject.preferred_show_email.should be false
26
+ expect(subject).to respond_to(:preferred_show_email)
27
+ expect(subject).to respond_to(:preferred_show_email=)
28
+ expect(subject.preferred_show_email).to be false
29
+ end
30
+
31
+ it 'should have the show_verified_purchaser preference' do
32
+ expect(subject).to respond_to(:preferred_show_verified_purchaser)
33
+ expect(subject).to respond_to(:preferred_show_verified_purchaser=)
34
+ expect(subject.preferred_show_verified_purchaser).to be false
26
35
  end
27
36
 
28
37
  it 'should have the feedback_rating preference' do
29
- subject.should respond_to(:preferred_feedback_rating)
30
- subject.should respond_to(:preferred_feedback_rating=)
31
- subject.preferred_feedback_rating.should be false
38
+ expect(subject).to respond_to(:preferred_feedback_rating)
39
+ expect(subject).to respond_to(:preferred_feedback_rating=)
40
+ expect(subject.preferred_feedback_rating).to be false
32
41
  end
33
42
 
34
43
  it 'should have the require_login preference' do
35
- subject.should respond_to(:preferred_require_login)
36
- subject.should respond_to(:preferred_require_login=)
37
- subject.preferred_require_login.should be true
44
+ expect(subject).to respond_to(:preferred_require_login)
45
+ expect(subject).to respond_to(:preferred_require_login=)
46
+ expect(subject.preferred_require_login).to be true
38
47
  end
39
48
 
40
- it 'should have the track_locale preference', pending: 'this leaks from elsewhere, causes it to be true' do
41
- subject.should respond_to(:preferred_track_locale)
42
- subject.should respond_to(:preferred_track_locale=)
43
- subject.preferred_track_locale.should be false
49
+ it 'should have the track_locale preference' do
50
+ expect(subject).to respond_to(:preferred_track_locale)
51
+ expect(subject).to respond_to(:preferred_track_locale=)
52
+ expect(subject.preferred_track_locale).to be false
44
53
  end
45
54
  end
@@ -1,55 +1,41 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simplecov'
2
4
  SimpleCov.start 'rails'
3
5
 
4
6
  ENV["RAILS_ENV"] = "test"
5
7
 
6
- require File.expand_path("../dummy/config/environment.rb", __FILE__)
7
- require 'rspec/rails'
8
- require 'ffaker'
9
- require 'database_cleaner'
10
- require 'capybara'
11
- require 'capybara/rspec'
12
- require 'capybara/rails'
13
- require 'capybara/poltergeist'
14
-
15
- Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f }
8
+ require File.expand_path('dummy/config/environment.rb', __dir__)
16
9
 
17
- require 'spree/testing_support/factories'
10
+ # Requires factories and other useful helpers defined in spree_core.
11
+ require "solidus_support/extension/feature_helper"
18
12
  require 'spree/testing_support/controller_requests'
19
- require 'spree/testing_support/authorization_helpers'
20
- require 'spree/testing_support/preferences'
21
- require 'spree/testing_support/url_helpers'
13
+ require 'selenium/webdriver'
22
14
 
23
- require 'solidus_reviews/factories'
15
+ Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
24
16
 
25
- FactoryGirl.find_definitions
26
-
27
- # Bugfix for Solidus < 1.3 using ffaker 1.x
28
- if defined?(Faker)
29
- FFaker = Faker
30
- end
17
+ require 'solidus_reviews/factories'
31
18
 
32
19
  RSpec.configure do |config|
33
20
  config.include Spree::TestingSupport::ControllerRequests, type: :controller
34
- config.include Spree::TestingSupport::Preferences
35
- config.include FactoryGirl::Syntax::Methods
36
- config.include Spree::TestingSupport::UrlHelpers
21
+
37
22
  config.infer_spec_type_from_file_location!
38
23
  config.use_transactional_fixtures = false
39
24
 
40
- config.before(:suite) do
41
- DatabaseCleaner.strategy = :transaction
42
- DatabaseCleaner.clean_with(:truncation)
25
+ Capybara.register_driver :selenium_chrome_headless do |app|
26
+ browser_options = ::Selenium::WebDriver::Chrome::Options.new
27
+ browser_options.args << '--headless'
28
+ browser_options.args << '--disable-gpu'
29
+ browser_options.args << '--window-size=1440,1080'
30
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
43
31
  end
44
32
 
45
- config.before do
46
- DatabaseCleaner.strategy = RSpec.current_example.metadata[:js] ? :truncation : :transaction
47
- DatabaseCleaner.start
48
- end
33
+ Capybara.javascript_driver = (ENV['CAPYBARA_DRIVER'] || :selenium_chrome_headless).to_sym
49
34
 
50
- config.after do
51
- DatabaseCleaner.clean
35
+ if Gem.loaded_specs['solidus'].version < Gem::Version.new('2.4')
36
+ config.include VersionCake::TestHelpers, type: :controller
37
+ config.before(:each, type: :controller) do
38
+ set_request_version('', 1)
39
+ end
52
40
  end
53
-
54
- Capybara.javascript_driver = :poltergeist
55
41
  end
@@ -1,376 +1,389 @@
1
- /*
2
- ### jQuery Star Rating Plugin v4.11 - 2013-03-14 ###
3
- * Home: http://www.fyneworks.com/jquery/star-rating/
4
- * Code: http://code.google.com/p/jquery-star-rating-plugin/
5
- *
6
- * Licensed under http://en.wikipedia.org/wiki/MIT_License
7
- ###
8
- */
9
-
10
- /*# AVOID COLLISIONS #*/
11
- ;if(window.jQuery) (function($){
12
- /*# AVOID COLLISIONS #*/
13
-
14
- // IE6 Background Image Fix
15
- if ((!$.support.opacity && !$.support.style)) try { document.execCommand("BackgroundImageCache", false, true)} catch(e) { };
16
- // Thanks to http://www.visualjquery.com/rating/rating_redux.html
17
-
18
- // plugin initialization
19
- $.fn.rating = function(options){
20
- if(this.length==0) return this; // quick fail
21
-
22
- // Handle API methods
23
- if(typeof arguments[0]=='string'){
24
- // Perform API methods on individual elements
25
- if(this.length>1){
26
- var args = arguments;
27
- return this.each(function(){
28
- $.fn.rating.apply($(this), args);
29
- });
30
- };
31
- // Invoke API method handler
32
- $.fn.rating[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
33
- // Quick exit...
34
- return this;
35
- };
36
-
37
- // Initialize options for this call
38
- var options = $.extend(
39
- {}/* new object */,
40
- $.fn.rating.options/* default options */,
41
- options || {} /* just-in-time options */
42
- );
43
-
44
- // Allow multiple controls with the same name by making each call unique
45
- $.fn.rating.calls++;
46
-
47
- // loop through each matched element
48
- this
49
- .not('.star-rating-applied')
50
- .addClass('star-rating-applied')
51
- .each(function(){
52
-
53
- // Load control parameters / find context / etc
54
- var control, input = $(this);
55
- var eid = (this.name || 'unnamed-rating').replace(/\[|\]/g, '_').replace(/^\_+|\_+$/g,'');
56
- var context = $(this.form || document.body);
57
-
58
- // FIX: http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=23
59
- var raters = context.data('rating');
60
- if(!raters || raters.call!=$.fn.rating.calls) raters = { count:0, call:$.fn.rating.calls };
61
- var rater = raters[eid] || context.data('rating'+eid);
62
-
63
- // if rater is available, verify that the control still exists
64
- if(rater) control = rater.data('rating');
65
-
66
- if(rater && control)//{// save a byte!
67
- // add star to control if rater is available and the same control still exists
68
- control.count++;
69
-
70
- //}// save a byte!
71
- else{
72
- // create new control if first star or control element was removed/replaced
73
-
74
- // Initialize options for this rater
75
- control = $.extend(
76
- {}/* new object */,
77
- options || {} /* current call options */,
78
- ($.metadata? input.metadata(): ($.meta?input.data():null)) || {}, /* metadata options */
79
- { count:0, stars: [], inputs: [] }
80
- );
81
-
82
- // increment number of rating controls
83
- control.serial = raters.count++;
84
-
85
- // create rating element
86
- rater = $('<span class="star-rating-control"/>');
87
- input.before(rater);
88
-
89
- // Mark element for initialization (once all stars are ready)
90
- rater.addClass('rating-to-be-drawn');
91
-
92
- // Accept readOnly setting from 'disabled' property
93
- if(input.attr('disabled') || input.hasClass('disabled')) control.readOnly = true;
94
-
95
- // Accept required setting from class property (class='required')
96
- if(input.hasClass('required')) control.required = true;
97
-
98
- // Create 'cancel' button
99
- rater.append(
100
- control.cancel = $('<div class="rating-cancel"><a title="' + control.cancel + '">' + control.cancelValue + '</a></div>')
101
- .on('mouseover',function(){
102
- $(this).rating('drain');
103
- $(this).addClass('star-rating-hover');
104
- //$(this).rating('focus');
105
- })
106
- .on('mouseout',function(){
107
- $(this).rating('draw');
108
- $(this).removeClass('star-rating-hover');
109
- //$(this).rating('blur');
110
- })
111
- .on('click',function(){
112
- $(this).rating('select');
113
- })
114
- .data('rating', control)
115
- );
116
-
117
- }; // first element of group
118
-
119
- // insert rating star (thanks Jan Fanslau rev125 for blind support https://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=125)
120
- var star = $('<div role="text" aria-label="'+ this.title +'" class="star-rating rater-'+ control.serial +'"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
121
- rater.append(star);
122
-
123
- // inherit attributes from input element
124
- if(this.id) star.attr('id', this.id);
125
- if(this.className) star.addClass(this.className);
126
-
127
- // Half-stars?
128
- if(control.half) control.split = 2;
129
-
130
- // Prepare division control
131
- if(typeof control.split=='number' && control.split>0){
132
- var stw = ($.fn.width ? star.width() : 0) || control.starWidth;
133
- var spi = (control.count % control.split), spw = Math.floor(stw/control.split);
134
- star
135
- // restrict star's width and hide overflow (already in CSS)
136
- .width(spw)
137
- // move the star left by using a negative margin
138
- // this is work-around to IE's stupid box model (position:relative doesn't work)
139
- .find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
140
- };
141
-
142
- // readOnly?
143
- if(control.readOnly)//{ //save a byte!
144
- // Mark star as readOnly so user can customize display
145
- star.addClass('star-rating-readonly');
146
- //} //save a byte!
147
- else//{ //save a byte!
148
- // Enable hover css effects
149
- star.addClass('star-rating-live')
150
- // Attach mouse events
151
- .on('mouseover',function(){
152
- $(this).rating('fill');
153
- $(this).rating('focus');
154
- })
155
- .on('mouseout',function(){
156
- $(this).rating('draw');
157
- $(this).rating('blur');
158
- })
159
- .on('click',function(){
160
- $(this).rating('select');
161
- })
162
- ;
163
- //}; //save a byte!
164
-
165
- // set current selection
166
- if(this.checked) control.current = star;
167
-
168
- // set current select for links
169
- if(this.nodeName=="A"){
170
- if($(this).hasClass('selected'))
171
- control.current = star;
172
- };
173
-
174
- // hide input element
175
- input.hide();
176
-
177
- // backward compatibility, form element to plugin
178
- input.on('change.rating',function(event){
179
- if(event.selfTriggered) return false;
180
- $(this).rating('select');
181
- });
182
-
183
- // attach reference to star to input element and vice-versa
184
- star.data('rating.input', input.data('rating.star', star));
185
-
186
- // store control information in form (or body when form not available)
187
- control.stars[control.stars.length] = star[0];
188
- control.inputs[control.inputs.length] = input[0];
189
- control.rater = raters[eid] = rater;
190
- control.context = context;
191
-
192
- input.data('rating', control);
193
- rater.data('rating', control);
194
- star.data('rating', control);
195
- context.data('rating', raters);
196
- context.data('rating'+eid, rater); // required for ajax forms
197
- }); // each element
198
-
199
- // Initialize ratings (first draw)
200
- $('.rating-to-be-drawn').rating('draw').removeClass('rating-to-be-drawn');
201
-
202
- return this; // don't break the chain...
203
- };
204
-
205
- /*--------------------------------------------------------*/
206
-
207
- /*
208
- ### Core functionality and API ###
209
- */
210
- $.extend($.fn.rating, {
211
- // Used to append a unique serial number to internal control ID
212
- // each time the plugin is invoked so same name controls can co-exist
213
- calls: 0,
214
-
215
- focus: function(){
216
- var control = this.data('rating'); if(!control) return this;
217
- if(!control.focus) return this; // quick fail if not required
218
- // find data for event
219
- var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
220
- // focus handler, as requested by focusdigital.co.uk
221
- if(control.focus) control.focus.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
222
- }, // $.fn.rating.focus
223
-
224
- blur: function(){
225
- var control = this.data('rating'); if(!control) return this;
226
- if(!control.blur) return this; // quick fail if not required
227
- // find data for event
228
- var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
229
- // blur handler, as requested by focusdigital.co.uk
230
- if(control.blur) control.blur.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
231
- }, // $.fn.rating.blur
232
-
233
- fill: function(){ // fill to the current mouse position.
234
- var control = this.data('rating'); if(!control) return this;
235
- // do not execute when control is in read-only mode
236
- if(control.readOnly) return;
237
- // Reset all stars and highlight them up to this element
238
- this.rating('drain');
239
- this.prevAll().addBack().filter('.rater-'+ control.serial).addClass('star-rating-hover');
240
- },// $.fn.rating.fill
241
-
242
- drain: function() { // drain all the stars.
243
- var control = this.data('rating'); if(!control) return this;
244
- // do not execute when control is in read-only mode
245
- if(control.readOnly) return;
246
- // Reset all stars
247
- control.rater.children().filter('.rater-'+ control.serial).removeClass('star-rating-on').removeClass('star-rating-hover');
248
- },// $.fn.rating.drain
249
-
250
- draw: function(){ // set value and stars to reflect current selection
251
- var control = this.data('rating'); if(!control) return this;
252
- // Clear all stars
253
- this.rating('drain');
254
- // Set control value
255
- var current = $( control.current );//? control.current.data('rating.input') : null );
256
- var starson = current.length ? current.prevAll().addBack().filter('.rater-'+ control.serial) : null;
257
- if(starson) starson.addClass('star-rating-on');
258
- // Show/hide 'cancel' button
259
- control.cancel[control.readOnly || control.required?'hide':'show']();
260
- // Add/remove read-only classes to remove hand pointer
261
- this.siblings()[control.readOnly?'addClass':'removeClass']('star-rating-readonly');
262
- },// $.fn.rating.draw
263
-
264
-
265
-
266
-
267
-
268
- select: function(value,wantCallBack){ // select a value
269
- var control = this.data('rating'); if(!control) return this;
270
- // do not execute when control is in read-only mode
271
- if(control.readOnly) return;
272
- // clear selection
273
- control.current = null;
274
- // programmatically (based on user input)
275
- if(typeof value!='undefined' || this.length>1){
276
- // select by index (0 based)
277
- if(typeof value=='number')
278
- return $(control.stars[value]).rating('select',undefined,wantCallBack);
279
- // select by literal value (must be passed as a string
280
- if(typeof value=='string'){
281
- //return
282
- $.each(control.stars, function(){
283
- //console.log($(this).data('rating.input'), $(this).data('rating.input').val(), value, $(this).data('rating.input').val()==value?'BINGO!':'');
284
- if($(this).data('rating.input').val()==value) $(this).rating('select',undefined,wantCallBack);
285
- });
286
- // don't break the chain
287
- return this;
288
- };
289
- }
290
- else{
291
- control.current = this[0].tagName=='INPUT' ?
292
- this.data('rating.star') :
293
- (this.is('.rater-'+ control.serial) ? this : null);
294
- };
295
- // Update rating control state
296
- this.data('rating', control);
297
- // Update display
298
- this.rating('draw');
299
- // find current input and its sibblings
300
- var current = $( control.current ? control.current.data('rating.input') : null );
301
- var lastipt = $( control.inputs ).filter(':checked');
302
- var deadipt = $( control.inputs ).not(current);
303
- // check and uncheck elements as required
304
- deadipt.prop('checked',false);//.removeAttr('checked');
305
- current.prop('checked',true);//.attr('checked','checked');
306
- // trigger change on current or last selected input
307
- $(current.length? current : lastipt ).trigger({ type:'change', selfTriggered:true });
308
- // click callback, as requested here: http://plugins.jquery.com/node/1655
309
- if((wantCallBack || wantCallBack == undefined) && control.callback) control.callback.apply(current[0], [current.val(), $('a', control.current)[0]]);// callback event
310
- // don't break the chain
311
- return this;
312
- },// $.fn.rating.select
313
-
314
-
315
-
316
-
317
-
318
- readOnly: function(toggle, disable){ // make the control read-only (still submits value)
319
- var control = this.data('rating'); if(!control) return this;
320
- // setread-only status
321
- control.readOnly = toggle || toggle==undefined ? true : false;
322
- // enable/disable control value submission
323
- if(disable) $(control.inputs).attr("disabled", "disabled");
324
- else $(control.inputs).removeAttr("disabled");
325
- // Update rating control state
326
- this.data('rating', control);
327
- // Update display
328
- this.rating('draw');
329
- },// $.fn.rating.readOnly
330
-
331
- disable: function(){ // make read-only and never submit value
332
- this.rating('readOnly', true, true);
333
- },// $.fn.rating.disable
334
-
335
- enable: function(){ // make read/write and submit value
336
- this.rating('readOnly', false, false);
337
- }// $.fn.rating.select
338
-
339
- });
340
-
341
- /*--------------------------------------------------------*/
342
-
343
- /*
344
- ### Default Settings ###
345
- eg.: You can override default control like this:
346
- $.fn.rating.options.cancel = 'Clear';
347
- */
348
- $.fn.rating.options = { //$.extend($.fn.rating, { options: {
349
- cancel: 'Cancel Rating', // advisory title for the 'cancel' link
350
- cancelValue: '', // value to submit when user click the 'cancel' link
351
- split: 0, // split the star into how many parts?
352
-
353
- // Width of star image in case the plugin can't work it out. This can happen if
354
- // the jQuery.dimensions plugin is not available OR the image is hidden at installation
355
- starWidth: 16//,
356
-
357
- //NB.: These don't need to be pre-defined (can be undefined/null) so let's save some code!
358
- //half: false, // just a shortcut to control.split = 2
359
- //required: false, // disables the 'cancel' button so user can only select one of the specified values
360
- //readOnly: false, // disable rating plugin interaction/ values cannot be.one('change', //focus: function(){}, // executed when stars are focused
361
- //blur: function(){}, // executed when stars are focused
362
- //callback: function(){}, // executed when a star is clicked
363
- }; //} });
364
-
365
- /*--------------------------------------------------------*/
366
-
367
-
368
- // auto-initialize plugin
369
- $(function(){
370
- $('input[type=radio].star').rating();
371
- });
372
-
373
-
374
- /*# AVOID COLLISIONS #*/
375
- })(jQuery);
376
- /*# AVOID COLLISIONS #*/
1
+ /*
2
+ ### jQuery Star Rating Plugin v4.11 - 2013-03-14 ###
3
+ * Home: http://www.fyneworks.com/jquery/star-rating/
4
+ * Code: http://code.google.com/p/jquery-star-rating-plugin/
5
+ *
6
+ * Licensed under http://en.wikipedia.org/wiki/MIT_License
7
+ ###
8
+ */
9
+
10
+ /*# AVOID COLLISIONS #*/
11
+ ;if(window.jQuery) (function($){
12
+ /*# AVOID COLLISIONS #*/
13
+
14
+ // IE6 Background Image Fix
15
+ if ((!$.support.opacity && !$.support.style)) try { document.execCommand("BackgroundImageCache", false, true)} catch(e) { };
16
+ // Thanks to http://www.visualjquery.com/rating/rating_redux.html
17
+
18
+ // plugin initialization
19
+ $.fn.rating = function(options){
20
+ if(this.length==0) return this; // quick fail
21
+
22
+ // Handle API methods
23
+ if(typeof arguments[0]=='string'){
24
+ // Perform API methods on individual elements
25
+ if(this.length>1){
26
+ var args = arguments;
27
+ return this.each(function(){
28
+ $.fn.rating.apply($(this), args);
29
+ });
30
+ };
31
+ // Invoke API method handler
32
+ $.fn.rating[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
33
+ // Quick exit...
34
+ return this;
35
+ };
36
+
37
+ // Initialize options for this call
38
+ var options = $.extend(
39
+ {}/* new object */,
40
+ $.fn.rating.options/* default options */,
41
+ options || {} /* just-in-time options */
42
+ );
43
+
44
+ // Allow multiple controls with the same name by making each call unique
45
+ $.fn.rating.calls++;
46
+
47
+ // loop through each matched element
48
+ this
49
+ .not('.star-rating-applied')
50
+ .addClass('star-rating-applied')
51
+ .each(function(){
52
+
53
+ // Load control parameters / find context / etc
54
+ var control, input = $(this);
55
+
56
+ var getUniqueId = function(input) {
57
+ var parent = input.parent();
58
+ var uniqueId = parent.data('review-uniqueid');
59
+ if (!uniqueId && uniqueId !== 0) {
60
+ uniqueId = $.fn.rating.uniqueId;
61
+ parent.data('review-uniqueid', uniqueId);
62
+ $.fn.rating.uniqueId++;
63
+ }
64
+ return uniqueId;
65
+ };
66
+
67
+ var eid = (this.name || 'unnamed-rating').replace(/\[|\]/g, '_').replace(/^\_+|\_+$/g,'') + '-' + getUniqueId(input);
68
+ var context = $(this.form || document.body);
69
+
70
+ // FIX: http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=23
71
+ var raters = context.data('rating');
72
+ if(!raters || raters.call!=$.fn.rating.calls) raters = { count:0, call:$.fn.rating.calls };
73
+ var rater = raters[eid] || context.data('rating'+eid);
74
+
75
+ // if rater is available, verify that the control still exists
76
+ if(rater) control = rater.data('rating');
77
+
78
+ if(rater && control)//{// save a byte!
79
+ // add star to control if rater is available and the same control still exists
80
+ control.count++;
81
+
82
+ //}// save a byte!
83
+ else{
84
+ // create new control if first star or control element was removed/replaced
85
+
86
+ // Initialize options for this rater
87
+ control = $.extend(
88
+ {}/* new object */,
89
+ options || {} /* current call options */,
90
+ ($.metadata? input.metadata(): ($.meta?input.data():null)) || {}, /* metadata options */
91
+ { count:0, stars: [], inputs: [] }
92
+ );
93
+
94
+ // increment number of rating controls
95
+ control.serial = raters.count++;
96
+
97
+ // create rating element
98
+ rater = $('<span class="star-rating-control"/>');
99
+ input.before(rater);
100
+
101
+ // Mark element for initialization (once all stars are ready)
102
+ rater.addClass('rating-to-be-drawn');
103
+
104
+ // Accept readOnly setting from 'disabled' property
105
+ if(input.attr('disabled') || input.hasClass('disabled')) control.readOnly = true;
106
+
107
+ // Accept required setting from class property (class='required')
108
+ if(input.hasClass('required')) control.required = true;
109
+
110
+ // Create 'cancel' button
111
+ rater.append(
112
+ control.cancel = $('<div class="rating-cancel"><a title="' + control.cancel + '">' + control.cancelValue + '</a></div>')
113
+ .on('mouseover',function(){
114
+ $(this).rating('drain');
115
+ $(this).addClass('star-rating-hover');
116
+ //$(this).rating('focus');
117
+ })
118
+ .on('mouseout',function(){
119
+ $(this).rating('draw');
120
+ $(this).removeClass('star-rating-hover');
121
+ //$(this).rating('blur');
122
+ })
123
+ .on('click',function(){
124
+ $(this).rating('select');
125
+ })
126
+ .data('rating', control)
127
+ );
128
+
129
+ }; // first element of group
130
+
131
+ // insert rating star (thanks Jan Fanslau rev125 for blind support https://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=125)
132
+ var star = $('<div role="text" aria-label="'+ this.title +'" class="star-rating rater-'+ control.serial +'"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
133
+ rater.append(star);
134
+
135
+ // inherit attributes from input element
136
+ if(this.id) star.attr('id', this.id);
137
+ if(this.className) star.addClass(this.className);
138
+
139
+ // Half-stars?
140
+ if(control.half) control.split = 2;
141
+
142
+ // Prepare division control
143
+ if(typeof control.split=='number' && control.split>0){
144
+ var stw = ($.fn.width ? star.width() : 0) || control.starWidth;
145
+ var spi = (control.count % control.split), spw = Math.floor(stw/control.split);
146
+ star
147
+ // restrict star's width and hide overflow (already in CSS)
148
+ .width(spw)
149
+ // move the star left by using a negative margin
150
+ // this is work-around to IE's stupid box model (position:relative doesn't work)
151
+ .find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
152
+ };
153
+
154
+ // readOnly?
155
+ if(control.readOnly)//{ //save a byte!
156
+ // Mark star as readOnly so user can customize display
157
+ star.addClass('star-rating-readonly');
158
+ //} //save a byte!
159
+ else//{ //save a byte!
160
+ // Enable hover css effects
161
+ star.addClass('star-rating-live')
162
+ // Attach mouse events
163
+ .on('mouseover',function(){
164
+ $(this).rating('fill');
165
+ $(this).rating('focus');
166
+ })
167
+ .on('mouseout',function(){
168
+ $(this).rating('draw');
169
+ $(this).rating('blur');
170
+ })
171
+ .on('click',function(){
172
+ $(this).rating('select');
173
+ })
174
+ ;
175
+ //}; //save a byte!
176
+
177
+ // set current selection
178
+ if(this.checked) control.current = star;
179
+
180
+ // set current select for links
181
+ if(this.nodeName=="A"){
182
+ if($(this).hasClass('selected'))
183
+ control.current = star;
184
+ };
185
+
186
+ // hide input element
187
+ input.hide();
188
+
189
+ // backward compatibility, form element to plugin
190
+ input.on('change.rating',function(event){
191
+ if(event.selfTriggered) return false;
192
+ $(this).rating('select');
193
+ });
194
+
195
+ // attach reference to star to input element and vice-versa
196
+ star.data('rating.input', input.data('rating.star', star));
197
+
198
+ // store control information in form (or body when form not available)
199
+ control.stars[control.stars.length] = star[0];
200
+ control.inputs[control.inputs.length] = input[0];
201
+ control.rater = raters[eid] = rater;
202
+ control.context = context;
203
+
204
+ input.data('rating', control);
205
+ rater.data('rating', control);
206
+ star.data('rating', control);
207
+ context.data('rating', raters);
208
+ context.data('rating'+eid, rater); // required for ajax forms
209
+ }); // each element
210
+
211
+ // Initialize ratings (first draw)
212
+ $('.rating-to-be-drawn').rating('draw').removeClass('rating-to-be-drawn');
213
+
214
+ return this; // don't break the chain...
215
+ };
216
+
217
+ /*--------------------------------------------------------*/
218
+
219
+ /*
220
+ ### Core functionality and API ###
221
+ */
222
+ $.extend($.fn.rating, {
223
+ // Used to append a unique serial number to internal control ID
224
+ // each time the plugin is invoked so same name controls can co-exist
225
+ calls: 0,
226
+ uniqueId: 0,
227
+
228
+ focus: function(){
229
+ var control = this.data('rating'); if(!control) return this;
230
+ if(!control.focus) return this; // quick fail if not required
231
+ // find data for event
232
+ var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
233
+ // focus handler, as requested by focusdigital.co.uk
234
+ if(control.focus) control.focus.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
235
+ }, // $.fn.rating.focus
236
+
237
+ blur: function(){
238
+ var control = this.data('rating'); if(!control) return this;
239
+ if(!control.blur) return this; // quick fail if not required
240
+ // find data for event
241
+ var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
242
+ // blur handler, as requested by focusdigital.co.uk
243
+ if(control.blur) control.blur.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
244
+ }, // $.fn.rating.blur
245
+
246
+ fill: function(){ // fill to the current mouse position.
247
+ var control = this.data('rating'); if(!control) return this;
248
+ // do not execute when control is in read-only mode
249
+ if(control.readOnly) return;
250
+ // Reset all stars and highlight them up to this element
251
+ this.rating('drain');
252
+ this.prevAll().addBack().filter('.rater-'+ control.serial).addClass('star-rating-hover');
253
+ },// $.fn.rating.fill
254
+
255
+ drain: function() { // drain all the stars.
256
+ var control = this.data('rating'); if(!control) return this;
257
+ // do not execute when control is in read-only mode
258
+ if(control.readOnly) return;
259
+ // Reset all stars
260
+ control.rater.children().filter('.rater-'+ control.serial).removeClass('star-rating-on').removeClass('star-rating-hover');
261
+ },// $.fn.rating.drain
262
+
263
+ draw: function(){ // set value and stars to reflect current selection
264
+ var control = this.data('rating'); if(!control) return this;
265
+ // Clear all stars
266
+ this.rating('drain');
267
+ // Set control value
268
+ var current = $( control.current );//? control.current.data('rating.input') : null );
269
+ var starson = current.length ? current.prevAll().addBack().filter('.rater-'+ control.serial) : null;
270
+ if(starson) starson.addClass('star-rating-on');
271
+ // Show/hide 'cancel' button
272
+ control.cancel[control.readOnly || control.required?'hide':'show']();
273
+ // Add/remove read-only classes to remove hand pointer
274
+ this.siblings()[control.readOnly?'addClass':'removeClass']('star-rating-readonly');
275
+ },// $.fn.rating.draw
276
+
277
+
278
+
279
+
280
+
281
+ select: function(value,wantCallBack){ // select a value
282
+ var control = this.data('rating'); if(!control) return this;
283
+ // do not execute when control is in read-only mode
284
+ if(control.readOnly) return;
285
+ // clear selection
286
+ control.current = null;
287
+ // programmatically (based on user input)
288
+ if(typeof value!='undefined' || this.length>1){
289
+ // select by index (0 based)
290
+ if(typeof value=='number')
291
+ return $(control.stars[value]).rating('select',undefined,wantCallBack);
292
+ // select by literal value (must be passed as a string
293
+ if(typeof value=='string'){
294
+ //return
295
+ $.each(control.stars, function(){
296
+ //console.log($(this).data('rating.input'), $(this).data('rating.input').val(), value, $(this).data('rating.input').val()==value?'BINGO!':'');
297
+ if($(this).data('rating.input').val()==value) $(this).rating('select',undefined,wantCallBack);
298
+ });
299
+ // don't break the chain
300
+ return this;
301
+ };
302
+ }
303
+ else{
304
+ control.current = this[0].tagName=='INPUT' ?
305
+ this.data('rating.star') :
306
+ (this.is('.rater-'+ control.serial) ? this : null);
307
+ };
308
+ // Update rating control state
309
+ this.data('rating', control);
310
+ // Update display
311
+ this.rating('draw');
312
+ // find current input and its sibblings
313
+ var current = $( control.current ? control.current.data('rating.input') : null );
314
+ var lastipt = $( control.inputs ).filter(':checked');
315
+ var deadipt = $( control.inputs ).not(current);
316
+ // check and uncheck elements as required
317
+ deadipt.prop('checked',false);//.removeAttr('checked');
318
+ current.prop('checked',true);//.attr('checked','checked');
319
+ // trigger change on current or last selected input
320
+ $(current.length? current : lastipt ).trigger({ type:'change', selfTriggered:true });
321
+ // click callback, as requested here: http://plugins.jquery.com/node/1655
322
+ if((wantCallBack || wantCallBack == undefined) && control.callback) control.callback.apply(current[0], [current.val(), $('a', control.current)[0]]);// callback event
323
+ // don't break the chain
324
+ return this;
325
+ },// $.fn.rating.select
326
+
327
+
328
+
329
+
330
+
331
+ readOnly: function(toggle, disable){ // make the control read-only (still submits value)
332
+ var control = this.data('rating'); if(!control) return this;
333
+ // setread-only status
334
+ control.readOnly = toggle || toggle==undefined ? true : false;
335
+ // enable/disable control value submission
336
+ if(disable) $(control.inputs).attr("disabled", "disabled");
337
+ else $(control.inputs).removeAttr("disabled");
338
+ // Update rating control state
339
+ this.data('rating', control);
340
+ // Update display
341
+ this.rating('draw');
342
+ },// $.fn.rating.readOnly
343
+
344
+ disable: function(){ // make read-only and never submit value
345
+ this.rating('readOnly', true, true);
346
+ },// $.fn.rating.disable
347
+
348
+ enable: function(){ // make read/write and submit value
349
+ this.rating('readOnly', false, false);
350
+ }// $.fn.rating.select
351
+
352
+ });
353
+
354
+ /*--------------------------------------------------------*/
355
+
356
+ /*
357
+ ### Default Settings ###
358
+ eg.: You can override default control like this:
359
+ $.fn.rating.options.cancel = 'Clear';
360
+ */
361
+ $.fn.rating.options = { //$.extend($.fn.rating, { options: {
362
+ cancel: 'Cancel Rating', // advisory title for the 'cancel' link
363
+ cancelValue: '', // value to submit when user click the 'cancel' link
364
+ split: 0, // split the star into how many parts?
365
+
366
+ // Width of star image in case the plugin can't work it out. This can happen if
367
+ // the jQuery.dimensions plugin is not available OR the image is hidden at installation
368
+ starWidth: 16//,
369
+
370
+ //NB.: These don't need to be pre-defined (can be undefined/null) so let's save some code!
371
+ //half: false, // just a shortcut to control.split = 2
372
+ //required: false, // disables the 'cancel' button so user can only select one of the specified values
373
+ //readOnly: false, // disable rating plugin interaction/ values cannot be.one('change', //focus: function(){}, // executed when stars are focused
374
+ //blur: function(){}, // executed when stars are focused
375
+ //callback: function(){}, // executed when a star is clicked
376
+ }; //} });
377
+
378
+ /*--------------------------------------------------------*/
379
+
380
+
381
+ // auto-initialize plugin
382
+ $(function(){
383
+ $('input[type=radio].star').rating();
384
+ });
385
+
386
+
387
+ /*# AVOID COLLISIONS #*/
388
+ })(jQuery);
389
+ /*# AVOID COLLISIONS #*/