spree_core 1.3.0.rc1 → 1.3.0.rc2
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.
- data/app/assets/javascripts/admin/admin.js.erb +28 -2
- data/app/assets/javascripts/admin/checkouts/edit.js +52 -96
- data/app/assets/javascripts/admin/handlebar_extensions.js +9 -0
- data/app/assets/javascripts/admin/spree-select2.js.erb +17 -19
- data/app/assets/javascripts/admin/spree_core.js +0 -1
- data/app/assets/javascripts/admin/states.js +9 -0
- data/app/assets/javascripts/admin/taxon_autocomplete.js.erb +1 -1
- data/app/assets/javascripts/admin/variant_autocomplete.js.erb +2 -6
- data/app/assets/javascripts/store/checkout.js.coffee +4 -4
- data/app/assets/stylesheets/store/screen.css.scss +8 -0
- data/app/controllers/spree/admin/option_values_controller.rb +11 -0
- data/app/controllers/spree/admin/product_properties_controller.rb +12 -0
- data/app/controllers/spree/admin/products_controller.rb +9 -0
- data/app/helpers/spree/admin/base_helper.rb +2 -8
- data/app/models/spree/app_configuration.rb +1 -0
- data/app/models/spree/calculator/per_item.rb +3 -1
- data/app/models/spree/line_item.rb +2 -2
- data/app/models/spree/order/checkout.rb +4 -1
- data/app/models/spree/order.rb +5 -1
- data/app/models/spree/payment/processing.rb +1 -1
- data/app/models/spree/preferences/preferable_class_methods.rb +6 -9
- data/app/models/spree/preferences/store.rb +22 -11
- data/app/models/spree/product/scopes.rb +5 -1
- data/app/models/spree/shipment.rb +7 -4
- data/app/models/spree/shipping_method.rb +4 -0
- data/app/views/spree/admin/orders/customer_details/_autocomplete.js.erb +19 -0
- data/app/views/spree/admin/orders/customer_details/edit.html.erb +4 -3
- data/app/views/spree/admin/orders/edit.html.erb +1 -1
- data/app/views/spree/admin/products/search.rabl +6 -0
- data/app/views/spree/admin/search/users.rabl +23 -25
- data/app/views/spree/admin/shared/_head.html.erb +1 -1
- data/app/views/spree/admin/shared/_routes.html.erb +3 -2
- data/app/views/spree/admin/shared/_translations.html.erb +3 -0
- data/app/views/spree/admin/shipping_methods/_form.html.erb +1 -1
- data/app/views/spree/admin/variants/_autocomplete.js.erb +2 -2
- data/app/views/spree/admin/variants/search.rabl +8 -10
- data/app/views/spree/checkout/payment/_gateway.html.erb +2 -2
- data/app/views/spree/order_mailer/cancel_email.text.erb +2 -2
- data/app/views/spree/order_mailer/confirm_email.text.erb +2 -2
- data/app/views/spree/orders/_line_item.html.erb +1 -1
- data/app/views/spree/products/_cart_form.html.erb +6 -2
- data/app/views/spree/shared/_google_analytics.html.erb +8 -8
- data/app/views/spree/shared/_order_details.html.erb +3 -1
- data/config/locales/en.yml +9 -7
- data/config/routes.rb +9 -0
- data/db/migrate/20121126040517_add_last_ip_to_spree_orders.rb +5 -0
- data/lib/spree/core/calculated_adjustments.rb +2 -1
- data/lib/spree/core/controller_helpers/common.rb +5 -0
- data/lib/spree/core/controller_helpers/order.rb +1 -0
- data/lib/spree/core/search/base.rb +5 -1
- data/lib/spree/core/testing_support/capybara_ext.rb +79 -0
- data/lib/spree/core/version.rb +1 -1
- metadata +13 -6
- data/vendor/assets/javascripts/jquery.tokeninput.js +0 -860
@@ -9,12 +9,12 @@
|
|
9
9
|
<%= item.variant.sku %> <%= raw(item.variant.product.name) %> <%= raw(item.variant.options_text) -%> (<%=item.quantity%>) @ <%= item.variant.display_amount %> = <%= item.display_amount %>
|
10
10
|
<% end %>
|
11
11
|
============================================================
|
12
|
-
<%= t('order_mailer.confirm_email.subtotal'
|
12
|
+
<%= t('order_mailer.confirm_email.subtotal', :subtotal => @order.display_item_total) %>
|
13
13
|
|
14
14
|
<% @order.adjustments.eligible.each do |adjustment| %>
|
15
15
|
<%= raw(adjustment.label) %> <%= adjustment.display_amount %>
|
16
16
|
<% end %>
|
17
17
|
|
18
|
-
<%= t('order_mailer.confirm_email.total'
|
18
|
+
<%= t('order_mailer.confirm_email.total', :total => @order.display_total) %>
|
19
19
|
|
20
20
|
<%= t('order_mailer.confirm_email.thanks') %>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<%= variant.options_text %>
|
12
12
|
<% if @order.insufficient_stock_lines.include? line_item %>
|
13
13
|
<span class="out-of-stock">
|
14
|
-
<%= variant.in_stock? ? t(:insufficient_stock, :on_hand => variant.on_hand) : t(:out_of_stock)
|
14
|
+
<%= variant.in_stock? ? t(:insufficient_stock, :on_hand => variant.on_hand) : t(:out_of_stock) %> <br />
|
15
15
|
</span>
|
16
16
|
<% end %>
|
17
17
|
<%= line_item_description(variant) %>
|
@@ -26,7 +26,7 @@
|
|
26
26
|
</div>
|
27
27
|
<% end%>
|
28
28
|
|
29
|
-
<% if @product.price %>
|
29
|
+
<% if @product.price_in(current_currency) and !@product.price.nil? %>
|
30
30
|
<div data-hook="product_price" class="columns five <% if !@product.has_variants? %> alpha <% else %> omega <% end %>">
|
31
31
|
|
32
32
|
<div id="product-price">
|
@@ -45,8 +45,12 @@
|
|
45
45
|
<%= content_tag('strong', t(:out_of_stock)) %>
|
46
46
|
<% end %>
|
47
47
|
</div>
|
48
|
-
|
49
48
|
</div>
|
49
|
+
<% else %>
|
50
|
+
<div id="product-price">
|
51
|
+
<br>
|
52
|
+
<div><span class="price selling" itemprop="price"><%= t('product_not_available_in_this_currency') %></span></div>
|
53
|
+
</div>
|
50
54
|
<% end %>
|
51
55
|
|
52
56
|
</div>
|
@@ -5,23 +5,23 @@
|
|
5
5
|
_gaq.push(['_setAccount', '<%= tracker.analytics_id %>']);
|
6
6
|
_gaq.push(['_trackPageview']);
|
7
7
|
|
8
|
-
<% if flash[:commerce_tracking] %>
|
8
|
+
<% if flash[:commerce_tracking] && @order.present? %>
|
9
9
|
<%# more info: https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiEcommerce %>
|
10
10
|
_gaq.push(['_addTrans',
|
11
|
-
"<%= @order.number %>",
|
11
|
+
"<%= j @order.number %>",
|
12
12
|
"",
|
13
13
|
"<%= @order.total %>",
|
14
14
|
"<%= @order.adjustments.tax.sum(:amount) %>",
|
15
15
|
"<%= @order.adjustments.shipping.sum(:amount) %>",
|
16
|
-
"<%= @order.bill_address.city %>",
|
17
|
-
"<%= @order.bill_address.state_text %>",
|
18
|
-
"<%= @order.bill_address.country.name %>"
|
16
|
+
"<%= j @order.bill_address.city %>",
|
17
|
+
"<%= j @order.bill_address.state_text %>",
|
18
|
+
"<%= j @order.bill_address.country.name %>"
|
19
19
|
]);
|
20
20
|
<% @order.line_items.each do |line_item| %>
|
21
21
|
_gaq.push(['_addItem',
|
22
|
-
"<%= @order.number %>",
|
23
|
-
"<%= line_item.variant.sku %>",
|
24
|
-
"<%= line_item.variant.product.name %>",
|
22
|
+
"<%= j @order.number %>",
|
23
|
+
"<%= j line_item.variant.sku %>",
|
24
|
+
"<%= j line_item.variant.product.name %>",
|
25
25
|
"",
|
26
26
|
"<%= line_item.price %>",
|
27
27
|
"<%= line_item.quantity %>"
|
@@ -32,7 +32,9 @@
|
|
32
32
|
<%= content_tag(:span, order.payment.payment_method.name) if order.payment %>
|
33
33
|
<% else %>
|
34
34
|
<span class="cc-type">
|
35
|
-
|
35
|
+
<% unless (cc_type = order.credit_cards.first.cc_type).blank? %>
|
36
|
+
<%= image_tag "credit_cards/icons/#{order.credit_cards.first.cc_type}.png" %>
|
37
|
+
<% end %>
|
36
38
|
<%= t(:ending_in)%> <%= order.credit_cards.first.last_digits %>
|
37
39
|
</span>
|
38
40
|
<br />
|
data/config/locales/en.yml
CHANGED
@@ -321,6 +321,7 @@ en:
|
|
321
321
|
charges: Charges
|
322
322
|
checkout: Checkout
|
323
323
|
cheque: Cheque
|
324
|
+
choose_a_customer: "Choose a customer"
|
324
325
|
city: City
|
325
326
|
clone: Clone
|
326
327
|
code: Code
|
@@ -642,16 +643,16 @@ en:
|
|
642
643
|
dear_customer: "Dear Customer,"
|
643
644
|
instructions: "Please review and retain the following order information for your records."
|
644
645
|
order_summary: "Order Summary"
|
645
|
-
subtotal: "Subtotal:"
|
646
|
-
total: "Order Total:"
|
646
|
+
subtotal: "Subtotal: %{subtotal}"
|
647
|
+
total: "Order Total: %{total}"
|
647
648
|
thanks: "Thank you for your business."
|
648
649
|
cancel_email:
|
649
650
|
subject: "Cancellation of Order"
|
650
651
|
dear_customer: "Dear Customer,"
|
651
652
|
instructions: "Your order has been CANCELED. Please retain this cancellation information for your records."
|
652
653
|
order_summary_canceled: "Order Summary [CANCELED]"
|
653
|
-
subtotal: "Subtotal:"
|
654
|
-
total: "Order Total:"
|
654
|
+
subtotal: "Subtotal: %{subtotal}"
|
655
|
+
total: "Order Total: %{total}"
|
655
656
|
order_not_in_system: That order number is not valid on this site.
|
656
657
|
order_number: Order
|
657
658
|
order_operation_authorize: Authorize
|
@@ -858,6 +859,7 @@ en:
|
|
858
859
|
sentence: with property <em>%s</em> and value <em>%s</em>
|
859
860
|
products: Products
|
860
861
|
products_with_zero_inventory_display: "Products with a zero inventory will %{not} be displayed"
|
862
|
+
product_not_available_in_this_currency: "This product is not available in the selected currency."
|
861
863
|
properties: Properties
|
862
864
|
property: Property
|
863
865
|
prototype: Prototype
|
@@ -1045,6 +1047,7 @@ en:
|
|
1045
1047
|
tax_type: "Tax Type"
|
1046
1048
|
taxon: Taxon
|
1047
1049
|
taxon_edit: Edit Taxon
|
1050
|
+
taxon_placeholder: "Add a Taxon"
|
1048
1051
|
taxonomy: Taxonomy
|
1049
1052
|
taxonomies: Taxonomies
|
1050
1053
|
taxonomies_setting_description: "Create and manage taxonomies."
|
@@ -1061,7 +1064,6 @@ en:
|
|
1061
1064
|
test_mode: Test Mode
|
1062
1065
|
thank_you_for_your_order: "Thank you for your business. Please print out a copy of this confirmation page for your records."
|
1063
1066
|
there_were_problems_with_the_following_fields: "There were problems with the following fields"
|
1064
|
-
this_file_language: "English (US)"
|
1065
1067
|
thumbnail: "Thumbnail"
|
1066
1068
|
to_add_variants_you_must_first_define: "To add variants, you must first define"
|
1067
1069
|
to_state: "To State"
|
@@ -1097,12 +1099,12 @@ en:
|
|
1097
1099
|
users: Users
|
1098
1100
|
validate_on_profile_create: Validate on profile create
|
1099
1101
|
validation:
|
1100
|
-
cannot_be_greater_than_available_stock: "cannot be greater than available stock."
|
1101
1102
|
cannot_be_less_than_shipped_units: "cannot be less than the number of shipped units."
|
1102
|
-
|
1103
|
+
cannot_destroy_line_item_as_inventory_units_have_shipped: "Cannot destroy line item as some inventory units have shipped."
|
1103
1104
|
is_too_large: "is too large -- stock on hand cannot cover requested quantity!"
|
1104
1105
|
must_be_int: "must be an integer"
|
1105
1106
|
must_be_non_negative: "must be a non-negative value"
|
1107
|
+
exceeds_available_stock: "exceeds available stock. Please ensure line items have a valid quantity."
|
1106
1108
|
value: Value
|
1107
1109
|
variant: Variant
|
1108
1110
|
variants: Variants
|
data/config/routes.rb
CHANGED
@@ -64,7 +64,12 @@ Spree::Core::Engine.routes.draw do
|
|
64
64
|
end
|
65
65
|
resources :states
|
66
66
|
resources :tax_categories
|
67
|
+
|
67
68
|
resources :products do
|
69
|
+
collection do
|
70
|
+
get :search
|
71
|
+
end
|
72
|
+
|
68
73
|
resources :product_properties
|
69
74
|
resources :images do
|
70
75
|
collection do
|
@@ -90,12 +95,16 @@ Spree::Core::Engine.routes.draw do
|
|
90
95
|
end
|
91
96
|
end
|
92
97
|
|
98
|
+
delete '/option_values/:id', :to => "option_values#destroy", :as => :option_value
|
99
|
+
|
93
100
|
resources :properties do
|
94
101
|
collection do
|
95
102
|
get :filtered
|
96
103
|
end
|
97
104
|
end
|
98
105
|
|
106
|
+
delete '/product_properties/:id', :to => "product_properties#destroy", :as => :product_property
|
107
|
+
|
99
108
|
resources :prototypes do
|
100
109
|
member do
|
101
110
|
get :select
|
@@ -33,7 +33,8 @@ module Spree
|
|
33
33
|
:source => calculable,
|
34
34
|
:originator => self,
|
35
35
|
:label => label,
|
36
|
-
:mandatory => mandatory
|
36
|
+
:mandatory => mandatory,
|
37
|
+
:locked => true }, :without_protection => true)
|
37
38
|
end
|
38
39
|
|
39
40
|
# Updates the amount of the adjustment using our Calculator and calling the +compute+ method with the +calculable+
|
@@ -24,6 +24,7 @@ module Spree
|
|
24
24
|
return @current_order if @current_order
|
25
25
|
if session[:order_id]
|
26
26
|
current_order = Spree::Order.find_by_id_and_currency(session[:order_id], current_currency, :include => :adjustments)
|
27
|
+
current_order.last_ip_address = ip_address
|
27
28
|
@current_order = current_order unless current_order.try(:completed?)
|
28
29
|
end
|
29
30
|
if create_order_if_necessary and (@current_order.nil? or @current_order.completed?)
|
@@ -16,7 +16,11 @@ module Spree
|
|
16
16
|
@products_scope = get_base_scope
|
17
17
|
curr_page = page || 1
|
18
18
|
|
19
|
-
@products = @products_scope.includes([:master => :prices])
|
19
|
+
@products = @products_scope.includes([:master => :prices])
|
20
|
+
unless Spree::Config.show_products_without_price
|
21
|
+
@products = @products.where("spree_prices.amount IS NOT NULL").where("spree_prices.currency" => current_currency)
|
22
|
+
end
|
23
|
+
@products = @products.page(curr_page).per(per_page)
|
20
24
|
end
|
21
25
|
|
22
26
|
def method_missing(name)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module CapybaraExt
|
2
|
+
def page!
|
3
|
+
save_and_open_page
|
4
|
+
end
|
5
|
+
|
6
|
+
def click_icon(type)
|
7
|
+
find(".icon-#{type}").click
|
8
|
+
end
|
9
|
+
|
10
|
+
def eventually_fill_in(field, options={})
|
11
|
+
Capybara.wait_until do
|
12
|
+
find_field field
|
13
|
+
end
|
14
|
+
fill_in field, options
|
15
|
+
end
|
16
|
+
|
17
|
+
def within_row(num, &block)
|
18
|
+
within("table.index tbody tr:nth-child(#{num})", &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def column_text(num)
|
22
|
+
find("td:nth-child(#{num})").text
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_select2_field(field, value)
|
26
|
+
page.execute_script %Q{$('#{field}').select2('val', '#{value}')}
|
27
|
+
end
|
28
|
+
|
29
|
+
def select2_search(value, options)
|
30
|
+
id = find_label_by_text(options[:from])
|
31
|
+
|
32
|
+
select2_id = "#s2id_#{id}"
|
33
|
+
find(select2_id).find(".select2-choices").click
|
34
|
+
page.execute_script "$('#{select2_id} input.select2-input').val('#{value}').trigger('keyup-change');"
|
35
|
+
select_select2_result(value)
|
36
|
+
end
|
37
|
+
|
38
|
+
def select2(value, options)
|
39
|
+
id = find_label_by_text(options[:from])
|
40
|
+
|
41
|
+
# generate select2 id
|
42
|
+
select2_id = "#s2id_#{id}"
|
43
|
+
|
44
|
+
# find select2 element and click it
|
45
|
+
find("#{select2_id}").find('a').click
|
46
|
+
select_select2_result(value)
|
47
|
+
end
|
48
|
+
|
49
|
+
def select_select2_result(value)
|
50
|
+
find(:xpath, %Q{//div[@class="select2-result-label" and text()="#{value}"]}).click
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_label_by_text(text)
|
54
|
+
label = find_label(text)
|
55
|
+
counter = 0
|
56
|
+
|
57
|
+
# Because JavaScript testing is prone to errors...
|
58
|
+
while label.nil? && counter < 10
|
59
|
+
sleep(1)
|
60
|
+
counter += 1
|
61
|
+
label = find_label(text)
|
62
|
+
end
|
63
|
+
|
64
|
+
if label.nil?
|
65
|
+
raise "Could not find label by text #{text}"
|
66
|
+
end
|
67
|
+
|
68
|
+
label ? label['for'] : text
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_label(text)
|
72
|
+
first(:xpath, "//label[text()='#{text}']")
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
RSpec.configure do |c|
|
78
|
+
c.include CapybaraExt
|
79
|
+
end
|
data/lib/spree/core/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.0.
|
4
|
+
version: 1.3.0.rc2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: acts_as_list
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - '='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 2.1.
|
37
|
+
version: 2.1.5
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - '='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 2.1.
|
45
|
+
version: 2.1.5
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: jquery-rails
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -349,6 +349,7 @@ files:
|
|
349
349
|
- app/assets/javascripts/admin/calculator.js
|
350
350
|
- app/assets/javascripts/admin/checkouts/edit.js
|
351
351
|
- app/assets/javascripts/admin/gateway.js
|
352
|
+
- app/assets/javascripts/admin/handlebar_extensions.js
|
352
353
|
- app/assets/javascripts/admin/image_settings.js.erb
|
353
354
|
- app/assets/javascripts/admin/images/index.js.coffee
|
354
355
|
- app/assets/javascripts/admin/images/new.js.coffee
|
@@ -360,6 +361,7 @@ files:
|
|
360
361
|
- app/assets/javascripts/admin/shipping_methods.js.coffee
|
361
362
|
- app/assets/javascripts/admin/spree-select2.js.erb
|
362
363
|
- app/assets/javascripts/admin/spree_core.js
|
364
|
+
- app/assets/javascripts/admin/states.js
|
363
365
|
- app/assets/javascripts/admin/taxon_autocomplete.js.erb
|
364
366
|
- app/assets/javascripts/admin/taxonomy.js
|
365
367
|
- app/assets/javascripts/admin/underscore-min.js
|
@@ -419,6 +421,7 @@ files:
|
|
419
421
|
- app/controllers/spree/admin/line_items_controller.rb
|
420
422
|
- app/controllers/spree/admin/mail_methods_controller.rb
|
421
423
|
- app/controllers/spree/admin/option_types_controller.rb
|
424
|
+
- app/controllers/spree/admin/option_values_controller.rb
|
422
425
|
- app/controllers/spree/admin/orders/customer_details_controller.rb
|
423
426
|
- app/controllers/spree/admin/orders_controller.rb
|
424
427
|
- app/controllers/spree/admin/overview_controller.rb
|
@@ -573,6 +576,7 @@ files:
|
|
573
576
|
- app/views/spree/admin/orders/_add_product.html.erb
|
574
577
|
- app/views/spree/admin/orders/_form.html.erb
|
575
578
|
- app/views/spree/admin/orders/_line_item.html.erb
|
579
|
+
- app/views/spree/admin/orders/customer_details/_autocomplete.js.erb
|
576
580
|
- app/views/spree/admin/orders/customer_details/_form.html.erb
|
577
581
|
- app/views/spree/admin/orders/customer_details/edit.html.erb
|
578
582
|
- app/views/spree/admin/orders/edit.html.erb
|
@@ -602,6 +606,7 @@ files:
|
|
602
606
|
- app/views/spree/admin/products/index.html.erb
|
603
607
|
- app/views/spree/admin/products/new.html.erb
|
604
608
|
- app/views/spree/admin/products/new.js.erb
|
609
|
+
- app/views/spree/admin/products/search.rabl
|
605
610
|
- app/views/spree/admin/properties/_form.html.erb
|
606
611
|
- app/views/spree/admin/properties/edit.html.erb
|
607
612
|
- app/views/spree/admin/properties/filtered.html.erb
|
@@ -801,6 +806,7 @@ files:
|
|
801
806
|
- lib/spree/core/ssl_requirement.rb
|
802
807
|
- lib/spree/core/store_helpers.rb
|
803
808
|
- lib/spree/core/testing_support/authorization_helpers.rb
|
809
|
+
- lib/spree/core/testing_support/capybara_ext.rb
|
804
810
|
- lib/spree/core/testing_support/common_rake.rb
|
805
811
|
- lib/spree/core/testing_support/controller_requests.rb
|
806
812
|
- lib/spree/core/testing_support/factories/activator_factory.rb
|
@@ -874,6 +880,7 @@ files:
|
|
874
880
|
- db/migrate/20121109173623_add_cost_currency_to_variants.rb
|
875
881
|
- db/migrate/20121111231553_remove_display_on_from_payment_methods.rb
|
876
882
|
- db/migrate/20121124203911_add_position_to_taxonomies.rb
|
883
|
+
- db/migrate/20121126040517_add_last_ip_to_spree_orders.rb
|
877
884
|
- db/seeds.rb
|
878
885
|
- vendor/assets/fonts/fontawesome-webfont.eot
|
879
886
|
- vendor/assets/fonts/fontawesome-webfont.svg
|
@@ -1164,7 +1171,6 @@ files:
|
|
1164
1171
|
- vendor/assets/javascripts/jquery.jstree/themes/apple/style.css
|
1165
1172
|
- vendor/assets/javascripts/jquery.jstree/themes/apple/throbber.gif
|
1166
1173
|
- vendor/assets/javascripts/jquery.powertip.js
|
1167
|
-
- vendor/assets/javascripts/jquery.tokeninput.js
|
1168
1174
|
- vendor/assets/javascripts/jquery.validate/additional-methods.min.js
|
1169
1175
|
- vendor/assets/javascripts/jquery.validate/jquery.validate.min.js
|
1170
1176
|
- vendor/assets/javascripts/jquery.validate/localization/messages_ar.js
|
@@ -1219,7 +1225,8 @@ files:
|
|
1219
1225
|
- vendor/assets/stylesheets/responsive-tables.css
|
1220
1226
|
- vendor/assets/stylesheets/skeleton.css
|
1221
1227
|
homepage: http://spreecommerce.com
|
1222
|
-
licenses:
|
1228
|
+
licenses:
|
1229
|
+
- BSD-3
|
1223
1230
|
post_install_message:
|
1224
1231
|
rdoc_options: []
|
1225
1232
|
require_paths:
|
@@ -1,860 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* jQuery Plugin: Tokenizing Autocomplete Text Entry
|
3
|
-
* Version 1.6.0
|
4
|
-
*
|
5
|
-
* Copyright (c) 2009 James Smith (http://loopj.com)
|
6
|
-
* Licensed jointly under the GPL and MIT licenses,
|
7
|
-
* choose which one suits your project best!
|
8
|
-
*
|
9
|
-
*/
|
10
|
-
|
11
|
-
(function ($) {
|
12
|
-
// Default settings
|
13
|
-
var DEFAULT_SETTINGS = {
|
14
|
-
// Search settings
|
15
|
-
method: "GET",
|
16
|
-
contentType: "json",
|
17
|
-
queryParam: "q",
|
18
|
-
searchDelay: 300,
|
19
|
-
minChars: 1,
|
20
|
-
propertyToSearch: "name",
|
21
|
-
jsonContainer: null,
|
22
|
-
|
23
|
-
// Display settings
|
24
|
-
hintText: "Type in a search term",
|
25
|
-
noResultsText: "No results",
|
26
|
-
searchingText: "Searching...",
|
27
|
-
deleteText: "×",
|
28
|
-
animateDropdown: true,
|
29
|
-
|
30
|
-
// Tokenization settings
|
31
|
-
tokenLimit: null,
|
32
|
-
tokenDelimiter: ",",
|
33
|
-
preventDuplicates: false,
|
34
|
-
|
35
|
-
// Output settings
|
36
|
-
tokenValue: "id",
|
37
|
-
|
38
|
-
// Prepopulation settings
|
39
|
-
prePopulate: null,
|
40
|
-
processPrePopulate: false,
|
41
|
-
|
42
|
-
// Manipulation settings
|
43
|
-
idPrefix: "token-input-",
|
44
|
-
|
45
|
-
// Formatters
|
46
|
-
resultsFormatter: function(item){ return "<li>" + item[this.propertyToSearch]+ "</li>" },
|
47
|
-
tokenFormatter: function(item) { return "<li><p>" + item[this.propertyToSearch] + "</p></li>" },
|
48
|
-
|
49
|
-
// Callbacks
|
50
|
-
onResult: null,
|
51
|
-
onAdd: null,
|
52
|
-
onDelete: null,
|
53
|
-
onReady: null
|
54
|
-
};
|
55
|
-
|
56
|
-
// Default classes to use when theming
|
57
|
-
var DEFAULT_CLASSES = {
|
58
|
-
tokenList: "token-input-list",
|
59
|
-
token: "token-input-token",
|
60
|
-
tokenDelete: "token-input-delete-token",
|
61
|
-
selectedToken: "token-input-selected-token",
|
62
|
-
highlightedToken: "token-input-highlighted-token",
|
63
|
-
dropdown: "token-input-dropdown",
|
64
|
-
dropdownItem: "token-input-dropdown-item",
|
65
|
-
dropdownItem2: "token-input-dropdown-item2",
|
66
|
-
selectedDropdownItem: "token-input-selected-dropdown-item",
|
67
|
-
inputToken: "token-input-input-token"
|
68
|
-
};
|
69
|
-
|
70
|
-
// Input box position "enum"
|
71
|
-
var POSITION = {
|
72
|
-
BEFORE: 0,
|
73
|
-
AFTER: 1,
|
74
|
-
END: 2
|
75
|
-
};
|
76
|
-
|
77
|
-
// Keys "enum"
|
78
|
-
var KEY = {
|
79
|
-
BACKSPACE: 8,
|
80
|
-
TAB: 9,
|
81
|
-
ENTER: 13,
|
82
|
-
ESCAPE: 27,
|
83
|
-
SPACE: 32,
|
84
|
-
PAGE_UP: 33,
|
85
|
-
PAGE_DOWN: 34,
|
86
|
-
END: 35,
|
87
|
-
HOME: 36,
|
88
|
-
LEFT: 37,
|
89
|
-
UP: 38,
|
90
|
-
RIGHT: 39,
|
91
|
-
DOWN: 40,
|
92
|
-
NUMPAD_ENTER: 108,
|
93
|
-
COMMA: 188
|
94
|
-
};
|
95
|
-
|
96
|
-
// Additional public (exposed) methods
|
97
|
-
var methods = {
|
98
|
-
init: function(url_or_data_or_function, options) {
|
99
|
-
var settings = $.extend({}, DEFAULT_SETTINGS, options || {});
|
100
|
-
|
101
|
-
return this.each(function () {
|
102
|
-
$(this).data("tokenInputObject", new $.TokenList(this, url_or_data_or_function, settings));
|
103
|
-
});
|
104
|
-
},
|
105
|
-
clear: function() {
|
106
|
-
this.data("tokenInputObject").clear();
|
107
|
-
return this;
|
108
|
-
},
|
109
|
-
add: function(item) {
|
110
|
-
this.data("tokenInputObject").add(item);
|
111
|
-
return this;
|
112
|
-
},
|
113
|
-
remove: function(item) {
|
114
|
-
this.data("tokenInputObject").remove(item);
|
115
|
-
return this;
|
116
|
-
},
|
117
|
-
get: function() {
|
118
|
-
return this.data("tokenInputObject").getTokens();
|
119
|
-
}
|
120
|
-
}
|
121
|
-
|
122
|
-
// Expose the .tokenInput function to jQuery as a plugin
|
123
|
-
$.fn.tokenInput = function (method) {
|
124
|
-
// Method calling and initialization logic
|
125
|
-
if(methods[method]) {
|
126
|
-
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
127
|
-
} else {
|
128
|
-
return methods.init.apply(this, arguments);
|
129
|
-
}
|
130
|
-
};
|
131
|
-
|
132
|
-
// TokenList class for each input
|
133
|
-
$.TokenList = function (input, url_or_data, settings) {
|
134
|
-
//
|
135
|
-
// Initialization
|
136
|
-
//
|
137
|
-
|
138
|
-
// Configure the data source
|
139
|
-
if($.type(url_or_data) === "string" || $.type(url_or_data) === "function") {
|
140
|
-
// Set the url to query against
|
141
|
-
settings.url = url_or_data;
|
142
|
-
|
143
|
-
// If the URL is a function, evaluate it here to do our initalization work
|
144
|
-
var url = computeURL();
|
145
|
-
|
146
|
-
// Make a smart guess about cross-domain if it wasn't explicitly specified
|
147
|
-
if(settings.crossDomain === undefined) {
|
148
|
-
if(url.indexOf("://") === -1) {
|
149
|
-
settings.crossDomain = false;
|
150
|
-
} else {
|
151
|
-
settings.crossDomain = (location.href.split(/\/+/g)[1] !== url.split(/\/+/g)[1]);
|
152
|
-
}
|
153
|
-
}
|
154
|
-
} else if(typeof(url_or_data) === "object") {
|
155
|
-
// Set the local data to search through
|
156
|
-
settings.local_data = url_or_data;
|
157
|
-
}
|
158
|
-
|
159
|
-
// Build class names
|
160
|
-
if(settings.classes) {
|
161
|
-
// Use custom class names
|
162
|
-
settings.classes = $.extend({}, DEFAULT_CLASSES, settings.classes);
|
163
|
-
} else if(settings.theme) {
|
164
|
-
// Use theme-suffixed default class names
|
165
|
-
settings.classes = {};
|
166
|
-
$.each(DEFAULT_CLASSES, function(key, value) {
|
167
|
-
settings.classes[key] = value + "-" + settings.theme;
|
168
|
-
});
|
169
|
-
} else {
|
170
|
-
settings.classes = DEFAULT_CLASSES;
|
171
|
-
}
|
172
|
-
|
173
|
-
|
174
|
-
// Save the tokens
|
175
|
-
var saved_tokens = [];
|
176
|
-
|
177
|
-
// Keep track of the number of tokens in the list
|
178
|
-
var token_count = 0;
|
179
|
-
|
180
|
-
// Basic cache to save on db hits
|
181
|
-
var cache = new $.TokenList.Cache();
|
182
|
-
|
183
|
-
// Keep track of the timeout, old vals
|
184
|
-
var timeout;
|
185
|
-
var input_val;
|
186
|
-
|
187
|
-
// Create a new text input an attach keyup events
|
188
|
-
var input_box = $("<input type=\"text\" autocomplete=\"off\">")
|
189
|
-
.css({
|
190
|
-
outline: "none"
|
191
|
-
})
|
192
|
-
.attr("id", settings.idPrefix + input.id)
|
193
|
-
.focus(function () {
|
194
|
-
if (settings.tokenLimit === null || settings.tokenLimit !== token_count) {
|
195
|
-
show_dropdown_hint();
|
196
|
-
}
|
197
|
-
})
|
198
|
-
.blur(function () {
|
199
|
-
hide_dropdown();
|
200
|
-
$(this).val("");
|
201
|
-
})
|
202
|
-
.bind("keyup keydown blur update", resize_input)
|
203
|
-
.keydown(function (event) {
|
204
|
-
var previous_token;
|
205
|
-
var next_token;
|
206
|
-
|
207
|
-
switch(event.keyCode) {
|
208
|
-
case KEY.LEFT:
|
209
|
-
case KEY.RIGHT:
|
210
|
-
case KEY.UP:
|
211
|
-
case KEY.DOWN:
|
212
|
-
if(!$(this).val()) {
|
213
|
-
previous_token = input_token.prev();
|
214
|
-
next_token = input_token.next();
|
215
|
-
|
216
|
-
if((previous_token.length && previous_token.get(0) === selected_token) || (next_token.length && next_token.get(0) === selected_token)) {
|
217
|
-
// Check if there is a previous/next token and it is selected
|
218
|
-
if(event.keyCode === KEY.LEFT || event.keyCode === KEY.UP) {
|
219
|
-
deselect_token($(selected_token), POSITION.BEFORE);
|
220
|
-
} else {
|
221
|
-
deselect_token($(selected_token), POSITION.AFTER);
|
222
|
-
}
|
223
|
-
} else if((event.keyCode === KEY.LEFT || event.keyCode === KEY.UP) && previous_token.length) {
|
224
|
-
// We are moving left, select the previous token if it exists
|
225
|
-
select_token($(previous_token.get(0)));
|
226
|
-
} else if((event.keyCode === KEY.RIGHT || event.keyCode === KEY.DOWN) && next_token.length) {
|
227
|
-
// We are moving right, select the next token if it exists
|
228
|
-
select_token($(next_token.get(0)));
|
229
|
-
}
|
230
|
-
} else {
|
231
|
-
var dropdown_item = null;
|
232
|
-
|
233
|
-
if(event.keyCode === KEY.DOWN || event.keyCode === KEY.RIGHT) {
|
234
|
-
dropdown_item = $(selected_dropdown_item).next();
|
235
|
-
} else {
|
236
|
-
dropdown_item = $(selected_dropdown_item).prev();
|
237
|
-
}
|
238
|
-
|
239
|
-
if(dropdown_item.length) {
|
240
|
-
select_dropdown_item(dropdown_item);
|
241
|
-
}
|
242
|
-
return false;
|
243
|
-
}
|
244
|
-
break;
|
245
|
-
|
246
|
-
case KEY.BACKSPACE:
|
247
|
-
previous_token = input_token.prev();
|
248
|
-
|
249
|
-
if(!$(this).val().length) {
|
250
|
-
if(selected_token) {
|
251
|
-
delete_token($(selected_token));
|
252
|
-
hidden_input.change();
|
253
|
-
} else if(previous_token.length) {
|
254
|
-
select_token($(previous_token.get(0)));
|
255
|
-
}
|
256
|
-
|
257
|
-
return false;
|
258
|
-
} else if($(this).val().length === 1) {
|
259
|
-
hide_dropdown();
|
260
|
-
} else {
|
261
|
-
// set a timeout just long enough to let this function finish.
|
262
|
-
setTimeout(function(){do_search();}, 5);
|
263
|
-
}
|
264
|
-
break;
|
265
|
-
|
266
|
-
case KEY.TAB:
|
267
|
-
case KEY.ENTER:
|
268
|
-
case KEY.NUMPAD_ENTER:
|
269
|
-
case KEY.COMMA:
|
270
|
-
if(selected_dropdown_item) {
|
271
|
-
add_token($(selected_dropdown_item).data("tokeninput"));
|
272
|
-
hidden_input.change();
|
273
|
-
return false;
|
274
|
-
}
|
275
|
-
break;
|
276
|
-
|
277
|
-
case KEY.ESCAPE:
|
278
|
-
hide_dropdown();
|
279
|
-
return true;
|
280
|
-
|
281
|
-
default:
|
282
|
-
if(String.fromCharCode(event.which)) {
|
283
|
-
// set a timeout just long enough to let this function finish.
|
284
|
-
setTimeout(function(){do_search();}, 5);
|
285
|
-
}
|
286
|
-
break;
|
287
|
-
}
|
288
|
-
});
|
289
|
-
|
290
|
-
// Keep a reference to the original input box
|
291
|
-
var hidden_input = $(input)
|
292
|
-
.hide()
|
293
|
-
.val("")
|
294
|
-
.focus(function () {
|
295
|
-
input_box.focus();
|
296
|
-
})
|
297
|
-
.blur(function () {
|
298
|
-
input_box.blur();
|
299
|
-
});
|
300
|
-
|
301
|
-
// Keep a reference to the selected token and dropdown item
|
302
|
-
var selected_token = null;
|
303
|
-
var selected_token_index = 0;
|
304
|
-
var selected_dropdown_item = null;
|
305
|
-
|
306
|
-
// The list to store the token items in
|
307
|
-
var token_list = $("<ul />")
|
308
|
-
.addClass(settings.classes.tokenList)
|
309
|
-
.click(function (event) {
|
310
|
-
var li = $(event.target).closest("li");
|
311
|
-
if(li && li.get(0) && $.data(li.get(0), "tokeninput")) {
|
312
|
-
toggle_select_token(li);
|
313
|
-
} else {
|
314
|
-
// Deselect selected token
|
315
|
-
if(selected_token) {
|
316
|
-
deselect_token($(selected_token), POSITION.END);
|
317
|
-
}
|
318
|
-
|
319
|
-
// Focus input box
|
320
|
-
input_box.focus();
|
321
|
-
}
|
322
|
-
})
|
323
|
-
.mouseover(function (event) {
|
324
|
-
var li = $(event.target).closest("li");
|
325
|
-
if(li && selected_token !== this) {
|
326
|
-
li.addClass(settings.classes.highlightedToken);
|
327
|
-
}
|
328
|
-
})
|
329
|
-
.mouseout(function (event) {
|
330
|
-
var li = $(event.target).closest("li");
|
331
|
-
if(li && selected_token !== this) {
|
332
|
-
li.removeClass(settings.classes.highlightedToken);
|
333
|
-
}
|
334
|
-
})
|
335
|
-
.insertBefore(hidden_input);
|
336
|
-
|
337
|
-
// The token holding the input box
|
338
|
-
var input_token = $("<li />")
|
339
|
-
.addClass(settings.classes.inputToken)
|
340
|
-
.appendTo(token_list)
|
341
|
-
.append(input_box);
|
342
|
-
|
343
|
-
// The list to store the dropdown items in
|
344
|
-
var dropdown = $("<div>")
|
345
|
-
.addClass(settings.classes.dropdown)
|
346
|
-
.appendTo("body")
|
347
|
-
.hide();
|
348
|
-
|
349
|
-
// Magic element to help us resize the text input
|
350
|
-
var input_resizer = $("<tester/>")
|
351
|
-
.insertAfter(input_box)
|
352
|
-
.css({
|
353
|
-
position: "absolute",
|
354
|
-
top: -9999,
|
355
|
-
left: -9999,
|
356
|
-
width: "auto",
|
357
|
-
fontSize: input_box.css("fontSize"),
|
358
|
-
fontFamily: input_box.css("fontFamily"),
|
359
|
-
fontWeight: input_box.css("fontWeight"),
|
360
|
-
letterSpacing: input_box.css("letterSpacing"),
|
361
|
-
whiteSpace: "nowrap"
|
362
|
-
});
|
363
|
-
|
364
|
-
// Pre-populate list if items exist
|
365
|
-
hidden_input.val("");
|
366
|
-
var li_data = settings.prePopulate || hidden_input.data("pre");
|
367
|
-
if(settings.processPrePopulate && $.isFunction(settings.onResult)) {
|
368
|
-
li_data = settings.onResult.call(hidden_input, li_data);
|
369
|
-
}
|
370
|
-
if(li_data && li_data.length) {
|
371
|
-
$.each(li_data, function (index, value) {
|
372
|
-
insert_token(value);
|
373
|
-
checkTokenLimit();
|
374
|
-
});
|
375
|
-
}
|
376
|
-
|
377
|
-
// Initialization is done
|
378
|
-
if($.isFunction(settings.onReady)) {
|
379
|
-
settings.onReady.call();
|
380
|
-
}
|
381
|
-
|
382
|
-
//
|
383
|
-
// Public functions
|
384
|
-
//
|
385
|
-
|
386
|
-
this.clear = function() {
|
387
|
-
token_list.children("li").each(function() {
|
388
|
-
if ($(this).children("input").length === 0) {
|
389
|
-
delete_token($(this));
|
390
|
-
}
|
391
|
-
});
|
392
|
-
}
|
393
|
-
|
394
|
-
this.add = function(item) {
|
395
|
-
add_token(item);
|
396
|
-
}
|
397
|
-
|
398
|
-
this.remove = function(item) {
|
399
|
-
token_list.children("li").each(function() {
|
400
|
-
if ($(this).children("input").length === 0) {
|
401
|
-
var currToken = $(this).data("tokeninput");
|
402
|
-
var match = true;
|
403
|
-
for (var prop in item) {
|
404
|
-
if (item[prop] !== currToken[prop]) {
|
405
|
-
match = false;
|
406
|
-
break;
|
407
|
-
}
|
408
|
-
}
|
409
|
-
if (match) {
|
410
|
-
delete_token($(this));
|
411
|
-
}
|
412
|
-
}
|
413
|
-
});
|
414
|
-
}
|
415
|
-
|
416
|
-
this.getTokens = function() {
|
417
|
-
return saved_tokens;
|
418
|
-
}
|
419
|
-
|
420
|
-
//
|
421
|
-
// Private functions
|
422
|
-
//
|
423
|
-
|
424
|
-
function checkTokenLimit() {
|
425
|
-
if(settings.tokenLimit !== null && token_count >= settings.tokenLimit) {
|
426
|
-
input_box.hide();
|
427
|
-
hide_dropdown();
|
428
|
-
return;
|
429
|
-
}
|
430
|
-
}
|
431
|
-
|
432
|
-
function resize_input() {
|
433
|
-
if(input_val === (input_val = input_box.val())) {return;}
|
434
|
-
|
435
|
-
// Enter new content into resizer and resize input accordingly
|
436
|
-
var escaped = input_val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>');
|
437
|
-
input_resizer.html(escaped);
|
438
|
-
input_box.width(input_resizer.width() + 30);
|
439
|
-
}
|
440
|
-
|
441
|
-
function is_printable_character(keycode) {
|
442
|
-
return ((keycode >= 48 && keycode <= 90) || // 0-1a-z
|
443
|
-
(keycode >= 96 && keycode <= 111) || // numpad 0-9 + - / * .
|
444
|
-
(keycode >= 186 && keycode <= 192) || // ; = , - . / ^
|
445
|
-
(keycode >= 219 && keycode <= 222)); // ( \ ) '
|
446
|
-
}
|
447
|
-
|
448
|
-
// Inner function to a token to the list
|
449
|
-
function insert_token(item) {
|
450
|
-
var this_token = settings.tokenFormatter(item);
|
451
|
-
this_token = $(this_token)
|
452
|
-
.addClass(settings.classes.token)
|
453
|
-
.insertBefore(input_token);
|
454
|
-
|
455
|
-
// The 'delete token' button
|
456
|
-
$("<span>" + settings.deleteText + "</span>")
|
457
|
-
.addClass(settings.classes.tokenDelete)
|
458
|
-
.appendTo(this_token)
|
459
|
-
.click(function () {
|
460
|
-
delete_token($(this).parent());
|
461
|
-
hidden_input.change();
|
462
|
-
return false;
|
463
|
-
});
|
464
|
-
|
465
|
-
// Store data on the token
|
466
|
-
var token_data = {"id": item.id};
|
467
|
-
token_data[settings.propertyToSearch] = item[settings.propertyToSearch];
|
468
|
-
$.data(this_token.get(0), "tokeninput", item);
|
469
|
-
|
470
|
-
// Save this token for duplicate checking
|
471
|
-
saved_tokens = saved_tokens.slice(0,selected_token_index).concat([token_data]).concat(saved_tokens.slice(selected_token_index));
|
472
|
-
selected_token_index++;
|
473
|
-
|
474
|
-
// Update the hidden input
|
475
|
-
update_hidden_input(saved_tokens, hidden_input);
|
476
|
-
|
477
|
-
token_count += 1;
|
478
|
-
|
479
|
-
// Check the token limit
|
480
|
-
if(settings.tokenLimit !== null && token_count >= settings.tokenLimit) {
|
481
|
-
input_box.hide();
|
482
|
-
hide_dropdown();
|
483
|
-
}
|
484
|
-
|
485
|
-
return this_token;
|
486
|
-
}
|
487
|
-
|
488
|
-
// Add a token to the token list based on user input
|
489
|
-
function add_token (item) {
|
490
|
-
var callback = settings.onAdd;
|
491
|
-
|
492
|
-
// See if the token already exists and select it if we don't want duplicates
|
493
|
-
if(token_count > 0 && settings.preventDuplicates) {
|
494
|
-
var found_existing_token = null;
|
495
|
-
token_list.children().each(function () {
|
496
|
-
var existing_token = $(this);
|
497
|
-
var existing_data = $.data(existing_token.get(0), "tokeninput");
|
498
|
-
if(existing_data && existing_data.id === item.id) {
|
499
|
-
found_existing_token = existing_token;
|
500
|
-
return false;
|
501
|
-
}
|
502
|
-
});
|
503
|
-
|
504
|
-
if(found_existing_token) {
|
505
|
-
select_token(found_existing_token);
|
506
|
-
input_token.insertAfter(found_existing_token);
|
507
|
-
input_box.focus();
|
508
|
-
return;
|
509
|
-
}
|
510
|
-
}
|
511
|
-
|
512
|
-
// Insert the new tokens
|
513
|
-
if(settings.tokenLimit == null || token_count < settings.tokenLimit) {
|
514
|
-
insert_token(item);
|
515
|
-
checkTokenLimit();
|
516
|
-
}
|
517
|
-
|
518
|
-
// Clear input box
|
519
|
-
input_box.val("");
|
520
|
-
|
521
|
-
// Don't show the help dropdown, they've got the idea
|
522
|
-
hide_dropdown();
|
523
|
-
|
524
|
-
// Execute the onAdd callback if defined
|
525
|
-
if($.isFunction(callback)) {
|
526
|
-
callback.call(hidden_input,item);
|
527
|
-
}
|
528
|
-
}
|
529
|
-
|
530
|
-
// Select a token in the token list
|
531
|
-
function select_token (token) {
|
532
|
-
token.addClass(settings.classes.selectedToken);
|
533
|
-
selected_token = token.get(0);
|
534
|
-
|
535
|
-
// Hide input box
|
536
|
-
input_box.val("");
|
537
|
-
|
538
|
-
// Hide dropdown if it is visible (eg if we clicked to select token)
|
539
|
-
hide_dropdown();
|
540
|
-
}
|
541
|
-
|
542
|
-
// Deselect a token in the token list
|
543
|
-
function deselect_token (token, position) {
|
544
|
-
token.removeClass(settings.classes.selectedToken);
|
545
|
-
selected_token = null;
|
546
|
-
|
547
|
-
if(position === POSITION.BEFORE) {
|
548
|
-
input_token.insertBefore(token);
|
549
|
-
selected_token_index--;
|
550
|
-
} else if(position === POSITION.AFTER) {
|
551
|
-
input_token.insertAfter(token);
|
552
|
-
selected_token_index++;
|
553
|
-
} else {
|
554
|
-
input_token.appendTo(token_list);
|
555
|
-
selected_token_index = token_count;
|
556
|
-
}
|
557
|
-
|
558
|
-
// Show the input box and give it focus again
|
559
|
-
input_box.focus();
|
560
|
-
}
|
561
|
-
|
562
|
-
// Toggle selection of a token in the token list
|
563
|
-
function toggle_select_token(token) {
|
564
|
-
var previous_selected_token = selected_token;
|
565
|
-
|
566
|
-
if(selected_token) {
|
567
|
-
deselect_token($(selected_token), POSITION.END);
|
568
|
-
}
|
569
|
-
|
570
|
-
if(previous_selected_token === token.get(0)) {
|
571
|
-
deselect_token(token, POSITION.END);
|
572
|
-
} else {
|
573
|
-
select_token(token);
|
574
|
-
}
|
575
|
-
}
|
576
|
-
|
577
|
-
// Delete a token from the token list
|
578
|
-
function delete_token (token) {
|
579
|
-
// Remove the id from the saved list
|
580
|
-
var token_data = $.data(token.get(0), "tokeninput");
|
581
|
-
var callback = settings.onDelete;
|
582
|
-
|
583
|
-
var index = token.prevAll().length;
|
584
|
-
if(index > selected_token_index) index--;
|
585
|
-
|
586
|
-
// Delete the token
|
587
|
-
token.remove();
|
588
|
-
selected_token = null;
|
589
|
-
|
590
|
-
// Show the input box and give it focus again
|
591
|
-
input_box.focus();
|
592
|
-
|
593
|
-
// Remove this token from the saved list
|
594
|
-
saved_tokens = saved_tokens.slice(0,index).concat(saved_tokens.slice(index+1));
|
595
|
-
if(index < selected_token_index) selected_token_index--;
|
596
|
-
|
597
|
-
// Update the hidden input
|
598
|
-
update_hidden_input(saved_tokens, hidden_input);
|
599
|
-
|
600
|
-
token_count -= 1;
|
601
|
-
|
602
|
-
if(settings.tokenLimit !== null) {
|
603
|
-
input_box
|
604
|
-
.show()
|
605
|
-
.val("")
|
606
|
-
.focus();
|
607
|
-
}
|
608
|
-
|
609
|
-
// Execute the onDelete callback if defined
|
610
|
-
if($.isFunction(callback)) {
|
611
|
-
callback.call(hidden_input,token_data);
|
612
|
-
}
|
613
|
-
}
|
614
|
-
|
615
|
-
// Update the hidden input box value
|
616
|
-
function update_hidden_input(saved_tokens, hidden_input) {
|
617
|
-
var token_values = $.map(saved_tokens, function (el) {
|
618
|
-
return el[settings.tokenValue];
|
619
|
-
});
|
620
|
-
hidden_input.val(token_values.join(settings.tokenDelimiter));
|
621
|
-
|
622
|
-
}
|
623
|
-
|
624
|
-
// Hide and clear the results dropdown
|
625
|
-
function hide_dropdown () {
|
626
|
-
dropdown.hide().empty();
|
627
|
-
selected_dropdown_item = null;
|
628
|
-
}
|
629
|
-
|
630
|
-
function show_dropdown() {
|
631
|
-
dropdown
|
632
|
-
.css({
|
633
|
-
position: "absolute",
|
634
|
-
top: $(token_list).offset().top + $(token_list).outerHeight(),
|
635
|
-
left: $(token_list).offset().left,
|
636
|
-
zindex: 999
|
637
|
-
})
|
638
|
-
.show();
|
639
|
-
}
|
640
|
-
|
641
|
-
function show_dropdown_searching () {
|
642
|
-
if(settings.searchingText) {
|
643
|
-
dropdown.html("<p>"+settings.searchingText+"</p>");
|
644
|
-
show_dropdown();
|
645
|
-
}
|
646
|
-
}
|
647
|
-
|
648
|
-
function show_dropdown_hint () {
|
649
|
-
if(settings.hintText) {
|
650
|
-
dropdown.html("<p>"+settings.hintText+"</p>");
|
651
|
-
show_dropdown();
|
652
|
-
}
|
653
|
-
}
|
654
|
-
|
655
|
-
// Highlight the query part of the search term
|
656
|
-
function highlight_term(value, term) {
|
657
|
-
return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<b>$1</b>");
|
658
|
-
}
|
659
|
-
|
660
|
-
function find_value_and_highlight_term(template, value, term) {
|
661
|
-
return template.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + value + ")(?![^<>]*>)(?![^&;]+;)", "g"), highlight_term(value, term));
|
662
|
-
}
|
663
|
-
|
664
|
-
// Populate the results dropdown with some results
|
665
|
-
function populate_dropdown (query, results) {
|
666
|
-
if(results && results.length) {
|
667
|
-
dropdown.empty();
|
668
|
-
var dropdown_ul = $("<ul>")
|
669
|
-
.appendTo(dropdown)
|
670
|
-
.mouseover(function (event) {
|
671
|
-
select_dropdown_item($(event.target).closest("li"));
|
672
|
-
})
|
673
|
-
.mousedown(function (event) {
|
674
|
-
add_token($(event.target).closest("li").data("tokeninput"));
|
675
|
-
hidden_input.change();
|
676
|
-
return false;
|
677
|
-
})
|
678
|
-
.hide();
|
679
|
-
|
680
|
-
$.each(results, function(index, value) {
|
681
|
-
var this_li = settings.resultsFormatter(value);
|
682
|
-
|
683
|
-
this_li = find_value_and_highlight_term(this_li ,value[settings.propertyToSearch], query);
|
684
|
-
|
685
|
-
this_li = $(this_li).appendTo(dropdown_ul);
|
686
|
-
|
687
|
-
if(index % 2) {
|
688
|
-
this_li.addClass(settings.classes.dropdownItem);
|
689
|
-
} else {
|
690
|
-
this_li.addClass(settings.classes.dropdownItem2);
|
691
|
-
}
|
692
|
-
|
693
|
-
if(index === 0) {
|
694
|
-
select_dropdown_item(this_li);
|
695
|
-
}
|
696
|
-
|
697
|
-
$.data(this_li.get(0), "tokeninput", value);
|
698
|
-
});
|
699
|
-
|
700
|
-
show_dropdown();
|
701
|
-
|
702
|
-
if(settings.animateDropdown) {
|
703
|
-
dropdown_ul.slideDown("fast");
|
704
|
-
} else {
|
705
|
-
dropdown_ul.show();
|
706
|
-
}
|
707
|
-
} else {
|
708
|
-
if(settings.noResultsText) {
|
709
|
-
dropdown.html("<p>"+settings.noResultsText+"</p>");
|
710
|
-
show_dropdown();
|
711
|
-
}
|
712
|
-
}
|
713
|
-
}
|
714
|
-
|
715
|
-
// Highlight an item in the results dropdown
|
716
|
-
function select_dropdown_item (item) {
|
717
|
-
if(item) {
|
718
|
-
if(selected_dropdown_item) {
|
719
|
-
deselect_dropdown_item($(selected_dropdown_item));
|
720
|
-
}
|
721
|
-
|
722
|
-
item.addClass(settings.classes.selectedDropdownItem);
|
723
|
-
selected_dropdown_item = item.get(0);
|
724
|
-
}
|
725
|
-
}
|
726
|
-
|
727
|
-
// Remove highlighting from an item in the results dropdown
|
728
|
-
function deselect_dropdown_item (item) {
|
729
|
-
item.removeClass(settings.classes.selectedDropdownItem);
|
730
|
-
selected_dropdown_item = null;
|
731
|
-
}
|
732
|
-
|
733
|
-
// Do a search and show the "searching" dropdown if the input is longer
|
734
|
-
// than settings.minChars
|
735
|
-
function do_search() {
|
736
|
-
var query = input_box.val().toLowerCase();
|
737
|
-
|
738
|
-
if(query && query.length) {
|
739
|
-
if(selected_token) {
|
740
|
-
deselect_token($(selected_token), POSITION.AFTER);
|
741
|
-
}
|
742
|
-
|
743
|
-
if(query.length >= settings.minChars) {
|
744
|
-
show_dropdown_searching();
|
745
|
-
clearTimeout(timeout);
|
746
|
-
|
747
|
-
timeout = setTimeout(function(){
|
748
|
-
run_search(query);
|
749
|
-
}, settings.searchDelay);
|
750
|
-
} else {
|
751
|
-
hide_dropdown();
|
752
|
-
}
|
753
|
-
}
|
754
|
-
}
|
755
|
-
|
756
|
-
// Do the actual search
|
757
|
-
function run_search(query) {
|
758
|
-
var cache_key = query + computeURL();
|
759
|
-
var cached_results = cache.get(cache_key);
|
760
|
-
if(cached_results) {
|
761
|
-
populate_dropdown(query, cached_results);
|
762
|
-
} else {
|
763
|
-
// Are we doing an ajax search or local data search?
|
764
|
-
if(settings.url) {
|
765
|
-
var url = computeURL();
|
766
|
-
// Extract exisiting get params
|
767
|
-
var ajax_params = {};
|
768
|
-
ajax_params.data = {};
|
769
|
-
if(url.indexOf("?") > -1) {
|
770
|
-
var parts = url.split("?");
|
771
|
-
ajax_params.url = parts[0];
|
772
|
-
|
773
|
-
var param_array = parts[1].split("&");
|
774
|
-
$.each(param_array, function (index, value) {
|
775
|
-
var kv = value.split("=");
|
776
|
-
ajax_params.data[kv[0]] = kv[1];
|
777
|
-
});
|
778
|
-
} else {
|
779
|
-
ajax_params.url = url;
|
780
|
-
}
|
781
|
-
|
782
|
-
// Prepare the request
|
783
|
-
ajax_params.data[settings.queryParam] = query;
|
784
|
-
ajax_params.type = settings.method;
|
785
|
-
ajax_params.dataType = settings.contentType;
|
786
|
-
if(settings.crossDomain) {
|
787
|
-
ajax_params.dataType = "jsonp";
|
788
|
-
}
|
789
|
-
|
790
|
-
// Attach the success callback
|
791
|
-
ajax_params.success = function(results) {
|
792
|
-
if($.isFunction(settings.onResult)) {
|
793
|
-
results = settings.onResult.call(hidden_input, results);
|
794
|
-
}
|
795
|
-
cache.add(cache_key, settings.jsonContainer ? results[settings.jsonContainer] : results);
|
796
|
-
|
797
|
-
// only populate the dropdown if the results are associated with the active search query
|
798
|
-
if(input_box.val().toLowerCase() === query) {
|
799
|
-
populate_dropdown(query, settings.jsonContainer ? results[settings.jsonContainer] : results);
|
800
|
-
}
|
801
|
-
};
|
802
|
-
|
803
|
-
// Make the request
|
804
|
-
$.ajax(ajax_params);
|
805
|
-
} else if(settings.local_data) {
|
806
|
-
// Do the search through local data
|
807
|
-
var results = $.grep(settings.local_data, function (row) {
|
808
|
-
return row[settings.propertyToSearch].toLowerCase().indexOf(query.toLowerCase()) > -1;
|
809
|
-
});
|
810
|
-
|
811
|
-
if($.isFunction(settings.onResult)) {
|
812
|
-
results = settings.onResult.call(hidden_input, results);
|
813
|
-
}
|
814
|
-
cache.add(cache_key, results);
|
815
|
-
populate_dropdown(query, results);
|
816
|
-
}
|
817
|
-
}
|
818
|
-
}
|
819
|
-
|
820
|
-
// compute the dynamic URL
|
821
|
-
function computeURL() {
|
822
|
-
var url = settings.url;
|
823
|
-
if(typeof settings.url == 'function') {
|
824
|
-
url = settings.url.call();
|
825
|
-
}
|
826
|
-
return url;
|
827
|
-
}
|
828
|
-
};
|
829
|
-
|
830
|
-
// Really basic cache for the results
|
831
|
-
$.TokenList.Cache = function (options) {
|
832
|
-
var settings = $.extend({
|
833
|
-
max_size: 500
|
834
|
-
}, options);
|
835
|
-
|
836
|
-
var data = {};
|
837
|
-
var size = 0;
|
838
|
-
|
839
|
-
var flush = function () {
|
840
|
-
data = {};
|
841
|
-
size = 0;
|
842
|
-
};
|
843
|
-
|
844
|
-
this.add = function (query, results) {
|
845
|
-
if(size > settings.max_size) {
|
846
|
-
flush();
|
847
|
-
}
|
848
|
-
|
849
|
-
if(!data[query]) {
|
850
|
-
size += 1;
|
851
|
-
}
|
852
|
-
|
853
|
-
data[query] = results;
|
854
|
-
};
|
855
|
-
|
856
|
-
this.get = function (query) {
|
857
|
-
return data[query];
|
858
|
-
};
|
859
|
-
};
|
860
|
-
}(jQuery));
|