solidus_reviews 1.0.0 → 1.1.0

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.
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 #*/