| <%=ot.name %> |
<%=ot.presentation %> |
- <%= link_to_with_icon 'icon-plus', t("select"),
+ | <%= link_to_with_icon 'plus', t("select"),
url_for(:controller => "admin/option_types",
:id => ot,
:product_id => @product.permalink,
diff --git a/spree_flexi_variants/app/views/spree/admin/product_customization_types/edit.html.erb b/spree_flexi_variants/app/views/spree/admin/product_customization_types/edit.html.erb
index ccbf1f2a..76729356 100644
--- a/spree_flexi_variants/app/views/spree/admin/product_customization_types/edit.html.erb
+++ b/spree_flexi_variants/app/views/spree/admin/product_customization_types/edit.html.erb
@@ -6,7 +6,7 @@
<% content_for :page_actions do %>
- <%= button_link_to Spree.t(:product_customization_types_list), spree.admin_product_customization_types_path, :icon => 'icon-arrow-left' %>
+ <%= button_link_to Spree.t(:product_customization_types_list), spree.admin_product_customization_types_path, :icon => 'arrow-left' %>
<% end %>
diff --git a/spree_flexi_variants/app/views/spree/admin/product_customization_types/index.html.erb b/spree_flexi_variants/app/views/spree/admin/product_customization_types/index.html.erb
index f78fe76c..ca7b06ea 100644
--- a/spree_flexi_variants/app/views/spree/admin/product_customization_types/index.html.erb
+++ b/spree_flexi_variants/app/views/spree/admin/product_customization_types/index.html.erb
@@ -3,7 +3,7 @@
<% content_for(:page_title, Spree.t("product_customization_types")) %>
<% content_for(:page_actions) do %>
- <%= button_link_to Spree.t("new_product_customization_type"), new_admin_product_customization_type_url, { :remote => true, :icon => 'icon-plus', :id => 'new_product_customization_type_link' } %>
+ <%= button_link_to Spree.t("new_product_customization_type"), new_admin_product_customization_type_url, { :remote => true, :icon => 'plus', :id => 'new_product_customization_type_link' } %>
<% end %>
diff --git a/spree_multi_site/Gemfile b/spree_multi_site/Gemfile
index 5581d11c..6e58e57d 100644
--- a/spree_multi_site/Gemfile
+++ b/spree_multi_site/Gemfile
@@ -3,11 +3,12 @@ source 'http://ruby.taobao.org'
group :development,:test do
- gem 'mail_view'
+ gem 'mysql2'
+ #gem 'mail_view'
# Provides basic authentication functionality for testing parts of your engine
gem 'spree', '~>2.4' # required to create dummy
- #gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '2-0-stable'
+ #test require it. site create user
+ #gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '2-4-stable'
end
gemspec
-
diff --git a/spree_multi_site/app/assets/javascripts/store/spree_multi_site.js b/spree_multi_site/app/assets/javascripts/store/spree_multi_site.js
index d10fba7f..fa0a16ee 100644
--- a/spree_multi_site/app/assets/javascripts/store/spree_multi_site.js
+++ b/spree_multi_site/app/assets/javascripts/store/spree_multi_site.js
@@ -1 +1 @@
-//= require store/spree_frontend
+//= require spree/frontend
diff --git a/spree_multi_site/app/assets/stylesheets/store/spree_multi_site.css b/spree_multi_site/app/assets/stylesheets/store/spree_multi_site.css
index bce0f84f..ad7db303 100644
--- a/spree_multi_site/app/assets/stylesheets/store/spree_multi_site.css
+++ b/spree_multi_site/app/assets/stylesheets/store/spree_multi_site.css
@@ -1,3 +1,3 @@
/*
- *= require store/spree_frontend
+ *= require spree/frontend
*/
diff --git a/spree_multi_site/app/controllers/spree/admin/general_settings_controller_decorator.rb b/spree_multi_site/app/controllers/spree/admin/general_settings_controller_decorator.rb
index 94e6da54..05e7e04f 100644
--- a/spree_multi_site/app/controllers/spree/admin/general_settings_controller_decorator.rb
+++ b/spree_multi_site/app/controllers/spree/admin/general_settings_controller_decorator.rb
@@ -1,18 +1,28 @@
Spree::Admin::GeneralSettingsController.class_eval do
#override original, update site model
+ def edit
+ @preferences_security = [:allow_ssl_in_production,
+ :allow_ssl_in_staging, :allow_ssl_in_development_and_test,
+ :check_for_spree_alerts]
+ @preferences_currency = [:display_currency, :hide_cents]
+ end
+
+
def update
- params.each do |name, value|
- next unless Spree::Config.has_preference? name
- Spree::Config[name] = value
- if name =='site_name'
- Spree::Site.current.update_attribute(:name, value)
- end
- if name =='site_url'
- Spree::Site.current.update_attribute(:domain, value)
- end
- end
- flash[:success] = Spree.t(:successfully_updated, :resource => Spree.t(:general_settings))
+ #params.each do |name, value|
+ # next unless Spree::Config.has_preference? name
+ # Spree::Config[name] = value
+ #end
+ current_store.update_attributes store_params
+
+ current_store.site.update_attributes site_params
+ flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:general_settings))
redirect_to edit_admin_general_settings_path
end
+
+ def site_params
+ params.require(:site).permit(Spree::PermittedAttributes.site_attributes)
+ end
+
end
\ No newline at end of file
diff --git a/spree_multi_site/app/controllers/spree/admin/images_controller_decorator.rb b/spree_multi_site/app/controllers/spree/admin/images_controller_decorator.rb
index af1212d3..e65ebeee 100644
--- a/spree_multi_site/app/controllers/spree/admin/images_controller_decorator.rb
+++ b/spree_multi_site/app/controllers/spree/admin/images_controller_decorator.rb
@@ -1,24 +1,24 @@
Spree::Admin::ImagesController.class_eval do
- create.before :update_paperclip_settings
- update.before :update_paperclip_settings
+ #create.before :update_paperclip_settings
+ #update.before :update_paperclip_settings
private
+ # we do not support this feature now.
# copy from image_settings_controller
# by default Spree::Image.attachment_definitions is set before site initialize, we need reset it after get site.
- def update_paperclip_settings
- if Spree::Config[:use_s3]
- s3_creds = { :access_key_id => Spree::Config[:s3_access_key], :secret_access_key => Spree::Config[:s3_secret], :bucket => Spree::Config[:s3_bucket] }
- Spree::Image.attachment_definitions[:attachment][:storage] = :s3
- Spree::Image.attachment_definitions[:attachment][:s3_credentials] = s3_creds
- Spree::Image.attachment_definitions[:attachment][:s3_headers] = ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
- Spree::Image.attachment_definitions[:attachment][:bucket] = Spree::Config[:s3_bucket]
- else
- Spree::Image.attachment_definitions[:attachment].delete :storage
- end
-
- Spree::Image.attachment_definitions[:attachment][:styles] = ActiveSupport::JSON.decode(Spree::Config[:attachment_styles]).symbolize_keys!
- Spree::Image.attachment_definitions[:attachment][:path] = Spree::Config[:attachment_path]
- Spree::Image.attachment_definitions[:attachment][:default_url] = Spree::Config[:attachment_default_url]
- Spree::Image.attachment_definitions[:attachment][:default_style] = Spree::Config[:attachment_default_style]
- end
+ #def update_paperclip_settings
+ # if Spree::Config[:use_s3]
+ # s3_creds = { :access_key_id => Spree::Config[:s3_access_key], :secret_access_key => Spree::Config[:s3_secret], :bucket => Spree::Config[:s3_bucket] }
+ # Spree::Image.attachment_definitions[:attachment][:storage] = :s3
+ # Spree::Image.attachment_definitions[:attachment][:s3_credentials] = s3_creds
+ # Spree::Image.attachment_definitions[:attachment][:s3_headers] = ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
+ # Spree::Image.attachment_definitions[:attachment][:bucket] = Spree::Config[:s3_bucket]
+ # else
+ # Spree::Image.attachment_definitions[:attachment].delete :storage
+ # end
+ # Spree::Image.attachment_definitions[:attachment][:styles] = ActiveSupport::JSON.decode(Spree::Config[:attachment_styles]).symbolize_keys!
+ # Spree::Image.attachment_definitions[:attachment][:path] = Spree::Config[:attachment_path]
+ # Spree::Image.attachment_definitions[:attachment][:default_url] = Spree::Config[:attachment_default_url]
+ # Spree::Image.attachment_definitions[:attachment][:default_style] = Spree::Config[:attachment_default_style]
+ #end
end
diff --git a/spree_multi_site/app/controllers/spree/admin/products_controller_decorator.rb b/spree_multi_site/app/controllers/spree/admin/products_controller_decorator.rb
index c8a2f691..acd9a0f3 100644
--- a/spree_multi_site/app/controllers/spree/admin/products_controller_decorator.rb
+++ b/spree_multi_site/app/controllers/spree/admin/products_controller_decorator.rb
@@ -2,20 +2,17 @@
update.before :prepare_more_params
create.before :prepare_more_params
around_filter :only=>[:create,:edit, :update, :destroy] do |controller, action_block|
- Spree::MultiSiteSystem.with_context_admin_site_product{
- action_block.call
+ Spree::MultiSiteSystem.with_context_free_taxon{
+ action_block.call
}
end
-
-
+
+
private
def prepare_more_params
if params[:product][:global_taxon_ids].present?
params[:product][:global_taxon_ids] = params[:product][:global_taxon_ids].split(',')
end
- end
-
- #def prepare_multi_site_context
- # Spree::MultiSiteSystem.setup_context('admin_site_product')
- #end
- end
\ No newline at end of file
+ end
+
+ end
diff --git a/spree_multi_site/app/controllers/spree/api/variants_controller_decorator.rb b/spree_multi_site/app/controllers/spree/api/variants_controller_decorator.rb
new file mode 100644
index 00000000..60044fcd
--- /dev/null
+++ b/spree_multi_site/app/controllers/spree/api/variants_controller_decorator.rb
@@ -0,0 +1,8 @@
+Spree::Api::VariantsController.class_eval do
+ def index
+ # since variant have no site_id, we should join product here
+ @variants = scope.joins(:product).includes({ option_values: :option_type }, :product, :default_price, :images, { stock_items: :stock_location })
+ .ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
+ respond_with(@variants)
+ end
+end
diff --git a/spree_multi_site/app/controllers/spree/sites_controller.rb b/spree_multi_site/app/controllers/spree/sites_controller.rb
index 248521e0..f1eeecbb 100644
--- a/spree_multi_site/app/controllers/spree/sites_controller.rb
+++ b/spree_multi_site/app/controllers/spree/sites_controller.rb
@@ -7,14 +7,15 @@ def new
if params[:template_theme_id].present?
@template_theme = Spree::TemplateTheme.foreign.find params[:template_theme_id]
end
- @site = Site.new
+ @site = Site.new
@user = @site.users.build
+ @store = @site.stores.build
end
# called from dalianshops home page
def quick_lunch
- params[:user][:password_confirmation] = params[:user][:password]
- @site = create_site( params[:site], params[:user] )
+
+ @site = create_site( permitted_resource_params )
if @site.persisted?
redirect_to @site.admin_url
else
@@ -28,7 +29,7 @@ def show
end
def create
- @site = create_site( params[:site], params[:user] )
+ @site = create_site( permitted_resource_params )
if @site.persisted?
flash[:success] = Spree.t(:site_successfully_opened, :site_name => @site.name)
#redirect_to @site.admin_url, format: 'js', status: 303
@@ -44,13 +45,9 @@ def create
end
# options
- def create_site( site_params, user_params, options= {})
- site = Site.new(site_params)
- user = Spree.user_class.new(user_params)
- site.users << user
+ def create_site( permitted_site_params)
+ site = Site.new(permitted_site_params)
if site.save
- site.users.first.spree_roles << Spree::Role.find_by_name('admin')
- shipping_category = site.shipping_categories.create!( :name=>Spree.t(:default))
# should not add @site.name as suffix of role.name, User.admin require :name="admin"
if site.has_sample?
site.load_sample
@@ -63,7 +60,14 @@ def create_site( site_params, user_params, options= {})
end
site
end
-
+
+ def permitted_resource_params
+ params[object_name].present? ? params.require(object_name).permit! : ActionController::Parameters.new
+ end
+
+ def object_name
+ 'site'
+ end
end
end
\ No newline at end of file
diff --git a/spree_multi_site/app/helpers/spree/base_helper_decorator.rb b/spree_multi_site/app/helpers/spree/base_helper_decorator.rb
new file mode 100644
index 00000000..e75ded08
--- /dev/null
+++ b/spree_multi_site/app/helpers/spree/base_helper_decorator.rb
@@ -0,0 +1,15 @@
+module Spree
+ module BaseHelper
+ private
+ # override original, always return style for feature :aliyun_oss
+ # Returns style of image or nil
+ def image_style_from_method_name(method_name)
+ if method_name.to_s.match(/_image$/) && style = method_name.to_s.sub(/_image$/, '')
+ #possible_styles = Spree::Image.attachment_definitions[:attachment][:styles]
+ #style if style.in? possible_styles.with_indifferent_access
+ style
+ end
+ end
+
+ end
+end
diff --git a/spree_multi_site/app/jobs/sample_seed_job.rb b/spree_multi_site/app/jobs/sample_seed_job.rb
index df3fd168..7efe4e38 100644
--- a/spree_multi_site/app/jobs/sample_seed_job.rb
+++ b/spree_multi_site/app/jobs/sample_seed_job.rb
@@ -1,14 +1,13 @@
class SampleSeedJob < Struct.new(:site)
def perform
- Spree::Site.current = site
+ Spree::Site.current = site
#site.users.first, it require `spree_users`.`site_id` =current_site.id
admin_user = site.users.first
- site.load_sample
-Rails.logger.info "user=#{admin_user.id}"
+ site.load_sample
Spree::UserMailer.load_sample(admin_user).deliver
end
def success(job)
site.update_attributes!(:loading_sample=>false)
end
-end
\ No newline at end of file
+end
diff --git a/spree_multi_site/app/models/spree/decorator/taxon_decorator.rb b/spree_multi_site/app/models/spree/decorator/taxon_decorator.rb
new file mode 100644
index 00000000..076290b8
--- /dev/null
+++ b/spree_multi_site/app/models/spree/decorator/taxon_decorator.rb
@@ -0,0 +1,3 @@
+Spree::Taxon.class_eval do
+
+end
diff --git a/spree_multi_site/app/models/spree/image_decorator.rb b/spree_multi_site/app/models/spree/image_decorator.rb
index d35777c6..6b4fa1aa 100644
--- a/spree_multi_site/app/models/spree/image_decorator.rb
+++ b/spree_multi_site/app/models/spree/image_decorator.rb
@@ -1,30 +1,46 @@
Spree::Image.class_eval do
-#override attachement[:path]
- Spree::Image.attachment_definitions[:attachment][:url] = '/shops/:rails_env/:site/products/:id/:basename_:style.:extension'
- Spree::Image.attachment_definitions[:attachment][:path] = ':rails_root/public/shops/:rails_env/:site/products/:id/:basename_:style.:extension'
+ #override attachement[:path]
+ attachment_definitions[:attachment][:url] = '/shops/:rails_env/:site/products/:id/:basename_:style.:extension'
+ attachment_definitions[:attachment][:path] = ':rails_root/public/shops/:rails_env/:site/products/:id/:basename_:style.:extension'
+ attachment_definitions[:attachment][:styles] = { mini: '48x48>', small: '100x100>', product: '240x240>', medium: '350x350>', large: '600x600>' }
- Spree::Image.attachment_definitions[:attachment][:styles] = { mini: '48x48>', small: '100x100>', product: '240x240>', medium: '350x350>', large: '600x600>' }
+ extend SpreeMultiSite::PaperclipAliyunOssHelper
end
Spree::Taxon.class_eval do
- #override attachement[:path]
+ #override attachement[:path]
attachment_definitions[:icon][:url] = '/shops/:rails_env/:site/taxons/:id/:style/:basename.:extension'
attachment_definitions[:icon][:path] = ':rails_root/public/shops/:rails_env/:site/taxons/:id/:style/:basename.:extension'
+
+ extend SpreeMultiSite::PaperclipAliyunOssHelper
end
#Spree::Post.class_eval do
-# #override attachement[:path]
-# attachment_definitions[:cover][:url] = '/shops/:rails_env/:site/posts/:id/:style/:basename.:extension'
-# attachment_definitions[:cover][:path] = ':rails_root/public/shops/:rails_env/:site/posts/:id/:style/:basename.:extension'
+# #override attachement[:path]
+# attachment_definitions[:cover][:url] = '/shops/:rails_env/:site/posts/:id/:basename_:style.:extension'
+# attachment_definitions[:cover][:path] = ':rails_root/public/shops/:rails_env/:site/posts/:id/:basename_:style.:extension'
+# extend SpreeMultiSite::PaperclipAliyunOssHelper
#end
-Rails.application.config.spree_multi_site.site_scope_required_classes_with_image_from_other_gems.each do |attachement_name_symbol, extra_class|
- extra_class.class_eval do
- include Spree::MultiSiteSystem
- # Spree::Post => 'posts'
- attachment_definitions[attachement_name_symbol][:url] = "/shops/:rails_env/:site/#{extra_class.to_s.demodulize.underscore.pluralize}/:id/:style/:basename.:extension"
- attachment_definitions[attachement_name_symbol][:path] = ':rails_root/public/shops/:rails_env/:site/#{extra_class.to_s.demodulize.underscore.pluralize}/:id/:style/:basename.:extension'
+#Spree::TemplateFile.class_eval do
+# attachment_definitions[:attachment][:url] = "/shops/:rails_env/:site/:class/:id/:basename_:style.:extension"
+# attachment_definitions[:attachment][:path] = ":rails_root/public/shops/:rails_env/:site/:class/:id/:basename_:style.:extension"
+# extend SpreeMultiSite::PaperclipAliyunOssHelper
+#end
- end
+# these class do not define in spree and spree_multi_site, we should specify in
+# site_scope_required_classes_with_image_from_other_gems, or cause error uninitialized constant
+# eventhough spree_multi_site is in spree_abc, tests in spree_multi_site would not work.
+# [['Spree::Post',:cover],['Spree::TemplateFile',:attachment]]
+Rails.application.config.spree_multi_site.site_scope_required_classes_with_image_from_other_gems.each do | klass, attachement_name_symbol|
+# extra_class.class_eval do
+# include Spree::MultiSiteSystem
+# end
+ klass.constantize.class_eval do
+ # Spree::Post => 'posts' class.to_s.demodulize.underscore.pluralize
+ attachment_definitions[attachement_name_symbol][:url] = "/shops/:rails_env/:site/:class/:id/:basename_:style.:extension"
+ attachment_definitions[attachement_name_symbol][:path] = ':rails_root/public/shops/:rails_env/:site/:class/:id/:basename_:style.:extension'
+ extend SpreeMultiSite::PaperclipAliyunOssHelper
+ end
end
diff --git a/spree_multi_site/app/models/spree/multi_site_configuration.rb b/spree_multi_site/app/models/spree/multi_site_configuration.rb
index dd2cac21..524d2ac0 100644
--- a/spree_multi_site/app/models/spree/multi_site_configuration.rb
+++ b/spree_multi_site/app/models/spree/multi_site_configuration.rb
@@ -1,10 +1,4 @@
-# I have to create own configuration class,
-# because that app_configuration_decorator is loaded after initialize,
-# so in config/initializers/spree.rb, could not get seed_dir
-# this new class would work
module Spree
class MultiSiteConfiguration < Preferences::Configuration
- #description start with global means it is for whole application, not just one site
- preference :seed_dir, :string, :default => File.join(SpreeMultiSite::Engine.root,'db')
end
end
diff --git a/spree_multi_site/app/models/spree/site.rb b/spree_multi_site/app/models/spree/site.rb
index 6ba7c129..3653212b 100644
--- a/spree_multi_site/app/models/spree/site.rb
+++ b/spree_multi_site/app/models/spree/site.rb
@@ -1,13 +1,14 @@
#encoding: utf-8
class Spree::Site < ActiveRecord::Base
- cattr_accessor :unknown,:subdomain_regexp, :loading_fake_order_with_sample
+ cattr_accessor :subdomain_regexp
+
has_many :taxonomies,:inverse_of =>:site,:dependent=>:destroy
has_many :products,:inverse_of =>:site,:dependent=>:destroy
has_many :orders,:inverse_of =>:site,:dependent=>:destroy
- has_many :users,:dependent=>:destroy, :class_name=>"Spree::User" #Spree.user_class.to_s
- #FIXME,:inverse_of =>:site, it cause uninitialized constant Spree::Site::,
+ has_many :users,:dependent=>:destroy, :class_name=>Spree.user_class.to_s
+ #FIXME,:inverse_of =>:site, it cause uninitialized constant Spree::Site::,
has_many :tax_categories,:inverse_of =>:site,:dependent=>:destroy
-
+
has_many :shipping_categories,:dependent=>:destroy
has_many :shipping_methods,:dependent=>:destroy
has_many :prototypes,:dependent=>:destroy
@@ -16,62 +17,70 @@ class Spree::Site < ActiveRecord::Base
has_many :payment_methods,:dependent=>:destroy
has_many :assets,:dependent=>:destroy
has_many :zones,:dependent=>:destroy
- has_many :state_changes,:dependent=>:destroy
+ has_many :state_changes,:dependent=>:destroy
+
+ has_many :stores, :dependent=>:destroy
#acts_as_nested_set
+ accepts_nested_attributes_for :stores
accepts_nested_attributes_for :users
-
- #app_configuration require site_id
- self.unknown = Struct.new(:id).new(0)
+
# it is load before create site table. self.new would trigger error "Table spree_sites' doesn't exist"
# db/migrate/some_migration is using Spree::Product, it has default_scope using Site.current.id
# so it require a default value.
self.subdomain_regexp = /\A([a-z0-9\-])*\Z/
- self.loading_fake_order_with_sample = false
+
+ #these attr is only used when create site, it is unavailabe in other case.
+ attr_accessor :email, :password, :password_confirmation
+
validates :name, length: 4..32 #"中国".length=> 2
validates :short_name, uniqueness: true, presence: true, length: 4..32, format: {with: subdomain_regexp} #, unless: "domain.blank?"
- validates_uniqueness_of :domain, :allow_blank=>true
+ validates_uniqueness_of :domain, :allow_blank=>true
#attr_accessible :name, :domain, :short_name, :has_sample
#generate short name fro name
before_validation :set_short_name
-
+ after_create :add_default_data
+
class << self
def dalianshops
#in development, we may change site domain
- find_by_short_name('first')#find_by_domain
+ find_by_short_name('www')#find_by_domain
end
-
+
def current
- ::Thread.current[:spree_site] || self.unknown
+ Spree::Store.current.site
end
-
+
def current=(some_site)
- ::Thread.current[:spree_site] = some_site
+ if some_site # durring test, add_default_data cause some_site nil
+ Spree::Store.current = Spree::Store.unscoped.where( site_id: some_site.id ).first
+ end
+ some_site
end
-
+
# execute block with given site
def with_site(new_site)
original_current = self.current
begin
self.current = new_site
- yield
+ yield( new_site )
ensure
- self.current = original_current
+ self.current = original_current
end
end
+
+ def system_top_domain
+ Rails.application.config.spree_multi_site.system_top_domain
+ end
end
-
+
def dalianshops?
- self == self.class.dalianshops
+ self == self.class.dalianshops
end
-
+
def current?
self == self.class.current
end
-
- def unknown?
- !(self.id>0)
- end
-
+
def load_sample( )
require 'ffaker'
# global tables
@@ -85,7 +94,7 @@ def load_sample( )
# [properties(site), prototypes(site)] -> properties_prototypes
# , option_types(site)] ->option_type_prototypes
# ->products(site)->variants(site?)->assets(site)
- # payment_methods(site)->payments->adjustments
+ # payment_methods(site)->payments->adjustments
# ->payment_capture_events
# ->alipay_transactions( source )
# preference(site)
@@ -95,36 +104,36 @@ def load_sample( )
# to be confirm
# spree_tracker, state_changes
# return_authorizations
- # mail_methods,
+ # mail_methods,
# friendly_id_slugs
# promotion_categories -> promotions -> promotion_rules
- # -> promotion_actions
- # product_promotion_rules, taxons_promotion_rules,
- #
+ # -> promotion_actions
+ # product_promotion_rules, taxons_promotion_rules,
+ #
# stores
#:spree_refunds
#:spree_return_authorization_inventory_units
#:spree_return_authorizations
#:spree_refund_reasons
#:spree_customer_returns
-
+
#:spree_reimbursements
#:spree_reimbursement_types
#:spree_reimbursement_credits
#:spree_taxons_prototypes
-
+
# unused table
# credit_cards(site?), gateways(site?)
#
raise "exists products" if self.products.any?
- self.class.with_site( self ) do
- load_sample_products
+ self.class.with_site( self ) do
+ load_sample_products
end
self
end
-
+
def unload_sample
- self.class.with_site( self ) do
+ self.class.with_site( self ) do
self.orders.each{|order|
order.state_changes.clear
order.inventory_units.clear
@@ -145,12 +154,12 @@ def unload_sample
taxonomy.root.destroy # remove taxons
taxonomy.destroy
}
-
+
self.zones.each{|zone|
zone.destroy
}
self.shipping_methods.clear
-
+
#TODO fix taxons.taconomy_id
self.users.includes(:ship_address,:bill_address).offset(1).each{|user|
user.bill_address.destroy
@@ -160,39 +169,48 @@ def unload_sample
#shipping_method, calculator, creditcard, inventory_units, state_change,tokenized_permission
#TODO remove image files
self.assets.clear
- #FIXME seems it do not work
- self.clear_preferences #remove preferences
#TODO clear those tables
# creditcarts,preferences
- self.state_changes.clear
+ self.state_changes.clear
end
self
end
-
+
# current site'subdomain => short_name.dalianshops.com
def subdomain
- return self.domain if dalianshops? #fix: first.dalianshops.com
- ([self.short_name] + self.class.dalianshops.domain.split('.')[1..-1]).join('.')
+ short_name + '.' + self.class.system_top_domain
end
-
+
def admin_url
"http://"+subdomain+"/admin"
end
-
+
private
+
+ def add_default_data
+ #current site is first, self is another.
+ self.class.with_site( self ) do| site |
+ site.stores.create!( name: site.name, code: site.short_name )
+ user_attributes = { email: site.email, password: site.password, password_confirmation: password_confirmation }
+ user = site.users.create!(user_attributes)
+ user.spree_roles << Spree::Role.find_by_name('admin')
+ site.shipping_categories.create!( name: Spree.t(:default) )
+ end
+ end
+
def load_sample_products
- file = Pathname.new(File.join(SpreeMultiSite::Config.seed_dir, 'samples', "seed.rb"))
+ file = File.join( Rails.application.root, 'db', 'samples', "seed.rb")
load file
end
-
+
def load_sample_orders
- file = Pathname.new(File.join(SpreeMultiSite::Config.seed_dir, 'fake_order', "seed.rb"))
+ file = File.join( Rails.application.root, 'db', 'fake_order', "seed.rb")
load file
end
-
+
def set_short_name
if short_name.blank?
- self.short_name = name.to_url
+ self.short_name = name.to_url
if self.class.exists?(:short_name=> self.short_name)
self.short_name << "-#{(self.class.last.id+1).to_s}"
end
diff --git a/spree_multi_site/app/models/spree/site_decorator.rb b/spree_multi_site/app/models/spree/site_decorator.rb
index 41a4ee28..6839890b 100644
--- a/spree_multi_site/app/models/spree/site_decorator.rb
+++ b/spree_multi_site/app/models/spree/site_decorator.rb
@@ -3,19 +3,24 @@
Spree::Asset.class_eval do
include Spree::MultiSiteSystem
end
+
Spree::Configuration.class_eval do
belongs_to :site
default_scope { where(:site_id => Spree::Site.current.id) }
-end
+end
Spree::LogEntry.class_eval do
belongs_to :site
default_scope { where(:site_id => Spree::Site.current.id) }
-end
+end
Spree::OptionType.class_eval do
belongs_to :site
default_scope { where(:site_id => Spree::Site.current.id) }
-end
+ clear_validators!
+ # Add new validates_uniqueness_of with correct scope
+ validates :name, :uniqueness => { :scope => [:site_id] }
+
+end
Spree::Order.class_eval do
include Spree::MultiSiteSystem
@@ -23,34 +28,37 @@
# we should never call LineItem.find or LineItem.new
# use @order.line_items, @order.add_variant instead
-Spree::LineItem.class_eval do
- #this cause ActiveRecord::ReadOnlyRecord, while modify lineitem
- #default_scope :joins => :order
- #default_scope {where("spree_orders.site_id=?", Spree::Site.current.id)}
-end
Spree::Prototype.class_eval do
belongs_to :site
default_scope { where(:site_id => Spree::Site.current.id) }
-end
+end
Spree::Preference.class_eval do
- belongs_to :site
- default_scope { where(:site_id => Spree::Site.current.id) }
-end
+ include Spree::MultiSiteSystem
+end
Spree::PaymentMethod.class_eval do
- belongs_to :site
- default_scope { where(:site_id => Spree::Site.current.id) }
-end
+ include Spree::MultiSiteSystem
+end
Spree::Product.class_eval do
include Spree::MultiSiteSystem
include Spree::ProductExtraScope
-
+
has_many :global_classifications, dependent: :delete_all
has_many :global_taxons, through: :global_classifications, source: :taxon
+
+ # Try building a slug based on the following fields in increasing order of specificity.
+ def slug_candidates
+ [
+ :name,
+ [:name, :sku],
+ [:name, :sku, :site_id]
+ ]
+ end
+
end
Spree::Property.class_eval do
@@ -61,18 +69,16 @@
#TODO add site_id into shipments?
Spree::ShippingCategory.class_eval do
- belongs_to :site
- default_scope { where(:site_id => Spree::Site.current.id) }
+ include Spree::MultiSiteSystem
end
Spree::ShippingMethod.class_eval do
- belongs_to :site
- default_scope { where(:site_id => Spree::Site.current.id) }
+ include Spree::MultiSiteSystem
end
+
Spree::Taxonomy.class_eval do
- belongs_to :site
- default_scope { where(:site_id => Spree::Site.current.id) }
+ include Spree::MultiSiteSystem
end
@@ -81,24 +87,24 @@
has_many :global_classifications, dependent: :delete_all
has_many :global_products, through: :global_classifications, source: :product
-
+
end
Spree::TaxCategory.class_eval do
-
+
belongs_to :site
default_scope { where(:site_id => Spree::Site.current.id) }
clear_validators!
# Add new validates_uniqueness_of with correct scope
- validates :name, :uniqueness => { :scope => [:site_id,:deleted_at] }
+ validates :name, :uniqueness => { scope: [:site_id,:deleted_at], allow_blank: true }
end
# TaxRate is join table, include tax_catory_id and zone_id
# in TaxRate.match it called method :all, so we have to add joins=>tax_category
-# in fact, we should never use TaxRate in spree_abc for now.
+# in fact, we should never use TaxRate in spree_abc for now.
Spree::TaxRate.class_eval do
default_scope { joins( :tax_category). where("spree_tax_categories.site_id=?", Spree::Site.current.id) }
end
@@ -113,22 +119,34 @@
# 1. we required dalianshops user have unique email,
# 2. we allow user modify their password after sign up.
# fix unique with scope [site_id] would conflict with 1
- belongs_to :site
- default_scope { where(:site_id => Spree::Site.current.id) }
+ include Spree::MultiSiteSystem
+end
+
+Spree::Variant.class_eval do
+ clear_validators!
+ # copy original validates
+ #validate :check_price
+
+ validates :cost_price, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
+ validates :price, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
+ # disable uniqueness_of :sku
+ validates_uniqueness_of :sku, allow_blank: true, conditions: -> { joins(:product).where( spree_variants: { deleted_at: nil}, spree_products: {site_id: Spree::Site.current.id } ) }
+
end
Spree::Zone.class_eval do
belongs_to :site
default_scope { where(:site_id => Spree::Site.current.id) }
-
+
clear_validators!
# Add new validates_uniqueness_of with correct scope
validates :name, :presence => true, :uniqueness => { :scope => [:site_id] }
-end
+end
+
Rails.application.config.spree_multi_site.site_scope_required_classes_from_other_gems.each do |extra_class|
- extra_class.class_eval do
+ extra_class.constantize.class_eval do
belongs_to :site
default_scope { where(:site_id => Spree::Site.current.id) }
- end
+ end
end
diff --git a/spree_multi_site/app/models/spree/store_decorator.rb b/spree_multi_site/app/models/spree/store_decorator.rb
new file mode 100644
index 00000000..e1437409
--- /dev/null
+++ b/spree_multi_site/app/models/spree/store_decorator.rb
@@ -0,0 +1,55 @@
+Spree::Store.class_eval do
+ # Do not use default_scope, in view template_theme/foreign, we want to get store of template_theme.
+ # include Spree::MultiSiteSystem
+ belongs_to :site
+
+ clear_validators!
+
+ #override original current
+ def self.current(domain = nil)
+ #UnknownStore.instance is for test only
+ ::Thread.current[:spree_store] || UnknownStore.instance
+ end
+
+ def self.current=(some_store)
+ ::Thread.current[:spree_store] = some_store
+ end
+
+ def self.by_domain( domain )
+ current_store = if domain.is_a? String
+ if domain.end_with? Spree::Site.system_top_domain
+ short_name = domain.split('.').first
+ self.find_by_code(short_name)
+ else
+ self.by_url(domain).first
+ end
+ else
+ self.first
+ end
+ current_store
+ end
+
+ # we can not easily modify cookies except firefox, we'll add default_site for debug page on other browser.
+ # we could set default site for missing site as well.
+ def self.default
+ where( default: true ).first
+ end
+
+ # current site'subdomain => short_name.dalianshops.com
+ def subdomain
+ code + '.' + Spree::Site.system_top_domain
+ end
+
+ #app_configuration require site_id
+ class UnknownStore
+ include Singleton
+ def id
+ 0
+ end
+
+ def site
+ #app_configuration require site_id
+ Struct.new(:id).new(0)
+ end
+ end
+end
diff --git a/spree_multi_site/app/views/spree/admin/general_settings/edit.html.erb b/spree_multi_site/app/views/spree/admin/general_settings/edit.html.erb
new file mode 100644
index 00000000..9de4e0d8
--- /dev/null
+++ b/spree_multi_site/app/views/spree/admin/general_settings/edit.html.erb
@@ -0,0 +1,129 @@
+<%= render :partial => 'spree/admin/shared/configuration_menu' %>
+
+<% content_for :page_title do %>
+ <%= Spree.t(:general_settings) %>
+<% end %>
+
+<%= form_tag admin_general_settings_path, method: :put do %>
+
+
+
+
+
+
+
+<% end %>
+
+
diff --git a/spree_multi_site/app/views/spree/admin/sites/index.html.erb b/spree_multi_site/app/views/spree/admin/sites/index.html.erb
index 14ac1442..dc8f2755 100644
--- a/spree_multi_site/app/views/spree/admin/sites/index.html.erb
+++ b/spree_multi_site/app/views/spree/admin/sites/index.html.erb
@@ -1,5 +1,5 @@
<% content_for :page_title do %>
- <%= Spree.t('site.index') %>
+ <%= Spree.t('site.index') %>
<% end %>
@@ -19,18 +19,17 @@
| <%= site.name %> |
<%= site.subdomain %> |
- <%= site.users.admin.first.email %> |
+
+ <%= Spree::MultiSiteSystem.with_context_admin_sites{ site.users.admin.first.email }%>
+ |
<%= pretty_time site.created_at %> |
- <%= link_to_with_icon 'icon-eye', Spree.t(:admin_store), site.admin_url, {:target=>'_blank',:no_text => true} %>
+ <%= link_to_with_icon 'eye', Spree.t(:admin_store), site.admin_url, {:target=>'_blank',:no_text => true} %>
|
<% end %>
-
-<%= paginate @sites %>
-
-
+<%= paginate @sites %>
diff --git a/spree_multi_site/app/views/spree/sites/_form.html.erb b/spree_multi_site/app/views/spree/sites/_form.html.erb
index 83b2c9d5..e6376e5d 100644
--- a/spree_multi_site/app/views/spree/sites/_form.html.erb
+++ b/spree_multi_site/app/views/spree/sites/_form.html.erb
@@ -3,25 +3,25 @@
<%= f.label :name %>
- <%= f.text_field :name, :class => 'fullwidth title', :minlength=>4, :maxlength=>30, :required=>"" %>
+ <%= f.text_field :name, :minlength=>4, :maxlength=>30, :required=>"" %>
-
- <%= f.label :short_name %>
- <%= f.text_field :short_name, :class => 'fullwidth title', :minlength=>4, :maxlength=>30, :required=>"" %>
- .dalianshops.com
-
-
- <% if @site.new_record? %>
- <%= render :partial => 'spree/sites/user', :locals => { :user => @user } %>
- <% end %>
+
+ <%= f.label :email, Spree.t(:email) %>
+ <%= f.email_field :email %>
+
+
+
+ <%= f.label :password, Spree.t(:password) %>
+ <%= f.password_field :password, :minlength=>6, :maxlength=>30, :required=>"" %>
+
<% if @template_theme.present? %>
<%= f.label :foreign_theme_id %>
- <%= f.hidden_field :foreign_theme_id, :value=>@template_theme.id %>
- <%= text_field_tag :template_theme_name, @template_theme.title, :class => 'fullwidth title', :readonly=>true, :size=>30 %>
-
+ <%= f.hidden_field :foreign_theme_id, :value=>@template_theme.id %>
+ <%= text_field_tag :template_theme_name, @template_theme.title, :readonly=>true, :size=>30 %>
+
<% end %>
diff --git a/spree_multi_site/app/views/spree/sites/_form_for_spree_theme.html.erb b/spree_multi_site/app/views/spree/sites/_form_for_spree_theme.html.erb
deleted file mode 100644
index 2b164f0d..00000000
--- a/spree_multi_site/app/views/spree/sites/_form_for_spree_theme.html.erb
+++ /dev/null
@@ -1,37 +0,0 @@
-<%
- @site ||= SpreeTheme.site_class.new
- @user ||= @site.users.build
-%>
-<%= form_for :site, :url => quick_lunch_path, :html=>{:id=>"site_form"} do |f| %>
-
-
- <%= f.text_field :name, :class => 'fullwidth title', :placeholder => Spree.t(:name_store), :minlength=>4, :maxlength=>24, :required=>"" %>
-
-
- <%= email_field :user, :email, :placeholder => Spree.t(:email)%>
-
-
- <%= password_field :user,:password, :placeholder=>Spree.t(:password), :minlength=>6, :maxlength=>24, :required=>"" %>
-
- <%= f.button Spree.t(:new_site), :class => 'button primary' %>
-
-<% end %>
-
diff --git a/spree_multi_site/app/views/spree/sites/after_new.html.erb b/spree_multi_site/app/views/spree/sites/after_new.html.erb
index 68adf890..06d56629 100644
--- a/spree_multi_site/app/views/spree/sites/after_new.html.erb
+++ b/spree_multi_site/app/views/spree/sites/after_new.html.erb
@@ -1,6 +1,6 @@
<%= t 'successfully_created',:resource=> "#{t('site')}:#{@site.name} "%>
-网站地址 <%=link_to @site.subdomain, :host=>@site.subdomain,:controller=>"home"%>
+网站地址 <%=link_to @site.subdomain, :host=>@site.subdomain %>
管理地址 <%=link_to @site.subdomain+'/admin', 'http://'+@site.subdomain+'/admin' %>
<% if @site.loading_sample? %>
<%= t :loading_sample %>
diff --git a/spree_multi_site/app/views/spree/sites/new.html.erb b/spree_multi_site/app/views/spree/sites/new.html.erb
index 02fd1cec..07bffd71 100644
--- a/spree_multi_site/app/views/spree/sites/new.html.erb
+++ b/spree_multi_site/app/views/spree/sites/new.html.erb
@@ -1,7 +1,7 @@
<%= render :partial => 'spree/shared/error_messages', :locals => { :target => @site } %>
<%= t(:new_site) %>
-<%= form_for :site, :url => new_site_path do |f| %>
+<%= form_for @site, :url => create_site_path do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<%= f.submit Spree.t(:create), :class => 'button primary' %>
<% end %>
diff --git a/spree_multi_site/config/locales/zh-CN.yml b/spree_multi_site/config/locales/zh-CN.yml
index 34df2ca1..b177aaf1 100644
--- a/spree_multi_site/config/locales/zh-CN.yml
+++ b/spree_multi_site/config/locales/zh-CN.yml
@@ -17,6 +17,10 @@ zh-CN:
domain: 网店域名
created_at: 创建时间
foreign_theme_id: 模板
+ spree/site/users:
+ email: 电子邮箱
+ password: 密码
+ password_confirmation: 密码
spree:
admin_store: 管理商店
errors:
diff --git a/spree_multi_site/config/routes.rb b/spree_multi_site/config/routes.rb
index ee7f3074..671e5a17 100644
--- a/spree_multi_site/config/routes.rb
+++ b/spree_multi_site/config/routes.rb
@@ -3,12 +3,18 @@
namespace :admin do
resources :sites
end
- post '/quick_lunch',:to => 'sites#quick_lunch', :as => :quick_lunch
+ # one click get form to trial
+ get 'one_click_trial' => 'sites#one_click_trial', :as => :one_click_trial
+
+ # bottom signup form
+ post 'quick_lunch',:to => 'sites#quick_lunch', :as => :quick_lunch
+
+ # create site with template_theme
get 'new_site' => 'sites#new', :as => :new_site
post 'create_site' => 'sites#create', :as => :create_site
resources :sites, :only => [:show]
- if Rails.env.development?
- mount Spree::UserMailer::Preview => 'mail_view'
- end
+ #if Rails.env.development?
+ # mount Spree::UserMailer::Preview => 'mail_view'
+ #end
end
diff --git a/spree_multi_site/db/default/spree/countries.rb b/spree_multi_site/db/default/spree/countries.rb
index 32483fac..da6c4ba1 100644
--- a/spree_multi_site/db/default/spree/countries.rb
+++ b/spree_multi_site/db/default/spree/countries.rb
@@ -1,229 +1,229 @@
-Spree::Country.create!({"name"=>"Chad", "iso3"=>"TCD", "iso"=>"TD", "iso_name"=>"CHAD", "numcode"=>"148"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Faroe Islands", "iso3"=>"FRO", "iso"=>"FO", "iso_name"=>"FAROE ISLANDS", "numcode"=>"234"}, :without_protection => true)
-Spree::Country.create!({"name"=>"India", "iso3"=>"IND", "iso"=>"IN", "iso_name"=>"INDIA", "numcode"=>"356"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Nicaragua", "iso3"=>"NIC", "iso"=>"NI", "iso_name"=>"NICARAGUA", "numcode"=>"558"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Saint Lucia", "iso3"=>"LCA", "iso"=>"LC", "iso_name"=>"SAINT LUCIA", "numcode"=>"662"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Fiji", "iso3"=>"FJI", "iso"=>"FJ", "iso_name"=>"FIJI", "numcode"=>"242"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Indonesia", "iso3"=>"IDN", "iso"=>"ID", "iso_name"=>"INDONESIA", "numcode"=>"360"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Niger", "iso3"=>"NER", "iso"=>"NE", "iso_name"=>"NIGER", "numcode"=>"562"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Saint Pierre and Miquelon", "iso3"=>"SPM", "iso"=>"PM", "iso_name"=>"SAINT PIERRE AND MIQUELON", "numcode"=>"666"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Finland", "iso3"=>"FIN", "iso"=>"FI", "iso_name"=>"FINLAND", "numcode"=>"246"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Nigeria", "iso3"=>"NGA", "iso"=>"NG", "iso_name"=>"NIGERIA", "numcode"=>"566"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Saint Vincent and the Grenadines", "iso3"=>"VCT", "iso"=>"VC", "iso_name"=>"SAINT VINCENT AND THE GRENADINES", "numcode"=>"670"}, :without_protection => true)
-Spree::Country.create!({"name"=>"France", "iso3"=>"FRA", "iso"=>"FR", "iso_name"=>"FRANCE", "numcode"=>"250"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Iran, Islamic Republic of", "iso3"=>"IRN", "iso"=>"IR", "iso_name"=>"IRAN, ISLAMIC REPUBLIC OF", "numcode"=>"364"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Niue", "iso3"=>"NIU", "iso"=>"NU", "iso_name"=>"NIUE", "numcode"=>"570"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Samoa", "iso3"=>"WSM", "iso"=>"WS", "iso_name"=>"SAMOA", "numcode"=>"882"}, :without_protection => true)
-Spree::Country.create!({"name"=>"French Guiana", "iso3"=>"GUF", "iso"=>"GF", "iso_name"=>"FRENCH GUIANA", "numcode"=>"254"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Iraq", "iso3"=>"IRQ", "iso"=>"IQ", "iso_name"=>"IRAQ", "numcode"=>"368"}, :without_protection => true)
-Spree::Country.create!({"name"=>"San Marino", "iso3"=>"SMR", "iso"=>"SM", "iso_name"=>"SAN MARINO", "numcode"=>"674"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Ireland", "iso3"=>"IRL", "iso"=>"IE", "iso_name"=>"IRELAND", "numcode"=>"372"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Sao Tome and Principe", "iso3"=>"STP", "iso"=>"ST", "iso_name"=>"SAO TOME AND PRINCIPE", "numcode"=>"678"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Israel", "iso3"=>"ISR", "iso"=>"IL", "iso_name"=>"ISRAEL", "numcode"=>"376"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Saudi Arabia", "iso3"=>"SAU", "iso"=>"SA", "iso_name"=>"SAUDI ARABIA", "numcode"=>"682"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Italy", "iso3"=>"ITA", "iso"=>"IT", "iso_name"=>"ITALY", "numcode"=>"380"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Senegal", "iso3"=>"SEN", "iso"=>"SN", "iso_name"=>"SENEGAL", "numcode"=>"686"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Jamaica", "iso3"=>"JAM", "iso"=>"JM", "iso_name"=>"JAMAICA", "numcode"=>"388"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Japan", "iso3"=>"JPN", "iso"=>"JP", "iso_name"=>"JAPAN", "numcode"=>"392"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Jordan", "iso3"=>"JOR", "iso"=>"JO", "iso_name"=>"JORDAN", "numcode"=>"400"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Belgium", "iso3"=>"BEL", "iso"=>"BE", "iso_name"=>"BELGIUM", "numcode"=>"56"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Belize", "iso3"=>"BLZ", "iso"=>"BZ", "iso_name"=>"BELIZE", "numcode"=>"84"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Kazakhstan", "iso3"=>"KAZ", "iso"=>"KZ", "iso_name"=>"KAZAKHSTAN", "numcode"=>"398"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Uganda", "iso3"=>"UGA", "iso"=>"UG", "iso_name"=>"UGANDA", "numcode"=>"800"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Benin", "iso3"=>"BEN", "iso"=>"BJ", "iso_name"=>"BENIN", "numcode"=>"204"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Kenya", "iso3"=>"KEN", "iso"=>"KE", "iso_name"=>"KENYA", "numcode"=>"404"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Ukraine", "iso3"=>"UKR", "iso"=>"UA", "iso_name"=>"UKRAINE", "numcode"=>"804"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Bermuda", "iso3"=>"BMU", "iso"=>"BM", "iso_name"=>"BERMUDA", "numcode"=>"60"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Kiribati", "iso3"=>"KIR", "iso"=>"KI", "iso_name"=>"KIRIBATI", "numcode"=>"296"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Mexico", "iso3"=>"MEX", "iso"=>"MX", "iso_name"=>"MEXICO", "numcode"=>"484"}, :without_protection => true)
-Spree::Country.create!({"name"=>"United Arab Emirates", "iso3"=>"ARE", "iso"=>"AE", "iso_name"=>"UNITED ARAB EMIRATES", "numcode"=>"784"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Bhutan", "iso3"=>"BTN", "iso"=>"BT", "iso_name"=>"BHUTAN", "numcode"=>"64"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Cuba", "iso3"=>"CUB", "iso"=>"CU", "iso_name"=>"CUBA", "numcode"=>"192"}, :without_protection => true)
-Spree::Country.create!({"name"=>"North Korea", "iso3"=>"PRK", "iso"=>"KP", "iso_name"=>"KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF", "numcode"=>"408"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Micronesia, Federated States of", "iso3"=>"FSM", "iso"=>"FM", "iso_name"=>"MICRONESIA, FEDERATED STATES OF", "numcode"=>"583"}, :without_protection => true)
-Spree::Country.create!({"name"=>"United Kingdom", "iso3"=>"GBR", "iso"=>"GB", "iso_name"=>"UNITED KINGDOM", "numcode"=>"826"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Bolivia", "iso3"=>"BOL", "iso"=>"BO", "iso_name"=>"BOLIVIA", "numcode"=>"68"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Cyprus", "iso3"=>"CYP", "iso"=>"CY", "iso_name"=>"CYPRUS", "numcode"=>"196"}, :without_protection => true)
-Spree::Country.create!({"name"=>"South Korea", "iso3"=>"KOR", "iso"=>"KR", "iso_name"=>"KOREA, REPUBLIC OF", "numcode"=>"410"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Moldova, Republic of", "iso3"=>"MDA", "iso"=>"MD", "iso_name"=>"MOLDOVA, REPUBLIC OF", "numcode"=>"498"}, :without_protection => true)
-Spree::Country.create!({"name"=>"United States", "iso3"=>"USA", "iso"=>"US", "iso_name"=>"UNITED STATES", "numcode"=>"840"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Bosnia and Herzegovina", "iso3"=>"BIH", "iso"=>"BA", "iso_name"=>"BOSNIA AND HERZEGOVINA", "numcode"=>"70"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Czech Republic", "iso3"=>"CZE", "iso"=>"CZ", "iso_name"=>"CZECH REPUBLIC", "numcode"=>"203"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Kuwait", "iso3"=>"KWT", "iso"=>"KW", "iso_name"=>"KUWAIT", "numcode"=>"414"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Monaco", "iso3"=>"MCO", "iso"=>"MC", "iso_name"=>"MONACO", "numcode"=>"492"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Uruguay", "iso3"=>"URY", "iso"=>"UY", "iso_name"=>"URUGUAY", "numcode"=>"858"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Botswana", "iso3"=>"BWA", "iso"=>"BW", "iso_name"=>"BOTSWANA", "numcode"=>"72"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Denmark", "iso3"=>"DNK", "iso"=>"DK", "iso_name"=>"DENMARK", "numcode"=>"208"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Guadeloupe", "iso3"=>"GLP", "iso"=>"GP", "iso_name"=>"GUADELOUPE", "numcode"=>"312"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Kyrgyzstan", "iso3"=>"KGZ", "iso"=>"KG", "iso_name"=>"KYRGYZSTAN", "numcode"=>"417"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Mongolia", "iso3"=>"MNG", "iso"=>"MN", "iso_name"=>"MONGOLIA", "numcode"=>"496"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Philippines", "iso3"=>"PHL", "iso"=>"PH", "iso_name"=>"PHILIPPINES", "numcode"=>"608"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Brazil", "iso3"=>"BRA", "iso"=>"BR", "iso_name"=>"BRAZIL", "numcode"=>"76"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Djibouti", "iso3"=>"DJI", "iso"=>"DJ", "iso_name"=>"DJIBOUTI", "numcode"=>"262"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Guam", "iso3"=>"GUM", "iso"=>"GU", "iso_name"=>"GUAM", "numcode"=>"316"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Lao People's Democratic Republic", "iso3"=>"LAO", "iso"=>"LA", "iso_name"=>"LAO PEOPLE'S DEMOCRATIC REPUBLIC", "numcode"=>"418"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Montserrat", "iso3"=>"MSR", "iso"=>"MS", "iso_name"=>"MONTSERRAT", "numcode"=>"500"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Pitcairn", "iso3"=>"PCN", "iso"=>"PN", "iso_name"=>"PITCAIRN", "numcode"=>"612"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Uzbekistan", "iso3"=>"UZB", "iso"=>"UZ", "iso_name"=>"UZBEKISTAN", "numcode"=>"860"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Brunei Darussalam", "iso3"=>"BRN", "iso"=>"BN", "iso_name"=>"BRUNEI DARUSSALAM", "numcode"=>"96"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Dominica", "iso3"=>"DMA", "iso"=>"DM", "iso_name"=>"DOMINICA", "numcode"=>"212"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Guatemala", "iso3"=>"GTM", "iso"=>"GT", "iso_name"=>"GUATEMALA", "numcode"=>"320"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Morocco", "iso3"=>"MAR", "iso"=>"MA", "iso_name"=>"MOROCCO", "numcode"=>"504"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Poland", "iso3"=>"POL", "iso"=>"PL", "iso_name"=>"POLAND", "numcode"=>"616"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Vanuatu", "iso3"=>"VUT", "iso"=>"VU", "iso_name"=>"VANUATU", "numcode"=>"548"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Dominican Republic", "iso3"=>"DOM", "iso"=>"DO", "iso_name"=>"DOMINICAN REPUBLIC", "numcode"=>"214"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Mozambique", "iso3"=>"MOZ", "iso"=>"MZ", "iso_name"=>"MOZAMBIQUE", "numcode"=>"508"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Portugal", "iso3"=>"PRT", "iso"=>"PT", "iso_name"=>"PORTUGAL", "numcode"=>"620"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Sudan", "iso3"=>"SDN", "iso"=>"SD", "iso_name"=>"SUDAN", "numcode"=>"736"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Venezuela", "iso3"=>"VEN", "iso"=>"VE", "iso_name"=>"VENEZUELA", "numcode"=>"862"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Ecuador", "iso3"=>"ECU", "iso"=>"EC", "iso_name"=>"ECUADOR", "numcode"=>"218"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Guinea", "iso3"=>"GIN", "iso"=>"GN", "iso_name"=>"GUINEA", "numcode"=>"324"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Myanmar", "iso3"=>"MMR", "iso"=>"MM", "iso_name"=>"MYANMAR", "numcode"=>"104"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Puerto Rico", "iso3"=>"PRI", "iso"=>"PR", "iso_name"=>"PUERTO RICO", "numcode"=>"630"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Suriname", "iso3"=>"SUR", "iso"=>"SR", "iso_name"=>"SURINAME", "numcode"=>"740"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Viet Nam", "iso3"=>"VNM", "iso"=>"VN", "iso_name"=>"VIET NAM", "numcode"=>"704"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Egypt", "iso3"=>"EGY", "iso"=>"EG", "iso_name"=>"EGYPT", "numcode"=>"818"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Guinea-Bissau", "iso3"=>"GNB", "iso"=>"GW", "iso_name"=>"GUINEA-BISSAU", "numcode"=>"624"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Namibia", "iso3"=>"NAM", "iso"=>"NA", "iso_name"=>"NAMIBIA", "numcode"=>"516"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Qatar", "iso3"=>"QAT", "iso"=>"QA", "iso_name"=>"QATAR", "numcode"=>"634"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Svalbard and Jan Mayen", "iso3"=>"SJM", "iso"=>"SJ", "iso_name"=>"SVALBARD AND JAN MAYEN", "numcode"=>"744"}, :without_protection => true)
-Spree::Country.create!({"name"=>"El Salvador", "iso3"=>"SLV", "iso"=>"SV", "iso_name"=>"EL SALVADOR", "numcode"=>"222"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Guyana", "iso3"=>"GUY", "iso"=>"GY", "iso_name"=>"GUYANA", "numcode"=>"328"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Reunion", "iso3"=>"REU", "iso"=>"RE", "iso_name"=>"REUNION", "numcode"=>"638"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Haiti", "iso3"=>"HTI", "iso"=>"HT", "iso_name"=>"HAITI", "numcode"=>"332"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Romania", "iso3"=>"ROM", "iso"=>"RO", "iso_name"=>"ROMANIA", "numcode"=>"642"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Swaziland", "iso3"=>"SWZ", "iso"=>"SZ", "iso_name"=>"SWAZILAND", "numcode"=>"748"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Holy See (Vatican City State)", "iso3"=>"VAT", "iso"=>"VA", "iso_name"=>"HOLY SEE (VATICAN CITY STATE)", "numcode"=>"336"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Russian Federation", "iso3"=>"RUS", "iso"=>"RU", "iso_name"=>"RUSSIAN FEDERATION", "numcode"=>"643"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Sweden", "iso3"=>"SWE", "iso"=>"SE", "iso_name"=>"SWEDEN", "numcode"=>"752"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Honduras", "iso3"=>"HND", "iso"=>"HN", "iso_name"=>"HONDURAS", "numcode"=>"340"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Rwanda", "iso3"=>"RWA", "iso"=>"RW", "iso_name"=>"RWANDA", "numcode"=>"646"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Switzerland", "iso3"=>"CHE", "iso"=>"CH", "iso_name"=>"SWITZERLAND", "numcode"=>"756"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Hong Kong", "iso3"=>"HKG", "iso"=>"HK", "iso_name"=>"HONG KONG", "numcode"=>"344"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Syrian Arab Republic", "iso3"=>"SYR", "iso"=>"SY", "iso_name"=>"SYRIAN ARAB REPUBLIC", "numcode"=>"760"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Taiwan", "iso3"=>"TWN", "iso"=>"TW", "iso_name"=>"TAIWAN, PROVINCE OF CHINA", "numcode"=>"158"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Tajikistan", "iso3"=>"TJK", "iso"=>"TJ", "iso_name"=>"TAJIKISTAN", "numcode"=>"762"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Tanzania, United Republic of", "iso3"=>"TZA", "iso"=>"TZ", "iso_name"=>"TANZANIA, UNITED REPUBLIC OF", "numcode"=>"834"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Armenia", "iso3"=>"ARM", "iso"=>"AM", "iso_name"=>"ARMENIA", "numcode"=>"51"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Aruba", "iso3"=>"ABW", "iso"=>"AW", "iso_name"=>"ARUBA", "numcode"=>"533"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Australia", "iso3"=>"AUS", "iso"=>"AU", "iso_name"=>"AUSTRALIA", "numcode"=>"36"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Thailand", "iso3"=>"THA", "iso"=>"TH", "iso_name"=>"THAILAND", "numcode"=>"764"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Austria", "iso3"=>"AUT", "iso"=>"AT", "iso_name"=>"AUSTRIA", "numcode"=>"40"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Madagascar", "iso3"=>"MDG", "iso"=>"MG", "iso_name"=>"MADAGASCAR", "numcode"=>"450"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Togo", "iso3"=>"TGO", "iso"=>"TG", "iso_name"=>"TOGO", "numcode"=>"768"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Azerbaijan", "iso3"=>"AZE", "iso"=>"AZ", "iso_name"=>"AZERBAIJAN", "numcode"=>"31"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Chile", "iso3"=>"CHL", "iso"=>"CL", "iso_name"=>"CHILE", "numcode"=>"152"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Malawi", "iso3"=>"MWI", "iso"=>"MW", "iso_name"=>"MALAWI", "numcode"=>"454"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Tokelau", "iso3"=>"TKL", "iso"=>"TK", "iso_name"=>"TOKELAU", "numcode"=>"772"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Bahamas", "iso3"=>"BHS", "iso"=>"BS", "iso_name"=>"BAHAMAS", "numcode"=>"44"}, :without_protection => true)
-Spree::Country.create!({"name"=>"China", "iso3"=>"CHN", "iso"=>"CN", "iso_name"=>"CHINA", "numcode"=>"156"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Malaysia", "iso3"=>"MYS", "iso"=>"MY", "iso_name"=>"MALAYSIA", "numcode"=>"458"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Tonga", "iso3"=>"TON", "iso"=>"TO", "iso_name"=>"TONGA", "numcode"=>"776"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Bahrain", "iso3"=>"BHR", "iso"=>"BH", "iso_name"=>"BAHRAIN", "numcode"=>"48"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Colombia", "iso3"=>"COL", "iso"=>"CO", "iso_name"=>"COLOMBIA", "numcode"=>"170"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Maldives", "iso3"=>"MDV", "iso"=>"MV", "iso_name"=>"MALDIVES", "numcode"=>"462"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Trinidad and Tobago", "iso3"=>"TTO", "iso"=>"TT", "iso_name"=>"TRINIDAD AND TOBAGO", "numcode"=>"780"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Bangladesh", "iso3"=>"BGD", "iso"=>"BD", "iso_name"=>"BANGLADESH", "numcode"=>"50"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Comoros", "iso3"=>"COM", "iso"=>"KM", "iso_name"=>"COMOROS", "numcode"=>"174"}, :without_protection => true)
-Spree::Country.create!({"name"=>"French Polynesia", "iso3"=>"PYF", "iso"=>"PF", "iso_name"=>"FRENCH POLYNESIA", "numcode"=>"258"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Mali", "iso3"=>"MLI", "iso"=>"ML", "iso_name"=>"MALI", "numcode"=>"466"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Norfolk Island", "iso3"=>"NFK", "iso"=>"NF", "iso_name"=>"NORFOLK ISLAND", "numcode"=>"574"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Tunisia", "iso3"=>"TUN", "iso"=>"TN", "iso_name"=>"TUNISIA", "numcode"=>"788"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Barbados", "iso3"=>"BRB", "iso"=>"BB", "iso_name"=>"BARBADOS", "numcode"=>"52"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Congo", "iso3"=>"COG", "iso"=>"CG", "iso_name"=>"CONGO", "numcode"=>"178"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Gabon", "iso3"=>"GAB", "iso"=>"GA", "iso_name"=>"GABON", "numcode"=>"266"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Malta", "iso3"=>"MLT", "iso"=>"MT", "iso_name"=>"MALTA", "numcode"=>"470"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Northern Mariana Islands", "iso3"=>"MNP", "iso"=>"MP", "iso_name"=>"NORTHERN MARIANA ISLANDS", "numcode"=>"580"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Turkey", "iso3"=>"TUR", "iso"=>"TR", "iso_name"=>"TURKEY", "numcode"=>"792"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Congo, the Democratic Republic of the", "iso3"=>"COD", "iso"=>"CD", "iso_name"=>"CONGO, THE DEMOCRATIC REPUBLIC OF THE", "numcode"=>"180"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Marshall Islands", "iso3"=>"MHL", "iso"=>"MH", "iso_name"=>"MARSHALL ISLANDS", "numcode"=>"584"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Norway", "iso3"=>"NOR", "iso"=>"NO", "iso_name"=>"NORWAY", "numcode"=>"578"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Turkmenistan", "iso3"=>"TKM", "iso"=>"TM", "iso_name"=>"TURKMENISTAN", "numcode"=>"795"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Belarus", "iso3"=>"BLR", "iso"=>"BY", "iso_name"=>"BELARUS", "numcode"=>"112"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Cook Islands", "iso3"=>"COK", "iso"=>"CK", "iso_name"=>"COOK ISLANDS", "numcode"=>"184"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Gambia", "iso3"=>"GMB", "iso"=>"GM", "iso_name"=>"GAMBIA", "numcode"=>"270"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Martinique", "iso3"=>"MTQ", "iso"=>"MQ", "iso_name"=>"MARTINIQUE", "numcode"=>"474"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Oman", "iso3"=>"OMN", "iso"=>"OM", "iso_name"=>"OMAN", "numcode"=>"512"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Seychelles", "iso3"=>"SYC", "iso"=>"SC", "iso_name"=>"SEYCHELLES", "numcode"=>"690"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Turks and Caicos Islands", "iso3"=>"TCA", "iso"=>"TC", "iso_name"=>"TURKS AND CAICOS ISLANDS", "numcode"=>"796"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Georgia", "iso3"=>"GEO", "iso"=>"GE", "iso_name"=>"GEORGIA", "numcode"=>"268"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Mauritania", "iso3"=>"MRT", "iso"=>"MR", "iso_name"=>"MAURITANIA", "numcode"=>"478"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Pakistan", "iso3"=>"PAK", "iso"=>"PK", "iso_name"=>"PAKISTAN", "numcode"=>"586"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Sierra Leone", "iso3"=>"SLE", "iso"=>"SL", "iso_name"=>"SIERRA LEONE", "numcode"=>"694"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Tuvalu", "iso3"=>"TUV", "iso"=>"TV", "iso_name"=>"TUVALU", "numcode"=>"798"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Costa Rica", "iso3"=>"CRI", "iso"=>"CR", "iso_name"=>"COSTA RICA", "numcode"=>"188"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Germany", "iso3"=>"DEU", "iso"=>"DE", "iso_name"=>"GERMANY", "numcode"=>"276"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Mauritius", "iso3"=>"MUS", "iso"=>"MU", "iso_name"=>"MAURITIUS", "numcode"=>"480"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Palau", "iso3"=>"PLW", "iso"=>"PW", "iso_name"=>"PALAU", "numcode"=>"585"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Cote D'Ivoire", "iso3"=>"CIV", "iso"=>"CI", "iso_name"=>"COTE D'IVOIRE", "numcode"=>"384"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Panama", "iso3"=>"PAN", "iso"=>"PA", "iso_name"=>"PANAMA", "numcode"=>"591"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Singapore", "iso3"=>"SGP", "iso"=>"SG", "iso_name"=>"SINGAPORE", "numcode"=>"702"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Croatia", "iso3"=>"HRV", "iso"=>"HR", "iso_name"=>"CROATIA", "numcode"=>"191"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Ghana", "iso3"=>"GHA", "iso"=>"GH", "iso_name"=>"GHANA", "numcode"=>"288"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Papua New Guinea", "iso3"=>"PNG", "iso"=>"PG", "iso_name"=>"PAPUA NEW GUINEA", "numcode"=>"598"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Slovakia", "iso3"=>"SVK", "iso"=>"SK", "iso_name"=>"SLOVAKIA", "numcode"=>"703"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Gibraltar", "iso3"=>"GIB", "iso"=>"GI", "iso_name"=>"GIBRALTAR", "numcode"=>"292"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Paraguay", "iso3"=>"PRY", "iso"=>"PY", "iso_name"=>"PARAGUAY", "numcode"=>"600"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Slovenia", "iso3"=>"SVN", "iso"=>"SI", "iso_name"=>"SLOVENIA", "numcode"=>"705"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Greece", "iso3"=>"GRC", "iso"=>"GR", "iso_name"=>"GREECE", "numcode"=>"300"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Peru", "iso3"=>"PER", "iso"=>"PE", "iso_name"=>"PERU", "numcode"=>"604"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Solomon Islands", "iso3"=>"SLB", "iso"=>"SB", "iso_name"=>"SOLOMON ISLANDS", "numcode"=>"90"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Greenland", "iso3"=>"GRL", "iso"=>"GL", "iso_name"=>"GREENLAND", "numcode"=>"304"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Somalia", "iso3"=>"SOM", "iso"=>"SO", "iso_name"=>"SOMALIA", "numcode"=>"706"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Grenada", "iso3"=>"GRD", "iso"=>"GD", "iso_name"=>"GRENADA", "numcode"=>"308"}, :without_protection => true)
-Spree::Country.create!({"name"=>"South Africa", "iso3"=>"ZAF", "iso"=>"ZA", "iso_name"=>"SOUTH AFRICA", "numcode"=>"710"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Spain", "iso3"=>"ESP", "iso"=>"ES", "iso_name"=>"SPAIN", "numcode"=>"724"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Sri Lanka", "iso3"=>"LKA", "iso"=>"LK", "iso_name"=>"SRI LANKA", "numcode"=>"144"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Afghanistan", "iso3"=>"AFG", "iso"=>"AF", "iso_name"=>"AFGHANISTAN", "numcode"=>"4"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Albania", "iso3"=>"ALB", "iso"=>"AL", "iso_name"=>"ALBANIA", "numcode"=>"8"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Algeria", "iso3"=>"DZA", "iso"=>"DZ", "iso_name"=>"ALGERIA", "numcode"=>"12"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Latvia", "iso3"=>"LVA", "iso"=>"LV", "iso_name"=>"LATVIA", "numcode"=>"428"}, :without_protection => true)
-Spree::Country.create!({"name"=>"American Samoa", "iso3"=>"ASM", "iso"=>"AS", "iso_name"=>"AMERICAN SAMOA", "numcode"=>"16"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Bulgaria", "iso3"=>"BGR", "iso"=>"BG", "iso_name"=>"BULGARIA", "numcode"=>"100"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Lebanon", "iso3"=>"LBN", "iso"=>"LB", "iso_name"=>"LEBANON", "numcode"=>"422"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Andorra", "iso3"=>"AND", "iso"=>"AD", "iso_name"=>"ANDORRA", "numcode"=>"20"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Burkina Faso", "iso3"=>"BFA", "iso"=>"BF", "iso_name"=>"BURKINA FASO", "numcode"=>"854"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Lesotho", "iso3"=>"LSO", "iso"=>"LS", "iso_name"=>"LESOTHO", "numcode"=>"426"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Angola", "iso3"=>"AGO", "iso"=>"AO", "iso_name"=>"ANGOLA", "numcode"=>"24"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Burundi", "iso3"=>"BDI", "iso"=>"BI", "iso_name"=>"BURUNDI", "numcode"=>"108"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Liberia", "iso3"=>"LBR", "iso"=>"LR", "iso_name"=>"LIBERIA", "numcode"=>"430"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Virgin Islands, British", "iso3"=>"VGB", "iso"=>"VG", "iso_name"=>"VIRGIN ISLANDS, BRITISH", "numcode"=>"92"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Anguilla", "iso3"=>"AIA", "iso"=>"AI", "iso_name"=>"ANGUILLA", "numcode"=>"660"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Cambodia", "iso3"=>"KHM", "iso"=>"KH", "iso_name"=>"CAMBODIA", "numcode"=>"116"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Equatorial Guinea", "iso3"=>"GNQ", "iso"=>"GQ", "iso_name"=>"EQUATORIAL GUINEA", "numcode"=>"226"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Libyan Arab Jamahiriya", "iso3"=>"LBY", "iso"=>"LY", "iso_name"=>"LIBYAN ARAB JAMAHIRIYA", "numcode"=>"434"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Nauru", "iso3"=>"NRU", "iso"=>"NR", "iso_name"=>"NAURU", "numcode"=>"520"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Virgin Islands, U.S.", "iso3"=>"VIR", "iso"=>"VI", "iso_name"=>"VIRGIN ISLANDS, U.S.", "numcode"=>"850"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Antigua and Barbuda", "iso3"=>"ATG", "iso"=>"AG", "iso_name"=>"ANTIGUA AND BARBUDA", "numcode"=>"28"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Cameroon", "iso3"=>"CMR", "iso"=>"CM", "iso_name"=>"CAMEROON", "numcode"=>"120"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Liechtenstein", "iso3"=>"LIE", "iso"=>"LI", "iso_name"=>"LIECHTENSTEIN", "numcode"=>"438"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Nepal", "iso3"=>"NPL", "iso"=>"NP", "iso_name"=>"NEPAL", "numcode"=>"524"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Wallis and Futuna", "iso3"=>"WLF", "iso"=>"WF", "iso_name"=>"WALLIS AND FUTUNA", "numcode"=>"876"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Western Sahara", "iso3"=>"ESH", "iso"=>"EH", "iso_name"=>"WESTERN SAHARA", "numcode"=>"732"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Argentina", "iso3"=>"ARG", "iso"=>"AR", "iso_name"=>"ARGENTINA", "numcode"=>"32"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Canada", "iso3"=>"CAN", "iso"=>"CA", "iso_name"=>"CANADA", "numcode"=>"124"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Eritrea", "iso3"=>"ERI", "iso"=>"ER", "iso_name"=>"ERITREA", "numcode"=>"232"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Lithuania", "iso3"=>"LTU", "iso"=>"LT", "iso_name"=>"LITHUANIA", "numcode"=>"440"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Netherlands", "iso3"=>"NLD", "iso"=>"NL", "iso_name"=>"NETHERLANDS", "numcode"=>"528"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Yemen", "iso3"=>"YEM", "iso"=>"YE", "iso_name"=>"YEMEN", "numcode"=>"887"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Cape Verde", "iso3"=>"CPV", "iso"=>"CV", "iso_name"=>"CAPE VERDE", "numcode"=>"132"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Estonia", "iso3"=>"EST", "iso"=>"EE", "iso_name"=>"ESTONIA", "numcode"=>"233"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Luxembourg", "iso3"=>"LUX", "iso"=>"LU", "iso_name"=>"LUXEMBOURG", "numcode"=>"442"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Netherlands Antilles", "iso3"=>"ANT", "iso"=>"AN", "iso_name"=>"NETHERLANDS ANTILLES", "numcode"=>"530"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Saint Helena", "iso3"=>"SHN", "iso"=>"SH", "iso_name"=>"SAINT HELENA", "numcode"=>"654"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Zambia", "iso3"=>"ZMB", "iso"=>"ZM", "iso_name"=>"ZAMBIA", "numcode"=>"894"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Cayman Islands", "iso3"=>"CYM", "iso"=>"KY", "iso_name"=>"CAYMAN ISLANDS", "numcode"=>"136"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Ethiopia", "iso3"=>"ETH", "iso"=>"ET", "iso_name"=>"ETHIOPIA", "numcode"=>"231"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Hungary", "iso3"=>"HUN", "iso"=>"HU", "iso_name"=>"HUNGARY", "numcode"=>"348"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Macao", "iso3"=>"MAC", "iso"=>"MO", "iso_name"=>"MACAO", "numcode"=>"446"}, :without_protection => true)
-Spree::Country.create!({"name"=>"New Caledonia", "iso3"=>"NCL", "iso"=>"NC", "iso_name"=>"NEW CALEDONIA", "numcode"=>"540"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Zimbabwe", "iso3"=>"ZWE", "iso"=>"ZW", "iso_name"=>"ZIMBABWE", "numcode"=>"716"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Central African Republic", "iso3"=>"CAF", "iso"=>"CF", "iso_name"=>"CENTRAL AFRICAN REPUBLIC", "numcode"=>"140"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Falkland Islands (Malvinas)", "iso3"=>"FLK", "iso"=>"FK", "iso_name"=>"FALKLAND ISLANDS (MALVINAS)", "numcode"=>"238"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Iceland", "iso3"=>"ISL", "iso"=>"IS", "iso_name"=>"ICELAND", "numcode"=>"352"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Macedonia", "iso3"=>"MKD", "iso"=>"MK", "iso_name"=>"MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF", "numcode"=>"807"}, :without_protection => true)
-Spree::Country.create!({"name"=>"New Zealand", "iso3"=>"NZL", "iso"=>"NZ", "iso_name"=>"NEW ZEALAND", "numcode"=>"554"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Saint Kitts and Nevis", "iso3"=>"KNA", "iso"=>"KN", "iso_name"=>"SAINT KITTS AND NEVIS", "numcode"=>"659"}, :without_protection => true)
-Spree::Country.create!({"name"=>"Serbia", "iso3"=>"SRB", "iso"=>"RS", "iso_name" => "SERBIA", "numcode"=>"999"}, :without_protection => true)
+Spree::Country.create!({"name"=>"Chad", "iso3"=>"TCD", "iso"=>"TD", "iso_name"=>"CHAD", "numcode"=>"148"})
+Spree::Country.create!({"name"=>"Faroe Islands", "iso3"=>"FRO", "iso"=>"FO", "iso_name"=>"FAROE ISLANDS", "numcode"=>"234"})
+Spree::Country.create!({"name"=>"India", "iso3"=>"IND", "iso"=>"IN", "iso_name"=>"INDIA", "numcode"=>"356"})
+Spree::Country.create!({"name"=>"Nicaragua", "iso3"=>"NIC", "iso"=>"NI", "iso_name"=>"NICARAGUA", "numcode"=>"558"})
+Spree::Country.create!({"name"=>"Saint Lucia", "iso3"=>"LCA", "iso"=>"LC", "iso_name"=>"SAINT LUCIA", "numcode"=>"662"})
+Spree::Country.create!({"name"=>"Fiji", "iso3"=>"FJI", "iso"=>"FJ", "iso_name"=>"FIJI", "numcode"=>"242"})
+Spree::Country.create!({"name"=>"Indonesia", "iso3"=>"IDN", "iso"=>"ID", "iso_name"=>"INDONESIA", "numcode"=>"360"})
+Spree::Country.create!({"name"=>"Niger", "iso3"=>"NER", "iso"=>"NE", "iso_name"=>"NIGER", "numcode"=>"562"})
+Spree::Country.create!({"name"=>"Saint Pierre and Miquelon", "iso3"=>"SPM", "iso"=>"PM", "iso_name"=>"SAINT PIERRE AND MIQUELON", "numcode"=>"666"})
+Spree::Country.create!({"name"=>"Finland", "iso3"=>"FIN", "iso"=>"FI", "iso_name"=>"FINLAND", "numcode"=>"246"})
+Spree::Country.create!({"name"=>"Nigeria", "iso3"=>"NGA", "iso"=>"NG", "iso_name"=>"NIGERIA", "numcode"=>"566"})
+Spree::Country.create!({"name"=>"Saint Vincent and the Grenadines", "iso3"=>"VCT", "iso"=>"VC", "iso_name"=>"SAINT VINCENT AND THE GRENADINES", "numcode"=>"670"})
+Spree::Country.create!({"name"=>"France", "iso3"=>"FRA", "iso"=>"FR", "iso_name"=>"FRANCE", "numcode"=>"250"})
+Spree::Country.create!({"name"=>"Iran, Islamic Republic of", "iso3"=>"IRN", "iso"=>"IR", "iso_name"=>"IRAN, ISLAMIC REPUBLIC OF", "numcode"=>"364"})
+Spree::Country.create!({"name"=>"Niue", "iso3"=>"NIU", "iso"=>"NU", "iso_name"=>"NIUE", "numcode"=>"570"})
+Spree::Country.create!({"name"=>"Samoa", "iso3"=>"WSM", "iso"=>"WS", "iso_name"=>"SAMOA", "numcode"=>"882"})
+Spree::Country.create!({"name"=>"French Guiana", "iso3"=>"GUF", "iso"=>"GF", "iso_name"=>"FRENCH GUIANA", "numcode"=>"254"})
+Spree::Country.create!({"name"=>"Iraq", "iso3"=>"IRQ", "iso"=>"IQ", "iso_name"=>"IRAQ", "numcode"=>"368"})
+Spree::Country.create!({"name"=>"San Marino", "iso3"=>"SMR", "iso"=>"SM", "iso_name"=>"SAN MARINO", "numcode"=>"674"})
+Spree::Country.create!({"name"=>"Ireland", "iso3"=>"IRL", "iso"=>"IE", "iso_name"=>"IRELAND", "numcode"=>"372"})
+Spree::Country.create!({"name"=>"Sao Tome and Principe", "iso3"=>"STP", "iso"=>"ST", "iso_name"=>"SAO TOME AND PRINCIPE", "numcode"=>"678"})
+Spree::Country.create!({"name"=>"Israel", "iso3"=>"ISR", "iso"=>"IL", "iso_name"=>"ISRAEL", "numcode"=>"376"})
+Spree::Country.create!({"name"=>"Saudi Arabia", "iso3"=>"SAU", "iso"=>"SA", "iso_name"=>"SAUDI ARABIA", "numcode"=>"682"})
+Spree::Country.create!({"name"=>"Italy", "iso3"=>"ITA", "iso"=>"IT", "iso_name"=>"ITALY", "numcode"=>"380"})
+Spree::Country.create!({"name"=>"Senegal", "iso3"=>"SEN", "iso"=>"SN", "iso_name"=>"SENEGAL", "numcode"=>"686"})
+Spree::Country.create!({"name"=>"Jamaica", "iso3"=>"JAM", "iso"=>"JM", "iso_name"=>"JAMAICA", "numcode"=>"388"})
+Spree::Country.create!({"name"=>"Japan", "iso3"=>"JPN", "iso"=>"JP", "iso_name"=>"JAPAN", "numcode"=>"392"})
+Spree::Country.create!({"name"=>"Jordan", "iso3"=>"JOR", "iso"=>"JO", "iso_name"=>"JORDAN", "numcode"=>"400"})
+Spree::Country.create!({"name"=>"Belgium", "iso3"=>"BEL", "iso"=>"BE", "iso_name"=>"BELGIUM", "numcode"=>"56"})
+Spree::Country.create!({"name"=>"Belize", "iso3"=>"BLZ", "iso"=>"BZ", "iso_name"=>"BELIZE", "numcode"=>"84"})
+Spree::Country.create!({"name"=>"Kazakhstan", "iso3"=>"KAZ", "iso"=>"KZ", "iso_name"=>"KAZAKHSTAN", "numcode"=>"398"})
+Spree::Country.create!({"name"=>"Uganda", "iso3"=>"UGA", "iso"=>"UG", "iso_name"=>"UGANDA", "numcode"=>"800"})
+Spree::Country.create!({"name"=>"Benin", "iso3"=>"BEN", "iso"=>"BJ", "iso_name"=>"BENIN", "numcode"=>"204"})
+Spree::Country.create!({"name"=>"Kenya", "iso3"=>"KEN", "iso"=>"KE", "iso_name"=>"KENYA", "numcode"=>"404"})
+Spree::Country.create!({"name"=>"Ukraine", "iso3"=>"UKR", "iso"=>"UA", "iso_name"=>"UKRAINE", "numcode"=>"804"})
+Spree::Country.create!({"name"=>"Bermuda", "iso3"=>"BMU", "iso"=>"BM", "iso_name"=>"BERMUDA", "numcode"=>"60"})
+Spree::Country.create!({"name"=>"Kiribati", "iso3"=>"KIR", "iso"=>"KI", "iso_name"=>"KIRIBATI", "numcode"=>"296"})
+Spree::Country.create!({"name"=>"Mexico", "iso3"=>"MEX", "iso"=>"MX", "iso_name"=>"MEXICO", "numcode"=>"484"})
+Spree::Country.create!({"name"=>"United Arab Emirates", "iso3"=>"ARE", "iso"=>"AE", "iso_name"=>"UNITED ARAB EMIRATES", "numcode"=>"784"})
+Spree::Country.create!({"name"=>"Bhutan", "iso3"=>"BTN", "iso"=>"BT", "iso_name"=>"BHUTAN", "numcode"=>"64"})
+Spree::Country.create!({"name"=>"Cuba", "iso3"=>"CUB", "iso"=>"CU", "iso_name"=>"CUBA", "numcode"=>"192"})
+Spree::Country.create!({"name"=>"North Korea", "iso3"=>"PRK", "iso"=>"KP", "iso_name"=>"KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF", "numcode"=>"408"})
+Spree::Country.create!({"name"=>"Micronesia, Federated States of", "iso3"=>"FSM", "iso"=>"FM", "iso_name"=>"MICRONESIA, FEDERATED STATES OF", "numcode"=>"583"})
+Spree::Country.create!({"name"=>"United Kingdom", "iso3"=>"GBR", "iso"=>"GB", "iso_name"=>"UNITED KINGDOM", "numcode"=>"826"})
+Spree::Country.create!({"name"=>"Bolivia", "iso3"=>"BOL", "iso"=>"BO", "iso_name"=>"BOLIVIA", "numcode"=>"68"})
+Spree::Country.create!({"name"=>"Cyprus", "iso3"=>"CYP", "iso"=>"CY", "iso_name"=>"CYPRUS", "numcode"=>"196"})
+Spree::Country.create!({"name"=>"South Korea", "iso3"=>"KOR", "iso"=>"KR", "iso_name"=>"KOREA, REPUBLIC OF", "numcode"=>"410"})
+Spree::Country.create!({"name"=>"Moldova, Republic of", "iso3"=>"MDA", "iso"=>"MD", "iso_name"=>"MOLDOVA, REPUBLIC OF", "numcode"=>"498"})
+Spree::Country.create!({"name"=>"United States", "iso3"=>"USA", "iso"=>"US", "iso_name"=>"UNITED STATES", "numcode"=>"840"})
+Spree::Country.create!({"name"=>"Bosnia and Herzegovina", "iso3"=>"BIH", "iso"=>"BA", "iso_name"=>"BOSNIA AND HERZEGOVINA", "numcode"=>"70"})
+Spree::Country.create!({"name"=>"Czech Republic", "iso3"=>"CZE", "iso"=>"CZ", "iso_name"=>"CZECH REPUBLIC", "numcode"=>"203"})
+Spree::Country.create!({"name"=>"Kuwait", "iso3"=>"KWT", "iso"=>"KW", "iso_name"=>"KUWAIT", "numcode"=>"414"})
+Spree::Country.create!({"name"=>"Monaco", "iso3"=>"MCO", "iso"=>"MC", "iso_name"=>"MONACO", "numcode"=>"492"})
+Spree::Country.create!({"name"=>"Uruguay", "iso3"=>"URY", "iso"=>"UY", "iso_name"=>"URUGUAY", "numcode"=>"858"})
+Spree::Country.create!({"name"=>"Botswana", "iso3"=>"BWA", "iso"=>"BW", "iso_name"=>"BOTSWANA", "numcode"=>"72"})
+Spree::Country.create!({"name"=>"Denmark", "iso3"=>"DNK", "iso"=>"DK", "iso_name"=>"DENMARK", "numcode"=>"208"})
+Spree::Country.create!({"name"=>"Guadeloupe", "iso3"=>"GLP", "iso"=>"GP", "iso_name"=>"GUADELOUPE", "numcode"=>"312"})
+Spree::Country.create!({"name"=>"Kyrgyzstan", "iso3"=>"KGZ", "iso"=>"KG", "iso_name"=>"KYRGYZSTAN", "numcode"=>"417"})
+Spree::Country.create!({"name"=>"Mongolia", "iso3"=>"MNG", "iso"=>"MN", "iso_name"=>"MONGOLIA", "numcode"=>"496"})
+Spree::Country.create!({"name"=>"Philippines", "iso3"=>"PHL", "iso"=>"PH", "iso_name"=>"PHILIPPINES", "numcode"=>"608"})
+Spree::Country.create!({"name"=>"Brazil", "iso3"=>"BRA", "iso"=>"BR", "iso_name"=>"BRAZIL", "numcode"=>"76"})
+Spree::Country.create!({"name"=>"Djibouti", "iso3"=>"DJI", "iso"=>"DJ", "iso_name"=>"DJIBOUTI", "numcode"=>"262"})
+Spree::Country.create!({"name"=>"Guam", "iso3"=>"GUM", "iso"=>"GU", "iso_name"=>"GUAM", "numcode"=>"316"})
+Spree::Country.create!({"name"=>"Lao People's Democratic Republic", "iso3"=>"LAO", "iso"=>"LA", "iso_name"=>"LAO PEOPLE'S DEMOCRATIC REPUBLIC", "numcode"=>"418"})
+Spree::Country.create!({"name"=>"Montserrat", "iso3"=>"MSR", "iso"=>"MS", "iso_name"=>"MONTSERRAT", "numcode"=>"500"})
+Spree::Country.create!({"name"=>"Pitcairn", "iso3"=>"PCN", "iso"=>"PN", "iso_name"=>"PITCAIRN", "numcode"=>"612"})
+Spree::Country.create!({"name"=>"Uzbekistan", "iso3"=>"UZB", "iso"=>"UZ", "iso_name"=>"UZBEKISTAN", "numcode"=>"860"})
+Spree::Country.create!({"name"=>"Brunei Darussalam", "iso3"=>"BRN", "iso"=>"BN", "iso_name"=>"BRUNEI DARUSSALAM", "numcode"=>"96"})
+Spree::Country.create!({"name"=>"Dominica", "iso3"=>"DMA", "iso"=>"DM", "iso_name"=>"DOMINICA", "numcode"=>"212"})
+Spree::Country.create!({"name"=>"Guatemala", "iso3"=>"GTM", "iso"=>"GT", "iso_name"=>"GUATEMALA", "numcode"=>"320"})
+Spree::Country.create!({"name"=>"Morocco", "iso3"=>"MAR", "iso"=>"MA", "iso_name"=>"MOROCCO", "numcode"=>"504"})
+Spree::Country.create!({"name"=>"Poland", "iso3"=>"POL", "iso"=>"PL", "iso_name"=>"POLAND", "numcode"=>"616"})
+Spree::Country.create!({"name"=>"Vanuatu", "iso3"=>"VUT", "iso"=>"VU", "iso_name"=>"VANUATU", "numcode"=>"548"})
+Spree::Country.create!({"name"=>"Dominican Republic", "iso3"=>"DOM", "iso"=>"DO", "iso_name"=>"DOMINICAN REPUBLIC", "numcode"=>"214"})
+Spree::Country.create!({"name"=>"Mozambique", "iso3"=>"MOZ", "iso"=>"MZ", "iso_name"=>"MOZAMBIQUE", "numcode"=>"508"})
+Spree::Country.create!({"name"=>"Portugal", "iso3"=>"PRT", "iso"=>"PT", "iso_name"=>"PORTUGAL", "numcode"=>"620"})
+Spree::Country.create!({"name"=>"Sudan", "iso3"=>"SDN", "iso"=>"SD", "iso_name"=>"SUDAN", "numcode"=>"736"})
+Spree::Country.create!({"name"=>"Venezuela", "iso3"=>"VEN", "iso"=>"VE", "iso_name"=>"VENEZUELA", "numcode"=>"862"})
+Spree::Country.create!({"name"=>"Ecuador", "iso3"=>"ECU", "iso"=>"EC", "iso_name"=>"ECUADOR", "numcode"=>"218"})
+Spree::Country.create!({"name"=>"Guinea", "iso3"=>"GIN", "iso"=>"GN", "iso_name"=>"GUINEA", "numcode"=>"324"})
+Spree::Country.create!({"name"=>"Myanmar", "iso3"=>"MMR", "iso"=>"MM", "iso_name"=>"MYANMAR", "numcode"=>"104"})
+Spree::Country.create!({"name"=>"Puerto Rico", "iso3"=>"PRI", "iso"=>"PR", "iso_name"=>"PUERTO RICO", "numcode"=>"630"})
+Spree::Country.create!({"name"=>"Suriname", "iso3"=>"SUR", "iso"=>"SR", "iso_name"=>"SURINAME", "numcode"=>"740"})
+Spree::Country.create!({"name"=>"Viet Nam", "iso3"=>"VNM", "iso"=>"VN", "iso_name"=>"VIET NAM", "numcode"=>"704"})
+Spree::Country.create!({"name"=>"Egypt", "iso3"=>"EGY", "iso"=>"EG", "iso_name"=>"EGYPT", "numcode"=>"818"})
+Spree::Country.create!({"name"=>"Guinea-Bissau", "iso3"=>"GNB", "iso"=>"GW", "iso_name"=>"GUINEA-BISSAU", "numcode"=>"624"})
+Spree::Country.create!({"name"=>"Namibia", "iso3"=>"NAM", "iso"=>"NA", "iso_name"=>"NAMIBIA", "numcode"=>"516"})
+Spree::Country.create!({"name"=>"Qatar", "iso3"=>"QAT", "iso"=>"QA", "iso_name"=>"QATAR", "numcode"=>"634"})
+Spree::Country.create!({"name"=>"Svalbard and Jan Mayen", "iso3"=>"SJM", "iso"=>"SJ", "iso_name"=>"SVALBARD AND JAN MAYEN", "numcode"=>"744"})
+Spree::Country.create!({"name"=>"El Salvador", "iso3"=>"SLV", "iso"=>"SV", "iso_name"=>"EL SALVADOR", "numcode"=>"222"})
+Spree::Country.create!({"name"=>"Guyana", "iso3"=>"GUY", "iso"=>"GY", "iso_name"=>"GUYANA", "numcode"=>"328"})
+Spree::Country.create!({"name"=>"Reunion", "iso3"=>"REU", "iso"=>"RE", "iso_name"=>"REUNION", "numcode"=>"638"})
+Spree::Country.create!({"name"=>"Haiti", "iso3"=>"HTI", "iso"=>"HT", "iso_name"=>"HAITI", "numcode"=>"332"})
+Spree::Country.create!({"name"=>"Romania", "iso3"=>"ROM", "iso"=>"RO", "iso_name"=>"ROMANIA", "numcode"=>"642"})
+Spree::Country.create!({"name"=>"Swaziland", "iso3"=>"SWZ", "iso"=>"SZ", "iso_name"=>"SWAZILAND", "numcode"=>"748"})
+Spree::Country.create!({"name"=>"Holy See (Vatican City State)", "iso3"=>"VAT", "iso"=>"VA", "iso_name"=>"HOLY SEE (VATICAN CITY STATE)", "numcode"=>"336"})
+Spree::Country.create!({"name"=>"Russian Federation", "iso3"=>"RUS", "iso"=>"RU", "iso_name"=>"RUSSIAN FEDERATION", "numcode"=>"643"})
+Spree::Country.create!({"name"=>"Sweden", "iso3"=>"SWE", "iso"=>"SE", "iso_name"=>"SWEDEN", "numcode"=>"752"})
+Spree::Country.create!({"name"=>"Honduras", "iso3"=>"HND", "iso"=>"HN", "iso_name"=>"HONDURAS", "numcode"=>"340"})
+Spree::Country.create!({"name"=>"Rwanda", "iso3"=>"RWA", "iso"=>"RW", "iso_name"=>"RWANDA", "numcode"=>"646"})
+Spree::Country.create!({"name"=>"Switzerland", "iso3"=>"CHE", "iso"=>"CH", "iso_name"=>"SWITZERLAND", "numcode"=>"756"})
+Spree::Country.create!({"name"=>"Hong Kong", "iso3"=>"HKG", "iso"=>"HK", "iso_name"=>"HONG KONG", "numcode"=>"344"})
+Spree::Country.create!({"name"=>"Syrian Arab Republic", "iso3"=>"SYR", "iso"=>"SY", "iso_name"=>"SYRIAN ARAB REPUBLIC", "numcode"=>"760"})
+Spree::Country.create!({"name"=>"Taiwan", "iso3"=>"TWN", "iso"=>"TW", "iso_name"=>"TAIWAN, PROVINCE OF CHINA", "numcode"=>"158"})
+Spree::Country.create!({"name"=>"Tajikistan", "iso3"=>"TJK", "iso"=>"TJ", "iso_name"=>"TAJIKISTAN", "numcode"=>"762"})
+Spree::Country.create!({"name"=>"Tanzania, United Republic of", "iso3"=>"TZA", "iso"=>"TZ", "iso_name"=>"TANZANIA, UNITED REPUBLIC OF", "numcode"=>"834"})
+Spree::Country.create!({"name"=>"Armenia", "iso3"=>"ARM", "iso"=>"AM", "iso_name"=>"ARMENIA", "numcode"=>"51"})
+Spree::Country.create!({"name"=>"Aruba", "iso3"=>"ABW", "iso"=>"AW", "iso_name"=>"ARUBA", "numcode"=>"533"})
+Spree::Country.create!({"name"=>"Australia", "iso3"=>"AUS", "iso"=>"AU", "iso_name"=>"AUSTRALIA", "numcode"=>"36"})
+Spree::Country.create!({"name"=>"Thailand", "iso3"=>"THA", "iso"=>"TH", "iso_name"=>"THAILAND", "numcode"=>"764"})
+Spree::Country.create!({"name"=>"Austria", "iso3"=>"AUT", "iso"=>"AT", "iso_name"=>"AUSTRIA", "numcode"=>"40"})
+Spree::Country.create!({"name"=>"Madagascar", "iso3"=>"MDG", "iso"=>"MG", "iso_name"=>"MADAGASCAR", "numcode"=>"450"})
+Spree::Country.create!({"name"=>"Togo", "iso3"=>"TGO", "iso"=>"TG", "iso_name"=>"TOGO", "numcode"=>"768"})
+Spree::Country.create!({"name"=>"Azerbaijan", "iso3"=>"AZE", "iso"=>"AZ", "iso_name"=>"AZERBAIJAN", "numcode"=>"31"})
+Spree::Country.create!({"name"=>"Chile", "iso3"=>"CHL", "iso"=>"CL", "iso_name"=>"CHILE", "numcode"=>"152"})
+Spree::Country.create!({"name"=>"Malawi", "iso3"=>"MWI", "iso"=>"MW", "iso_name"=>"MALAWI", "numcode"=>"454"})
+Spree::Country.create!({"name"=>"Tokelau", "iso3"=>"TKL", "iso"=>"TK", "iso_name"=>"TOKELAU", "numcode"=>"772"})
+Spree::Country.create!({"name"=>"Bahamas", "iso3"=>"BHS", "iso"=>"BS", "iso_name"=>"BAHAMAS", "numcode"=>"44"})
+Spree::Country.create!({"name"=>"China", "iso3"=>"CHN", "iso"=>"CN", "iso_name"=>"CHINA", "numcode"=>"156"})
+Spree::Country.create!({"name"=>"Malaysia", "iso3"=>"MYS", "iso"=>"MY", "iso_name"=>"MALAYSIA", "numcode"=>"458"})
+Spree::Country.create!({"name"=>"Tonga", "iso3"=>"TON", "iso"=>"TO", "iso_name"=>"TONGA", "numcode"=>"776"})
+Spree::Country.create!({"name"=>"Bahrain", "iso3"=>"BHR", "iso"=>"BH", "iso_name"=>"BAHRAIN", "numcode"=>"48"})
+Spree::Country.create!({"name"=>"Colombia", "iso3"=>"COL", "iso"=>"CO", "iso_name"=>"COLOMBIA", "numcode"=>"170"})
+Spree::Country.create!({"name"=>"Maldives", "iso3"=>"MDV", "iso"=>"MV", "iso_name"=>"MALDIVES", "numcode"=>"462"})
+Spree::Country.create!({"name"=>"Trinidad and Tobago", "iso3"=>"TTO", "iso"=>"TT", "iso_name"=>"TRINIDAD AND TOBAGO", "numcode"=>"780"})
+Spree::Country.create!({"name"=>"Bangladesh", "iso3"=>"BGD", "iso"=>"BD", "iso_name"=>"BANGLADESH", "numcode"=>"50"})
+Spree::Country.create!({"name"=>"Comoros", "iso3"=>"COM", "iso"=>"KM", "iso_name"=>"COMOROS", "numcode"=>"174"})
+Spree::Country.create!({"name"=>"French Polynesia", "iso3"=>"PYF", "iso"=>"PF", "iso_name"=>"FRENCH POLYNESIA", "numcode"=>"258"})
+Spree::Country.create!({"name"=>"Mali", "iso3"=>"MLI", "iso"=>"ML", "iso_name"=>"MALI", "numcode"=>"466"})
+Spree::Country.create!({"name"=>"Norfolk Island", "iso3"=>"NFK", "iso"=>"NF", "iso_name"=>"NORFOLK ISLAND", "numcode"=>"574"})
+Spree::Country.create!({"name"=>"Tunisia", "iso3"=>"TUN", "iso"=>"TN", "iso_name"=>"TUNISIA", "numcode"=>"788"})
+Spree::Country.create!({"name"=>"Barbados", "iso3"=>"BRB", "iso"=>"BB", "iso_name"=>"BARBADOS", "numcode"=>"52"})
+Spree::Country.create!({"name"=>"Congo", "iso3"=>"COG", "iso"=>"CG", "iso_name"=>"CONGO", "numcode"=>"178"})
+Spree::Country.create!({"name"=>"Gabon", "iso3"=>"GAB", "iso"=>"GA", "iso_name"=>"GABON", "numcode"=>"266"})
+Spree::Country.create!({"name"=>"Malta", "iso3"=>"MLT", "iso"=>"MT", "iso_name"=>"MALTA", "numcode"=>"470"})
+Spree::Country.create!({"name"=>"Northern Mariana Islands", "iso3"=>"MNP", "iso"=>"MP", "iso_name"=>"NORTHERN MARIANA ISLANDS", "numcode"=>"580"})
+Spree::Country.create!({"name"=>"Turkey", "iso3"=>"TUR", "iso"=>"TR", "iso_name"=>"TURKEY", "numcode"=>"792"})
+Spree::Country.create!({"name"=>"Congo, the Democratic Republic of the", "iso3"=>"COD", "iso"=>"CD", "iso_name"=>"CONGO, THE DEMOCRATIC REPUBLIC OF THE", "numcode"=>"180"})
+Spree::Country.create!({"name"=>"Marshall Islands", "iso3"=>"MHL", "iso"=>"MH", "iso_name"=>"MARSHALL ISLANDS", "numcode"=>"584"})
+Spree::Country.create!({"name"=>"Norway", "iso3"=>"NOR", "iso"=>"NO", "iso_name"=>"NORWAY", "numcode"=>"578"})
+Spree::Country.create!({"name"=>"Turkmenistan", "iso3"=>"TKM", "iso"=>"TM", "iso_name"=>"TURKMENISTAN", "numcode"=>"795"})
+Spree::Country.create!({"name"=>"Belarus", "iso3"=>"BLR", "iso"=>"BY", "iso_name"=>"BELARUS", "numcode"=>"112"})
+Spree::Country.create!({"name"=>"Cook Islands", "iso3"=>"COK", "iso"=>"CK", "iso_name"=>"COOK ISLANDS", "numcode"=>"184"})
+Spree::Country.create!({"name"=>"Gambia", "iso3"=>"GMB", "iso"=>"GM", "iso_name"=>"GAMBIA", "numcode"=>"270"})
+Spree::Country.create!({"name"=>"Martinique", "iso3"=>"MTQ", "iso"=>"MQ", "iso_name"=>"MARTINIQUE", "numcode"=>"474"})
+Spree::Country.create!({"name"=>"Oman", "iso3"=>"OMN", "iso"=>"OM", "iso_name"=>"OMAN", "numcode"=>"512"})
+Spree::Country.create!({"name"=>"Seychelles", "iso3"=>"SYC", "iso"=>"SC", "iso_name"=>"SEYCHELLES", "numcode"=>"690"})
+Spree::Country.create!({"name"=>"Turks and Caicos Islands", "iso3"=>"TCA", "iso"=>"TC", "iso_name"=>"TURKS AND CAICOS ISLANDS", "numcode"=>"796"})
+Spree::Country.create!({"name"=>"Georgia", "iso3"=>"GEO", "iso"=>"GE", "iso_name"=>"GEORGIA", "numcode"=>"268"})
+Spree::Country.create!({"name"=>"Mauritania", "iso3"=>"MRT", "iso"=>"MR", "iso_name"=>"MAURITANIA", "numcode"=>"478"})
+Spree::Country.create!({"name"=>"Pakistan", "iso3"=>"PAK", "iso"=>"PK", "iso_name"=>"PAKISTAN", "numcode"=>"586"})
+Spree::Country.create!({"name"=>"Sierra Leone", "iso3"=>"SLE", "iso"=>"SL", "iso_name"=>"SIERRA LEONE", "numcode"=>"694"})
+Spree::Country.create!({"name"=>"Tuvalu", "iso3"=>"TUV", "iso"=>"TV", "iso_name"=>"TUVALU", "numcode"=>"798"})
+Spree::Country.create!({"name"=>"Costa Rica", "iso3"=>"CRI", "iso"=>"CR", "iso_name"=>"COSTA RICA", "numcode"=>"188"})
+Spree::Country.create!({"name"=>"Germany", "iso3"=>"DEU", "iso"=>"DE", "iso_name"=>"GERMANY", "numcode"=>"276"})
+Spree::Country.create!({"name"=>"Mauritius", "iso3"=>"MUS", "iso"=>"MU", "iso_name"=>"MAURITIUS", "numcode"=>"480"})
+Spree::Country.create!({"name"=>"Palau", "iso3"=>"PLW", "iso"=>"PW", "iso_name"=>"PALAU", "numcode"=>"585"})
+Spree::Country.create!({"name"=>"Cote D'Ivoire", "iso3"=>"CIV", "iso"=>"CI", "iso_name"=>"COTE D'IVOIRE", "numcode"=>"384"})
+Spree::Country.create!({"name"=>"Panama", "iso3"=>"PAN", "iso"=>"PA", "iso_name"=>"PANAMA", "numcode"=>"591"})
+Spree::Country.create!({"name"=>"Singapore", "iso3"=>"SGP", "iso"=>"SG", "iso_name"=>"SINGAPORE", "numcode"=>"702"})
+Spree::Country.create!({"name"=>"Croatia", "iso3"=>"HRV", "iso"=>"HR", "iso_name"=>"CROATIA", "numcode"=>"191"})
+Spree::Country.create!({"name"=>"Ghana", "iso3"=>"GHA", "iso"=>"GH", "iso_name"=>"GHANA", "numcode"=>"288"})
+Spree::Country.create!({"name"=>"Papua New Guinea", "iso3"=>"PNG", "iso"=>"PG", "iso_name"=>"PAPUA NEW GUINEA", "numcode"=>"598"})
+Spree::Country.create!({"name"=>"Slovakia", "iso3"=>"SVK", "iso"=>"SK", "iso_name"=>"SLOVAKIA", "numcode"=>"703"})
+Spree::Country.create!({"name"=>"Gibraltar", "iso3"=>"GIB", "iso"=>"GI", "iso_name"=>"GIBRALTAR", "numcode"=>"292"})
+Spree::Country.create!({"name"=>"Paraguay", "iso3"=>"PRY", "iso"=>"PY", "iso_name"=>"PARAGUAY", "numcode"=>"600"})
+Spree::Country.create!({"name"=>"Slovenia", "iso3"=>"SVN", "iso"=>"SI", "iso_name"=>"SLOVENIA", "numcode"=>"705"})
+Spree::Country.create!({"name"=>"Greece", "iso3"=>"GRC", "iso"=>"GR", "iso_name"=>"GREECE", "numcode"=>"300"})
+Spree::Country.create!({"name"=>"Peru", "iso3"=>"PER", "iso"=>"PE", "iso_name"=>"PERU", "numcode"=>"604"})
+Spree::Country.create!({"name"=>"Solomon Islands", "iso3"=>"SLB", "iso"=>"SB", "iso_name"=>"SOLOMON ISLANDS", "numcode"=>"90"})
+Spree::Country.create!({"name"=>"Greenland", "iso3"=>"GRL", "iso"=>"GL", "iso_name"=>"GREENLAND", "numcode"=>"304"})
+Spree::Country.create!({"name"=>"Somalia", "iso3"=>"SOM", "iso"=>"SO", "iso_name"=>"SOMALIA", "numcode"=>"706"})
+Spree::Country.create!({"name"=>"Grenada", "iso3"=>"GRD", "iso"=>"GD", "iso_name"=>"GRENADA", "numcode"=>"308"})
+Spree::Country.create!({"name"=>"South Africa", "iso3"=>"ZAF", "iso"=>"ZA", "iso_name"=>"SOUTH AFRICA", "numcode"=>"710"})
+Spree::Country.create!({"name"=>"Spain", "iso3"=>"ESP", "iso"=>"ES", "iso_name"=>"SPAIN", "numcode"=>"724"})
+Spree::Country.create!({"name"=>"Sri Lanka", "iso3"=>"LKA", "iso"=>"LK", "iso_name"=>"SRI LANKA", "numcode"=>"144"})
+Spree::Country.create!({"name"=>"Afghanistan", "iso3"=>"AFG", "iso"=>"AF", "iso_name"=>"AFGHANISTAN", "numcode"=>"4"})
+Spree::Country.create!({"name"=>"Albania", "iso3"=>"ALB", "iso"=>"AL", "iso_name"=>"ALBANIA", "numcode"=>"8"})
+Spree::Country.create!({"name"=>"Algeria", "iso3"=>"DZA", "iso"=>"DZ", "iso_name"=>"ALGERIA", "numcode"=>"12"})
+Spree::Country.create!({"name"=>"Latvia", "iso3"=>"LVA", "iso"=>"LV", "iso_name"=>"LATVIA", "numcode"=>"428"})
+Spree::Country.create!({"name"=>"American Samoa", "iso3"=>"ASM", "iso"=>"AS", "iso_name"=>"AMERICAN SAMOA", "numcode"=>"16"})
+Spree::Country.create!({"name"=>"Bulgaria", "iso3"=>"BGR", "iso"=>"BG", "iso_name"=>"BULGARIA", "numcode"=>"100"})
+Spree::Country.create!({"name"=>"Lebanon", "iso3"=>"LBN", "iso"=>"LB", "iso_name"=>"LEBANON", "numcode"=>"422"})
+Spree::Country.create!({"name"=>"Andorra", "iso3"=>"AND", "iso"=>"AD", "iso_name"=>"ANDORRA", "numcode"=>"20"})
+Spree::Country.create!({"name"=>"Burkina Faso", "iso3"=>"BFA", "iso"=>"BF", "iso_name"=>"BURKINA FASO", "numcode"=>"854"})
+Spree::Country.create!({"name"=>"Lesotho", "iso3"=>"LSO", "iso"=>"LS", "iso_name"=>"LESOTHO", "numcode"=>"426"})
+Spree::Country.create!({"name"=>"Angola", "iso3"=>"AGO", "iso"=>"AO", "iso_name"=>"ANGOLA", "numcode"=>"24"})
+Spree::Country.create!({"name"=>"Burundi", "iso3"=>"BDI", "iso"=>"BI", "iso_name"=>"BURUNDI", "numcode"=>"108"})
+Spree::Country.create!({"name"=>"Liberia", "iso3"=>"LBR", "iso"=>"LR", "iso_name"=>"LIBERIA", "numcode"=>"430"})
+Spree::Country.create!({"name"=>"Virgin Islands, British", "iso3"=>"VGB", "iso"=>"VG", "iso_name"=>"VIRGIN ISLANDS, BRITISH", "numcode"=>"92"})
+Spree::Country.create!({"name"=>"Anguilla", "iso3"=>"AIA", "iso"=>"AI", "iso_name"=>"ANGUILLA", "numcode"=>"660"})
+Spree::Country.create!({"name"=>"Cambodia", "iso3"=>"KHM", "iso"=>"KH", "iso_name"=>"CAMBODIA", "numcode"=>"116"})
+Spree::Country.create!({"name"=>"Equatorial Guinea", "iso3"=>"GNQ", "iso"=>"GQ", "iso_name"=>"EQUATORIAL GUINEA", "numcode"=>"226"})
+Spree::Country.create!({"name"=>"Libyan Arab Jamahiriya", "iso3"=>"LBY", "iso"=>"LY", "iso_name"=>"LIBYAN ARAB JAMAHIRIYA", "numcode"=>"434"})
+Spree::Country.create!({"name"=>"Nauru", "iso3"=>"NRU", "iso"=>"NR", "iso_name"=>"NAURU", "numcode"=>"520"})
+Spree::Country.create!({"name"=>"Virgin Islands, U.S.", "iso3"=>"VIR", "iso"=>"VI", "iso_name"=>"VIRGIN ISLANDS, U.S.", "numcode"=>"850"})
+Spree::Country.create!({"name"=>"Antigua and Barbuda", "iso3"=>"ATG", "iso"=>"AG", "iso_name"=>"ANTIGUA AND BARBUDA", "numcode"=>"28"})
+Spree::Country.create!({"name"=>"Cameroon", "iso3"=>"CMR", "iso"=>"CM", "iso_name"=>"CAMEROON", "numcode"=>"120"})
+Spree::Country.create!({"name"=>"Liechtenstein", "iso3"=>"LIE", "iso"=>"LI", "iso_name"=>"LIECHTENSTEIN", "numcode"=>"438"})
+Spree::Country.create!({"name"=>"Nepal", "iso3"=>"NPL", "iso"=>"NP", "iso_name"=>"NEPAL", "numcode"=>"524"})
+Spree::Country.create!({"name"=>"Wallis and Futuna", "iso3"=>"WLF", "iso"=>"WF", "iso_name"=>"WALLIS AND FUTUNA", "numcode"=>"876"})
+Spree::Country.create!({"name"=>"Western Sahara", "iso3"=>"ESH", "iso"=>"EH", "iso_name"=>"WESTERN SAHARA", "numcode"=>"732"})
+Spree::Country.create!({"name"=>"Argentina", "iso3"=>"ARG", "iso"=>"AR", "iso_name"=>"ARGENTINA", "numcode"=>"32"})
+Spree::Country.create!({"name"=>"Canada", "iso3"=>"CAN", "iso"=>"CA", "iso_name"=>"CANADA", "numcode"=>"124"})
+Spree::Country.create!({"name"=>"Eritrea", "iso3"=>"ERI", "iso"=>"ER", "iso_name"=>"ERITREA", "numcode"=>"232"})
+Spree::Country.create!({"name"=>"Lithuania", "iso3"=>"LTU", "iso"=>"LT", "iso_name"=>"LITHUANIA", "numcode"=>"440"})
+Spree::Country.create!({"name"=>"Netherlands", "iso3"=>"NLD", "iso"=>"NL", "iso_name"=>"NETHERLANDS", "numcode"=>"528"})
+Spree::Country.create!({"name"=>"Yemen", "iso3"=>"YEM", "iso"=>"YE", "iso_name"=>"YEMEN", "numcode"=>"887"})
+Spree::Country.create!({"name"=>"Cape Verde", "iso3"=>"CPV", "iso"=>"CV", "iso_name"=>"CAPE VERDE", "numcode"=>"132"})
+Spree::Country.create!({"name"=>"Estonia", "iso3"=>"EST", "iso"=>"EE", "iso_name"=>"ESTONIA", "numcode"=>"233"})
+Spree::Country.create!({"name"=>"Luxembourg", "iso3"=>"LUX", "iso"=>"LU", "iso_name"=>"LUXEMBOURG", "numcode"=>"442"})
+Spree::Country.create!({"name"=>"Netherlands Antilles", "iso3"=>"ANT", "iso"=>"AN", "iso_name"=>"NETHERLANDS ANTILLES", "numcode"=>"530"})
+Spree::Country.create!({"name"=>"Saint Helena", "iso3"=>"SHN", "iso"=>"SH", "iso_name"=>"SAINT HELENA", "numcode"=>"654"})
+Spree::Country.create!({"name"=>"Zambia", "iso3"=>"ZMB", "iso"=>"ZM", "iso_name"=>"ZAMBIA", "numcode"=>"894"})
+Spree::Country.create!({"name"=>"Cayman Islands", "iso3"=>"CYM", "iso"=>"KY", "iso_name"=>"CAYMAN ISLANDS", "numcode"=>"136"})
+Spree::Country.create!({"name"=>"Ethiopia", "iso3"=>"ETH", "iso"=>"ET", "iso_name"=>"ETHIOPIA", "numcode"=>"231"})
+Spree::Country.create!({"name"=>"Hungary", "iso3"=>"HUN", "iso"=>"HU", "iso_name"=>"HUNGARY", "numcode"=>"348"})
+Spree::Country.create!({"name"=>"Macao", "iso3"=>"MAC", "iso"=>"MO", "iso_name"=>"MACAO", "numcode"=>"446"})
+Spree::Country.create!({"name"=>"New Caledonia", "iso3"=>"NCL", "iso"=>"NC", "iso_name"=>"NEW CALEDONIA", "numcode"=>"540"})
+Spree::Country.create!({"name"=>"Zimbabwe", "iso3"=>"ZWE", "iso"=>"ZW", "iso_name"=>"ZIMBABWE", "numcode"=>"716"})
+Spree::Country.create!({"name"=>"Central African Republic", "iso3"=>"CAF", "iso"=>"CF", "iso_name"=>"CENTRAL AFRICAN REPUBLIC", "numcode"=>"140"})
+Spree::Country.create!({"name"=>"Falkland Islands (Malvinas)", "iso3"=>"FLK", "iso"=>"FK", "iso_name"=>"FALKLAND ISLANDS (MALVINAS)", "numcode"=>"238"})
+Spree::Country.create!({"name"=>"Iceland", "iso3"=>"ISL", "iso"=>"IS", "iso_name"=>"ICELAND", "numcode"=>"352"})
+Spree::Country.create!({"name"=>"Macedonia", "iso3"=>"MKD", "iso"=>"MK", "iso_name"=>"MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF", "numcode"=>"807"})
+Spree::Country.create!({"name"=>"New Zealand", "iso3"=>"NZL", "iso"=>"NZ", "iso_name"=>"NEW ZEALAND", "numcode"=>"554"})
+Spree::Country.create!({"name"=>"Saint Kitts and Nevis", "iso3"=>"KNA", "iso"=>"KN", "iso_name"=>"SAINT KITTS AND NEVIS", "numcode"=>"659"})
+Spree::Country.create!({"name"=>"Serbia", "iso3"=>"SRB", "iso"=>"RS", "iso_name" => "SERBIA", "numcode"=>"999"})
Spree::Config[:default_country_id] = Spree::Country.find_by_name("United States").id
diff --git a/spree_multi_site/db/default/spree/states.rb b/spree_multi_site/db/default/spree/states.rb
index 01c7468b..0a43f780 100644
--- a/spree_multi_site/db/default/spree/states.rb
+++ b/spree_multi_site/db/default/spree/states.rb
@@ -1,57 +1,57 @@
# encoding: utf-8
country = Spree::Country.find_by_name('United States')
-Spree::State.create!({"name"=>"Michigan", "abbr"=>"MI", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"South Dakota", "abbr"=>"SD", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Washington", "abbr"=>"WA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Wisconsin", "abbr"=>"WI", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Arizona", "abbr"=>"AZ", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Illinois", "abbr"=>"IL", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"New Hampshire", "abbr"=>"NH", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"North Carolina", "abbr"=>"NC", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Kansas", "abbr"=>"KS", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Missouri", "abbr"=>"MO", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Arkansas", "abbr"=>"AR", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Nevada", "abbr"=>"NV", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"District of Columbia", "abbr"=>"DC", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Idaho", "abbr"=>"ID", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Nebraska", "abbr"=>"NE", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Pennsylvania", "abbr"=>"PA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Hawaii", "abbr"=>"HI", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Utah", "abbr"=>"UT", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Vermont", "abbr"=>"VT", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Delaware", "abbr"=>"DE", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Rhode Island", "abbr"=>"RI", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Oklahoma", "abbr"=>"OK", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Louisiana", "abbr"=>"LA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Montana", "abbr"=>"MT", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Tennessee", "abbr"=>"TN", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Maryland", "abbr"=>"MD", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Florida", "abbr"=>"FL", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Virginia", "abbr"=>"VA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Minnesota", "abbr"=>"MN", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"New Jersey", "abbr"=>"NJ", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Ohio", "abbr"=>"OH", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"California", "abbr"=>"CA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"North Dakota", "abbr"=>"ND", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Maine", "abbr"=>"ME", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Indiana", "abbr"=>"IN", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Texas", "abbr"=>"TX", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Oregon", "abbr"=>"OR", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Wyoming", "abbr"=>"WY", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Alabama", "abbr"=>"AL", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Iowa", "abbr"=>"IA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Mississippi", "abbr"=>"MS", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Kentucky", "abbr"=>"KY", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"New Mexico", "abbr"=>"NM", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Georgia", "abbr"=>"GA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Colorado", "abbr"=>"CO", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Massachusetts", "abbr"=>"MA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Connecticut", "abbr"=>"CT", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"New York", "abbr"=>"NY", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"South Carolina", "abbr"=>"SC", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"Alaska", "abbr"=>"AK", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"West Virginia", "abbr"=>"WV", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"U.S. Armed Forces – Americas", "abbr"=>"AA", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"U.S. Armed Forces – Europe", "abbr"=>"AE", :country=>country}, :without_protection => true)
-Spree::State.create!({"name"=>"U.S. Armed Forces – Pacific", "abbr"=>"AP", :country=>country}, :without_protection => true)
+Spree::State.create!({"name"=>"Michigan", "abbr"=>"MI", :country=>country})
+Spree::State.create!({"name"=>"South Dakota", "abbr"=>"SD", :country=>country})
+Spree::State.create!({"name"=>"Washington", "abbr"=>"WA", :country=>country})
+Spree::State.create!({"name"=>"Wisconsin", "abbr"=>"WI", :country=>country})
+Spree::State.create!({"name"=>"Arizona", "abbr"=>"AZ", :country=>country})
+Spree::State.create!({"name"=>"Illinois", "abbr"=>"IL", :country=>country})
+Spree::State.create!({"name"=>"New Hampshire", "abbr"=>"NH", :country=>country})
+Spree::State.create!({"name"=>"North Carolina", "abbr"=>"NC", :country=>country})
+Spree::State.create!({"name"=>"Kansas", "abbr"=>"KS", :country=>country})
+Spree::State.create!({"name"=>"Missouri", "abbr"=>"MO", :country=>country})
+Spree::State.create!({"name"=>"Arkansas", "abbr"=>"AR", :country=>country})
+Spree::State.create!({"name"=>"Nevada", "abbr"=>"NV", :country=>country})
+Spree::State.create!({"name"=>"District of Columbia", "abbr"=>"DC", :country=>country})
+Spree::State.create!({"name"=>"Idaho", "abbr"=>"ID", :country=>country})
+Spree::State.create!({"name"=>"Nebraska", "abbr"=>"NE", :country=>country})
+Spree::State.create!({"name"=>"Pennsylvania", "abbr"=>"PA", :country=>country})
+Spree::State.create!({"name"=>"Hawaii", "abbr"=>"HI", :country=>country})
+Spree::State.create!({"name"=>"Utah", "abbr"=>"UT", :country=>country})
+Spree::State.create!({"name"=>"Vermont", "abbr"=>"VT", :country=>country})
+Spree::State.create!({"name"=>"Delaware", "abbr"=>"DE", :country=>country})
+Spree::State.create!({"name"=>"Rhode Island", "abbr"=>"RI", :country=>country})
+Spree::State.create!({"name"=>"Oklahoma", "abbr"=>"OK", :country=>country})
+Spree::State.create!({"name"=>"Louisiana", "abbr"=>"LA", :country=>country})
+Spree::State.create!({"name"=>"Montana", "abbr"=>"MT", :country=>country})
+Spree::State.create!({"name"=>"Tennessee", "abbr"=>"TN", :country=>country})
+Spree::State.create!({"name"=>"Maryland", "abbr"=>"MD", :country=>country})
+Spree::State.create!({"name"=>"Florida", "abbr"=>"FL", :country=>country})
+Spree::State.create!({"name"=>"Virginia", "abbr"=>"VA", :country=>country})
+Spree::State.create!({"name"=>"Minnesota", "abbr"=>"MN", :country=>country})
+Spree::State.create!({"name"=>"New Jersey", "abbr"=>"NJ", :country=>country})
+Spree::State.create!({"name"=>"Ohio", "abbr"=>"OH", :country=>country})
+Spree::State.create!({"name"=>"California", "abbr"=>"CA", :country=>country})
+Spree::State.create!({"name"=>"North Dakota", "abbr"=>"ND", :country=>country})
+Spree::State.create!({"name"=>"Maine", "abbr"=>"ME", :country=>country})
+Spree::State.create!({"name"=>"Indiana", "abbr"=>"IN", :country=>country})
+Spree::State.create!({"name"=>"Texas", "abbr"=>"TX", :country=>country})
+Spree::State.create!({"name"=>"Oregon", "abbr"=>"OR", :country=>country})
+Spree::State.create!({"name"=>"Wyoming", "abbr"=>"WY", :country=>country})
+Spree::State.create!({"name"=>"Alabama", "abbr"=>"AL", :country=>country})
+Spree::State.create!({"name"=>"Iowa", "abbr"=>"IA", :country=>country})
+Spree::State.create!({"name"=>"Mississippi", "abbr"=>"MS", :country=>country})
+Spree::State.create!({"name"=>"Kentucky", "abbr"=>"KY", :country=>country})
+Spree::State.create!({"name"=>"New Mexico", "abbr"=>"NM", :country=>country})
+Spree::State.create!({"name"=>"Georgia", "abbr"=>"GA", :country=>country})
+Spree::State.create!({"name"=>"Colorado", "abbr"=>"CO", :country=>country})
+Spree::State.create!({"name"=>"Massachusetts", "abbr"=>"MA", :country=>country})
+Spree::State.create!({"name"=>"Connecticut", "abbr"=>"CT", :country=>country})
+Spree::State.create!({"name"=>"New York", "abbr"=>"NY", :country=>country})
+Spree::State.create!({"name"=>"South Carolina", "abbr"=>"SC", :country=>country})
+Spree::State.create!({"name"=>"Alaska", "abbr"=>"AK", :country=>country})
+Spree::State.create!({"name"=>"West Virginia", "abbr"=>"WV", :country=>country})
+Spree::State.create!({"name"=>"U.S. Armed Forces – Americas", "abbr"=>"AA", :country=>country})
+Spree::State.create!({"name"=>"U.S. Armed Forces – Europe", "abbr"=>"AE", :country=>country})
+Spree::State.create!({"name"=>"U.S. Armed Forces – Pacific", "abbr"=>"AP", :country=>country})
diff --git a/spree_multi_site/db/fake_order1.2.0/spree/payments.rb b/spree_multi_site/db/fake_order1.2.0/spree/payments.rb
index 68d8c63b..4ad79cc0 100644
--- a/spree_multi_site/db/fake_order1.2.0/spree/payments.rb
+++ b/spree_multi_site/db/fake_order1.2.0/spree/payments.rb
@@ -11,13 +11,13 @@ def self.current
creditcard = Spree::CreditCard.create({:cc_type => 'visa', :month => 12, :year => 2014, :last_digits => '1111',
:first_name => 'Sean', :last_name => 'Schofield',
- :gateway_customer_profile_id => 'BGS-1234'}, :without_protection => true)
+ :gateway_customer_profile_id => 'BGS-1234'})
Spree::Order.all.each_with_index do |order,index|
printf "\rProcessing order #{index}"
STDOUT.flush
order.update!
- payment = order.payments.create({:amount => order.total, :payment_method => method}, :without_protection => true) # :source => creditcard.clone,
+ payment = order.payments.create({:amount => order.total, :payment_method => method}) # :source => creditcard.clone,
payment.update_attributes_without_callbacks({
:state => 'pending',
:response_code => '12345'
diff --git a/spree_multi_site/db/firstshop/users.rb b/spree_multi_site/db/firstshop/users.rb
deleted file mode 100644
index da550829..00000000
--- a/spree_multi_site/db/firstshop/users.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-#copy from spree_auth_devise/db/defaults/users
-require 'highline/import'
-
-# see last line where we create an admin if there is none, asking for email and password
-def prompt_for_admin_password
- if ENV['ADMIN_PASSWORD']
- password = ENV['ADMIN_PASSWORD'].dup
- say "Admin Password #{password}"
- else
- password = ask('Password [spree123]: ') do |q|
- q.echo = false
- q.validate = /^(|.{5,40})$/
- q.responses[:not_valid] = 'Invalid password. Must be at least 5 characters long.'
- q.whitespace = :strip
- end
- password = 'spree123' if password.blank?
- end
-
- password
-end
-
-def prompt_for_admin_email
- if ENV['ADMIN_EMAIL']
- email = ENV['ADMIN_EMAIL'].dup
- say "Admin User #{email}"
- else
- email = ask('Email [spree@example.com]: ') do |q|
- q.echo = true
- q.whitespace = :strip
- end
- email = 'spree@example.com' if email.blank?
- end
-
- email
-end
-
-def create_admin_user
- if ENV['AUTO_ACCEPT']
- password = 'spree123'
- email = 'spree@example.com'
- else
- puts 'Create the admin user (press enter for defaults).'
- #name = prompt_for_admin_name unless name
- email = prompt_for_admin_email
- password = prompt_for_admin_password
- end
- attributes = {
- :password => password,
- :password_confirmation => password,
- :email => email,
- :login => email
- }
-
-# load 'spree/user.rb'
-
- if Spree.user_class.find_by_email(email)
- say "\nWARNING: There is already a user with the email: #{email}, so no account changes were made. If you wish to create an additional admin user, please run rake db:admin:create again with a different email.\n\n"
- else
- admin = Spree.user_class.create(attributes,:without_protection => true)
- # create an admin role and and assign the admin user to that role
- role = Spree::Role.find_or_create_by_name 'admin'
- admin.spree_roles << role
- admin.save
- end
-end
-
-unless Spree.user_class.exists?
- create_admin_user
-else
- puts 'Admin user has already been previously created.'
- if agree('Would you like to create a new admin user? (yes/no)')
- create_admin_user
- else
- puts 'No admin user created.'
- end
-end
-
diff --git a/spree_multi_site/db/migrate/20120415215214_create_sites.rb b/spree_multi_site/db/migrate/20120415215214_create_sites.rb
index d1ef0f79..24e4547b 100644
--- a/spree_multi_site/db/migrate/20120415215214_create_sites.rb
+++ b/spree_multi_site/db/migrate/20120415215214_create_sites.rb
@@ -1,5 +1,8 @@
class CreateSites < ActiveRecord::Migration
def self.up
+ # disable default site during migration,
+ # or default :site cause error before site_id added.
+ Spree::MultiSiteSystem.multi_site_context = 'admin_sites'
create_table :spree_sites do |t|
t.string :name
t.string :domain
diff --git a/spree_multi_site/db/migrate/20150108135747_associate_store_with_site.rb b/spree_multi_site/db/migrate/20150108135747_associate_store_with_site.rb
new file mode 100644
index 00000000..2631ee99
--- /dev/null
+++ b/spree_multi_site/db/migrate/20150108135747_associate_store_with_site.rb
@@ -0,0 +1,12 @@
+class AssociateStoreWithSite < ActiveRecord::Migration
+ def change
+ add_column :spree_stores, :site_id, :integer, :default=>0
+ Spree::Site.all.each{|site|
+ if site.stores.blank?
+ site.stores.create!( url: site.domain, name: site.name, code: site.short_name )
+ end
+ }
+ end
+
+
+end
diff --git a/spree_multi_site/db/migrate/20150316135747_move_app_configuration_to_site.rb b/spree_multi_site/db/migrate/20150316135747_move_app_configuration_to_site.rb
new file mode 100644
index 00000000..39a50ad6
--- /dev/null
+++ b/spree_multi_site/db/migrate/20150316135747_move_app_configuration_to_site.rb
@@ -0,0 +1,18 @@
+class MoveAppConfigurationToSite < ActiveRecord::Migration
+ def change
+ add_column :spree_sites, :allow_ssl_in_production, :boolean, :default=>false
+ add_column :spree_sites, :allow_ssl_in_development_and_test, :boolean, :default=>false
+ add_column :spree_sites, :allow_ssl_in_staging, :boolean, :default=>false
+ add_column :spree_sites, :check_for_spree_alerts, :boolean, :default=>false
+
+ add_column :spree_sites, :display_currency, :boolean, :default=>false
+ add_column :spree_sites, :hide_cents, :boolean, :default=>false
+
+ add_column :spree_sites, :currency, :string, :default=>'CNY'
+ add_column :spree_sites, :currency_symbol_position, :string, :default=>"before"
+ add_column :spree_sites, :currency_decimal_mark, :string, :default=>"."
+ add_column :spree_sites, :currency_thousands_separator, :string, :default=>","
+ end
+
+
+end
diff --git a/spree_multi_site/db/sample1.2.0/spree/inventory_units.rb b/spree_multi_site/db/sample1.2.0/spree/inventory_units.rb
index c2efa2c1..cd624871 100644
--- a/spree_multi_site/db/sample1.2.0/spree/inventory_units.rb
+++ b/spree_multi_site/db/sample1.2.0/spree/inventory_units.rb
@@ -1,4 +1,4 @@
# create the inventory units associated with the line item (we need to do this after the fixture b/c quantity is random)
Spree::LineItem.all.each do |li|
- li.quantity.times { li.order.inventory_units.create({:variant => li.variant, :state => 'sold', :shipment => li.order.shipment}, :without_protection => true) }
+ li.quantity.times { li.order.inventory_units.create({:variant => li.variant, :state => 'sold', :shipment => li.order.shipment}) }
end
diff --git a/spree_multi_site/db/samples/addresses.rb b/spree_multi_site/db/samples/addresses.rb
index 7899c5f8..a7b9070d 100644
--- a/spree_multi_site/db/samples/addresses.rb
+++ b/spree_multi_site/db/samples/addresses.rb
@@ -12,7 +12,7 @@
:zipcode => 16804,
:country => united_states,
:phone => Faker::PhoneNumber.phone_number
-}, :without_protection => true)
+})
#Shipping address
Spree::Address.create!({
@@ -25,4 +25,4 @@
:zipcode => 16804,
:country => united_states,
:phone => Faker::PhoneNumber.phone_number
-}, :without_protection => true)
+})
diff --git a/spree_multi_site/db/samples/adjustments.rb b/spree_multi_site/db/samples/adjustments.rb
index e635bae0..b802e236 100644
--- a/spree_multi_site/db/samples/adjustments.rb
+++ b/spree_multi_site/db/samples/adjustments.rb
@@ -10,7 +10,7 @@
:label => "Tax",
:state => "open",
:mandatory => true
-}, :without_protection => true)
+})
last_order.adjustments.create!({
:amount => 0,
@@ -19,7 +19,7 @@
:label => "Tax",
:state => "open",
:mandatory => true
-}, :without_protection => true)
+})
first_order.adjustments.create!({
:amount => 0,
@@ -28,7 +28,7 @@
:label => "Shipping",
:state => "finalized",
:mandatory => true
-}, :without_protection => true)
+})
last_order.adjustments.create!({
:amount => 0,
@@ -37,4 +37,4 @@
:label => "Shipping",
:state => "finalized",
:mandatory => true
-}, :without_protection => true)
+})
diff --git a/spree_multi_site/db/samples/option_types.rb b/spree_multi_site/db/samples/option_types.rb
index 0e15384f..f862173f 100644
--- a/spree_multi_site/db/samples/option_types.rb
+++ b/spree_multi_site/db/samples/option_types.rb
@@ -12,5 +12,5 @@
]
option_types.each do |option_type_attrs|
- Spree::OptionType.create!(option_type_attrs, :without_protection => true)
+ Spree::OptionType.create!(option_type_attrs)
end
diff --git a/spree_multi_site/db/samples/option_values.rb b/spree_multi_site/db/samples/option_values.rb
index 36c87cba..34aaac8b 100644
--- a/spree_multi_site/db/samples/option_values.rb
+++ b/spree_multi_site/db/samples/option_values.rb
@@ -49,5 +49,5 @@
]
option_values.each do |option_value_attrs|
- Spree::OptionValue.create!(option_values, :without_protection => true)
+ Spree::OptionValue.create!(option_values)
end
diff --git a/spree_multi_site/db/samples/orders.rb b/spree_multi_site/db/samples/orders.rb
index 08515db1..c0f143a9 100644
--- a/spree_multi_site/db/samples/orders.rb
+++ b/spree_multi_site/db/samples/orders.rb
@@ -9,7 +9,7 @@
:total => 301.90,
:shipping_address => Spree::Address.first,
:billing_address => Spree::Address.last
-}, :without_protection => true)
+})
orders << Spree::Order.create!({
:number => "R987654321",
@@ -19,19 +19,19 @@
:total => 31.90,
:shipping_address => Spree::Address.first,
:billing_address => Spree::Address.last
-}, :without_protection => true)
+})
orders[0].line_items.create!({
:variant => Spree::Product.find_by_name!("Ruby on Rails Tote").master,
:quantity => 1,
:price => 15.99
-}, :without_protection => true)
+})
orders[1].line_items.create!({
:variant => Spree::Product.find_by_name!("Ruby on Rails Bag").master,
:quantity => 1,
:price => 22.99
-}, :without_protection => true)
+})
orders.each(&:create_proposed_shipments)
diff --git a/spree_multi_site/db/samples/payments.rb b/spree_multi_site/db/samples/payments.rb
index 66992f19..a61d1795 100644
--- a/spree_multi_site/db/samples/payments.rb
+++ b/spree_multi_site/db/samples/payments.rb
@@ -14,11 +14,11 @@ def self.current
creditcard = Spree::CreditCard.create({ :cc_type => 'visa', :month => 12, :year => 2014, :last_digits => '1111',
:first_name => 'Sean', :last_name => 'Schofield',
- :gateway_customer_profile_id => 'BGS-1234' }, :without_protection => true)
+ :gateway_customer_profile_id => 'BGS-1234' })
Spree::Order.all.each_with_index do |order, index|
order.update!
- payment = order.payments.create!({ :amount => order.total, :source => creditcard.clone, :payment_method => method }, :without_protection => true)
+ payment = order.payments.create!({ :amount => order.total, :source => creditcard.clone, :payment_method => method })
payment.update_attributes_without_callbacks({
:state => 'pending',
:response_code => '12345'
diff --git a/spree_multi_site/db/samples/products.rb b/spree_multi_site/db/samples/products.rb
index c7d53d55..e2e11457 100644
--- a/spree_multi_site/db/samples/products.rb
+++ b/spree_multi_site/db/samples/products.rb
@@ -126,7 +126,7 @@
Spree::Config[:currency] = "USD"
default_shipping_category = Spree::ShippingCategory.find_by_name!("Default Shipping")
- product = Spree::Product.create!(default_attrs.merge(product_attrs), :without_protection => true)
+ product = Spree::Product.create!(default_attrs.merge(product_attrs))
Spree::Config[:currency] = "EUR"
product.reload
product.price = eur_price
diff --git a/spree_multi_site/db/samples/shipping_methods.rb b/spree_multi_site/db/samples/shipping_methods.rb
index f099c5b2..efa94bd8 100644
--- a/spree_multi_site/db/samples/shipping_methods.rb
+++ b/spree_multi_site/db/samples/shipping_methods.rb
@@ -7,7 +7,7 @@
end
europe_vat = Spree::Zone.find_by_name!("EU_VAT")
-shipping_category = Spree::ShippingCategory.find_or_create_by_name!('Default')
+shipping_category = Spree::ShippingCategory.find_or_create_by!( name: 'Default')
shipping_methods = [
{
@@ -37,7 +37,7 @@
]
shipping_methods.each do |shipping_method_attrs|
- Spree::ShippingMethod.create!(shipping_method_attrs, :without_protection => true)
+ Spree::ShippingMethod.create!(shipping_method_attrs)
end
{
diff --git a/spree_multi_site/db/samples/taxons.rb b/spree_multi_site/db/samples/taxons.rb
index f5942da6..4233d100 100644
--- a/spree_multi_site/db/samples/taxons.rb
+++ b/spree_multi_site/db/samples/taxons.rb
@@ -116,6 +116,6 @@
taxons.each do |taxon_attrs|
if taxon_attrs[:parent]
taxon_attrs[:parent] = Spree::Taxon.find_by_name!(taxon_attrs[:parent])
- Spree::Taxon.create!(taxon_attrs, :without_protection => true)
+ Spree::Taxon.create!(taxon_attrs)
end
end
diff --git a/spree_multi_site/db/samples/variants.rb b/spree_multi_site/db/samples/variants.rb
index 8c06ad5e..75a7f3c0 100644
--- a/spree_multi_site/db/samples/variants.rb
+++ b/spree_multi_site/db/samples/variants.rb
@@ -160,7 +160,7 @@
}
variants.each do |variant_attrs|
- Spree::Variant.create!(variant_attrs, :without_protection => true)
+ Spree::Variant.create!(variant_attrs)
end
masters.each do |product, variant_attrs|
diff --git a/spree_multi_site/db/seeds.rb b/spree_multi_site/db/seeds.rb
index 92c8d14f..e69de29b 100644
--- a/spree_multi_site/db/seeds.rb
+++ b/spree_multi_site/db/seeds.rb
@@ -1,10 +0,0 @@
-
-default_path = File.join(SpreeMultiSite::Config.seed_dir, 'default')
-# This first resets the task's already_invoked state, allowing the task to then be executed again, dependencies and all:
-Rake::Task['db:load_dir'].reenable
-Rake::Task['db:load_dir'].invoke(default_path)
-
-# For easy to test, load first shop while load seeds.
-#default_path = File.join(SpreeMultiSite::Config.seed_dir, 'firstshop')
-#Rake::Task['db:load_dir'].reenable
-#Rake::Task['db:load_dir'].invoke(default_path)
\ No newline at end of file
diff --git a/spree_multi_site/lib/spree_multi_site.rb b/spree_multi_site/lib/spree_multi_site.rb
index c8628e96..c9df5851 100644
--- a/spree_multi_site/lib/spree_multi_site.rb
+++ b/spree_multi_site/lib/spree_multi_site.rb
@@ -6,3 +6,11 @@
require 'spree_multi_site/middleware'
require 'spree_multi_site/environment'
require 'spree_multi_site/permitted_attributes_for_site'
+require 'spree_multi_site/paperclip_aliyun_oss_helper'
+
+
+module SpreeMultiSite
+ # these keys are alipay oss folder names
+ AttachmentClassEnum = Struct.new(:spree_taxon, :spree_post, :spree_image, :ckeditor_picture, :ckeditor_file, :spree_template_file, :spree_post_files )\
+ ['Spree::Taxon','Spree::Post','Spree::Image', 'Ckeditor::Picture','Ckeditor::AttachmentFile', 'Spree::TemplateFile','Spree::PostFile']
+end
diff --git a/spree_multi_site/lib/spree_multi_site/custom_fixtures.rb b/spree_multi_site/lib/spree_multi_site/custom_fixtures.rb
index 686fb641..e69de29b 100644
--- a/spree_multi_site/lib/spree_multi_site/custom_fixtures.rb
+++ b/spree_multi_site/lib/spree_multi_site/custom_fixtures.rb
@@ -1,254 +0,0 @@
-require 'active_record/fixtures'
-
-module SpreeMultiSite
-
- class Fixtures < ActiveRecord::Fixtures
-
- @@all_cached_models = Hash.new { |h,k| h[k] = {} }
- #handle has_and_belongs_to_many join table , key is association_reflection
- @@all_cached_habtm_rows = Hash.new { |h,k| h[k] = [] }
-
- def self.cache_for_table(table_name)
- @@all_cached_models[table_name]
- end
- def self.cache_models(table_name, models_map)
- cache_for_table(table_name).update(models_map)
- end
- def self.cache_habtm_rows(habtm_association, rows)
- @@all_cached_habtm_rows[habtm_association].concat rows
- end
- # Since create sample for each site, original key generating in Fixtures
- # would not work. We should load fixture in proper order, all created model
- # instances are cached, then the right foreign id could be set while create
- # model instance which contains belongs_to association.
- # ex. assets belongs_to variant, variant should be loaded before assets.
- # Replace this method to prevent the table being emptied on each call. Needed
- # when both core & auth have user fixtures, see below for code commented out.
- #
- def self.create_fixtures(fixtures_directory, table_names, class_names = {})
- table_names = [table_names].flatten.map { |n| n.to_s }
- if class_names.empty?
- table_names.each { |n|
- class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/')
- }
- end
- # FIXME: Apparently JK uses this.
- connection = block_given? ? yield : ActiveRecord::Base.connection
-
- files_to_read = table_names.reject { |table_name|
- fixture_is_cached?(connection, table_name)
- }
-
- unless files_to_read.empty?
- connection.disable_referential_integrity do
- fixtures_map = {}
-
- fixture_files = files_to_read.map do |path|
- table_name = path.tr '/', '_'
-
- fixtures_map[path] = self.new(
- connection,
- table_name,
- class_names[table_name.to_sym] || table_name.classify,
- ::File.join(fixtures_directory, path))
- end
-
- all_loaded_fixtures.update(fixtures_map)
-
- connection.transaction(:requires_new => true) do
- fixture_files.each do |ff|
- models_map = {}
- conn = ff.model_class.respond_to?(:connection) ? ff.model_class.connection : connection
- client_connection = conn.instance_variable_get(:@connection)
- table_rows = ff.table_rows
- model_class= ff.model_class
- # REMOVED BY SPREE
- # table_rows.keys.each do |table|
- # conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
- # end
- habtm_association = model_class.reflect_on_all_associations(:has_and_belongs_to_many).first
-
- table_rows.each do |table_name,rows|
- #handle join table separately, assume one model only have one HABTM association
- next if habtm_association.present? and table_name == habtm_association.options[:join_table]
- #correct it after create all objects.
- rows.each do |row|
- #conn.insert_fixture(row, table_name)
- primary_key = ff.identify_primary_key(row)
- row.delete( "id" )
-
- if row['parent_id'].present? # nested set, taxon
- parent_key = ActiveRecord::Fixtures.identify(row['parent_id'])
- row['parent_id'] = models_map[parent_key]
- if row['parent_id']==0
-Rails.logger.debug "model_class=#{ff.model_class},primary_key=#{primary_key},table_name=#{table_name},parent_id=#{row['parent_id']}"
- raise "can not find parent reference: #{row.inspect},parent_key=#{parent_key},models_map=#{models_map.inspect}"
- end
- end
-Rails.logger.debug "model_class=#{ff.model_class},primary_key=#{primary_key},table_name=#{table_name},parent_id=#{row['parent_id']}"
- model_instance = model_class.new()
- model_instance.assign_attributes(row,:without_protection => true)
- if table_name=~/taxonomies|tax_rates|shipping_methods|products|users|shipments/
- # taxonomies has :after_save to create taxon root, insert_fixture would avoid that.
- # tax_rate has one calculator, calculator belongs to tax_rate,
- # we have to create tax_rate before calculator since calculator require tax_rate.id
- # tax_rate has calculator presence validation, so set validate=>false here. so does shipping_method
- # TODO for product price validation
- #model_instance.save!(:validate => false), it may not work,
- conn.insert_fixture(row, table_name)
- models_map[primary_key] = client_connection.last_id
- else
- model_instance.save!
- models_map[primary_key] = model_instance.id
- end
-#puts "primary_key=#{primary_key},model_instance=#{model_instance.inspect}"
- end
- end
- #create HABTM join talbe record with real foreign_key and mock association_foreign_key
- #because association may not be created yet
- #correct it after load all fixtures
- if habtm_association.present?
- habtm_rows =table_rows[habtm_association.options[:join_table]]
-#Rails.logger.debug "cache habtm_association=#{habtm_association.options[:join_table]},#{habtm_rows.length}---------------------"
- cache_habtm_rows(habtm_association, habtm_rows)
- end
- cache_models(ff.table_name, models_map)
- end
-
- # Cap primary key sequences to max(pk).
- if connection.respond_to?(:reset_pk_sequence!)
- table_names.each do |table_name|
- connection.reset_pk_sequence!(table_name.tr('/', '_'))
- end
- end
- end
-
- cache_fixtures(connection, fixtures_map)
- end
- end
- cached_fixtures(connection, table_names)
- end
-
- #we have to create join table record after normal fixtures created.
- def self.create_habtm_records
- @@all_cached_habtm_rows.each_pair{|habtm_association, rows|
- foreign_models_map = cache_for_table(habtm_association.active_record.table_name)
- association_foreign_models_map = cache_for_table(habtm_association.klass.table_name)
- association_klass = habtm_association.klass
- rows.each{|row|
- #set real foreign_key from created models
-# puts "original_row=#{row.inspect},\nmodel_class=#{association_klass}"
- row[ habtm_association.foreign_key ] = foreign_models_map[ row[ habtm_association.foreign_key ]]
- row[ habtm_association.association_foreign_key ] = association_foreign_models_map[ row[ habtm_association.association_foreign_key ]]
-if row[ habtm_association.foreign_key ].nil? or row[ habtm_association.association_foreign_key ].nil?
- #puts "row[#{habtm_association.foreign_key}]=#{row[ habtm_association.foreign_key ]},#{foreign_models_map.length}"
- #puts "row[#{habtm_association.association_foreign_key}]=#{row[ habtm_association.association_foreign_key ]},#{association_foreign_models_map.keys.inspect} "
- raise "can not find foreign reference"
-end
- association_klass.connection.insert_fixture(row, habtm_association.options[:join_table])
- }
- }
- @@all_cached_habtm_rows.clear
- end
-
-
- # Replace this method to handle associations in yml.
- # Return a hash of rows to be inserted. The key is the table, the value is
- # a list of rows to insert to that table.
- def table_rows
- now = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
- now = now.to_s(:db)
- site_column = 'site_id'
- # allow a standard key to be used for doing defaults in YAML
- fixtures.delete('DEFAULTS')
-
- # track any join tables we need to insert later
- rows = Hash.new { |h,table| h[table] = [] }
-
- rows[table_name] = fixtures.map do |label, fixture|
- row = fixture.to_hash
-
- if model_class && model_class < ActiveRecord::Base
- # fill in timestamp columns if they aren't specified and the model is set to record_timestamps
- if model_class.record_timestamps
- timestamp_column_names.each do |name|
- row[name] = now unless row.key?(name)
- end
- end
- #set current site id if they aren't specified
- if model_class.column_names.include? site_column
- row[site_column] = Spree::Site.current.id unless row.key?(site_column)
- end
- # interpolate the fixture label
- row.each do |key, value|
- row[key] = label if value == "$LABEL"
- end
-
- # generate a primary key if necessary
- if has_primary_key_column? && !row.include?(primary_key_name)
-#Rails.logger.debug "label=#{label},identify=#{ActiveRecord::Fixtures.identify(label)}"
- row[primary_key_name] = ActiveRecord::Fixtures.identify(label)
- end
-
- # If STI is used, find the correct subclass for association reflection
- reflection_class =
- if row.include?(inheritance_column_name)
- row[inheritance_column_name].constantize rescue model_class
- else
- model_class
- end
-
- reflection_class.reflect_on_all_associations.each do |association|
- case association.macro
- when :belongs_to
- # Do not replace association name with association foreign key if they are named the same
- fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
-#puts "association.name=#{association.name}, "
- if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
-
- if association.options[:polymorphic]
- if value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
- # support polymorphic belongs_to as "label (Type)"
- row[association.foreign_type] = $1
- end
- #puts "cached_table=#{self.class.cache_for_table(row[association.foreign_type].constantize.table_name).inspect}"
- #puts "row[association.foreign_type].constantize.table_name=#{row[association.foreign_type].constantize.table_name}"
- row[fk_name] = self.class.cache_for_table(row[association.foreign_type].constantize.table_name)[ActiveRecord::Fixtures.identify(value)]
- else
- row[fk_name] = self.class.cache_for_table(association.klass.table_name)[ActiveRecord::Fixtures.identify(value)]
- end
- if row[fk_name].nil?
- puts "looking for #{table_name},row=#{row.inspect}"
- #puts "self.class.cache_for_table('spree_variants')=#{self.class.cache_for_table('spree_variants').keys.inspect}"
- puts "@@all_cached_models=#{@@all_cached_models.keys.inspect}"
- raise "can not find foreign reference: #{reflection_class}.#{fk_name}"
- end
- #row[fk_name] = ActiveRecord::Fixtures.identify(value)
- end
- when :has_and_belongs_to_many
- if (targets = row.delete(association.name.to_s))
- targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
- table_name = association.options[:join_table]
- rows[table_name].concat targets.map { |target|
-# Rails.logger.debug "target=#{target},#{ActiveRecord::Fixtures.identify(target)}"
- { association.foreign_key => row[primary_key_name],
- association.association_foreign_key => ActiveRecord::Fixtures.identify(target) }
- }
- end
- end
- end
- end
-
- row
- end
- rows
- end
-
- # generate a primary key if necessary
- def identify_primary_key(row)
- # Rails.logger.debug "primary_key_name=#{primary_key_name},val=#{row[primary_key_name]}, has_primary_key_column?=#{has_primary_key_column?} "
- row[primary_key_name] if has_primary_key_column? && row.include?(primary_key_name)
- end
- end
-
-end
\ No newline at end of file
diff --git a/spree_multi_site/lib/spree_multi_site/engine.rb b/spree_multi_site/lib/spree_multi_site/engine.rb
index 827868d2..bb736e12 100644
--- a/spree_multi_site/lib/spree_multi_site/engine.rb
+++ b/spree_multi_site/lib/spree_multi_site/engine.rb
@@ -9,41 +9,41 @@ class Engine < Rails::Engine
g.test_framework :rspec
end
- initializer "spree.multisite.environment", :before => "spree.environment" do |app|
+ initializer "spree.multisite.environment", :before => :load_environment_config do |app|
app.config.spree_multi_site = SpreeMultiSite::Environment.new
- SpreeMultiSite::Config = app.config.spree_multi_site.preferences #legacy access
- app.config.spree_multi_site.site_scope_required_classes_from_other_gems = []
-
+ #SpreeMultiSite::Config = app.config.spree_multi_site.preferences
+ #app.config.spree_multi_site.site_scope_required_classes_from_other_gems = []
+ # use site.attributes instead
# preferences contains two kind of records
# 1. override AppConfiguration's default value.
- # a. some preferences in AppConfiguration are for whole application, so override record site_id=0, like seed_dir
+ # a. some preferences in AppConfiguration are for whole application, so override record site_id=0
# this kind preference's description start with 'global'
- # b. some preferences are for one site, so override record site_id>0, like :default_seo_title
- #
- # 2. preference in other models, site_id>0, key contain model instance id.
-
- #hack this class before :load_config_initializers, Spree::Config is using while initialize
- Spree::AppConfiguration.class_eval do
- #replace original :preference_cache_key, add current_site.id as part of key
- #fix error Duplicate entry 'spree/app_configuration/site_url/1'
- def preference_cache_key(name)
- global_preferences = ["seed_dir"]
- some_key = nil
- if global_preferences.include? name#preference_description( name ).to_s.start_with? "global_"
- some_key =[self.class.name, name, 0].join('::').underscore
- else
- some_key =[self.class.name, name, Spree::Site.current.id].join('::').underscore
- end
- some_key
- end
- end
+ # b. some preferences are for one site, so override record site_id>0, like :default_seo_title
+ #
+ # 2. preference in other models, site_id>0, key contain model instance id.
+
+ #hack this class before :load_config_initializers, Spree::Config is using while initialize
+ #Spree::AppConfiguration.class_eval do
+ # #replace original :preference_cache_key, add current_site.id as part of key
+ # #fix error Duplicate entry 'spree/app_configuration/site_url/1'
+ # def preference_cache_key(name)
+ # global_preferences = []
+ # some_key = nil
+ # if global_preferences.include? name#preference_description( name ).to_s.start_with? "global_"
+ # some_key =[self.class.name, name, 0].join('::').underscore
+ # else
+ # some_key =[self.class.name, name, Spree::Site.current.id].join('::').underscore
+ # end
+ # some_key
+ # end
+ #end
end
-
+
initializer "spree.multisite.add_middleware" do |app|
app.middleware.use SpreeMultiSite::Middleware
- end
-
+ end
+
def self.activate
Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c|
Rails.configuration.cache_classes ? require(c) : load(c)
@@ -51,9 +51,9 @@ def self.activate
end
#spree_abc require #{config.root}/app/mailers
config.autoload_paths += %W(#{config.root}/app/models/spree #{config.root}/app/jobs)
- #Defines generic callbacks to run before after_initialize.
+ #Defines generic callbacks to run before after_initialize.
config.to_prepare &method(:activate).to_proc
-
-
+
+
end
end
diff --git a/spree_multi_site/lib/spree_multi_site/environment.rb b/spree_multi_site/lib/spree_multi_site/environment.rb
index 0b8a3077..d80004ef 100644
--- a/spree_multi_site/lib/spree_multi_site/environment.rb
+++ b/spree_multi_site/lib/spree_multi_site/environment.rb
@@ -4,12 +4,17 @@ class Environment
include Spree::Core::EnvironmentExtension
attr_accessor :site_scope_required_classes_from_other_gems, :site_scope_required_classes_with_image_from_other_gems, :preferences
+ # system_top_domain is required, in middleware, we compare it with request.host,
+ # it tell us to initialize site by short_name or domain.
+ attr_accessor :system_top_domain
def initialize
- @preferences = Spree::MultiSiteConfiguration.new
+ #@preferences = Spree::MultiSiteConfiguration.new
+ #"Spree.user_class MUST be a String or Symbol object, not a Class object."
+ # it has to be in Environment, it vary in env
+ @system_top_domain = "dalianshops.com"
@site_scope_required_classes_from_other_gems = []
- @site_scope_required_classes_with_image_from_other_gems ={}
+ @site_scope_required_classes_with_image_from_other_gems = []
end
end
end
-
diff --git a/spree_multi_site/lib/spree_multi_site/middleware.rb b/spree_multi_site/lib/spree_multi_site/middleware.rb
index d0d59e76..a84fbc32 100644
--- a/spree_multi_site/lib/spree_multi_site/middleware.rb
+++ b/spree_multi_site/lib/spree_multi_site/middleware.rb
@@ -7,39 +7,40 @@ def initialize(app)
def call(env)
request = Rack::Request.new(env)
- unless request.path.include?('.') # ignore .css, .js, .img
- site = get_site_from_request(request)
- Spree::Site.current = ( site || Spree::Site.first)
+ resource_extension = request.path[/\.[\w]+/]
+ # ignore .css, .js, .img, except .json
+ if resource_extension.nil? || resource_extension=='.json'
+ Spree::Store.current = get_store_from_request(request)
end
status, headers, body = @app.call(env)
[status, headers, body]
end
- def get_site_from_request( request )
- site = nil
- # test.david.com => www.david.com/?n=test.david.com
+ def get_store_from_request( request )
+ # test.david.com => localhost:8080/?n=test.david.com
# our domain is www.dalianshops.com
- if request.params['n'].try(:split,'.') # support short_name.dalianshops.com
- short_name = request.params['n'].split('.').first
- site = Spree::Site.find_by_short_name(short_name)
- end
-
- if site.blank?
- # support domain, ex. www.david.com
- # TODO should use public_suffix_service handle example.com.cn
- site = Spree::Site.find_by_domain(request.host)
- end
- if(( Rails.env !~ /prduction/ ) && ( site.blank? ) )
+ store = Spree::Store.by_domain( request.host )
+
+ # support domain, ex. www.david.com
+ # apache rewrite test.david.com => localhost:8080/?n=test.david.com, request.host is 'test.david.com'
+ # TODO should use public_suffix_service handle example.com.cn
+
+ if(( Rails.env !~ /prduction/ ) && ( store.blank? ) )
# for development or test, enable get site from cookie
- #Rails.logger.debug "request.cookie_jar=#{request.cookie_jar.inspect},#{request.cookie_jar[:abc_development_domain]},#{request.cookie_jar['abc_development_domain']}"
- #string and symbol both OK. cookie.domain should be exactly same as host, www.domain.com != domain.com
- cookie_domain = request.cookies['_dalianshops_domain']
- if cookie_domain.present?
- site = Spree::Site.find_by_domain( cookie_domain )
- end
+ # string and symbol both OK. cookie.domain should be exactly same as host, www.domain.com != domain.com
+ # disable domain, some site have no domain, short_name always exists.
+ # we can not easily modify cookies except firefox, we'll add default_site for debug page on other browser.
+ # we could set default site for missing site as well.
+ short_name = request.cookies['_dalianshops_short_name']
+ if short_name.present?
+ store = Spree::Store.unscoped.find_by_code( short_name )
+ end
+ #support request.host for development
+ store ||= Spree::Store.default
+
end
- site
+ store
end
end
diff --git a/spree_multi_site/lib/spree_multi_site/multi_site_system.rb b/spree_multi_site/lib/spree_multi_site/multi_site_system.rb
index 82315578..0a947033 100644
--- a/spree_multi_site/lib/spree_multi_site/multi_site_system.rb
+++ b/spree_multi_site/lib/spree_multi_site/multi_site_system.rb
@@ -1,63 +1,59 @@
# Spree::BaseController.class_eval would not work
# Spree::UserSessionsController derive from Devise::SessionsController, it included Spree::Core::ControllerHelpers
-require 'spree/core/controller_helpers/common'
-class<< Spree::Core::ControllerHelpers::Common
- #def included_with_site_support(receiver)
- # receiver.send :include, Spree::MultiSiteSystem
- # included_without_site_support(receiver)
- # #receiver.prepend_before_filter :get_site #initialize site before authorize user in Spree::UserSessionsController.create
- #end
- #alias_method_chain :included, :site_support
-
- #Spree::Api::BaseController would include MultiSiteSystem, get_layout should not in it.
- #override original methods
- def get_layout
- Spree::Site.current.layout.present? ? Spree::Site.current.layout : Spree::Config[:layout]
- end
-end
-
+#require 'spree/core/controller_helpers/common'
+#class<< Spree::Core::ControllerHelpers::Common
+# #Spree::Api::BaseController would include MultiSiteSystem, get_layout should not in it.
+# #override original methods
+# def get_layout
+# Spree::Site.current.layout.present? ? Spree::Site.current.layout : Spree::Config[:layout]
+# end
+#end
+
module Spree
module MultiSiteSystem
extend ActiveSupport::Concern
mattr_accessor :multi_site_context
-
+
included do
belongs_to :site
# rails 3.2.19
# fix: Spree::Taxon.create!({ taxonomy_id: 0, name: 'name' }, without_protection: true) =>
- #
- before_create {|record| record.site_id||= Spree::Site.current.id }
-
+ #
+ # before_create {|record| record.site_id||= Spree::Site.current.id }
+
default_scope {
- # admin_site_product, create or update global taxon.
- if self == Spree::Taxon && multi_site_context=='admin_site_product'
- scoped
- # first site list template themes
+ # design shop create theme product, assign it to global taxon( taxon in site 1)
+ # enable getting taxon from site 1
+ # user import theme from design site, we support import theme with taxon.
+ # enable geting taxon from design site
+ if ( self == Spree::Taxon || self == Spree::Taxonomy ) && multi_site_context=='free_taxon'
+ where(nil)
+ # first site list template themes
elsif self == Spree::Product && multi_site_context=='site1_themes'
- scoped
- # first site list product images
- elsif self == Spree::Image && multi_site_context=='site_product_images'
- scoped
- elsif multi_site_context=='admin_migration'
- scoped
- else
+ where(nil)
+ # first site list product images
+ elsif multi_site_context=='site_product_images'
+ where(nil)
+ # admin sites, site.users site.stores ..
+ elsif multi_site_context=='admin_sites'
+ where(nil)
+ else
where(:site_id => Spree::Site.current.id)
- end
+ end
}
-
+
end
-
+
module ClassMethods
- # remove it after upgrade to rails 4.0
def multi_site_context
MultiSiteSystem.multi_site_context
- end
+ end
end
-
+
def self.setup_context( new_multi_site_context = nil)
self.multi_site_context = new_multi_site_context
end
-
+
# do block with given context
def self.with_context( new_context, &block )
original_context = self.multi_site_context
@@ -68,17 +64,22 @@ def self.with_context( new_context, &block )
self.multi_site_context = original_context
end
end
-
- def self.with_context_admin_site_product(&block)
- with_context( 'admin_site_product', &block )
+
+ def self.with_context_free_taxon(&block)
+ with_context( 'free_taxon', &block )
end
def self.with_context_site1_themes(&block)
with_context( 'site1_themes', &block )
end
+
def self.with_context_site_product_images(&block)
with_context( 'site_product_images', &block )
end
-
+
+ def self.with_context_admin_sites(&block)
+ with_context( 'admin_sites', &block )
+ end
+
end
-end
\ No newline at end of file
+end
diff --git a/spree_multi_site/lib/spree_multi_site/paper_clip_interpolate_site.rb b/spree_multi_site/lib/spree_multi_site/paper_clip_interpolate_site.rb
index 09139da1..80e13311 100644
--- a/spree_multi_site/lib/spree_multi_site/paper_clip_interpolate_site.rb
+++ b/spree_multi_site/lib/spree_multi_site/paper_clip_interpolate_site.rb
@@ -1,5 +1,76 @@
-unless Paperclip::Interpolations.all.include? :site
- Paperclip.interpolates :site do |attachment, style_name|
- attachment.instance.site_id # site.current do not work anymore, since we assign theme product to taxon of shop1.
+module SpreeMultiSite
+
+ unless Paperclip::Interpolations.all.include? :site
+
+ Paperclip.interpolates :site do |attachment, style_name|
+ attachment.instance.site_id # site.current do not work anymore, since we assign theme product to taxon of shop1.
+ end
+ # Paperclip support :class, Spree::Taxon => spree/taxon, with simple_class, Spree::Taxon => taxon
+ Paperclip.interpolates :simple_class do |attachment, style_name|
+
+ AttachmentClassEnum.to_h.key( attachment.instance.class.name ) || 'unkown'
+ #attachment.instance.class.name.demodulize.underscore
+ end
+
+ Paperclip.interpolates :aliyun_host do |attachment, style_name|
+ #style_name is symbol
+ case style_name
+ when :original
+ Paperclip::Attachment.default_options[:aliyun][:oss_host]
+ else
+ Paperclip::Attachment.default_options[:aliyun][:img_host]
+ end
+ end
+
+ # support aliyun image resize service
+ # product image { mini: '48x48>', small: '100x100>', product: '240x240>', medium: '350x350>', large: '600x600>' }
+ # post image { mini: '60x60>', small: '180x120>', medium: '280x190>', large: '670x370>'},
+ # http://userdomain/object.jpg@100w_100h_90Q.jpg
+ Paperclip.interpolates :aliyun_style do |attachment, style_name|
+ extension = '.jpg'
+ style_symbol = style_name.to_sym
+ if attachment.instance.class.name == AttachmentClassEnum.spree_image
+ case style_symbol
+ when :mini
+ '@48w_48h_1x' + extension
+ when :small
+ '@100w_100h_1x' + extension
+ when :product
+ '@240w_240h_1x' + extension
+ when :medium
+ '@350w_350h_1x' + extension
+ when :large
+ '@600w_600h_1x' + extension
+ end
+ elsif attachment.instance.class.name == AttachmentClassEnum.spree_post
+ case style_symbol
+ when :mini # post cover
+ '@60w_60h_1x' + extension
+ when :small
+ '@180w_120h_1x' + extension
+ when :medium
+ '@280w_190h_1x' + extension
+ when :large
+ '@670w_370h_1x' + extension
+ end
+ elsif attachment.instance.class.name == AttachmentClassEnum.ckeditor_picture
+ case style_symbol
+ when :thumb # ckeditor image, '118x100#', as list item
+ #先把图按短边优先缩略,然后再用指定颜色填充剩余区域
+ '@118w_100h_4e' + extension
+ when :content # ckeditor image, '800>' , as editor content
+ '@800w_l1' + extension
+ end
+ elsif attachment.instance.class.name == AttachmentClassEnum.spree_template_file
+ case style_symbol
+ when :mini
+ #将图按短边缩略到48x48, 然后按白色填充
+ '@48w_48h_4e' + extension
+ end
+
+ end
+
+ end # :aliyun_style
end
-end
\ No newline at end of file
+
+end # SpreeMultiSite
diff --git a/spree_multi_site/lib/spree_multi_site/paperclip_aliyun_oss_helper.rb b/spree_multi_site/lib/spree_multi_site/paperclip_aliyun_oss_helper.rb
new file mode 100644
index 00000000..9b4bcc0a
--- /dev/null
+++ b/spree_multi_site/lib/spree_multi_site/paperclip_aliyun_oss_helper.rb
@@ -0,0 +1,35 @@
+module SpreeMultiSite
+
+ # include into model
+ module PaperclipAliyunOssHelper
+ # original path and url
+ # :url => "/shops/:rails_env/:site/ckeditor_assets/pictures/:id/:style_:basename.:extension",
+ # :path => ":rails_root/public/shops/:rails_env/:site/ckeditor_assets/pictures/:id/:style_:basename.:extension",
+
+ def self.extended( base )
+ if base.storage_aliyun?
+ base.fix_path_for_aliyun_oss
+ end
+ end
+
+ def fix_path_for_aliyun_oss
+ # ex. Spree::Taxon path = 1/taxon/1_test.jpg, :aliyun_style start with @
+ # taxon/post/
+ path = ":site/:simple_class/:id_:filename"
+ #make sure each
+ attachment_key = :attachment # spree_image/ spree_template_file
+ attachment_key = :icon if self.name == AttachmentClassEnum.spree_taxon
+ attachment_key = :cover if self.name == AttachmentClassEnum.spree_post
+ attachment_key = :data if self.name == AttachmentClassEnum.ckeditor_picture #Ckeditor::Picture,
+ attachment_key = :data if self.name == AttachmentClassEnum.ckeditor_file #Ckeditor::AttachmentFile
+ attachment_definitions[attachment_key][:path] = path
+ attachment_definitions[attachment_key][:url] = 'http://:aliyun_host/'+path+':aliyun_style'
+ attachment_definitions[attachment_key][:styles] = {} #no need styles anymore. it is supproted by oss style
+ end
+
+ def storage_aliyun?
+ (attachment_definitions[:storage]||Paperclip::Attachment.default_options[:storage]) == :aliyun
+ end
+ end
+
+end
diff --git a/spree_multi_site/lib/spree_multi_site/permitted_attributes_for_site.rb b/spree_multi_site/lib/spree_multi_site/permitted_attributes_for_site.rb
index 2bc1d1c2..9d50285b 100644
--- a/spree_multi_site/lib/spree_multi_site/permitted_attributes_for_site.rb
+++ b/spree_multi_site/lib/spree_multi_site/permitted_attributes_for_site.rb
@@ -4,6 +4,9 @@ module PermittedAttributes
ATTRIBUTES_FOR_SITE=[:site_attributes]
mattr_reader *ATTRIBUTES_FOR_SITE
- @@site_attributes = [:name, :domain, :short_name, :has_sample, :index_page,:theme_id,:foreign_theme_id]
+ @@site_attributes = [:name, :domain, :short_name, :has_sample, :index_page,:theme_id,:foreign_theme_id, :email, :password,:password_confirmation,
+ # from app_configuration
+ :allow_ssl_in_production, :allow_ssl_in_development_and_test, :allow_ssl_in_staging, :check_for_spree_alerts, :display_currency, :hide_cents, :currency, :currency_symbol_position, :currency_decimal_mark, :currency_thousands_separator
+ ]
end
end
\ No newline at end of file
diff --git a/spree_multi_site/lib/spree_multi_site/testing_support/factories.rb b/spree_multi_site/lib/spree_multi_site/testing_support/factories.rb
new file mode 100644
index 00000000..a36a5d0b
--- /dev/null
+++ b/spree_multi_site/lib/spree_multi_site/testing_support/factories.rb
@@ -0,0 +1,3 @@
+Dir["#{File.dirname(__FILE__)}/factories/**"].each do |f|
+ load File.expand_path(f)
+end
diff --git a/spree_multi_site/lib/spree_multi_site/testing_support/factories/site_factory.rb b/spree_multi_site/lib/spree_multi_site/testing_support/factories/site_factory.rb
new file mode 100644
index 00000000..6c0b2588
--- /dev/null
+++ b/spree_multi_site/lib/spree_multi_site/testing_support/factories/site_factory.rb
@@ -0,0 +1,25 @@
+FactoryGirl.define do
+ factory :site1, class: Spree::Site do
+ name 'first'
+ email 'first@dalianshops.com'
+ password 'password'
+
+ before(:create) do
+ Spree::Role.find_by(name: 'admin') || create(:role, name: 'admin')
+ end
+
+ after(:create) do| site |
+ store = create(:store, site: site, is_public: true )
+ #it is not work.
+ #store.is_public = true
+ #store.save!
+ end
+
+ factory :site2 do
+ name 'design'
+ email 'design@dalianshops.com'
+ end
+
+ end
+
+end
diff --git a/spree_multi_site/lib/tasks/multi_site_extension_tasks.rake b/spree_multi_site/lib/tasks/multi_site_extension_tasks.rake
index f89b054a..d67b288f 100644
--- a/spree_multi_site/lib/tasks/multi_site_extension_tasks.rake
+++ b/spree_multi_site/lib/tasks/multi_site_extension_tasks.rake
@@ -1,18 +1,25 @@
def rename_multi_site_migrations
puts "calling spree_multi_site:install:migrations enhance"
- #default migration sequence is spree's migration -> extension's migration
- #we need to create site first, or User.find will cause error, so change name to reset order
- #1create_site -> spree_zero_nine_zero -> other_spree_multi_site_migrations
+ # default migration sequence is spree's migration -> extension's migration
+ # we need to create site first, or User.find will cause error, so change name to reset order
+ #
+ # 1create_site ->
+ # -> spree_zero_nine_zero -> other_spree_multi_site_migrations
spree_zero_nine_zero_migration = nil
- spree_multi_site_migrations = []
+ special_migration_regex = /create_sites/
+ #add_site_orders|
+ #add_short_name_and_parent_id_to_site|
+ #add_has_sample|
+ #add_site_taxons/
+ spree_multi_site_migrations = []
Dir[File.join(Rails.root,'db','migrate','*.rb')].sort.each{|file|
spree_zero_nine_zero_migration = file if file =~/spree_one_two/
- spree_multi_site_migrations<< file if file=~/spree_multi_site.rb$/ && file !~/_last_/ #z: load it at last.
- #leave this file 'add_site_payment_methods' at the end
+ spree_multi_site_migrations<< file if file=~/spree_multi_site.rb$/ && file =~special_migration_regex #z: load it at last.
+ #leave this file 'add_site_payment_methods' at the end
}
- #puts "--spree_zero_nine_zero_migration=#{spree_zero_nine_zero_migration}"
- #puts "--spree_multi_site_migrations=#{spree_multi_site_migrations}"
- if spree_zero_nine_zero_migration.present? and spree_multi_site_migrations.present?
+ #puts "--spree_zero_nine_zero_migration=#{spree_zero_nine_zero_migration}"
+ #puts "--spree_multi_site_migrations=#{spree_multi_site_migrations}"
+ if spree_zero_nine_zero_migration.present? && spree_multi_site_migrations.present?
spree_zero_file_name = File.basename(spree_zero_nine_zero_migration,'.rb') # spree_zero_nine_zero_migration is full path
migration_start_number = spree_zero_file_name.to_i - spree_multi_site_migrations.size
create_site_migration = spree_multi_site_migrations.shift
@@ -23,12 +30,12 @@ def rename_multi_site_migrations
File.rename(spree_zero_nine_zero_migration, spree_zero_nine_zero_migration.sub(/\d+/,(migration_start_number+1).to_s))
spree_multi_site_migrations.each_index{|i|
migration_file = spree_multi_site_migrations[i]
- File.rename(migration_file, migration_file.sub(/\d+/,(migration_start_number+2+i).to_s))
+ File.rename(migration_file, migration_file.sub(/\d+/,(migration_start_number+2+i).to_s))
}
- end
+ end
end
- puts "complete renaming spree_multi_site's migration"
-
+ puts "complete renaming spree_multi_site's migration"
+
end
# task test_app call railties:install:migrations
@@ -38,7 +45,7 @@ end
#namespace :spree_multi_site do
# namespace :install do
-# namespace :migrations do
+# namespace :migrations do
# end
# end
#end
@@ -56,13 +63,13 @@ namespace :spree do
mkdir_p RAILS_ROOT + directory
cp file, RAILS_ROOT + path
end
- end
+ end
desc "remove multi_site's migrations first,then install again, useful for modifing some existing migration file!"
task :reinstall_migrations => :environment do
Dir[File.join(Rails.root,'db','migrate','*.rb')].sort.each{|file|
if file=~/spree_multi_site.rb$/
File.delete(file)
- end
+ end
}
Rake::Task['spree_multi_site:install:migrations'].invoke
end
@@ -74,7 +81,7 @@ namespace :spree do
#site.taxonomies = Spree::Taxonomy.find(:all)
#site.orders = Spree::Order.find(:all)
#site.save
- #end
+ #end
end
end
-end
\ No newline at end of file
+end
diff --git a/spree_multi_site/spec/controllers/spree/site_controller_spec.rb b/spree_multi_site/spec/controllers/spree/site_controller_spec.rb
deleted file mode 100644
index 2b9e2c69..00000000
--- a/spree_multi_site/spec/controllers/spree/site_controller_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'spec_helper'
-
-describe Spree::SitesController do
-
- it "should create site" do
- spree_post :quick_lunch,{:site=>{:name=>"a test"}, :user=>{:email=>'test@test.com',:password=>'123456'}}
- site = assigns(:site)
- site.should be_kind_of Spree::Site
- site.shipping_categories.count.should eq 1
- site.users.count.should eq 1
- response.should redirect_to(site.admin_url)
- end
-end
diff --git a/spree_multi_site/spec/controllers/spree/sites_controller_spec.rb b/spree_multi_site/spec/controllers/spree/sites_controller_spec.rb
new file mode 100644
index 00000000..ef745c51
--- /dev/null
+++ b/spree_multi_site/spec/controllers/spree/sites_controller_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe Spree::SitesController do
+ #let!(:user) { mock_model(Spree::User, :spree_api_key => 'fake', :last_incomplete_spree_order => nil) }
+ let!(:role) { create(:admin_role) }
+
+ before do
+ Spree::Site.current = create(:site1)
+ end
+ #Delete this example and add some real ones
+ it "should use Spree::SitesController" do
+ controller.should be_an_instance_of(Spree::SitesController)
+ end
+ #{"utf8"=>"✓", "authenticity_token"=>"Klllros8vRbKw1rGMzq33yHRXJ2ioTyaXV0Uy2YlsUw=", "site"=>{"name"=>"test", "short_name"=>"test", "has_sample"=>"1"}, "user"=>{"email"=>"test@gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"创建"}
+ it "should create a site successfully" do
+ spree_post :create, { "site"=>{"name"=>"test", "short_name"=>"test", "email"=>"test@gmail.com", "password"=>"123456", "password_confirmation"=>"123456"} }
+ expect(assigns(:site)).to be_kind_of Spree::Site
+ expect(response).to redirect_to( assigns(:site).admin_url )
+ end
+
+ it "should quick lunch a site successfully" do
+ spree_post :quick_lunch, { "site"=>{"name"=>"test", "short_name"=>"test", "email"=>"test@gmail.com", "password"=>"123456"}}
+ expect(assigns(:site)).to be_kind_of Spree::Site
+ expect(response).to redirect_to( assigns(:site).admin_url )
+ end
+
+
+end
diff --git a/spree_multi_site/spec/controllers/spree/store_controller_spec.rb b/spree_multi_site/spec/controllers/spree/store_controller_spec.rb
deleted file mode 100644
index be44744c..00000000
--- a/spree_multi_site/spec/controllers/spree/store_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'spec_helper'
-
-describe Spree::StoreController do
-
- #Delete this example and add some real ones
- it "should use Spree::StoreController" do
- controller.should be_an_instance_of(Spree::StoreController)
- expect( controller.methods).to include(:get_site_and_products)
-
- end
-#{"utf8"=>"✓", "authenticity_token"=>"Klllros8vRbKw1rGMzq33yHRXJ2ioTyaXV0Uy2YlsUw=", "site"=>{"name"=>"test", "short_name"=>"test", "has_sample"=>"1"}, "user"=>{"email"=>"test@gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"创建"}
- it "should create a site successfully with an HTTP 200 status code" do
- post :new
- expect(response).to be_success
- expect(response.status).to eq(200)
- end
-end
diff --git a/spree_multi_site/spec/fixtures/qinghe.jpg b/spree_multi_site/spec/fixtures/qinghe.jpg
new file mode 100644
index 00000000..6e647b70
Binary files /dev/null and b/spree_multi_site/spec/fixtures/qinghe.jpg differ
diff --git a/spree_multi_site/spec/models/site_spec.rb b/spree_multi_site/spec/models/site_spec.rb
index 8b820260..6168eb55 100644
--- a/spree_multi_site/spec/models/site_spec.rb
+++ b/spree_multi_site/spec/models/site_spec.rb
@@ -2,87 +2,76 @@
require 'spec_helper'
describe Spree::Site do
before(:each) do
- @site = Spree::Site.new(:name=>'ABCD',:domain=>'www.abc.net')
+ create(:admin_role)
+ @site = Spree::Site.new(:name=>'ABCD',:domain=>'www.abc.net', :email=>'test@dalianshops.com', :password=>'123456')
end
- it "should be valid" do
- @site.should be_valid
- @site.domain = ''
- @site.should be_valid
-
+ it "should be valid with blank domain" do
@site.domain = nil
@site.should be_valid
-
- @site.domain = 'www.abc.net'
- @site.save!
-
- site2 = @site.dup
- site2.should be_invalid
- site2.short_name = nil
- site2.domain = nil
- site2.should be_valid
- site2.save.should be_true
- site2.short_name.should start_with( @site.short_name)
- site2.short_name.should_not == @site.short_name
end
-
-
-
- it "should not be valid" do
+
+ it "named 'ABC' should not be valid" do
@site.name = 'ABC'
@site.short_name = nil
- @site.valid?.should be_false
-
+ @site.valid?.should be_falsy
+ end
+
+ it "generate 'da-lian-and-bai-jiu' from name '大连&白酒!'" do
@site.name = '大连&白酒!'
@site.short_name = nil
- @site.valid?.should be_true
+ @site.valid?.should be_truthy
@site.short_name.should eq "da-lian-and-bai-jiu"
- @site.save.should be_true
- end
-
- it "should create site and user" do
- user_attributes = {"email"=>"test@abc.com", "password"=>"a12345z", "password_confirmation"=>"a12345z"}
- @site.users<< Spree::User.new(user_attributes)
- @site.save
- @site.should_not be_new_record
- @site.users.first.email.should eq(user_attributes['email'])
+ @site.save.should be_truthy
end
-
- it "shold load samples" do
+
+ it "should create site with store, user and shipping_category" do
+ #user_attributes = {"email"=>"test@abc.com", "password"=>"a12345z", "password_confirmation"=>"a12345z"}
+ #@site.users<< Spree::User.new(user_attributes)
@site.save!
- @site.load_sample
- @site.shipping_categories.should be_present
+ @site.should be_persisted
+ Spree::Site.current = @site
+ @site.users.should be_present
+ @site.stores.should be_present
end
-
- it "should has associations" do
- @site.users.build.should be_present
- @site.products.build.should be_present
- @site.zones.build.should be_present
-
- end
-
+
+ # raise error ./app/models/spree/site.rb:56:in `current'
+ #it "should create site and admin user" do
+ # site_params = { "name"=>"test", "short_name"=>"test",
+ # "users_attributes"=>{"0"=>{"email"=>"test@dalianshops.com", "password"=>"123456", "password_confirmation"=>"123456"}}
+ # }
+ # site = Spree::Site.new(site_params)
+ # site.save
+ # site.should_not be_new_record
+ #end
+
+ #it "shold load samples" do
+ # @site.save!
+ # @site.load_sample
+ # @site.shipping_categories.should be_present
+ # @site.users.first.should be_persisted
+ # @site.users.first.should be_admin
+ #end
+
it "shold remove samples" do
-
@site.save!
- @site.load_sample(false)
+ @site.unload_sample
Spree::Site.current = @site
Spree::Product.count.should eq(0)
- Spree::Variant.count.should eq(0)
Spree::Zone.count.should eq(0)
- Spree::ZoneMember.count.should eq(0)
Spree::StateChange.count.should eq(0)
#product variants
#taxonomy, taxon
#zone,zone_member
#state_changes
end
-
+
it "shold create two site and load samples for them" do
- @site1 = Spree::Site.create!(:name=>'Site1',:domain=>'www.site1.net',:short_name=>'site1')
- @site2 = Spree::Site.create!(:name=>'Site1',:domain=>'www.site2.net',:short_name=>'site2')
- @site1.load_sample
- @site2.load_sample
+ #@site1 = Spree::Site.create!(:name=>'Site1',:domain=>'www.site1.net',:short_name=>'site1', :email=>'site1@dalianshops.com', :password=>'123456')
+ #@site2 = Spree::Site.create!(:name=>'Site1',:domain=>'www.site2.net',:short_name=>'site2', :email=>'site2@dalianshops.com', :password=>'123456')
+ #@site1.load_sample
+ #@site2.load_sample
#product image copied and in right folder.
end
-
+
end
diff --git a/spree_multi_site/spec/models/taxon_spec.rb b/spree_multi_site/spec/models/taxon_spec.rb
deleted file mode 100644
index 02f2773f..00000000
--- a/spree_multi_site/spec/models/taxon_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-#encoding: utf-8
-require 'spec_helper'
-describe Spree::Taxon do
- before(:each) do
- Spree::Site.current = Spree::Site.create!(:name=>'ABCD',:domain=>'www.abc.net')
- @taxon = Spree::Taxon.new(:name=>'ABCD')
- end
- it "should create taxon with valid site!" do
- new_taxon = Spree::Taxon.create!({ taxonomy_id: 0, name: 'name' })
- new_taxon.site.should eq Spree::Site.current
- end
-end
diff --git a/spree_multi_site/spec/spec_helper.rb b/spree_multi_site/spec/spec_helper.rb
index 453981c7..2dec8323 100644
--- a/spree_multi_site/spec/spec_helper.rb
+++ b/spree_multi_site/spec/spec_helper.rb
@@ -15,6 +15,7 @@
require File.expand_path('../dummy/config/environment.rb', __FILE__)
require 'rspec/rails'
+require 'database_cleaner'
require 'ffaker'
# Requires supporting ruby files with custom matchers and macros, etc,
@@ -23,10 +24,16 @@
# Requires factories and other useful helpers defined in spree_core.
require 'spree/testing_support/authorization_helpers'
-require 'spree/testing_support/capybara_ext'
-require 'spree/testing_support/controller_requests'
require 'spree/testing_support/factories'
+require 'spree/testing_support/preferences'
+require 'spree/testing_support/controller_requests'
+require 'spree/testing_support/flash'
require 'spree/testing_support/url_helpers'
+require 'spree/testing_support/order_walkthrough'
+require 'spree/testing_support/capybara_ext'
+
+# Requires factories defined in lib/spree_multi_site/factories.rb
+require 'spree_multi_site/testing_support/factories'
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
@@ -40,8 +47,10 @@
#
# visit spree.admin_path
# current_path.should eql(spree.products_path)
+ config.include Spree::TestingSupport::Preferences
config.include Spree::TestingSupport::UrlHelpers
-
+ config.include Spree::TestingSupport::ControllerRequests
+ config.include Spree::TestingSupport::Flash
# == Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
@@ -63,7 +72,7 @@
# Ensure Suite is set to use transactions for speed.
config.before :suite do
DatabaseCleaner.strategy = :transaction
- DatabaseCleaner.clean_with :truncation
+ #DatabaseCleaner.clean_with :truncation
end
# Before each spec check if it is a Javascript test and switch between using database transactions or not where necessary.
diff --git a/spree_pingpp/.gitignore b/spree_pingpp/.gitignore
new file mode 100644
index 00000000..a3fc71a1
--- /dev/null
+++ b/spree_pingpp/.gitignore
@@ -0,0 +1,36 @@
+*.rbc
+capybara-*.html
+.rspec
+/log
+/tmp
+/db/*.sqlite3
+/db/*.sqlite3-journal
+/public/system
+/coverage/
+/spec/tmp
+/spec/dummy
+**.orig
+rerun.txt
+pickle-email-*.html
+
+# TODO Comment out these rules if you are OK with secrets being uploaded to the repo
+config/initializers/secret_token.rb
+config/secrets.yml
+
+## Environment normalisation:
+/.bundle
+/vendor/bundle
+
+# these should all be checked in to normalise the environment:
+# Gemfile.lock, .ruby-version, .ruby-gemset
+
+# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
+.rvmrc
+
+# if using bower-rails ignore default bower_components path bower.json files
+/vendor/assets/bower_components
+*.bowerrc
+bower.json
+
+# Ignore pow environment settings
+.powenv
diff --git a/spree_pingpp/Gemfile b/spree_pingpp/Gemfile
new file mode 100644
index 00000000..4e3f60fb
--- /dev/null
+++ b/spree_pingpp/Gemfile
@@ -0,0 +1,8 @@
+source 'https://rubygems.org'
+
+eval(File.read(File.dirname(__FILE__) + '/../common_spree_dependencies.rb'))
+
+gem 'pingpp', '~> 2.0.8'
+
+
+gemspec
diff --git a/spree_pingpp/LICENSE b/spree_pingpp/LICENSE
new file mode 100644
index 00000000..84112151
--- /dev/null
+++ b/spree_pingpp/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 RuanShan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/spree_pingpp/README.md b/spree_pingpp/README.md
new file mode 100644
index 00000000..43421dbc
--- /dev/null
+++ b/spree_pingpp/README.md
@@ -0,0 +1,51 @@
+SpreePingppHtml5
+================
+
+Integrate pingpp-html5 into spree,
+It is working in progress...
+
+Installation
+------------
+
+Add spree_pingpp to your Gemfile:
+
+```ruby
+gem 'spree_pingpp'
+```
+
+Bundle your dependencies and run the installation generator:
+
+```shell
+bundle
+bundle exec rails g spree_pingpp:install
+```
+
+Testing
+-------
+
+First bundle your dependencies, then run `rake`. `rake` will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using `rake test_app`.
+
+```shell
+bundle
+bundle exec rake
+```
+
+When testing your applications integration with this extension you may use it's factories.
+Simply add this require statement to your spec_helper:
+
+```ruby
+require 'spree_pingpp/factories'
+```
+
+Related project
+---------------
+
+Spree https://github.com/spree/spree
+PingPlusPlus https://github.com/PingPlusPlus
+
+Copyright (c) 2015 [name of extension creator], released under the New BSD License
+
+
+
+
+
diff --git a/spree_pingpp/Rakefile b/spree_pingpp/Rakefile
new file mode 100644
index 00000000..e42ff482
--- /dev/null
+++ b/spree_pingpp/Rakefile
@@ -0,0 +1,21 @@
+require 'bundler'
+Bundler::GemHelper.install_tasks
+
+require 'rspec/core/rake_task'
+require 'spree/testing_support/extension_rake'
+
+RSpec::Core::RakeTask.new
+
+task :default do
+ if Dir["spec/dummy"].empty?
+ Rake::Task[:test_app].invoke
+ Dir.chdir("../../")
+ end
+ Rake::Task[:spec].invoke
+end
+
+desc 'Generates a dummy app for testing'
+task :test_app do
+ ENV['LIB_NAME'] = 'spree_pingpp'
+ Rake::Task['extension:test_app'].invoke
+end
diff --git a/spree_pingpp/app/assets/images/billing_integrations/pingpp/alipay_pc_direct.jpg b/spree_pingpp/app/assets/images/billing_integrations/pingpp/alipay_pc_direct.jpg
new file mode 100644
index 00000000..e34d5d82
Binary files /dev/null and b/spree_pingpp/app/assets/images/billing_integrations/pingpp/alipay_pc_direct.jpg differ
diff --git a/spree_pingpp/app/assets/images/billing_integrations/pingpp/alipay_wap.jpg b/spree_pingpp/app/assets/images/billing_integrations/pingpp/alipay_wap.jpg
new file mode 100644
index 00000000..e34d5d82
Binary files /dev/null and b/spree_pingpp/app/assets/images/billing_integrations/pingpp/alipay_wap.jpg differ
diff --git a/spree_pingpp/app/assets/images/billing_integrations/pingpp/upacp_pc.jpg b/spree_pingpp/app/assets/images/billing_integrations/pingpp/upacp_pc.jpg
new file mode 100644
index 00000000..1254869a
Binary files /dev/null and b/spree_pingpp/app/assets/images/billing_integrations/pingpp/upacp_pc.jpg differ
diff --git a/spree_pingpp/app/assets/javascripts/pingpp-pc.js b/spree_pingpp/app/assets/javascripts/pingpp-pc.js
new file mode 100644
index 00000000..98e08393
--- /dev/null
+++ b/spree_pingpp/app/assets/javascripts/pingpp-pc.js
@@ -0,0 +1,171 @@
+(function(){
+var
+ version = "2.0.7",
+ hasOwn = {}.hasOwnProperty,
+ PingppSDK = function(){},
+ cfg = {
+ PINGPP_NOTIFY_URL: 'https://api.pingxx.com/notify/charges/',
+ PINGPP_MOCK_URL: 'http://sissi.pingxx.com/mock.php',
+ ALIPAY_PC_DIRECT_URL: 'https://mapi.alipay.com/gateway.do',
+ UPACP_PC_URL: 'https://gateway.95516.com/gateway/api/frontTransReq.do'
+ },
+ channels = {
+ alipay_pc_direct: 'alipay_pc_direct',
+ upacp_pc: 'upacp_pc'
+ };
+
+PingppSDK.prototype = {
+
+ version: version,
+
+ _resultCallback: undefined,
+
+ _debug: false,
+
+ createPayment: function(charge_json, callback, debug) {
+ if (typeof callback == "function") {
+ this._resultCallback = callback;
+ }
+ if (typeof debug == "boolean") {
+ this._debug = debug;
+ }
+ var charge;
+ if(typeof charge_json == "string"){
+ try{
+ charge = JSON.parse(charge_json);
+ }catch(err){
+ this._innerCallback("fail", this._error("json_decode_fail"));
+ return;
+ }
+ }else{
+ charge = charge_json;
+ }
+ if(typeof charge == "undefined"){
+ this._innerCallback("fail", this._error("json_decode_fail"));
+ return;
+ }
+ if(!hasOwn.call(charge, 'id')){
+ this._innerCallback("fail", this._error("invalid_charge", "no_charge_id"));
+ return;
+ }
+ if(!hasOwn.call(charge, 'channel')){
+ this._innerCallback("fail", this._error("invalid_charge", "no_channel"));
+ return;
+ }
+ var channel = charge['channel'];
+ if(!hasOwn.call(charge, 'credential')){
+ this._innerCallback("fail", this._error("invalid_charge", "no_credential"));
+ return;
+ }
+ if (!charge['credential']) {
+ this._innerCallback("fail", this._error("invalid_credential", "credential_is_undefined"));
+ return;
+ }
+ if (!hasOwn.call(channels, channel)) {
+ this._innerCallback("fail", this._error("invalid_charge", "no_such_channel:" + channel));
+ return;
+ }
+ if (!hasOwn.call(charge['credential'], channel)) {
+ this._innerCallback("fail", this._error("invalid_credential", "no_valid_channel_credential"));
+ return;
+ }
+ if(!hasOwn.call(charge, 'livemode')){
+ this._innerCallback("fail", this._error("invalid_charge", "no_livemode"));
+ return;
+ }
+ if (charge['livemode'] == false) {
+ this._testModeNotify(charge);
+ return;
+ }
+ var credential = charge['credential'][channel];
+ if (channel == channels.upacp_pc) {
+ form_submit(cfg.UPACP_PC_URL, 'post', credential);
+ } else if (channel == channels.alipay_pc_direct) {
+ if (!hasOwn.call(credential, "_input_charset")) {
+ credential["_input_charset"] = 'utf-8';
+ }
+ var query = stringify_data(credential, channel, true);
+ window.location.href = cfg.ALIPAY_PC_DIRECT_URL + "?" + query;
+ }
+ },
+
+ _error: function(msg, extra) {
+ msg = (typeof msg == "undefined") ? "" : msg;
+ extra = (typeof extra == "undefined") ? "" : extra;
+ return {
+ msg:msg,
+ extra:extra
+ };
+ },
+
+ _innerCallback: function(result, err) {
+ if (typeof this._resultCallback == "function") {
+ if (typeof err == "undefined") {
+ err = this._error();
+ }
+ this._resultCallback(result, err);
+ }
+ },
+
+ _testModeNotify: function(charge) {
+ var params = {
+ 'ch_id': charge['id'],
+ 'scheme': 'http',
+ 'channel': charge['channel']
+ };
+ if (hasOwn.call(charge, 'order_no')) {
+ params['order_no'] = charge['order_no'];
+ } else if (hasOwn.call(charge, 'orderNo')) {
+ params['order_no'] = charge['orderNo'];
+ }
+ if (hasOwn.call(charge, 'time_expire')) {
+ params['time_expire'] = charge['time_expire'];
+ } else if (hasOwn.call(charge, 'timeExpire')) {
+ params['time_expire'] = charge['timeExpire'];
+ }
+ if (hasOwn.call(charge, 'extra')) {
+ params['extra'] = encodeURIComponent(JSON.stringify(charge['extra']));
+ }
+ location.href = cfg.PINGPP_MOCK_URL+'?'+stringify_data(params);
+ }
+};
+
+function form_submit(url, method, params) {
+ var form = document.createElement("form");
+ form.setAttribute("method", method);
+ form.setAttribute("action", url);
+
+ for (var key in params) {
+ if (hasOwn.call(params, key)) {
+ var hiddenField = document.createElement("input");
+ hiddenField.setAttribute("type", "hidden");
+ hiddenField.setAttribute("name", key);
+ hiddenField.setAttribute("value", params[key]);
+ form.appendChild(hiddenField);
+ }
+ }
+
+ document.body.appendChild(form);
+ form.submit();
+}
+
+function stringify_data(data, channel, urlencode) {
+ if (typeof urlencode == "undefined") {
+ urlencode = false;
+ }
+ var output = [];
+ for (var i in data) {
+ if (channel == "bfb_wap" && i == "url") {
+ continue;
+ }
+ if (channel == "yeepay_wap" && i == "mode") {
+ continue;
+ }
+ output.push(i + '=' + (urlencode ? encodeURIComponent(data[i]) : data[i]));
+ }
+ return output.join('&');
+}
+
+PingppSDK.prototype.payment = PingppSDK.prototype.createPayment;
+window.pingppPc = new PingppSDK();
+})();
diff --git a/spree_pingpp/app/assets/javascripts/pingpp.js b/spree_pingpp/app/assets/javascripts/pingpp.js
new file mode 100644
index 00000000..48ab1ac6
--- /dev/null
+++ b/spree_pingpp/app/assets/javascripts/pingpp.js
@@ -0,0 +1,322 @@
+(function(){
+var
+ version = "2.0.7",
+ hasOwn = {}.hasOwnProperty,
+ PingppSDK = function(){},
+ cfg = {
+ PINGPP_NOTIFY_URL: 'https://api.pingxx.com/notify/charges/',
+ UPACP_WAP_URL: 'https://gateway.95516.com/gateway/api/frontTransReq.do',
+ ALIPAY_WAP_URL: 'http://wappaygw.alipay.com/service/rest.htm',
+ UPMP_WAP_URL: 'uppay://uppayservice/?style=token&paydata=',
+ JDPAY_WAP_URL: 'https://m.jdpay.com/wepay/web/pay',
+ YEEPAY_WAP_URL: 'https://ok.yeepay.com/paymobile/api/pay/request',
+ YEEPAY_WAP_TEST_URL: 'http://mobiletest.yeepay.com/paymobile/api/pay/request',
+ PINGPP_MOCK_URL: 'http://sissi.pingxx.com/mock.php'
+ },
+ channels = {
+ alipay_wap: 'alipay_wap',
+ upmp_wap: 'upmp_wap',
+ upacp_wap: 'upacp_wap',
+ bfb_wap: 'bfb_wap',
+ wx_pub: 'wx_pub',
+ yeepay_wap: 'yeepay_wap',
+ jdpay_wap: 'jdpay_wap'
+ };
+
+PingppSDK.prototype = {
+
+ version: version,
+
+ _resultCallback: undefined,
+
+ _jsApiParameters: {},
+
+ _debug: false,
+
+ _signature: undefined,
+
+ createPayment: function(charge_json, callback, signature, debug) {
+ if (typeof callback == "function") {
+ this._resultCallback = callback;
+ }
+ if (typeof signature != "undefined") {
+ this._signature = signature;
+ }
+ if (typeof debug == "boolean") {
+ this._debug = debug;
+ }
+ var charge;
+ if(typeof charge_json == "string"){
+ try{
+ charge = JSON.parse(charge_json);
+ }catch(err){
+ this._innerCallback("fail", this._error("json_decode_fail"));
+ return;
+ }
+ }else{
+ charge = charge_json;
+ }
+ if(typeof charge == "undefined"){
+ this._innerCallback("fail", this._error("json_decode_fail"));
+ return;
+ }
+ if(!hasOwn.call(charge, 'id')){
+ this._innerCallback("fail", this._error("invalid_charge", "no_charge_id"));
+ return;
+ }
+ if(!hasOwn.call(charge, 'channel')){
+ this._innerCallback("fail", this._error("invalid_charge", "no_channel"));
+ return;
+ }
+ var channel = charge['channel'];
+ if(!hasOwn.call(charge, 'credential')){
+ this._innerCallback("fail", this._error("invalid_charge", "no_credential"));
+ return;
+ }
+ if (!charge['credential']) {
+ this._innerCallback("fail", this._error("invalid_credential", "credential_is_undefined"));
+ return;
+ }
+ if (!hasOwn.call(channels, channel)) {
+ this._innerCallback("fail", this._error("invalid_charge", "no_such_channel:" + channel));
+ return;
+ }
+ if (!hasOwn.call(charge['credential'], channel)) {
+ this._innerCallback("fail", this._error("invalid_credential", "no_valid_channel_credential"));
+ return;
+ }
+ if(!hasOwn.call(charge, 'livemode')){
+ this._innerCallback("fail", this._error("invalid_charge", "no_livemode"));
+ return;
+ }
+ if (charge['livemode'] == false) {
+ this._testModeNotify(charge);
+ return;
+ }
+ var credential = charge['credential'][channel];
+ if (channel == channels.upmp_wap) { // 调起银联支付控件,客户端需要安装银联支付控件才能调起
+ location.href = cfg.UPMP_WAP_URL + credential['paydata'];
+ } else if (channel == channels.upacp_wap) {
+ form_submit(cfg.UPACP_WAP_URL, 'post', credential);
+ } else if (channel == channels.alipay_wap) { // 调起支付宝手机网页支付
+ credential['_input_charset'] = 'utf-8';
+ if (typeof _AP != "undefined") {
+ var query = stringify_data(credential, channel, true);
+ _AP.pay(cfg.ALIPAY_WAP_URL + "?" + query);
+ } else {
+ form_submit(cfg.ALIPAY_WAP_URL, 'get', credential);
+ }
+ } else if (channel == channels.bfb_wap) {
+ if (!hasOwn.call(credential, 'url')) {
+ this._innerCallback("fail", this._error("invalid_credential", "missing_field:url"));
+ return;
+ }
+ location.href = credential['url'] + '?' + stringify_data(credential, channel);
+ } else if (channel == channels.yeepay_wap) {
+ var fields = ["merchantaccount", "encryptkey", "data"];
+ for (var k = 0; k < fields.length; k++) {
+ if(!hasOwn.call(credential, fields[k])){
+ this._innerCallback("fail", this._error("invalid_credential", "missing_field_"+fields[k]));
+ return;
+ }
+ }
+ if (hasOwn.call(credential, "mode") && credential["mode"] == "test") {
+ location.href = cfg.YEEPAY_WAP_TEST_URL + '?' + stringify_data(credential, channel, true);
+ } else {
+ location.href = cfg.YEEPAY_WAP_URL + '?' + stringify_data(credential, channel, true);
+ }
+ } else if (channel == channels.wx_pub) {
+ var fields = ["appId", "timeStamp", "nonceStr", "package", "signType", "paySign"];
+ for (var k = 0; k < fields.length; k++) {
+ if (!hasOwn.call(credential, fields[k])) {
+ this._innerCallback("fail", this._error("invalid_credential", "missing_field_"+fields[k]));
+ return;
+ }
+ }
+ this._jsApiParameters = credential;
+ this._callpay();
+ } else if (channel == channels.jdpay_wap) {
+ form_submit(cfg.JDPAY_WAP_URL, 'post', credential);
+ }
+ },
+
+ _jsApiCall: function(){
+ var self = this;
+ if(self._jsApiParameters != {}){
+ WeixinJSBridge.invoke(
+ 'getBrandWCPayRequest',
+ self._jsApiParameters,
+ function(res){
+ if(res.err_msg == 'get_brand_wcpay_request:ok'){
+ self._innerCallback("success");
+ }else if(res.err_msg == 'get_brand_wcpay_request:cancel'){
+ self._innerCallback("cancel");
+ }else{
+ self._innerCallback("fail", self._error("wx_result_fail", res.err_msg));
+ }
+ }
+ );
+ }
+ },
+
+ _callpay: function(){
+ var self = this;
+ if (typeof wx != "undefined" && typeof self._signature != "undefined") {
+ var wxConfigFailed = false;
+ wx.config({
+ debug: self._debug,
+ appId: self._jsApiParameters["appId"],
+ timestamp: self._jsApiParameters["timeStamp"],
+ nonceStr: self._jsApiParameters["nonceStr"],
+ signature: self._signature,
+ jsApiList: ['chooseWXPay']
+ });
+ wx.ready(function(){
+ if (wxConfigFailed) {
+ return;
+ }
+ wx.chooseWXPay({
+ timestamp: self._jsApiParameters["timeStamp"],
+ nonceStr: self._jsApiParameters["nonceStr"],
+ "package": self._jsApiParameters["package"],
+ signType: self._jsApiParameters["signType"],
+ paySign: self._jsApiParameters["paySign"],
+ success: function(res) {
+ if (res.errMsg == "chooseWXPay:ok") {
+ self._innerCallback("success");
+ } else {
+ self._innerCallback("fail", self._error("wx_result_fail", res.errMsg));
+ }
+ },
+ cancel: function(res) {
+ self._innerCallback("cancel");
+ },
+ fail: function(res) {
+ self._innerCallback("fail", self._error("wx_result_fail", res.errMsg));
+ }
+ });
+ });
+ wx.error(function(res){
+ wxConfigFailed = true;
+ self._innerCallback("fail", self._error("wx_config_error", res.errMsg));
+ });
+ } else if (typeof WeixinJSBridge == "undefined") {
+ function eventCallback(){
+ self._jsApiCall();
+ }
+ if (document.addEventListener) {
+ document.addEventListener('WeixinJSBridgeReady', eventCallback, false);
+ } else if(document.attachEvent) {
+ document.attachEvent('WeixinJSBridgeReady', eventCallback);
+ document.attachEvent('onWeixinJSBridgeReady', eventCallback);
+ }
+ }else{
+ this._jsApiCall();
+ }
+ },
+
+ _error: function(msg, extra) {
+ msg = (typeof msg == "undefined") ? "" : msg;
+ extra = (typeof extra == "undefined") ? "" : extra;
+ return {
+ msg:msg,
+ extra:extra
+ };
+ },
+
+ _innerCallback: function(result, err) {
+ if (typeof this._resultCallback == "function") {
+ if (typeof err == "undefined") {
+ err = this._error();
+ }
+ this._resultCallback(result, err);
+ }
+ },
+
+ _testModeNotify: function(charge) {
+ var self = this;
+ if (charge['channel'] == channels.wx_pub) {
+ var dopay = confirm("模拟付款?");
+ if (dopay) {
+ var request = new XMLHttpRequest();
+ request.open('GET', cfg.PINGPP_NOTIFY_URL+charge['id']+'?livemode=false', true);
+ request.onload = function() {
+ if (request.status >= 200 && request.status < 400 && request.responseText == "success"){
+ self._innerCallback("success");
+ } else {
+ var extra = 'http_code:'+request.status+';response:'+request.responseText;
+ self._innerCallback("fail", self._error("testmode_notify_fail", extra));
+ }
+ };
+ request.onerror = function() {
+ self._innerCallback("fail", self._error("network_err"));
+ };
+ request.send();
+ } else {
+ self._innerCallback("cancel");
+ }
+ } else {
+ var params = {
+ 'ch_id': charge['id'],
+ 'scheme': 'http',
+ 'channel': charge['channel']
+ };
+ if (hasOwn.call(charge, 'order_no')) {
+ params['order_no'] = charge['order_no'];
+ } else if (hasOwn.call(charge, 'orderNo')) {
+ params['order_no'] = charge['orderNo'];
+ }
+ if (hasOwn.call(charge, 'time_expire')) {
+ params['time_expire'] = charge['time_expire'];
+ } else if (hasOwn.call(charge, 'timeExpire')) {
+ params['time_expire'] = charge['timeExpire'];
+ }
+ if (hasOwn.call(charge, 'extra')) {
+ params['extra'] = encodeURIComponent(JSON.stringify(charge['extra']));
+ }
+ location.href = cfg.PINGPP_MOCK_URL+'?'+stringify_data(params);
+ }
+ }
+};
+
+function form_submit(url, method, params) {
+ var form = document.createElement("form");
+ form.setAttribute("method", method);
+ form.setAttribute("action", url);
+
+ for (var key in params) {
+ if (hasOwn.call(params, key)) {
+ var hiddenField = document.createElement("input");
+ hiddenField.setAttribute("type", "hidden");
+ hiddenField.setAttribute("name", key);
+ hiddenField.setAttribute("value", params[key]);
+ form.appendChild(hiddenField);
+ }
+ }
+
+ document.body.appendChild(form);
+ form.submit();
+}
+
+function stringify_data(data, channel, urlencode) {
+ if (typeof urlencode == "undefined") {
+ urlencode = false;
+ }
+ var output = [];
+ for (var i in data) {
+ if (channel == "bfb_wap" && i == "url") {
+ continue;
+ }
+ if (channel == "yeepay_wap" && i == "mode") {
+ continue;
+ }
+ output.push(i + '=' + (urlencode ? encodeURIComponent(data[i]) : data[i]));
+ }
+ return output.join('&');
+}
+
+PingppSDK.prototype.payment = PingppSDK.prototype.createPayment;
+window.pingpp = new PingppSDK();
+// aliases
+window.PINGPP_PAY_SDK = window.PINGPP_WX_PUB = window.pingpp;
+})();
diff --git a/spree_pingpp/app/assets/javascripts/spree/backend/spree_pingpp.js b/spree_pingpp/app/assets/javascripts/spree/backend/spree_pingpp.js
new file mode 100644
index 00000000..8aa3b014
--- /dev/null
+++ b/spree_pingpp/app/assets/javascripts/spree/backend/spree_pingpp.js
@@ -0,0 +1,2 @@
+// Placeholder manifest file.
+// the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
\ No newline at end of file
diff --git a/spree_pingpp/app/assets/javascripts/spree/frontend/spree_pingpp.js b/spree_pingpp/app/assets/javascripts/spree/frontend/spree_pingpp.js
new file mode 100644
index 00000000..f116f26c
--- /dev/null
+++ b/spree_pingpp/app/assets/javascripts/spree/frontend/spree_pingpp.js
@@ -0,0 +1,2 @@
+//= require 'pingpp-pc'
+//= require 'pingpp'
diff --git a/spree_pingpp/app/assets/stylesheets/spree/backend/spree_pingpp.css b/spree_pingpp/app/assets/stylesheets/spree/backend/spree_pingpp.css
new file mode 100644
index 00000000..e3c23662
--- /dev/null
+++ b/spree_pingpp/app/assets/stylesheets/spree/backend/spree_pingpp.css
@@ -0,0 +1,4 @@
+/*
+Placeholder manifest file.
+the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
+*/
diff --git a/spree_pingpp/app/assets/stylesheets/spree/frontend/spree_pingpp.css b/spree_pingpp/app/assets/stylesheets/spree/frontend/spree_pingpp.css
new file mode 100644
index 00000000..da236237
--- /dev/null
+++ b/spree_pingpp/app/assets/stylesheets/spree/frontend/spree_pingpp.css
@@ -0,0 +1,4 @@
+/*
+Placeholder manifest file.
+the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
+*/
diff --git a/spree_pingpp/app/controllers/spree/checkout_controller_decorator.rb b/spree_pingpp/app/controllers/spree/checkout_controller_decorator.rb
new file mode 100644
index 00000000..2e05551c
--- /dev/null
+++ b/spree_pingpp/app/controllers/spree/checkout_controller_decorator.rb
@@ -0,0 +1,48 @@
+#encoding: utf-8
+module Spree
+ CheckoutController.class_eval do
+ before_filter :payment_pingpp_hook, :only => [:update]
+
+ def payment_pingpp_hook
+ @pingpp_base_class = Spree::Gateway::PingppBase
+
+ return unless @order.next_step_complete?
+ #in confirm step, only param is {"state"=>"confirm"}
+ payment_method = get_payment_method_by_params( )
+ if payment_method.kind_of?( @pingpp_base_class )
+ handle_pingpp( payment_method )
+ end
+ end
+
+ # handle all supported billing_integration
+ def handle_pingpp( payment_method )
+ if @order.update_from_params( params, permitted_checkout_attributes, request.headers.env )
+ pingpp_channel = params['payment_pingpp'][payment_method.id.to_s]
+ #more flow detail
+ #https://pingxx.com/guidance/products/sdk
+ payment_provider = payment_method.provider
+ #please try with host 127.0.0.1 instead localhost, or get invalid url http://localhost:3000/...
+ #order_path( order, :only_path => false )
+ begin
+ @charge = payment_provider.create_charge( @order, pingpp_channel, spree.pingpp_charge_done_path( :only_path => false ) )
+ #redirect_to payment_provider.get_payment_url( charge )
+ #render json: charge
+ render( :payment_pingpp_dispatch ) and return
+ rescue Pingpp::PingppError => error
+ Rails.logger.error error
+ redirect_to checkout_state_path( @order.state )
+ end
+ else
+ render( :edit ) and return
+ end
+ end
+
+ private
+
+ def get_payment_method_by_params
+ payment_method_id = params[:order].try(:[],:payments_attributes).try(:first).try(:[],:payment_method_id).to_i
+ Spree::PaymentMethod.find_by_id(payment_method_id)
+ end
+
+ end
+end
diff --git a/spree_pingpp/app/controllers/spree/pingpp_status_controller.rb b/spree_pingpp/app/controllers/spree/pingpp_status_controller.rb
new file mode 100644
index 00000000..a0701c44
--- /dev/null
+++ b/spree_pingpp/app/controllers/spree/pingpp_status_controller.rb
@@ -0,0 +1,61 @@
+#inspired by https://github.com/spree-contrib/spree_skrill
+module Spree
+ class PingppStatusController < StoreController
+ include Gateway::PingppHelper
+
+ #fixes Action::Controller::InvalidAuthenticityToken error on alipay_notify
+ skip_before_action :verify_authenticity_token
+
+ # success url
+ def charge_done
+ #alipay, get, "result"=>"success", "out_trade_no"=>"R677576938"
+ #upacp_pc, post, "orderId"=>"R677576938", "respMsg"=>"success"
+ order = retrieve_order
+ # get charge from server, notify message may be delay
+ unless order.complete?
+ payment_method = order.payments.last.payment_method
+ if payment_method.kind_of? Gateway::PingppBase
+ charge = payment_method.provider.retrieve_charge( order )
+ if charge['paid']
+ order.reload
+ end
+ end
+ end
+ if order.complete?
+ redirect_to spree.order_path( order )
+ else
+ redirect_to checkout_state_path(order.state)
+ end
+ end
+
+ def charge_notify
+ begin
+ event = JSON.parse( request.raw_post )
+ response_status, response_body = Gateway::PingppEventHandler.new( event ).perform
+ rescue JSON::ParserError
+ response_body = 'JSON 解析失败'
+ end
+ render plain: response_body, status: response_status, content_type: 'text/plain; charset=utf-8'
+ end
+
+ def test_charge_notify
+ begin
+ event = JSON.parse( request.raw_post )
+ response_status, response_body = Gateway::PingppEventHandler.new( event ).perform
+ rescue JSON::ParserError
+ response_body = 'JSON 解析失败'
+ end
+ render plain: response_body, status: response_status, content_type: 'text/plain; charset=utf-8'
+ end
+
+
+ private
+
+ def retrieve_order()
+ order_number = ( params["orderId"] || params["out_trade_no"] )
+ # channel alipay_wap cannel_url is charge_done, order_number maybe nil in that case.
+ Spree::Order.find_by_number(order_number) || current_order
+ end
+
+ end
+end
diff --git a/spree_pingpp/app/models/spree/gateway/pingpp_base.rb b/spree_pingpp/app/models/spree/gateway/pingpp_base.rb
new file mode 100644
index 00000000..20c813b0
--- /dev/null
+++ b/spree_pingpp/app/models/spree/gateway/pingpp_base.rb
@@ -0,0 +1,29 @@
+require "pingpp"
+module Spree
+ class Gateway::PingppBase < PaymentMethod
+ preference :api_key, :string
+ preference :app_key, :string
+ preference :channels, :string
+ #Pingpp.api_key = "YOUR-KEY"
+
+ delegate :purchase, to: :provider
+
+ def provider_class
+ Gateway::PingppProvider
+ end
+
+ def provider
+ provider_class.new( self )
+ end
+
+ # it is required to make payment completed.
+ def source_required?
+ true
+ end
+
+ def available_channels
+ self.preferred_channels.try(:split, ',') || []
+ end
+
+ end
+end
diff --git a/spree_pingpp/app/models/spree/gateway/pingpp_event_handler.rb b/spree_pingpp/app/models/spree/gateway/pingpp_event_handler.rb
new file mode 100644
index 00000000..52ac8713
--- /dev/null
+++ b/spree_pingpp/app/models/spree/gateway/pingpp_event_handler.rb
@@ -0,0 +1,39 @@
+require "pingpp"
+module Spree
+ class Gateway::PingppEventHandler
+ include Gateway::PingppHelper
+
+ attr_accessor :event, :response_body, :status
+ def initialize( event )
+ self.event = event
+ status = 400
+ response_body = '' # 可自定义
+ end
+
+ def perform
+ if event['type'].nil?
+ response_body = 'missing Event type'
+ elsif event['type'] == 'charge.succeeded'
+ charge_succeeded
+ elsif event['object'] == 'refund.succeeded'
+ # 开发者在此处加入对退款异步通知的处理代码
+ status = 200
+ response_body = 'OK'
+ else
+ response_body = 'unkonwn Event type'
+ end
+ return status, response_body
+ end
+
+ def charge_succeeded
+ charge = event['data']['object']
+ order = get_order_by_charge charge
+ if order
+ complete_order order
+ end
+ self.status = 200
+ self.response_body = 'OK'
+ end
+
+ end
+end
diff --git a/spree_pingpp/app/models/spree/gateway/pingpp_helper.rb b/spree_pingpp/app/models/spree/gateway/pingpp_helper.rb
new file mode 100644
index 00000000..ba9664dc
--- /dev/null
+++ b/spree_pingpp/app/models/spree/gateway/pingpp_helper.rb
@@ -0,0 +1,22 @@
+module Spree
+ # helpers
+ module Gateway::PingppHelper
+
+ def get_order_by_charge( charge )
+ Spree::Order.find_by_number( charge['order_no'] )
+ end
+
+ def get_payment_by_order( order )
+ order.payments.last
+ end
+
+ def complete_order( order )
+ order.next
+ end
+
+ def get_order_by_gateway_options( gateway_options )
+ gateway_order_id = gateway_options[:order_id]
+ end
+
+ end
+end
diff --git a/spree_pingpp/app/models/spree/gateway/pingpp_mobile.rb b/spree_pingpp/app/models/spree/gateway/pingpp_mobile.rb
new file mode 100644
index 00000000..f65f641b
--- /dev/null
+++ b/spree_pingpp/app/models/spree/gateway/pingpp_mobile.rb
@@ -0,0 +1,10 @@
+require "pingpp"
+module Spree
+ class Gateway::PingppMobile < Gateway::PingppBase
+
+ def auto_capture?
+ true
+ end
+
+ end
+end
diff --git a/spree_pingpp/app/models/spree/gateway/pingpp_pc.rb b/spree_pingpp/app/models/spree/gateway/pingpp_pc.rb
new file mode 100644
index 00000000..068db929
--- /dev/null
+++ b/spree_pingpp/app/models/spree/gateway/pingpp_pc.rb
@@ -0,0 +1,11 @@
+require "pingpp"
+module Spree
+ class Gateway::PingppPc < Gateway::PingppBase
+
+ def auto_capture?
+ true
+ end
+
+
+ end
+end
diff --git a/spree_pingpp/app/models/spree/gateway/pingpp_provider.rb b/spree_pingpp/app/models/spree/gateway/pingpp_provider.rb
new file mode 100644
index 00000000..ab72d149
--- /dev/null
+++ b/spree_pingpp/app/models/spree/gateway/pingpp_provider.rb
@@ -0,0 +1,130 @@
+require "pingpp"
+module Spree
+ class Gateway::PingppProvider
+ include Gateway::PingppHelper
+ #PINGPP_NOTIFY_URL = 'https://api.pingxx.com/notify/charges/',
+ #PINGPP_MOCK_URL = 'http://sissi.pingxx.com/mock.php',
+ #ALIPAY_PC_DIRECT_URL = 'https://mapi.alipay.com/gateway.do',
+ #UPACP_PC_URL = 'https://gateway.95516.com/gateway/api/frontTransReq.do'
+
+ PingppPcChannelEnum = Struct.new( :alipay_pc_direct, :upacp_pc )[ 'alipay_pc_direct', 'upacp_pc' ]
+ PingppWapChannelEnum = Struct.new( :alipay_wap, :upacp_wap )[ 'alipay_wap', 'upacp_wap']
+ attr_accessor :payment_method
+
+ def initialize( payment_method )
+ self.payment_method = payment_method
+ setup_api_key( payment_method.preferred_api_key )
+ end
+
+ def setup_api_key( key )
+ Pingpp.api_key = key
+ end
+
+ def create_charge( order, channel, success_url )
+ channel ||= PingppPcChannelEnum.alipay_pc_direct
+ params = {
+ :order_no => order.number,
+ :amount => (order.total * 100).to_i, # in cent
+ :subject => "Order : #{order.number}",
+ :body => order.products.collect(&:name).to_s, #String(400)
+ :channel => channel,
+ :currency => "cny",
+ :client_ip=> order.last_ip_address,
+ :app => { :id => payment_method.preferred_app_key },
+ }
+ extra_alipay_params= {
+ :extra => {
+ # alipay
+ :success_url => success_url #
+ }
+ }
+ extra_alipay_wap_params= {
+ :extra => {
+ # alipay
+ :cancel_url => success_url,
+ :success_url => success_url #
+ }
+ }
+ extra_upacp_params= {
+ :extra => {
+ # upacp
+ :result_url => success_url #
+ }
+ }
+
+ case channel
+ when PingppPcChannelEnum.alipay_pc_direct
+ params.merge! extra_alipay_params
+ when PingppPcChannelEnum.upacp_pc
+ params.merge! extra_upacp_params
+ when PingppWapChannelEnum.alipay_wap
+ params.merge! extra_alipay_wap_params
+ when PingppWapChannelEnum.upacp_wap
+ params.merge! extra_upacp_params
+ end
+ charge = Pingpp::Charge.create( params )
+ # store charge "id": "ch_Hm5uTSifDOuTy9iLeLPSurrD",
+ payment = get_payment_by_order( order )
+ payment.update_attribute( :response_code, charge['id'] )
+
+ charge
+ end
+
+ def retrieve_charge( order )
+ payment = get_payment_by_order( order )
+ charge = Pingpp::Charge.retrieve( payment.response_code )
+ end
+
+ #def get_payment_url( charge )
+ # channel = charge['channel'];
+ # raise "no_such_channel: #{channel}" unless PingppPcChannelEnum.values.include? channel
+ # raise "no_credential" unless charge['credential'].present?
+ # raise "no_valid_channel_credential" unless charge['credential'][channel].present?
+ # if charge['livemode'] == false
+ # return test_mode_notify_url(charge);
+ # end
+ # credential = charge['credential'][channel];
+ # if channel == PingppPcChannelEnum.upacp_pc
+ # form_submit(cfg.UPACP_PC_URL, 'post', credential);
+ # elsif channel == PingppPcChannelEnum.alipay_pc_direct
+ # credential["_input_charset"] = 'utf-8';
+ # ALIPAY_PC_DIRECT_URL + "?" + credential.to_param;
+ # end
+ #end
+
+ #def test_mode_notify_url(charge)
+ # params = { ch_id: charge['id'], scheme: 'http', channel: charge['channel'] }
+ # if charge['order_no']
+ # params['order_no'] = charge['order_no']
+ # elsif charge['orderNo']
+ # params['order_no'] = charge['orderNo']
+ # end
+ # if charge['time_expire']
+ # params['time_expire'] = charge['time_expire']
+ # elsif charge['timeExpire']
+ # params['time_expire'] = charge['timeExpire']
+ # end
+ # if charge['extra']
+ # params['extra'] = charge['extra'].to_json
+ # end
+ # PINGPP_MOCK_URL+'?'+ params.to_param
+ #end
+
+
+ def cancel( order )
+ Pingpp::Charge.retrieve("CHARGE_ID").refunds.create(:description => "Refund Description")
+ end
+
+ # * description - before order transition to: :complete
+ # * call spree/payment#gateway_action
+ # * params
+ # * options - gateway_options
+ # * return - pingpp_response
+ def purchase(money, credit_card, options = {})
+ # since pingpp is offsite payment, this method is placehodler only.
+ # in this way, we could go through spree payment process.
+ return Gateway::PingppResponse.new
+ end
+
+ end
+end
diff --git a/spree_pingpp/app/models/spree/gateway/pingpp_response.rb b/spree_pingpp/app/models/spree/gateway/pingpp_response.rb
new file mode 100644
index 00000000..71cc49a0
--- /dev/null
+++ b/spree_pingpp/app/models/spree/gateway/pingpp_response.rb
@@ -0,0 +1,9 @@
+module Spree
+ class Gateway::PingppResponse
+ attr_accessor :authorization
+
+ def success?
+ true
+ end
+ end
+end
diff --git a/spree_pingpp/app/models/spree/order_decorator.rb b/spree_pingpp/app/models/spree/order_decorator.rb
new file mode 100644
index 00000000..ac455af4
--- /dev/null
+++ b/spree_pingpp/app/models/spree/order_decorator.rb
@@ -0,0 +1,8 @@
+Spree::Order.class_eval do
+
+ def next_step_complete?
+ available_steps = checkout_steps
+ available_steps[ available_steps.index( self.state ).succ ] == 'complete'
+ end
+
+end
diff --git a/spree_pingpp/app/models/spree/payment_decorator.rb b/spree_pingpp/app/models/spree/payment_decorator.rb
new file mode 100644
index 00000000..7c1bccd9
--- /dev/null
+++ b/spree_pingpp/app/models/spree/payment_decorator.rb
@@ -0,0 +1,26 @@
+Spree::Payment.class_eval do
+ # order/payments, payment/processing
+ # order.process_payments! => payment.process! => handle_payment_preconditions { process_purchase }
+ def handle_payment_preconditions(&block)
+ unless block_given?
+ raise ArgumentError.new("handle_payment_preconditions must be called with a block")
+ end
+
+ if payment_method && payment_method.source_required?
+ if source
+ if !processing?
+ if payment_method.supports?(source) || token_based?
+ yield
+ else
+ invalidate!
+ raise Core::GatewayError.new(Spree.t(:payment_method_not_supported))
+ end
+ end
+ elsif payment_method.kind_of? Spree::Gateway::PingppBase
+ yield
+ else
+ raise Core::GatewayError.new(Spree.t(:payment_processing_failed))
+ end
+ end
+ end
+end
diff --git a/spree_pingpp/app/views/spree/checkout/payment/_pingppmobile.html.erb b/spree_pingpp/app/views/spree/checkout/payment/_pingppmobile.html.erb
new file mode 100644
index 00000000..61a6fdfc
--- /dev/null
+++ b/spree_pingpp/app/views/spree/checkout/payment/_pingppmobile.html.erb
@@ -0,0 +1,5 @@
+
+<% payment_method.available_channels.each_with_index{|channel, i| %>
+ <%= hidden_field_tag "payment_pingpp[#{payment_method.id}]", channel %>
+ <%= image_tag "billing_integrations/pingpp/#{channel}.jpg", alt: Spree.t( "pingpp_channel.#{channel}") %>
+<% } %>
diff --git a/spree_pingpp/app/views/spree/checkout/payment/_pingpppc.html.erb b/spree_pingpp/app/views/spree/checkout/payment/_pingpppc.html.erb
new file mode 100644
index 00000000..61a6fdfc
--- /dev/null
+++ b/spree_pingpp/app/views/spree/checkout/payment/_pingpppc.html.erb
@@ -0,0 +1,5 @@
+
+<% payment_method.available_channels.each_with_index{|channel, i| %>
+ <%= hidden_field_tag "payment_pingpp[#{payment_method.id}]", channel %>
+ <%= image_tag "billing_integrations/pingpp/#{channel}.jpg", alt: Spree.t( "pingpp_channel.#{channel}") %>
+<% } %>
diff --git a/spree_pingpp/app/views/spree/checkout/payment_pingpp_dispatch.html.erb b/spree_pingpp/app/views/spree/checkout/payment_pingpp_dispatch.html.erb
new file mode 100644
index 00000000..3d639f3e
--- /dev/null
+++ b/spree_pingpp/app/views/spree/checkout/payment_pingpp_dispatch.html.erb
@@ -0,0 +1,19 @@
+<%
+pingpp_object_name = ( Spree::Gateway::PingppProvider::PingppPcChannelEnum.values.include?( @charge['channel'] ) ? 'pingppPc' : 'pingpp' )
+%>
+
+
+ Payment page loading
+
+<%= javascript_tag defer: 'defer' do -%>
+<%= pingpp_object_name%>.createPayment( <%== @charge.to_json %>, function(result, err){
+ if( result == "success" ){
+
+ }else if(result == "fail" ){
+ alert(err)
+ }else if( result == "cancel" ){
+ alert(err)
+ }
+
+} )
+<% end %>
diff --git a/spree_pingpp/bin/rails b/spree_pingpp/bin/rails
new file mode 100644
index 00000000..e5539d0f
--- /dev/null
+++ b/spree_pingpp/bin/rails
@@ -0,0 +1,7 @@
+# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
+
+ENGINE_ROOT = File.expand_path('../..', __FILE__)
+ENGINE_PATH = File.expand_path('../../lib/spree_pingpp/engine', __FILE__)
+
+require 'rails/all'
+require 'rails/engine/commands'
diff --git a/spree_pingpp/config/locales/en.yml b/spree_pingpp/config/locales/en.yml
new file mode 100644
index 00000000..36a26416
--- /dev/null
+++ b/spree_pingpp/config/locales/en.yml
@@ -0,0 +1,10 @@
+# Sample localization file for English. Add more files in this directory for other locales.
+# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
+
+en:
+ spree:
+ pingpp_channel:
+ alipay_pc_direct: Alipay PC direct
+ alipay_wap: Alipay Phone
+ upacp_pc: UnionPay PC
+ upacp_wap: UnionPay Phone
diff --git a/spree_pingpp/config/locales/zh-CN.yml b/spree_pingpp/config/locales/zh-CN.yml
new file mode 100644
index 00000000..aae0c0d4
--- /dev/null
+++ b/spree_pingpp/config/locales/zh-CN.yml
@@ -0,0 +1,10 @@
+# Sample localization file for English. Add more files in this directory for other locales.
+# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
+
+zh-CN:
+ spree:
+ pingpp_channel:
+ alipay_pc_direct: 支付宝
+ alipay_wap: Alipay Phone
+ upacp_pc: 银联
+ upacp_wap: UnionPay Phone
diff --git a/spree_pingpp/config/routes.rb b/spree_pingpp/config/routes.rb
new file mode 100644
index 00000000..c958c699
--- /dev/null
+++ b/spree_pingpp/config/routes.rb
@@ -0,0 +1,11 @@
+Spree::Core::Engine.routes.draw do
+ # Add your extension routes here
+ patch '/checkout/handle_pingpp', :to => 'checkout#handle_pingpp', as: :handle_pingpp, format: :json
+
+ # called by pingpp webhook
+ post '/pingpp/charge_notify', :to=> 'pingpp_status#charge_notify'
+ post '/pingpp/test_charge_notify', :to=> 'pingpp_status#test_charge_notify'
+ # alipay get, upacp_pc post
+ match '/pingpp/charge_done', :to=> 'pingpp_status#charge_done', as: :pingpp_charge_done, via: [:get, :post]
+
+end
diff --git a/spree_pingpp/lib/generators/spree_pingpp/install/install_generator.rb b/spree_pingpp/lib/generators/spree_pingpp/install/install_generator.rb
new file mode 100644
index 00000000..c672ab7a
--- /dev/null
+++ b/spree_pingpp/lib/generators/spree_pingpp/install/install_generator.rb
@@ -0,0 +1,31 @@
+module SpreePingpp
+ module Generators
+ class InstallGenerator < Rails::Generators::Base
+
+ class_option :auto_run_migrations, :type => :boolean, :default => false
+
+ def add_javascripts
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/spree_pingpp\n"
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/spree_pingpp\n"
+ end
+
+ def add_stylesheets
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/spree_pingpp\n", :before => /\*\//, :verbose => true
+ inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/spree_pingpp\n", :before => /\*\//, :verbose => true
+ end
+
+ def add_migrations
+ run 'bundle exec rake railties:install:migrations FROM=spree_pingpp'
+ end
+
+ def run_migrations
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
+ if run_migrations
+ run 'bundle exec rake db:migrate'
+ else
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
+ end
+ end
+ end
+ end
+end
diff --git a/spree_pingpp/lib/spree_pingpp.rb b/spree_pingpp/lib/spree_pingpp.rb
new file mode 100644
index 00000000..df7f44aa
--- /dev/null
+++ b/spree_pingpp/lib/spree_pingpp.rb
@@ -0,0 +1,3 @@
+require 'spree_core'
+require 'spree_pingpp/engine'
+require 'sass/rails'
diff --git a/spree_pingpp/lib/spree_pingpp/engine.rb b/spree_pingpp/lib/spree_pingpp/engine.rb
new file mode 100644
index 00000000..d08b0367
--- /dev/null
+++ b/spree_pingpp/lib/spree_pingpp/engine.rb
@@ -0,0 +1,28 @@
+module SpreePingpp
+ class Engine < Rails::Engine
+ require 'spree/core'
+ isolate_namespace Spree
+ engine_name 'spree_pingpp'
+
+ # use rspec for tests
+ config.generators do |g|
+ g.test_framework :rspec
+ end
+
+ def self.activate
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
+ Rails.configuration.cache_classes ? require(c) : load(c)
+ end
+ end
+
+ config.to_prepare &method(:activate).to_proc
+
+
+ config.after_initialize do |app|
+ app.config.spree.payment_methods += [
+ Spree::Gateway::PingppPc,
+ Spree::Gateway::PingppMobile
+ ]
+ end
+ end
+end
diff --git a/spree_pingpp/lib/spree_pingpp/factories.rb b/spree_pingpp/lib/spree_pingpp/factories.rb
new file mode 100644
index 00000000..08019404
--- /dev/null
+++ b/spree_pingpp/lib/spree_pingpp/factories.rb
@@ -0,0 +1,6 @@
+FactoryGirl.define do
+ # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
+ #
+ # Example adding this to your spec_helper will load these Factories for use:
+ # require 'spree_pingpp/factories'
+end
diff --git a/spree_pingpp/spec/features/pingpp_pc_spec.rb b/spree_pingpp/spec/features/pingpp_pc_spec.rb
new file mode 100644
index 00000000..0c51794b
--- /dev/null
+++ b/spree_pingpp/spec/features/pingpp_pc_spec.rb
@@ -0,0 +1,75 @@
+require 'spec_helper'
+#copy from https://raw.github.com/radar/better_spree_paypal_express/master/spec/features/paypal_spec.rb
+#http://sandbox.alipaydev.com/index.htm
+#sandbox_areq22@aliyun.com
+#http://openapi.alipaydev.com/gateway.do
+describe "Alipay", :js => true, :type => :feature do
+ let!(:product) { FactoryGirl.create(:product, :name => 'iPad') }
+
+ before do
+ @gateway = Spree::Gateway::PingppPc.create!({
+ name: "PingppPcAlipay",
+ active: true,
+ preferences: {
+ channels: 'alipay_pc_direct',
+ app_key: 'app_S8qPKGyH8SKSvfLq',
+ api_key: 'sk_test_W9azX94mLu1O4SCibPHCCyHG'
+ }
+ })
+ FactoryGirl.create(:shipping_method)
+ end
+
+
+ it "pays for an order successfully" do
+
+ payment_method_css = "#order_payments_attributes__payment_method_id_#{@gateway.id}"
+
+
+ visit spree.root_path
+ click_link product.name
+ click_button 'Add To Cart'
+ click_button 'Checkout'
+
+ #within("#guest_checkout") do
+ # fill_in "Email", :with => "test@example.com"
+ # click_button 'Continue'
+ #end
+
+ fill_in_billing
+ click_button "Save and Continue"
+ # Delivery step doesn't require any action
+ click_button "Save and Continue"
+
+ choose payment_method_css
+ click_button "Save and Continue"
+ # should redirect to pingpp mock page
+ find("#btn_pay").click
+ #page.should have_content("Your order has been processed successfully")
+ #Spree::Payment.last.should be_complete
+ end
+
+ def fill_in_billing
+ fill_in "order_email", :with => "test@example.com"
+
+ within("#billing") do
+ fill_in "First Name", :with => "Test"
+ fill_in "Last Name", :with => "User"
+ fill_in "Street Address", :with => "1 User Lane"
+ # City, State and ZIP must all match for PayPal to be happy
+ fill_in "City", :with => "Adamsville"
+ select "United States of America", :from => "order_bill_address_attributes_country_id"
+ select "Alabama", :from => "order_bill_address_attributes_state_id"
+ fill_in "Zip", :with => "35005"
+ fill_in "Phone", :with => "555-AME-RICA"
+ end
+ end
+
+ def switch_to_paypal_login
+ # If you go through a payment once in the sandbox, it remembers your preferred setting.
+ # It defaults to the *wrong* setting for the first time, so we need to have this method.
+ unless page.has_selector?("#login_email")
+ find("#loadLogin").click
+ end
+ end
+
+end
diff --git a/spree_pingpp/spec/spec_helper.rb b/spree_pingpp/spec/spec_helper.rb
new file mode 100644
index 00000000..424257cf
--- /dev/null
+++ b/spree_pingpp/spec/spec_helper.rb
@@ -0,0 +1,87 @@
+# Run Coverage report
+require 'simplecov'
+SimpleCov.start do
+ add_filter 'spec/dummy'
+ add_group 'Controllers', 'app/controllers'
+ add_group 'Helpers', 'app/helpers'
+ add_group 'Mailers', 'app/mailers'
+ add_group 'Models', 'app/models'
+ add_group 'Views', 'app/views'
+ add_group 'Libraries', 'lib'
+end
+
+# Configure Rails Environment
+ENV['RAILS_ENV'] = 'test'
+
+require File.expand_path('../dummy/config/environment.rb', __FILE__)
+
+require 'rspec/rails'
+require 'database_cleaner'
+require 'ffaker'
+
+# Requires supporting ruby files with custom matchers and macros, etc,
+# in spec/support/ and its subdirectories.
+Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
+
+# Requires factories and other useful helpers defined in spree_core.
+require 'spree/testing_support/authorization_helpers'
+require 'spree/testing_support/capybara_ext'
+require 'spree/testing_support/controller_requests'
+require 'spree/testing_support/factories'
+require 'spree/testing_support/url_helpers'
+
+# Requires factories defined in lib/spree_pingpp/factories.rb
+require 'spree_pingpp/factories'
+
+RSpec.configure do |config|
+ config.include FactoryGirl::Syntax::Methods
+
+ # Infer an example group's spec type from the file location.
+ config.infer_spec_type_from_file_location!
+
+ # == URL Helpers
+ #
+ # Allows access to Spree's routes in specs:
+ #
+ # visit spree.admin_path
+ # current_path.should eql(spree.products_path)
+ config.include Spree::TestingSupport::UrlHelpers
+
+ # == Mock Framework
+ #
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
+ #
+ # config.mock_with :mocha
+ # config.mock_with :flexmock
+ # config.mock_with :rr
+ config.mock_with :rspec
+ config.color = true
+
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
+
+ # Capybara javascript drivers require transactional fixtures set to false, and we use DatabaseCleaner
+ # to cleanup after each test instead. Without transactional fixtures set to false the records created
+ # to setup a test will be unavailable to the browser, which runs under a separate server instance.
+ config.use_transactional_fixtures = false
+
+ # Ensure Suite is set to use transactions for speed.
+ config.before :suite do
+ DatabaseCleaner.strategy = :transaction
+ DatabaseCleaner.clean_with :truncation
+ end
+
+ # Before each spec check if it is a Javascript test and switch between using database transactions or not where necessary.
+ config.before :each do
+ DatabaseCleaner.strategy = RSpec.current_example.metadata[:js] ? :truncation : :transaction
+ DatabaseCleaner.start
+ end
+
+ # After each spec clean the database.
+ config.after :each do
+ DatabaseCleaner.clean
+ end
+
+ config.fail_fast = ENV['FAIL_FAST'] || false
+ config.order = "random"
+end
diff --git a/spree_pingpp/spree_pingpp.gemspec b/spree_pingpp/spree_pingpp.gemspec
new file mode 100644
index 00000000..b90c1704
--- /dev/null
+++ b/spree_pingpp/spree_pingpp.gemspec
@@ -0,0 +1,32 @@
+# encoding: UTF-8
+Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = 'spree_pingpp'
+ s.version = '2.4.10'
+ s.summary = 'spree pingpp'
+ s.description = 'spree extension payment pingpp'
+ s.required_ruby_version = '>= 1.9.3'
+
+ s.author = 'David'
+ s.email = 'areq22@gmail.com'
+ s.homepage = 'http://www.getstore.cn'
+
+ #s.files = `git ls-files`.split("\n")
+ #s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.require_path = 'lib'
+ s.requirements << 'none'
+
+ s.add_dependency 'spree_core', '~> 2.4.10'
+ s.add_dependency 'pingpp', '~> 2.0.8'
+
+ s.add_development_dependency 'capybara', '~> 2.4'
+ s.add_development_dependency 'coffee-rails'
+ s.add_development_dependency 'database_cleaner'
+ s.add_development_dependency 'factory_girl', '~> 4.5'
+ s.add_development_dependency 'ffaker'
+ s.add_development_dependency 'rspec-rails', '~> 3.1'
+ s.add_development_dependency 'sass-rails', '~> 4.0.2'
+ s.add_development_dependency 'selenium-webdriver'
+ s.add_development_dependency 'simplecov'
+ s.add_development_dependency 'sqlite3'
+end
diff --git a/spree_theme/Gemfile b/spree_theme/Gemfile
index 583b777d..f733fbe4 100644
--- a/spree_theme/Gemfile
+++ b/spree_theme/Gemfile
@@ -1,16 +1,14 @@
source 'http://rubygems.org'
+#source "https://rails-assets.org"
+eval(File.read(File.dirname(__FILE__) + '/../common_spree_dependencies.rb'))
-gem 'spree', :github => "spree/spree", :branch => "2-0-stable"
-
group :test,:development do
- gem 'ruby-graphviz' #print checkout flow
- gem 'simplecov' #rspec using it.
+ #gem 'ruby-graphviz' #print checkout flow
+ #gem 'simplecov' #rspec using it.
#using backend required
- gem 'spree_auth_devise', :github => 'spree/spree_auth_devise', :branch => '2-0-stable'
gem "mysql2"
- gem 'thin'
end
#group :test do
@@ -20,18 +18,16 @@ end
gem "acts_as_list"
gem "acts_as_tree"
gem "awesome_nested_set"
+gem 'acts_as_commentable'
-#use paperclip instead of dragonfly, dragonfly have no way to configure image path
-#gem "paperclip", "2.8.0" # spree require it.
-gem "responds_to_parent"
# spree already contain
#gem 'jquery-rails'
-#gem 'jquery-ui-rails'
+gem 'useragent'
gem "friendly_id"
-group :assets do
- gem 'sass'
- gem 'coffee-rails'
-end
#gem 'ssl_requirement'
+
+#gem 'bootstrap-sass', '~> 3.3.1'
+#gem 'sass-rails', '>= 3.2'
+
gemspec
diff --git a/spree_theme/README.md b/spree_theme/README.md
index bde58218..dfb7576f 100644
--- a/spree_theme/README.md
+++ b/spree_theme/README.md
@@ -1,101 +1,56 @@
-SpreeTheme
-==========
-
-New frontend of spree, user could easy modify theme or add new theme. It is not working now!
-It is just for spree_abc, not common use, cause it override some cart/checkout views.
-
-how it work
------------
- roles: designer, user, customer
- sites: design site, shopping site
- a design/shopping site must have a released theme, or redirect to under_contruction.
- released theme contains layout, js, css. each release has own folder.
- a designer could login and design new theme.
-
-
- designer
- 0. new theme
- 1. design theme
- 2. release completed theme. generate themeN/versionN.html.erb
- 3. theme is viewable by public. shops/themes/themeN/
- designs.dalianshops.com?theme_id=N
-
- backend
+#SpreeTheme
+
+New frontend of spree, user could easy modify theme or add new theme.
+__It is just for spree_abc, not common use.__
+
+####terms and conditions
+Each site want their own theme, site could have more than one themes.
+Theme should be configurable, site could assigned their own data to it.
+Each site could select preferred theme from all available list.
+Designer could design theme and release it.
+
+Shops
+* design shop: product is theme, designer produce theme on line.
+* other shop: use released theme as frentend, sell product on line.
+
+Roles
+* user: on line shop user, have full permission to manage shop.
+* customer: shopping on line.
+* designer: login design site, design template on line.
+
+Themes
+* theme: a theme of site, contains html, js, css.
+
+
+####How it work
+designer produce theme
+ 0. in design shop, create new theme.
+ 1. design theme vie editor.
+ 2. release completed theme, generate theme files themeX/html, css, js
+ 3. theme is public now. user could import, config and publish.
+
+user apply theme to site
1. user browse available themes, snapshot or live demo.
- 2. import preferred theme
- *3. preview it. Do not support it now, find a clean way support tld/admin/add_to_cart first.
- 4. apply it to frontend
-
-requirement
- admin.sometld/... is for user preview, ex. admin.somtld/some_taxon
- www.sometld/... is for customer, ex. www.sometld/some_taxon
-
-how roles get layout?
----------------------
- designer: get current editing template
- customer: get layout from current site
-
-path
-----
- 1. designer design product list page
- www.tld/tid
- 2. designer design product detail page
- www.tld/tid/pid
- 2. designer release design
- www.tld/admin/template_theme
- 3. customer view product list
- www.tld/tid -> /var/www/shops/n/
- 4. customer view product detail
- www.tld/tid/pid
- 5. admin manage site
- www.tld/admin/...
- 6. user login
- www.tld/admin/
- 7. customer view live template demo
- templates.dalianshops.com -> /var/www/shops/1
- 8. customer browse published template list
- www.tld/admin/template_themes/
- 9. shop folders
- template folder
- t(current template id)-> /var/www/shops/1/t(original template id)
- theme image folder:
- tx/images
- generated layout
- tx/tx.html.erb
- theme css, js
- tx/cssx.css
- tx/jsx.js
- page_layout image folder: images belongs to shop, like logo
- lx
-
-configure
----------
- website theme_id, index_page should greater than 0.
- website index_page could equal to 0.
-
-extra feature for theme
------------------------
- option value has image, please look at https://github.com/citrus/spree_variant_options for detail
-
-Installation
-============
+ 2. import preferred theme,
+ 3. configure it with site data.
+ 4. apply it as frontend
+####Installation(tbd...)
rake spree_theme:install:migrations
rake db:migrate
rails r "SpreeeTheme::Engine.load_seed"
in config/spree.rb
- SpreeTheme.website_class = 'Spree::FakeWebsite'
- SpreeTheme.taxon_class = 'Spree::Taxon'
-
+SpreeTheme.website_class = 'Spree::FakeWebsite'
+SpreeTheme.taxon_class = 'Spree::Taxon'
Load sample
------------
+
rake spree_theme:load_samples
rake spree_theme:import_theme
-Testing
--------
+####Testing(tbd...)
rake test_app
+
change db from sqlite to mysql, fix id setting, rails sqlite adapter ignore id setting
rake db:seed RAILS_ENV=test
rake spree_theme:import_theme RAILS_ENV=test SEED_PATH=1 THEME_ID=2
diff --git a/spree_theme/Rakefile b/spree_theme/Rakefile
index 9bb1d6ec..c605a5f7 100644
--- a/spree_theme/Rakefile
+++ b/spree_theme/Rakefile
@@ -2,14 +2,20 @@ require 'bundler'
Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
-require 'spree/testing_support/common_rake'
+require 'spree/testing_support/extension_rake'
RSpec::Core::RakeTask.new
-task :default => [:spec]
+task :default do
+ if Dir["spec/dummy"].empty?
+ Rake::Task[:test_app].invoke
+ Dir.chdir("../../")
+ end
+ Rake::Task[:spec].invoke
+end
desc 'Generates a dummy app for testing'
task :test_app do
ENV['LIB_NAME'] = 'spree_theme'
- Rake::Task['common:test_app'].invoke
-end
\ No newline at end of file
+ Rake::Task['extension:test_app'].invoke
+end
diff --git a/spree_theme/app/assets/javascripts/admin/resource_autocomplete.js.erb b/spree_theme/app/assets/javascripts/admin/resource_autocomplete.js.erb
index e69de29b..b3d1aa2b 100644
--- a/spree_theme/app/assets/javascripts/admin/resource_autocomplete.js.erb
+++ b/spree_theme/app/assets/javascripts/admin/resource_autocomplete.js.erb
@@ -0,0 +1,50 @@
+// copy from spree/backend/assets/javascripts/admin/taxon_autocomlete.js.erb
+// locals {:dom_id, :multiple, :search_url} # Spree.routes.taxons_search or Spree.routes.global_taxons_search
+'use strict';
+
+var set_resource_taxon_select = function(dom_id, multiple, search_url){
+ if ($('#'+dom_id).length > 0) {
+ $('#'+dom_id).select2({
+ placeholder: Spree.translations.taxon_placeholder,
+ multiple: multiple,
+ initSelection: function (element, callback) {
+ var url = Spree.url(search_url, {
+ ids: element.val()
+ });
+ return $.getJSON(url, null, function (data) {
+ if(multiple){
+ return callback(data['taxons']);
+ } else {
+ return callback(data['taxons'].pop());
+ }
+ });
+ },
+ ajax: {
+ url: search_url,
+ datatype: 'json',
+ data: function (term, page) {
+ return {
+ per_page: 50,
+ page: page,
+ q: {
+ name_cont: term
+ }
+ };
+ },
+ results: function (data, page) {
+ var more = page < data.pages;
+ return {
+ results: data['taxons'],
+ more: more
+ };
+ }
+ },
+ formatResult: function (taxon) {
+ return taxon.pretty_name;
+ },
+ formatSelection: function (taxon) {
+ return taxon.pretty_name;
+ }
+ });
+ }
+}
diff --git a/spree_theme/app/assets/javascripts/admin/spree_theme.js b/spree_theme/app/assets/javascripts/admin/spree_theme.js
index e154ca94..061e5cdf 100644
--- a/spree_theme/app/assets/javascripts/admin/spree_theme.js
+++ b/spree_theme/app/assets/javascripts/admin/spree_theme.js
@@ -2,10 +2,13 @@
//= require jquery.ajax
//= require jquery.jeditable
//= require admin/resource_autocomplete
+//= require store/spree_theme.routes
+
+
jQuery(function ($) {
$('#page_layout_tree_inner').bind('select_node.jstree', function (e, data) {
var selected_node = data.rslt.obj
- var url = [Spree.routes.admin_template_themes, selected_node.data('tid'), 'page_layout',selected_node.data('lid'), selected_node.data('action') ].join('/')
+ var url = [Spree.routes.admin_page_layouts( selected_node.data('tid')),selected_node.data('lid'), selected_node.data('action') ].join('/')
$.ajax({ url: url, type: 'GET', dataType: "script"})
}).bind('deselect_all.jstree', function (e, data) {
//$(this).find('select').hide()
@@ -16,8 +19,7 @@ jQuery(function ($) {
core : { multiple: false, animation: 0 }
}
);
- //$('#page_layout_tree_inner select.select22').select2();
-
+
$('#listing_template_themes .editable').editable(function(value, settings) {
var jquery_element = $(this)
diff --git a/spree_theme/app/assets/javascripts/hoverIntent.js b/spree_theme/app/assets/javascripts/hoverIntent.js
new file mode 100644
index 00000000..cbe3ae71
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/hoverIntent.js
@@ -0,0 +1,114 @@
+/**
+ * hoverIntent is similar to jQuery's built-in "hover" method except that
+ * instead of firing the handlerIn function immediately, hoverIntent checks
+ * to see if the user's mouse has slowed down (beneath the sensitivity
+ * threshold) before firing the event. The handlerOut function is only
+ * called after a matching handlerIn.
+ *
+ * hoverIntent r7 // 2013.03.11 // jQuery 1.9.1+
+ * http://cherne.net/brian/resources/jquery.hoverIntent.html
+ *
+ * You may use hoverIntent under the terms of the MIT license. Basically that
+ * means you are free to use hoverIntent as long as this header is left intact.
+ * Copyright 2007, 2013 Brian Cherne
+ *
+ * // basic usage ... just like .hover()
+ * .hoverIntent( handlerIn, handlerOut )
+ * .hoverIntent( handlerInOut )
+ *
+ * // basic usage ... with event delegation!
+ * .hoverIntent( handlerIn, handlerOut, selector )
+ * .hoverIntent( handlerInOut, selector )
+ *
+ * // using a basic configuration object
+ * .hoverIntent( config )
+ *
+ * @param handlerIn function OR configuration object
+ * @param handlerOut function OR selector for delegation OR undefined
+ * @param selector selector OR undefined
+ * @author Brian Cherne
+ **/
+(function($) {
+ $.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
+
+ // default configuration values
+ var cfg = {
+ interval: 100,
+ sensitivity: 7,
+ timeout: 0
+ };
+
+ if ( typeof handlerIn === "object" ) {
+ cfg = $.extend(cfg, handlerIn );
+ } else if ($.isFunction(handlerOut)) {
+ cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
+ } else {
+ cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
+ }
+
+ // instantiate variables
+ // cX, cY = current X and Y position of mouse, updated by mousemove event
+ // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
+ var cX, cY, pX, pY;
+
+ // A private function for getting mouse position
+ var track = function(ev) {
+ cX = ev.pageX;
+ cY = ev.pageY;
+ };
+
+ // A private function for comparing current and previous mouse position
+ var compare = function(ev,ob) {
+ ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
+ // compare mouse positions to see if they've crossed the threshold
+ if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
+ $(ob).off("mousemove.hoverIntent",track);
+ // set hoverIntent state to true (so mouseOut can be called)
+ ob.hoverIntent_s = 1;
+ return cfg.over.apply(ob,[ev]);
+ } else {
+ // set previous coordinates for next time
+ pX = cX; pY = cY;
+ // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
+ ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
+ }
+ };
+
+ // A private function for delaying the mouseOut function
+ var delay = function(ev,ob) {
+ ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
+ ob.hoverIntent_s = 0;
+ return cfg.out.apply(ob,[ev]);
+ };
+
+ // A private function for handling mouse 'hovering'
+ var handleHover = function(e) {
+ // copy objects to be passed into t (required for event object to be passed in IE)
+ var ev = jQuery.extend({},e);
+ var ob = this;
+
+ // cancel hoverIntent timer if it exists
+ if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
+
+ // if e.type == "mouseenter"
+ if (e.type == "mouseenter") {
+ // set "previous" X and Y position based on initial entry point
+ pX = ev.pageX; pY = ev.pageY;
+ // update "current" X and Y position based on mousemove
+ $(ob).on("mousemove.hoverIntent",track);
+ // start polling interval (self-calling timeout) to compare mouse coordinates over time
+ if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
+
+ // else e.type == "mouseleave"
+ } else {
+ // unbind expensive mousemove event
+ $(ob).off("mousemove.hoverIntent",track);
+ // if hoverIntent state is true, then call the mouseOut function after the specified delay
+ if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
+ }
+ };
+
+ // listen for mouseenter and mouseleave
+ return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
+ };
+})(jQuery);
\ No newline at end of file
diff --git a/spree_theme/app/assets/javascripts/image-zoom.js b/spree_theme/app/assets/javascripts/image-zoom.js
new file mode 100644
index 00000000..bed8e877
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/image-zoom.js
@@ -0,0 +1,398 @@
+/*
+ * The image zoom plugin references the jQzoom plugin, and remove the features not be used.
+ * Make the code be simple.
+ *
+ * Colin Ju
+ *
+ * jQzoom Evolution Library v2.3 - Javascript Image magnifier
+ * http://www.mind-projects.it
+ *
+ * Copyright 2011, Engineer Marco Renzi
+ * Licensed under the BSD license.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the organization nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Date: 03 May 2011 22:16:00
+ */
+(function($) {
+ var _config = {
+ thumbConfig: {
+ containerSelector: '',
+ unitSelector: 'a',
+ eventName: 'click',
+ attr: 'rel',
+ activeClassName: 'thumb-active'
+ },
+ zoomPadConfig: {
+ containerSelector: ''
+ },
+ zoomViewerConfig: {
+ width: 300,
+ height: 300
+ },
+ largeImageContainerSelector: ''
+ };
+
+ var isIE6 = (!$.support.opacity && !$.support.style && window.XMLHttpRequest==undefined),
+ doc = document,
+ win = window,
+ jWin = $(win),
+ min = Math.min;
+
+ /***
+ * Define custom event
+ */
+ var CustomEvent = {
+ eventObj: $({}),
+ bind: function() {
+ this.eventObj.bind.apply(this.eventObj, arguments);
+ },
+ trigger: function() {
+ this.eventObj.trigger.apply(this.eventObj, arguments);
+ },
+ unbind: function() {
+ this.eventObj.unbind.apply(this.eventObj, arguments);
+ }
+ };
+ /**
+ * add image zoom to jquery plugin
+ */
+ $.fn.imageZoom = function(config) {
+ return this.each(function () {
+ new ImageZoom(this, config);
+ });
+ };
+
+ /**
+ * The image zoom component entry.
+ */
+ var ImageZoom = function(container, config) {
+ var jContainer = $(container);
+ if (jContainer.data('inited') === 'y') {//Init image zoom only one time.
+ return;
+ }
+ this.jContainer = jContainer;
+ this.config = $.extend(true, _config, config || {}); //Deep copy.
+ this._init();
+ jContainer.data('inited', 'y');
+ };
+
+ $.extend(ImageZoom.prototype, {
+ constructor: ImageZoom,
+ _init: function() {
+ //Init the zoom pad component
+ var config = this.config,
+ zoomPadConfig = config.zoomPadConfig;
+
+ new ZoomPad(this.jContainer.find(zoomPadConfig.containerSelector), zoomPadConfig, config.zoomViewerConfig);
+
+ var thumbConfig = config.thumbConfig;
+ //if there is thumb list, init it.
+ if (thumbConfig && thumbConfig.containerSelector) {
+ var jThumbContainer = this.jContainer.find(thumbConfig.containerSelector);
+
+ if (jThumbContainer.length) {
+ new ThumbList(jThumbContainer, thumbConfig);
+ }
+ }
+ }
+ });
+
+ /**
+ * The thumbnail list component
+ */
+ var ThumbList = function(jContainer, config) {
+ this.jContainer = jContainer;
+ this.config = config;
+ this._init();
+ };
+
+ $.extend(ThumbList.prototype, {
+ constructor: ThumbList,
+ _init: function() {
+ this.dActiveUnit = this.jContainer.find(this.config.unitSelector).get(0);
+ this._bindEvent();
+ },
+ _bindEvent: function() {
+ var _this = this,
+ config = this.config;
+
+ this.jContainer.delegate(config.unitSelector, config.eventName, function(event) {
+ var jThis = $(this),
+ activeClassName,
+ oImagesSrc = eval('(' + $.trim(jThis.attr(config.attr)) + ')');
+
+ if (_this.dActiveUnit !== this) {
+ activeClassName = config.activeClassName;
+ $(_this.dActiveUnit).removeClass(activeClassName);
+ jThis.addClass(activeClassName);
+ _this.dActiveUnit = this;
+ CustomEvent.trigger('thumb-unit-active', oImagesSrc);
+ }
+ });
+ }
+ });
+
+ /**
+ * The zoom pad component
+ */
+ var ZoomPad = function(jContainer, zoomPadConfig, zoomViewerConfig) {
+ this.jBody = $(doc.body) // get body in function, body may not ready when loading this file
+ this.jContainer = jContainer;
+ this.zoomPadConfig = zoomPadConfig;
+ this.zoomViewerConfig = zoomViewerConfig;
+ this._init();
+ };
+
+ $.extend(ZoomPad.prototype, {
+ constructor: ZoomPad,
+ _init: function() {
+ this.largeImageLoading = false;
+ this.largeImageLoaded = false;
+ this.smallImageData = null;
+ this.largeImageData = null;
+ this.jZoomLens = null;
+ this.jZoomViewer = null;
+ this.jIframe = null;
+ this.jSmallImage = this.jContainer.find('img');
+ this.jSmallImageParent = this.jSmallImage.parent();
+ this.jLargeImage = this._createLargeImage();
+ this.jLoading = null;
+ this.eventPos = null;
+ this.isHover = false;
+ this.lensL = 0;
+ this.lensT = 0;
+ this._bindEvent();
+ if (this.jSmallImage[0].complete) {//sometimes the image is loaded and the onload will not be fired.
+ this.smallImageLoaded = true;
+ this._fetchSmallImageData();
+ }
+ },
+ _bindEvent: function() {
+ var _this = this;
+
+ this.jSmallImage.load(function() {
+ _this._fetchSmallImageData();
+ }).error(function() {
+ //TODO
+ }).hover(function(e) {
+ _this.isHover = true;
+ if (!_this.largeImageLoaded && !_this.largeImageLoading) {
+ _this._showLoading(true);
+ //_this._loadLargeImage(_this.jSmallImageParent.attr('href'));
+ _this._loadLargeImage(_this.jSmallImage.data('big-image'));
+ }
+ _this.eventPos = {
+ pageX: e.pageX,
+ pageY: e.pageY
+ };
+ }, function() {
+ _this.isHover = false;
+ });
+
+ this.jSmallImageParent.hover(function() {
+ //TODO
+ }, function() {
+ _this._hideMoveZoomLens();
+ }).click(function(e) {
+ return false;
+ }).mousemove(function(e) {
+ _this.eventPos = {
+ pageX: e.pageX,
+ pageY: e.pageY
+ };
+
+ if (_this.largeImageLoaded) {
+ var oScale = _this._getScale();
+ if (oScale.x > 1 || oScale.y > 1) {
+ _this._moveZoomLens(_this._countLensSizeAndPos());
+ }
+ }
+ });
+ this.jLargeImage.load(function() {
+ _this.largeImageLoaded = true;
+ _this.largeImageLoading = false;
+ _this._showLoading(false);
+ _this._fetchLargeImageData();
+
+ var oScale = _this._getScale();
+ if (_this.isHover && (oScale.x > 1 || oScale.y > 1)) {
+ _this._moveZoomLens(_this._countLensSizeAndPos());
+ }
+ }).error(function() {
+ _this.largeImageLoading = false;
+ _this._showLoading(false);
+ });
+ CustomEvent.bind('thumb-unit-active', function(event, oImagesSrc) {
+ _this.smallImageData = null;
+ _this.largeImageData = null;
+ _this.oScale = null;
+ _this.largeImageLoaded = false;
+ _this.largeImageLoading = false;
+ _this.jSmallImage.attr('src', oImagesSrc.smallimage).parent().attr('href', oImagesSrc.largeimage);
+ });
+ },
+ _createLargeImage: function() {
+ var jLargeImage = $(new Image());
+
+ jLargeImage.hide().appendTo(this.jBody);
+ return jLargeImage;
+ },
+ _loadLargeImage: function(src) {
+ this.largeImageLoaded = false;
+ this.largeImageLoading = true;
+ this.jLargeImage.attr('src', src);
+ },
+ _fetchSmallImageData: function() {
+ var jSmallImage = this.jSmallImage,
+ offset = jSmallImage.offset();
+
+ this.smallImageData = {
+ w: jSmallImage.width(),
+ h: jSmallImage.height(),
+ t: offset.top,
+ l: offset.left,
+ borderT: parseInt(jSmallImage.css('border-top-width').replace('px', '')),
+ borderL: parseInt(jSmallImage.css('border-left-width').replace('px', '')),
+ borderR: parseInt(jSmallImage.css('border-right-width').replace('px', ''))
+ };
+ },
+ _fetchLargeImageData: function() {
+ this.largeImageData = {
+ w: this.jLargeImage.width(),
+ h: this.jLargeImage.height()
+ }
+ },
+ _getScale: function() {
+ return {
+ x: this.largeImageData.w/this.smallImageData.w,
+ y: this.largeImageData.h/this.smallImageData.h
+ };
+ },
+ _countLensSizeAndPos: function() {
+ //the lens's position is relatived to image's parent.
+ var zoomViewerConfig = this.zoomViewerConfig,
+ oScale = this._getScale(),
+ smallImageData = this.smallImageData,
+ w = min(parseInt(zoomViewerConfig.width / oScale.x), smallImageData.w),
+ h = min(parseInt(zoomViewerConfig.height / oScale.y), smallImageData.h),
+ eventPos = this.eventPos,
+ pageX = eventPos.pageX,
+ pageY = eventPos.pageY,
+ x = pageX - smallImageData.l - smallImageData.borderL,
+ y = pageY - smallImageData.t - smallImageData.borderT,
+ lensL = pageX - smallImageData.l - w/2,
+ lensT = pageY - smallImageData.t - h/2;
+
+ if (x - w/2 <= 0) {
+ lensL = smallImageData.borderL;
+ } else if (x + w/2 >= smallImageData.w) {
+ lensL = smallImageData.w - w + smallImageData.borderL;
+ }
+ if (y - h/2 <= 0) {
+ lensT = smallImageData.borderT;
+ } else if (y + h/2 >= smallImageData.h) {
+ lensT = smallImageData.h - h + smallImageData.borderT;
+ }
+ this.lensL = lensL;
+ this.lensT = lensT;
+ return {
+ width: w,
+ height: h,
+ top: lensT,
+ left: lensL
+ };
+ },
+ _showLoading: function(isShow) {
+ var smallImageData = this.smallImageData;
+
+ this.jLoading = this.jSmallImageParent.find('div.zoom-loading');
+ if (this.jLoading.length === 0) {
+ this.jLoading = $('').appendTo(this.jSmallImageParent);
+ }
+ if (isShow) {//show loading
+ this.jLoading.css({
+ left: (this.jSmallImageParent.width() - this.jLoading.width())/2,
+ top: (this.jSmallImageParent.height() - this.jLoading.height())/2
+ }).show();
+ } else {//hide loading
+ this.jLoading.hide();
+ }
+ },
+ _moveZoomLens: function(oSizeAndPos) {
+ this.jZoomLens = this.jSmallImageParent.find('div.zoom-lens');
+ if (this.jZoomLens.length === 0) {
+ this.jZoomLens = $('').appendTo(this.jSmallImageParent);
+ }
+ this.jZoomLens.css(oSizeAndPos).show();
+ this._showZoomViewer();
+ },
+ _hideMoveZoomLens: function() {
+ if (this.jZoomLens) {
+ this.jZoomLens.hide();
+ }
+ this._hideZoomViewer();
+ },
+ _isInImageArea: function() {
+ var smallImageData = this.smallImageData,
+ eventPos = this.eventPos,
+ pageX = eventPos.pageX,
+ pageY = eventPos.pageY;
+
+ return (pageX >= smallImageData.l + smallImageData.borderL &&
+ pageX <= smallImageData.l + smallImageData.borderL + smallImageData.w &&
+ pageY >= smallImageData.t + smallImageData.borderT &&
+ pageY <= smallImageData.t + smallImageData.borderT + smallImageData.h
+ ) ? true : false;
+ },
+ _showZoomViewer: function() {
+ var smallImageData = this.smallImageData,
+ oScale = this._getScale(),
+ jImage,
+ imageSrc = this.jSmallImage.data('big-image');
+ //imageSrc = this.jSmallImageParent.attr('href');
+
+ this.jZoomViewer = this.jBody.find('div.zoom-viewer');
+ if (this.jZoomViewer.length === 0) {
+ this.jZoomViewer = $('![]() ').css(this.zoomViewerConfig).appendTo(this.jBody);
+ }
+ if (isIE6) {
+ this.jIframe = this.jBody.find('iframe.zoom-iframe');
+ if (this.jIframe.length === 0) {
+ this.jIframe = $('').css(this.zoomViewerConfig).appendTo(this.jBody);
+ }
+ this.jIframe.show();
+ }
+
+ this.jZoomViewer.css({
+ left: smallImageData.l + smallImageData.borderL + smallImageData.w + smallImageData.borderR + 10,
+ top: smallImageData.t
+ }).show();
+ jImage = this.jZoomViewer.find('img');
+ if (this.jZoomViewer.find('img').attr('src') !== imageSrc) {
+ jImage.attr('src', imageSrc);
+ }
+ jImage.css({
+ left: -((this.lensL - smallImageData.borderL) * oScale.x),
+ top: -((this.lensT - smallImageData.borderT)* oScale.y)
+ });
+ },
+ _hideZoomViewer: function() {
+ if (this.jZoomViewer) {
+ this.jZoomViewer.hide();
+ }
+ if (this.jIframe) {
+ this.jIframe.hide();
+ }
+ }
+ });
+})(jQuery);
\ No newline at end of file
diff --git a/spree_theme/app/assets/javascripts/interface.js b/spree_theme/app/assets/javascripts/interface.js
index c02c6021..d71a901b 100644
--- a/spree_theme/app/assets/javascripts/interface.js
+++ b/spree_theme/app/assets/javascripts/interface.js
@@ -10,7 +10,7 @@ function SelectorGadget() {
this.sg_div = null;
this.unbound = false;
//this.prediction_helper = new DomPredictionHelper();
- this.restricted_elements = jQuery.map(['html', 'body', 'head', 'base'], function(selector) { return jQuery(selector).get(0) });
+ this.restricted_elements = jQuery.map(['html', 'body', 'head', 'base'], function(selector) { return jQuery(selector).get(0); });
// david added at 04/28/2012 10:00
this.cover = null; // cover on the selected element
this.covers = [];
@@ -21,7 +21,7 @@ SelectorGadget.prototype = new Object();
SelectorGadget.prototype.makeBorders = function(orig_elem, makeRed) {
//this.removeBorders();
- this.cover = this.get_available_cover()
+ this.cover = this.get_available_cover();
if (this.cover==null)
{
this.setupBorders();//set cover
@@ -36,8 +36,8 @@ SelectorGadget.prototype.makeBorders = function(orig_elem, makeRed) {
var top = p.top;
var left = p.left;
- var width = elem.outerWidth()
- var height = elem.outerHeight()
+ var width = elem.outerWidth();
+ var height = elem.outerHeight();
// david added at 04/28/2012 10:00
this.cover.css('width', this.px(width)).css('height', this.px(height)).css('top', this.px(top )).css('left', this.px(left));
@@ -72,13 +72,13 @@ SelectorGadget.prototype.removeBorders = function() {
this.covers[i].hide();
}
}
-}
+};
SelectorGadget.prototype.setupBorders = function() {
if (!this.cover) {
var width = this.border_width + 'px';
// david added at 04/28/2012 10:00
- this.cover = jQuery('').addClass('sg_cover').hide()
+ this.cover = jQuery(' ').addClass('sg_cover').hide();
this.addBorderToDom();
}
};
@@ -137,10 +137,10 @@ SelectorGadget.prototype.sgMouseover = function(e) {
SelectorGadget.prototype.firstSelectedOrSuggestedParent = function(elem) {
var orig = elem;
- if (jQuery(elem).hasClass('sg_suggested') || jQuery(elem).hasClass('sg_selected')) return elem
+ if (jQuery(elem).hasClass('sg_suggested') || jQuery(elem).hasClass('sg_selected')) return elem;
while (elem.parentNode && (elem = elem.parentNode)) {
if (jQuery.inArray(elem, this.restricted_elements) == -1)
- if (jQuery(elem).hasClass('sg_suggested') || jQuery(elem).hasClass('sg_selected')) return elem
+ if (jQuery(elem).hasClass('sg_suggested') || jQuery(elem).hasClass('sg_selected')) return elem;
}
return null;
};
@@ -190,7 +190,7 @@ SelectorGadget.prototype.sgMousedown = function(e) {
gadget.selected.push(elem);
}
- gadget.clearSuggested()
+ gadget.clearSuggested();
var prediction = gadget.prediction_helper.predictCss(gadget.selected, gadget.rejected.concat(gadget.restricted_elements));
gadget.suggestPredicted(prediction);
gadget.setPath(prediction);
@@ -322,8 +322,8 @@ SelectorGadget.prototype.clearSelected = function(e) {
SelectorGadget.prototype.clearEverything = function(e) {
var self = (e && e.data && e.data.self) || this;
- self.clearSelected()
- self.resetOutputs()
+ self.clearSelected();
+ self.resetOutputs();
};
SelectorGadget.prototype.resetOutputs = function() {
diff --git a/spree_theme/app/assets/javascripts/jquery.floatBar.js b/spree_theme/app/assets/javascripts/jquery.floatBar.js
deleted file mode 100644
index 43f5cb7d..00000000
--- a/spree_theme/app/assets/javascripts/jquery.floatBar.js
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * floatBar v1.3
- * Copyright (c) 2013 Wendell http://blog.webql.info/
- * https://github.com/wendellvian/floatBar.git
-
-*/
-/*
-// liveHeight:360, // 活动高度: 取0时边栏位置为固定样式
-// bodyWidth:960, // 页面布局宽度
-// winMinHeight:600, // 浏览器最小高度
-// topFixHeight:30, // 顶部Fixed层的高度 vertical:top共用
-// spaceWidth:10, // 浮动边栏与页面的间距
-// align:"right", // 浮动边栏左右停靠方式:right | left
-// vertical:"bottom", // 浮动边栏上下停靠方式:bottom | top
-// speed:300, // 速度:非0毫秒数值 | "slow" | "fast"
-// aniOnOff:true, // 效果开关:true | false
-// moveOnOff:true, // 运动开关:true | false
-
-// eleFocus:"focus", // 焦点:class="focus"
-// eleName:"back", // 元素名称
-// eleLabel:"li", // 结构标签
-// anchorIndex:"anchor-index", // 锚节点
-// eleMargin:10, // 板块间距
-// mouseCtrl:"click", // 鼠标事件:click | mouseover
-// focusOnOff:true // 滚动获焦开关:false | true
-*/
-
-(function($){
- $.fn.extend({
- floatBar:function(options){
- var defaults = {
- liveHeight:360,
- bodyWidth:960,
- winMinHeight:600,
- topFixHeight:30,
- spaceWidth:10,
- align:"right",
- vertical:"bottom",
- speed:300,
- aniOnOff:true,
- moveOnOff:true,
-
- eleFocus:"focus",
- eleName:"back",
- eleLabel:"li",
- anchorIndex:"anchor-index",
- eleMargin:10,
- mouseCtrl:"click",
- focusOnOff:true
- }
- var options = $.extend(defaults,options);
- var thisObj = $(this);
-
- // 滚屏导航
- var queArray=[];
- var eleQue;
-
- $("["+options.anchorIndex+"]").each(function(){
- queArray.push({
- index:$(this).attr(options.anchorIndex),
- height:$(this).height(),
- top:$(this).offset().top
- });
- });
-
- function sCrollScreen(cObj){
- var oWinTop = $(window).scrollTop();
- thisObj.find("."+options.eleFocus).removeClass(options.eleFocus);
- for(var i = 0,k = queArray.length;i oWinTop){
- if(eleQue.top > oWinTopX){
- eleQue = queArray[i-1];
- }
- if(eleQue){
- thisObj.find(options.eleLabel).eq(eleQue.index-1).addClass(options.eleFocus);
- }
- break;
- }
- }
- }
-
- thisObj.find(options.eleLabel).bind(options.mouseCtrl,function(){
- var index = $(this).index() + 1;
- var $anchor = $("["+options.anchorIndex+"="+index+"]");
- $("html,body").stop().animate({
- scrollTop:$anchor.offset().top-options.eleMargin
- },options.speed);
- return false;
- });
- thisObj.find("."+options.eleName+"top").click(function(){
- $("html,body").stop().animate({
- scrollTop:0
- },options.speed);
- });
- thisObj.find("."+options.eleName+"bottom").click(function(){
- $("html,body").stop().animate({
- scrollTop:$("body").height()
- },options.speed);
- });
-
- if(navigator.userAgent.indexOf("MSIE 6")!=-1){
- switch(options.vertical){
- case "bottom":
- thisObj.addClass("JQUI-FloBarDown");
- break;
- case "top":
- thisObj.addClass("JQUI-FloBarUp");
- break;
- }
- $("head").append("");
- }else{
- thisObj.css({
- position:"fixed",
- right:"0"
- });
- }
-
- function dataEle(attrObj){
- switch(options.vertical){
- case "bottom":
- thisObj.data(attrObj,parseInt(thisObj.css(attrObj))); // 存储样式表中bottom的值
- return thisObj.data(attrObj);
- break;
- case "top":
- thisObj.data(attrObj,parseInt(thisObj.css(attrObj))); // 存储样式表中top的值
- if(navigator.userAgent.indexOf("MSIE 6")!=-1){
- thisObj.data(attrObj,parseInt(thisObj.css("margin-top")));
- }
- return thisObj.data(attrObj);
- break;
- }
- }
- var dataConBottom = dataEle("bottom"); // 提取bottom值
- var dataConTop = dataEle("top"); // 提取bottom值
- var posiObj = posiEle(); // 首次函数加载
- // thisObj.show();
-
- function posiEle(){
- var posiAlign;
- var posi = {};
- posi.oWinWidth = $(window).width();
- posi.oWinHeight = $(window).height();
- posi.oFloatElementWidth = thisObj.width(); // 浮动边栏宽度
- oWinTop = $(window).scrollTop(); // 滚动条首次距离顶部的坐标
-
- var posiRight = (posi.oWinWidth-options.bodyWidth)/2 - posi.oFloatElementWidth - options.spaceWidth;
- // 左侧窗口停靠,相当left:0
- var posiLeft = posiRight + (options.bodyWidth + posi.oWinWidth)/2 + options.spaceWidth;
- // 左侧页面停靠
- var posiLeftExp = posiLeft - (posi.oWinWidth-options.bodyWidth)/2 + posi.oFloatElementWidth + options.spaceWidth;
-
- // 浏览器可视窗口大小判断
- if(posi.oWinWidth <= (((posi.oWinWidth-options.bodyWidth)/2) + options.bodyWidth + posi.oFloatElementWidth + options.spaceWidth)){
- switch(options.align){
- case "right":
- posiAlign = {right:'0'};
- break;
- case "left":
- posiAlign = {right:posiLeft};
- break;
- }
- thisObj.css(posiAlign);
- }else{
- switch(options.align){
- case "right":
- posiAlign = {right:posiRight};
- break;
- case "left":
- posiAlign = {right:posiLeftExp};
- break;
- }
- thisObj.css(posiAlign);
- }
-
- options.moveOnOff ? chaScroll(posi) : " ";
- options.focusOnOff ? sCrollScreen(posi) : " "; // 滚屏首次加载
-
- return posi;
- }
-
- function chaScroll(cObj){
- var floSwi = function(fT,fB){
- switch(options.vertical){
- case "bottom":
- options.aniOnOff ? thisObj.stop().animate(fT,options.speed) : thisObj.css(fT);
- break;
- case "top":
- options.aniOnOff ? thisObj.stop().animate(fB,options.speed) : thisObj.css(fB);
- break;
- }
- }
-
- if(navigator.userAgent.indexOf("MSIE 6")!=-1){ // 判断IE6
- if(oWinTop < options.liveHeight && cObj.oWinHeight > options.winMinHeight){
- floSwi({marginTop:"0"},{marginTop:dataConTop});
- }else if(oWinTop < options.liveHeight && cObj.oWinHeight < options.winMinHeight){
- floSwi({marginTop:"0"},{marginTop:options.topFixHeight});
- }else if(oWinTop > options.liveHeight && cObj.oWinHeight > options.winMinHeight){
- floSwi({marginTop:-dataConBottom},{marginTop:options.topFixHeight});
- }else if(oWinTop > options.liveHeight && cObj.oWinHeight < options.winMinHeight){
- floSwi({marginTop:"0"},{marginTop:options.topFixHeight});
- }
- }
- else{
- if(oWinTop < options.liveHeight && cObj.oWinHeight > options.winMinHeight){
- floSwi({bottom:"0"},{top:dataConTop});
- }else if(oWinTop < options.liveHeight && cObj.oWinHeight < options.winMinHeight){
- floSwi({bottom:"0"},{top:options.topFixHeight});
- }else if(oWinTop > options.liveHeight && cObj.oWinHeight > options.winMinHeight){
- floSwi({bottom:dataConBottom},{top:options.topFixHeight});
- }else if(oWinTop > options.liveHeight && cObj.oWinHeight < options.winMinHeight){
- floSwi({bottom:"0"},{top:options.topFixHeight});
- }
- }
- }
-
- // 重置尺寸大小事件
- $(window).resize(function (){
- var posiObj = posiEle();
- });
-
- // 滚动事件
- $(window).scroll(function(){
- var posiObj = posiEle();
- oWinTop = $(window).scrollTop(); // 滚动条滚动时距离顶部的坐标
- options.moveOnOff ? chaScroll(posiObj) : " ";
- options.focusOnOff ? sCrollScreen(posiObj) : " ";
- });
-
- return $(this);
- }
- });
-})(jQuery);
diff --git a/spree_theme/app/assets/javascripts/jquery.layout.js b/spree_theme/app/assets/javascripts/jquery.layout.js
index 0cab20d1..5b744667 100644
--- a/spree_theme/app/assets/javascripts/jquery.layout.js
+++ b/spree_theme/app/assets/javascripts/jquery.layout.js
@@ -451,7 +451,7 @@ $.layout = {
else
CSS[p] = style[p];
};
- return CSS
+ return CSS;
}
/**
@@ -617,7 +617,7 @@ $.layout = {
+ ''
+ ''
).appendTo("body");
- $e.css('left', $(window).width() - $e.outerWidth() - 5)
+ $e.css('left', $(window).width() - $e.outerWidth() - 5);
if ($.ui.draggable) $e.draggable({ handle: ':first-child' });
return $e;
};
@@ -1733,7 +1733,7 @@ $.fn.layout = function (opts) {
// check for destroy()ed layouts and update the child pointers & arrays
if ($.isPlainObject( pC )) {
$.each( pC, function (key, child) {
- if (child.destroyed) delete pC[key]
+ if (child.destroyed) delete pC[key];
});
// if no more children, remove the children hash
if ($.isEmptyObject( pC ))
@@ -1900,7 +1900,7 @@ $.fn.layout = function (opts) {
if (o.inset && !$.isPlainObject(o.inset)) {
// can specify a single number for equal outset all-around
- n = parseInt(o.inset, 10) || 0
+ n = parseInt(o.inset, 10) || 0;
o.inset = {
top: n
, bottom: n
@@ -1923,7 +1923,7 @@ $.fn.layout = function (opts) {
}
else if (!$.isPlainObject(o.outset)) {
// can specify a single number for equal outset all-around
- n = parseInt(o.outset, 10) || 0
+ n = parseInt(o.outset, 10) || 0;
o.outset = {
top: n
, bottom: n
@@ -2042,7 +2042,7 @@ $.fn.layout = function (opts) {
if ($.inArray(key, rootKeys) < 0 && $.inArray(key, data) < 0) {
if (!opts.panes[key])
opts.panes[key] = $.isPlainObject(val) ? $.extend(true, {}, val) : val;
- delete opts[key]
+ delete opts[key];
}
}
@@ -2160,7 +2160,7 @@ $.fn.layout = function (opts) {
* @param {string} pane The pane to process
*/
, getPane = function (pane) {
- var sel = options[pane].paneSelector
+ var sel = options[pane].paneSelector;
if (sel.substr(0,1)==="#") // ID selector
// NOTE: elements selected 'by ID' DO NOT have to be 'children'
return $N.find(sel).eq(0);
@@ -2686,7 +2686,7 @@ $.fn.layout = function (opts) {
// SET RESIZER LIMITS - used in drag()
setSizeLimits(pane); // update pane/resizer state
r = s.resizerPosition;
- lastPos = ui.position[ side ]
+ lastPos = ui.position[ side ];
$R.addClass( resizerClass +" "+ resizerPaneClass ); // add drag classes
helperClassesSet = false; // reset logic var - see drag()
@@ -2730,7 +2730,7 @@ $.fn.layout = function (opts) {
// won't trigger unless resizer has actually moved!
if (live && Math.abs(ui.position[side] - lastPos) >= o.liveResizingTolerance) {
lastPos = ui.position[side];
- resizePanes(e, ui, pane)
+ resizePanes(e, ui, pane);
}
}
@@ -2852,7 +2852,7 @@ $.fn.layout = function (opts) {
if (s.isVisible && ( o.maskObjects || (!a.objectsOnly && o.maskContents) )) {
getMasks(p).each(function(){
sizeMask.call(this);
- this.style.zIndex = s.isSliding ? z.pane_sliding+1 : z.pane_normal+1
+ this.style.zIndex = s.isSliding ? z.pane_sliding+1 : z.pane_normal+1;
this.style.display = "block";
});
}
@@ -3596,7 +3596,7 @@ $.fn.layout = function (opts) {
.addClass( rClass+_open +" "+ rClass+_pane+_open )
;
if (s.isSliding)
- $R.addClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
+ $R.addClass( rClass+_sliding +" "+ rClass+_pane+_sliding );
else // in case 'was sliding'
$R.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
@@ -3781,7 +3781,7 @@ $.fn.layout = function (opts) {
// must remove double-click-toggle when using dblclick-slide
if (o.resizerDblClickToggle && evtName.match(/click/)) {
- $R[enable ? "unbind" : "bind"]('dblclick.'+ sID, toggle)
+ $R[enable ? "unbind" : "bind"]('dblclick.'+ sID, toggle);
}
$R
@@ -4446,7 +4446,7 @@ $.fn.layout = function (opts) {
, numFooters: $Fs.length
, hiddenFooters: $Fs.length - $Fs_vis.length
, spaceBelow: 0 // correct if no content footer ($E)
- }
+ };
m.spaceAbove = m.top; // just for state - not used in calc
m.bottom = m.top + m.height;
if ($F.length)
@@ -4466,7 +4466,7 @@ $.fn.layout = function (opts) {
* @param {(string|Object)=} evt_or_panes The pane(s) being resized
*/
, sizeHandles = function (evt_or_panes) {
- var panes = evtPane.call(this, evt_or_panes)
+ var panes = evtPane.call(this, evt_or_panes);
panes = panes ? panes.split(",") : _c.borderPanes;
$.each(panes, function (i, pane) {
@@ -4778,7 +4778,7 @@ $.fn.layout = function (opts) {
, C: $C ? $C[0] : false
, state: $.extend(true, {}, state[n])
, options: $.extend(true, {}, options[n])
- }
+ };
};
function move (oPane, pane) {
@@ -5126,7 +5126,7 @@ $.fn.layout = function (opts) {
else // true OR false -- if layout-elements did NOT init (hidden or do not exist), can auto-init later
return Instance; // return the Instance object
-}
+};
})( jQuery );
@@ -5397,7 +5397,7 @@ $.layout.state = {
s = o.size;
c = o.initClosed;
h = o.initHidden;
- ar = o.autoResize
+ ar = o.autoResize;
state = inst.state[pane];
open = state.isVisible;
diff --git a/spree_theme/app/assets/javascripts/jquery.lightbox.custom.js b/spree_theme/app/assets/javascripts/jquery.lightbox.custom.js
new file mode 100644
index 00000000..69eb5282
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/jquery.lightbox.custom.js
@@ -0,0 +1,510 @@
+/**
+ * jQuery Lightbox
+ * @author Warren Krewenki
+ *
+ * This package is distributed under the BSD license.
+ * For full license information, see LICENSE.TXT
+ *
+ * Based on Lightbox 2 by Lokesh Dhakar (http://www.huddletogether.com/projects/lightbox2/)
+ *
+ *
+ **/
+
+(function($) {
+ $.fn.lightbox = function(options) {
+ // build main options
+ var opts = $.extend({}, $.fn.lightbox.defaults, options);
+
+ $(window).resize(resizeOverlayToFitWindow);
+
+ return $(this).on(opts.triggerEvent,function(){
+ // initialize the lightbox
+ initialize();
+ showLightbox(this);
+ return false;
+ });
+ /*
+ # Initialize the lightbox by creating our html and reading some image data
+ # This method is called by the constructor after any click events trigger it
+ # You will never call it by itself, to my knowledge.
+ */
+ function initialize() {
+ $('.lightbox-overlay, #lightbox').remove();
+ opts.inprogress = false;
+
+ // if jsonData, build the imageArray from data provided in JSON format
+ if (opts.jsonData && opts.jsonData.length > 0) {
+ var parser = opts.jsonDataParser ? opts.jsonDataParser : $.fn.lightbox.parseJsonData;
+ opts.imageArray = [];
+ opts.imageArray = parser(opts.jsonData);
+ }
+
+ var outerImage = ' ';
+ var imageData = '
';
+
+ if (opts.displayHelp) {
+ imageData += ' ' + opts.strings.help + '';
+ }
+
+ imageData += '  ';
+
+ var string;
+
+ if (opts.navbarOnTop) {
+ string = ' ' + imageData + outerImage + ' ';
+ $("body").append(string);
+ $("#imageDataContainer").addClass('ontop');
+ } else {
+ string = ' ' + outerImage + imageData + ' ';
+ $("body").append(string);
+ }
+
+ if (opts.imageScroll === true) {
+ $('#lightbox').css('position', 'fixed')
+ }
+
+ $(".lightbox-overlay, #lightbox").click(function(){ end(); }).hide();
+ $("#loadingLink, #bottomNavClose").click(function(){ end(); return false;});
+ $('#outerImageContainer').width(opts.widthCurrent).height(opts.heightCurrent);
+ $('#imageDataContainer').width(opts.widthCurrent);
+
+ if (!opts.imageClickClose) {
+ $("#lightboxImage").click(function(){ return false; });
+ $("#hoverNav").click(function(){ return false; });
+ }
+
+ return true;
+ };
+
+ /*
+ # Get the document and window width/heigh
+ #
+ # Examples
+ #
+ # getPageSize()
+ # # => [1024,768,1024,768]
+ #
+ # Returns a numerically indexed array of document width/height and window width/height
+ */
+ function getPageSize() {
+ var jqueryPageSize = new Array($(document).width(),$(document).height(), $(window).width(), $(window).height());
+ return jqueryPageSize;
+ };
+
+ function getPageScroll() {
+ var xScroll, yScroll;
+
+ if (self.pageYOffset) {
+ yScroll = self.pageYOffset;
+ xScroll = self.pageXOffset;
+ } else if (document.documentElement && (document.documentElement.scrollTop || document.documentElement.scrollLeft)){ // Explorer 6 Strict, Firefox
+ yScroll = document.documentElement.scrollTop;
+ xScroll = document.documentElement.scrollLeft;
+ } else if (document.body) {// all other Explorers
+ yScroll = document.body.scrollTop;
+ xScroll = document.body.scrollLeft;
+ }
+
+ var arrayPageScroll = new Array(xScroll,yScroll);
+ return arrayPageScroll;
+ };
+
+ /*
+ # Deploy the sexy overlay and display the lightbox
+ #
+ # imageObject - the jQuery object passed via the click event in the constructor
+ #
+ # Examples
+ #
+ # showLightbox($('#CheesusCrust'))
+ #
+ # Returns a boolean true, because it's got nothing else to return. It should give visual feedback when run
+ */
+ function showLightbox(imageObject) {
+ /**
+ * select, embed and object tags render over the lightbox in some browsers
+ * Right now, the best way to fix it is to hide them, but that can trigger reloading of some flash content
+ * I don't have a better fix for this right now, but I want ot leave this comment here so you and I both
+ * know that i'm aware of it, and I would love to fix it, if you have any suggestions.
+ **/
+ $("select, embed, object").hide();
+
+ // Resize and display the sexy, sexy overlay.
+ resizeOverlayToFitWindow();
+ $(".lightbox-overlay").hide().css({ opacity : opts.overlayOpacity }).fadeIn();
+ imageNum = 0;
+ var $imageObject = $(imageObject);
+ // if data is not provided by jsonData parameter
+ if (!opts.jsonData) {
+ opts.imageArray = [];
+ // if image is NOT part of a set..
+ if ((!getImageSetOf(imageObject) || (getImageSetOf(imageObject) == '')) && !opts.allSet) {
+ // add single image to Lightbox.imageArray
+ opts.imageArray.push(new Array(imageObject.href, opts.displayTitle ? imageObject.title : ''));
+ } else {
+ // if image is part of a set..
+ $("a").each(function() {
+ if(this.href && (getImageSetOf(this) == getImageSetOf(imageObject))) {
+ opts.imageArray.push(new Array(this.href, opts.displayTitle ? this.title : ''));
+ }
+ });
+ }
+ }
+
+ if (opts.imageArray.length > 1) {
+ for (i = 0; i < opts.imageArray.length; i++) {
+ for (j = opts.imageArray.length - 1; j > i; j--) {
+ if (opts.imageArray[i][0] == opts.imageArray[j][0]) {
+ opts.imageArray.splice(j, 1);
+ }
+ }
+ }
+ // custom change, for spree_abc only.
+ // get current selected image url from data-big-image
+ //while (opts.imageArray[imageNum][0] != imageObject.url) {
+ while (opts.imageArray[imageNum][0] != $imageObject.data("big-image")) {
+ imageNum++;
+ }
+ }
+
+ // calculate top and left offset for the lightbox
+ var arrayPageScroll = getPageScroll();
+ var lightboxTop = arrayPageScroll[1] + ($(window).height() / 10);
+ var lightboxLeft = arrayPageScroll[0];
+ $('#lightbox').css({top: lightboxTop+'px', left: lightboxLeft+'px'}).show();
+
+ if (!opts.slideNavBar) {
+ $('#imageData').hide();
+ }
+
+ changeImage(imageNum);
+ };
+
+ function changeImage(imageNum) {
+ if (opts.inprogress == false) {
+ opts.inprogress = true;
+
+ // update global var
+ opts.activeImage = imageNum;
+
+ // hide elements during transition
+ $('.lightbox-loading').show();
+ $('#lightboxImage, #hoverNav, #prevLink, #nextLink').hide();
+
+ // delay preloading image until navbar will slide up
+ if (opts.slideNavBar) {
+ $('#imageDataContainer').hide();
+ $('#imageData').hide();
+ }
+ doChangeImage();
+ }
+ };
+
+ function doChangeImage() {
+ var imgPreloader = new Image();
+
+ // once image is preloaded, resize image container
+ imgPreloader.onload = function() {
+ var newWidth = imgPreloader.width;
+ var newHeight = imgPreloader.height;
+
+ if (opts.scaleImages) {
+ newWidth = parseInt(opts.xScale * newWidth);
+ newHeight = parseInt(opts.yScale * newHeight);
+ }
+
+ if (opts.fitToScreen) {
+ var arrayPageSize = getPageSize();
+ var ratio;
+ var initialPageWidth = arrayPageSize[2] - 2 * opts.borderSize;
+ var initialPageHeight = arrayPageSize[3] - 200;
+
+ var dI = initialPageWidth/initialPageHeight;
+ var dP = imgPreloader.width/imgPreloader.height;
+
+ if ((imgPreloader.height > initialPageHeight) || (imgPreloader.width > initialPageWidth)) {
+ if (dI > dP) {
+ newWidth = parseInt((initialPageHeight/imgPreloader.height) * imgPreloader.width);
+ newHeight = initialPageHeight;
+ } else {
+ newHeight = parseInt((initialPageWidth/imgPreloader.width) * imgPreloader.height);
+ newWidth = initialPageWidth;
+ }
+ }
+ }
+
+ $('#lightboxImage').
+ attr('src', opts.imageArray[opts.activeImage][0]).
+ width(newWidth).
+ height(newHeight);
+
+ resizeImageContainer(newWidth, newHeight);
+ };
+
+ imgPreloader.src = opts.imageArray[opts.activeImage][0];
+ };
+
+ function end() {
+ disableKeyboardNav();
+ $('#lightbox').hide();
+ $('.lightbox-overlay').fadeOut();
+ $('select, object, embed').show();
+ };
+
+ function preloadNeighborImages() {
+ var preloadPrevImage, preloadNextImage;
+ if (opts.loopImages && opts.imageArray.length > 1) {
+ preloadNextImage = new Image();
+ preloadNextImage.src = opts.imageArray[(opts.activeImage == (opts.imageArray.length - 1)) ? 0 : opts.activeImage + 1][0];
+
+ preloadPrevImage = new Image();
+ preloadPrevImage.src = opts.imageArray[(opts.activeImage == 0) ? (opts.imageArray.length - 1) : opts.activeImage - 1][0];
+ } else {
+ if ((opts.imageArray.length - 1) > opts.activeImage) {
+ preloadNextImage = new Image();
+ preloadNextImage.src = opts.imageArray[opts.activeImage + 1][0];
+ }
+ if (opts.activeImage > 0) {
+ preloadPrevImage = new Image();
+ preloadPrevImage.src = opts.imageArray[opts.activeImage - 1][0];
+ }
+ }
+ };
+
+ function resizeImageContainer(imgWidth, imgHeight) {
+ // get current width and height
+ opts.widthCurrent = $("#outerImageContainer").outerWidth();
+ opts.heightCurrent = $("#outerImageContainer").outerHeight();
+
+ // get new width and height
+ var widthNew = Math.max(350, imgWidth + (opts.borderSize * 2));
+ var heightNew = (imgHeight + (opts.borderSize * 2));
+
+ // calculate size difference between new and old image, and resize if necessary
+ wDiff = opts.widthCurrent - widthNew;
+ hDiff = opts.heightCurrent - heightNew;
+
+ $('#imageDataContainer').animate({width: widthNew},opts.resizeSpeed,'linear');
+ $('#outerImageContainer').animate({width: widthNew},opts.resizeSpeed,'linear', function() {
+ $('#outerImageContainer').animate({height: heightNew},opts.resizeSpeed,'linear', function() {
+ showImage();
+ });
+ });
+
+ afterTimeout = function () {
+ $('#prevLink').height(imgHeight);
+ $('#nextLink').height(imgHeight);
+ };
+
+ // if new and old image are same size and no scaling transition is necessary,
+ // do a quick pause to prevent image flicker.
+ if((hDiff == 0) && (wDiff == 0)) {
+ setTimeout(afterTimeout, 100);
+ } else {
+ // otherwise just trigger the height and width change
+ afterTimeout();
+ }
+
+ };
+
+ function showImage() {
+ $('.lightbox-loading').hide();
+ $('#lightboxImage').fadeIn("fast");
+ updateDetails();
+ preloadNeighborImages();
+
+ opts.inprogress = false;
+ };
+
+ function updateDetails() {
+ $('#numberDisplay').html('');
+
+ if (opts.imageArray[opts.activeImage][1]) {
+ $('#caption').html(opts.imageArray[opts.activeImage][1]).show();
+ }
+
+ // if image is part of set display 'Image x of x'
+ if (opts.imageArray.length > 1) {
+ var nav_html;
+
+ nav_html = opts.strings.image + (opts.activeImage + 1) + opts.strings.of + opts.imageArray.length;
+
+ if (opts.displayDownloadLink) {
+ nav_html += " " + opts.strings.download + "";
+ }
+
+ if (!opts.disableNavbarLinks) {
+ // display previous / next text links
+ if ((opts.activeImage) > 0 || opts.loopImages) {
+ nav_html = ' ' + opts.strings.prevLinkText + "" + nav_html;
+ }
+
+ if (((opts.activeImage + 1) < opts.imageArray.length) || opts.loopImages) {
+ nav_html += ' ' + opts.strings.nextLinkText + "";
+ }
+ }
+
+ $('#numberDisplay').html(nav_html).show();
+ }
+
+ if (opts.slideNavBar) {
+ $("#imageData").slideDown(opts.navBarSlideSpeed);
+ } else {
+ $("#imageData").show();
+ }
+
+ resizeOverlayToFitWindow();
+ updateNav();
+ };
+
+ /*
+ # Resize the sexy overlay to fit the constraints of your current viewing environment
+ #
+ # This should now happen whenever a window is resized, so you should always see a full overlay
+ */
+ function resizeOverlayToFitWindow(){
+ $('.lightbox-overlay').css({width: $(document).width(), height: $(document).height()});
+ // ^^^^^^^ <- sexy!
+ };
+
+ function updateNav() {
+ if (opts.imageArray.length > 1) {
+ $('#hoverNav').show();
+
+ // if loopImages is true, always show next and prev image buttons
+ if(opts.loopImages) {
+ $('#prevLink,#prevLinkText').show().click(function() {
+ changeImage((opts.activeImage == 0) ? (opts.imageArray.length - 1) : opts.activeImage - 1);
+ return false;
+ });
+
+ $('#nextLink,#nextLinkText').show().click(function() {
+ changeImage((opts.activeImage == (opts.imageArray.length - 1)) ? 0 : opts.activeImage + 1);
+ return false;
+ });
+
+ } else {
+ // if not first image in set, display prev image button
+ if(opts.activeImage != 0) {
+ $('#prevLink,#prevLinkText').show().click(function() {
+ changeImage(opts.activeImage - 1);
+ return false;
+ });
+ }
+
+ // if not last image in set, display next image button
+ if(opts.activeImage != (opts.imageArray.length - 1)) {
+ $('#nextLink,#nextLinkText').show().click(function() {
+ changeImage(opts.activeImage +1);
+ return false;
+ });
+ }
+ }
+
+ }
+ enableKeyboardNav();
+
+ };
+
+ function keyboardAction(e) {
+ var o = e.data.opts;
+ var keycode = e.keyCode;
+ var escapeKey = 27;
+
+ var key = String.fromCharCode(keycode).toLowerCase();
+
+ // close lightbox
+ if ((key == 'x') || (key == 'o') || (key == 'c') || (keycode == escapeKey)) {
+ end();
+
+ // display previous image
+ } else if ((key == 'p') || (keycode == 37)) {
+ if(o.loopImages) {
+ disableKeyboardNav();
+ changeImage((o.activeImage == 0) ? (o.imageArray.length - 1) : o.activeImage - 1);
+ } else if (o.activeImage != 0) {
+ disableKeyboardNav();
+ changeImage(o.activeImage - 1);
+ }
+
+ // display next image
+ } else if ((key == 'n') || (keycode == 39)) {
+ if (opts.loopImages) {
+ disableKeyboardNav();
+ changeImage((o.activeImage == (o.imageArray.length - 1)) ? 0 : o.activeImage + 1);
+ } else if (o.activeImage != (o.imageArray.length - 1)) {
+ disableKeyboardNav();
+ changeImage(o.activeImage + 1);
+ }
+ }
+ };
+
+ function enableKeyboardNav() {
+ $(document).bind('keydown', {opts: opts}, keyboardAction);
+ };
+
+ function disableKeyboardNav() {
+ $(document).unbind('keydown');
+ };
+
+ function getImageSetOf(imageObject) {
+ var set_name = imageObject.rel;
+ if (!set_name || set_name == '') {
+ set_name = $(imageObject).attr('data-lightbox-set');
+ }
+ return set_name;
+ };
+ };
+
+ $.fn.lightbox.parseJsonData = function(data) {
+ var imageArray = [];
+
+ $.each(data, function() {
+ imageArray.push(new Array(this.url, this.title));
+ });
+
+ return imageArray;
+ };
+
+ $.fn.lightbox.defaults = {
+ triggerEvent: "click",
+ allSet: false,
+ fileLoadingImage: '/shops/shared/images/lightbox/loading.gif',
+ fileBottomNavCloseImage: '/shops/shared/images/lightbox/closelabel.gif',
+ overlayOpacity: 0.6,
+ borderSize: 10,
+ imageArray: new Array,
+ activeImage: null,
+ imageScroll: false,
+ inprogress: false,
+ resizeSpeed: 350,
+ widthCurrent: 250,
+ heightCurrent: 250,
+ scaleImages: false,
+ xScale: 1,
+ yScale: 1,
+ displayTitle: true,
+ navbarOnTop: false,
+ displayDownloadLink: false,
+ slideNavBar: false,
+ navBarSlideSpeed: 350,
+ displayHelp: false,
+ strings: {
+ help: ' \u2190 / P - previous image\u00a0\u00a0\u00a0\u00a0\u2192 / N - next image\u00a0\u00a0\u00a0\u00a0ESC / X - close image gallery',
+ prevLinkTitle: 'previous image',
+ nextLinkTitle: 'next image',
+ prevLinkText: '« Previous',
+ nextLinkText: 'Next »',
+ closeTitle: 'close image gallery',
+ image: 'Image ',
+ of: ' of ',
+ download: 'Download'
+ },
+ fitToScreen: false,
+ disableNavbarLinks: false,
+ loopImages: false,
+ imageClickClose: true,
+ jsonData: null,
+ jsonDataParser: null
+ };
+})(jQuery);
diff --git a/spree_theme/app/assets/javascripts/jquery.menuhover.js b/spree_theme/app/assets/javascripts/jquery.menuhover.js
new file mode 100644
index 00000000..1af3be40
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/jquery.menuhover.js
@@ -0,0 +1,76 @@
+// a hover event as amazon
+// by yilizhang@sohu-inc.com
+
+(function($) {
+
+ $.fn.menuhover = function(opts) {
+
+ this.each(function() {
+ init.call(this, opts);
+ });
+
+ return this;
+ };
+
+ function init(opts) {
+ var $menuhover = $(this),
+ timeoutId = null,
+ options = $.extend({
+ submenuDirection: "below",
+ activate: $.noop,
+ deactivate: $.noop,
+ $hover:null,
+ $hover_effect_container: $menuhover
+ },opts),
+ $hover = options.$hover;
+
+ var MOUSE_LOCS_TRACKED = 3,
+ DELAY = 200;
+
+
+ function mouseenter(e){
+ options.activate();
+ //e.stopPropagation();
+ }
+
+ function mouseleave(e){
+ if(inArea(e)){
+ timeoutId = setTimeout(function() {
+ options.deactivate();
+ }, DELAY);
+ }else{
+ options.deactivate();
+ }
+ }
+
+ function mouseenterHover(){
+ if (timeoutId) {
+ // Cancel any previous activation delays
+ clearTimeout(timeoutId);
+ }
+ }
+
+ function inArea(e){
+ var offset = $menuhover.offset();
+ if( options.submenuDirection=='b'){
+ // y+menuhover.height, disable case mouse move from one menu itme to next menu item.
+ if( e.pageX >= offset.left && e.pageY >= (offset.top + $menuhover.height())){ // mouse move to right bottom
+ return true;
+ }
+ }else{
+ if( e.pageX <= offset.left && e.pageY >= offset.top){ // mouse move to left bottom
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ $menuhover.mouseenter(mouseenter)
+ .mouseleave(mouseleave);
+ $hover.mouseenter(mouseenterHover);
+ // hover is not in element menuhover, mouseleave is required.
+ $hover.mouseleave(mouseleave);
+ }
+
+})(jQuery);
diff --git a/spree_theme/app/assets/javascripts/jquery.sidr.js b/spree_theme/app/assets/javascripts/jquery.sidr.js
new file mode 100644
index 00000000..6d855924
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/jquery.sidr.js
@@ -0,0 +1,341 @@
+/*
+ * Sidr
+ * https://github.com/generoi/sidr
+ *
+ * Copyright (c) 2013 Alberto Varela
+ * Licensed under the MIT license.
+ */
+
+;(function( $ ){
+
+ var sidrMoving = false,
+ sidrOpened = false;
+
+ // Private methods
+ var privateMethods = {
+ // Check for valids urls
+ // From : http://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-an-url
+ isUrl: function (str) {
+ var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
+ '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
+ '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
+ '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
+ '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
+ '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
+ if(!pattern.test(str)) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+ // Loads the content into the menu bar
+ loadContent: function($menu, content) {
+ $menu.html(content);
+ this.addTitle($menu);
+ },
+ // add title include close button
+ addTitle: function( $menu ){
+ $(' ')
+ .prependTo($menu);
+ },
+
+ // Add sidr prefixes
+ addPrefix: function($element) {
+ var elementId = $element.attr('id'),
+ elementClass = $element.attr('class');
+
+ if(typeof elementId === 'string' && '' !== elementId) {
+ $element.attr('id', elementId.replace(/([A-Za-z0-9_.\-]+)/g, 'sidr-id-$1'));
+ }
+ if(typeof elementClass === 'string' && '' !== elementClass && 'sidr-inner' !== elementClass) {
+ $element.attr('class', elementClass.replace(/([A-Za-z0-9_.\-]+)/g, 'sidr-class-$1'));
+ }
+ $element.removeAttr('style');
+ },
+ execute: function(action, name, callback) {
+ // Check arguments
+ if(typeof name === 'function') {
+ callback = name;
+ name = 'sidr';
+ }
+ else if(!name) {
+ name = 'sidr';
+ }
+
+ // Declaring
+ var $menu = $('#' + name),
+ $menuOverlay = $('#' + name + '-overlay'),
+ $body = $($menu.data('body')),
+ $html = $('html'),
+ menuWidth = $menu.outerWidth(true) ,
+ menuHeight = $menu.outerHeight(true) ,
+ speed = $menu.data('speed'),
+ side = $menu.data('side'),
+ displace = $menu.data('displace'),
+ onOpen = $menu.data('onOpen'),
+ onClose = $menu.data('onClose'),
+ bodyAnimation,
+ menuAnimation,
+ scrollTop,
+ bodyClass = (name === 'sidr' ? 'sidr-open' : 'sidr-open ' + name + '-open');
+
+ // Open Sidr
+ if('open' === action || ('toggle' === action && !$menu.is(':visible'))) {
+ // Check if we can open it
+ if( $menu.is(':visible') || sidrMoving ) {
+ return;
+ }
+
+ // If another menu opened close first
+ if(sidrOpened !== false) {
+ methods.close(sidrOpened, function() {
+ methods.open(name);
+ });
+
+ return;
+ }
+
+ // Lock sidr
+ sidrMoving = true;
+
+ // Left or right?
+ if(side === 'top') {
+ menuAnimation = {top: '0px'};
+ }else if(side === 'bottom') {
+ menuAnimation = {bottom: '0px'};
+ }else if(side === 'left') {
+ bodyAnimation = {left: menuWidth + 'px'};
+ menuAnimation = {left: '0px'};
+ }
+ else {
+ bodyAnimation = {right: menuWidth + 'px'};
+ menuAnimation = {right: '0px'};
+ }
+
+ // Prepare page if container is body
+ if($body.is('body')){
+ scrollTop = $html.scrollTop();
+ $html.css('overflow-x', 'hidden').scrollTop(scrollTop);
+ }
+
+ // Open menu
+ $menuOverlay.show();
+ if(displace){
+ $body.addClass('sidr-animating').css({
+ width: $body.width(),
+ position: 'absolute'
+ }).animate(bodyAnimation, speed, function() {
+ $(this).addClass(bodyClass);
+ });
+ }
+ else {
+ setTimeout(function() {
+ $(this).addClass(bodyClass);
+ }, speed);
+ }
+ $menu.css('display', 'block').animate(menuAnimation, speed, function() {
+ sidrMoving = false;
+ sidrOpened = name;
+ // Callback
+ if(typeof callback === 'function') {
+ callback(name);
+ }
+ $body.removeClass('sidr-animating');
+ });
+
+ // onOpen callback
+ onOpen();
+ }
+ // Close Sidr
+ else {
+ // Check if we can close it
+ if( !$menu.is(':visible') || sidrMoving ) {
+ return;
+ }
+
+ // Lock sidr
+ sidrMoving = true;
+
+ // Right or left menu?
+ if(side === 'top') {
+ menuAnimation = {top: '-' + menuWidth + 'px'};
+ }else if(side === 'bottom') {
+ menuAnimation = {bottom: '-' + menuWidth + 'px'};
+ }else if(side === 'left') {
+ bodyAnimation = {left: 0};
+ menuAnimation = {left: '-' + menuWidth + 'px'};
+ }
+ else {
+ bodyAnimation = {right: 0};
+ menuAnimation = {right: '-' + menuWidth + 'px'};
+ }
+
+ // Close menu
+ if($body.is('body')){
+ scrollTop = $html.scrollTop();
+ $html.removeAttr('style').scrollTop(scrollTop);
+ }
+ $body.addClass('sidr-animating').animate(bodyAnimation, speed).removeClass(bodyClass);
+ $menu.animate(menuAnimation, speed, function() {
+ $menu.removeAttr('style').hide();
+ $body.removeAttr('style');
+ $('html').removeAttr('style');
+ sidrMoving = false;
+ sidrOpened = false;
+ // Callback
+ if(typeof callback === 'function') {
+ callback(name);
+ }
+ $body.removeClass('sidr-animating');
+ });
+
+ // onClose callback
+ onClose();
+ $menuOverlay.hide();
+ }
+ }
+ };
+
+ // Sidr public methods
+ var methods = {
+ open: function(name, callback) {
+ privateMethods.execute('open', name, callback);
+ },
+ close: function(name, callback) {
+ privateMethods.execute('close', name, callback);
+ },
+ toggle: function(name, callback) {
+ privateMethods.execute('toggle', name, callback);
+ },
+ // I made a typo, so I mantain this method to keep backward compatibilty with 1.1.1v and previous
+ toogle: function(name, callback) {
+ privateMethods.execute('toggle', name, callback);
+ }
+ };
+
+ $.sidr = function( method ) {
+
+ if ( methods[method] ) {
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
+ }
+ else if ( typeof method === 'function' || typeof method === 'string' || ! method ) {
+ return methods.toggle.apply( this, arguments );
+ }
+ else {
+ $.error( 'Method ' + method + ' does not exist on jQuery.sidr' );
+ }
+
+ };
+
+ $.fn.sidr = function( options ) {
+ sidrOpened = false;// for reason turbolinks, reset it when initialize sidr.
+
+ var settings = $.extend( {
+ name : 'sidr', // Name for the 'sidr'
+ speed : 200, // Accepts standard jQuery effects speeds (i.e. fast, normal or milliseconds)
+ side : 'left', // Accepts 'left' or 'right' 'top', 'bottom'
+ source : null, // Override the source of the content.
+ renaming : true, // The ids and classes will be prepended with a prefix when loading existent content
+ body : 'body', // Page container selector,
+ displace: true, // Displace the body content or not
+ onOpen : function() {}, // Callback when sidr opened
+ onClose : function() {} // Callback when sidr closed
+ }, options);
+
+ var name = settings.name,
+ $sideMenu = $('#' + name), $sideOverlay = $('#' + name +'-overlay');
+
+ // If the side menu do not exist create it
+ if( $sideMenu.length === 0 ) {
+ $sideMenu = $(' ')
+ .attr('id', name)
+ .appendTo($(settings.body));
+ // create the overlay
+ $sideOverlay = $(' ')
+ .attr('id', name +'-overlay')
+ .addClass('sidr-overlay')
+ .appendTo($(settings.body));
+ }
+
+ // Adding styles and options
+ $sideMenu
+ .addClass('sidr')
+ .addClass(settings.side)
+ .data({
+ speed : settings.speed,
+ side : settings.side,
+ body : settings.body,
+ displace : settings.displace,
+ onOpen : settings.onOpen,
+ onClose : settings.onClose
+ });
+
+ // The menu content
+ if(typeof settings.source === 'function') {
+ var newContent = settings.source(name);
+ privateMethods.loadContent($sideMenu, newContent);
+ }
+ else if(typeof settings.source === 'string' && privateMethods.isUrl(settings.source)) {
+ $.get(settings.source, function(data) {
+ privateMethods.loadContent($sideMenu, data);
+ });
+ }
+ else if(typeof settings.source === 'string') {
+ var htmlContent = '',
+ selectors = settings.source.split(',');
+
+ $.each(selectors, function(index, element) {
+ htmlContent += ' ' + $(element).html() + ' ';
+ });
+
+ // Renaming ids and classes
+ if(settings.renaming) {
+ var $htmlContent = $(' ').html(htmlContent);
+ $htmlContent.find('*').each(function(index, element) {
+ var $element = $(element);
+ privateMethods.addPrefix($element);
+ });
+ htmlContent = $htmlContent.html();
+ }
+ privateMethods.loadContent($sideMenu, htmlContent);
+ }
+ else if(settings.source !== null) {
+ $.error('Invalid Sidr Source');
+ }
+
+ $('#' + name).find('a').click(function() {
+ methods.toggle(name);
+ });
+
+ return this.each(function(){
+ var $this = $(this),
+ data = $this.data('sidr'),
+ touchStart;
+
+ // If the plugin hasn't been initialized yet
+ if ( ! data ) {
+ sidrOpened = false;
+ sidrMoving = false;
+ $this.data('sidr', name);
+ if('ontouchstart' in document.documentElement) {
+ $this.bind('touchstart', function(e) {
+ var theEvent = e.originalEvent.touches[0];
+ touchStart = e.timeStamp;
+ });
+ $this.bind('touchend', function(e) {
+ var delta = Math.abs(e.timeStamp - touchStart);
+ if(delta < 200) {
+ e.preventDefault();
+ methods.toggle(name);
+ }
+ });
+ }
+ $this.click(function(e) {
+ e.preventDefault();
+ methods.toggle(name);
+ });
+ }
+ });
+ };
+
+})( jQuery );
diff --git a/spree_theme/app/assets/javascripts/jquery.simplemodal.js b/spree_theme/app/assets/javascripts/jquery.simplemodal.js
index 69b77f0a..b3054536 100644
--- a/spree_theme/app/assets/javascripts/jquery.simplemodal.js
+++ b/spree_theme/app/assets/javascripts/jquery.simplemodal.js
@@ -15,26 +15,26 @@
* SimpleModal.
*
* There are two ways to call SimpleModal:
- * 1) As a chained function on a jQuery object, like $('#myDiv').modal();.
+ * 1) As a chained function on a jQuery object, like $('#myDiv').simplemodal();.
* This call would place the DOM object, #myDiv, inside a modal dialog.
* Chaining requires a jQuery object. An optional options object can be
* passed as a parameter.
*
- * @example $(' my data ').modal({options});
- * @example $('#myDiv').modal({options});
- * @example jQueryObject.modal({options});
+ * @example $(' my data ').simplemodal({options});
+ * @example $('#myDiv').simplemodal({options});
+ * @example jQueryObject.simplemodal({options});
*
- * 2) As a stand-alone function, like $.modal(data). The data parameter
+ * 2) As a stand-alone function, like $.simplemodal(data). The data parameter
* is required and an optional options object can be passed as a second
* parameter. This method provides more flexibility in the types of data
* that are allowed. The data could be a DOM object, a jQuery object, HTML
* or a string.
*
- * @example $.modal(' my data ', {options});
- * @example $.modal('my data', {options});
- * @example $.modal($('#myDiv'), {options});
- * @example $.modal(jQueryObject, {options});
- * @example $.modal(document.getElementById('myDiv'), {options});
+ * @example $.simplemodal(' my data ', {options});
+ * @example $.simplemodal('my data', {options});
+ * @example $.simplemodal($('#myDiv'), {options});
+ * @example $.simplemodal(jQueryObject, {options});
+ * @example $.simplemodal(document.getElementById('myDiv'), {options});
*
* A SimpleModal call can contain multiple elements, but only one modal
* dialog can be created at a time. Which means that all of the matched
@@ -92,39 +92,39 @@
* @param {string, object} data A string, jQuery object or DOM object
* @param {object} [options] An optional object containing options overrides
*/
- $.modal = function (data, options) {
- return $.modal.impl.init(data, options);
+ $.simplemodal = function (data, options) {
+ return $.simplemodal.impl.init(data, options);
};
/*
* Close the modal dialog.
*/
- $.modal.close = function () {
- $.modal.impl.close();
+ $.simplemodal.close = function () {
+ $.simplemodal.impl.close();
};
/*
* Set focus on first or last visible input in the modal dialog. To focus on the last
- * element, call $.modal.focus('last'). If no input elements are found, focus is placed
+ * element, call $.simplemodal.focus('last'). If no input elements are found, focus is placed
* on the data wrapper element.
*/
- $.modal.focus = function (pos) {
- $.modal.impl.focus(pos);
+ $.simplemodal.focus = function (pos) {
+ $.simplemodal.impl.focus(pos);
};
/*
* Determine and set the dimensions of the modal dialog container.
* setPosition() is called if the autoPosition option is true.
*/
- $.modal.setContainerDimensions = function () {
- $.modal.impl.setContainerDimensions();
+ $.simplemodal.setContainerDimensions = function () {
+ $.simplemodal.impl.setContainerDimensions();
};
/*
* Re-position the modal dialog.
*/
- $.modal.setPosition = function () {
- $.modal.impl.setPosition();
+ $.simplemodal.setPosition = function () {
+ $.simplemodal.impl.setPosition();
};
/*
@@ -134,8 +134,8 @@
* setContainerDimensions() is called, which in turn calls setPosition(), if enabled.
* Lastly, focus() is called is the focus option is true.
*/
- $.modal.update = function (height, width) {
- $.modal.impl.update(height, width);
+ $.simplemodal.update = function (height, width) {
+ $.simplemodal.impl.update(height, width);
};
/*
@@ -143,8 +143,8 @@
*
* @param {object} [options] An optional object containing options overrides
*/
- $.fn.modal = function (options) {
- return $.modal.impl.init(this, options);
+ $.fn.simplemodal = function (options) {
+ return $.simplemodal.impl.init(this, options);
};
/*
@@ -186,7 +186,7 @@
* onShow: (Function:null) The callback function used after the modal dialog has opened
* onClose: (Function:null) The callback function used in place of SimpleModal's close
*/
- $.modal.defaults = {
+ $.simplemodal.defaults = {
appendTo: 'body',
focus: true,
opacity: 50,
@@ -221,7 +221,7 @@
* Main modal object
* o = options
*/
- $.modal.impl = {
+ $.simplemodal.impl = {
/*
* Contains the modal dialog elements and is the object passed
* back to the callback (onOpen, onShow, onClose) functions
@@ -241,7 +241,7 @@
browser.ieQuirks = browser.msie && !browser.boxModel;
// merge defaults and user options
- s.o = $.extend({}, $.modal.defaults, options);
+ s.o = $.extend({}, $.simplemodal.defaults, options);
// keep track of z-index
s.zIndex = s.o.zIndex;
@@ -305,7 +305,7 @@
s.getDimensions();
// add an iframe to prevent select options from bleeding through
- if (s.o.modal && browser.ie6) {
+ if (s.o.simplemodal && browser.ie6) {
s.d.iframe = $(' ')
.css($.extend(s.o.iframeCss, {
display: 'none',
@@ -326,7 +326,7 @@
.addClass('simplemodal-overlay')
.css($.extend(s.o.overlayCss, {
display: 'none',
- opacity: s.o.opacity / 100,
+ //opacity: s.o.opacity / 100, // config opcity by param_value.
height: s.o.modal ? d[0] : 0,
width: s.o.modal ? d[1] : 0,
position: 'fixed',
@@ -388,7 +388,7 @@
});
// bind the overlay click to the close function, if enabled
- if (s.o.modal && s.o.close && s.o.overlayClose) {
+ if (s.o.simplemodal && s.o.close && s.o.overlayClose) {
s.d.overlay.bind('click.simplemodal', function (e) {
e.preventDefault();
s.close();
@@ -397,7 +397,7 @@
// bind keydown events
doc.bind('keydown.simplemodal', function (e) {
- if (s.o.modal && e.keyCode === 9) { // TAB
+ if (s.o.simplemodal && e.keyCode === 9) { // TAB
s.watchTab(e);
}
else if ((s.o.close && s.o.escClose) && e.keyCode === 27) { // ESC
@@ -417,7 +417,7 @@
if (browser.ie6 || browser.ieQuirks) {
s.fixIE();
}
- else if (s.o.modal) {
+ else if (s.o.simplemodal) {
// update the iframe & overlay
s.d.iframe && s.d.iframe.css({height: w[0], width: w[1]});
s.d.overlay.css({height: d[0], width: d[1]});
@@ -440,7 +440,7 @@
var s = this, p = s.o.position;
// simulate fixed position - adapted from BlockUI
- $.each([s.d.iframe || null, !s.o.modal ? null : s.d.overlay, s.d.container.css('position') === 'fixed' ? s.d.container : null], function (i, el) {
+ $.each([s.d.iframe || null, !s.o.simplemodal ? null : s.d.overlay, s.d.container.css('position') === 'fixed' ? s.d.container : null], function (i, el) {
if (el) {
var bch = 'document.body.clientHeight', bcw = 'document.body.clientWidth',
bsh = 'document.body.scrollHeight', bsl = 'document.body.scrollLeft',
diff --git a/spree_theme/app/assets/javascripts/jquery.ui.customize.js b/spree_theme/app/assets/javascripts/jquery.ui.customize.js
new file mode 100644
index 00000000..82d394ac
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/jquery.ui.customize.js
@@ -0,0 +1,3 @@
+//= require jquery-ui/core
+// jquery.layout require jquery-ui/core
+// spree_backend require jquery-ui/datepicker
diff --git a/spree_theme/app/assets/javascripts/jssor.19/jssor.js b/spree_theme/app/assets/javascripts/jssor.19/jssor.js
new file mode 100644
index 00000000..2c90a9d2
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/jssor.19/jssor.js
@@ -0,0 +1,2928 @@
+/*
+* Jssor 19.0
+* http://www.jssor.com/
+*
+* Licensed under the MIT license:
+* http://www.opensource.org/licenses/MIT
+*
+* TERMS OF USE - Jssor
+*
+* Copyright 2014 Jssor
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*! Jssor */
+
+//$JssorDebug$
+var $JssorDebug$ = new function () {
+
+ this.$DebugMode = true;
+
+ // Methods
+
+ this.$Log = function (msg, important) {
+ var console = window.console || {};
+ var debug = this.$DebugMode;
+
+ if (debug && console.log) {
+ console.log(msg);
+ } else if (debug && important) {
+ alert(msg);
+ }
+ };
+
+ this.$Error = function (msg, e) {
+ var console = window.console || {};
+ var debug = this.$DebugMode;
+
+ if (debug && console.error) {
+ console.error(msg);
+ } else if (debug) {
+ alert(msg);
+ }
+
+ if (debug) {
+ // since we're debugging, fail fast by crashing
+ throw e || new Error(msg);
+ }
+ };
+
+ this.$Fail = function (msg) {
+ throw new Error(msg);
+ };
+
+ this.$Assert = function (value, msg) {
+ var debug = this.$DebugMode;
+ if (debug) {
+ if (!value)
+ throw new Error("Assert failed " + msg || "");
+ }
+ };
+
+ this.$Trace = function (msg) {
+ var console = window.console || {};
+ var debug = this.$DebugMode;
+
+ if (debug && console.log) {
+ console.log(msg);
+ }
+ };
+
+ this.$Execute = function (func) {
+ var debug = this.$DebugMode;
+ if (debug)
+ func();
+ };
+
+ this.$LiveStamp = function (obj, id) {
+ var debug = this.$DebugMode;
+ if (debug) {
+ var stamp = document.createElement("DIV");
+ stamp.setAttribute("id", id);
+
+ obj.$Live = stamp;
+ }
+ };
+
+ this.$C_AbstractProperty = function () {
+ ///
+ /// Tells compiler the property is abstract, it should be implemented by subclass.
+ ///
+
+ throw new Error("The property is abstract, it should be implemented by subclass.");
+ };
+
+ this.$C_AbstractMethod = function () {
+ ///
+ /// Tells compiler the method is abstract, it should be implemented by subclass.
+ ///
+
+ throw new Error("The method is abstract, it should be implemented by subclass.");
+ };
+
+ function C_AbstractClass(instance) {
+ ///
+ /// Tells compiler the class is abstract, it should be implemented by subclass.
+ ///
+
+ if (instance.constructor === C_AbstractClass.caller)
+ throw new Error("Cannot create instance of an abstract class.");
+ }
+
+ this.$C_AbstractClass = C_AbstractClass;
+};
+
+//$JssorEasing$
+var $JssorEasing$ = window.$JssorEasing$ = {
+ $EaseLinear: function (t) {
+ return t;
+ },
+ $EaseGoBack: function (t) {
+ return 1 - Math.abs((t *= 2) - 1);
+ },
+ $EaseSwing: function (t) {
+ return -Math.cos(t * Math.PI) / 2 + .5;
+ },
+ $EaseInQuad: function (t) {
+ return t * t;
+ },
+ $EaseOutQuad: function (t) {
+ return -t * (t - 2);
+ },
+ $EaseInOutQuad: function (t) {
+ return (t *= 2) < 1 ? 1 / 2 * t * t : -1 / 2 * (--t * (t - 2) - 1);
+ },
+ $EaseInCubic: function (t) {
+ return t * t * t;
+ },
+ $EaseOutCubic: function (t) {
+ return (t -= 1) * t * t + 1;
+ },
+ $EaseInOutCubic: function (t) {
+ return (t *= 2) < 1 ? 1 / 2 * t * t * t : 1 / 2 * ((t -= 2) * t * t + 2);
+ },
+ $EaseInQuart: function (t) {
+ return t * t * t * t;
+ },
+ $EaseOutQuart: function (t) {
+ return -((t -= 1) * t * t * t - 1);
+ },
+ $EaseInOutQuart: function (t) {
+ return (t *= 2) < 1 ? 1 / 2 * t * t * t * t : -1 / 2 * ((t -= 2) * t * t * t - 2);
+ },
+ $EaseInQuint: function (t) {
+ return t * t * t * t * t;
+ },
+ $EaseOutQuint: function (t) {
+ return (t -= 1) * t * t * t * t + 1;
+ },
+ $EaseInOutQuint: function (t) {
+ return (t *= 2) < 1 ? 1 / 2 * t * t * t * t * t : 1 / 2 * ((t -= 2) * t * t * t * t + 2);
+ },
+ $EaseInSine: function (t) {
+ return 1 - Math.cos(t * Math.PI / 2);
+ },
+ $EaseOutSine: function (t) {
+ return Math.sin(t * Math.PI / 2);
+ },
+ $EaseInOutSine: function (t) {
+ return -1 / 2 * (Math.cos(Math.PI * t) - 1);
+ },
+ $EaseInExpo: function (t) {
+ return t == 0 ? 0 : Math.pow(2, 10 * (t - 1));
+ },
+ $EaseOutExpo: function (t) {
+ return t == 1 ? 1 : -Math.pow(2, -10 * t) + 1;
+ },
+ $EaseInOutExpo: function (t) {
+ return t == 0 || t == 1 ? t : (t *= 2) < 1 ? 1 / 2 * Math.pow(2, 10 * (t - 1)) : 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
+ },
+ $EaseInCirc: function (t) {
+ return -(Math.sqrt(1 - t * t) - 1);
+ },
+ $EaseOutCirc: function (t) {
+ return Math.sqrt(1 - (t -= 1) * t);
+ },
+ $EaseInOutCirc: function (t) {
+ return (t *= 2) < 1 ? -1 / 2 * (Math.sqrt(1 - t * t) - 1) : 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
+ },
+ $EaseInElastic: function (t) {
+ if (!t || t == 1)
+ return t;
+ var p = .3, s = .075;
+ return -(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * 2 * Math.PI / p));
+ },
+ $EaseOutElastic: function (t) {
+ if (!t || t == 1)
+ return t;
+ var p = .3, s = .075;
+ return Math.pow(2, -10 * t) * Math.sin((t - s) * 2 * Math.PI / p) + 1;
+ },
+ $EaseInOutElastic: function (t) {
+ if (!t || t == 1)
+ return t;
+ var p = .45, s = .1125;
+ return (t *= 2) < 1 ? -.5 * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * 2 * Math.PI / p) : Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * 2 * Math.PI / p) * .5 + 1;
+ },
+ $EaseInBack: function (t) {
+ var s = 1.70158;
+ return t * t * ((s + 1) * t - s);
+ },
+ $EaseOutBack: function (t) {
+ var s = 1.70158;
+ return (t -= 1) * t * ((s + 1) * t + s) + 1;
+ },
+ $EaseInOutBack: function (t) {
+ var s = 1.70158;
+ return (t *= 2) < 1 ? 1 / 2 * t * t * (((s *= 1.525) + 1) * t - s) : 1 / 2 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2);
+ },
+ $EaseInBounce: function (t) {
+ return 1 - $JssorEasing$.$EaseOutBounce(1 - t)
+ },
+ $EaseOutBounce: function (t) {
+ return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
+ },
+ $EaseInOutBounce: function (t) {
+ return t < 1 / 2 ? $JssorEasing$.$EaseInBounce(t * 2) * .5 : $JssorEasing$.$EaseOutBounce(t * 2 - 1) * .5 + .5;
+ },
+ $EaseInWave: function (t) {
+ return 1 - Math.cos(t * Math.PI * 2)
+ },
+ $EaseOutWave: function (t) {
+ return Math.sin(t * Math.PI * 2);
+ },
+ $EaseOutJump: function (t) {
+ return 1 - (((t *= 2) < 1) ? (t = 1 - t) * t * t : (t -= 1) * t * t);
+ },
+ $EaseInJump: function (t) {
+ return ((t *= 2) < 1) ? t * t * t : (t = 2 - t) * t * t;
+ }
+};
+
+var $JssorDirection$ = window.$JssorDirection$ = {
+ $TO_LEFT: 0x0001,
+ $TO_RIGHT: 0x0002,
+ $TO_TOP: 0x0004,
+ $TO_BOTTOM: 0x0008,
+ $HORIZONTAL: 0x0003,
+ $VERTICAL: 0x000C,
+ //$LEFTRIGHT: 0x0003,
+ //$TOPBOTOM: 0x000C,
+ //$TOPLEFT: 0x0005,
+ //$TOPRIGHT: 0x0006,
+ //$BOTTOMLEFT: 0x0009,
+ //$BOTTOMRIGHT: 0x000A,
+ //$AROUND: 0x000F,
+
+ $GetDirectionHorizontal: function (direction) {
+ return direction & 0x0003;
+ },
+ $GetDirectionVertical: function (direction) {
+ return direction & 0x000C;
+ },
+ //$ChessHorizontal: function (direction) {
+ // return (~direction & 0x0003) + (direction & 0x000C);
+ //},
+ //$ChessVertical: function (direction) {
+ // return (~direction & 0x000C) + (direction & 0x0003);
+ //},
+ //$IsToLeft: function (direction) {
+ // return (direction & 0x0003) == 0x0001;
+ //},
+ //$IsToRight: function (direction) {
+ // return (direction & 0x0003) == 0x0002;
+ //},
+ //$IsToTop: function (direction) {
+ // return (direction & 0x000C) == 0x0004;
+ //},
+ //$IsToBottom: function (direction) {
+ // return (direction & 0x000C) == 0x0008;
+ //},
+ $IsHorizontal: function (direction) {
+ return direction & 0x0003;
+ },
+ $IsVertical: function (direction) {
+ return direction & 0x000C;
+ }
+};
+
+var $JssorKeyCode$ = {
+ $BACKSPACE: 8,
+ $COMMA: 188,
+ $DELETE: 46,
+ $DOWN: 40,
+ $END: 35,
+ $ENTER: 13,
+ $ESCAPE: 27,
+ $HOME: 36,
+ $LEFT: 37,
+ $NUMPAD_ADD: 107,
+ $NUMPAD_DECIMAL: 110,
+ $NUMPAD_DIVIDE: 111,
+ $NUMPAD_ENTER: 108,
+ $NUMPAD_MULTIPLY: 106,
+ $NUMPAD_SUBTRACT: 109,
+ $PAGE_DOWN: 34,
+ $PAGE_UP: 33,
+ $PERIOD: 190,
+ $RIGHT: 39,
+ $SPACE: 32,
+ $TAB: 9,
+ $UP: 38
+};
+
+//var $JssorAlignment$ = {
+// $TopLeft: 0x11,
+// $TopCenter: 0x12,
+// $TopRight: 0x14,
+// $MiddleLeft: 0x21,
+// $MiddleCenter: 0x22,
+// $MiddleRight: 0x24,
+// $BottomLeft: 0x41,
+// $BottomCenter: 0x42,
+// $BottomRight: 0x44,
+// $IsTop: function (aligment) {
+// return aligment & 0x10 > 0;
+// },
+// $IsMiddle: function (alignment) {
+// return alignment & 0x20 > 0;
+// },
+// $IsBottom: function (alignment) {
+// return alignment & 0x40 > 0;
+// },
+// $IsLeft: function (alignment) {
+// return alignment & 0x01 > 0;
+// },
+// $IsCenter: function (alignment) {
+// return alignment & 0x02 > 0;
+// },
+// $IsRight: function (alignment) {
+// return alignment & 0x04 > 0;
+// }
+//};
+
+// $Jssor$ is a static class, so make it singleton instance
+var $Jssor$ = window.$Jssor$ = new function () {
+ var _This = this;
+
+ //#region Constants
+ var REGEX_WHITESPACE_GLOBAL = /\S+/g;
+ var ROWSER_UNKNOWN = 0;
+ var BROWSER_IE = 1;
+ var BROWSER_FIREFOX = 2;
+ var BROWSER_SAFARI = 3;
+ var BROWSER_CHROME = 4;
+ var BROWSER_OPERA = 5;
+
+ //var arrActiveX = ["Msxml2.XMLHTTP", "Msxml3.XMLHTTP", "Microsoft.XMLHTTP"];
+ //#endregion
+
+ //#region Variables
+ var _Device;
+ var _Browser = 0;
+ var _BrowserRuntimeVersion = 0;
+ var _BrowserEngineVersion = 0;
+ var _BrowserJavascriptVersion = 0;
+ var _WebkitVersion = 0;
+
+ var _Navigator = navigator;
+ var _AppName = _Navigator.appName;
+ var _AppVersion = _Navigator.appVersion;
+ var _UserAgent = _Navigator.userAgent;
+
+ var _DocElmt = document.documentElement;
+ var _TransformProperty;
+ //#endregion
+
+ function Device() {
+ if (!_Device) {
+ _Device = {
+ $Evt_Down: "mousedown",
+ $Evt_Move: "mousemove",
+ $Evt_Up: "mouseup"
+ };
+ var msPrefix;
+ if (_Navigator.pointerEnabled || (msPrefix = _Navigator.msPointerEnabled)) {
+ _Device = {
+ $Evt_Down: msPrefix ? "MSPointerDown" : "pointerdown",
+ $Evt_Move: msPrefix ? "MSPointerMove" : "pointermove",
+ $Evt_Up: msPrefix ? "MSPointerUp" : "pointerup",
+ $Evt_Cancel: msPrefix ? "MSPointerCancel" : "pointercancel",
+ $TouchActionAttr: msPrefix ? "msTouchAction" : "touchAction",
+ $Touchable: _UserAgent.match(/iemobile/i)
+ };
+ }
+ else if ("ontouchstart" in window || "createTouch" in document) {
+ _Device = {
+ $Evt_Down: "touchstart",
+ $Evt_Move: "touchmove",
+ $Evt_Up: "touchend",
+ $Evt_Cancel: "touchcancel",
+ $Touchable: true,
+ $TouchOnly: true
+ };
+ }
+ }
+
+ return _Device;
+ }
+
+ function DetectBrowser(browser) {
+ if (!_Browser) {
+ if (_AppName == "Microsoft Internet Explorer" &&
+ !!window.attachEvent && !!window.ActiveXObject) {
+
+ var ieOffset = _UserAgent.indexOf("MSIE");
+ _Browser = BROWSER_IE;
+ _BrowserEngineVersion = ParseFloat(_UserAgent.substring(ieOffset + 5, _UserAgent.indexOf(";", ieOffset)));
+
+ //check IE javascript version
+ /*@cc_on
+ _BrowserJavascriptVersion = @_jscript_version;
+ @*/
+
+ // update: for intranet sites and compat view list sites, IE sends
+ // an IE7 User-Agent to the server to be interoperable, and even if
+ // the page requests a later IE version, IE will still report the
+ // IE7 UA to JS. we should be robust to self
+ //var docMode = document.documentMode;
+ //if (typeof docMode !== "undefined") {
+ // _BrowserRuntimeVersion = docMode;
+ //}
+
+ _BrowserRuntimeVersion = document.documentMode || _BrowserEngineVersion;
+
+ }
+ else if (_AppName == "Netscape" && !!window.addEventListener) {
+
+ var ffOffset = _UserAgent.indexOf("Firefox");
+ var saOffset = _UserAgent.indexOf("Safari");
+ var chOffset = _UserAgent.indexOf("Chrome");
+ var webkitOffset = _UserAgent.indexOf("AppleWebKit");
+
+ if (ffOffset >= 0) {
+ _Browser = BROWSER_FIREFOX;
+ _BrowserRuntimeVersion = ParseFloat(_UserAgent.substring(ffOffset + 8));
+ }
+ else if (saOffset >= 0) {
+ var slash = _UserAgent.substring(0, saOffset).lastIndexOf("/");
+ _Browser = (chOffset >= 0) ? BROWSER_CHROME : BROWSER_SAFARI;
+ _BrowserRuntimeVersion = ParseFloat(_UserAgent.substring(slash + 1, saOffset));
+ }
+
+ if (webkitOffset >= 0)
+ _WebkitVersion = ParseFloat(_UserAgent.substring(webkitOffset + 12));
+ }
+ else {
+ var match = /(opera)(?:.*version|)[ \/]([\w.]+)/i.exec(_UserAgent);
+ if (match) {
+ _Browser = BROWSER_OPERA;
+ _BrowserRuntimeVersion = ParseFloat(match[2]);
+ }
+ }
+ }
+
+ return browser == _Browser;
+ }
+
+ function IsBrowserIE() {
+ return DetectBrowser(BROWSER_IE);
+ }
+
+ function IsBrowserIeQuirks() {
+ return IsBrowserIE() && (_BrowserRuntimeVersion < 6 || document.compatMode == "BackCompat"); //Composite to "CSS1Compat"
+ }
+
+ function IsBrowserFireFox() {
+ return DetectBrowser(BROWSER_FIREFOX);
+ }
+
+ function IsBrowserSafari() {
+ return DetectBrowser(BROWSER_SAFARI);
+ }
+
+ function IsBrowserChrome() {
+ return DetectBrowser(BROWSER_CHROME);
+ }
+
+ function IsBrowserOpera() {
+ return DetectBrowser(BROWSER_OPERA);
+ }
+
+ function IsBrowserBadTransform() {
+ return IsBrowserSafari() && (_WebkitVersion > 534) && (_WebkitVersion < 535);
+ }
+
+ function IsBrowserIe9Earlier() {
+ return IsBrowserIE() && _BrowserRuntimeVersion < 9;
+ }
+
+ function GetTransformProperty(elmt) {
+
+ if (!_TransformProperty) {
+ // Note that in some versions of IE9 it is critical that
+ // msTransform appear in this list before MozTransform
+
+ each(['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (property) {
+ if (elmt.style[property] != undefined) {
+ _TransformProperty = property;
+ return true;
+ }
+ });
+
+ _TransformProperty = _TransformProperty || "transform";
+ }
+
+ return _TransformProperty;
+ }
+
+ // Helpers
+ function getOffsetParent(elmt, isFixed) {
+ // IE and Opera "fixed" position elements don't have offset parents.
+ // regardless, if it's fixed, its offset parent is the body.
+ if (isFixed && elmt != document.body) {
+ return document.body;
+ } else {
+ return elmt.offsetParent;
+ }
+ }
+
+ function toString(obj) {
+ return Object.prototype.toString.call(obj);
+ }
+
+ // [[Class]] -> type pairs
+ var class2type;
+
+ function each(object, callback) {
+ if (toString(object) == "[object Array]") {
+ for (var i = 0; i < object.length; i++) {
+ if (callback(object[i], i, object)) {
+ return true;
+ }
+ }
+ }
+ else {
+ for (var name in object) {
+ if (callback(object[name], name, object)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ function GetClass2Type() {
+ if (!class2type) {
+ class2type = {};
+ each(["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object"], function (name) {
+ class2type["[object " + name + "]"] = name.toLowerCase();
+ });
+ }
+
+ return class2type;
+ }
+
+ function type(obj) {
+ return obj == null ? String(obj) : GetClass2Type()[toString(obj)] || "object";
+ }
+
+ function isPlainObject(obj) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if (!obj || type(obj) !== "object" || obj.nodeType || _This.$IsWindow(obj)) {
+ return false;
+ }
+
+ var hasOwn = Object.prototype.hasOwnProperty;
+
+ try {
+ // Not own constructor property must be Object
+ if (obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
+ return false;
+ }
+ } catch (e) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for (key in obj) { }
+
+ return key === undefined || hasOwn.call(obj, key);
+ }
+
+ function Point(x, y) {
+ return { x: x, y: y };
+ }
+
+ function Delay(code, delay) {
+ setTimeout(code, delay || 0);
+ }
+
+ function RemoveByReg(str, reg) {
+ var m = reg.exec(str);
+
+ if (m) {
+ var header = str.substr(0, m.index);
+ var tailer = str.substr(m.lastIndex + 1, str.length - (m.lastIndex + 1));
+ str = header + tailer;
+ }
+
+ return str;
+ }
+
+ function BuildNewCss(oldCss, removeRegs, replaceValue) {
+ var css = (!oldCss || oldCss == "inherit") ? "" : oldCss;
+
+ each(removeRegs, function (removeReg) {
+ var m = removeReg.exec(css);
+
+ if (m) {
+ var header = css.substr(0, m.index);
+ var tailer = css.substr(m.lastIndex + 1, css.length - (m.lastIndex + 1));
+ css = header + tailer;
+ }
+ });
+
+ css = replaceValue + (css.indexOf(" ") != 0 ? " " : "") + css;
+
+ return css;
+ }
+
+ function SetStyleFilterIE(elmt, value) {
+ if (_BrowserRuntimeVersion < 9) {
+ elmt.style.filter = value;
+ }
+ }
+
+ function SetStyleMatrixIE(elmt, matrix, offset) {
+ //matrix is not for ie9+ running in ie8- mode
+ if (_BrowserJavascriptVersion < 9) {
+ var oldFilterValue = elmt.style.filter;
+ var matrixReg = new RegExp(/[\s]*progid:DXImageTransform\.Microsoft\.Matrix\([^\)]*\)/g);
+ var matrixValue = matrix ? "progid:DXImageTransform.Microsoft.Matrix(" + "M11=" + matrix[0][0] + ", M12=" + matrix[0][1] + ", M21=" + matrix[1][0] + ", M22=" + matrix[1][1] + ", SizingMethod='auto expand')" : "";
+
+ var newFilterValue = BuildNewCss(oldFilterValue, [matrixReg], matrixValue);
+
+ SetStyleFilterIE(elmt, newFilterValue);
+
+ _This.$CssMarginTop(elmt, offset.y);
+ _This.$CssMarginLeft(elmt, offset.x);
+ }
+ }
+
+ // Methods
+
+ //_This.$IsTouchDevice = function () {
+ // return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(_UserAgent);
+ //};
+
+ _This.$Device = Device;
+
+ _This.$IsBrowserIE = IsBrowserIE;
+
+ _This.$IsBrowserIeQuirks = IsBrowserIeQuirks;
+
+ _This.$IsBrowserFireFox = IsBrowserFireFox;
+
+ _This.$IsBrowserSafari = IsBrowserSafari;
+
+ _This.$IsBrowserChrome = IsBrowserChrome;
+
+ _This.$IsBrowserOpera = IsBrowserOpera;
+
+ _This.$IsBrowserBadTransform = IsBrowserBadTransform;
+
+ _This.$IsBrowserIe9Earlier = IsBrowserIe9Earlier;
+
+ _This.$BrowserVersion = function () {
+ return _BrowserRuntimeVersion;
+ };
+
+ _This.$BrowserEngineVersion = function () {
+ return _BrowserEngineVersion || _BrowserRuntimeVersion;
+ };
+
+ _This.$WebKitVersion = function () {
+ DetectBrowser();
+
+ return _WebkitVersion;
+ };
+
+ _This.$Delay = Delay;
+
+ _This.$Inherit = function (instance, baseClass) {
+ baseClass.call(instance);
+ return Extend({}, instance);
+ };
+
+ function Construct(instance) {
+ instance.constructor === Construct.caller && instance.$Construct && instance.$Construct.apply(instance, Construct.caller.arguments);
+ }
+
+ _This.$Construct = Construct;
+
+ _This.$GetElement = function (elmt) {
+ if (_This.$IsString(elmt)) {
+ elmt = document.getElementById(elmt);
+ }
+
+ return elmt;
+ };
+
+ function GetEvent(event) {
+ return event || window.event;
+ }
+
+ _This.$GetEvent = GetEvent;
+
+ _This.$EventSrc = function (event) {
+ event = GetEvent(event);
+ return event.target || event.srcElement || document;
+ };
+
+ _This.$EventTarget = function (event) {
+ event = GetEvent(event);
+ return event.relatedTarget || event.toElement;
+ };
+
+ _This.$MousePosition = function (event) {
+ event = GetEvent(event);
+ var body = document.body;
+
+ return {
+ x: event.pageX || event.clientX + (_DocElmt.scrollLeft || body.scrollLeft || 0) - (_DocElmt.clientLeft || body.clientLeft || 0) || 0,
+ y: event.pageY || event.clientY + (_DocElmt.scrollTop || body.scrollTop || 0) - (_DocElmt.clientTop || body.clientTop || 0) || 0
+ };
+ };
+
+ _This.$PageScroll = function () {
+ var body = document.body;
+
+ return {
+ x: (window.pageXOffset || _DocElmt.scrollLeft || body.scrollLeft || 0) - (_DocElmt.clientLeft || body.clientLeft || 0),
+ y: (window.pageYOffset || _DocElmt.scrollTop || body.scrollTop || 0) - (_DocElmt.clientTop || body.clientTop || 0)
+ };
+ };
+
+ _This.$WindowSize = function () {
+ var body = document.body;
+
+ return {
+ x: body.clientWidth || _DocElmt.clientWidth,
+ y: body.clientHeight || _DocElmt.clientHeight
+ };
+ };
+
+ //_This.$GetElementPosition = function (elmt) {
+ // elmt = _This.$GetElement(elmt);
+ // var result = Point();
+
+ // // technique from:
+ // // http://www.quirksmode.org/js/findpos.html
+ // // with special check for "fixed" elements.
+
+ // while (elmt) {
+ // result.x += elmt.offsetLeft;
+ // result.y += elmt.offsetTop;
+
+ // var isFixed = _This.$GetElementStyle(elmt).position == "fixed";
+
+ // if (isFixed) {
+ // result = result.$Plus(_This.$PageScroll(window));
+ // }
+
+ // elmt = getOffsetParent(elmt, isFixed);
+ // }
+
+ // return result;
+ //};
+
+ //_This.$GetMouseScroll = function (event) {
+ // event = GetEvent(event);
+ // var delta = 0; // default value
+
+ // // technique from:
+ // // http://blog.paranoidferret.com/index.php/2007/10/31/javascript-tutorial-the-scroll-wheel/
+
+ // if (typeof (event.wheelDelta) == "number") {
+ // delta = event.wheelDelta;
+ // } else if (typeof (event.detail) == "number") {
+ // delta = event.detail * -1;
+ // } else {
+ // $JssorDebug$.$Fail("Unknown event mouse scroll, no known technique.");
+ // }
+
+ // // normalize value to [-1, 1]
+ // return delta ? delta / Math.abs(delta) : 0;
+ //};
+
+ //_This.$MakeAjaxRequest = function (url, callback) {
+ // var async = typeof (callback) == "function";
+ // var req = null;
+
+ // if (async) {
+ // var actual = callback;
+ // var callback = function () {
+ // Delay($Jssor$.$CreateCallback(null, actual, req), 1);
+ // };
+ // }
+
+ // if (window.ActiveXObject) {
+ // for (var i = 0; i < arrActiveX.length; i++) {
+ // try {
+ // req = new ActiveXObject(arrActiveX[i]);
+ // break;
+ // } catch (e) {
+ // continue;
+ // }
+ // }
+ // } else if (window.XMLHttpRequest) {
+ // req = new XMLHttpRequest();
+ // }
+
+ // if (!req) {
+ // $JssorDebug$.$Fail("Browser doesn't support XMLHttpRequest.");
+ // }
+
+ // if (async) {
+ // req.onreadystatechange = function () {
+ // if (req.readyState == 4) {
+ // // prevent memory leaks by breaking circular reference now
+ // req.onreadystatechange = new Function();
+ // callback();
+ // }
+ // };
+ // }
+
+ // try {
+ // req.open("GET", url, async);
+ // req.send(null);
+ // } catch (e) {
+ // $JssorDebug$.$Log(e.name + " while making AJAX request: " + e.message);
+
+ // req.onreadystatechange = null;
+ // req = null;
+
+ // if (async) {
+ // callback();
+ // }
+ // }
+
+ // return async ? null : req;
+ //};
+
+ //_This.$ParseXml = function (string) {
+ // var xmlDoc = null;
+
+ // if (window.ActiveXObject) {
+ // try {
+ // xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+ // xmlDoc.async = false;
+ // xmlDoc.loadXML(string);
+ // } catch (e) {
+ // $JssorDebug$.$Log(e.name + " while parsing XML (ActiveX): " + e.message);
+ // }
+ // } else if (window.DOMParser) {
+ // try {
+ // var parser = new DOMParser();
+ // xmlDoc = parser.parseFromString(string, "text/xml");
+ // } catch (e) {
+ // $JssorDebug$.$Log(e.name + " while parsing XML (DOMParser): " + e.message);
+ // }
+ // } else {
+ // $JssorDebug$.$Fail("Browser doesn't support XML DOM.");
+ // }
+
+ // return xmlDoc;
+ //};
+
+ function Css(elmt, name, value) {
+ ///
+ /// access css
+ /// $Jssor$.$Css(elmt, name); //get css value
+ /// $Jssor$.$Css(elmt, name, value); //set css value
+ ///
+ ///
+ /// the element to access css
+ ///
+ ///
+ /// the name of css property
+ ///
+ ///
+ /// the value to set
+ ///
+ if (value != undefined) {
+ elmt.style[name] = value;
+ }
+ else {
+ var style = elmt.currentStyle || elmt.style;
+ value = style[name];
+
+ if (value == "" && window.getComputedStyle) {
+ style = elmt.ownerDocument.defaultView.getComputedStyle(elmt, null);
+
+ style && (value = style.getPropertyValue(name) || style[name]);
+ }
+
+ return value;
+ }
+ }
+
+ function CssN(elmt, name, value, isDimensional) {
+ ///
+ /// access css as numeric
+ /// $Jssor$.$CssN(elmt, name); //get css value
+ /// $Jssor$.$CssN(elmt, name, value); //set css value
+ ///
+ ///
+ /// the element to access css
+ ///
+ ///
+ /// the name of css property
+ ///
+ ///
+ /// the value to set
+ ///
+ if (value != undefined) {
+ isDimensional && (value += "px");
+ Css(elmt, name, value);
+ }
+ else {
+ return ParseFloat(Css(elmt, name));
+ }
+ }
+
+ function CssP(elmt, name, value) {
+ ///
+ /// access css in pixel as numeric, like 'top', 'left', 'width', 'height'
+ /// $Jssor$.$CssP(elmt, name); //get css value
+ /// $Jssor$.$CssP(elmt, name, value); //set css value
+ ///
+ ///
+ /// the element to access css
+ ///
+ ///
+ /// the name of css property
+ ///
+ ///
+ /// the value to set
+ ///
+ return CssN(elmt, name, value, true);
+ }
+
+ function CssProxy(name, numericOrDimension) {
+ ///
+ /// create proxy to access css, CssProxy(name[, numericOrDimension]);
+ ///
+ ///
+ /// the element to access css
+ ///
+ ///
+ /// not set: access original css, 1: access css as numeric, 2: access css in pixel as numeric
+ ///
+ var isDimensional = numericOrDimension & 2;
+ var cssAccessor = numericOrDimension ? CssN : Css;
+ return function (elmt, value) {
+ return cssAccessor(elmt, name, value, isDimensional);
+ };
+ }
+
+ function GetStyleOpacity(elmt) {
+ if (IsBrowserIE() && _BrowserEngineVersion < 9) {
+ var match = /opacity=([^)]*)/.exec(elmt.style.filter || "");
+ return match ? (ParseFloat(match[1]) / 100) : 1;
+ }
+ else
+ return ParseFloat(elmt.style.opacity || "1");
+ }
+
+ function SetStyleOpacity(elmt, opacity, ie9EarlierForce) {
+
+ if (IsBrowserIE() && _BrowserEngineVersion < 9) {
+ //var filterName = "filter"; // _BrowserEngineVersion < 8 ? "filter" : "-ms-filter";
+ var finalFilter = elmt.style.filter || "";
+
+ // for CSS filter browsers (IE), remove alpha filter if it's unnecessary.
+ // update: doing _This always since IE9 beta seems to have broken the
+ // behavior if we rely on the programmatic filters collection.
+ var alphaReg = new RegExp(/[\s]*alpha\([^\)]*\)/g);
+
+ // important: note the lazy star! _This protects against
+ // multiple filters; we don't want to delete the other ones.
+ // update: also trimming extra whitespace around filter.
+
+ var ieOpacity = Math.round(100 * opacity);
+ var alphaFilter = "";
+ if (ieOpacity < 100 || ie9EarlierForce) {
+ alphaFilter = "alpha(opacity=" + ieOpacity + ") ";
+ //elmt.style["-ms-filter"] = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + ieOpacity + ") ";
+ }
+
+ var newFilterValue = BuildNewCss(finalFilter, [alphaReg], alphaFilter);
+
+ SetStyleFilterIE(elmt, newFilterValue);
+ }
+
+ //if (!IsBrowserIE() || _BrowserEngineVersion >= 9)
+ else {
+ elmt.style.opacity = opacity == 1 ? "" : Math.round(opacity * 100) / 100;
+ }
+ }
+
+ function SetStyleTransformInternal(elmt, transform) {
+ var rotate = transform.$Rotate || 0;
+ var scale = transform.$Scale == undefined ? 1 : transform.$Scale;
+
+ if (IsBrowserIe9Earlier()) {
+ var matrix = _This.$CreateMatrix(rotate / 180 * Math.PI, scale, scale);
+ SetStyleMatrixIE(elmt, (!rotate && scale == 1) ? null : matrix, _This.$GetMatrixOffset(matrix, transform.$OriginalWidth, transform.$OriginalHeight));
+ }
+ else {
+ //rotate(15deg) scale(.5) translateZ(0)
+ var transformProperty = GetTransformProperty(elmt);
+ if (transformProperty) {
+ var transformValue = "rotate(" + rotate % 360 + "deg) scale(" + scale + ")";
+
+ //needed for touch device, no need for desktop device
+ if (IsBrowserChrome() && _WebkitVersion > 535 && "ontouchstart" in window)
+ transformValue += " perspective(2000px)";
+
+ elmt.style[transformProperty] = transformValue;
+ }
+ }
+ }
+
+ _This.$SetStyleTransform = function (elmt, transform) {
+ if (IsBrowserBadTransform()) {
+ Delay(_This.$CreateCallback(null, SetStyleTransformInternal, elmt, transform));
+ }
+ else {
+ SetStyleTransformInternal(elmt, transform);
+ }
+ };
+
+ _This.$SetStyleTransformOrigin = function (elmt, transformOrigin) {
+ var transformProperty = GetTransformProperty(elmt);
+
+ if (transformProperty)
+ elmt.style[transformProperty + "Origin"] = transformOrigin;
+ };
+
+ _This.$CssScale = function (elmt, scale) {
+
+ if (IsBrowserIE() && _BrowserEngineVersion < 9 || (_BrowserEngineVersion < 10 && IsBrowserIeQuirks())) {
+ elmt.style.zoom = (scale == 1) ? "" : scale;
+ }
+ else {
+ var transformProperty = GetTransformProperty(elmt);
+
+ if (transformProperty) {
+ //rotate(15deg) scale(.5)
+ var transformValue = "scale(" + scale + ")";
+
+ var oldTransformValue = elmt.style[transformProperty];
+ var scaleReg = new RegExp(/[\s]*scale\(.*?\)/g);
+
+ var newTransformValue = BuildNewCss(oldTransformValue, [scaleReg], transformValue);
+
+ elmt.style[transformProperty] = newTransformValue;
+ }
+ }
+ };
+
+ _This.$EnableHWA = function (elmt) {
+ if (!elmt.style[GetTransformProperty(elmt)] || elmt.style[GetTransformProperty(elmt)] == "none")
+ elmt.style[GetTransformProperty(elmt)] = "perspective(2000px)";
+ };
+
+ _This.$DisableHWA = function (elmt) {
+ //if (force || elmt.style[GetTransformProperty(elmt)] == "perspective(2000px)")
+ elmt.style[GetTransformProperty(elmt)] = "none";
+ };
+
+ var ie8OffsetWidth = 0;
+ var ie8OffsetHeight = 0;
+ //var ie8WindowResizeCallbackHandlers;
+ //var ie8LastVerticalScrollbar;
+ //var toggleInfo = "";
+
+ //function Ie8WindowResizeFilter(window, handler) {
+
+ // var trigger = true;
+
+ // var checkElement = (IsBrowserIeQuirks() ? window.document.body : window.document.documentElement);
+ // if (checkElement) {
+ // //check vertical bar
+ // //var hasVerticalBar = checkElement.scrollHeight > checkElement.clientHeight;
+ // //var verticalBarToggle = hasVerticalBar != ie8LastVerticalScrollbar;
+ // //ie8LastVerticalScrollbar = hasVerticalBar;
+
+ // var widthChange = checkElement.offsetWidth - ie8OffsetWidth;
+ // var heightChange = checkElement.offsetHeight - ie8OffsetHeight;
+ // if (widthChange || heightChange) {
+
+ // ie8OffsetWidth += widthChange;
+ // ie8OffsetHeight += heightChange;
+ // }
+ // else
+ // trigger = false;
+ // }
+
+ // trigger && handler();
+ //}
+
+ //_This.$OnWindowResize = function (window, handler) {
+
+ // if (IsBrowserIE() && _BrowserEngineVersion < 9) {
+ // if (!ie8WindowResizeCallbackHandlers) {
+ // ie8WindowResizeCallbackHandlers = [handler];
+ // handler = _This.$CreateCallback(null, Ie8WindowResizeFilter, window);
+ // }
+ // else {
+ // ie8WindowResizeCallbackHandlers.push(handler);
+ // return;
+ // }
+ // }
+
+ // _This.$AddEvent(window, "resize", handler);
+ //};
+
+ _This.$WindowResizeFilter = function (window, handler) {
+ return IsBrowserIe9Earlier() ? function () {
+
+ var trigger = true;
+
+ var checkElement = (IsBrowserIeQuirks() ? window.document.body : window.document.documentElement);
+ if (checkElement) {
+ //check vertical bar
+ //var hasVerticalBar = checkElement.scrollHeight > checkElement.clientHeight;
+ //var verticalBarToggle = hasVerticalBar != ie8LastVerticalScrollbar;
+ //ie8LastVerticalScrollbar = hasVerticalBar;
+
+ var widthChange = checkElement.offsetWidth - ie8OffsetWidth;
+ var heightChange = checkElement.offsetHeight - ie8OffsetHeight;
+ if (widthChange || heightChange) {
+ ie8OffsetWidth += widthChange;
+ ie8OffsetHeight += heightChange;
+ }
+ else
+ trigger = false;
+ }
+
+ trigger && handler();
+
+ } : handler;
+ };
+
+ _This.$MouseOverOutFilter = function (handler, target) {
+ ///
+ /// The target element to detect mouse over/out events. (for ie < 9 compatibility)
+ ///
+
+ $JssorDebug$.$Execute(function () {
+ if (!target) {
+ throw new Error("Null reference, parameter \"target\".");
+ }
+ });
+
+ return function (event) {
+ event = GetEvent(event);
+
+ var eventName = event.type;
+ var related = event.relatedTarget || (eventName == "mouseout" ? event.toElement : event.fromElement);
+
+ if (!related || (related !== target && !_This.$IsChild(target, related))) {
+ handler(event);
+ }
+ };
+ };
+
+ _This.$AddEvent = function (elmt, eventName, handler, useCapture) {
+ elmt = _This.$GetElement(elmt);
+
+ $JssorDebug$.$Execute(function () {
+ if (!elmt) {
+ $JssorDebug$.$Fail("Parameter 'elmt' not specified.");
+ }
+
+ if (!handler) {
+ $JssorDebug$.$Fail("Parameter 'handler' not specified.");
+ }
+
+ if (!elmt.addEventListener && !elmt.attachEvent) {
+ $JssorDebug$.$Fail("Unable to attach event handler, no known technique.");
+ }
+ });
+
+ // technique from:
+ // http://blog.paranoidferret.com/index.php/2007/08/10/javascript-working-with-events/
+
+ //function Handler(event) {
+ // handler(event || window.event);
+ //}
+
+ if (elmt.addEventListener) {
+ if (eventName == "mousewheel") {
+ elmt.addEventListener("DOMMouseScroll", handler, useCapture);
+ }
+ // we are still going to add the mousewheel -- not a mistake!
+ // _This is for opera, since it uses onmousewheel but needs addEventListener.
+ elmt.addEventListener(eventName, handler, useCapture);
+ }
+ else if (elmt.attachEvent) {
+ elmt.attachEvent("on" + eventName, handler);
+ if (useCapture && elmt.setCapture) {
+ elmt.setCapture();
+ }
+ }
+ };
+
+ _This.$RemoveEvent = function (elmt, eventName, handler, useCapture) {
+ elmt = _This.$GetElement(elmt);
+
+ // technique from:
+ // http://blog.paranoidferret.com/index.php/2007/08/10/javascript-working-with-events/
+
+ if (elmt.removeEventListener) {
+ if (eventName == "mousewheel") {
+ elmt.removeEventListener("DOMMouseScroll", handler, useCapture);
+ }
+ // we are still going to remove the mousewheel -- not a mistake!
+ // _This is for opera, since it uses onmousewheel but needs removeEventListener.
+ elmt.removeEventListener(eventName, handler, useCapture);
+ }
+ else if (elmt.detachEvent) {
+ elmt.detachEvent("on" + eventName, handler);
+ if (useCapture && elmt.releaseCapture) {
+ elmt.releaseCapture();
+ }
+ }
+ };
+
+ _This.$FireEvent = function (elmt, eventName) {
+ //var document = elmt.document;
+
+ $JssorDebug$.$Execute(function () {
+ if (!document.createEvent && !document.createEventObject) {
+ $JssorDebug$.$Fail("Unable to fire event, no known technique.");
+ }
+
+ if (!elmt.dispatchEvent && !elmt.fireEvent) {
+ $JssorDebug$.$Fail("Unable to fire event, no known technique.");
+ }
+ });
+
+ var evento;
+
+ if (document.createEvent) {
+ evento = document.createEvent("HTMLEvents");
+ evento.initEvent(eventName, false, false);
+ elmt.dispatchEvent(evento);
+ }
+ else {
+ var ieEventName = "on" + eventName;
+ evento = document.createEventObject();
+ //event.eventType = ieEventName;
+ //event.eventName = ieEventName;
+
+ elmt.fireEvent(ieEventName, evento);
+ }
+ };
+
+ //_This.$AddEventBrowserMouseUp = function (handler, userCapture) {
+ // _This.$AddEvent((IsBrowserIe9Earlier()) ? document : window, "mouseup", handler, userCapture);
+ //};
+
+ //_This.$RemoveEventBrowserMouseUp = function (handler, userCapture) {
+ // _This.$RemoveEvent((IsBrowserIe9Earlier()) ? document : window, "mouseup", handler, userCapture);
+ //};
+
+ //_This.$AddEventBrowserMouseDown = function (handler, userCapture) {
+ // _This.$AddEvent((IsBrowserIe9Earlier()) ? document : window, "mousedown", handler, userCapture);
+ //};
+
+ //_This.$RemoveEventBrowserMouseDown = function (handler, userCapture) {
+ // _This.$RemoveEvent((IsBrowserIe9Earlier()) ? document : window, "mousedown", handler, userCapture);
+ //};
+
+ _This.$CancelEvent = function (event) {
+ event = GetEvent(event);
+
+ // technique from:
+ // http://blog.paranoidferret.com/index.php/2007/08/10/javascript-working-with-events/
+
+ if (event.preventDefault) {
+ event.preventDefault(); // W3C for preventing default
+ }
+
+ event.cancel = true; // legacy for preventing default
+ event.returnValue = false; // IE for preventing default
+ };
+
+ _This.$StopEvent = function (event) {
+ event = GetEvent(event);
+
+ // technique from:
+ // http://blog.paranoidferret.com/index.php/2007/08/10/javascript-working-with-events/
+
+ if (event.stopPropagation) {
+ event.stopPropagation(); // W3C for stopping propagation
+ }
+
+ event.cancelBubble = true; // IE for stopping propagation
+ };
+
+ _This.$CreateCallback = function (object, method) {
+ // create callback args
+ var initialArgs = [].slice.call(arguments, 2);
+
+ // create closure to apply method
+ var callback = function () {
+ // concatenate new args, but make a copy of initialArgs first
+ var args = initialArgs.concat([].slice.call(arguments, 0));
+
+ return method.apply(object, args);
+ };
+
+ //$JssorDebug$.$LiveStamp(callback, "callback_" + ($Jssor$.$GetNow() & 0xFFFFFF));
+
+ return callback;
+ };
+
+ //var _Freeer;
+ //_This.$FreeElement = function (elmt) {
+ // if (!_Freeer)
+ // _Freeer = _This.$CreateDiv();
+
+ // if (elmt) {
+ // $Jssor$.$AppendChild(_Freeer, elmt);
+ // $Jssor$.$ClearInnerHtml(_Freeer);
+ // }
+ //};
+
+ _This.$InnerText = function (elmt, text) {
+ if (text == undefined)
+ return elmt.textContent || elmt.innerText;
+
+ var textNode = document.createTextNode(text);
+ _This.$Empty(elmt);
+ elmt.appendChild(textNode);
+ };
+
+ _This.$InnerHtml = function (elmt, html) {
+ if (html == undefined)
+ return elmt.innerHTML;
+
+ elmt.innerHTML = html;
+ };
+
+ _This.$GetClientRect = function (elmt) {
+ var rect = elmt.getBoundingClientRect();
+
+ return { x: rect.left, y: rect.top, w: rect.right - rect.left, h: rect.bottom - rect.top };
+ };
+
+ _This.$ClearInnerHtml = function (elmt) {
+ elmt.innerHTML = "";
+ };
+
+ _This.$EncodeHtml = function (text) {
+ var div = _This.$CreateDiv();
+ _This.$InnerText(div, text);
+ return _This.$InnerHtml(div);
+ };
+
+ _This.$DecodeHtml = function (html) {
+ var div = _This.$CreateDiv();
+ _This.$InnerHtml(div, html);
+ return _This.$InnerText(div);
+ };
+
+ _This.$SelectElement = function (elmt) {
+ var userSelection;
+ if (window.getSelection) {
+ //W3C default
+ userSelection = window.getSelection();
+ }
+ var theRange = null;
+ if (document.createRange) {
+ theRange = document.createRange();
+ theRange.selectNode(elmt);
+ }
+ else {
+ theRange = document.body.createTextRange();
+ theRange.moveToElementText(elmt);
+ theRange.select();
+ }
+ //set user selection
+ if (userSelection)
+ userSelection.addRange(theRange);
+ };
+
+ _This.$DeselectElements = function () {
+ if (document.selection) {
+ document.selection.empty();
+ } else if (window.getSelection) {
+ window.getSelection().removeAllRanges();
+ }
+ };
+
+ _This.$Children = function (elmt, includeAll) {
+ var children = [];
+
+ for (var tmpEl = elmt.firstChild; tmpEl; tmpEl = tmpEl.nextSibling) {
+ if (includeAll || tmpEl.nodeType == 1) {
+ children.push(tmpEl);
+ }
+ }
+
+ return children;
+ };
+
+ function FindChild(elmt, attrValue, noDeep, attrName) {
+ attrName = attrName || "u";
+
+ for (elmt = elmt ? elmt.firstChild : null; elmt; elmt = elmt.nextSibling) {
+ if (elmt.nodeType == 1) {
+ if (AttributeEx(elmt, attrName) == attrValue)
+ return elmt;
+
+ if (!noDeep) {
+ var childRet = FindChild(elmt, attrValue, noDeep, attrName);
+ if (childRet)
+ return childRet;
+ }
+ }
+ }
+ }
+
+ _This.$FindChild = FindChild;
+
+ function FindChildren(elmt, attrValue, noDeep, attrName) {
+ attrName = attrName || "u";
+
+ var ret = [];
+
+ for (elmt = elmt ? elmt.firstChild : null; elmt; elmt = elmt.nextSibling) {
+ if (elmt.nodeType == 1) {
+ if (AttributeEx(elmt, attrName) == attrValue)
+ ret.push(elmt);
+
+ if (!noDeep) {
+ var childRet = FindChildren(elmt, attrValue, noDeep, attrName);
+ if (childRet.length)
+ ret = ret.concat(childRet);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ _This.$FindChildren = FindChildren;
+
+ function FindChildByTag(elmt, tagName, noDeep) {
+
+ for (elmt = elmt ? elmt.firstChild : null; elmt; elmt = elmt.nextSibling) {
+ if (elmt.nodeType == 1) {
+ if (elmt.tagName == tagName)
+ return elmt;
+
+ if (!noDeep) {
+ var childRet = FindChildByTag(elmt, tagName, noDeep);
+ if (childRet)
+ return childRet;
+ }
+ }
+ }
+ }
+
+ _This.$FindChildByTag = FindChildByTag;
+
+ function FindChildrenByTag(elmt, tagName, noDeep) {
+ var ret = [];
+
+ for (elmt = elmt ? elmt.firstChild : null; elmt; elmt = elmt.nextSibling) {
+ if (elmt.nodeType == 1) {
+ if (!tagName || elmt.tagName == tagName)
+ ret.push(elmt);
+
+ if (!noDeep) {
+ var childRet = FindChildrenByTag(elmt, tagName, noDeep);
+ if (childRet.length)
+ ret = ret.concat(childRet);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ _This.$FindChildrenByTag = FindChildrenByTag;
+
+ _This.$GetElementsByTag = function (elmt, tagName) {
+ return elmt.getElementsByTagName(tagName);
+ };
+
+ function Extend(target) {
+ for (var i = 1; i < arguments.length; i++) {
+
+ var options = arguments[i];
+
+ // Only deal with non-null/undefined values
+ if (options) {
+ // Extend the base object
+ for (var name in options) {
+ target[name] = options[name];
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+ }
+
+ _This.$Extend = Extend;
+
+ function Unextend(target, options) {
+ $JssorDebug$.$Assert(options);
+
+ var unextended = {};
+
+ // Extend the base object
+ for (var name in target) {
+ if (target[name] !== options[name]) {
+ unextended[name] = target[name];
+ }
+ }
+
+ // Return the modified object
+ return unextended;
+ }
+
+ _This.$Unextend = Unextend;
+
+ _This.$IsUndefined = function (obj) {
+ return type(obj) == "undefined";
+ };
+
+ _This.$IsFunction = function (obj) {
+ return type(obj) == "function";
+ };
+
+ _This.$IsArray = function (obj) {
+ return type(obj) == "array";
+ };
+
+ _This.$IsString = function (obj) {
+ return type(obj) == "string";
+ };
+
+ _This.$IsNumeric = function (obj) {
+ return !isNaN(ParseFloat(obj)) && isFinite(obj);
+ };
+
+ _This.$IsWindow = function (obj) {
+ return obj && obj == obj.window;
+ };
+
+ _This.$Type = type;
+
+ // args is for internal usage only
+ _This.$Each = each;
+
+ _This.$IsPlainObject = isPlainObject;
+
+ function CreateElement(tagName) {
+ return document.createElement(tagName);
+ }
+
+ _This.$CreateElement = CreateElement;
+
+ _This.$CreateDiv = function () {
+ return CreateElement("DIV", document);
+ };
+
+ _This.$CreateSpan = function () {
+ return CreateElement("SPAN", document);
+ };
+
+ _This.$EmptyFunction = function () { };
+
+ function Attribute(elmt, name, value) {
+ if (value == undefined)
+ return elmt.getAttribute(name);
+
+ elmt.setAttribute(name, value);
+ }
+
+ function AttributeEx(elmt, name) {
+ return Attribute(elmt, name) || Attribute(elmt, "data-" + name);
+ }
+
+ _This.$Attribute = Attribute;
+ _This.$AttributeEx = AttributeEx;
+
+ function ClassName(elmt, className) {
+ if (className == undefined)
+ return elmt.className;
+
+ elmt.className = className;
+ }
+
+ _This.$ClassName = ClassName;
+
+ function ToHash(array) {
+ var hash = {};
+
+ each(array, function (item) {
+ hash[item] = item;
+ });
+
+ return hash;
+ }
+
+ _This.$ToHash = ToHash;
+
+ function Join(separator, strings) {
+ ///
+ /// The element to show the dialog around
+ ///
+ ///
+ /// The element to show the dialog around
+ ///
+
+ var joined = "";
+
+ each(strings, function (str) {
+ joined && (joined += separator);
+ joined += str;
+ });
+
+ return joined;
+ }
+
+ _This.$Join = Join;
+
+ _This.$AddClass = function (elmt, className) {
+ var newClassName = ClassName(elmt) + " " + className;
+ ClassName(elmt, Join(" ", ToHash(newClassName.match(REGEX_WHITESPACE_GLOBAL))));
+ };
+
+ _This.$RemoveClass = function (elmt, className) {
+ ClassName(elmt, Join(" ", _This.$Unextend(ToHash(ClassName(elmt).match(REGEX_WHITESPACE_GLOBAL)), ToHash(className.match(REGEX_WHITESPACE_GLOBAL)))));
+ };
+
+ _This.$ParentNode = function (elmt) {
+ return elmt.parentNode;
+ };
+
+ _This.$HideElement = function (elmt) {
+ _This.$CssDisplay(elmt, "none");
+ };
+
+ _This.$EnableElement = function (elmt, notEnable) {
+ if (notEnable) {
+ _This.$Attribute(elmt, "disabled", true);
+ }
+ else {
+ _This.$RemoveAttribute(elmt, "disabled");
+ }
+ };
+
+ _This.$HideElements = function (elmts) {
+ for (var i = 0; i < elmts.length; i++) {
+ _This.$HideElement(elmts[i]);
+ }
+ };
+
+ _This.$ShowElement = function (elmt, hide) {
+ _This.$CssDisplay(elmt, hide ? "none" : "");
+ };
+
+ _This.$ShowElements = function (elmts, hide) {
+ for (var i = 0; i < elmts.length; i++) {
+ _This.$ShowElement(elmts[i], hide);
+ }
+ };
+
+ _This.$RemoveAttribute = function (elmt, attrbuteName) {
+ elmt.removeAttribute(attrbuteName);
+ };
+
+ _This.$CanClearClip = function () {
+ return IsBrowserIE() && _BrowserRuntimeVersion < 10;
+ };
+
+ _This.$SetStyleClip = function (elmt, clip) {
+ if (clip) {
+ elmt.style.clip = "rect(" + Math.round(clip.$Top) + "px " + Math.round(clip.$Right) + "px " + Math.round(clip.$Bottom) + "px " + Math.round(clip.$Left) + "px)";
+ }
+ else {
+ var cssText = elmt.style.cssText;
+ var clipRegs = [
+ new RegExp(/[\s]*clip: rect\(.*?\)[;]?/i),
+ new RegExp(/[\s]*cliptop: .*?[;]?/i),
+ new RegExp(/[\s]*clipright: .*?[;]?/i),
+ new RegExp(/[\s]*clipbottom: .*?[;]?/i),
+ new RegExp(/[\s]*clipleft: .*?[;]?/i)
+ ];
+
+ var newCssText = BuildNewCss(cssText, clipRegs, "");
+
+ $Jssor$.$CssCssText(elmt, newCssText);
+ }
+ };
+
+ _This.$GetNow = function () {
+ return new Date().getTime();
+ };
+
+ _This.$AppendChild = function (elmt, child) {
+ elmt.appendChild(child);
+ };
+
+ _This.$AppendChildren = function (elmt, children) {
+ each(children, function (child) {
+ _This.$AppendChild(elmt, child);
+ });
+ };
+
+ _This.$InsertBefore = function (newNode, refNode, pNode) {
+ ///
+ /// Insert a node before a reference node
+ ///
+ ///
+ /// A new node to insert
+ ///
+ ///
+ /// The reference node to insert a new node before
+ ///
+ ///
+ /// The parent node to insert node to
+ ///
+
+ (pNode || refNode.parentNode).insertBefore(newNode, refNode);
+ };
+
+ _This.$InsertAfter = function (newNode, refNode, pNode) {
+ ///
+ /// Insert a node after a reference node
+ ///
+ ///
+ /// A new node to insert
+ ///
+ ///
+ /// The reference node to insert a new node after
+ ///
+ ///
+ /// The parent node to insert node to
+ ///
+
+ _This.$InsertBefore(newNode, refNode.nextSibling, pNode || refNode.parentNode);
+ };
+
+ _This.$InsertAdjacentHtml = function (elmt, where, text) {
+ elmt.insertAdjacentHTML(where, text);
+ };
+
+ _This.$RemoveElement = function (elmt, pNode) {
+ ///
+ /// Remove element from parent node
+ ///
+ ///
+ /// The element to remove
+ ///
+ ///
+ /// The parent node to remove elment from
+ ///
+ (pNode || elmt.parentNode).removeChild(elmt);
+ };
+
+ _This.$RemoveElements = function (elmts, pNode) {
+ each(elmts, function (elmt) {
+ _This.$RemoveElement(elmt, pNode);
+ });
+ };
+
+ _This.$Empty = function (elmt) {
+ _This.$RemoveElements(_This.$Children(elmt, true), elmt);
+ };
+
+ _This.$ParseInt = function (str, radix) {
+ return parseInt(str, radix || 10);
+ };
+
+ var ParseFloat = parseFloat;
+
+ _This.$ParseFloat = ParseFloat;
+
+ _This.$IsChild = function (elmtA, elmtB) {
+ var body = document.body;
+
+ while (elmtB && elmtA !== elmtB && body !== elmtB) {
+ try {
+ elmtB = elmtB.parentNode;
+ } catch (e) {
+ // Firefox sometimes fires events for XUL elements, which throws
+ // a "permission denied" error. so this is not a child.
+ return false;
+ }
+ }
+
+ return elmtA === elmtB;
+ };
+
+ function CloneNode(elmt, noDeep, keepId) {
+ var clone = elmt.cloneNode(!noDeep);
+ if (!keepId) {
+ _This.$RemoveAttribute(clone, "id");
+ }
+
+ return clone;
+ }
+
+ _This.$CloneNode = CloneNode;
+
+ //function TranslateTransition(transition) {
+ // if (transition) {
+ // var flyDirection = transition.$FlyDirection;
+
+ // if (flyDirection & 1) {
+ // transition.x = transition.$ScaleHorizontal || 1;
+ // }
+ // if (flyDirection & 2) {
+ // transition.x = -transition.$ScaleHorizontal || -1;
+ // }
+ // if (flyDirection & 4) {
+ // transition.y = transition.$ScaleVertical || 1;
+ // }
+ // if (flyDirection & 8) {
+ // transition.y = -transition.$ScaleVertical || -1;
+ // }
+
+ // if (transition.$Rotate == true)
+ // transition.$Rotate = 1;
+
+ // TranslateTransition(transition.$Brother);
+ // }
+ //}
+
+ //_This.$TranslateTransitions = function (transitions) {
+ // ///
+ // /// For backward compatibility only.
+ // ///
+ // if (transitions) {
+ // for (var i = 0; i < transitions.length; i++) {
+ // TranslateTransition(transitions[i]);
+ // }
+ // for (var name in transitions) {
+ // TranslateTransition(transitions[name]);
+ // }
+ // }
+ //};
+
+ //function ImageLoader() {
+ // var _ThisImageLoader = this;
+ // var _BaseImageLoader = _This.$Inherit(_ThisImageLoader, $JssorObject$);
+
+ // var _ImageLoading = 1;
+ // var _MainImageSrc;
+ // var _MainImage;
+ // var _CompleteCallback;
+ // var _MainImageAbort;
+
+ // function LoadCompleteCallback(image, abort) {
+ // _ImageLoading--;
+
+ // if (image) {
+ // _This.$RemoveEvent(image, "load");
+ // _This.$RemoveEvent(image, "abort");
+ // _This.$RemoveEvent(image, "error");
+
+ // if (_MainImageSrc == image.src) {
+ // _MainImage = image;
+ // _MainImageAbort = abort;
+ // }
+ // }
+
+ // _CompleteCallback && _CompleteCallback(_MainImage, _MainImageAbort);
+ // }
+
+ // function LoadImage(src) {
+ // _ImageLoading++;
+
+ // if (IsBrowserOpera() && _BrowserRuntimeVersion < 11.6 || !src) {
+ // LoadImageCallback(callback, null, !src);
+ // }
+ // else {
+ // var image = new Image();
+
+ // _This.$AddEvent(image, "load", _This.$CreateCallback(null, LoadImageCallback, image, false));
+
+ // var abortHandler = _This.$CreateCallback(null, LoadImageCallback, image, true);
+ // _This.$AddEvent(image, "abort", abortHandler);
+ // _This.$AddEvent(image, "error", abortHandler);
+
+ // image.src = src;
+ // }
+ // }
+
+ // _ThisImageLoader.$LoadImage = function (src, callback) {
+ // _MainImageSrc = src;
+ // _CompleteCallback = callback;
+
+ // LoadImage(src);
+ // LoadComplete();
+ // };
+
+ // _ThisImageLoader.$LoadImages = function (imageElmts, mainImageElmt, callback) {
+ // mainImageElmt && (_MainImageSrc = mainImageElmt.src);
+ // _CompleteCallback = callback;
+
+ // each(imageElmts, function (imageElmt) {
+ // LoadImage(imageElmt.src);
+ // });
+ // LoadComplete();
+ // };
+ //}
+
+ _This.$LoadImage = function (src, callback) {
+ var image = new Image();
+
+ function LoadImageCompleteHandler(event, abort) {
+ _This.$RemoveEvent(image, "load", LoadImageCompleteHandler);
+ _This.$RemoveEvent(image, "abort", ErrorOrAbortHandler);
+ _This.$RemoveEvent(image, "error", ErrorOrAbortHandler);
+
+ if (callback)
+ callback(image, abort);
+ }
+
+ function ErrorOrAbortHandler(event) {
+ LoadImageCompleteHandler(event, true);
+ }
+
+ if (IsBrowserOpera() && _BrowserRuntimeVersion < 11.6 || !src) {
+ LoadImageCompleteHandler(!src);
+ }
+ else {
+
+ _This.$AddEvent(image, "load", LoadImageCompleteHandler);
+ _This.$AddEvent(image, "abort", ErrorOrAbortHandler);
+ _This.$AddEvent(image, "error", ErrorOrAbortHandler);
+
+ image.src = src;
+ }
+ };
+
+ _This.$LoadImages = function (imageElmts, mainImageElmt, callback) {
+
+ var _ImageLoading = imageElmts.length + 1;
+
+ function LoadImageCompleteEventHandler(image, abort) {
+
+ _ImageLoading--;
+ if (mainImageElmt && image && image.src == mainImageElmt.src)
+ mainImageElmt = image;
+ !_ImageLoading && callback && callback(mainImageElmt);
+ }
+
+ each(imageElmts, function (imageElmt) {
+ _This.$LoadImage(imageElmt.src, LoadImageCompleteEventHandler);
+ });
+
+ LoadImageCompleteEventHandler();
+ };
+
+ _This.$BuildElement = function (template, tagName, replacer, createCopy) {
+ if (createCopy)
+ template = CloneNode(template);
+
+ var templateHolders = FindChildren(template, tagName);
+ if (!templateHolders.length)
+ templateHolders = $Jssor$.$GetElementsByTag(template, tagName);
+
+ for (var j = templateHolders.length - 1; j > -1; j--) {
+ var templateHolder = templateHolders[j];
+ var replaceItem = CloneNode(replacer);
+ ClassName(replaceItem, ClassName(templateHolder));
+ $Jssor$.$CssCssText(replaceItem, templateHolder.style.cssText);
+
+ $Jssor$.$InsertBefore(replaceItem, templateHolder);
+ $Jssor$.$RemoveElement(templateHolder);
+ }
+
+ return template;
+ };
+
+ function JssorButtonEx(elmt) {
+ var _Self = this;
+
+ var _OriginClassName;
+
+ var _IsMouseDown; //class name 'dn'
+ var _IsSelected; //class name 1(active): 'av', 2(passive): 'pv'
+ var _IsDisabled; //class name 'ds'
+
+ function Highlight() {
+ var className = _OriginClassName;
+
+ if (_IsDisabled) {
+ className += 'ds';
+ }
+ else if (_IsMouseDown) {
+ className += 'dn';
+ }
+ else if (_IsSelected == 2) {
+ className += "pv";
+ }
+ else if (_IsSelected) {
+ className += "av";
+ }
+
+ ClassName(elmt, className);
+ }
+
+ function MouseUpOrCancelEventHandler(event) {
+ _IsMouseDown = false;
+
+ Highlight();
+
+ _This.$RemoveEvent(document, Device().$Evt_Up, MouseUpOrCancelEventHandler);
+ Device().$Evt_Cancel && _This.$RemoveEvent(document, Device().$Evt_Cancel, MouseUpOrCancelEventHandler);
+ }
+
+ function MouseDownEventHandler(event) {
+ if (_IsDisabled) {
+ _This.$CancelEvent(event);
+ }
+ else {
+
+ _IsMouseDown = true;
+
+ Highlight();
+
+ _This.$AddEvent(document, Device().$Evt_Up, MouseUpOrCancelEventHandler);
+ Device().$Evt_Cancel && _This.$AddEvent(document, Device().$Evt_Cancel, MouseUpOrCancelEventHandler);
+ }
+ }
+
+ _Self.$Selected = function (activate) {
+ if (activate != undefined) {
+ _IsSelected = activate;
+
+ Highlight();
+ }
+ else {
+ return _IsSelected;
+ }
+ };
+
+ _Self.$Enable = function (enable) {
+ if (enable != undefined) {
+ _IsDisabled = !enable;
+
+ Highlight();
+ }
+ else {
+ return !_IsDisabled;
+ }
+ };
+
+ //JssorButtonEx Constructor
+ {
+ elmt = _This.$GetElement(elmt);
+
+ _OriginClassName = ClassName(elmt);
+
+ $Jssor$.$AddEvent(elmt, Device().$Evt_Down, MouseDownEventHandler);
+ }
+ }
+
+ _This.$Buttonize = function (elmt) {
+ return new JssorButtonEx(elmt);
+ };
+
+ _This.$Css = Css;
+ _This.$CssN = CssN;
+ _This.$CssP = CssP;
+
+ _This.$CssOverflow = CssProxy("overflow");
+
+ _This.$CssTop = CssProxy("top", 2);
+ _This.$CssLeft = CssProxy("left", 2);
+ _This.$CssWidth = CssProxy("width", 2);
+ _This.$CssHeight = CssProxy("height", 2);
+ _This.$CssMarginLeft = CssProxy("marginLeft", 2);
+ _This.$CssMarginTop = CssProxy("marginTop", 2);
+ _This.$CssPosition = CssProxy("position");
+ _This.$CssDisplay = CssProxy("display");
+ _This.$CssZIndex = CssProxy("zIndex", 1);
+ _This.$CssFloat = function (elmt, floatValue) {
+ return Css(elmt, IsBrowserIE() ? "styleFloat" : "cssFloat", floatValue);
+ };
+ _This.$CssOpacity = function (elmt, opacity, ie9EarlierForce) {
+ if (opacity != undefined) {
+ SetStyleOpacity(elmt, opacity, ie9EarlierForce);
+ }
+ else {
+ return GetStyleOpacity(elmt);
+ }
+ };
+
+ _This.$CssCssText = function (elmt, text) {
+ if (text != undefined) {
+ elmt.style.cssText = text;
+ }
+ else {
+ return elmt.style.cssText;
+ }
+ };
+
+ var _StyleGetter = {
+ $Opacity: _This.$CssOpacity,
+ $Top: _This.$CssTop,
+ $Left: _This.$CssLeft,
+ $Width: _This.$CssWidth,
+ $Height: _This.$CssHeight,
+ $Position: _This.$CssPosition,
+ $Display: _This.$CssDisplay,
+ $ZIndex: _This.$CssZIndex
+ };
+
+ var _StyleSetterReserved;
+
+ function StyleSetter() {
+ if (!_StyleSetterReserved) {
+ _StyleSetterReserved = Extend({
+ $MarginTop: _This.$CssMarginTop,
+ $MarginLeft: _This.$CssMarginLeft,
+ $Clip: _This.$SetStyleClip,
+ $Transform: _This.$SetStyleTransform
+ }, _StyleGetter);
+ }
+ return _StyleSetterReserved;
+ }
+
+ function StyleSetterEx() {
+ StyleSetter();
+
+ //For Compression Only
+ _StyleSetterReserved.$Transform = _StyleSetterReserved.$Transform;
+
+ return _StyleSetterReserved;
+ }
+
+ _This.$StyleSetter = StyleSetter;
+
+ _This.$StyleSetterEx = StyleSetterEx;
+
+ _This.$GetStyles = function (elmt, originStyles) {
+ StyleSetter();
+
+ var styles = {};
+
+ each(originStyles, function (value, key) {
+ if (_StyleGetter[key]) {
+ styles[key] = _StyleGetter[key](elmt);
+ }
+ });
+
+ return styles;
+ };
+
+ _This.$SetStyles = function (elmt, styles) {
+ var styleSetter = StyleSetter();
+
+ each(styles, function (value, key) {
+ styleSetter[key] && styleSetter[key](elmt, value);
+ });
+ };
+
+ _This.$SetStylesEx = function (elmt, styles) {
+ StyleSetterEx();
+
+ _This.$SetStyles(elmt, styles);
+ };
+
+ var $JssorMatrix$ = new function () {
+ var _ThisMatrix = this;
+
+ function Multiply(ma, mb) {
+ var acs = ma[0].length;
+ var rows = ma.length;
+ var cols = mb[0].length;
+
+ var matrix = [];
+
+ for (var r = 0; r < rows; r++) {
+ var row = matrix[r] = [];
+ for (var c = 0; c < cols; c++) {
+ var unitValue = 0;
+
+ for (var ac = 0; ac < acs; ac++) {
+ unitValue += ma[r][ac] * mb[ac][c];
+ }
+
+ row[c] = unitValue;
+ }
+ }
+
+ return matrix;
+ }
+
+ _ThisMatrix.$ScaleX = function (matrix, sx) {
+ return _ThisMatrix.$ScaleXY(matrix, sx, 0);
+ };
+
+ _ThisMatrix.$ScaleY = function (matrix, sy) {
+ return _ThisMatrix.$ScaleXY(matrix, 0, sy);
+ };
+
+ _ThisMatrix.$ScaleXY = function (matrix, sx, sy) {
+ return Multiply(matrix, [[sx, 0], [0, sy]]);
+ };
+
+ _ThisMatrix.$TransformPoint = function (matrix, p) {
+ var pMatrix = Multiply(matrix, [[p.x], [p.y]]);
+
+ return Point(pMatrix[0][0], pMatrix[1][0]);
+ };
+ };
+
+ _This.$CreateMatrix = function (alpha, scaleX, scaleY) {
+ var cos = Math.cos(alpha);
+ var sin = Math.sin(alpha);
+ //var r11 = cos;
+ //var r21 = sin;
+ //var r12 = -sin;
+ //var r22 = cos;
+
+ //var m11 = cos * scaleX;
+ //var m12 = -sin * scaleY;
+ //var m21 = sin * scaleX;
+ //var m22 = cos * scaleY;
+
+ return [[cos * scaleX, -sin * scaleY], [sin * scaleX, cos * scaleY]];
+ };
+
+ _This.$GetMatrixOffset = function (matrix, width, height) {
+ var p1 = $JssorMatrix$.$TransformPoint(matrix, Point(-width / 2, -height / 2));
+ var p2 = $JssorMatrix$.$TransformPoint(matrix, Point(width / 2, -height / 2));
+ var p3 = $JssorMatrix$.$TransformPoint(matrix, Point(width / 2, height / 2));
+ var p4 = $JssorMatrix$.$TransformPoint(matrix, Point(-width / 2, height / 2));
+
+ return Point(Math.min(p1.x, p2.x, p3.x, p4.x) + width / 2, Math.min(p1.y, p2.y, p3.y, p4.y) + height / 2);
+ };
+
+ _This.$Cast = function (fromStyles, difStyles, interPosition, easings, durings, rounds, options) {
+
+ var currentStyles = difStyles;
+
+ if (fromStyles) {
+ currentStyles = {};
+
+ for (var key in difStyles) {
+
+ var round = rounds[key] || 1;
+ var during = durings[key] || [0, 1];
+ var propertyInterPosition = (interPosition - during[0]) / during[1];
+ propertyInterPosition = Math.min(Math.max(propertyInterPosition, 0), 1);
+ propertyInterPosition = propertyInterPosition * round;
+ var floorPosition = Math.floor(propertyInterPosition);
+ if (propertyInterPosition != floorPosition)
+ propertyInterPosition -= floorPosition;
+
+ var easing = easings[key] || easings.$Default || $JssorEasing$.$EaseSwing;
+ var easingValue = easing(propertyInterPosition);
+ var currentPropertyValue;
+ var value = fromStyles[key];
+ var toValue = difStyles[key];
+ var difValue = difStyles[key];
+
+ if ($Jssor$.$IsNumeric(difValue)) {
+ currentPropertyValue = value + difValue * easingValue;
+ }
+ else {
+ currentPropertyValue = $Jssor$.$Extend({ $Offset: {} }, fromStyles[key]);
+
+ $Jssor$.$Each(difValue.$Offset, function (rectX, n) {
+ var offsetValue = rectX * easingValue;
+ currentPropertyValue.$Offset[n] = offsetValue;
+ currentPropertyValue[n] += offsetValue;
+ });
+ }
+ currentStyles[key] = currentPropertyValue;
+ }
+
+ if (difStyles.$Zoom || difStyles.$Rotate) {
+ currentStyles.$Transform = { $Rotate: currentStyles.$Rotate || 0, $Scale: currentStyles.$Zoom, $OriginalWidth: options.$OriginalWidth, $OriginalHeight: options.$OriginalHeight };
+ }
+ }
+
+ if (difStyles.$Clip && options.$Move) {
+ var styleFrameNClipOffset = currentStyles.$Clip.$Offset;
+
+ var offsetY = (styleFrameNClipOffset.$Top || 0) + (styleFrameNClipOffset.$Bottom || 0);
+ var offsetX = (styleFrameNClipOffset.$Left || 0) + (styleFrameNClipOffset.$Right || 0);
+
+ currentStyles.$Left = (currentStyles.$Left || 0) + offsetX;
+ currentStyles.$Top = (currentStyles.$Top || 0) + offsetY;
+ currentStyles.$Clip.$Left -= offsetX;
+ currentStyles.$Clip.$Right -= offsetX;
+ currentStyles.$Clip.$Top -= offsetY;
+ currentStyles.$Clip.$Bottom -= offsetY;
+ }
+
+ if (currentStyles.$Clip && $Jssor$.$CanClearClip() && !currentStyles.$Clip.$Top && !currentStyles.$Clip.$Left && (currentStyles.$Clip.$Right == options.$OriginalWidth) && (currentStyles.$Clip.$Bottom == options.$OriginalHeight))
+ currentStyles.$Clip = null;
+
+ return currentStyles;
+ };
+};
+
+//$JssorObject$
+function $JssorObject$() {
+ var _ThisObject = this;
+ // Fields
+
+ var _Listeners = []; // dictionary of eventName --> array of handlers
+ var _Listenees = [];
+
+ // Private Methods
+ function AddListener(eventName, handler) {
+
+ $JssorDebug$.$Execute(function () {
+ if (eventName == undefined || eventName == null)
+ throw new Error("param 'eventName' is null or empty.");
+
+ if (typeof (handler) != "function") {
+ throw "param 'handler' must be a function.";
+ }
+
+ $Jssor$.$Each(_Listeners, function (listener) {
+ if (listener.$EventName == eventName && listener.$Handler === handler) {
+ throw new Error("The handler listened to the event already, cannot listen to the same event of the same object with the same handler twice.");
+ }
+ });
+ });
+
+ _Listeners.push({ $EventName: eventName, $Handler: handler });
+ }
+
+ function RemoveListener(eventName, handler) {
+
+ $JssorDebug$.$Execute(function () {
+ if (eventName == undefined || eventName == null)
+ throw new Error("param 'eventName' is null or empty.");
+
+ if (typeof (handler) != "function") {
+ throw "param 'handler' must be a function.";
+ }
+ });
+
+ $Jssor$.$Each(_Listeners, function (listener, index) {
+ if (listener.$EventName == eventName && listener.$Handler === handler) {
+ _Listeners.splice(index, 1);
+ }
+ });
+ }
+
+ function ClearListeners() {
+ _Listeners = [];
+ }
+
+ function ClearListenees() {
+
+ $Jssor$.$Each(_Listenees, function (listenee) {
+ $Jssor$.$RemoveEvent(listenee.$Obj, listenee.$EventName, listenee.$Handler);
+ });
+
+ _Listenees = [];
+ }
+
+ //Protected Methods
+ _ThisObject.$Listen = function (obj, eventName, handler, useCapture) {
+
+ $JssorDebug$.$Execute(function () {
+ if (!obj)
+ throw new Error("param 'obj' is null or empty.");
+
+ if (eventName == undefined || eventName == null)
+ throw new Error("param 'eventName' is null or empty.");
+
+ if (typeof (handler) != "function") {
+ throw "param 'handler' must be a function.";
+ }
+
+ $Jssor$.$Each(_Listenees, function (listenee) {
+ if (listenee.$Obj === obj && listenee.$EventName == eventName && listenee.$Handler === handler) {
+ throw new Error("The handler listened to the event already, cannot listen to the same event of the same object with the same handler twice.");
+ }
+ });
+ });
+
+ $Jssor$.$AddEvent(obj, eventName, handler, useCapture);
+ _Listenees.push({ $Obj: obj, $EventName: eventName, $Handler: handler });
+ };
+
+ _ThisObject.$Unlisten = function (obj, eventName, handler) {
+
+ $JssorDebug$.$Execute(function () {
+ if (!obj)
+ throw new Error("param 'obj' is null or empty.");
+
+ if (eventName == undefined || eventName == null)
+ throw new Error("param 'eventName' is null or empty.");
+
+ if (typeof (handler) != "function") {
+ throw "param 'handler' must be a function.";
+ }
+ });
+
+ $Jssor$.$Each(_Listenees, function (listenee, index) {
+ if (listenee.$Obj === obj && listenee.$EventName == eventName && listenee.$Handler === handler) {
+ $Jssor$.$RemoveEvent(obj, eventName, handler);
+ _Listenees.splice(index, 1);
+ }
+ });
+ };
+
+ _ThisObject.$UnlistenAll = ClearListenees;
+
+ // Public Methods
+ _ThisObject.$On = _ThisObject.addEventListener = AddListener;
+
+ _ThisObject.$Off = _ThisObject.removeEventListener = RemoveListener;
+
+ _ThisObject.$TriggerEvent = function (eventName) {
+
+ var args = [].slice.call(arguments, 1);
+
+ $Jssor$.$Each(_Listeners, function (listener) {
+ listener.$EventName == eventName && listener.$Handler.apply(window, args);
+ });
+ };
+
+ _ThisObject.$Destroy = function () {
+ ClearListenees();
+ ClearListeners();
+
+ for (var name in _ThisObject)
+ delete _ThisObject[name];
+ };
+
+ $JssorDebug$.$C_AbstractClass(_ThisObject);
+};
+
+function $JssorAnimator$(delay, duration, options, elmt, fromStyles, difStyles) {
+ delay = delay || 0;
+
+ var _ThisAnimator = this;
+ var _AutoPlay;
+ var _Hiden;
+ var _CombineMode;
+ var _PlayToPosition;
+ var _PlayDirection;
+ var _NoStop;
+ var _TimeStampLastFrame = 0;
+
+ var _SubEasings;
+ var _SubRounds;
+ var _SubDurings;
+ var _Callback;
+
+ var _Shift = 0;
+ var _Position_Current = 0;
+ var _Position_Display = 0;
+ var _Hooked;
+
+ var _Position_InnerBegin = delay;
+ var _Position_InnerEnd = delay + duration;
+ var _Position_OuterBegin;
+ var _Position_OuterEnd;
+ var _LoopLength;
+
+ var _NestedAnimators = [];
+ var _StyleSetter;
+
+ function GetPositionRange(position, begin, end) {
+ var range = 0;
+
+ if (position < begin)
+ range = -1;
+
+ else if (position > end)
+ range = 1;
+
+ return range;
+ }
+
+ function GetInnerPositionRange(position) {
+ return GetPositionRange(position, _Position_InnerBegin, _Position_InnerEnd);
+ }
+
+ function GetOuterPositionRange(position) {
+ return GetPositionRange(position, _Position_OuterBegin, _Position_OuterEnd);
+ }
+
+ function Shift(offset) {
+ _Position_OuterBegin += offset;
+ _Position_OuterEnd += offset;
+ _Position_InnerBegin += offset;
+ _Position_InnerEnd += offset;
+
+ _Position_Current += offset;
+ _Position_Display += offset;
+
+ _Shift = offset;
+ }
+
+ function Locate(position, relative) {
+ var offset = position - _Position_OuterBegin + delay * relative;
+
+ Shift(offset);
+
+ //$JssorDebug$.$Execute(function () {
+ // _ThisAnimator.$Position_InnerBegin = _Position_InnerBegin;
+ // _ThisAnimator.$Position_InnerEnd = _Position_InnerEnd;
+ // _ThisAnimator.$Position_OuterBegin = _Position_OuterBegin;
+ // _ThisAnimator.$Position_OuterEnd = _Position_OuterEnd;
+ //});
+
+ return _Position_OuterEnd;
+ }
+
+ function GoToPosition(positionOuter, force) {
+ var trimedPositionOuter = positionOuter;
+
+ if (_LoopLength && (trimedPositionOuter >= _Position_OuterEnd || trimedPositionOuter <= _Position_OuterBegin)) {
+ trimedPositionOuter = ((trimedPositionOuter - _Position_OuterBegin) % _LoopLength + _LoopLength) % _LoopLength + _Position_OuterBegin;
+ }
+
+ if (!_Hooked || _NoStop || force || _Position_Current != trimedPositionOuter) {
+
+ var positionToDisplay = Math.min(trimedPositionOuter, _Position_OuterEnd);
+ positionToDisplay = Math.max(positionToDisplay, _Position_OuterBegin);
+
+ if (!_Hooked || _NoStop || force || positionToDisplay != _Position_Display) {
+ if (difStyles) {
+
+ var interPosition = (positionToDisplay - _Position_InnerBegin) / (duration || 1);
+
+ if (options.$Reverse)
+ interPosition = 1 - interPosition;
+
+ var currentStyles = $Jssor$.$Cast(fromStyles, difStyles, interPosition, _SubEasings, _SubDurings, _SubRounds, options);
+
+ $Jssor$.$Each(currentStyles, function (value, key) {
+ _StyleSetter[key] && _StyleSetter[key](elmt, value);
+ });
+ }
+
+ _ThisAnimator.$OnInnerOffsetChange(_Position_Display - _Position_InnerBegin, positionToDisplay - _Position_InnerBegin);
+ }
+
+ _Position_Display = positionToDisplay;
+
+ $Jssor$.$Each(_NestedAnimators, function (animator, i) {
+ var nestedAnimator = positionOuter < _Position_Current ? _NestedAnimators[_NestedAnimators.length - i - 1] : animator;
+ nestedAnimator.$GoToPosition(positionOuter - _Shift, force);
+ });
+
+ var positionOld = _Position_Current;
+ var positionNew = positionOuter;
+
+ _Position_Current = trimedPositionOuter;
+ _Hooked = true;
+
+ _ThisAnimator.$OnPositionChange(positionOld, positionNew);
+ }
+ }
+
+ function Join(animator, combineMode, noExpand) {
+ ///
+ /// Combine another animator as nested animator
+ ///
+ ///
+ /// An instance of $JssorAnimator$
+ ///
+ ///
+ /// 0: parallel - place the animator parallel to this animator.
+ /// 1: chain - chain the animator at the _Position_InnerEnd of this animator.
+ ///
+ $JssorDebug$.$Execute(function () {
+ if (combineMode !== 0 && combineMode !== 1)
+ $JssorDebug$.$Fail("Argument out of range, the value of 'combineMode' should be either 0 or 1.");
+ });
+
+ if (combineMode)
+ animator.$Locate(_Position_OuterEnd, 1);
+
+ !noExpand && (_Position_OuterEnd = Math.max(_Position_OuterEnd, animator.$GetPosition_OuterEnd() + _Shift));
+ _NestedAnimators.push(animator);
+ }
+
+ var RequestAnimationFrame = window.requestAnimationFrame
+ || window.webkitRequestAnimationFrame
+ || window.mozRequestAnimationFrame
+ || window.msRequestAnimationFrame;
+
+ if ($Jssor$.$IsBrowserSafari() && $Jssor$.$BrowserVersion() < 7) {
+ RequestAnimationFrame = null;
+
+ $JssorDebug$.$Log("Custom animation frame for safari before 7.");
+ }
+
+ RequestAnimationFrame = RequestAnimationFrame || function (callback) {
+ $Jssor$.$Delay(callback, options.$Interval);
+ };
+
+ function ShowFrame() {
+ if (_AutoPlay) {
+ var now = $Jssor$.$GetNow();
+ var timeOffset = Math.min(now - _TimeStampLastFrame, options.$IntervalMax);
+ var timePosition = _Position_Current + timeOffset * _PlayDirection;
+ _TimeStampLastFrame = now;
+
+ if (timePosition * _PlayDirection >= _PlayToPosition * _PlayDirection)
+ timePosition = _PlayToPosition;
+
+ GoToPosition(timePosition);
+
+ if (!_NoStop && timePosition * _PlayDirection >= _PlayToPosition * _PlayDirection) {
+ Stop(_Callback);
+ }
+ else {
+ RequestAnimationFrame(ShowFrame);
+ }
+ }
+ }
+
+ function PlayToPosition(toPosition, callback, noStop) {
+ if (!_AutoPlay) {
+ _AutoPlay = true;
+ _NoStop = noStop
+ _Callback = callback;
+ toPosition = Math.max(toPosition, _Position_OuterBegin);
+ toPosition = Math.min(toPosition, _Position_OuterEnd);
+ _PlayToPosition = toPosition;
+ _PlayDirection = _PlayToPosition < _Position_Current ? -1 : 1;
+ _ThisAnimator.$OnStart();
+ _TimeStampLastFrame = $Jssor$.$GetNow();
+ RequestAnimationFrame(ShowFrame);
+ }
+ }
+
+ function Stop(callback) {
+ if (_AutoPlay) {
+ _NoStop = _AutoPlay = _Callback = false;
+ _ThisAnimator.$OnStop();
+
+ if (callback)
+ callback();
+ }
+ }
+
+ _ThisAnimator.$Play = function (positionLength, callback, noStop) {
+ PlayToPosition(positionLength ? _Position_Current + positionLength : _Position_OuterEnd, callback, noStop);
+ };
+
+ _ThisAnimator.$PlayToPosition = PlayToPosition;
+
+ _ThisAnimator.$PlayToBegin = function (callback, noStop) {
+ PlayToPosition(_Position_OuterBegin, callback, noStop);
+ };
+
+ _ThisAnimator.$PlayToEnd = function (callback, noStop) {
+ PlayToPosition(_Position_OuterEnd, callback, noStop);
+ };
+
+ _ThisAnimator.$Stop = Stop;
+
+ _ThisAnimator.$Continue = function (toPosition) {
+ PlayToPosition(toPosition);
+ };
+
+ _ThisAnimator.$GetPosition = function () {
+ return _Position_Current;
+ };
+
+ _ThisAnimator.$GetPlayToPosition = function () {
+ return _PlayToPosition;
+ };
+
+ _ThisAnimator.$GetPosition_Display = function () {
+ return _Position_Display;
+ };
+
+ _ThisAnimator.$GoToPosition = GoToPosition;
+
+ _ThisAnimator.$GoToBegin = function () {
+ GoToPosition(_Position_OuterBegin, true);
+ };
+
+ _ThisAnimator.$GoToEnd = function () {
+ GoToPosition(_Position_OuterEnd, true);
+ };
+
+ _ThisAnimator.$Move = function (offset) {
+ GoToPosition(_Position_Current + offset);
+ };
+
+ _ThisAnimator.$CombineMode = function () {
+ return _CombineMode;
+ };
+
+ _ThisAnimator.$GetDuration = function () {
+ return duration;
+ };
+
+ _ThisAnimator.$IsPlaying = function () {
+ return _AutoPlay;
+ };
+
+ _ThisAnimator.$IsOnTheWay = function () {
+ return _Position_Current > _Position_InnerBegin && _Position_Current <= _Position_InnerEnd;
+ };
+
+ _ThisAnimator.$SetLoopLength = function (length) {
+ _LoopLength = length;
+ };
+
+ _ThisAnimator.$Locate = Locate;
+
+ _ThisAnimator.$Shift = Shift;
+
+ _ThisAnimator.$Join = Join;
+
+ _ThisAnimator.$Combine = function (animator) {
+ ///
+ /// Combine another animator parallel to this animator
+ ///
+ ///
+ /// An instance of $JssorAnimator$
+ ///
+ Join(animator, 0);
+ };
+
+ _ThisAnimator.$Chain = function (animator) {
+ ///
+ /// Chain another animator at the _Position_InnerEnd of this animator
+ ///
+ ///
+ /// An instance of $JssorAnimator$
+ ///
+ Join(animator, 1);
+ };
+
+ _ThisAnimator.$GetPosition_InnerBegin = function () {
+ ///
+ /// Internal member function, do not use it.
+ ///
+ ///
+ ///
+ return _Position_InnerBegin;
+ };
+
+ _ThisAnimator.$GetPosition_InnerEnd = function () {
+ ///
+ /// Internal member function, do not use it.
+ ///
+ ///
+ ///
+ return _Position_InnerEnd;
+ };
+
+ _ThisAnimator.$GetPosition_OuterBegin = function () {
+ ///
+ /// Internal member function, do not use it.
+ ///
+ ///
+ ///
+ return _Position_OuterBegin;
+ };
+
+ _ThisAnimator.$GetPosition_OuterEnd = function () {
+ ///
+ /// Internal member function, do not use it.
+ ///
+ ///
+ ///
+ return _Position_OuterEnd;
+ };
+
+ _ThisAnimator.$OnPositionChange = _ThisAnimator.$OnStart = _ThisAnimator.$OnStop = _ThisAnimator.$OnInnerOffsetChange = $Jssor$.$EmptyFunction;
+ _ThisAnimator.$Version = $Jssor$.$GetNow();
+
+ //Constructor 1
+ {
+ options = $Jssor$.$Extend({
+ $Interval: 16,
+ $IntervalMax: 50
+ }, options);
+
+ //Sodo statement, for development time intellisence only
+ $JssorDebug$.$Execute(function () {
+ options = $Jssor$.$Extend({
+ $LoopLength: undefined,
+ $Setter: undefined,
+ $Easing: undefined
+ }, options);
+ });
+
+ _LoopLength = options.$LoopLength;
+
+ _StyleSetter = $Jssor$.$Extend({}, $Jssor$.$StyleSetter(), options.$Setter);
+
+ _Position_OuterBegin = _Position_InnerBegin = delay;
+ _Position_OuterEnd = _Position_InnerEnd = delay + duration;
+
+ _SubRounds = options.$Round || {};
+ _SubDurings = options.$During || {};
+ _SubEasings = $Jssor$.$Extend({ $Default: $Jssor$.$IsFunction(options.$Easing) && options.$Easing || $JssorEasing$.$EaseSwing }, options.$Easing);
+ }
+};
+
+function $JssorPlayerClass$() {
+
+ var _ThisPlayer = this;
+ var _PlayerControllers = [];
+
+ function PlayerController(playerElement) {
+ var _SelfPlayerController = this;
+ var _PlayerInstance;
+ var _PlayerInstantces = [];
+
+ function OnPlayerInstanceDataAvailable(event) {
+ var srcElement = $Jssor$.$EventSrc(event);
+ _PlayerInstance = srcElement.pInstance;
+
+ $Jssor$.$RemoveEvent(srcElement, "dataavailable", OnPlayerInstanceDataAvailable);
+ $Jssor$.$Each(_PlayerInstantces, function (playerInstance) {
+ if (playerInstance != _PlayerInstance) {
+ playerInstance.$Remove();
+ }
+ });
+
+ playerElement.pTagName = _PlayerInstance.tagName;
+ _PlayerInstantces = null;
+ }
+
+ function HandlePlayerInstance(playerInstanceElement) {
+ var playerHandler;
+
+ if (!playerInstanceElement.pInstance) {
+ var playerHandlerAttribute = $Jssor$.$AttributeEx(playerInstanceElement, "pHandler");
+
+ if ($JssorPlayer$[playerHandlerAttribute]) {
+ $Jssor$.$AddEvent(playerInstanceElement, "dataavailable", OnPlayerInstanceDataAvailable);
+ playerHandler = new $JssorPlayer$[playerHandlerAttribute](playerElement, playerInstanceElement);
+ _PlayerInstantces.push(playerHandler);
+
+ $JssorDebug$.$Execute(function () {
+ if ($Jssor$.$Type(playerHandler.$Remove) != "function") {
+ $JssorDebug$.$Fail("'pRemove' interface not implemented for player handler '" + playerHandlerAttribute + "'.");
+ }
+ });
+ }
+ }
+
+ return playerHandler;
+ }
+
+ _SelfPlayerController.$InitPlayerController = function () {
+ if (!playerElement.pInstance && !HandlePlayerInstance(playerElement)) {
+
+ var playerInstanceElements = $Jssor$.$Children(playerElement);
+
+ $Jssor$.$Each(playerInstanceElements, function (playerInstanceElement) {
+ HandlePlayerInstance(playerInstanceElement);
+ });
+ }
+ };
+ }
+
+ _ThisPlayer.$EVT_SWITCH = 21;
+
+ _ThisPlayer.$FetchPlayers = function (elmt) {
+ elmt = elmt || document.body;
+
+ var playerElements = $Jssor$.$FindChildren(elmt, "player");
+
+ $Jssor$.$Each(playerElements, function (playerElement) {
+ if (!_PlayerControllers[playerElement.pId]) {
+ playerElement.pId = _PlayerControllers.length;
+ _PlayerControllers.push(new PlayerController(playerElement));
+ }
+ var playerController = _PlayerControllers[playerElement.pId];
+ playerController.$InitPlayerController();
+ });
+ };
+}
\ No newline at end of file
diff --git a/spree_theme/app/assets/javascripts/jssor.19/jssor.slider.js b/spree_theme/app/assets/javascripts/jssor.19/jssor.slider.js
new file mode 100644
index 00000000..44f668a4
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/jssor.19/jssor.slider.js
@@ -0,0 +1,4169 @@
+///
+
+/*
+* Jssor.Slider 19.0
+* http://www.jssor.com/
+*
+* Licensed under the MIT license:
+* http://www.opensource.org/licenses/MIT
+*
+* TERMS OF USE - Jssor.Slider
+*
+* Copyright 2014 Jssor
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+var $JssorSlideshowFormations$ = window.$JssorSlideshowFormations$ = new function () {
+ var _This = this;
+
+ //Constants +++++++
+
+ var COLUMN_INCREASE = 0;
+ var COLUMN_DECREASE = 1;
+ var ROW_INCREASE = 2;
+ var ROW_DECREASE = 3;
+
+ var DIRECTION_HORIZONTAL = 0x0003;
+ var DIRECTION_VERTICAL = 0x000C;
+
+ var TO_LEFT = 0x0001;
+ var TO_RIGHT = 0x0002;
+ var TO_TOP = 0x0004;
+ var TO_BOTTOM = 0x0008;
+
+ var FROM_LEFT = 0x0100;
+ var FROM_TOP = 0x0200;
+ var FROM_RIGHT = 0x0400;
+ var FROM_BOTTOM = 0x0800;
+
+ var ASSEMBLY_BOTTOM_LEFT = FROM_BOTTOM + TO_LEFT;
+ var ASSEMBLY_BOTTOM_RIGHT = FROM_BOTTOM + TO_RIGHT;
+ var ASSEMBLY_TOP_LEFT = FROM_TOP + TO_LEFT;
+ var ASSEMBLY_TOP_RIGHT = FROM_TOP + TO_RIGHT;
+ var ASSEMBLY_LEFT_TOP = FROM_LEFT + TO_TOP;
+ var ASSEMBLY_LEFT_BOTTOM = FROM_LEFT + TO_BOTTOM;
+ var ASSEMBLY_RIGHT_TOP = FROM_RIGHT + TO_TOP;
+ var ASSEMBLY_RIGHT_BOTTOM = FROM_RIGHT + TO_BOTTOM;
+
+ //Constants -------
+
+ //Formation Definition +++++++
+ function isToLeft(roadValue) {
+ return (roadValue & TO_LEFT) == TO_LEFT;
+ }
+
+ function isToRight(roadValue) {
+ return (roadValue & TO_RIGHT) == TO_RIGHT;
+ }
+
+ function isToTop(roadValue) {
+ return (roadValue & TO_TOP) == TO_TOP;
+ }
+
+ function isToBottom(roadValue) {
+ return (roadValue & TO_BOTTOM) == TO_BOTTOM;
+ }
+
+ function PushFormationOrder(arr, order, formationItem) {
+ formationItem.push(order);
+ arr[order] = arr[order] || [];
+ arr[order].push(formationItem);
+ }
+
+ _This.$FormationStraight = function (transition) {
+ var cols = transition.$Cols;
+ var rows = transition.$Rows;
+ var formationDirection = transition.$Assembly;
+ var count = transition.$Count;
+ var a = [];
+ var i = 0;
+ var col = 0;
+ var r = 0;
+ var cl = cols - 1;
+ var rl = rows - 1;
+ var il = count - 1;
+ var cr;
+ var order;
+ for (r = 0; r < rows; r++) {
+ for (col = 0; col < cols; col++) {
+ cr = r + ',' + col;
+ switch (formationDirection) {
+ case ASSEMBLY_BOTTOM_LEFT:
+ order = il - (col * rows + (rl - r));
+ break;
+ case ASSEMBLY_RIGHT_TOP:
+ order = il - (r * cols + (cl - col));
+ break;
+ case ASSEMBLY_TOP_LEFT:
+ order = il - (col * rows + r);
+ case ASSEMBLY_LEFT_TOP:
+ order = il - (r * cols + col);
+ break;
+ case ASSEMBLY_BOTTOM_RIGHT:
+ order = col * rows + r;
+ break;
+ case ASSEMBLY_LEFT_BOTTOM:
+ order = r * cols + (cl - col);
+ break;
+ case ASSEMBLY_TOP_RIGHT:
+ order = col * rows + (rl - r);
+ break;
+ default:
+ order = r * cols + col;
+ break; //ASSEMBLY_RIGHT_BOTTOM
+ }
+ PushFormationOrder(a, order, [r, col]);
+ }
+ }
+
+ return a;
+ };
+
+ _This.$FormationSwirl = function (transition) {
+ var cols = transition.$Cols;
+ var rows = transition.$Rows;
+ var formationDirection = transition.$Assembly;
+ var count = transition.$Count;
+ var a = [];
+ var hit = [];
+ var i = 0;
+ var col = 0;
+ var r = 0;
+ var cl = cols - 1;
+ var rl = rows - 1;
+ var il = count - 1;
+ var cr;
+ var courses;
+ var course = 0;
+ switch (formationDirection) {
+ case ASSEMBLY_BOTTOM_LEFT:
+ col = cl;
+ r = 0;
+ courses = [ROW_INCREASE, COLUMN_DECREASE, ROW_DECREASE, COLUMN_INCREASE];
+ break;
+ case ASSEMBLY_RIGHT_TOP:
+ col = 0;
+ r = rl;
+ courses = [COLUMN_INCREASE, ROW_DECREASE, COLUMN_DECREASE, ROW_INCREASE];
+ break;
+ case ASSEMBLY_TOP_LEFT:
+ col = cl;
+ r = rl;
+ courses = [ROW_DECREASE, COLUMN_DECREASE, ROW_INCREASE, COLUMN_INCREASE];
+ break;
+ case ASSEMBLY_LEFT_TOP:
+ col = cl;
+ r = rl;
+ courses = [COLUMN_DECREASE, ROW_DECREASE, COLUMN_INCREASE, ROW_INCREASE];
+ break;
+ case ASSEMBLY_BOTTOM_RIGHT:
+ col = 0;
+ r = 0;
+ courses = [ROW_INCREASE, COLUMN_INCREASE, ROW_DECREASE, COLUMN_DECREASE];
+ break;
+ case ASSEMBLY_LEFT_BOTTOM:
+ col = cl;
+ r = 0;
+ courses = [COLUMN_DECREASE, ROW_INCREASE, COLUMN_INCREASE, ROW_DECREASE];
+ break;
+ case ASSEMBLY_TOP_RIGHT:
+ col = 0;
+ r = rl;
+ courses = [ROW_DECREASE, COLUMN_INCREASE, ROW_INCREASE, COLUMN_DECREASE];
+ break;
+ default:
+ col = 0;
+ r = 0;
+ courses = [COLUMN_INCREASE, ROW_INCREASE, COLUMN_DECREASE, ROW_DECREASE];
+ break; //ASSEMBLY_RIGHT_BOTTOM
+ }
+ i = 0;
+ while (i < count) {
+ cr = r + ',' + col;
+ if (col >= 0 && col < cols && r >= 0 && r < rows && !hit[cr]) {
+ //a[cr] = i++;
+ hit[cr] = true;
+ PushFormationOrder(a, i++, [r, col]);
+ }
+ else {
+ switch (courses[course++ % courses.length]) {
+ case COLUMN_INCREASE:
+ col--;
+ break;
+ case ROW_INCREASE:
+ r--;
+ break;
+ case COLUMN_DECREASE:
+ col++;
+ break;
+ case ROW_DECREASE:
+ r++;
+ break;
+ }
+ }
+
+ switch (courses[course % courses.length]) {
+ case COLUMN_INCREASE:
+ col++;
+ break;
+ case ROW_INCREASE:
+ r++;
+ break;
+ case COLUMN_DECREASE:
+ col--;
+ break;
+ case ROW_DECREASE:
+ r--;
+ break;
+ }
+ }
+ return a;
+ };
+
+ _This.$FormationZigZag = function (transition) {
+ var cols = transition.$Cols;
+ var rows = transition.$Rows;
+ var formationDirection = transition.$Assembly;
+ var count = transition.$Count;
+ var a = [];
+ var i = 0;
+ var col = 0;
+ var r = 0;
+ var cl = cols - 1;
+ var rl = rows - 1;
+ var il = count - 1;
+ var cr;
+ var courses;
+ var course = 0;
+ switch (formationDirection) {
+ case ASSEMBLY_BOTTOM_LEFT:
+ col = cl;
+ r = 0;
+ courses = [ROW_INCREASE, COLUMN_DECREASE, ROW_DECREASE, COLUMN_DECREASE];
+ break;
+ case ASSEMBLY_RIGHT_TOP:
+ col = 0;
+ r = rl;
+ courses = [COLUMN_INCREASE, ROW_DECREASE, COLUMN_DECREASE, ROW_DECREASE];
+ break;
+ case ASSEMBLY_TOP_LEFT:
+ col = cl;
+ r = rl;
+ courses = [ROW_DECREASE, COLUMN_DECREASE, ROW_INCREASE, COLUMN_DECREASE];
+ break;
+ case ASSEMBLY_LEFT_TOP:
+ col = cl;
+ r = rl;
+ courses = [COLUMN_DECREASE, ROW_DECREASE, COLUMN_INCREASE, ROW_DECREASE];
+ break;
+ case ASSEMBLY_BOTTOM_RIGHT:
+ col = 0;
+ r = 0;
+ courses = [ROW_INCREASE, COLUMN_INCREASE, ROW_DECREASE, COLUMN_INCREASE];
+ break;
+ case ASSEMBLY_LEFT_BOTTOM:
+ col = cl;
+ r = 0;
+ courses = [COLUMN_DECREASE, ROW_INCREASE, COLUMN_INCREASE, ROW_INCREASE];
+ break;
+ case ASSEMBLY_TOP_RIGHT:
+ col = 0;
+ r = rl;
+ courses = [ROW_DECREASE, COLUMN_INCREASE, ROW_INCREASE, COLUMN_INCREASE];
+ break;
+ default:
+ col = 0;
+ r = 0;
+ courses = [COLUMN_INCREASE, ROW_INCREASE, COLUMN_DECREASE, ROW_INCREASE];
+ break; //ASSEMBLY_RIGHT_BOTTOM
+ }
+ i = 0;
+ while (i < count) {
+ cr = r + ',' + col;
+ if (col >= 0 && col < cols && r >= 0 && r < rows && typeof (a[cr]) == 'undefined') {
+ PushFormationOrder(a, i++, [r, col]);
+ //a[cr] = i++;
+ switch (courses[course % courses.length]) {
+ case COLUMN_INCREASE:
+ col++;
+ break;
+ case ROW_INCREASE:
+ r++;
+ break;
+ case COLUMN_DECREASE:
+ col--;
+ break;
+ case ROW_DECREASE:
+ r--;
+ break;
+ }
+ }
+ else {
+ switch (courses[course++ % courses.length]) {
+ case COLUMN_INCREASE:
+ col--;
+ break;
+ case ROW_INCREASE:
+ r--;
+ break;
+ case COLUMN_DECREASE:
+ col++;
+ break;
+ case ROW_DECREASE:
+ r++;
+ break;
+ }
+ switch (courses[course++ % courses.length]) {
+ case COLUMN_INCREASE:
+ col++;
+ break;
+ case ROW_INCREASE:
+ r++;
+ break;
+ case COLUMN_DECREASE:
+ col--;
+ break;
+ case ROW_DECREASE:
+ r--;
+ break;
+ }
+ }
+ }
+ return a;
+ };
+
+ _This.$FormationStraightStairs = function (transition) {
+ var cols = transition.$Cols;
+ var rows = transition.$Rows;
+ var formationDirection = transition.$Assembly;
+ var count = transition.$Count;
+ var a = [];
+ var i = 0;
+ var col = 0;
+ var r = 0;
+ var cl = cols - 1;
+ var rl = rows - 1;
+ var il = count - 1;
+ var cr;
+ switch (formationDirection) {
+ case ASSEMBLY_BOTTOM_LEFT:
+ case ASSEMBLY_TOP_RIGHT:
+ case ASSEMBLY_TOP_LEFT:
+ case ASSEMBLY_BOTTOM_RIGHT:
+ var C = 0;
+ var R = 0;
+ break;
+ case ASSEMBLY_LEFT_BOTTOM:
+ case ASSEMBLY_RIGHT_TOP:
+ case ASSEMBLY_LEFT_TOP:
+ case ASSEMBLY_RIGHT_BOTTOM:
+ var C = cl;
+ var R = 0;
+ break;
+ default:
+ formationDirection = ASSEMBLY_RIGHT_BOTTOM;
+ var C = cl;
+ var R = 0;
+ break;
+ }
+ col = C;
+ r = R;
+ while (i < count) {
+ cr = r + ',' + col;
+ if (isToTop(formationDirection) || isToRight(formationDirection)) {
+ PushFormationOrder(a, il - i++, [r, col]);
+ //a[cr] = il - i++;
+ }
+ else {
+ PushFormationOrder(a, i++, [r, col]);
+ //a[cr] = i++;
+ }
+ switch (formationDirection) {
+ case ASSEMBLY_BOTTOM_LEFT:
+ case ASSEMBLY_TOP_RIGHT:
+ col--;
+ r++;
+ break;
+ case ASSEMBLY_TOP_LEFT:
+ case ASSEMBLY_BOTTOM_RIGHT:
+ col++;
+ r--;
+ break;
+ case ASSEMBLY_LEFT_BOTTOM:
+ case ASSEMBLY_RIGHT_TOP:
+ col--;
+ r--;
+ break;
+ case ASSEMBLY_RIGHT_BOTTOM:
+ case ASSEMBLY_LEFT_TOP:
+ default:
+ col++;
+ r++;
+ break;
+ }
+ if (col < 0 || r < 0 || col > cl || r > rl) {
+ switch (formationDirection) {
+ case ASSEMBLY_BOTTOM_LEFT:
+ case ASSEMBLY_TOP_RIGHT:
+ C++;
+ break;
+ case ASSEMBLY_LEFT_BOTTOM:
+ case ASSEMBLY_RIGHT_TOP:
+ case ASSEMBLY_TOP_LEFT:
+ case ASSEMBLY_BOTTOM_RIGHT:
+ R++;
+ break;
+ case ASSEMBLY_RIGHT_BOTTOM:
+ case ASSEMBLY_LEFT_TOP:
+ default:
+ C--;
+ break;
+ }
+ if (C < 0 || R < 0 || C > cl || R > rl) {
+ switch (formationDirection) {
+ case ASSEMBLY_BOTTOM_LEFT:
+ case ASSEMBLY_TOP_RIGHT:
+ C = cl;
+ R++;
+ break;
+ case ASSEMBLY_TOP_LEFT:
+ case ASSEMBLY_BOTTOM_RIGHT:
+ R = rl;
+ C++;
+ break;
+ case ASSEMBLY_LEFT_BOTTOM:
+ case ASSEMBLY_RIGHT_TOP: R = rl; C--;
+ break;
+ case ASSEMBLY_RIGHT_BOTTOM:
+ case ASSEMBLY_LEFT_TOP:
+ default:
+ C = 0;
+ R++;
+ break;
+ }
+ if (R > rl)
+ R = rl;
+ else if (R < 0)
+ R = 0;
+ else if (C > cl)
+ C = cl;
+ else if (C < 0)
+ C = 0;
+ }
+ r = R;
+ col = C;
+ }
+ }
+ return a;
+ };
+
+ _This.$FormationSquare = function (transition) {
+ var cols = transition.$Cols || 1;
+ var rows = transition.$Rows || 1;
+ var arr = [];
+ var i = 0;
+ var col;
+ var r;
+ var dc;
+ var dr;
+ var cr;
+ dc = cols < rows ? (rows - cols) / 2 : 0;
+ dr = cols > rows ? (cols - rows) / 2 : 0;
+ cr = Math.round(Math.max(cols / 2, rows / 2)) + 1;
+ for (col = 0; col < cols; col++) {
+ for (r = 0; r < rows; r++)
+ PushFormationOrder(arr, cr - Math.min(col + 1 + dc, r + 1 + dr, cols - col + dc, rows - r + dr), [r, col]);
+ }
+ return arr;
+ };
+
+ _This.$FormationRectangle = function (transition) {
+ var cols = transition.$Cols || 1;
+ var rows = transition.$Rows || 1;
+ var arr = [];
+ var i = 0;
+ var col;
+ var r;
+ var cr;
+ cr = Math.round(Math.min(cols / 2, rows / 2)) + 1;
+ for (col = 0; col < cols; col++) {
+ for (r = 0; r < rows; r++)
+ PushFormationOrder(arr, cr - Math.min(col + 1, r + 1, cols - col, rows - r), [r, col]);
+ }
+ return arr;
+ };
+
+ _This.$FormationRandom = function (transition) {
+ var a = [];
+ var r, col, i;
+ for (r = 0; r < transition.$Rows; r++) {
+ for (col = 0; col < transition.$Cols; col++)
+ PushFormationOrder(a, Math.ceil(100000 * Math.random()) % 13, [r, col]);
+ }
+
+ return a;
+ };
+
+ _This.$FormationCircle = function (transition) {
+ var cols = transition.$Cols || 1;
+ var rows = transition.$Rows || 1;
+ var arr = [];
+ var i = 0;
+ var col;
+ var r;
+ var hc = cols / 2 - 0.5;
+ var hr = rows / 2 - 0.5;
+ for (col = 0; col < cols; col++) {
+ for (r = 0; r < rows; r++)
+ PushFormationOrder(arr, Math.round(Math.sqrt(Math.pow(col - hc, 2) + Math.pow(r - hr, 2))), [r, col]);
+ }
+ return arr;
+ };
+
+ _This.$FormationCross = function (transition) {
+ var cols = transition.$Cols || 1;
+ var rows = transition.$Rows || 1;
+ var arr = [];
+ var i = 0;
+ var col;
+ var r;
+ var hc = cols / 2 - 0.5;
+ var hr = rows / 2 - 0.5;
+ for (col = 0; col < cols; col++) {
+ for (r = 0; r < rows; r++)
+ PushFormationOrder(arr, Math.round(Math.min(Math.abs(col - hc), Math.abs(r - hr))), [r, col]);
+ }
+ return arr;
+ };
+
+ _This.$FormationRectangleCross = function (transition) {
+ var cols = transition.$Cols || 1;
+ var rows = transition.$Rows || 1;
+ var arr = [];
+ var i = 0;
+ var col;
+ var r;
+ var hc = cols / 2 - 0.5;
+ var hr = rows / 2 - 0.5;
+ var cr = Math.max(hc, hr) + 1;
+ for (col = 0; col < cols; col++) {
+ for (r = 0; r < rows; r++)
+ PushFormationOrder(arr, Math.round(cr - Math.max(hc - Math.abs(col - hc), hr - Math.abs(r - hr))) - 1, [r, col]);
+ }
+ return arr;
+ };
+};
+
+var $JssorSlideshowRunner$ = window.$JssorSlideshowRunner$ = function (slideContainer, slideContainerWidth, slideContainerHeight, slideshowOptions, isTouchDevice) {
+
+ var _SelfSlideshowRunner = this;
+
+ //var _State = 0; //-1 fullfill, 0 clean, 1 initializing, 2 stay, 3 playing
+ var _EndTime;
+
+ var _SliderFrameCount;
+
+ var _SlideshowPlayerBelow;
+ var _SlideshowPlayerAbove;
+
+ var _PrevItem;
+ var _SlideItem;
+
+ var _TransitionIndex = 0;
+ var _TransitionsOrder = slideshowOptions.$TransitionsOrder;
+
+ var _SlideshowTransition;
+
+ var _SlideshowPerformance = 8;
+
+ //#region Private Methods
+ function EnsureTransitionInstance(options, slideshowInterval) {
+
+ var slideshowTransition = {
+ $Interval: slideshowInterval, //Delay to play next frame
+ $Duration: 1, //Duration to finish the entire transition
+ $Delay: 0, //Delay to assembly blocks
+ $Cols: 1, //Number of columns
+ $Rows: 1, //Number of rows
+ $Opacity: 0, //Fade block or not
+ $Zoom: 0, //Zoom block or not
+ $Clip: 0, //Clip block or not
+ $Move: false, //Move block or not
+ $SlideOut: false, //Slide the previous slide out to display next slide instead
+ //$FlyDirection: 0, //Specify fly transform with direction
+ $Reverse: false, //Reverse the assembly or not
+ $Formation: $JssorSlideshowFormations$.$FormationRandom, //Shape that assembly blocks as
+ $Assembly: 0x0408, //The way to assembly blocks ASSEMBLY_RIGHT_BOTTOM
+ $ChessMode: { $Column: 0, $Row: 0 }, //Chess move or fly direction
+ $Easing: $JssorEasing$.$EaseSwing, //Specify variation of speed during transition
+ $Round: {},
+ $Blocks: [],
+ $During: {}
+ };
+
+ $Jssor$.$Extend(slideshowTransition, options);
+
+ slideshowTransition.$Count = slideshowTransition.$Cols * slideshowTransition.$Rows;
+ if ($Jssor$.$IsFunction(slideshowTransition.$Easing))
+ slideshowTransition.$Easing = { $Default: slideshowTransition.$Easing };
+
+ slideshowTransition.$FramesCount = Math.ceil(slideshowTransition.$Duration / slideshowTransition.$Interval);
+
+ slideshowTransition.$GetBlocks = function (width, height) {
+ width /= slideshowTransition.$Cols;
+ height /= slideshowTransition.$Rows;
+ var wh = width + 'x' + height;
+ if (!slideshowTransition.$Blocks[wh]) {
+ slideshowTransition.$Blocks[wh] = { $Width: width, $Height: height };
+ for (var col = 0; col < slideshowTransition.$Cols; col++) {
+ for (var r = 0; r < slideshowTransition.$Rows; r++)
+ slideshowTransition.$Blocks[wh][r + ',' + col] = { $Top: r * height, $Right: col * width + width, $Bottom: r * height + height, $Left: col * width };
+ }
+ }
+
+ return slideshowTransition.$Blocks[wh];
+ };
+
+ if (slideshowTransition.$Brother) {
+ slideshowTransition.$Brother = EnsureTransitionInstance(slideshowTransition.$Brother, slideshowInterval);
+ slideshowTransition.$SlideOut = true;
+ }
+
+ return slideshowTransition;
+ }
+ //#endregion
+
+ //#region Private Classes
+ function JssorSlideshowPlayer(slideContainer, slideElement, slideTransition, beginTime, slideContainerWidth, slideContainerHeight) {
+ var _Self = this;
+
+ var _Block;
+ var _StartStylesArr = {};
+ var _AnimationStylesArrs = {};
+ var _AnimationBlockItems = [];
+ var _StyleStart;
+ var _StyleEnd;
+ var _StyleDif;
+ var _ChessModeColumn = slideTransition.$ChessMode.$Column || 0;
+ var _ChessModeRow = slideTransition.$ChessMode.$Row || 0;
+
+ var _Blocks = slideTransition.$GetBlocks(slideContainerWidth, slideContainerHeight);
+ var _FormationInstance = GetFormation(slideTransition);
+ var _MaxOrder = _FormationInstance.length - 1;
+ var _Period = slideTransition.$Duration + slideTransition.$Delay * _MaxOrder;
+ var _EndTime = beginTime + _Period;
+
+ var _SlideOut = slideTransition.$SlideOut;
+ var _IsIn;
+
+ //_EndTime += $Jssor$.$IsBrowserChrome() ? 260 : 50;
+ _EndTime += 50;
+
+ //#region Private Methods
+
+ function GetFormation(transition) {
+
+ var formationInstance = transition.$Formation(transition);
+
+ return transition.$Reverse ? formationInstance.reverse() : formationInstance;
+
+ }
+ //#endregion
+
+ _Self.$EndTime = _EndTime;
+
+ _Self.$ShowFrame = function (time) {
+ time -= beginTime;
+
+ var isIn = time < _Period;
+
+ if (isIn || _IsIn) {
+ _IsIn = isIn;
+
+ if (!_SlideOut)
+ time = _Period - time;
+
+ var frameIndex = Math.ceil(time / slideTransition.$Interval);
+
+ $Jssor$.$Each(_AnimationStylesArrs, function (value, index) {
+
+ var itemFrameIndex = Math.max(frameIndex, value.$Min);
+ itemFrameIndex = Math.min(itemFrameIndex, value.length - 1);
+
+ if (value.$LastFrameIndex != itemFrameIndex) {
+ if (!value.$LastFrameIndex && !_SlideOut) {
+ $Jssor$.$ShowElement(_AnimationBlockItems[index]);
+ }
+ else if (itemFrameIndex == value.$Max && _SlideOut) {
+ $Jssor$.$HideElement(_AnimationBlockItems[index]);
+ }
+ value.$LastFrameIndex = itemFrameIndex;
+ $Jssor$.$SetStylesEx(_AnimationBlockItems[index], value[itemFrameIndex]);
+ }
+ });
+ }
+ };
+
+ function DisableHWA(elmt) {
+ $Jssor$.$DisableHWA(elmt);
+
+ var children = $Jssor$.$Children(elmt);
+
+ $Jssor$.$Each(children, function (child) {
+ DisableHWA(child);
+ });
+ }
+
+ //constructor
+ {
+ slideElement = $Jssor$.$CloneNode(slideElement);
+ //$Jssor$.$RemoveAttribute(slideElement, "id");
+ DisableHWA(slideElement);
+ if ($Jssor$.$IsBrowserIe9Earlier()) {
+ var hasImage = !slideElement["no-image"];
+ var slideChildElements = $Jssor$.$FindChildrenByTag(slideElement);
+ $Jssor$.$Each(slideChildElements, function (slideChildElement) {
+ if (hasImage || slideChildElement["jssor-slider"])
+ $Jssor$.$CssOpacity(slideChildElement, $Jssor$.$CssOpacity(slideChildElement), true);
+ });
+ }
+
+ $Jssor$.$Each(_FormationInstance, function (formationItems, order) {
+ $Jssor$.$Each(formationItems, function (formationItem) {
+ var row = formationItem[0];
+ var col = formationItem[1];
+ {
+ var columnRow = row + ',' + col;
+
+ var chessHorizontal = false;
+ var chessVertical = false;
+ var chessRotate = false;
+
+ if (_ChessModeColumn && col % 2) {
+ if ($JssorDirection$.$IsHorizontal(_ChessModeColumn)) {
+ chessHorizontal = !chessHorizontal;
+ }
+ if ($JssorDirection$.$IsVertical(_ChessModeColumn)) {
+ chessVertical = !chessVertical;
+ }
+
+ if (_ChessModeColumn & 16)
+ chessRotate = !chessRotate;
+ }
+
+ if (_ChessModeRow && row % 2) {
+ if ($JssorDirection$.$IsHorizontal(_ChessModeRow)) {
+ chessHorizontal = !chessHorizontal;
+ }
+ if ($JssorDirection$.$IsVertical(_ChessModeRow)) {
+ chessVertical = !chessVertical;
+ }
+ if (_ChessModeRow & 16)
+ chessRotate = !chessRotate;
+ }
+
+ slideTransition.$Top = slideTransition.$Top || (slideTransition.$Clip & 4);
+ slideTransition.$Bottom = slideTransition.$Bottom || (slideTransition.$Clip & 8);
+ slideTransition.$Left = slideTransition.$Left || (slideTransition.$Clip & 1);
+ slideTransition.$Right = slideTransition.$Right || (slideTransition.$Clip & 2);
+
+ var topBenchmark = chessVertical ? slideTransition.$Bottom : slideTransition.$Top;
+ var bottomBenchmark = chessVertical ? slideTransition.$Top : slideTransition.$Bottom;
+ var leftBenchmark = chessHorizontal ? slideTransition.$Right : slideTransition.$Left;
+ var rightBenchmark = chessHorizontal ? slideTransition.$Left : slideTransition.$Right;
+
+ //$JssorDebug$.$Execute(function () {
+ // topBenchmark = bottomBenchmark = leftBenchmark = rightBenchmark = false;
+ //});
+
+ slideTransition.$Clip = topBenchmark || bottomBenchmark || leftBenchmark || rightBenchmark;
+
+ _StyleDif = {};
+ _StyleEnd = { $Top: 0, $Left: 0, $Opacity: 1, $Width: slideContainerWidth, $Height: slideContainerHeight };
+ _StyleStart = $Jssor$.$Extend({}, _StyleEnd);
+ _Block = $Jssor$.$Extend({}, _Blocks[columnRow]);
+
+ if (slideTransition.$Opacity) {
+ _StyleEnd.$Opacity = 2 - slideTransition.$Opacity;
+ }
+
+ if (slideTransition.$ZIndex) {
+ _StyleEnd.$ZIndex = slideTransition.$ZIndex;
+ _StyleStart.$ZIndex = 0;
+ }
+
+ var allowClip = slideTransition.$Cols * slideTransition.$Rows > 1 || slideTransition.$Clip;
+
+ if (slideTransition.$Zoom || slideTransition.$Rotate) {
+ var allowRotate = true;
+ if ($Jssor$.$IsBrowserIE() && $Jssor$.$BrowserEngineVersion() < 9) {
+ if (slideTransition.$Cols * slideTransition.$Rows > 1)
+ allowRotate = false;
+ else
+ allowClip = false;
+ }
+
+ if (allowRotate) {
+ _StyleEnd.$Zoom = slideTransition.$Zoom ? slideTransition.$Zoom - 1 : 1;
+ _StyleStart.$Zoom = 1;
+
+ if ($Jssor$.$IsBrowserIe9Earlier() || $Jssor$.$IsBrowserOpera())
+ _StyleEnd.$Zoom = Math.min(_StyleEnd.$Zoom, 2);
+
+ var rotate = slideTransition.$Rotate;
+
+ _StyleEnd.$Rotate = rotate * 360 * ((chessRotate) ? -1 : 1);
+ _StyleStart.$Rotate = 0;
+ }
+ }
+
+ if (allowClip) {
+ if (slideTransition.$Clip) {
+ var clipScale = slideTransition.$ScaleClip || 1;
+ var blockOffset = _Block.$Offset = {};
+ if (topBenchmark && bottomBenchmark) {
+ blockOffset.$Top = _Blocks.$Height / 2 * clipScale;
+ blockOffset.$Bottom = -blockOffset.$Top;
+ }
+ else if (topBenchmark) {
+ blockOffset.$Bottom = -_Blocks.$Height * clipScale;
+ }
+ else if (bottomBenchmark) {
+ blockOffset.$Top = _Blocks.$Height * clipScale;
+ }
+
+ if (leftBenchmark && rightBenchmark) {
+ blockOffset.$Left = _Blocks.$Width / 2 * clipScale;
+ blockOffset.$Right = -blockOffset.$Left;
+ }
+ else if (leftBenchmark) {
+ blockOffset.$Right = -_Blocks.$Width * clipScale;
+ }
+ else if (rightBenchmark) {
+ blockOffset.$Left = _Blocks.$Width * clipScale;
+ }
+ }
+
+ _StyleDif.$Clip = _Block;
+ _StyleStart.$Clip = _Blocks[columnRow];
+ }
+
+ //fly
+ {
+ var chessHor = chessHorizontal ? 1 : -1;
+ var chessVer = chessVertical ? 1 : -1;
+
+ if (slideTransition.x)
+ _StyleEnd.$Left += slideContainerWidth * slideTransition.x * chessHor;
+
+ if (slideTransition.y)
+ _StyleEnd.$Top += slideContainerHeight * slideTransition.y * chessVer;
+ }
+
+ $Jssor$.$Each(_StyleEnd, function (propertyEnd, property) {
+ if ($Jssor$.$IsNumeric(propertyEnd)) {
+ if (propertyEnd != _StyleStart[property]) {
+ _StyleDif[property] = propertyEnd - _StyleStart[property];
+ }
+ }
+ });
+
+ _StartStylesArr[columnRow] = _SlideOut ? _StyleStart : _StyleEnd;
+
+ var animationStylesArr = [];
+ var framesCount = slideTransition.$FramesCount;
+ var virtualFrameCount = Math.round(order * slideTransition.$Delay / slideTransition.$Interval);
+ _AnimationStylesArrs[columnRow] = new Array(virtualFrameCount);
+ _AnimationStylesArrs[columnRow].$Min = virtualFrameCount;
+ _AnimationStylesArrs[columnRow].$Max = virtualFrameCount + framesCount - 1;
+
+ for (var frameN = 0; frameN <= framesCount; frameN++) {
+ var styleFrameN = $Jssor$.$Cast(_StyleStart, _StyleDif, frameN / framesCount, slideTransition.$Easing, slideTransition.$During, slideTransition.$Round, { $Move: slideTransition.$Move, $OriginalWidth: slideContainerWidth, $OriginalHeight: slideContainerHeight })
+
+ styleFrameN.$ZIndex = styleFrameN.$ZIndex || 1;
+
+ _AnimationStylesArrs[columnRow].push(styleFrameN);
+ }
+
+ } //for
+ });
+ });
+
+ _FormationInstance.reverse();
+ $Jssor$.$Each(_FormationInstance, function (formationItems) {
+ $Jssor$.$Each(formationItems, function (formationItem) {
+ var row = formationItem[0];
+ var col = formationItem[1];
+
+ var columnRow = row + ',' + col;
+
+ var image = slideElement;
+ if (col || row)
+ image = $Jssor$.$CloneNode(slideElement);
+
+ $Jssor$.$SetStyles(image, _StartStylesArr[columnRow]);
+ $Jssor$.$CssOverflow(image, "hidden");
+
+ $Jssor$.$CssPosition(image, "absolute");
+ slideContainer.$AddClipElement(image);
+ _AnimationBlockItems[columnRow] = image;
+ $Jssor$.$ShowElement(image, !_SlideOut);
+ });
+ });
+ }
+ }
+
+ function SlideshowProcessor() {
+ var _SelfSlideshowProcessor = this;
+ var _CurrentTime = 0;
+
+ $JssorAnimator$.call(_SelfSlideshowProcessor, 0, _EndTime);
+
+ _SelfSlideshowProcessor.$OnPositionChange = function (oldPosition, newPosition) {
+ if ((newPosition - _CurrentTime) > _SlideshowPerformance) {
+ _CurrentTime = newPosition;
+
+ _SlideshowPlayerAbove && _SlideshowPlayerAbove.$ShowFrame(newPosition);
+ _SlideshowPlayerBelow && _SlideshowPlayerBelow.$ShowFrame(newPosition);
+ }
+ };
+
+ _SelfSlideshowProcessor.$Transition = _SlideshowTransition;
+ }
+ //#endregion
+
+ //member functions
+ _SelfSlideshowRunner.$GetTransition = function (slideCount) {
+ var n = 0;
+
+ var transitions = slideshowOptions.$Transitions;
+
+ var transitionCount = transitions.length;
+
+ if (_TransitionsOrder) { /*Sequence*/
+ //if (transitionCount > slideCount && ($Jssor$.$IsBrowserChrome() || $Jssor$.$IsBrowserSafari() || $Jssor$.$IsBrowserFireFox())) {
+ // transitionCount -= transitionCount % slideCount;
+ //}
+ n = _TransitionIndex++ % transitionCount;
+ }
+ else { /*Random*/
+ n = Math.floor(Math.random() * transitionCount);
+ }
+
+ transitions[n] && (transitions[n].$Index = n);
+
+ return transitions[n];
+ };
+
+ _SelfSlideshowRunner.$Initialize = function (slideIndex, prevIndex, slideItem, prevItem, slideshowTransition) {
+ $JssorDebug$.$Execute(function () {
+ if (_SlideshowPlayerBelow) {
+ $JssorDebug$.$Fail("slideshow runner has not been cleared.");
+ }
+ });
+
+ _SlideshowTransition = slideshowTransition;
+
+ slideshowTransition = EnsureTransitionInstance(slideshowTransition, _SlideshowPerformance);
+
+ _SlideItem = slideItem;
+ _PrevItem = prevItem;
+
+ var prevSlideElement = prevItem.$Item;
+ var currentSlideElement = slideItem.$Item;
+ prevSlideElement["no-image"] = !prevItem.$Image;
+ currentSlideElement["no-image"] = !slideItem.$Image;
+
+ var slideElementAbove = prevSlideElement;
+ var slideElementBelow = currentSlideElement;
+
+ var slideTransitionAbove = slideshowTransition;
+ var slideTransitionBelow = slideshowTransition.$Brother || EnsureTransitionInstance({}, _SlideshowPerformance);
+
+ if (!slideshowTransition.$SlideOut) {
+ slideElementAbove = currentSlideElement;
+ slideElementBelow = prevSlideElement;
+ }
+
+ var shift = slideTransitionBelow.$Shift || 0;
+
+ _SlideshowPlayerBelow = new JssorSlideshowPlayer(slideContainer, slideElementBelow, slideTransitionBelow, Math.max(shift - slideTransitionBelow.$Interval, 0), slideContainerWidth, slideContainerHeight);
+ _SlideshowPlayerAbove = new JssorSlideshowPlayer(slideContainer, slideElementAbove, slideTransitionAbove, Math.max(slideTransitionBelow.$Interval - shift, 0), slideContainerWidth, slideContainerHeight);
+
+ _SlideshowPlayerBelow.$ShowFrame(0);
+ _SlideshowPlayerAbove.$ShowFrame(0);
+
+ _EndTime = Math.max(_SlideshowPlayerBelow.$EndTime, _SlideshowPlayerAbove.$EndTime);
+
+ _SelfSlideshowRunner.$Index = slideIndex;
+ };
+
+ _SelfSlideshowRunner.$Clear = function () {
+ slideContainer.$Clear();
+ _SlideshowPlayerBelow = null;
+ _SlideshowPlayerAbove = null;
+ };
+
+ _SelfSlideshowRunner.$GetProcessor = function () {
+ var slideshowProcessor = null;
+
+ if (_SlideshowPlayerAbove)
+ slideshowProcessor = new SlideshowProcessor();
+
+ return slideshowProcessor;
+ };
+
+ //Constructor
+ {
+ if ($Jssor$.$IsBrowserIe9Earlier() || $Jssor$.$IsBrowserOpera() || (isTouchDevice && $Jssor$.$WebKitVersion() < 537)) {
+ _SlideshowPerformance = 16;
+ }
+
+ $JssorObject$.call(_SelfSlideshowRunner);
+ $JssorAnimator$.call(_SelfSlideshowRunner, -10000000, 10000000);
+ }
+};
+
+var $JssorSlider$ = window.$JssorSlider$ = function (elmt, options) {
+ var _SelfSlider = this;
+
+ //#region Private Classes
+ //Conveyor
+ function Conveyor() {
+ var _SelfConveyor = this;
+ $JssorAnimator$.call(_SelfConveyor, -100000000, 200000000);
+
+ _SelfConveyor.$GetCurrentSlideInfo = function () {
+ var positionDisplay = _SelfConveyor.$GetPosition_Display();
+ var virtualIndex = Math.floor(positionDisplay);
+ var slideIndex = GetRealIndex(virtualIndex);
+ var slidePosition = positionDisplay - Math.floor(positionDisplay);
+
+ return { $Index: slideIndex, $VirtualIndex: virtualIndex, $Position: slidePosition };
+ };
+
+ _SelfConveyor.$OnPositionChange = function (oldPosition, newPosition) {
+
+ var index = Math.floor(newPosition);
+ if (index != newPosition && newPosition > oldPosition)
+ index++;
+
+ ResetNavigator(index, true);
+
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_POSITION_CHANGE, GetRealIndex(newPosition), GetRealIndex(oldPosition), newPosition, oldPosition);
+ };
+ }
+ //Conveyor
+
+ //Carousel
+ function Carousel() {
+ var _SelfCarousel = this;
+
+ $JssorAnimator$.call(_SelfCarousel, 0, 0, { $LoopLength: _SlideCount });
+
+ //Carousel Constructor
+ {
+ $Jssor$.$Each(_SlideItems, function (slideItem) {
+ (_Loop & 1) && slideItem.$SetLoopLength(_SlideCount);
+ _SelfCarousel.$Chain(slideItem);
+ slideItem.$Shift(_ParkingPosition / _StepLength);
+ });
+ }
+ }
+ //Carousel
+
+ //Slideshow
+ function Slideshow() {
+ var _SelfSlideshow = this;
+ var _Wrapper = _SlideContainer.$Elmt;
+
+ $JssorAnimator$.call(_SelfSlideshow, -1, 2, { $Easing: $JssorEasing$.$EaseLinear, $Setter: { $Position: SetPosition }, $LoopLength: _SlideCount }, _Wrapper, { $Position: 1 }, { $Position: -2 });
+
+ _SelfSlideshow.$Wrapper = _Wrapper;
+
+ //Slideshow Constructor
+ {
+ $JssorDebug$.$Execute(function () {
+ $Jssor$.$Attribute(_SlideContainer.$Elmt, "debug-id", "slide_container");
+ });
+ }
+ }
+ //Slideshow
+
+ //CarouselPlayer
+ function CarouselPlayer(carousel, slideshow) {
+ var _SelfCarouselPlayer = this;
+ var _FromPosition;
+ var _ToPosition;
+ var _Duration;
+ var _StandBy;
+ var _StandByPosition;
+
+ $JssorAnimator$.call(_SelfCarouselPlayer, -100000000, 200000000, { $IntervalMax: 100 });
+
+ _SelfCarouselPlayer.$OnStart = function () {
+ _IsSliding = true;
+ _LoadingTicket = null;
+
+ //EVT_SWIPE_START
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_SWIPE_START, GetRealIndex(_Conveyor.$GetPosition()), _Conveyor.$GetPosition());
+ };
+
+ _SelfCarouselPlayer.$OnStop = function () {
+
+ _IsSliding = false;
+ _StandBy = false;
+
+ var currentSlideInfo = _Conveyor.$GetCurrentSlideInfo();
+
+ //EVT_SWIPE_END
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_SWIPE_END, GetRealIndex(_Conveyor.$GetPosition()), _Conveyor.$GetPosition());
+
+ if (!currentSlideInfo.$Position) {
+ OnPark(currentSlideInfo.$VirtualIndex, _CurrentSlideIndex);
+ }
+ };
+
+ _SelfCarouselPlayer.$OnPositionChange = function (oldPosition, newPosition) {
+
+ var toPosition;
+
+ if (_StandBy)
+ toPosition = _StandByPosition;
+ else {
+ toPosition = _ToPosition;
+
+ if (_Duration) {
+ var interPosition = newPosition / _Duration;
+ //if ($Jssor$.$IsBrowserChrome() || $Jssor$.$IsBrowserFireFox()) {
+ // Math.round(interPosition * 8 / _Duration) / 8 * _Duration;
+
+ // if ($Jssor$.$BrowserVersion() < 38)
+ // interPosition = parseFloat(interPosition.toFixed(4));
+ //}
+ toPosition = _Options.$SlideEasing(interPosition) * (_ToPosition - _FromPosition) + _FromPosition;
+ }
+ }
+
+ _Conveyor.$GoToPosition(toPosition);
+ };
+
+ _SelfCarouselPlayer.$PlayCarousel = function (fromPosition, toPosition, duration, callback) {
+ $JssorDebug$.$Execute(function () {
+ if (_SelfCarouselPlayer.$IsPlaying())
+ $JssorDebug$.$Fail("The carousel is already playing.");
+ });
+
+ _FromPosition = fromPosition;
+ _ToPosition = toPosition;
+ _Duration = duration;
+
+ _Conveyor.$GoToPosition(fromPosition);
+ _SelfCarouselPlayer.$GoToPosition(0);
+
+ _SelfCarouselPlayer.$PlayToPosition(duration, callback);
+ };
+
+ _SelfCarouselPlayer.$StandBy = function (standByPosition) {
+ _StandBy = true;
+ _StandByPosition = standByPosition;
+ _SelfCarouselPlayer.$Play(standByPosition, null, true);
+ };
+
+ _SelfCarouselPlayer.$SetStandByPosition = function (standByPosition) {
+ _StandByPosition = standByPosition;
+ };
+
+ _SelfCarouselPlayer.$MoveCarouselTo = function (position) {
+ _Conveyor.$GoToPosition(position);
+ };
+
+ //CarouselPlayer Constructor
+ {
+ _Conveyor = new Conveyor();
+
+ _Conveyor.$Combine(carousel);
+ _Conveyor.$Combine(slideshow);
+ }
+ }
+ //CarouselPlayer
+
+ //SlideContainer
+ function SlideContainer() {
+ var _Self = this;
+ var elmt = CreatePanel();
+
+ $Jssor$.$CssZIndex(elmt, 0);
+ $Jssor$.$Css(elmt, "pointerEvents", "none");
+
+ _Self.$Elmt = elmt;
+
+ _Self.$AddClipElement = function (clipElement) {
+ $Jssor$.$AppendChild(elmt, clipElement);
+ $Jssor$.$ShowElement(elmt);
+ };
+
+ _Self.$Clear = function () {
+ $Jssor$.$HideElement(elmt);
+ $Jssor$.$Empty(elmt);
+ };
+ }
+ //SlideContainer
+
+ //SlideItem
+ function SlideItem(slideElmt, slideIndex) {
+
+ var _SelfSlideItem = this;
+
+ var _CaptionSliderIn;
+ var _CaptionSliderOut;
+ var _CaptionSliderCurrent;
+ var _IsCaptionSliderPlayingWhenDragStart;
+
+ var _Wrapper;
+ var _BaseElement = slideElmt;
+
+ var _LoadingScreen;
+
+ var _ImageItem;
+ var _ImageElmts = [];
+ var _LinkItemOrigin;
+ var _LinkItem;
+ var _ImageLoading;
+ var _ImageLoaded;
+ var _ImageLazyLoading;
+ var _ContentRefreshed;
+
+ var _Processor;
+
+ var _PlayerInstanceElement;
+ var _PlayerInstance;
+
+ var _SequenceNumber; //for debug only
+
+ $JssorAnimator$.call(_SelfSlideItem, -_DisplayPieces, _DisplayPieces + 1, { $SlideItemAnimator: true });
+
+ function ResetCaptionSlider(fresh) {
+ _CaptionSliderOut && _CaptionSliderOut.$Revert();
+ _CaptionSliderIn && _CaptionSliderIn.$Revert();
+
+ RefreshContent(slideElmt, fresh);
+ _ContentRefreshed = true;
+
+ _CaptionSliderIn = new _CaptionSliderOptions.$Class(slideElmt, _CaptionSliderOptions, 1);
+ $JssorDebug$.$LiveStamp(_CaptionSliderIn, "caption_slider_" + _CaptionSliderCount + "_in");
+ _CaptionSliderOut = new _CaptionSliderOptions.$Class(slideElmt, _CaptionSliderOptions);
+ $JssorDebug$.$LiveStamp(_CaptionSliderOut, "caption_slider_" + _CaptionSliderCount + "_out");
+
+ $JssorDebug$.$Execute(function () {
+ _CaptionSliderCount++;
+ });
+
+ _CaptionSliderOut.$GoToBegin();
+ _CaptionSliderIn.$GoToBegin();
+ }
+
+ function EnsureCaptionSliderVersion() {
+ if (_CaptionSliderIn.$Version < _CaptionSliderOptions.$Version) {
+ ResetCaptionSlider();
+ }
+ }
+
+ //event handling begin
+ function LoadImageCompleteEventHandler(completeCallback, loadingScreen, image) {
+ if (!_ImageLoaded) {
+ _ImageLoaded = true;
+
+ if (_ImageItem && image) {
+ var imageWidth = image.width;
+ var imageHeight = image.height;
+ var fillWidth = imageWidth;
+ var fillHeight = imageHeight;
+
+ if (imageWidth && imageHeight && _Options.$FillMode) {
+
+ //0 stretch, 1 contain (keep aspect ratio and put all inside slide), 2 cover (keep aspect ratio and cover whole slide), 4 actual size, 5 contain for large image, actual size for small image, default value is 0
+ if (_Options.$FillMode & 3 && (!(_Options.$FillMode & 4) || imageWidth > _SlideWidth || imageHeight > _SlideHeight)) {
+ var fitHeight = false;
+ var ratio = _SlideWidth / _SlideHeight * imageHeight / imageWidth;
+
+ if (_Options.$FillMode & 1) {
+ fitHeight = (ratio > 1);
+ }
+ else if (_Options.$FillMode & 2) {
+ fitHeight = (ratio < 1);
+ }
+ fillWidth = fitHeight ? imageWidth * _SlideHeight / imageHeight : _SlideWidth;
+ fillHeight = fitHeight ? _SlideHeight : imageHeight * _SlideWidth / imageWidth;
+ }
+
+ $Jssor$.$CssWidth(_ImageItem, fillWidth);
+ $Jssor$.$CssHeight(_ImageItem, fillHeight);
+ $Jssor$.$CssTop(_ImageItem, (_SlideHeight - fillHeight) / 2);
+ $Jssor$.$CssLeft(_ImageItem, (_SlideWidth - fillWidth) / 2);
+ }
+
+ $Jssor$.$CssPosition(_ImageItem, "absolute");
+
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_LOAD_END, slideIndex);
+ }
+ }
+
+ $Jssor$.$HideElement(loadingScreen);
+ completeCallback && completeCallback(_SelfSlideItem);
+ }
+
+ function LoadSlideshowImageCompleteEventHandler(nextIndex, nextItem, slideshowTransition, loadingTicket) {
+ if (loadingTicket == _LoadingTicket && _CurrentSlideIndex == slideIndex && _AutoPlay) {
+ if (!_Frozen) {
+ var nextRealIndex = GetRealIndex(nextIndex);
+ _SlideshowRunner.$Initialize(nextRealIndex, slideIndex, nextItem, _SelfSlideItem, slideshowTransition);
+ nextItem.$HideContentForSlideshow();
+ _Slideshow.$Locate(nextRealIndex, 1);
+ _Slideshow.$GoToPosition(nextRealIndex);
+ _CarouselPlayer.$PlayCarousel(nextIndex, nextIndex, 0);
+ }
+ }
+ }
+
+ function SlideReadyEventHandler(loadingTicket) {
+ if (loadingTicket == _LoadingTicket && _CurrentSlideIndex == slideIndex) {
+
+ if (!_Processor) {
+ var slideshowProcessor = null;
+ if (_SlideshowRunner) {
+ if (_SlideshowRunner.$Index == slideIndex)
+ slideshowProcessor = _SlideshowRunner.$GetProcessor();
+ else
+ _SlideshowRunner.$Clear();
+ }
+
+ EnsureCaptionSliderVersion();
+
+ _Processor = new Processor(slideElmt, slideIndex, slideshowProcessor, _SelfSlideItem.$GetCaptionSliderIn(), _SelfSlideItem.$GetCaptionSliderOut());
+ _Processor.$SetPlayer(_PlayerInstance);
+ }
+
+ !_Processor.$IsPlaying() && _Processor.$Replay();
+ }
+ }
+
+ function ParkEventHandler(currentIndex, previousIndex, manualActivate) {
+ if (currentIndex == slideIndex) {
+
+ if (currentIndex != previousIndex)
+ _SlideItems[previousIndex] && _SlideItems[previousIndex].$ParkOut();
+ else
+ !manualActivate && _Processor && _Processor.$AdjustIdleOnPark();
+
+ _PlayerInstance && _PlayerInstance.$Enable();
+
+ //park in
+ var loadingTicket = _LoadingTicket = $Jssor$.$GetNow();
+ _SelfSlideItem.$LoadImage($Jssor$.$CreateCallback(null, SlideReadyEventHandler, loadingTicket));
+ }
+ else {
+ var distance = Math.abs(slideIndex - currentIndex);
+ var loadRange = _DisplayPieces + _Options.$LazyLoading - 1;
+ if (!_ImageLazyLoading || distance <= loadRange) {
+ _SelfSlideItem.$LoadImage();
+ }
+ }
+ }
+
+ function SwipeStartEventHandler() {
+ if (_CurrentSlideIndex == slideIndex && _Processor) {
+ _Processor.$Stop();
+ _PlayerInstance && _PlayerInstance.$Quit();
+ _PlayerInstance && _PlayerInstance.$Disable();
+ _Processor.$OpenSlideshowPanel();
+ }
+ }
+
+ function FreezeEventHandler() {
+ if (_CurrentSlideIndex == slideIndex && _Processor) {
+ _Processor.$Stop();
+ }
+ }
+
+ function ContentClickEventHandler(event) {
+ if (_LastDragSucceded) {
+ $Jssor$.$StopEvent(event);
+
+ var checkElement = $Jssor$.$EventSrc(event);
+ while (checkElement && slideElmt !== checkElement) {
+ if (checkElement.tagName == "A") {
+ $Jssor$.$CancelEvent(event);
+ }
+ try {
+ checkElement = checkElement.parentNode;
+ } catch (e) {
+ // Firefox sometimes fires events for XUL elements, which throws
+ // a "permission denied" error. so this is not a child.
+ break;
+ }
+ }
+ }
+ }
+
+ function SlideClickEventHandler(event) {
+ if (!_LastDragSucceded) {
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_CLICK, slideIndex, event);
+ }
+ //else {
+ // var tagName = $Jssor$.$EventSrc(event).tagName;
+ // if (tagName != "INPUT" && tagName != "TEXTAREA" && tagName != "SELECT")
+ // $Jssor$.$CancelEvent(event);
+ //}
+ }
+
+ function PlayerAvailableEventHandler() {
+ _PlayerInstance = _PlayerInstanceElement.pInstance;
+ _Processor && _Processor.$SetPlayer(_PlayerInstance);
+ }
+
+ _SelfSlideItem.$LoadImage = function (completeCallback, loadingScreen) {
+ loadingScreen = loadingScreen || _LoadingScreen;
+
+ if (_ImageElmts.length && !_ImageLoaded) {
+
+ $Jssor$.$ShowElement(loadingScreen);
+
+ if (!_ImageLoading) {
+ _ImageLoading = true;
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_LOAD_START, slideIndex);
+
+ $Jssor$.$Each(_ImageElmts, function (imageElmt) {
+
+ if (!imageElmt.src) {
+ imageElmt.src = $Jssor$.$AttributeEx(imageElmt, "src2");
+ $Jssor$.$CssDisplay(imageElmt, imageElmt["display-origin"]);
+ }
+ });
+ }
+ $Jssor$.$LoadImages(_ImageElmts, _ImageItem, $Jssor$.$CreateCallback(null, LoadImageCompleteEventHandler, completeCallback, loadingScreen));
+ }
+ else {
+ LoadImageCompleteEventHandler(completeCallback, loadingScreen);
+ }
+ };
+
+ _SelfSlideItem.$GoForNextSlide = function () {
+ if (_SlideshowRunner) {
+ var slideshowTransition = _SlideshowRunner.$GetTransition(_SlideCount);
+
+ if (slideshowTransition) {
+ var loadingTicket = _LoadingTicket = $Jssor$.$GetNow();
+
+ var nextIndex = slideIndex + _PlayReverse;
+ var nextItem = _SlideItems[GetRealIndex(nextIndex)];
+ return nextItem.$LoadImage($Jssor$.$CreateCallback(null, LoadSlideshowImageCompleteEventHandler, nextIndex, nextItem, slideshowTransition, loadingTicket), _LoadingScreen);
+ }
+ }
+
+ PlayTo(_CurrentSlideIndex + _Options.$AutoPlaySteps * _PlayReverse);
+ };
+
+ _SelfSlideItem.$TryActivate = function () {
+ ParkEventHandler(slideIndex, slideIndex, true);
+ };
+
+ _SelfSlideItem.$ParkOut = function () {
+ //park out
+ _PlayerInstance && _PlayerInstance.$Quit();
+ _PlayerInstance && _PlayerInstance.$Disable();
+ _SelfSlideItem.$UnhideContentForSlideshow();
+ _Processor && _Processor.$Abort();
+ _Processor = null;
+ ResetCaptionSlider();
+ };
+
+ //for debug only
+ _SelfSlideItem.$StampSlideItemElements = function (stamp) {
+ stamp = _SequenceNumber + "_" + stamp;
+
+ $JssorDebug$.$Execute(function () {
+ if (_ImageItem)
+ $Jssor$.$Attribute(_ImageItem, "debug-id", stamp + "_slide_item_image_id");
+
+ $Jssor$.$Attribute(slideElmt, "debug-id", stamp + "_slide_item_item_id");
+ });
+
+ $JssorDebug$.$Execute(function () {
+ $Jssor$.$Attribute(_Wrapper, "debug-id", stamp + "_slide_item_wrapper_id");
+ });
+
+ $JssorDebug$.$Execute(function () {
+ $Jssor$.$Attribute(_LoadingScreen, "debug-id", stamp + "_loading_container_id");
+ });
+ };
+
+ _SelfSlideItem.$HideContentForSlideshow = function () {
+ $Jssor$.$HideElement(slideElmt);
+ };
+
+ _SelfSlideItem.$UnhideContentForSlideshow = function () {
+ $Jssor$.$ShowElement(slideElmt);
+ };
+
+ _SelfSlideItem.$EnablePlayer = function () {
+ _PlayerInstance && _PlayerInstance.$Enable();
+ };
+
+ function RefreshContent(elmt, fresh, level) {
+ if (elmt["jssor-slider"])
+ return;
+
+ level = level || 0;
+
+ if (!_ContentRefreshed) {
+ if (elmt.tagName == "IMG") {
+ _ImageElmts.push(elmt);
+
+ if (!elmt.src) {
+ _ImageLazyLoading = true;
+ elmt["display-origin"] = $Jssor$.$CssDisplay(elmt);
+ $Jssor$.$HideElement(elmt);
+ }
+ }
+ if ($Jssor$.$IsBrowserIe9Earlier()) {
+ $Jssor$.$CssZIndex(elmt, ($Jssor$.$CssZIndex(elmt) || 0) + 1);
+ }
+ if (_Options.$HWA && $Jssor$.$WebKitVersion()) {
+ if (!_IsTouchDevice || $Jssor$.$WebKitVersion() < 534 || (!_SlideshowEnabled && !$Jssor$.$IsBrowserChrome())) {
+ $Jssor$.$EnableHWA(elmt);
+ }
+ }
+ }
+
+ var childElements = $Jssor$.$Children(elmt);
+
+ $Jssor$.$Each(childElements, function (childElement, i) {
+
+ var childTagName = childElement.tagName;
+ var uAttribute = $Jssor$.$AttributeEx(childElement, "u");
+ if (uAttribute == "player" && !_PlayerInstanceElement) {
+ _PlayerInstanceElement = childElement;
+ if (_PlayerInstanceElement.pInstance) {
+ PlayerAvailableEventHandler();
+ }
+ else {
+ $Jssor$.$AddEvent(_PlayerInstanceElement, "dataavailable", PlayerAvailableEventHandler);
+ }
+ }
+
+ if (uAttribute == "caption") {
+ if (!$Jssor$.$IsBrowserIE() && !fresh) {
+
+ if (childTagName == "A") {
+ $Jssor$.$RemoveEvent(childElement, "click", ContentClickEventHandler);
+ $Jssor$.$Attribute(childElement, "jssor-content", null);
+ }
+
+ var captionElement = $Jssor$.$CloneNode(childElement, false, true);
+ $Jssor$.$InsertBefore(captionElement, childElement, elmt);
+ $Jssor$.$RemoveElement(childElement, elmt);
+ childElement = captionElement;
+
+ fresh = true;
+ }
+ }
+ else if (!_ContentRefreshed && !level && !_ImageItem) {
+
+ if (childTagName == "A") {
+ if ($Jssor$.$AttributeEx(childElement, "u") == "image") {
+ _ImageItem = $Jssor$.$FindChildByTag(childElement, "IMG");
+
+ $JssorDebug$.$Execute(function () {
+ if (!_ImageItem) {
+ $JssorDebug$.$Error("slide html code definition error, no 'IMG' found in a 'image with link' slide.\r\n" + elmt.outerHTML);
+ }
+ });
+ }
+ else {
+ _ImageItem = $Jssor$.$FindChild(childElement, "image", true);
+ }
+
+ if (_ImageItem) {
+ _LinkItemOrigin = childElement;
+ $Jssor$.$SetStyles(_LinkItemOrigin, _StyleDef);
+
+ _LinkItem = $Jssor$.$CloneNode(_LinkItemOrigin, true);
+ $Jssor$.$AddEvent(_LinkItem, "click", ContentClickEventHandler);
+
+ $Jssor$.$CssDisplay(_LinkItem, "block");
+ $Jssor$.$SetStyles(_LinkItem, _StyleDef);
+ $Jssor$.$CssOpacity(_LinkItem, 0);
+ $Jssor$.$Css(_LinkItem, "backgroundColor", "#000");
+ }
+ }
+ else if (childTagName == "IMG" && $Jssor$.$AttributeEx(childElement, "u") == "image") {
+ _ImageItem = childElement;
+ }
+
+ if (_ImageItem) {
+ _ImageItem.border = 0;
+ $Jssor$.$SetStyles(_ImageItem, _StyleDef);
+ }
+ }
+
+ if (!$Jssor$.$Attribute(childElement, "jssor-content")) {
+ //cancel click event on element when a drag of slide succeeded
+ $Jssor$.$AddEvent(childElement, "click", ContentClickEventHandler);
+ $Jssor$.$Attribute(childElement, "jssor-content", true);
+ }
+
+ RefreshContent(childElement, fresh, level +1);
+ });
+ }
+
+ _SelfSlideItem.$OnInnerOffsetChange = function (oldOffset, newOffset) {
+ var slidePosition = _DisplayPieces - newOffset;
+
+ SetPosition(_Wrapper, slidePosition);
+
+ //following lines are for future usage, not ready yet
+ //if (!_IsDragging || !_IsCaptionSliderPlayingWhenDragStart) {
+ // var _DealWithParallax;
+ // if (IsCurrentSlideIndex(slideIndex)) {
+ // if (_CaptionSliderOptions.$PlayOutMode == 2)
+ // _DealWithParallax = true;
+ // }
+ // else {
+ // if (!_CaptionSliderOptions.$PlayInMode) {
+ // //PlayInMode: 0 none
+ // _CaptionSliderIn.$GoToEnd();
+ // }
+ // //else if (_CaptionSliderOptions.$PlayInMode == 1) {
+ // // //PlayInMode: 1 chain
+ // // _CaptionSliderIn.$GoToBegin();
+ // //}
+ // else if (_CaptionSliderOptions.$PlayInMode == 2) {
+ // //PlayInMode: 2 parallel
+ // _DealWithParallax = true;
+ // }
+ // }
+
+ // if (_DealWithParallax) {
+ // _CaptionSliderIn.$GoToPosition((_CaptionSliderIn.$GetPosition_OuterEnd() - _CaptionSliderIn.$GetPosition_OuterBegin()) * Math.abs(newOffset - 1) * .8 + _CaptionSliderIn.$GetPosition_OuterBegin());
+ // }
+ //}
+ };
+
+ _SelfSlideItem.$GetCaptionSliderIn = function () {
+ return _CaptionSliderIn;
+ };
+
+ _SelfSlideItem.$GetCaptionSliderOut = function () {
+ return _CaptionSliderOut;
+ };
+
+ _SelfSlideItem.$Index = slideIndex;
+
+ $JssorObject$.call(_SelfSlideItem);
+
+ //SlideItem Constructor
+ {
+
+ var thumb = $Jssor$.$FindChild(slideElmt, "thumb", true);
+ if (thumb) {
+ _SelfSlideItem.$Thumb = $Jssor$.$CloneNode(thumb);
+ $Jssor$.$RemoveAttribute(thumb, "id");
+ $Jssor$.$HideElement(thumb);
+ }
+ $Jssor$.$ShowElement(slideElmt);
+
+ _LoadingScreen = $Jssor$.$CloneNode(_LoadingContainer);
+ $Jssor$.$CssZIndex(_LoadingScreen, 1000);
+
+ //cancel click event on element when a drag of slide succeeded
+ $Jssor$.$AddEvent(slideElmt, "click", SlideClickEventHandler);
+
+ ResetCaptionSlider(true);
+
+ _SelfSlideItem.$Image = _ImageItem;
+ _SelfSlideItem.$Link = _LinkItem;
+
+ _SelfSlideItem.$Item = slideElmt;
+
+ _SelfSlideItem.$Wrapper = _Wrapper = slideElmt;
+ $Jssor$.$AppendChild(_Wrapper, _LoadingScreen);
+
+ _SelfSlider.$On(203, ParkEventHandler);
+ _SelfSlider.$On(28, FreezeEventHandler);
+ _SelfSlider.$On(24, SwipeStartEventHandler);
+
+ $JssorDebug$.$Execute(function () {
+ _SequenceNumber = _SlideItemCreatedCount++;
+ });
+
+ $JssorDebug$.$Execute(function () {
+ $Jssor$.$Attribute(_Wrapper, "debug-id", "slide-" + slideIndex);
+ });
+ }
+ }
+ //SlideItem
+
+ //Processor
+ function Processor(slideElmt, slideIndex, slideshowProcessor, captionSliderIn, captionSliderOut) {
+
+ var _SelfProcessor = this;
+
+ var _ProgressBegin = 0;
+ var _SlideshowBegin = 0;
+ var _SlideshowEnd;
+ var _CaptionInBegin;
+ var _IdleBegin;
+ var _IdleEnd;
+ var _ProgressEnd;
+
+ var _IsSlideshowRunning;
+ var _IsRollingBack;
+
+ var _PlayerInstance;
+ var _IsPlayerOnService;
+
+ var slideItem = _SlideItems[slideIndex];
+
+ $JssorAnimator$.call(_SelfProcessor, 0, 0);
+
+ function UpdateLink() {
+
+ $Jssor$.$Empty(_LinkContainer);
+
+ if (_ShowLink && _IsSlideshowRunning && slideItem.$Link) {
+ $Jssor$.$AppendChild(_LinkContainer, slideItem.$Link);
+ }
+
+ $Jssor$.$ShowElement(_LinkContainer, !_IsSlideshowRunning && slideItem.$Image);
+ }
+
+ function ProcessCompleteEventHandler() {
+
+ if (_IsRollingBack) {
+ _IsRollingBack = false;
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_ROLLBACK_END, slideIndex, _IdleEnd, _ProgressBegin, _IdleBegin, _IdleEnd, _ProgressEnd);
+ _SelfProcessor.$GoToPosition(_IdleBegin);
+ }
+
+ _SelfProcessor.$Replay();
+ }
+
+ function PlayerSwitchEventHandler(isOnService) {
+ _IsPlayerOnService = isOnService;
+
+ _SelfProcessor.$Stop();
+ _SelfProcessor.$Replay();
+ }
+
+ _SelfProcessor.$Replay = function () {
+
+ var currentPosition = _SelfProcessor.$GetPosition_Display();
+
+ if (!_IsDragging && !_IsSliding && !_IsPlayerOnService && _CurrentSlideIndex == slideIndex) {
+
+ if (!currentPosition) {
+ if (_SlideshowEnd && !_IsSlideshowRunning) {
+ _IsSlideshowRunning = true;
+
+ _SelfProcessor.$OpenSlideshowPanel(true);
+
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_SLIDESHOW_START, slideIndex, _ProgressBegin, _SlideshowBegin, _SlideshowEnd, _ProgressEnd);
+ }
+
+ UpdateLink();
+ }
+
+ var toPosition;
+ var stateEvent = $JssorSlider$.$EVT_STATE_CHANGE;
+
+ if (currentPosition != _ProgressEnd) {
+ if (currentPosition == _IdleEnd) {
+ toPosition = _ProgressEnd;
+ }
+ else if (currentPosition == _IdleBegin) {
+ toPosition = _IdleEnd;
+ }
+ else if (!currentPosition) {
+ toPosition = _IdleBegin;
+ }
+ else if (currentPosition > _IdleEnd) {
+ _IsRollingBack = true;
+ toPosition = _IdleEnd;
+ stateEvent = $JssorSlider$.$EVT_ROLLBACK_START;
+ }
+ else {
+ //continue from break (by drag or lock)
+ toPosition = _SelfProcessor.$GetPlayToPosition();
+ }
+ }
+
+ //$JssorDebug$.$Execute(function () {
+ // if (currentPosition == _ProgressEnd) {
+ // debugger;
+ // }
+ //});
+
+ _SelfSlider.$TriggerEvent(stateEvent, slideIndex, currentPosition, _ProgressBegin, _IdleBegin, _IdleEnd, _ProgressEnd);
+
+ var allowAutoPlay = _AutoPlay && (!_HoverToPause || _NotOnHover);
+
+ if (currentPosition == _ProgressEnd) {
+ (_IdleEnd != _ProgressEnd && !(_HoverToPause & 12) || allowAutoPlay) && slideItem.$GoForNextSlide();
+ }
+ else if (allowAutoPlay || currentPosition != _IdleEnd) {
+ _SelfProcessor.$PlayToPosition(toPosition, ProcessCompleteEventHandler);
+ }
+ }
+ };
+
+ _SelfProcessor.$AdjustIdleOnPark = function () {
+ if (_IdleEnd == _ProgressEnd && _IdleEnd == _SelfProcessor.$GetPosition_Display())
+ _SelfProcessor.$GoToPosition(_IdleBegin);
+ };
+
+ _SelfProcessor.$Abort = function () {
+ _SlideshowRunner && _SlideshowRunner.$Index == slideIndex && _SlideshowRunner.$Clear();
+
+ var currentPosition = _SelfProcessor.$GetPosition_Display();
+ if (currentPosition < _ProgressEnd) {
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_STATE_CHANGE, slideIndex, -currentPosition - 1, _ProgressBegin, _IdleBegin, _IdleEnd, _ProgressEnd);
+ }
+ };
+
+ _SelfProcessor.$OpenSlideshowPanel = function (open) {
+ if (slideshowProcessor) {
+ $Jssor$.$CssOverflow(_SlideshowPanel, open && slideshowProcessor.$Transition.$Outside ? "" : "hidden");
+ }
+ };
+
+ _SelfProcessor.$OnInnerOffsetChange = function (oldPosition, newPosition) {
+
+ if (_IsSlideshowRunning && newPosition >= _SlideshowEnd) {
+ _IsSlideshowRunning = false;
+ UpdateLink();
+ slideItem.$UnhideContentForSlideshow();
+ _SlideshowRunner.$Clear();
+
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_SLIDESHOW_END, slideIndex, _ProgressBegin, _SlideshowBegin, _SlideshowEnd, _ProgressEnd);
+ }
+
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_PROGRESS_CHANGE, slideIndex, newPosition, _ProgressBegin, _IdleBegin, _IdleEnd, _ProgressEnd);
+ };
+
+ _SelfProcessor.$SetPlayer = function (playerInstance) {
+ if (playerInstance && !_PlayerInstance) {
+ _PlayerInstance = playerInstance;
+
+ playerInstance.$On($JssorPlayer$.$EVT_SWITCH, PlayerSwitchEventHandler);
+ }
+ };
+
+ //Processor Constructor
+ {
+ if (slideshowProcessor) {
+ _SelfProcessor.$Chain(slideshowProcessor);
+ }
+
+ _SlideshowEnd = _SelfProcessor.$GetPosition_OuterEnd();
+ _CaptionInBegin = _SelfProcessor.$GetPosition_OuterEnd();
+ _SelfProcessor.$Chain(captionSliderIn);
+ _IdleBegin = captionSliderIn.$GetPosition_OuterEnd();
+ _IdleEnd = _IdleBegin + ($Jssor$.$ParseFloat($Jssor$.$AttributeEx(slideElmt, "idle")) || _Options.$AutoPlayInterval);
+
+ captionSliderOut.$Shift(_IdleEnd);
+ _SelfProcessor.$Combine(captionSliderOut);
+ _ProgressEnd = _SelfProcessor.$GetPosition_OuterEnd();
+ }
+ }
+ //Processor
+ //#endregion
+
+ function SetPosition(elmt, position) {
+ var orientation = _DragOrientation > 0 ? _DragOrientation : _PlayOrientation;
+ var x = _StepLengthX * position * (orientation & 1);
+ var y = _StepLengthY * position * ((orientation >> 1) & 1);
+
+ if ($Jssor$.$IsBrowserChrome() && $Jssor$.$BrowserVersion() < 38) {
+ x = x.toFixed(3);
+ y = y.toFixed(3);
+ }
+ else {
+ x = Math.round(x);
+ y = Math.round(y);
+ }
+
+ if ($Jssor$.$IsBrowserIE() && $Jssor$.$BrowserVersion() >= 10 && $Jssor$.$BrowserVersion() < 11) {
+ elmt.style.msTransform = "translate(" + x + "px, " + y + "px)";
+ }
+ else if ($Jssor$.$IsBrowserChrome() && $Jssor$.$BrowserVersion() >= 30 && $Jssor$.$BrowserVersion() < 34) {
+ elmt.style.WebkitTransition = "transform 0s";
+ elmt.style.WebkitTransform = "translate3d(" + x + "px, " + y + "px, 0px) perspective(2000px)";
+ }
+ else {
+ $Jssor$.$CssLeft(elmt, x);
+ $Jssor$.$CssTop(elmt, y);
+ }
+ }
+
+ //Event handling begin
+
+ function OnMouseDown(event) {
+ var eventSrc = $Jssor$.$EventSrc(event);
+ var tagName = eventSrc.tagName;
+ if (!_DragOrientationRegistered && (tagName != "INPUT" || eventSrc.type != "text") && tagName != "TEXTAREA" && tagName != "SELECT" && RegisterDrag()) {
+ OnDragStart(event);
+ }
+ }
+
+ function RecordFreezePoint() {
+
+ _CarouselPlaying_OnFreeze = _IsSliding;
+ _PlayToPosition_OnFreeze = _CarouselPlayer.$GetPlayToPosition();
+ _Position_OnFreeze = _Conveyor.$GetPosition();
+
+ }
+
+ function Freeze() {
+
+ RecordFreezePoint();
+
+ if (_IsDragging || !_NotOnHover && (_HoverToPause & 12)) {
+ _CarouselPlayer.$Stop();
+
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_FREEZE);
+ }
+
+ }
+
+ function Unfreeze(byDrag) {
+
+ byDrag && RecordFreezePoint();
+
+ if (!_IsDragging && (_NotOnHover || !(_HoverToPause & 12)) && !_CarouselPlayer.$IsPlaying()) {
+
+ var currentPosition = _Conveyor.$GetPosition();
+ var toPosition = Math.ceil(_Position_OnFreeze);
+
+ if (byDrag && Math.abs(_DragOffsetTotal) >= _Options.$MinDragOffsetToSlide) {
+ toPosition = Math.ceil(currentPosition);
+ toPosition += _DragIndexAdjust;
+ }
+
+ if (!(_Loop & 1)) {
+ toPosition = Math.min(_SlideCount - _DisplayPieces, Math.max(toPosition, 0));
+ }
+
+ var t = Math.abs(toPosition - currentPosition);
+ t = 1 - Math.pow(1 - t, 5);
+
+ if (!_LastDragSucceded && _CarouselPlaying_OnFreeze) {
+ _CarouselPlayer.$Continue(_PlayToPosition_OnFreeze);
+ }
+ else if (currentPosition == toPosition) {
+ _CurrentSlideItem.$EnablePlayer();
+ _CurrentSlideItem.$TryActivate();
+ }
+ else {
+
+ _CarouselPlayer.$PlayCarousel(currentPosition, toPosition, t * _SlideDuration);
+ }
+ }
+ }
+
+ function PreventDragStart(event) {
+ $Jssor$.$CancelEvent(event);
+ }
+
+ function OnDragStart(event) {
+
+ _IsDragging = true;
+ _DragInvalid = false;
+ _LoadingTicket = null;
+
+ $Jssor$.$AddEvent(document, _MoveEvent, OnDragMove);
+
+ _LastTimeMoveByDrag = $Jssor$.$GetNow() - 50;
+
+ _LastDragSucceded = 0;
+ Freeze();
+
+ if (!_CarouselPlaying_OnFreeze)
+ _DragOrientation = 0;
+
+ if (_HandleTouchEventOnly) {
+ var touchPoint = event.touches[0];
+ _DragStartMouseX = touchPoint.clientX;
+ _DragStartMouseY = touchPoint.clientY;
+ }
+ else {
+ var mousePoint = $Jssor$.$MousePosition(event);
+
+ _DragStartMouseX = mousePoint.x;
+ _DragStartMouseY = mousePoint.y;
+
+ if ($Jssor$.$IsBrowserFireFox() && $Jssor$.$BrowserVersion() < 4)
+ $Jssor$.$CancelEvent(event);
+ }
+
+ _DragOffsetTotal = 0;
+ _DragOffsetLastTime = 0;
+ _DragIndexAdjust = 0;
+
+ //Trigger EVT_DRAGSTART
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_DRAG_START, GetRealIndex(_Position_OnFreeze), _Position_OnFreeze, event);
+ }
+
+ function OnDragMove(event) {
+ if (_IsDragging && (!$Jssor$.$IsBrowserIe9Earlier() || event.button)) {
+ var actionPoint;
+
+ if (_HandleTouchEventOnly) {
+ var touches = event.touches;
+ if (touches && touches.length > 0) {
+ actionPoint = { x: touches[0].clientX, y: touches[0].clientY };
+ }
+ }
+ else {
+ actionPoint = $Jssor$.$MousePosition(event);
+ }
+
+ if (actionPoint) {
+ var distanceX = actionPoint.x - _DragStartMouseX;
+ var distanceY = actionPoint.y - _DragStartMouseY;
+
+
+ if (Math.floor(_Position_OnFreeze) != _Position_OnFreeze)
+ _DragOrientation = _DragOrientation || (_PlayOrientation & _DragOrientationRegistered);
+
+ if ((distanceX || distanceY) && !_DragOrientation) {
+ if (_DragOrientationRegistered == 3) {
+ if (Math.abs(distanceY) > Math.abs(distanceX)) {
+ _DragOrientation = 2;
+ }
+ else
+ _DragOrientation = 1;
+ }
+ else {
+ _DragOrientation = _DragOrientationRegistered;
+ }
+
+ if (_IsTouchDevice && _DragOrientation == 1 && Math.abs(distanceY) - Math.abs(distanceX) > 3) {
+ _DragInvalid = true;
+ }
+ }
+
+ if (_DragOrientation) {
+ var distance = distanceY;
+ var stepLength = _StepLengthY;
+
+ if (_DragOrientation == 1) {
+ distance = distanceX;
+ stepLength = _StepLengthX;
+ }
+
+ if (!(_Loop & 1)) {
+ if (distance > 0) {
+ var normalDistance = stepLength * _CurrentSlideIndex;
+ var sqrtDistance = distance - normalDistance;
+ if (sqrtDistance > 0) {
+ distance = normalDistance + Math.sqrt(sqrtDistance) * 5;
+ }
+ }
+
+ if (distance < 0) {
+ var normalDistance = stepLength * (_SlideCount - _DisplayPieces - _CurrentSlideIndex);
+ var sqrtDistance = -distance - normalDistance;
+
+ if (sqrtDistance > 0) {
+ distance = -normalDistance - Math.sqrt(sqrtDistance) * 5;
+ }
+ }
+ }
+
+ if (_DragOffsetTotal - _DragOffsetLastTime < -2) {
+ _DragIndexAdjust = 0;
+ }
+ else if (_DragOffsetTotal - _DragOffsetLastTime > 2) {
+ _DragIndexAdjust = -1;
+ }
+
+ _DragOffsetLastTime = _DragOffsetTotal;
+ _DragOffsetTotal = distance;
+ _PositionToGoByDrag = _Position_OnFreeze - _DragOffsetTotal / stepLength / (_ScaleRatio || 1);
+
+ if (_DragOffsetTotal && _DragOrientation && !_DragInvalid) {
+ $Jssor$.$CancelEvent(event);
+ if (!_IsSliding) {
+ _CarouselPlayer.$StandBy(_PositionToGoByDrag);
+ }
+ else
+ _CarouselPlayer.$SetStandByPosition(_PositionToGoByDrag);
+ }
+ else if ($Jssor$.$IsBrowserIe9Earlier()) {
+ $Jssor$.$CancelEvent(event);
+ }
+ }
+ }
+ }
+ else {
+ OnDragEnd(event);
+ }
+ }
+
+ function OnDragEnd(event) {
+ UnregisterDrag();
+
+ if (_IsDragging) {
+
+ _IsDragging = false;
+
+ _LastTimeMoveByDrag = $Jssor$.$GetNow();
+
+ $Jssor$.$RemoveEvent(document, _MoveEvent, OnDragMove);
+
+ _LastDragSucceded = _DragOffsetTotal;
+
+ //_LastDragSucceded && $Jssor$.$CancelEvent(event);
+
+ _CarouselPlayer.$Stop();
+
+ var currentPosition = _Conveyor.$GetPosition();
+
+ //Trigger EVT_DRAG_END
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_DRAG_END, GetRealIndex(currentPosition), currentPosition, GetRealIndex(_Position_OnFreeze), _Position_OnFreeze, event);
+
+ Unfreeze(true);
+ }
+ }
+ //Event handling end
+
+ function SetCurrentSlideIndex(index) {
+ _PrevSlideItem = _SlideItems[_CurrentSlideIndex];
+ _PreviousSlideIndex = _CurrentSlideIndex;
+ _CurrentSlideIndex = GetRealIndex(index);
+ _CurrentSlideItem = _SlideItems[_CurrentSlideIndex];
+ ResetNavigator(index);
+ return _CurrentSlideIndex;
+ }
+
+ function OnPark(slideIndex, prevIndex) {
+ _DragOrientation = 0;
+
+ SetCurrentSlideIndex(slideIndex);
+
+ //Trigger EVT_PARK
+ _SelfSlider.$TriggerEvent($JssorSlider$.$EVT_PARK, GetRealIndex(slideIndex), prevIndex);
+ }
+
+ function ResetNavigator(index, temp) {
+ _TempSlideIndex = index;
+ $Jssor$.$Each(_Navigators, function (navigator) {
+ navigator.$SetCurrentIndex(GetRealIndex(index), index, temp);
+ });
+ }
+
+ function RegisterDrag() {
+ var dragRegistry = $JssorSlider$.$DragRegistry || 0;
+ var dragOrientation = _DragEnabled;
+ if (_IsTouchDevice)
+ (dragOrientation & 1) && (dragOrientation &= 1);
+ $JssorSlider$.$DragRegistry |= dragOrientation;
+
+ return (_DragOrientationRegistered = dragOrientation & ~dragRegistry);
+ }
+
+ function UnregisterDrag() {
+ if (_DragOrientationRegistered) {
+ $JssorSlider$.$DragRegistry &= ~_DragEnabled;
+ _DragOrientationRegistered = 0;
+ }
+ }
+
+ function CreatePanel() {
+ var div = $Jssor$.$CreateDiv();
+
+ $Jssor$.$SetStyles(div, _StyleDef);
+ $Jssor$.$CssPosition(div, "absolute");
+
+ return div;
+ }
+
+ function GetRealIndex(index) {
+ return (index % _SlideCount + _SlideCount) % _SlideCount;
+ }
+
+ function IsCurrentSlideIndex(index) {
+ return GetRealIndex(index) == _CurrentSlideIndex;
+ }
+
+ function IsPreviousSlideIndex(index) {
+ return GetRealIndex(index) == _PreviousSlideIndex;
+ }
+
+ //Navigation Request Handler
+ function NavigationClickHandler(index, relative) {
+ if (relative) {
+ if (!_Loop) {
+ //Stop at threshold
+ index = Math.min(Math.max(index + _TempSlideIndex, 0), _SlideCount - _DisplayPieces);
+ relative = false;
+ }
+ else if (_Loop & 2) {
+ //Rewind
+ index = GetRealIndex(index + _TempSlideIndex);
+ relative = false;
+ }
+ }
+ PlayTo(index, _Options.$SlideDuration, relative);
+ }
+
+ function ShowNavigators() {
+ $Jssor$.$Each(_Navigators, function (navigator) {
+ navigator.$Show(navigator.$Options.$ChanceToShow <= _NotOnHover);
+ });
+ }
+
+ function MainContainerMouseLeaveEventHandler() {
+ if (!_NotOnHover) {
+
+ //$JssorDebug$.$Log("mouseleave");
+
+ _NotOnHover = 1;
+
+ ShowNavigators();
+
+ if (!_IsDragging) {
+ (_HoverToPause & 12) && Unfreeze();
+ (_HoverToPause & 3) && _SlideItems[_CurrentSlideIndex].$TryActivate();
+ }
+ }
+ }
+
+ function MainContainerMouseEnterEventHandler() {
+
+ if (_NotOnHover) {
+
+ //$JssorDebug$.$Log("mouseenter");
+
+ _NotOnHover = 0;
+
+ ShowNavigators();
+
+ _IsDragging || !(_HoverToPause & 12) || Freeze();
+ }
+ }
+
+ function AdjustSlidesContainerSize() {
+ _StyleDef = { $Width: _SlideWidth, $Height: _SlideHeight, $Top: 0, $Left: 0 };
+
+ $Jssor$.$Each(_SlideElmts, function (slideElmt, i) {
+
+ $Jssor$.$SetStyles(slideElmt, _StyleDef);
+ $Jssor$.$CssPosition(slideElmt, "absolute");
+ $Jssor$.$CssOverflow(slideElmt, "hidden");
+
+ $Jssor$.$HideElement(slideElmt);
+ });
+
+ $Jssor$.$SetStyles(_LoadingContainer, _StyleDef);
+ }
+
+ function PlayToOffset(offset, slideDuration) {
+ PlayTo(offset, slideDuration, true);
+ }
+
+ function PlayTo(slideIndex, slideDuration, relative) {
+ ///
+ /// PlayTo( slideIndex [, slideDuration] ); //Play slider to position 'slideIndex' within a period calculated base on 'slideDuration'.
+ ///
+ ///
+ /// slide slideIndex or position will be playing to
+ ///
+ ///
+ /// base slide duration in milliseconds to calculate the whole duration to complete this play request.
+ /// default value is '$SlideDuration' value which is specified when initialize the slider.
+ ///
+ /// http://msdn.microsoft.com/en-us/library/vstudio/bb385682.aspx
+ /// http://msdn.microsoft.com/en-us/library/vstudio/hh542720.aspx
+ if (_CarouselEnabled && (!_IsDragging || _Options.$NaviQuitDrag)) {
+ _IsSliding = true;
+ _IsDragging = false;
+ _CarouselPlayer.$Stop();
+
+ {
+ //Slide Duration
+ if (slideDuration == undefined)
+ slideDuration = _SlideDuration;
+
+ var positionDisplay = _Carousel.$GetPosition_Display();
+ var positionTo = slideIndex;
+ if (relative) {
+ positionTo = positionDisplay + slideIndex;
+ if (slideIndex > 0)
+ positionTo = Math.ceil(positionTo);
+ else
+ positionTo = Math.floor(positionTo);
+ }
+
+ if (_Loop & 2) {
+ //Rewind
+ positionTo = GetRealIndex(positionTo);
+ }
+ if (!(_Loop & 1)) {
+ //Stop at threshold
+ positionTo = Math.max(0, Math.min(positionTo, _SlideCount - _DisplayPieces));
+ }
+
+ var positionOffset = (positionTo - positionDisplay) % _SlideCount;
+ positionTo = positionDisplay + positionOffset;
+
+ var duration = positionDisplay == positionTo ? 0 : slideDuration * Math.abs(positionOffset);
+ duration = Math.min(duration, slideDuration * _DisplayPieces * 1.5);
+
+ _CarouselPlayer.$PlayCarousel(positionDisplay, positionTo, duration || 1);
+ }
+ }
+ }
+
+ //private functions
+
+ //member functions
+
+ _SelfSlider.$PlayTo = PlayTo;
+
+ _SelfSlider.$GoTo = function (slideIndex) {
+ ///
+ /// instance.$GoTo( slideIndex ); //Go to the specifed slide immediately with no play.
+ ///
+ PlayTo(slideIndex, 1);
+ };
+
+ _SelfSlider.$Next = function () {
+ ///
+ /// instance.$Next(); //Play the slider to next slide.
+ ///
+ PlayToOffset(1);
+ };
+
+ _SelfSlider.$Prev = function () {
+ ///
+ /// instance.$Prev(); //Play the slider to previous slide.
+ ///
+ PlayToOffset(-1);
+ };
+
+ _SelfSlider.$Pause = function () {
+ ///
+ /// instance.$Pause(); //Pause the slider, prevent it from auto playing.
+ ///
+ _AutoPlay = false;
+ };
+
+ _SelfSlider.$Play = function () {
+ ///
+ /// instance.$Play(); //Start auto play if the slider is currently paused.
+ ///
+ if (!_AutoPlay) {
+ _AutoPlay = true;
+ _SlideItems[_CurrentSlideIndex] && _SlideItems[_CurrentSlideIndex].$TryActivate();
+ }
+ };
+
+ _SelfSlider.$SetSlideshowTransitions = function (transitions) {
+ ///
+ /// instance.$SetSlideshowTransitions( transitions ); //Reset slideshow transitions for the slider.
+ ///
+ $JssorDebug$.$Execute(function () {
+ if (!transitions || !transitions.length) {
+ $JssorDebug$.$Error("Can not set slideshow transitions, no transitions specified.");
+ }
+ });
+
+ //$Jssor$.$TranslateTransitions(transitions); //for old transition compatibility
+ _Options.$SlideshowOptions.$Transitions = transitions;
+ };
+
+ _SelfSlider.$SetCaptionTransitions = function (transitions) {
+ ///
+ /// instance.$SetCaptionTransitions( transitions ); //Reset caption transitions for the slider.
+ ///
+ $JssorDebug$.$Execute(function () {
+ if (!transitions || !transitions.length) {
+ $JssorDebug$.$Error("Can not set caption transitions, no transitions specified");
+ }
+ });
+
+ //$Jssor$.$TranslateTransitions(transitions); //for old transition compatibility
+ _CaptionSliderOptions.$CaptionTransitions = transitions;
+ _CaptionSliderOptions.$Version = $Jssor$.$GetNow();
+ };
+
+ _SelfSlider.$SlidesCount = function () {
+ ///
+ /// instance.$SlidesCount(); //Retrieve slides count of the slider.
+ ///
+ return _SlideElmts.length;
+ };
+
+ _SelfSlider.$CurrentIndex = function () {
+ ///
+ /// instance.$CurrentIndex(); //Retrieve current slide index of the slider.
+ ///
+ return _CurrentSlideIndex;
+ };
+
+ _SelfSlider.$IsAutoPlaying = function () {
+ ///
+ /// instance.$IsAutoPlaying(); //Retrieve auto play status of the slider.
+ ///
+ return _AutoPlay;
+ };
+
+ _SelfSlider.$IsDragging = function () {
+ ///
+ /// instance.$IsDragging(); //Retrieve drag status of the slider.
+ ///
+ return _IsDragging;
+ };
+
+ _SelfSlider.$IsSliding = function () {
+ ///
+ /// instance.$IsSliding(); //Retrieve right<-->left sliding status of the slider.
+ ///
+ return _IsSliding;
+ };
+
+ _SelfSlider.$IsMouseOver = function () {
+ ///
+ /// instance.$IsMouseOver(); //Retrieve mouse over status of the slider.
+ ///
+ return !_NotOnHover;
+ };
+
+ _SelfSlider.$LastDragSucceded = function () {
+ ///
+ /// instance.$IsLastDragSucceded(); //Retrieve last drag succeded status, returns 0 if failed, returns drag offset if succeded
+ ///
+ return _LastDragSucceded;
+ };
+
+ function OriginalWidth() {
+ ///
+ /// instance.$OriginalWidth(); //Retrieve original width of the slider.
+ ///
+ return $Jssor$.$CssWidth(_ScaleWrapper || elmt);
+ }
+
+ function OriginalHeight() {
+ ///
+ /// instance.$OriginalHeight(); //Retrieve original height of the slider.
+ ///
+ return $Jssor$.$CssHeight(_ScaleWrapper || elmt);
+ }
+
+ _SelfSlider.$OriginalWidth = _SelfSlider.$GetOriginalWidth = OriginalWidth;
+
+ _SelfSlider.$OriginalHeight = _SelfSlider.$GetOriginalHeight = OriginalHeight;
+
+ function Scale(dimension, isHeight) {
+ ///
+ /// instance.$ScaleWidth(); //Retrieve scaled dimension the slider currently displays.
+ /// instance.$ScaleWidth( dimension ); //Scale the slider to new width and keep aspect ratio.
+ ///
+
+ if (dimension == undefined)
+ return $Jssor$.$CssWidth(elmt);
+
+ if (!_ScaleWrapper) {
+ $JssorDebug$.$Execute(function () {
+ var originalWidthStr = $Jssor$.$Css(elmt, "width");
+ var originalHeightStr = $Jssor$.$Css(elmt, "height");
+ var originalWidth = $Jssor$.$CssP(elmt, "width");
+ var originalHeight = $Jssor$.$CssP(elmt, "height");
+
+ if (!originalWidthStr || originalWidthStr.indexOf("px") == -1) {
+ $JssorDebug$.$Fail("Cannot scale jssor slider, 'width' of 'outer container' not specified. Please specify 'width' in pixel. e.g. 'width: 600px;'");
+ }
+
+ if (!originalHeightStr || originalHeightStr.indexOf("px") == -1) {
+ $JssorDebug$.$Fail("Cannot scale jssor slider, 'height' of 'outer container' not specified. Please specify 'height' in pixel. e.g. 'height: 300px;'");
+ }
+
+ if (originalWidthStr.indexOf('%') != -1) {
+ $JssorDebug$.$Fail("Cannot scale jssor slider, 'width' of 'outer container' not valid. Please specify 'width' in pixel. e.g. 'width: 600px;'");
+ }
+
+ if (originalHeightStr.indexOf('%') != -1) {
+ $JssorDebug$.$Fail("Cannot scale jssor slider, 'height' of 'outer container' not valid. Please specify 'height' in pixel. e.g. 'height: 300px;'");
+ }
+
+ if (!originalWidth) {
+ $JssorDebug$.$Fail("Cannot scale jssor slider, 'width' of 'outer container' not valid. 'width' of 'outer container' should be positive number. e.g. 'width: 600px;'");
+ }
+
+ if (!originalHeight) {
+ $JssorDebug$.$Fail("Cannot scale jssor slider, 'height' of 'outer container' not valid. 'height' of 'outer container' should be positive number. e.g. 'height: 300px;'");
+ }
+ });
+
+ var innerWrapper = $Jssor$.$CreateDiv(document);
+ $Jssor$.$ClassName(innerWrapper, $Jssor$.$ClassName(elmt));
+ $Jssor$.$CssCssText(innerWrapper, $Jssor$.$CssCssText(elmt));
+ $Jssor$.$CssDisplay(innerWrapper, "block");
+
+ $Jssor$.$CssPosition(innerWrapper, "relative");
+ $Jssor$.$CssTop(innerWrapper, 0);
+ $Jssor$.$CssLeft(innerWrapper, 0);
+ $Jssor$.$CssOverflow(innerWrapper, "visible");
+
+ _ScaleWrapper = $Jssor$.$CreateDiv(document);
+
+ $Jssor$.$CssPosition(_ScaleWrapper, "absolute");
+ $Jssor$.$CssTop(_ScaleWrapper, 0);
+ $Jssor$.$CssLeft(_ScaleWrapper, 0);
+ $Jssor$.$CssWidth(_ScaleWrapper, $Jssor$.$CssWidth(elmt));
+ $Jssor$.$CssHeight(_ScaleWrapper, $Jssor$.$CssHeight(elmt));
+ $Jssor$.$SetStyleTransformOrigin(_ScaleWrapper, "0 0");
+
+ $Jssor$.$AppendChild(_ScaleWrapper, innerWrapper);
+
+ var children = $Jssor$.$Children(elmt);
+ $Jssor$.$AppendChild(elmt, _ScaleWrapper);
+
+ $Jssor$.$Css(elmt, "backgroundImage", "");
+
+ var noMoveElmts = {
+ "navigator": _BulletNavigatorOptions && _BulletNavigatorOptions.$Scale == false,
+ "arrowleft": _ArrowNavigatorOptions && _ArrowNavigatorOptions.$Scale == false,
+ "arrowright": _ArrowNavigatorOptions && _ArrowNavigatorOptions.$Scale == false,
+ "thumbnavigator": _ThumbnailNavigatorOptions && _ThumbnailNavigatorOptions.$Scale == false,
+ "thumbwrapper": _ThumbnailNavigatorOptions && _ThumbnailNavigatorOptions.$Scale == false
+ };
+
+ $Jssor$.$Each(children, function (child) {
+ $Jssor$.$AppendChild(noMoveElmts[$Jssor$.$AttributeEx(child, "u")] ? elmt : innerWrapper, child);
+ });
+ }
+
+ $JssorDebug$.$Execute(function () {
+ if (!dimension || dimension < 0) {
+ $JssorDebug$.$Fail("'$ScaleWidth' error, 'dimension' should be positive value.");
+ }
+ });
+
+ $JssorDebug$.$Execute(function () {
+ if (!_InitialScrollWidth) {
+ _InitialScrollWidth = _SelfSlider.$Elmt.scrollWidth;
+ }
+ });
+
+ _ScaleRatio = dimension / (isHeight ? $Jssor$.$CssHeight : $Jssor$.$CssWidth)(_ScaleWrapper);
+ $Jssor$.$CssScale(_ScaleWrapper, _ScaleRatio);
+
+ var scaleWidth = isHeight ? (_ScaleRatio * OriginalWidth()) : dimension;
+ var scaleHeight = isHeight ? dimension : (_ScaleRatio * OriginalHeight());
+
+ $Jssor$.$CssWidth(elmt, scaleWidth);
+ $Jssor$.$CssHeight(elmt, scaleHeight);
+
+ $Jssor$.$Each(_Navigators, function (navigator) {
+ navigator.$Relocate(scaleWidth, scaleHeight);
+ });
+ }
+
+ _SelfSlider.$ScaleHeight = _SelfSlider.$GetScaleHeight = function (height) {
+ ///
+ /// instance.$ScaleHeight(); //Retrieve scaled height the slider currently displays.
+ /// instance.$ScaleHeight( dimension ); //Scale the slider to new height and keep aspect ratio.
+ ///
+
+ if (height == undefined)
+ return $Jssor$.$CssHeight(elmt);
+
+ Scale(height, true);
+ };
+
+ _SelfSlider.$ScaleWidth = _SelfSlider.$SetScaleWidth = _SelfSlider.$GetScaleWidth = Scale;
+
+ _SelfSlider.$GetVirtualIndex = function (index) {
+ var parkingIndex = Math.ceil(GetRealIndex(_ParkingPosition / _StepLength));
+ var displayIndex = GetRealIndex(index - _CurrentSlideIndex + parkingIndex);
+
+ if (displayIndex > _DisplayPieces) {
+ if (index - _CurrentSlideIndex > _SlideCount / 2)
+ index -= _SlideCount;
+ else if (index - _CurrentSlideIndex <= -_SlideCount / 2)
+ index += _SlideCount;
+ }
+ else {
+ index = _CurrentSlideIndex + displayIndex - parkingIndex;
+ }
+
+ return index;
+ };
+
+ //member functions
+
+ $JssorObject$.call(_SelfSlider);
+
+ $JssorDebug$.$Execute(function () {
+ var outerContainerElmt = $Jssor$.$GetElement(elmt);
+ if (!outerContainerElmt)
+ $JssorDebug$.$Fail("Outer container '" + elmt + "' not found.");
+ });
+
+ //initialize member variables
+ _SelfSlider.$Elmt = elmt = $Jssor$.$GetElement(elmt);
+ //initialize member variables
+
+ var _InitialScrollWidth; //for debug only
+ var _CaptionSliderCount = 1; //for debug only
+
+ var _Options = $Jssor$.$Extend({
+ $FillMode: 0, //[Optional] The way to fill image in slide, 0 stretch, 1 contain (keep aspect ratio and put all inside slide), 2 cover (keep aspect ratio and cover whole slide), 4 actual size, 5 contain for large image, actual size for small image, default value is 0
+ $LazyLoading: 1, //[Optional] For image with lazy loading format ( ), by default it will be loaded only when the slide comes.
+ //But an integer value (maybe 0, 1, 2 or 3) indicates that how far of nearby slides should be loaded immediately as well, default value is 1.
+ $StartIndex: 0, //[Optional] Index of slide to display when initialize, default value is 0
+ $AutoPlay: false, //[Optional] Whether to auto play, default value is false
+ $Loop: 1, //[Optional] Enable loop(circular) of carousel or not, 0: stop, 1: loop, 2 rewind, default value is 1
+ $HWA: true, //[Optional] Enable hardware acceleration or not, default value is true
+ $NaviQuitDrag: true,
+ $AutoPlaySteps: 1, //[Optional] Steps to go of every play (this options applys only when slideshow disabled), default value is 1
+ $AutoPlayInterval: 3000, //[Optional] Interval to play next slide since the previous stopped if a slideshow is auto playing, default value is 3000
+ $PauseOnHover: 1, //[Optional] Whether to pause when mouse over if a slider is auto playing, 0 no pause, 1 pause for desktop, 2 pause for touch device, 3 pause for desktop and touch device, 4 freeze for desktop, 8 freeze for touch device, 12 freeze for desktop and touch device, default value is 1
+
+ $SlideDuration: 500, //[Optional] Specifies default duration (swipe) for slide in milliseconds, default value is 400
+ $SlideEasing: $JssorEasing$.$EaseOutQuad, //[Optional] Specifies easing for right to left animation, default value is $JssorEasing$.$EaseOutQuad
+ $MinDragOffsetToSlide: 20, //[Optional] Minimum drag offset that trigger slide, default value is 20
+ $SlideSpacing: 0, //[Optional] Space between each slide in pixels, default value is 0
+ $DisplayPieces: 1, //[Optional] Number of pieces to display (the slideshow would be disabled if the value is set to greater than 1), default value is 1
+ $ParkingPosition: 0, //[Optional] The offset position to park slide (this options applys only when slideshow disabled), default value is 0.
+ $UISearchMode: 1, //[Optional] The way (0 parellel, 1 recursive, default value is recursive) to search UI components (slides container, loading screen, navigator container, arrow navigator container, thumbnail navigator container etc.
+ $PlayOrientation: 1, //[Optional] Orientation to play slide (for auto play, navigation), 1 horizental, 2 vertical, 5 horizental reverse, 6 vertical reverse, default value is 1
+ $DragOrientation: 1 //[Optional] Orientation to drag slide, 0 no drag, 1 horizental, 2 vertical, 3 both, default value is 1 (Note that the $DragOrientation should be the same as $PlayOrientation when $DisplayPieces is greater than 1, or parking position is not 0)
+
+ }, options);
+
+ //Sodo statement for development time intellisence only
+ $JssorDebug$.$Execute(function () {
+ _Options = $Jssor$.$Extend({
+ $ArrowKeyNavigation: undefined,
+ $SlideWidth: undefined,
+ $SlideHeight: undefined,
+ $SlideshowOptions: undefined,
+ $CaptionSliderOptions: undefined,
+ $BulletNavigatorOptions: undefined,
+ $ArrowNavigatorOptions: undefined,
+ $ThumbnailNavigatorOptions: undefined
+ },
+ _Options);
+ });
+
+ var _PlayOrientation = _Options.$PlayOrientation & 3;
+ var _PlayReverse = (_Options.$PlayOrientation & 4) / -4 || 1;
+
+ var _SlideshowOptions = _Options.$SlideshowOptions;
+ var _CaptionSliderOptions = $Jssor$.$Extend({ $Class: $JssorCaptionSliderBase$, $PlayInMode: 1, $PlayOutMode: 1 }, _Options.$CaptionSliderOptions);
+ //$Jssor$.$TranslateTransitions(_CaptionSliderOptions.$CaptionTransitions); //for old transition compatibility
+ var _BulletNavigatorOptions = _Options.$BulletNavigatorOptions;
+ var _ArrowNavigatorOptions = _Options.$ArrowNavigatorOptions;
+ var _ThumbnailNavigatorOptions = _Options.$ThumbnailNavigatorOptions;
+
+ $JssorDebug$.$Execute(function () {
+ if (_SlideshowOptions && !_SlideshowOptions.$Class) {
+ $JssorDebug$.$Fail("Option $SlideshowOptions error, class not specified.");
+ }
+ });
+
+ $JssorDebug$.$Execute(function () {
+ if (_Options.$CaptionSliderOptions && !_Options.$CaptionSliderOptions.$Class) {
+ $JssorDebug$.$Fail("Option $CaptionSliderOptions error, class not specified.");
+ }
+ });
+
+ $JssorDebug$.$Execute(function () {
+ if (_BulletNavigatorOptions && !_BulletNavigatorOptions.$Class) {
+ $JssorDebug$.$Fail("Option $BulletNavigatorOptions error, class not specified.");
+ }
+ });
+
+ $JssorDebug$.$Execute(function () {
+ if (_ArrowNavigatorOptions && !_ArrowNavigatorOptions.$Class) {
+ $JssorDebug$.$Fail("Option $ArrowNavigatorOptions error, class not specified.");
+ }
+ });
+
+ $JssorDebug$.$Execute(function () {
+ if (_ThumbnailNavigatorOptions && !_ThumbnailNavigatorOptions.$Class) {
+ $JssorDebug$.$Fail("Option $ThumbnailNavigatorOptions error, class not specified.");
+ }
+ });
+
+ var _UISearchNoDeep = !_Options.$UISearchMode;
+ var _ScaleWrapper;
+ var _SlidesContainer = $Jssor$.$FindChild(elmt, "slides", _UISearchNoDeep);
+ var _LoadingContainer = $Jssor$.$FindChild(elmt, "loading", _UISearchNoDeep) || $Jssor$.$CreateDiv(document);
+
+ var _BulletNavigatorContainer = $Jssor$.$FindChild(elmt, "navigator", _UISearchNoDeep);
+
+ var _ArrowLeft = $Jssor$.$FindChild(elmt, "arrowleft", _UISearchNoDeep);
+ var _ArrowRight = $Jssor$.$FindChild(elmt, "arrowright", _UISearchNoDeep);
+
+ var _ThumbnailNavigatorContainer = $Jssor$.$FindChild(elmt, "thumbnavigator", _UISearchNoDeep);
+
+ $JssorDebug$.$Execute(function () {
+ //if (_BulletNavigatorOptions && !_BulletNavigatorContainer) {
+ // throw new Error("$BulletNavigatorOptions specified but bullet navigator container ( 1 && _Options.$DragOrientation && _Options.$DragOrientation != _PlayOrientation)
+ $JssorDebug$.$Fail("Option $DragOrientation error, it should be 0 or the same of $PlayOrientation when $DisplayPieces is greater than 1.");
+
+ if (!$Jssor$.$IsNumeric(_Options.$ParkingPosition))
+ $JssorDebug$.$Fail("Option $ParkingPosition error, it should be a numeric value.");
+
+ if (_Options.$ParkingPosition && _Options.$DragOrientation && _Options.$DragOrientation != _PlayOrientation)
+ $JssorDebug$.$Fail("Option $DragOrientation error, it should be 0 or the same of $PlayOrientation when $ParkingPosition is not equal to 0.");
+ });
+
+ var _StyleDef;
+
+ var _SlideElmts = [];
+
+ {
+ var slideElmts = $Jssor$.$Children(_SlidesContainer);
+ $Jssor$.$Each(slideElmts, function (slideElmt) {
+ if (slideElmt.tagName == "DIV" && !$Jssor$.$AttributeEx(slideElmt, "u")) {
+ _SlideElmts.push(slideElmt);
+ }
+ });
+ }
+
+ $JssorDebug$.$Execute(function () {
+ if (_SlideElmts.length < 1) {
+ $JssorDebug$.$Error("Slides html code definition error, there must be at least 1 slide to initialize a slider.");
+ }
+ });
+
+ var _SlideItemCreatedCount = 0; //for debug only
+ var _SlideItemReleasedCount = 0; //for debug only
+
+ var _PreviousSlideIndex;
+ var _CurrentSlideIndex = -1;
+ var _TempSlideIndex;
+ var _PrevSlideItem;
+ var _CurrentSlideItem;
+ var _SlideCount = _SlideElmts.length;
+
+ var _SlideWidth = _Options.$SlideWidth || _SlidesContainerWidth;
+ var _SlideHeight = _Options.$SlideHeight || _SlidesContainerHeight;
+
+ var _SlideSpacing = _Options.$SlideSpacing;
+ var _StepLengthX = _SlideWidth + _SlideSpacing;
+ var _StepLengthY = _SlideHeight + _SlideSpacing;
+ var _StepLength = (_PlayOrientation & 1) ? _StepLengthX : _StepLengthY;
+ var _DisplayPieces = Math.min(_Options.$DisplayPieces, _SlideCount);
+
+ var _SlideshowPanel;
+ var _CurrentBoardIndex = 0;
+ var _DragOrientation;
+ var _DragOrientationRegistered;
+ var _DragInvalid;
+
+ var _Navigators = [];
+ var _BulletNavigator;
+ var _ArrowNavigator;
+ var _ThumbnailNavigator;
+
+ var _ShowLink;
+
+ var _Frozen;
+ var _AutoPlay;
+ var _AutoPlaySteps = _Options.$AutoPlaySteps;
+ var _HoverToPause = _Options.$PauseOnHover;
+ var _AutoPlayInterval = _Options.$AutoPlayInterval;
+ var _SlideDuration = _Options.$SlideDuration;
+
+ var _SlideshowRunnerClass;
+ var _TransitionsOrder;
+
+ var _SlideshowEnabled;
+ var _ParkingPosition;
+ var _CarouselEnabled = _DisplayPieces < _SlideCount;
+ var _Loop = _CarouselEnabled ? _Options.$Loop : 0;
+
+ var _DragEnabled;
+ var _LastDragSucceded;
+
+ var _NotOnHover = 1; //0 Hovering, 1 Not hovering
+
+ //Variable Definition
+ var _IsSliding;
+ var _IsDragging;
+ var _LoadingTicket;
+
+ //The X position of mouse/touch when a drag start
+ var _DragStartMouseX = 0;
+ //The Y position of mouse/touch when a drag start
+ var _DragStartMouseY = 0;
+ var _DragOffsetTotal;
+ var _DragOffsetLastTime;
+ var _DragIndexAdjust;
+
+ var _Carousel;
+ var _Conveyor;
+ var _Slideshow;
+ var _CarouselPlayer;
+ var _SlideContainer = new SlideContainer();
+ var _ScaleRatio;
+
+ //$JssorSlider$ Constructor
+ {
+ _AutoPlay = _Options.$AutoPlay;
+ _SelfSlider.$Options = options;
+
+ AdjustSlidesContainerSize();
+
+ elmt["jssor-slider"] = true;
+
+ //_SlideshowPanel = CreatePanel();
+ //$Jssor$.$CssZIndex(elmt, $Jssor$.$CssZIndex(elmt));
+ //$Jssor$.$CssLeft(_SlideshowPanel, $Jssor$.$CssLeft(_SlidesContainer));
+ //$Jssor$.$CssZIndex(_SlidesContainer, $Jssor$.$CssZIndex(_SlidesContainer));
+ //$Jssor$.$CssTop(_SlideshowPanel, $Jssor$.$CssTop(_SlidesContainer));
+ $Jssor$.$CssZIndex(_SlidesContainer, $Jssor$.$CssZIndex(_SlidesContainer) || 0);
+ $Jssor$.$CssPosition(_SlidesContainer, "absolute");
+ _SlideshowPanel = $Jssor$.$CloneNode(_SlidesContainer, true);
+ $Jssor$.$InsertBefore(_SlideshowPanel, _SlidesContainer);
+
+ if (_SlideshowOptions) {
+ _ShowLink = _SlideshowOptions.$ShowLink;
+ _SlideshowRunnerClass = _SlideshowOptions.$Class;
+
+ $JssorDebug$.$Execute(function () {
+ if (!_SlideshowOptions.$Transitions || !_SlideshowOptions.$Transitions.length) {
+ $JssorDebug$.$Error("Invalid '$SlideshowOptions', no '$Transitions' specified.");
+ }
+ });
+
+ //$Jssor$.$TranslateTransitions(_SlideshowOptions.$Transitions); //for old transition compatibility
+
+ _SlideshowEnabled = _DisplayPieces == 1 && _SlideCount > 1 && _SlideshowRunnerClass && (!$Jssor$.$IsBrowserIE() || $Jssor$.$BrowserVersion() >= 8);
+ }
+
+ _ParkingPosition = (_SlideshowEnabled || _DisplayPieces >= _SlideCount || !(_Loop & 1)) ? 0 : _Options.$ParkingPosition;
+
+ _DragEnabled = ((_DisplayPieces > 1 || _ParkingPosition) ? _PlayOrientation : -1) & _Options.$DragOrientation;
+
+ //SlideBoard
+ var _SlideboardElmt = _SlidesContainer;
+ var _SlideItems = [];
+
+ var _SlideshowRunner;
+ var _LinkContainer;
+
+ var _Device = $Jssor$.$Device();
+ var _DownEvent = _Device.$Evt_Down;
+ var _MoveEvent = _Device.$Evt_Move;
+ var _UpEvent = _Device.$Evt_Up;
+ var _CancelEvent = _Device.$Evt_Cancel;
+
+ var _HandleTouchEventOnly = _Device.$TouchOnly;
+ var _IsTouchDevice = _Device.$Touchable;
+
+ var _LastTimeMoveByDrag;
+ var _Position_OnFreeze;
+ var _CarouselPlaying_OnFreeze;
+ var _PlayToPosition_OnFreeze;
+ var _PositionToGoByDrag;
+
+ //SlideBoard Constructor
+ {
+ if (_Device.$TouchActionAttr) {
+ if (_DragEnabled) {
+ var touchAction = "auto";
+ if (_DragEnabled == 2) {
+ touchAction = "pan-x";
+ }
+ else if (_DragEnabled) {
+ touchAction = "pan-y";
+ }
+
+ $Jssor$.$Css(_SlideboardElmt, _Device.$TouchActionAttr, touchAction);
+ }
+ }
+
+ _Slideshow = new Slideshow();
+
+ if (_SlideshowEnabled)
+ _SlideshowRunner = new _SlideshowRunnerClass(_SlideContainer, _SlideWidth, _SlideHeight, _SlideshowOptions, _IsTouchDevice);
+
+ $Jssor$.$AppendChild(_SlideshowPanel, _Slideshow.$Wrapper);
+ $Jssor$.$CssOverflow(_SlidesContainer, "hidden");
+
+ //link container
+ {
+ _LinkContainer = CreatePanel();
+ $Jssor$.$Css(_LinkContainer, "backgroundColor", "#000");
+ $Jssor$.$CssOpacity(_LinkContainer, 0);
+ $Jssor$.$InsertBefore(_LinkContainer, _SlideboardElmt.firstChild, _SlideboardElmt);
+ }
+
+ for (var i = 0; i < _SlideElmts.length; i++) {
+ var slideElmt = _SlideElmts[i];
+ var slideItem = new SlideItem(slideElmt, i);
+ _SlideItems.push(slideItem);
+ }
+
+ $Jssor$.$HideElement(_LoadingContainer);
+
+ $JssorDebug$.$Execute(function () {
+ $Jssor$.$Attribute(_LoadingContainer, "debug-id", "loading-container");
+ });
+
+ _Carousel = new Carousel()
+ _CarouselPlayer = new CarouselPlayer(_Carousel, _Slideshow);
+
+ $JssorDebug$.$Execute(function () {
+ $Jssor$.$Attribute(_SlideboardElmt, "debug-id", "slide-board");
+ });
+
+ if (_DragEnabled) {
+ $Jssor$.$AddEvent(_SlidesContainer, _DownEvent, OnMouseDown);
+ $Jssor$.$AddEvent(_SlidesContainer, "dragstart", PreventDragStart);
+ $Jssor$.$AddEvent(document, _UpEvent, OnDragEnd);
+ _CancelEvent && $Jssor$.$AddEvent(document, _CancelEvent, OnDragEnd);
+ }
+ }
+ //SlideBoard
+
+ _HoverToPause &= (_IsTouchDevice ? 10 : 5);
+
+ //Bullet Navigator
+ if (_BulletNavigatorContainer && _BulletNavigatorOptions) {
+ _BulletNavigator = new _BulletNavigatorOptions.$Class(_BulletNavigatorContainer, _BulletNavigatorOptions, OriginalWidth(), OriginalHeight());
+ _Navigators.push(_BulletNavigator);
+ }
+
+ //Arrow Navigator
+ if (_ArrowNavigatorOptions && _ArrowLeft && _ArrowRight) {
+ _ArrowNavigatorOptions.$Loop = _Loop;
+ _ArrowNavigatorOptions.$DisplayPieces = _DisplayPieces;
+ _ArrowNavigator = new _ArrowNavigatorOptions.$Class(_ArrowLeft, _ArrowRight, _ArrowNavigatorOptions, OriginalWidth(), OriginalHeight());
+ _Navigators.push(_ArrowNavigator);
+ }
+
+ //Thumbnail Navigator
+ if (_ThumbnailNavigatorContainer && _ThumbnailNavigatorOptions) {
+ _ThumbnailNavigatorOptions.$StartIndex = _Options.$StartIndex;
+ _ThumbnailNavigator = new _ThumbnailNavigatorOptions.$Class(_ThumbnailNavigatorContainer, _ThumbnailNavigatorOptions);
+ _Navigators.push(_ThumbnailNavigator);
+ }
+
+ $Jssor$.$Each(_Navigators, function (navigator) {
+ navigator.$Reset(_SlideCount, _SlideItems, _LoadingContainer);
+ navigator.$On($JssorNavigatorEvents$.$NAVIGATIONREQUEST, NavigationClickHandler);
+ });
+
+ Scale(OriginalWidth());
+
+ $Jssor$.$AddEvent(elmt, "mouseout", $Jssor$.$MouseOverOutFilter(MainContainerMouseLeaveEventHandler, elmt));
+ $Jssor$.$AddEvent(elmt, "mouseover", $Jssor$.$MouseOverOutFilter(MainContainerMouseEnterEventHandler, elmt));
+
+ ShowNavigators();
+
+ //Keyboard Navigation
+ if (_Options.$ArrowKeyNavigation) {
+ $Jssor$.$AddEvent(document, "keydown", function (e) {
+ if (e.keyCode == $JssorKeyCode$.$LEFT) {
+ //Arrow Left
+ PlayToOffset(-1);
+ }
+ else if (e.keyCode == $JssorKeyCode$.$RIGHT) {
+ //Arrow Right
+ PlayToOffset(1);
+ }
+ });
+ }
+
+ var startPosition = _Options.$StartIndex;
+ if (!(_Loop & 1)) {
+ startPosition = Math.max(0, Math.min(startPosition, _SlideCount - _DisplayPieces));
+ }
+ _CarouselPlayer.$PlayCarousel(startPosition, startPosition, 0);
+ }
+};
+var $JssorSlideo$ = window.$JssorSlideo$ = $JssorSlider$;
+
+$JssorSlider$.$EVT_CLICK = 21;
+$JssorSlider$.$EVT_DRAG_START = 22;
+$JssorSlider$.$EVT_DRAG_END = 23;
+$JssorSlider$.$EVT_SWIPE_START = 24;
+$JssorSlider$.$EVT_SWIPE_END = 25;
+
+$JssorSlider$.$EVT_LOAD_START = 26;
+$JssorSlider$.$EVT_LOAD_END = 27;
+$JssorSlider$.$EVT_FREEZE = 28;
+
+$JssorSlider$.$EVT_POSITION_CHANGE = 202;
+$JssorSlider$.$EVT_PARK = 203;
+
+$JssorSlider$.$EVT_SLIDESHOW_START = 206;
+$JssorSlider$.$EVT_SLIDESHOW_END = 207;
+
+$JssorSlider$.$EVT_PROGRESS_CHANGE = 208;
+$JssorSlider$.$EVT_STATE_CHANGE = 209;
+$JssorSlider$.$EVT_ROLLBACK_START = 210;
+$JssorSlider$.$EVT_ROLLBACK_END = 211;
+
+//(function ($) {
+// jQuery.fn.jssorSlider = function (options) {
+// return this.each(function () {
+// return $(this).data('jssorSlider') || $(this).data('jssorSlider', new $JssorSlider$(this, options));
+// });
+// };
+//})(jQuery);
+
+//window.jQuery && (jQuery.fn.jssorSlider = function (options) {
+// return this.each(function () {
+// return jQuery(this).data('jssorSlider') || jQuery(this).data('jssorSlider', new $JssorSlider$(this, options));
+// });
+//});
+
+//$JssorBulletNavigator$
+var $JssorNavigatorEvents$ = {
+ $NAVIGATIONREQUEST: 1,
+ $INDEXCHANGE: 2,
+ $RESET: 3
+};
+
+var $JssorBulletNavigator$ = window.$JssorBulletNavigator$ = function (elmt, options, containerWidth, containerHeight) {
+ var self = this;
+ $JssorObject$.call(self);
+
+ elmt = $Jssor$.$GetElement(elmt);
+
+ var _Count;
+ var _Length;
+ var _Width;
+ var _Height;
+ var _CurrentIndex;
+ var _CurrentInnerIndex = 0;
+ var _Options;
+ var _Steps;
+ var _Lanes;
+ var _SpacingX;
+ var _SpacingY;
+ var _Orientation;
+ var _ItemPrototype;
+ var _PrototypeWidth;
+ var _PrototypeHeight;
+
+ var _ButtonElements = [];
+ var _Buttons = [];
+
+ function Highlight(index) {
+ if (index != -1)
+ _Buttons[index].$Selected(index == _CurrentInnerIndex);
+ }
+
+ function OnNavigationRequest(index) {
+ self.$TriggerEvent($JssorNavigatorEvents$.$NAVIGATIONREQUEST, index * _Steps);
+ }
+
+ self.$Elmt = elmt;
+ self.$GetCurrentIndex = function () {
+ return _CurrentIndex;
+ };
+
+ self.$SetCurrentIndex = function (index) {
+ if (index != _CurrentIndex) {
+ var lastInnerIndex = _CurrentInnerIndex;
+ var innerIndex = Math.floor(index / _Steps);
+ _CurrentInnerIndex = innerIndex;
+ _CurrentIndex = index;
+
+ Highlight(lastInnerIndex);
+ Highlight(innerIndex);
+
+ //self.$TriggerEvent($JssorNavigatorEvents$.$INDEXCHANGE, index);
+ }
+ };
+
+ self.$Show = function (hide) {
+ $Jssor$.$ShowElement(elmt, hide);
+ };
+
+ var _Located;
+ self.$Relocate = function (containerWidth, containerHeight) {
+ if (!_Located || _Options.$Scale == false) {
+ if (_Options.$AutoCenter & 1) {
+ $Jssor$.$CssLeft(elmt, (containerWidth - _Width) / 2);
+ }
+ if (_Options.$AutoCenter & 2) {
+ $Jssor$.$CssTop(elmt, (containerHeight - _Height) / 2);
+ }
+
+ _Located = true;
+ }
+ };
+
+ var _Initialized;
+ self.$Reset = function (length) {
+ if (!_Initialized) {
+ _Length = length;
+ _Count = Math.ceil(length / _Steps);
+ _CurrentInnerIndex = 0;
+
+ var itemOffsetX = _PrototypeWidth + _SpacingX;
+ var itemOffsetY = _PrototypeHeight + _SpacingY;
+
+ var maxIndex = Math.ceil(_Count / _Lanes) - 1;
+
+ _Width = _PrototypeWidth + itemOffsetX * (!_Orientation ? maxIndex : _Lanes - 1);
+ _Height = _PrototypeHeight + itemOffsetY * (_Orientation ? maxIndex : _Lanes - 1);
+
+ $Jssor$.$CssWidth(elmt, _Width);
+ $Jssor$.$CssHeight(elmt, _Height);
+
+ for (var buttonIndex = 0; buttonIndex < _Count; buttonIndex++) {
+
+ var numberDiv = $Jssor$.$CreateSpan();
+ $Jssor$.$InnerText(numberDiv, buttonIndex + 1);
+
+ var div = $Jssor$.$BuildElement(_ItemPrototype, "numbertemplate", numberDiv, true);
+ $Jssor$.$CssPosition(div, "absolute");
+
+ var columnIndex = buttonIndex % (maxIndex + 1);
+ $Jssor$.$CssLeft(div, !_Orientation ? itemOffsetX * columnIndex : buttonIndex % _Lanes * itemOffsetX);
+ $Jssor$.$CssTop(div, _Orientation ? itemOffsetY * columnIndex : Math.floor(buttonIndex / (maxIndex + 1)) * itemOffsetY);
+
+ $Jssor$.$AppendChild(elmt, div);
+ _ButtonElements[buttonIndex] = div;
+
+ if (_Options.$ActionMode & 1)
+ $Jssor$.$AddEvent(div, "click", $Jssor$.$CreateCallback(null, OnNavigationRequest, buttonIndex));
+
+ if (_Options.$ActionMode & 2)
+ $Jssor$.$AddEvent(div, "mouseover", $Jssor$.$MouseOverOutFilter($Jssor$.$CreateCallback(null, OnNavigationRequest, buttonIndex), div));
+
+ _Buttons[buttonIndex] = $Jssor$.$Buttonize(div);
+ }
+
+ //self.$TriggerEvent($JssorNavigatorEvents$.$RESET);
+ _Initialized = true;
+ }
+ };
+
+ //JssorBulletNavigator Constructor
+ {
+ self.$Options = _Options = $Jssor$.$Extend({
+ $SpacingX: 0,
+ $SpacingY: 0,
+ $Orientation: 1,
+ $ActionMode: 1
+ }, options);
+
+ //Sodo statement for development time intellisence only
+ $JssorDebug$.$Execute(function () {
+ _Options = $Jssor$.$Extend({
+ $Steps: undefined,
+ $Lanes: undefined
+ }, _Options);
+ });
+
+ _ItemPrototype = $Jssor$.$FindChild(elmt, "prototype");
+
+ $JssorDebug$.$Execute(function () {
+ if (!_ItemPrototype)
+ $JssorDebug$.$Fail("Navigator item prototype not defined.");
+
+ if (isNaN($Jssor$.$CssWidth(_ItemPrototype))) {
+ $JssorDebug$.$Fail("Width of 'navigator item prototype' not specified.");
+ }
+
+ if (isNaN($Jssor$.$CssHeight(_ItemPrototype))) {
+ $JssorDebug$.$Fail("Height of 'navigator item prototype' not specified.");
+ }
+ });
+
+ _PrototypeWidth = $Jssor$.$CssWidth(_ItemPrototype);
+ _PrototypeHeight = $Jssor$.$CssHeight(_ItemPrototype);
+
+ $Jssor$.$RemoveElement(_ItemPrototype, elmt);
+
+ _Steps = _Options.$Steps || 1;
+ _Lanes = _Options.$Lanes || 1;
+ _SpacingX = _Options.$SpacingX;
+ _SpacingY = _Options.$SpacingY;
+ _Orientation = _Options.$Orientation - 1;
+ }
+};
+
+var $JssorArrowNavigator$ = window.$JssorArrowNavigator$ = function (arrowLeft, arrowRight, options, containerWidth, containerHeight) {
+ var self = this;
+ $JssorObject$.call(self);
+
+ $JssorDebug$.$Execute(function () {
+
+ if (!arrowLeft)
+ $JssorDebug$.$Fail("Option '$ArrowNavigatorOptions' spepcified, but UI 'arrowleft' not defined. Define 'arrowleft' to enable direct navigation, or remove option '$ArrowNavigatorOptions' to disable direct navigation.");
+
+ if (!arrowRight)
+ $JssorDebug$.$Fail("Option '$ArrowNavigatorOptions' spepcified, but UI 'arrowright' not defined. Define 'arrowright' to enable direct navigation, or remove option '$ArrowNavigatorOptions' to disable direct navigation.");
+
+ if (isNaN($Jssor$.$CssWidth(arrowLeft))) {
+ $JssorDebug$.$Fail("Width of 'arrow left' not specified.");
+ }
+
+ if (isNaN($Jssor$.$CssWidth(arrowRight))) {
+ $JssorDebug$.$Fail("Width of 'arrow right' not specified.");
+ }
+
+ if (isNaN($Jssor$.$CssHeight(arrowLeft))) {
+ $JssorDebug$.$Fail("Height of 'arrow left' not specified.");
+ }
+
+ if (isNaN($Jssor$.$CssHeight(arrowRight))) {
+ $JssorDebug$.$Fail("Height of 'arrow right' not specified.");
+ }
+ });
+
+ var _Hide;
+ var _Length;
+ var _CurrentIndex;
+ var _Options;
+ var _Steps;
+ var _ArrowWidth = $Jssor$.$CssWidth(arrowLeft);
+ var _ArrowHeight = $Jssor$.$CssHeight(arrowLeft);
+
+ function OnNavigationRequest(steps) {
+ self.$TriggerEvent($JssorNavigatorEvents$.$NAVIGATIONREQUEST, steps, true);
+ }
+
+ function ShowArrows(hide) {
+ $Jssor$.$ShowElement(arrowLeft, hide || !options.$Loop && _CurrentIndex == 0);
+ $Jssor$.$ShowElement(arrowRight, hide || !options.$Loop && _CurrentIndex >= _Length - options.$DisplayPieces);
+
+ _Hide = hide;
+ }
+
+ self.$GetCurrentIndex = function () {
+ return _CurrentIndex;
+ };
+
+ self.$SetCurrentIndex = function (index, virtualIndex, temp) {
+ if (temp) {
+ _CurrentIndex = virtualIndex;
+ }
+ else {
+ _CurrentIndex = index;
+
+ ShowArrows(_Hide);
+ }
+ //self.$TriggerEvent($JssorNavigatorEvents$.$INDEXCHANGE, index);
+ };
+
+ self.$Show = ShowArrows;
+
+ var _Located;
+ self.$Relocate = function (conainerWidth, containerHeight) {
+ if (!_Located || _Options.$Scale == false) {
+
+ if (_Options.$AutoCenter & 1) {
+ $Jssor$.$CssLeft(arrowLeft, (containerWidth - _ArrowWidth) / 2);
+ $Jssor$.$CssLeft(arrowRight, (containerWidth - _ArrowWidth) / 2);
+ }
+
+ if (_Options.$AutoCenter & 2) {
+ $Jssor$.$CssTop(arrowLeft, (containerHeight - _ArrowHeight) / 2);
+ $Jssor$.$CssTop(arrowRight, (containerHeight - _ArrowHeight) / 2);
+ }
+
+ _Located = true;
+ }
+ };
+
+ var _Initialized;
+ self.$Reset = function (length) {
+ _Length = length;
+ _CurrentIndex = 0;
+
+ if (!_Initialized) {
+
+ $Jssor$.$AddEvent(arrowLeft, "click", $Jssor$.$CreateCallback(null, OnNavigationRequest, -_Steps));
+ $Jssor$.$AddEvent(arrowRight, "click", $Jssor$.$CreateCallback(null, OnNavigationRequest, _Steps));
+
+ $Jssor$.$Buttonize(arrowLeft);
+ $Jssor$.$Buttonize(arrowRight);
+
+ _Initialized = true;
+ }
+
+ //self.$TriggerEvent($JssorNavigatorEvents$.$RESET);
+ };
+
+ //JssorArrowNavigator Constructor
+ {
+ self.$Options = _Options = $Jssor$.$Extend({
+ $Steps: 1
+ }, options);
+
+ _Steps = _Options.$Steps;
+ }
+};
+
+//$JssorThumbnailNavigator$
+var $JssorThumbnailNavigator$ = window.$JssorThumbnailNavigator$ = function (elmt, options) {
+ var _Self = this;
+ var _Length;
+ var _Count;
+ var _CurrentIndex;
+ var _Options;
+ var _NavigationItems = [];
+
+ var _Width;
+ var _Height;
+ var _Lanes;
+ var _SpacingX;
+ var _SpacingY;
+ var _PrototypeWidth;
+ var _PrototypeHeight;
+ var _DisplayPieces;
+
+ var _Slider;
+ var _CurrentMouseOverIndex = -1;
+
+ var _SlidesContainer;
+ var _ThumbnailPrototype;
+
+ $JssorObject$.call(_Self);
+ elmt = $Jssor$.$GetElement(elmt);
+
+ function NavigationItem(item, index) {
+ var self = this;
+ var _Wrapper;
+ var _Button;
+ var _Thumbnail;
+
+ function Highlight(mouseStatus) {
+ _Button.$Selected(_CurrentIndex == index);
+ }
+
+ function OnNavigationRequest(event) {
+ if (!_Slider.$LastDragSucceded()) {
+ var tail = _Lanes - index % _Lanes;
+ var slideVirtualIndex = _Slider.$GetVirtualIndex((index + tail) / _Lanes - 1);
+ var itemVirtualIndex = slideVirtualIndex * _Lanes + _Lanes - tail;
+ _Self.$TriggerEvent($JssorNavigatorEvents$.$NAVIGATIONREQUEST, itemVirtualIndex);
+ }
+
+ //$JssorDebug$.$Log("navigation request");
+ }
+
+ $JssorDebug$.$Execute(function () {
+ self.$Wrapper = undefined;
+ });
+
+ self.$Index = index;
+
+ self.$Highlight = Highlight;
+
+ //NavigationItem Constructor
+ {
+ _Thumbnail = item.$Thumb || item.$Image || $Jssor$.$CreateDiv();
+ self.$Wrapper = _Wrapper = $Jssor$.$BuildElement(_ThumbnailPrototype, "thumbnailtemplate", _Thumbnail, true);
+
+ _Button = $Jssor$.$Buttonize(_Wrapper);
+ if (_Options.$ActionMode & 1)
+ $Jssor$.$AddEvent(_Wrapper, "click", OnNavigationRequest);
+ if (_Options.$ActionMode & 2)
+ $Jssor$.$AddEvent(_Wrapper, "mouseover", $Jssor$.$MouseOverOutFilter(OnNavigationRequest, _Wrapper));
+ }
+ }
+
+ _Self.$GetCurrentIndex = function () {
+ return _CurrentIndex;
+ };
+
+ _Self.$SetCurrentIndex = function (index, virtualIndex, temp) {
+ var oldIndex = _CurrentIndex;
+ _CurrentIndex = index;
+ if (oldIndex != -1)
+ _NavigationItems[oldIndex].$Highlight();
+ _NavigationItems[index].$Highlight();
+
+ if (!temp) {
+ _Slider.$PlayTo(_Slider.$GetVirtualIndex(Math.floor(virtualIndex / _Lanes)));
+ }
+ };
+
+ _Self.$Show = function (hide) {
+ $Jssor$.$ShowElement(elmt, hide);
+ };
+
+ _Self.$Relocate = $Jssor$.$EmptyFunction;
+
+ var _Initialized;
+ _Self.$Reset = function (length, items, loadingContainer) {
+ if (!_Initialized) {
+ _Length = length;
+ _Count = Math.ceil(_Length / _Lanes);
+ _CurrentIndex = -1;
+ _DisplayPieces = Math.min(_DisplayPieces, items.length);
+
+ var horizontal = _Options.$Orientation & 1;
+
+ var slideWidth = _PrototypeWidth + (_PrototypeWidth + _SpacingX) * (_Lanes - 1) * (1 - horizontal);
+ var slideHeight = _PrototypeHeight + (_PrototypeHeight + _SpacingY) * (_Lanes - 1) * horizontal;
+
+ var slidesContainerWidth = slideWidth + (slideWidth + _SpacingX) * (_DisplayPieces - 1) * horizontal;
+ var slidesContainerHeight = slideHeight + (slideHeight + _SpacingY) * (_DisplayPieces - 1) * (1 - horizontal);
+
+ $Jssor$.$CssPosition(_SlidesContainer, "absolute");
+ $Jssor$.$CssOverflow(_SlidesContainer, "hidden");
+ if (_Options.$AutoCenter & 1) {
+ $Jssor$.$CssLeft(_SlidesContainer, (_Width - slidesContainerWidth) / 2);
+ }
+ if (_Options.$AutoCenter & 2) {
+ $Jssor$.$CssTop(_SlidesContainer, (_Height - slidesContainerHeight) / 2);
+ }
+ //$JssorDebug$.$Execute(function () {
+ // if (!_Options.$AutoCenter) {
+ // var slidesContainerTop = $Jssor$.$CssTop(_SlidesContainer);
+ // var slidesContainerLeft = $Jssor$.$CssLeft(_SlidesContainer);
+
+ // if (isNaN(slidesContainerTop)) {
+ // $JssorDebug$.$Fail("Position 'top' wrong specification of thumbnail navigator slides container ( ... ), \r\nwhen option $ThumbnailNavigatorOptions.$AutoCenter set to 0, it should be specified in pixel (like )");
+ // }
+
+ // if (isNaN(slidesContainerLeft)) {
+ // $JssorDebug$.$Fail("Position 'left' wrong specification of thumbnail navigator slides container ( ... ), \r\nwhen option $ThumbnailNavigatorOptions.$AutoCenter set to 0, it should be specified in pixel (like )");
+ // }
+ // }
+ //});
+ $Jssor$.$CssWidth(_SlidesContainer, slidesContainerWidth);
+ $Jssor$.$CssHeight(_SlidesContainer, slidesContainerHeight);
+
+ var slideItemElmts = [];
+ $Jssor$.$Each(items, function (item, index) {
+ var navigationItem = new NavigationItem(item, index);
+ var navigationItemWrapper = navigationItem.$Wrapper;
+
+ var columnIndex = Math.floor(index / _Lanes);
+ var laneIndex = index % _Lanes;
+
+ $Jssor$.$CssLeft(navigationItemWrapper, (_PrototypeWidth + _SpacingX) * laneIndex * (1 - horizontal));
+ $Jssor$.$CssTop(navigationItemWrapper, (_PrototypeHeight + _SpacingY) * laneIndex * horizontal);
+
+ if (!slideItemElmts[columnIndex]) {
+ slideItemElmts[columnIndex] = $Jssor$.$CreateDiv();
+ $Jssor$.$AppendChild(_SlidesContainer, slideItemElmts[columnIndex]);
+ }
+
+ $Jssor$.$AppendChild(slideItemElmts[columnIndex], navigationItemWrapper);
+
+ _NavigationItems.push(navigationItem);
+ });
+
+ var thumbnailSliderOptions = $Jssor$.$Extend({
+ $HWA: false,
+ $AutoPlay: false,
+ $NaviQuitDrag: false,
+ $SlideWidth: slideWidth,
+ $SlideHeight: slideHeight,
+ $SlideSpacing: _SpacingX * horizontal + _SpacingY * (1 - horizontal),
+ $MinDragOffsetToSlide: 12,
+ $SlideDuration: 200,
+ $PauseOnHover: 1,
+ $PlayOrientation: _Options.$Orientation,
+ $DragOrientation: _Options.$DisableDrag ? 0 : _Options.$Orientation
+ }, _Options);
+
+ _Slider = new $JssorSlider$(elmt, thumbnailSliderOptions);
+
+ _Initialized = true;
+ }
+
+ //_Self.$TriggerEvent($JssorNavigatorEvents$.$RESET);
+ };
+
+ //JssorThumbnailNavigator Constructor
+ {
+ _Self.$Options = _Options = $Jssor$.$Extend({
+ $SpacingX: 3,
+ $SpacingY: 3,
+ $DisplayPieces: 1,
+ $Orientation: 1,
+ $AutoCenter: 3,
+ $ActionMode: 1
+ }, options);
+
+ //Sodo statement for development time intellisence only
+ $JssorDebug$.$Execute(function () {
+ _Options = $Jssor$.$Extend({
+ $Lanes: undefined,
+ $Width: undefined,
+ $Height: undefined
+ }, _Options);
+ });
+
+ _Width = $Jssor$.$CssWidth(elmt);
+ _Height = $Jssor$.$CssHeight(elmt);
+
+ $JssorDebug$.$Execute(function () {
+ if (!_Width)
+ $JssorDebug$.$Fail("width of 'thumbnavigator' container not specified.");
+ if (!_Height)
+ $JssorDebug$.$Fail("height of 'thumbnavigator' container not specified.");
+ });
+
+ _SlidesContainer = $Jssor$.$FindChild(elmt, "slides", true);
+ _ThumbnailPrototype = $Jssor$.$FindChild(_SlidesContainer, "prototype");
+
+ $JssorDebug$.$Execute(function () {
+ if (!_ThumbnailPrototype)
+ $JssorDebug$.$Fail("prototype of 'thumbnavigator' not defined.");
+ });
+
+ _PrototypeWidth = $Jssor$.$CssWidth(_ThumbnailPrototype);
+ _PrototypeHeight = $Jssor$.$CssHeight(_ThumbnailPrototype);
+
+ $Jssor$.$RemoveElement(_ThumbnailPrototype, _SlidesContainer);
+
+ _Lanes = _Options.$Lanes || 1;
+ _SpacingX = _Options.$SpacingX;
+ _SpacingY = _Options.$SpacingY;
+ _DisplayPieces = _Options.$DisplayPieces;
+ }
+};
+
+//$JssorCaptionSliderBase$
+function $JssorCaptionSliderBase$() {
+ $JssorAnimator$.call(this, 0, 0);
+ this.$Revert = $Jssor$.$EmptyFunction;
+}
+
+var $JssorCaptionSlider$ = window.$JssorCaptionSlider$ = function (container, captionSlideOptions, playIn) {
+ $JssorDebug$.$Execute(function () {
+ if (!captionSlideOptions.$CaptionTransitions) {
+ $JssorDebug$.$Error("'$CaptionSliderOptions' option error, '$CaptionSliderOptions.$CaptionTransitions' not specified.");
+ }
+ //else if (!$Jssor$.$IsArray(captionSlideOptions.$CaptionTransitions)) {
+ // $JssorDebug$.$Error("'$CaptionSliderOptions' option error, '$CaptionSliderOptions.$CaptionTransitions' is not an array.");
+ //}
+ });
+
+ var _Self = this;
+ var _ImmediateOutCaptionHanger;
+ var _PlayMode = playIn ? captionSlideOptions.$PlayInMode : captionSlideOptions.$PlayOutMode;
+
+ var _CaptionTransitions = captionSlideOptions.$CaptionTransitions;
+ var _CaptionTuningFetcher = { $Transition: "t", $Delay: "d", $Duration: "du", x: "x", y: "y", $Rotate: "r", $Zoom: "z", $Opacity: "f", $BeginTime: "b" };
+ var _CaptionTuningTransfer = {
+ $Default: function (value, tuningValue) {
+ if (!isNaN(tuningValue.$Value))
+ value = tuningValue.$Value;
+ else
+ value *= tuningValue.$Percent;
+
+ return value;
+ },
+ $Opacity: function (value, tuningValue) {
+ return this.$Default(value - 1, tuningValue);
+ }
+ };
+ _CaptionTuningTransfer.$Zoom = _CaptionTuningTransfer.$Opacity;
+
+ $JssorAnimator$.call(_Self, 0, 0);
+
+ function GetCaptionItems(element, level) {
+
+ var itemsToPlay = [];
+ var lastTransitionName;
+ var namedTransitions = [];
+ var namedTransitionOrders = [];
+
+ //$JssorDebug$.$Execute(function () {
+
+ // var debugInfoElement = $Jssor$.$GetElement("debugInfo");
+
+ // if (debugInfoElement && playIn) {
+
+ // var text = $Jssor.$InnerHtml(debugInfoElement) + " ";
+
+ // $Jssor$.$InnerHtml(debugInfoElement, text);
+ // }
+ //});
+
+ function FetchRawTransition(captionElmt, index) {
+ var rawTransition = {};
+
+ $Jssor$.$Each(_CaptionTuningFetcher, function (fetchAttribute, fetchProperty) {
+ var attributeValue = $Jssor$.$AttributeEx(captionElmt, fetchAttribute + (index || ""));
+ if (attributeValue) {
+ var propertyValue = {};
+
+ if (fetchAttribute == "t") {
+ //if (($Jssor$.$IsBrowserChrome() || $Jssor$.$IsBrowserSafari() || $Jssor$.$IsBrowserFireFox()) && attributeValue == "*") {
+ // attributeValue = Math.floor(Math.random() * captionSlideOptions.$CaptionTransitions.length);
+ // $Jssor$.$Attribute(captionElmt, fetchAttribute + (index || ""), attributeValue);
+ //}
+
+ propertyValue.$Value = attributeValue;
+ }
+ else if (attributeValue.indexOf("%") + 1)
+ propertyValue.$Percent = $Jssor$.$ParseFloat(attributeValue) / 100;
+ else
+ propertyValue.$Value = $Jssor$.$ParseFloat(attributeValue);
+
+ rawTransition[fetchProperty] = propertyValue;
+ }
+ });
+
+ return rawTransition;
+ }
+
+ function GetRandomTransition() {
+ return _CaptionTransitions[Math.floor(Math.random() * _CaptionTransitions.length)];
+ }
+
+ function EvaluateCaptionTransition(transitionName) {
+
+ var transition;
+
+ if (transitionName == "*") {
+ transition = GetRandomTransition();
+ }
+ else if (transitionName) {
+
+ //indexed transition allowed, just the same as named transition
+ var tempTransition = _CaptionTransitions[$Jssor$.$ParseInt(transitionName)] || _CaptionTransitions[transitionName];
+
+ if ($Jssor$.$IsArray(tempTransition)) {
+ if (transitionName != lastTransitionName) {
+ lastTransitionName = transitionName;
+ namedTransitionOrders[transitionName] = 0;
+
+ namedTransitions[transitionName] = tempTransition[Math.floor(Math.random() * tempTransition.length)];
+ }
+ else {
+ namedTransitionOrders[transitionName]++;
+ }
+
+ tempTransition = namedTransitions[transitionName];
+
+ if ($Jssor$.$IsArray(tempTransition)) {
+ tempTransition = tempTransition.length && tempTransition[namedTransitionOrders[transitionName] % tempTransition.length];
+
+ if ($Jssor$.$IsArray(tempTransition)) {
+ //got transition from array level 3, random for all captions
+ tempTransition = tempTransition[Math.floor(Math.random() * tempTransition.length)];
+ }
+ //else {
+ // //got transition from array level 2, in sequence for all adjacent captions with same name specified
+ // transition = tempTransition;
+ //}
+ }
+ //else {
+ // //got transition from array level 1, random but same for all adjacent captions with same name specified
+ // transition = tempTransition;
+ //}
+ }
+ //else {
+ // //got transition directly from a simple transition object
+ // transition = tempTransition;
+ //}
+
+ transition = tempTransition;
+
+ if ($Jssor$.$IsString(transition))
+ transition = EvaluateCaptionTransition(transition);
+ }
+
+ return transition;
+ }
+
+ var captionElmts = $Jssor$.$Children(element);
+ $Jssor$.$Each(captionElmts, function (captionElmt, i) {
+
+ var transitionsWithTuning = [];
+ transitionsWithTuning.$Elmt = captionElmt;
+ var isCaption = $Jssor$.$AttributeEx(captionElmt, "u") == "caption";
+
+ $Jssor$.$Each(playIn ? [0, 3] : [2], function (j, k) {
+
+ if (isCaption) {
+ var transition;
+ var rawTransition;
+
+ if (j != 2 || !$Jssor$.$AttributeEx(captionElmt, "t3")) {
+ rawTransition = FetchRawTransition(captionElmt, j);
+
+ if (j == 2 && !rawTransition.$Transition) {
+ rawTransition.$Delay = rawTransition.$Delay || { $Value: 0 };
+ rawTransition = $Jssor$.$Extend(FetchRawTransition(captionElmt, 0), rawTransition);
+ }
+ }
+
+ if (rawTransition && rawTransition.$Transition) {
+
+ transition = EvaluateCaptionTransition(rawTransition.$Transition.$Value);
+
+ if (transition) {
+
+ //var transitionWithTuning = $Jssor$.$Extend({ $Delay: 0, $ScaleHorizontal: 1, $ScaleVertical: 1 }, transition);
+ var transitionWithTuning = $Jssor$.$Extend({ $Delay: 0 }, transition);
+
+ $Jssor$.$Each(rawTransition, function (rawPropertyValue, propertyName) {
+ var tuningPropertyValue = (_CaptionTuningTransfer[propertyName] || _CaptionTuningTransfer.$Default).apply(_CaptionTuningTransfer, [transitionWithTuning[propertyName], rawTransition[propertyName]]);
+ if (!isNaN(tuningPropertyValue))
+ transitionWithTuning[propertyName] = tuningPropertyValue;
+ });
+
+ if (!k) {
+ if (rawTransition.$BeginTime)
+ transitionWithTuning.$BeginTime = rawTransition.$BeginTime.$Value || 0;
+ else if ((_PlayMode) & 2)
+ transitionWithTuning.$BeginTime = 0;
+ }
+ }
+ }
+
+ transitionsWithTuning.push(transitionWithTuning);
+ }
+
+ if ((level % 2) && !k) {
+ //transitionsWithTuning.$Children = GetCaptionItems(captionElmt, lastTransitionName, [].concat(namedTransitions), [].concat(namedTransitionOrders), level + 1);
+ transitionsWithTuning.$Children = GetCaptionItems(captionElmt, level + 1);
+ }
+ });
+
+ itemsToPlay.push(transitionsWithTuning);
+ });
+
+ return itemsToPlay;
+ }
+
+ function CreateAnimator(item, transition, immediateOut) {
+
+ var animatorOptions = {
+ $Easing: transition.$Easing,
+ $Round: transition.$Round,
+ $During: transition.$During,
+ $Reverse: playIn && !immediateOut//,
+ //$Optimize: true
+ };
+
+ $JssorDebug$.$Execute(function () {
+ animatorOptions.$CaptionAnimator = true;
+ });
+
+ var captionItem = item;
+ var captionParent = $Jssor$.$ParentNode(item);
+
+ var captionItemWidth = $Jssor$.$CssWidth(captionItem);
+ var captionItemHeight = $Jssor$.$CssHeight(captionItem);
+ var captionParentWidth = $Jssor$.$CssWidth(captionParent);
+ var captionParentHeight = $Jssor$.$CssHeight(captionParent);
+
+ //var toStyles = {};
+ var fromStyles = {};
+ var difStyles = {};
+ var scaleClip = transition.$ScaleClip || 1;
+
+ //Opacity
+ if (transition.$Opacity) {
+ ///toStyles.$Opacity = 2 - transition.$Opacity;
+ difStyles.$Opacity = 1 - transition.$Opacity;
+ }
+
+ animatorOptions.$OriginalWidth = captionItemWidth;
+ animatorOptions.$OriginalHeight = captionItemHeight;
+
+ //Transform
+ if (transition.$Zoom || transition.$Rotate) {
+ //toStyles.$Zoom = transition.$Zoom ? transition.$Zoom - 1 : 1;
+ difStyles.$Zoom = (transition.$Zoom || 2) - 2;
+
+ if ($Jssor$.$IsBrowserIe9Earlier() || $Jssor$.$IsBrowserOpera()) {
+ //toStyles.$Zoom = Math.min(toStyles.$Zoom, 2);
+ difStyles.$Zoom = Math.min(difStyles.$Zoom, 1);
+ }
+
+ fromStyles.$Zoom = 1;
+
+ var rotate = transition.$Rotate || 0;
+
+ //toStyles.$Rotate = rotate * 360;
+ difStyles.$Rotate = rotate * 360;
+ fromStyles.$Rotate = 0;
+ }
+ //Clip
+ else if (transition.$Clip) {
+ var fromStyleClip = { $Top: 0, $Right: captionItemWidth, $Bottom: captionItemHeight, $Left: 0 };
+ var toStyleClip = $Jssor$.$Extend({}, fromStyleClip);
+
+ var blockOffset = toStyleClip.$Offset = {};
+
+ var topBenchmark = transition.$Clip & 4;
+ var bottomBenchmark = transition.$Clip & 8;
+ var leftBenchmark = transition.$Clip & 1;
+ var rightBenchmark = transition.$Clip & 2;
+
+ if (topBenchmark && bottomBenchmark) {
+ blockOffset.$Top = captionItemHeight / 2 * scaleClip;
+ blockOffset.$Bottom = -blockOffset.$Top;
+ }
+ else if (topBenchmark)
+ blockOffset.$Bottom = -captionItemHeight * scaleClip;
+ else if (bottomBenchmark)
+ blockOffset.$Top = captionItemHeight * scaleClip;
+
+ if (leftBenchmark && rightBenchmark) {
+ blockOffset.$Left = captionItemWidth / 2 * scaleClip;
+ blockOffset.$Right = -blockOffset.$Left;
+ }
+ else if (leftBenchmark)
+ blockOffset.$Right = -captionItemWidth * scaleClip;
+ else if (rightBenchmark)
+ blockOffset.$Left = captionItemWidth * scaleClip;
+
+ animatorOptions.$Move = transition.$Move;
+ //toStyles.$Clip = toStyleClip;
+ difStyles.$Clip = toStyleClip;
+ fromStyles.$Clip = fromStyleClip;
+ }
+
+ //Fly
+ {
+ var toLeft = 0;
+ var toTop = 0;
+
+ if (transition.x)
+ toLeft -= captionParentWidth * transition.x;
+
+ if (transition.y)
+ toTop -= captionParentHeight * transition.y;
+
+ if (toLeft || toTop || animatorOptions.$Move) {
+ //toStyles.$Left = toLeft + $Jssor$.$CssLeft(captionItem);
+ //toStyles.$Top = toTop + $Jssor$.$CssTop(captionItem);
+ difStyles.$Left = toLeft;
+ difStyles.$Top = toTop;
+ }
+ }
+
+ //duration
+ var duration = transition.$Duration;
+
+ fromStyles = $Jssor$.$Extend(fromStyles, $Jssor$.$GetStyles(captionItem, difStyles));
+
+ animatorOptions.$Setter = $Jssor$.$StyleSetterEx();
+
+ return new $JssorAnimator$(transition.$Delay, duration, animatorOptions, captionItem, fromStyles, difStyles);
+ }
+
+ function CreateAnimators(streamLineLength, captionItems) {
+
+ $Jssor$.$Each(captionItems, function (captionItem, i) {
+
+ $JssorDebug$.$Execute(function () {
+ if (captionItem.length) {
+ var top = $Jssor$.$CssTop(captionItem.$Elmt);
+ var left = $Jssor$.$CssLeft(captionItem.$Elmt);
+ var width = $Jssor$.$CssWidth(captionItem.$Elmt);
+ var height = $Jssor$.$CssHeight(captionItem.$Elmt);
+
+ var error = null;
+
+ if (isNaN(top))
+ error = "Style 'top' for caption not specified. Please always specify caption like 'position: absolute; top: ...px; left: ...px; width: ...px; height: ...px;'.";
+ else if (isNaN(left))
+ error = "Style 'left' not specified. Please always specify caption like 'position: absolute; top: ...px; left: ...px; width: ...px; height: ...px;'.";
+ else if (isNaN(width))
+ error = "Style 'width' not specified. Please always specify caption like 'position: absolute; top: ...px; left: ...px; width: ...px; height: ...px;'.";
+ else if (isNaN(height))
+ error = "Style 'height' not specified. Please always specify caption like 'position: absolute; top: ...px; left: ...px; width: ...px; height: ...px;'.";
+
+ if (error)
+ $JssorDebug$.$Error("Caption " + (i + 1) + " definition error, \r\n" + error + "\r\n" + captionItem.$Elmt.outerHTML);
+ }
+ });
+
+ var animator;
+ var captionElmt = captionItem.$Elmt;
+ var transition = captionItem[0];
+ var transition3 = captionItem[1];
+
+ if (transition) {
+
+ animator = CreateAnimator(captionElmt, transition);
+ streamLineLength = animator.$Locate(transition.$BeginTime == undefined ? streamLineLength : transition.$BeginTime, 1);
+ }
+
+ streamLineLength = CreateAnimators(streamLineLength, captionItem.$Children);
+
+ if (transition3) {
+ var animator3 = CreateAnimator(captionElmt, transition3, 1);
+ animator3.$Locate(streamLineLength, 1);
+ _Self.$Combine(animator3);
+ _ImmediateOutCaptionHanger.$Combine(animator3);
+ }
+
+ if (animator)
+ _Self.$Combine(animator);
+ });
+
+ return streamLineLength;
+ }
+
+ _Self.$Revert = function () {
+ _Self.$GoToPosition(_Self.$GetPosition_OuterEnd() * (playIn || 0));
+ _ImmediateOutCaptionHanger.$GoToBegin();
+ };
+
+ //Constructor
+ {
+ _ImmediateOutCaptionHanger = new $JssorAnimator$(0, 0);
+
+ //var streamLineLength = 0;
+ //var captionItems = GetCaptionItems(container, null, [], [], 1);
+
+ CreateAnimators(0, _PlayMode ? GetCaptionItems(container, 1) : []);
+ }
+};
+
+var $JssorCaptionSlideo$ = window.$JssorCaptionSlideo$ = function (container, captionSlideoOptions, playIn) {
+ $JssorDebug$.$Execute(function () {
+ if (!captionSlideoOptions.$CaptionTransitions) {
+ $JssorDebug$.$Error("'$CaptionSlideoOptions' option error, '$CaptionSlideoOptions.$CaptionTransitions' not specified.");
+ }
+ else if (!$Jssor$.$IsArray(captionSlideoOptions.$CaptionTransitions)) {
+ $JssorDebug$.$Error("'$CaptionSlideoOptions' option error, '$CaptionSlideoOptions.$CaptionTransitions' is not an array.");
+ }
+ });
+
+ var _This = this;
+
+ var _CaptionTransitions = captionSlideoOptions.$CaptionTransitions;
+
+ $JssorAnimator$.call(_This, 0, 0);
+
+ function GetCaptionItems(element, level) {
+
+ var itemsToPlay = [];
+
+ var captionElmts = $Jssor$.$Children(element);
+ $Jssor$.$Each(captionElmts, function (captionElmt, i) {
+ var isCaption = $Jssor$.$AttributeEx(captionElmt, "u") == "caption";
+ if (isCaption) {
+ var transitionName = $Jssor$.$AttributeEx(captionElmt, "t");
+ var transition = _CaptionTransitions[$Jssor$.$ParseInt(transitionName)] || _CaptionTransitions[transitionName];
+
+ var transitionName2 = $Jssor$.$AttributeEx(captionElmt, "t2");
+ var transition2 = _CaptionTransitions[$Jssor$.$ParseInt(transitionName2)] || _CaptionTransitions[transitionName2];
+
+ var itemToPlay = { $Elmt: captionElmt, $Transition: transition, $Transition2: transition2 };
+ if (level < 3) {
+ itemsToPlay.concat(GetCaptionItems(captionElmt, level + 1));
+ }
+ itemsToPlay.push(itemToPlay);
+ }
+ });
+
+ return itemsToPlay;
+ }
+
+ function CreateAnimator(captionElmt, transitions, lastStyles, forIn) {
+
+ $Jssor$.$Each(transitions, function (transition) {
+
+ var animatorOptions = {
+ $Easing: transition.$Easing,
+ $Round: transition.$Round,
+ $During: transition.$During,
+ $Setter: $Jssor$.$StyleSetterEx()
+ };
+
+ var fromStyles = $Jssor$.$Extend($Jssor$.$GetStyles(captionItem, transition), lastStyles);
+
+ var animator = new $JssorAnimator$(transition.$Begin || 0, (transition.$End || 0) - (transition.$Begin || 0), animatorOptions, captionElmt, fromStyles, transition);
+
+ !forIn == !playIn && _This.$Combine(animator);
+
+ var castOptions;
+ //castOptions = { $Move: slideTransition.$Move, $OriginalWidth: slideContainerWidth, $OriginalHeight: slideContainerHeight };
+
+ lastStyles = $Jssor$.$Extend(lastStyles, $Jssor$.$Cast(fromStyles, transition, 1, animatorOptions.$Easing, animatorOptions.$During, animatorOptions.$Round, animatorOptions, castOptions));
+ });
+
+ return lastStyles;
+ }
+
+ function CreateAnimators(captionItems) {
+
+ $Jssor$.$Each(captionItems, function (captionItem, i) {
+
+ $JssorDebug$.$Execute(function () {
+ if (captionItem.length) {
+ var top = $Jssor$.$CssTop(captionItem.$Elmt);
+ var left = $Jssor$.$CssLeft(captionItem.$Elmt);
+ var width = $Jssor$.$CssWidth(captionItem.$Elmt);
+ var height = $Jssor$.$CssHeight(captionItem.$Elmt);
+
+ var error = null;
+
+ if (isNaN(top))
+ error = "style 'top' not specified";
+ else if (isNaN(left))
+ error = "style 'left' not specified";
+ else if (isNaN(width))
+ error = "style 'width' not specified";
+ else if (isNaN(height))
+ error = "style 'height' not specified";
+
+ if (error)
+ throw new Error("Caption " + (i + 1) + " definition error, " + error + ".\r\n" + captionItem.$Elmt.outerHTML);
+ }
+ });
+
+ var captionElmt = captionItem.$Elmt;
+
+ var captionItemWidth = $Jssor$.$CssWidth(captionItem);
+ var captionItemHeight = $Jssor$.$CssHeight(captionItem);
+ var captionParentWidth = $Jssor$.$CssWidth(captionParent);
+ var captionParentHeight = $Jssor$.$CssHeight(captionParent);
+
+ var lastStyles = { $Zoom: 1, $Rotate: 0, $Clip: { $Top: 0, $Right: captionItemWidth, $Bottom: captionItemHeight, $Left: 0 } };
+
+ lastStyles = CreateAnimator(captionElmt, captionItem.$Transition, lastStyles, true);
+ CreateAnimator(captionElmt, captionItem.$Transition2, lastStyles, false);
+ });
+ }
+
+ _This.$Revert = function () {
+ _This.$GoToPosition(-1, true);
+ }
+
+ //Constructor
+ {
+ CreateAnimators(GetCaptionItems(container, 1));
+ }
+};
+
+//Event Table
+
+//$EVT_CLICK = 21; function(slideIndex[, event])
+//$EVT_DRAG_START = 22; function(position[, virtualPosition, event])
+//$EVT_DRAG_END = 23; function(position, startPosition[, virtualPosition, virtualStartPosition, event])
+//$EVT_SWIPE_START = 24; function(position[, virtualPosition])
+//$EVT_SWIPE_END = 25; function(position[, virtualPosition])
+
+//$EVT_LOAD_START = 26; function(slideIndex)
+//$EVT_LOAD_END = 27; function(slideIndex)
+
+//$EVT_POSITION_CHANGE = 202; function(position, fromPosition[, virtualPosition, virtualFromPosition])
+//$EVT_PARK = 203; function(slideIndex, fromIndex)
+
+//$EVT_PROGRESS_CHANGE = 208; function(slideIndex, progress[, progressBegin, idleBegin, idleEnd, progressEnd])
+//$EVT_STATE_CHANGE = 209; function(slideIndex, progress[, progressBegin, idleBegin, idleEnd, progressEnd])
+
+//$EVT_ROLLBACK_START = 210; function(slideIndex, progress[, progressBegin, idleBegin, idleEnd, progressEnd])
+//$EVT_ROLLBACK_END = 211; function(slideIndex, progress[, progressBegin, idleBegin, idleEnd, progressEnd])
+
+//$EVT_SLIDESHOW_START = 206; function(slideIndex[, progressBegin, slideshowBegin, slideshowEnd, progressEnd])
+//$EVT_SLIDESHOW_END = 207; function(slideIndex[, progressBegin, slideshowBegin, slideshowEnd, progressEnd])
+
+//http://www.jssor.com/development/reference-api.html
\ No newline at end of file
diff --git a/spree_theme/app/assets/javascripts/jssor.slider.one.js b/spree_theme/app/assets/javascripts/jssor.slider.one.js
index 538a3b96..7798a3cb 100644
--- a/spree_theme/app/assets/javascripts/jssor.slider.one.js
+++ b/spree_theme/app/assets/javascripts/jssor.slider.one.js
@@ -1,3 +1,5 @@
-//= require jssor.slider/jssor.core
-//= require jssor.slider/jssor.utils
-//= require jssor.slider/jssor.slider
\ No newline at end of file
+// require jssor.slider/jssor.core
+// require jssor.slider/jssor.utils
+// require jssor.slider/jssor.slider
+//= require jssor.19/jssor
+//= require jssor.19/jssor.slider
\ No newline at end of file
diff --git a/spree_theme/app/assets/javascripts/scotchPanels.js b/spree_theme/app/assets/javascripts/scotchPanels.js
new file mode 100644
index 00000000..4dd18fc3
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/scotchPanels.js
@@ -0,0 +1,656 @@
+/*
+* scotchPanels - v1.0.3 - 2014-09-25
+* https://github.com/scotch-io/scotch-panels
+* Copyright (c) 2014 Nicholas Cerminara
+*/
+// Start with Semicolon to block
+;(function($) {
+
+ // Enable Strict Mode
+ 'use strict';
+
+ // Create Panels Array
+ var panels = [];
+
+ // Has done CSS3 browser support check?
+ var browserSupportTest = false;
+ var has3d = false;
+ var hasTransitions = false;
+
+ // Plugin Default Settings
+ var defaults = {
+
+ // General Config
+ containerSelector: 'body',
+ type: 'html', // html, iframe, video, image
+
+ // Styles
+ direction: 'top', // top, left, right, bottom
+ duration: 300, // ms
+ transition: 'ease', // linear, ease, ease-in, ease-out, ease-in-out, cubic-bezier(P1x,P1y,P2x,P2y)
+
+ // Browser Support
+ easingPluginTransition: 'easeInCirc',
+ useCSS: true, // Consider not using if have Fixed Elements
+ useEasingPlugin: false, // http://gsgd.co.uk/sandbox/jquery/easing/ only for browser support
+
+ // Image Options
+ imageURL: false,
+
+ // Iframe Options
+ iframeURL: false,
+
+ // Video Options
+ autoPlayVideo: true,
+ youtubeID: false,
+ youTubeTheme: 'light',
+
+ // TranslateX Options
+ distanceX: '70%',
+
+ // TranslateY Options
+ forceMinHeight: false,
+ minHeight: '200px',
+
+ // Triggers
+ closeAfter: 0, // ms
+ startOpened: false,
+ startOpenedDelay: 0, // ms
+
+ // Event Helpers
+ clickSelector: false,
+ enableEscapeKey: true,
+ hoverSelector: false,
+ touchSelector: false,
+
+ // Callbacks
+ beforePanelOpen: function() {},
+ afterPanelOpen: function() {},
+ beforePanelClose: function() {},
+ afterPanelClose: function() {}
+ };
+
+
+ $.fn.scotchPanel = function(options) {
+
+ // Check to see if Default Options are Set
+ if (typeof options === 'undefined') {
+ options = {};
+ }
+
+ // Check to see if an element is even selected
+ if (this.length === 0) return this;
+
+ // Support selecting Panels
+ if (this.length > 1) {
+
+ // Loop through all selected scotch panels
+ this.each(function() {
+ // Add panel to array
+ panels.push($(this).scotchPanel(options));
+ });
+
+ // Public Functions Functionality for all at once
+ panels.open = function() {
+ for (var i = 0; i < panels.length; i++) {
+ panels[i].open();
+ }
+ };
+ panels.close = function() {
+ for (var i = 0; i < panels.length; i++) {
+ panels[i].close();
+ }
+ };
+ panels.toggle = function() {
+ for (var i = 0; i < panels.length; i++) {
+ panels[i].toggle();
+ }
+ };
+
+ // Return the Scotch Panels
+ return panels;
+ }
+
+ // Create Current Scotch Panel Object
+ var panel = {};
+ panel = this;
+
+
+ /*=========================================
+ = PRIVATE FUNCTIONS =
+ =========================================*/
+ // Prep everything
+ var init = function() {
+
+ // Do CSS3 Check!
+ if (!browserSupportTest) {
+ browserSupportTest = true;
+ has3d = browserSupport.transition();
+ hasTransitions = browserSupport.translate3d();
+ }
+
+ // Check for HTML5 data attributes instead
+ for (var key in defaults) {
+ if (defaults.hasOwnProperty(key)) {
+ if (panel.attr('data-'+key.toLowerCase())) {
+ options[key] = panel.data(key.toLowerCase());
+ }
+ }
+ }
+
+ // Merge Custom Plugin Settings with Default
+ panel.settings = $.extend({}, defaults, options);
+
+ // Start DOM and CSS Modifications
+ setup();
+ };
+
+
+ // DOM / CSS Changes / Make Things Happen
+ var setup = function() {
+
+ // Wrap the panel!
+ var container = $(panel.settings.containerSelector);
+ if (!container.hasClass('scotchified')) {
+ container.wrapInner('').addClass('scotchified');
+ }
+
+ // Scotch Panel Wrapper CSS
+ $('.scotch-panel-wrapper').css({
+ 'position': 'relative',
+ 'overflow': 'hidden',
+ 'width': '100%'
+ });
+ // Scotch Panel Canvas CSS
+ $('.scotch-panel-canvas').css({
+ 'position': 'relative',
+ 'height': '100%',
+ 'width': '100%'
+ });
+ // Do 3D Stuff separate
+ if (panel.settings.useCSS) {
+ $('.scotch-panel-canvas').css({
+ '-moz-transform': 'translate3d(0, 0, 0)',
+ '-ms-transform': 'translate3d(0, 0, 0)',
+ '-o-transform': 'translate3d(0, 0, 0)',
+ '-webkit-transform': 'translate3d(0, 0, 0)',
+ 'transform': 'translate3d(0, 0, 0)',
+ '-moz-backface-visibility': 'hidden',
+ '-ms-backface-visibility': 'hidden',
+ '-o-backface-visibility': 'hidden',
+ '-webkit-backface-visibility': 'hidden',
+ 'backface-visibility': 'hidden'
+ });
+ }
+
+ // Figure out which off canvas style is used (left, top, right)
+ if (panel.settings.direction == 'top') {
+ panel.height = panel.height();
+ panel.addClass('scotch-panel-top');
+
+ panel.css({
+ 'bottom': '100%',
+ 'left': '0',
+ 'width': '100%',
+ 'position': 'absolute',
+ 'z-index': '888888',
+ 'overflow': 'hidden'
+ });
+ }
+ if (panel.settings.direction == 'bottom') {
+ panel.height = panel.height();
+ panel.addClass('scotch-panel-bottom');
+
+ panel.css({
+ 'top': '100%',
+ 'left': '0',
+ 'width': '100%',
+ 'position': 'absolute',
+ 'z-index': '888888',
+ 'overflow': 'hidden'
+ });
+ }
+ if (panel.settings.direction == 'left') {
+ panel.addClass('scotch-panel-left');
+
+ panel.css({
+ 'top': '0',
+ 'left': '-' + panel.settings.distanceX,
+ 'width': panel.settings.distanceX,
+ 'height': '100%',
+ 'position': 'absolute',
+ 'z-index': '888888',
+ 'overflow': 'hidden'
+ });
+ }
+ if (panel.settings.direction == 'right') {
+ panel.addClass('scotch-panel-right');
+
+ panel.css({
+ 'top': '0',
+ 'right': '-' + panel.settings.distanceX,
+ 'width': panel.settings.distanceX,
+ 'height': '100%',
+ 'position': 'absolute',
+ 'z-index': '888888',
+ 'overflow': 'hidden'
+ });
+ }
+ panel.css({
+ '-moz-backface-visibility': 'hidden',
+ '-ms-backface-visibility': 'hidden',
+ '-o-backface-visibility': 'hidden',
+ '-webkit-backface-visibility': 'hidden',
+ 'backface-visibility': 'hidden'
+ });
+
+ // Photo Logic
+ if (panel.settings.type == 'image' && panel.settings.imageURL) {
+ panel.css({
+ '-o-background-size': 'cover',
+ '-ms-background-size': 'cover',
+ '-moz-background-size': 'cover',
+ '-webkit-background-size': 'cover',
+ 'background-size': 'cover',
+ 'background-position': '50% 0',
+ 'background-repeat': 'no-repeat',
+ 'background-image': 'url('+panel.settings.imageURL+')'
+ });
+
+ // Update Panel Height if top or bottom
+ if (panel.settings.direction == 'top' || panel.settings.direction == 'bottom') {
+ panel.css('min-height', panel.settings.minHeight);
+ panel.height = $(panel).height();
+ }
+ }
+
+ // Iframe Logic
+ if (panel.settings.type == 'iframe' && panel.settings.iframeURL) {
+ panel.iframeIsLoaded = false;
+ panel.append('');
+
+ // Update Panel Height if top or bottom
+ if (panel.settings.direction == 'top' || panel.settings.direction == 'bottom') {
+ panel.height = $(panel).height();
+ }
+ }
+
+ // YouTube Logic
+ if (panel.settings.type == 'video' && panel.settings.youtubeID) {
+ panel.append('');
+
+ // Update Panel Height if top or bottom
+ if (panel.settings.direction == 'top' || panel.settings.direction == 'bottom') {
+ panel.height = $(panel).height();
+ }
+ }
+
+ // Apply CSS3 Transitions if modern browser
+ if (has3d && hasTransitions) {
+ applyTransition(panel.settings.transition, panel.settings.duration);
+ }
+
+ // Open on Start?
+ if (panel.settings.startOpened) {
+ setTimeout(function(){
+ panel.open();
+ }, panel.settings.startOpenedDelay);
+ }
+
+ // Close after X milliseconds?
+ if (panel.settings.closeAfter != 0) {
+ setTimeout(function(){
+ panel.close();
+ }, panel.settings.closeAfter);
+ }
+ };
+
+
+ // Browser Support Object
+ var browserSupport = {
+ transition: function() {
+ // IE 7 + 8 Sucks
+ if (!window.getComputedStyle) {
+ return false;
+ }
+
+ var b = document.body || document.documentElement,
+ s = b.style,
+ p = 'transition';
+
+ if (typeof s[p] == 'string') { return true; }
+
+ // Tests for vendor specific prop
+ var v = ['Moz', 'webkit', 'Webkit', 'Khtml', 'O', 'ms'];
+ p = p.charAt(0).toUpperCase() + p.substr(1);
+
+ for (var i=0; i100){
+ // $("#return_top").fadeIn(500);
+ // }
+ // else{
+ // $("#return_top").fadeOut(1500);
+ // }
+ //});
+ $("body,html").animate({scrollTop:0},1000);
+ return false;
+ });
+
+ // change bg,border when hovering
+ $('.hoverable').hover(function(){
+ $('.inner',this).addClass( 'hover' );
+ }, function(){
+ $('.inner',this).removeClass( 'hover' );
+ });
+
+ // like taobao, show big image when hovering product image.
+ $('.zoomable').each(function(i, element){
+ var $element =$(element);
+ var $main_image_wrapper = $element.find('.main_image_wrapper');
+ $element.find('.thumbnails a').click(function(){
+ var $this = $(this);
+ $main_image_wrapper.find('img').data('big-image', $this.find('img').data('big-image'));
+ });
+ $element.imageZoom({
+ zoomType: 'standard',
+ lens:true,
+ preloadImages: false,
+ alwaysOn:false,
+ thumbConfig: {
+ containerSelector: null//'.thumbnails'
+ },
+ zoomViewerConfig:{
+ width: $main_image_wrapper.width()-2, // 2 is border l+r
+ height: $main_image_wrapper.height()-2
+ },
+ zoomPadConfig: {
+ containerSelector: '.main_image_wrapper'
+ }
+ });
+ });
+
+
+ $('.lightboxable').each( function(i, element){
+
+ var $element =$(element);
+ var $main_image = $element.find('.main_image_wrapper img');
+ var jsonData =[];
+ var thumbnails = $element.find('.thumbnails img');
+ if( thumbnails.is('*') ){
+ thumbnails.each(function(j,img){
+ jsonData.push({ url:$(img).data('big-image'), title: img.alt });
+ });
+ }else{
+ jsonData.push({ url:$main_image.data('big-image'), title: $main_image.attr('alt') });
+ }
+
+ $main_image.lightbox({
+ fitToScreen: true,
+ jsonData: jsonData,
+ loopImages: true,
+ imageClickClose: false,
+ disableNavbarLinks: true
+ });
+
+ });
+
+ // scroll to target
+ $('.effect_scroll').click(function() {
+ var $body = (window.opera) ? (document.compatMode == "CSS1Compat" ? $('html') : $('body')) : $('html,body');
+ var $self = $(this);
+ var $target = $($self.attr('href'));
+ if($target.is('*')) {
+ $body.animate({
+ scrollTop : ($target.offset().top - 120)
+ }, 500);
+ return false;
+ }
+ });
+
+ function ScaleSlider(jssor_slider) {
+ var parentWidth = $(jssor_slider.$Elmt.parentNode).width();
+ if(parentWidth)
+ jssor_slider.$SetScaleWidth(parentWidth);
+ else
+ window.setTimeout(ScaleSlider, 30);
+ }
+
+ // dom structure
+ //
+ //
+ //
+ // slide1
+ // slide2
+ //
+ //
+ $(".effect_slider").each(function(index, element) {
+ var $self = $(element);
+ var $parent = $self.parent();
+ var $slide_container = $self.children("[u='slides']");
+ // if parent height is 1, use width. it is for product image slider on mobile
+ var height = $parent.height();
+ if (height > 1){
+ $self.css({ height : $parent.css('height'), width : $parent.css('width') });
+ $slide_container.css({ height : $parent.css('height'), width : $parent.css('width') });
+ }else{
+ $self.css({ height : $parent.css('width'), width : $parent.css('width') });
+ $slide_container.css({ height : $parent.css('width'), width : $parent.css('width') });
+ }
+ var options = null;
+ var auto_play = ( $slide_container.data('auto-play') == null ? true : $slide_container.data('auto-play') );
+ var display_pieces = $slide_container.data('display-pieces');
+ if( display_pieces ){
+ var slide_width = $self.find("[u='slides']>div").width();
+ var display_piece = Math.ceil( $parent.width() / slide_width );
+ // get width of a slide
+ options = {
+ $AutoPlay: auto_play, //[Optional] Whether to auto play, to enable slideshow, this option must be set to true, default value is false
+ $AutoPlaySteps: 1, //[Optional] Steps to go for each navigation request (this options applys only when slideshow disabled), the default value is 1
+ $AutoPlayInterval: 0, //[Optional] Interval (in milliseconds) to go for next slide since the previous stopped if the slider is auto playing, default value is 3000
+ $PauseOnHover: 4, //[Optional] Whether to pause when mouse over if a slider is auto playing, 0 no pause, 1 pause for desktop, 2 pause for touch device, 3 pause for desktop and touch device, 4 freeze for desktop, 8 freeze for touch device, 12 freeze for desktop and touch device, default value is 1
+
+ $ArrowKeyNavigation: true, //[Optional] Allows keyboard (arrow key) navigation or not, default value is false
+ $SlideEasing: $JssorEasing$.$EaseLinear, //[Optional] Specifies easing for right to left animation, default value is $JssorEasing$.$EaseOutQuad
+ $SlideDuration: 1600, //[Optional] Specifies default duration (swipe) for slide in milliseconds, default value is 500
+ $MinDragOffsetToSlide: 20, //[Optional] Minimum drag offset to trigger slide , default value is 20
+ $SlideWidth: slide_width, //it is requried //[Optional] Width of every slide in pixels, default value is width of 'slides' container
+ //$SlideHeight: 100, //[Optional] Height of every slide in pixels, default value is height of 'slides' container
+ $SlideSpacing: 0, //[Optional] Space between each slide in pixels, default value is 0
+ $DisplayPieces: display_piece, //it is required //[Optional] Number of pieces to display (the slideshow would be disabled if the value is set to greater than 1), the default value is 1
+ $ParkingPosition: 0, //[Optional] The offset position to park slide (this options applys only when slideshow disabled), default value is 0.
+ $UISearchMode: 1, //[Optional] The way (0 parellel, 1 recursive, default value is 1) to search UI components (slides container, loading screen, navigator container, arrow navigator container, thumbnail navigator container etc).
+ $PlayOrientation: 1, //[Optional] Orientation to play slide (for auto play, navigation), 1 horizental, 2 vertical, 5 horizental reverse, 6 vertical reverse, default value is 1
+ $DragOrientation: 1 //[Optional] Orientation to drag slide, 0 no drag, 1 horizental, 2 vertical, 3 either, default value is 1 (Note that the $DragOrientation should be the same as $PlayOrientation when $DisplayPieces is greater than 1, or parking position is not 0)
+ };
+
+ } else{
+ options = {
+ $AutoPlay : auto_play,
+ $FillMode : 2,
+ $BulletNavigatorOptions : {
+ $Class : $JssorBulletNavigator$,
+ $ChanceToShow : 2,
+ $AutoCenter : 1
+ }
+ };
+ }
+ if( $slide_container.children().length>0){
+ var jssor_slider1 = new $JssorSlider$($self.get(0), options);
+ //responsive code begin
+ //you can remove responsive code if you don't want the slider scales while window resizes
+ //Scale slider immediately
+ ScaleSlider(jssor_slider1);
+ //if (!navigator.userAgent.match(/(iPhone|iPod|iPad|BlackBerry|IEMobile)/)) {
+ // $(window).bind('resize', ScaleSlider);
+ //}
+ //responsive code end
+ }
+ });
+
+ if($("#map").is('*')) {
+ // initialize baid map.
+ initMap();
+ };
+
+ // dom
+ // div.hover_effect_xxx
+ // .child_1
+ // .child_2
+ // div.hover_effect_xxx
+ // .child_1
+ // .child_2
+
+ //menu effect slide
+ $(".hover_effect_slide").each(function(index, element) {
+ //nav sliding
+ var height = '' + $('.child_1', element).height() + 'px';
+ var offset = '-' + height;
+ //$('.name',element).css({ height: height});
+ $('.child_2', element).css({
+ bottom : offset,
+ height : height
+ });
+ //nav sliding
+ $(element).hover(function() {
+ $(".child_1", this).stop().animate({
+ top : offset,
+ left : '0px'
+ }, {
+ queue : false,
+ duration : 300
+ });
+ $(".child_2", this).stop().animate({
+ bottom : '0px',
+ left : '0px'
+ }, {
+ queue : false,
+ duration : 300
+ });
+ }, function() {
+ $(".child_1", this).stop().animate({
+ top : '0px',
+ left : '0px'
+ }, {
+ queue : false,
+ duration : 300
+ });
+ $(".child_2", this).stop().animate({
+ bottom : offset,
+ left : '0px'
+ }, {
+ queue : false,
+ duration : 300
+ });
+ });
+ });
+ //
+ $('.hover_effect_show').hover(function() {
+ $('.child_2', this).stop().slideDown();
+ }, function() {
+ $('.child_2', this).stop().slideUp();
+ });
+ //slides the element with class "menu_body" when mouse is over the paragraph
+ $(".hover_effect_expansion .child_1").mouseover(function() {
+ $(this).parents('.hover_effect_expansion').addClass('hovered').siblings().removeClass('hovered');
+ $(this).next(".child_2").slideDown(500);
+ $(this).parents('.hover_effect_expansion').siblings().find('.child_2').slideUp("slow");
+ });
+
+ $(".hover_effect_overlay").hover(function() {
+ var offset = '-' + $('.child_1', this).width() + 'px';
+ $(".child_2", this).stop().animate({
+ top : '0',
+ left : offset
+ }, {
+ queue : false,
+ duration : 400
+ });
+ }, function() {
+ $(".child_2", this).stop().animate({
+ top : '0px',
+ left : '0px'
+ }, {
+ queue : false,
+ duration : 400
+ });
+ });
+ $(".hover_effect_multi_level_menu").each(function(index, element) {
+ // navigation horizental two level menu
+ // menu item1 | menu item2 hovering | menu item3
+ // | menu item21 |
+ // | menu item22 |
+ $("ul ul", element).css({
+ display: "none"
+ }); // Opera Fix
+ $("ul li", element).hover(function() {
+ $(this).find('ul:first').css({
+ visibility: "visible",
+ display: "none"
+ }).slideDown("normal");
+ }, function() {
+ $(this).find('ul:first').css({
+ visibility: "hidden"
+ });
+ });
+
+ });
+ // usage: compute child_2 display position of window for effect popup
+ // html
+ // params: direction- there are five option values t,r,b,l,rl,
+ // it composite of three character.
+ // xya: x axis, y axis, a alignment. ex. lbl, position left bottom, align left
+ function compute_popup_position( $container, direction ){
+ var $self = $container;
+ var child1 = $(".child_1", $self);
+ var child2 = $(".child_2", $self);
+ var offset = child1.offset();
+ // get silbings, get parent.width, get current
+ // get currentTarge.pageX,
+ var position = [0,0];
+ // top, left
+ var block = $(window);
+ var scroll_top = block.scrollTop();
+ var scroll_left = block.scrollLeft();
+ if ( direction == 'rl' ){
+ var p = $self.parent().width() / 2 - $self.position().left - $self.width();
+ if(p >= 0) {// pop up on right side of child2
+ position[0] = offset.top - (child2.height() - child1.height() ) / 2 - scroll_top;
+ position[1] = offset.left + child1.width();
+ } else {// pop up on left side of $self
+ position[0] = offset.top - (child2.height() - child1.height() ) / 2 - scroll_top;
+ position[1] = offset.left - child2.width();
+ }
+ }else if ( direction == 'b' ){
+ position[0] = offset.top + child1.height() - scroll_top;;
+ position[1] = offset.left - (child2.width() - child1.width() ) / 2 - scroll_left;
+ }else if ( direction == 't' ){
+ position[0] = offset.top - child2.height() - scroll_top;;
+ position[1] = offset.left - (child2.width() - child1.width() ) / 2 - scroll_left;
+ }else if ( direction == 'l' ){
+ position[0] = offset.top - (child2.height() - child1.height() ) / 2 - scroll_top;
+ position[1] = offset.left - child2.width();
+ }else if ( direction == 'lbl' ){
+ position[0] = offset.top - (child2.height() - child1.height() ) - scroll_top;
+ position[1] = offset.left - child2.width();
+ }
+ return position;
+ }
+
+ $(".hover_effect_popup").hover(function(e) {
+ var position = compute_popup_position( $(this), 'rl' );
+ //console.log( "pos y=%d, x=%d", position[0], position[1] );
+ $(".child_2", this).simplemodal({
+ appendTo: '#page-wrapper',
+ closeHTML:'', // remove a.close, or get incorrect container demension
+ modal : false,
+ focus : false,
+ position : position,
+ fixed : false
+ });
+ }, function() {
+ $.simplemodal.close();
+ });
+
+ // popup menu, enable mouse hover on popup div, user could click menu on it.
+ $(".hover_effect_popup_menu_l,.hover_effect_popup_menu").each(function(i, element){
+ var $self = $(element);
+ var direction = 'b';// popup at bottom, center as well.
+ if ($self.hasClass('hover_effect_popup_menu_l')){
+ direction = 'l';
+ }else if ($self.hasClass('hover_effect_popup_menu_lbl')){
+ direction = 'lbl';
+ }
+ function activate_element( ){
+ var $hover_effect_container = this.$hover_effect_container;
+ var position = compute_popup_position( $hover_effect_container, direction );
+ //console.log( "pos y=%d, x=%d", position[0], position[1] );
+ $(".child_2", $hover_effect_container).simplemodal({
+ appendTo: '#page-wrapper',
+ closeHTML:'', // remove a.close, or get incorrect container demension
+ modal : false,
+ focus : false,
+ position : position,
+ fixed : false
+ });
+ };
+ function deactivate_element( ){
+ $.simplemodal.close();
+ };
+ var child1 = $(".child_1", this);
+ var child2 = $(".child_2", this);
+
+ $(element).menuhover({
+ activate: activate_element,
+ deactivate: deactivate_element,
+ submenuDirection: direction,
+ $hover: child2
+ });
+ });
+ $(".click_effect_sider").each(function(i, element){
+ var child2 = $(".child_2", element);
+ //var class_names = $(".child_2", element).attr('class').replace(/(^\s+)|(\s+$)/g,"").replace(/\s+/g,'.');
+ $(".child_1", element).sidr({
+ body: '#page-inner', // append into page innner, apply page css.
+ displace: false,
+ renaming: false,
+ source: function(){
+ return ( child2.is("*") ? child2[0].outerHTML : "no content");
+ }
+ });
+ });
+ $(".sidr").on( 'click',".sidr-close",function(){
+ $.sidr( 'close','sidr');
+ });
+
+});
diff --git a/spree_theme/app/assets/javascripts/store/spree_theme.client.js b/spree_theme/app/assets/javascripts/store/spree_theme.client.js
index c6cfa32f..86f56a2c 100644
--- a/spree_theme/app/assets/javascripts/store/spree_theme.client.js
+++ b/spree_theme/app/assets/javascripts/store/spree_theme.client.js
@@ -1,8 +1,14 @@
-//= require jquery
-//= require jquery.validate/localization/messages_zh-CN.js
-//= require jquery.simplemodal.js
+//= require jquery.validate/localization/messages_zh-CN
+//= require jquery.simplemodal
+//= require jquery.lightbox.custom
+//= require store/section_effect
$(document).ready(function() {
+ // disable progress-bar, coolpadwebkit do not support
+ //if( !g_client_info.is_mobile ){
+ // Turbolinks.enableProgressBar();
+ //}
+
// template theme selection for designer shop
$( "#embeded_content_wrapper" ).hover(
function() { $(this).show(); $( "#embeded_content_wrapper_icon" ).hide();},
@@ -11,21 +17,12 @@ $(document).ready(function() {
$( "#embeded_content_wrapper_icon" ).hover(
function() { $( "#embeded_content_wrapper" ).show(); }
);
-
-});
-$(document).ready(function() {
- // initialize sections
- $($("input.fixed_container").val()).floatBar({
- bodyWidth:980, vertical:"top", moveOnOff:false, focusOnOff:false
- });
- $("input.hover_effect_container").each(function(index, element){
- var children = $(element).siblings('div');
- if( children.length == 2){
- var child1 = $(children[0]); var child2 = $(children[1]);
- child2.on('mouseenter',function(){ child1.show();child2.hide(); })
- child1.on('mouseout', function(){child2.show();child1.hide();})
- }
- })
+
+
+ // code for theme, should move to template_themes.js
+ $(".u_dialog").delegate( "a.cancel,button.cancel", "click",function(){
+ $.simplemodal.close();
+ });
});
// copy from project https://github.com/citrus/spree_variant_options
@@ -35,9 +32,9 @@ $(document).ready(function() {
// allow_select_outofstock: By setting allow_select_outofstock to true, when an user selects variant options it will automatically update any form's input variant_id with an data-form-type="variant" attribute.
// default_instock: (default: false) If this is option is set to true, it will automatically preselect in-stock variant options.
function VariantOptions(params) {
- var view_style = params['view_style']
+ var view_style = params['view_style'];
var options = params['options'];
- var container_selector = params['container_selector']
+ var container_selector = params['container_selector'];
var allow_backorders = !params['track_inventory_levels'] || params['allow_backorders'];
var allow_select_outofstock = params['allow_select_outofstock'];
var default_instock = params['default_instock'];
@@ -45,7 +42,7 @@ function VariantOptions(params) {
var option_types, option_values_container, index = 0;
// option_types: all option_types included option_values
// option_values_container: a container for option_values of an option_type
- var available_variant_ids = []; // base on selected option value, there are some available variant ids
+ var available_variant_ids = []; // base on selected option value, there are some available variant ids
var buttons;
@@ -63,7 +60,7 @@ function VariantOptions(params) {
});
}
}
-
+
// set current option type
function update(i) {
index = isNaN(i) ? index : i;
@@ -76,15 +73,15 @@ function VariantOptions(params) {
}
// enable option values of current option type
function enable(btns) {
- var bt = btns.not('.unavailable').removeClass('locked')
+ var bt = btns.not('.unavailable').removeClass('locked');
if (!allow_select_outofstock && !allow_backorders){
- bt = bt.filter('.in-stock')
- }
+ bt = bt.filter('.in-stock');
+ }
return bt.filter('.auto-click').removeClass('auto-click').click();
}
function advance() {
- index++
+ index++;
update();
inventory(buttons.removeClass('locked'));
enable(buttons);
@@ -108,14 +105,14 @@ function VariantOptions(params) {
var a = $(this);
//return if has class unavailable locked
if( a.hasClass("unavailable") || a.hasClass("locked")){
- return
+ return;
}
//if (!allow_select_outofstock && !allow_backorders){
// bt = bt.filter('.in-stock')
- //}
-
+ //}
+
if (a.filter('.selected').length>0){
- // unclick selected,
+ // unclick selected,
clear(option_types.index(a.parents('.variant-option:first')));
}else{
if (!option_values_container.has(a).length) {
@@ -126,8 +123,8 @@ function VariantOptions(params) {
advance();
if (target_variant=find_variant()) {
toggle(target_variant);
- }
- }
+ }
+ }
}
@@ -158,18 +155,18 @@ function VariantOptions(params) {
function hide_all_variant_images() {
$('li.vtmb').hide();
}
-
+
function inventory(btns) {
// for each option_value there is collection of available variants
- // given option_values, Intersection of those collections is final available variants
+ // given option_values, Intersection of those collections is final available variants
var variant_ids, variants, count = 0, selected = {};
- var sels = $.map(option_types.find('a.selected'), function(i) { return i.rel });
-
+ var sels = $.map(option_types.find('a.selected'), function(i) { return i.rel; });
+
variants = get_variant_objects(sels);
- available_variant_ids = $.map(variants, function(i) { return i.id });
+ available_variant_ids = $.map(variants, function(i) { return i.id; });
btns.removeClass('in-stock out-of-stock unavailable').each(function(i, element) {
variants = get_variant_objects([].concat( sels, element.rel));
- variant_ids = $.map(variants, function(i) { return i.id });
+ variant_ids = $.map(variants, function(i) { return i.id; });
if (variant_ids.length == 0) {
disable($(element).addClass('unavailable locked'));
} else if (variant_ids.length == 1) {
@@ -178,7 +175,7 @@ function VariantOptions(params) {
} else if (allow_backorders) {
$(element).addClass('in-stock');
} else {
- $.each(variants, function(variant) { count += variant.count });
+ $.each(variants, function(variant) { count += variant.count; });
$(element).addClass(count ? 'in-stock' : 'out-of-stock');
}
});
@@ -189,10 +186,10 @@ function VariantOptions(params) {
//------------------------------------------------------------------------------------------
function init_for_slide_style() {
option_types = $(container_selector+" .variant-option");
- option_types.find('a.option-value').click( handle_click_for_slide_style );
+ option_types.find('a.option-value').click( handle_click_for_slide_style );
$(container_selector+' button.next').click( next_step_click );
$(container_selector+' button.back').click( back_step_click );
-
+
initialize_option_view();
}
@@ -202,21 +199,21 @@ function VariantOptions(params) {
update_model();
// hide button back if index =0
if (index==0){
- $(container_selector+' button.back').attr('disabled', true);
+ $(container_selector+' button.back').attr('disabled', true);
}else{
- $(container_selector+' button.back').attr('disabled', false);
+ $(container_selector+' button.back').attr('disabled', false);
}
if ((index+1) == option_types.length){
- $(container_selector+' button.next').attr('disabled', true);
+ $(container_selector+' button.next').attr('disabled', true);
}else{
- $(container_selector+' button.next').attr('disabled', false);
+ $(container_selector+' button.next').attr('disabled', false);
}
-
+
// select one, or no option image show.
if( option_values_container.find("a.option-value.selected").length == 0) {
option_values_container.find("a.option-value:first").click();
}
- option_values_container.show()
+ option_values_container.show();
}
// update
// update data, option_values_container,buttons
@@ -224,49 +221,49 @@ function VariantOptions(params) {
option_values_container = $(option_types.get(index));
buttons = option_values_container.find('a.option-value');
}
-
- // update price?
+
+ // update price?
function update_view() {
- //show
+ //show
var option_type_id_and_option_value_id = buttons.filter('.selected').attr('rel').split('-');
option_values_container.find(' .olge').hide();
option_values_container.find(' .lge-'+option_type_id_and_option_value_id[1]).show();
}
-
+
function next_step_click() {
index++;
initialize_option_view();
}
-
+
function back_step_click() {
index--;
initialize_option_view();
}
-
+
function handle_click_for_slide_style(evt) {
evt.preventDefault();
var a = $(this);
var target_variant= null;
//return if has class unavailable locked
if( a.hasClass("unavailable") || a.hasClass("locked")|| a.hasClass("selected")){
- return
- }
+ return;
+ }
buttons.not(a).removeClass('selected');
a.addClass('selected');
-
+
update_view();
-
- target_variant=find_variant()
+
+ target_variant=find_variant();
toggle(target_variant);
-
+
}
// end slide style
//==========================================================================================
-
+
//==========================================================================================
// common method for option value
//------------------------------------------------------------------------------------------
-
+
function index_of_array(array, obj) {
for(var i = 0; i < array.length; i++){
if(array[i] == obj) {
@@ -275,21 +272,21 @@ function VariantOptions(params) {
}
return -1;
}
-
+
function to_f(string) {
return parseFloat(string.replace(/[^\d\.]/g, ''));
}
function find_variant() {
- var form_container = $(container_selector).parents('form:first')
- var rels = $.map(option_types.find('a.selected'), function(i) { return i.rel });
+ var form_container = $(container_selector).parents('form:first');
+ var rels = $.map(option_types.find('a.selected'), function(i) { return i.rel; });
var variants = get_variant_objects(rels);
if (rels.length == option_types.length) {
return variants.pop();
} else {
var prices = [];
- $.each(variants, function(i, variant) { prices.push(variant.price) });
+ $.each(variants, function(i, variant) { prices.push(variant.price); });
prices = $.unique(prices).sort(function(a, b) {
return to_f(a) < to_f(b) ? -1 : 1;
});
@@ -301,16 +298,16 @@ function VariantOptions(params) {
return false;
}
}
-
+
// get variants by selected option_vlaues
function get_variant_objects(rels) {
- var variant_objects = []
+ var variant_objects = [];
var i, ids, obj, variants = {};
if (typeof(rels) == 'string') { rels = [rels]; }
var otid, ovid, opt, opv;
i = rels.length;
try {
- for(var i=0; i0){
+ if( view_style == 'slide' ){
+ $(document).ready(init_for_slide_style);
+ }else{
+ $(document).ready(init);
+ }
}
};
diff --git a/spree_theme/app/assets/javascripts/store/spree_theme.js b/spree_theme/app/assets/javascripts/store/spree_theme.js
index b7518535..1b3ffdc3 100644
--- a/spree_theme/app/assets/javascripts/store/spree_theme.js
+++ b/spree_theme/app/assets/javascripts/store/spree_theme.js
@@ -1,81 +1,121 @@
//= require jquery
+//= require jquery.turbolinks
//= require jquery_ujs
//= require jquery.form
-//= require jquery.layout
//= require jquery.ajax
//= require jssor.slider.one
//= require spree/frontend
//= require store/spree_theme.client
+//= require store/spree_theme.routes
//= require interface.js
//= require jquery.jeditable.js
-//= require jquery.floatBar.js
+//= require turbolinks
+//require jquery.layout
$(document).ready(function() {
- if (typeof(g_is_preview) != 'undefined' && g_is_preview==true)
+
+ if (typeof(g_client_info) != 'undefined' && g_client_info.is_preview==true)
{
if (typeof(g_selector_gadget) == 'undefined' || g_selector_gadget == null) {
g_selector_gadget = new SelectorGadget();
g_selector_gadget.setMode('interactive');
}
+ $( "#editor_panel a.close" ).click(
+ function() { $(this).parent().hide(); $( "#editor_panel_icon" ).show();}
+ );
+ $( "#editor_panel_icon" ).click(
+ function() { $( "#editor_panel" ).show(); }
+ );
+
+ //$('body').layout({ applyDefaultStyles: true,
+ // stateManagement__enabled: true //enable stateManagement - automatic cookie load & save enabled by default
+ //});
- $('body').layout({ applyDefaultStyles: true,
- stateManagement__enabled: true // enable stateManagement - automatic cookie load & save enabled by default
- });
-
//$("#section_select_dialog").dialog({ autoOpen: false,
// buttons: { "Cancel": function() { $(this).dialog("close"); },
// "OK": function() { submit_layout_tree_form( 'add_child',null, $(this).find('[name="selected_section_id"]').val());
// $(this).dialog("close"); }
- // },
+ // },
// width:500,height:245 });
-
+
$("#section_select_dialog .titles li").click(function(){
$(this).parent().children().removeClass('selected');
- $(this).addClass('selected');
+ $(this).addClass('selected');
$(this).parent().next().children().removeClass('selected');
$(this).parent().next().children().eq($(this).index()).addClass('selected');
- $(this).parent().siblings('input').val($(this).attr('data-section-id'))
+ $(this).parent().siblings('input').val($(this).attr('data-section-id'));
});
$("#section_select_dialog .dialog_close_button").click(function(){
- $.modal.close();
- })
+ $.simplemodal.close();
+ });
$("#section_select_dialog .dialog_ok_button").click(function(){
- submit_layout_tree_form( 'add_child',null, $('#section_select_dialog [name="selected_section_id"]').val());
- $.modal.close();
- })
+ $('#selected_section_id').val($('#section_select_dialog [name="selected_section_id"]').val());
+
+ submit_layout_tree_form( this );
+ $.simplemodal.close();
+ });
// add, remove, move section
- $('.add_section_button').click(function(){
- var page_layout_id = $(this).data('id');
- $('#layout_id').val(page_layout.id);
- $('#section_select_dialog').modal({ minHeight:300, minWidth: 600 });
- })
- $('.remove_section_button').click(function(){
- var page_layout_id = $(this).data('id');
- if (confirm('Really?')) submit_layout_tree_form('del_self', page_layout.id )
- })
- $('.move_section_to_left_button').click(function(){
- var page_layout_id = $(this).data('id');
- submit_layout_tree_form('move_left',page_layout.id )
- })
- $('.move_section_to_right_button').click(function(){
- var page_layout_id = $(this).data('id');
- submit_layout_tree_form('move_right',page_layout.id )
- })
- $('.promote_section_button').click(function(){
- var page_layout_id = $(this).data('id');
- submit_layout_tree_form('promote',page_layout.id )
- })
- $('.demote_section_button').click(function(){
- var page_layout_id = $(this).data('id');
- submit_layout_tree_form('demote',page_layout.id )
- })
- }
-})
-function submit_layout_tree_form (op, layout_id, selected_section_id) {
+
+ // event is erase when layout tree updated.
+ $("#layout_tree_form .click_editable").editable(function(value, settings) {
+ var jquery_element = $(this);
+ var url = Spree.routes.admin_page_layouts( jquery_element.data('tid') )+'/'+jquery_element.data('lid');
+ var submitdata = {};
+ submitdata[settings.name] = value;
+ //submitdata[settings.id] = self.id;
+ $.ajax({ dataType: 'json', url: url, type: 'put', data : submitdata,
+ success: function(data){
+ // data is null, "nocontent" returned
+ // jquery_element.html(data.page_layout.title);
+ }
+ });
+ return(value);
+ },
+ { //since dblclick would trigger click, for a link, we should not click,dblclick together
+ event : "click_editable",
+ name : "page_layout[title]",
+ cssclass : "editable",
+ style : "inherit"
+ });
+
+ $(document).on( 'click',"#layout_tree_form .click_editable",function(){
+ self = $(this);
+ if($('#page_layout_editable').is(':checked')){
+ // check event.editable to see editable initialized or not
+ // $(this).data('event.editable', settings.event);
+ self.trigger('click_editable');
+ }else{
+ $('#selected_page_layout_id').val(self.data('lid'));
+ $('#layout_editor_form').trigger('submit');
+ }
+ });
+
+ $(document).on('mouseover',"#editors .tabs li", function(){
+ $(this).parent().find('a').removeClass('selected');
+ $(this).find('a').addClass('selected');
+ $(this).parent().next().children().hide();
+ $(this).parent().next().children().eq($(this).index()).show();
+ $("#selected_editor_id").val($(this).attr('data-id'));
+ });
+
+ }
+});
+function submit_layout_tree_form ( currentTarget ) {
+ var target = $(currentTarget);
+ var page_layout_id = target.data('id');
+
+ var op = target.data('op');
+ if(op=='list_section'){
+ $('#layout_id').val(page_layout_id);
+ $('#section_select_dialog').simplemodal({ minHeight:300, minWidth: 600,
+ overlayCss:{ 'background-color': 'gray' },
+ containerCss: {'background-color': 'white', 'overflow' :'auto' }
+ });
+ return;
+ }
+
$('#op').val(op);
// layout_id, selected_section_id could be null.
- if (layout_id) $('#layout_id').val(layout_id);
- if (selected_section_id) $('#selected_section_id').val(selected_section_id);
+ if (page_layout_id) $('#layout_id').val(page_layout_id);
$('#layout_tree_form').trigger('submit');
}
-
diff --git a/spree_theme/app/assets/javascripts/store/spree_theme.login.js b/spree_theme/app/assets/javascripts/store/spree_theme.login.js
new file mode 100644
index 00000000..52e9ebc1
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/store/spree_theme.login.js
@@ -0,0 +1 @@
+//= require spree
diff --git a/spree_theme/app/assets/javascripts/store/spree_theme.mobile.js b/spree_theme/app/assets/javascripts/store/spree_theme.mobile.js
new file mode 100644
index 00000000..f9cf24d7
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/store/spree_theme.mobile.js
@@ -0,0 +1 @@
+//= require bootstrap-sprockets
diff --git a/spree_theme/app/assets/javascripts/store/spree_theme.routes.js b/spree_theme/app/assets/javascripts/store/spree_theme.routes.js
new file mode 100644
index 00000000..6ba5c757
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/store/spree_theme.routes.js
@@ -0,0 +1,9 @@
+
+Spree.routes.admin_template_themes = Spree.pathFor('admin/template_themes')
+Spree.routes.admin_page_layouts = function(template_theme_id) {
+ return Spree.pathFor('admin/template_themes/'+template_theme_id+'/page_layouts')
+}
+Spree.routes.global_taxons_search = Spree.pathFor('api/taxons/global')
+
+//Spree.routes.global_taxons_search = "<%= spree.global_api_taxons_url(:format => :json) %>";'
+
diff --git a/spree_theme/app/assets/javascripts/superfish.js b/spree_theme/app/assets/javascripts/superfish.js
new file mode 100644
index 00000000..d594a739
--- /dev/null
+++ b/spree_theme/app/assets/javascripts/superfish.js
@@ -0,0 +1,262 @@
+/*
+ * jQuery Superfish Menu Plugin - v1.7.5
+ * Copyright (c) 2014 Joel Birch
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ */
+
+;(function ($, w) {
+ "use strict";
+
+ var methods = (function () {
+ // private properties and methods go here
+ var c = {
+ bcClass: 'sf-breadcrumb',
+ menuClass: 'sf-js-enabled',
+ anchorClass: 'sf-with-ul',
+ menuArrowClass: 'sf-arrows'
+ },
+ ios = (function () {
+ var ios = /iPhone|iPad|iPod/i.test(navigator.userAgent);
+ if (ios) {
+ // iOS clicks only bubble as far as body children
+ $(w).load(function () {
+ $('body').children().on('click', $.noop);
+ });
+ }
+ return ios;
+ })(),
+ wp7 = (function () {
+ var style = document.documentElement.style;
+ return ('behavior' in style && 'fill' in style && /iemobile/i.test(navigator.userAgent));
+ })(),
+ unprefixedPointerEvents = (function () {
+ return (!!w.PointerEvent);
+ })(),
+ toggleMenuClasses = function ($menu, o) {
+ var classes = c.menuClass;
+ if (o.cssArrows) {
+ classes += ' ' + c.menuArrowClass;
+ }
+ $menu.toggleClass(classes);
+ },
+ setPathToCurrent = function ($menu, o) {
+ return $menu.find('li.' + o.pathClass).slice(0, o.pathLevels)
+ .addClass(o.hoverClass + ' ' + c.bcClass)
+ .filter(function () {
+ return ($(this).children(o.popUpSelector).hide().show().length);
+ }).removeClass(o.pathClass);
+ },
+ toggleAnchorClass = function ($li) {
+ $li.children('a').toggleClass(c.anchorClass);
+ },
+ toggleTouchAction = function ($menu) {
+ var msTouchAction = $menu.css('ms-touch-action');
+ var touchAction = $menu.css('touch-action');
+ touchAction = touchAction || msTouchAction;
+ touchAction = (touchAction === 'pan-y') ? 'auto' : 'pan-y';
+ $menu.css({
+ 'ms-touch-action': touchAction,
+ 'touch-action': touchAction
+ });
+ },
+ applyHandlers = function ($menu, o) {
+ var targets = 'li:has(' + o.popUpSelector + ')';
+ if ($.fn.hoverIntent && !o.disableHI) {
+ $menu.hoverIntent(over, out, targets);
+ }
+ else {
+ $menu
+ .on('mouseenter.superfish', targets, over)
+ .on('mouseleave.superfish', targets, out);
+ }
+ var touchevent = 'MSPointerDown.superfish';
+ if (unprefixedPointerEvents) {
+ touchevent = 'pointerdown.superfish';
+ }
+ if (!ios) {
+ touchevent += ' touchend.superfish';
+ }
+ if (wp7) {
+ touchevent += ' mousedown.superfish';
+ }
+ $menu
+ .on('focusin.superfish', 'li', over)
+ .on('focusout.superfish', 'li', out)
+ .on(touchevent, 'a', o, touchHandler);
+ },
+ touchHandler = function (e) {
+ var $this = $(this),
+ $ul = $this.siblings(e.data.popUpSelector);
+
+ if ($ul.length > 0 && $ul.is(':hidden')) {
+ $this.one('click.superfish', false);
+ if (e.type === 'MSPointerDown' || e.type === 'pointerdown') {
+ $this.trigger('focus');
+ } else {
+ $.proxy(over, $this.parent('li'))();
+ }
+ }
+ },
+ over = function () {
+ var $this = $(this),
+ o = getOptions($this);
+ clearTimeout(o.sfTimer);
+ $this.siblings().superfish('hide').end().superfish('show');
+ },
+ out = function () {
+ var $this = $(this),
+ o = getOptions($this);
+ if (ios) {
+ $.proxy(close, $this, o)();
+ }
+ else {
+ clearTimeout(o.sfTimer);
+ o.sfTimer = setTimeout($.proxy(close, $this, o), o.delay);
+ }
+ },
+ close = function (o) {
+ o.retainPath = ($.inArray(this[0], o.$path) > -1);
+ this.superfish('hide');
+
+ if (!this.parents('.' + o.hoverClass).length) {
+ o.onIdle.call(getMenu(this));
+ if (o.$path.length) {
+ $.proxy(over, o.$path)();
+ }
+ }
+ },
+ getMenu = function ($el) {
+ return $el.closest('.' + c.menuClass);
+ },
+ getOptions = function ($el) {
+ return getMenu($el).data('sf-options');
+ };
+
+ return {
+ // public methods
+ hide: function (instant) {
+ if (this.length) {
+ var $this = this,
+ o = getOptions($this);
+ if (!o) {
+ return this;
+ }
+ var not = (o.retainPath === true) ? o.$path : '',
+ $ul = $this.find('li.' + o.hoverClass).add(this).not(not).removeClass(o.hoverClass).children(o.popUpSelector),
+ speed = o.speedOut;
+
+ if (instant) {
+ $ul.show();
+ speed = 0;
+ }
+ o.retainPath = false;
+ o.onBeforeHide.call($ul);
+ $ul.stop(true, true).animate(o.animationOut, speed, function () {
+ var $this = $(this);
+ o.onHide.call($this);
+ });
+ }
+ return this;
+ },
+ show: function () {
+ var o = getOptions(this);
+ if (!o) {
+ return this;
+ }
+ var $this = this.addClass(o.hoverClass),
+ $ul = $this.children(o.popUpSelector);
+
+ o.onBeforeShow.call($ul);
+ $ul.stop(true, true).animate(o.animation, o.speed, function () {
+ o.onShow.call($ul);
+ });
+ return this;
+ },
+ destroy: function () {
+ return this.each(function () {
+ var $this = $(this),
+ o = $this.data('sf-options'),
+ $hasPopUp;
+ if (!o) {
+ return false;
+ }
+ $hasPopUp = $this.find(o.popUpSelector).parent('li');
+ clearTimeout(o.sfTimer);
+ toggleMenuClasses($this, o);
+ toggleAnchorClass($hasPopUp);
+ toggleTouchAction($this);
+ // remove event handlers
+ $this.off('.superfish').off('.hoverIntent');
+ // clear animation's inline display style
+ $hasPopUp.children(o.popUpSelector).attr('style', function (i, style) {
+ return style.replace(/display[^;]+;?/g, '');
+ });
+ // reset 'current' path classes
+ o.$path.removeClass(o.hoverClass + ' ' + c.bcClass).addClass(o.pathClass);
+ $this.find('.' + o.hoverClass).removeClass(o.hoverClass);
+ o.onDestroy.call($this);
+ $this.removeData('sf-options');
+ });
+ },
+ init: function (op) {
+ return this.each(function () {
+ var $this = $(this);
+ if ($this.data('sf-options')) {
+ return false;
+ }
+ var o = $.extend({}, $.fn.superfish.defaults, op),
+ $hasPopUp = $this.find(o.popUpSelector).parent('li');
+ o.$path = setPathToCurrent($this, o);
+
+ $this.data('sf-options', o);
+
+ toggleMenuClasses($this, o);
+ toggleAnchorClass($hasPopUp);
+ toggleTouchAction($this);
+ applyHandlers($this, o);
+
+ $hasPopUp.not('.' + c.bcClass).superfish('hide', true);
+
+ o.onInit.call(this);
+ });
+ }
+ };
+ })();
+
+ $.fn.superfish = function (method, args) {
+ if (methods[method]) {
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+ }
+ else if (typeof method === 'object' || ! method) {
+ return methods.init.apply(this, arguments);
+ }
+ else {
+ return $.error('Method ' + method + ' does not exist on jQuery.fn.superfish');
+ }
+ };
+
+ $.fn.superfish.defaults = {
+ popUpSelector: 'ul,.sf-mega', // within menu context
+ hoverClass: 'sfHover',
+ pathClass: 'overrideThisToUse',
+ pathLevels: 1,
+ delay: 800,
+ animation: {opacity: 'show'},
+ animationOut: {opacity: 'hide'},
+ speed: 'normal',
+ speedOut: 'fast',
+ cssArrows: true,
+ disableHI: false,
+ onInit: $.noop,
+ onBeforeShow: $.noop,
+ onShow: $.noop,
+ onBeforeHide: $.noop,
+ onHide: $.noop,
+ onIdle: $.noop,
+ onDestroy: $.noop
+ };
+
+})(jQuery, window);
diff --git a/spree_theme/app/assets/stylesheets/_bootstrap_custom.scss b/spree_theme/app/assets/stylesheets/_bootstrap_custom.scss
new file mode 100644
index 00000000..02dc1f51
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/_bootstrap_custom.scss
@@ -0,0 +1,50 @@
+// Core variables and mixins
+@import "bootstrap/variables";
+@import "bootstrap/mixins";
+
+// Reset and dependencies
+@import "bootstrap/normalize";
+@import "bootstrap/print";
+//@import "bootstrap/glyphicons";
+
+// Core CSS
+@import "bootstrap/scaffolding";
+@import "bootstrap/type";
+@import "bootstrap/code";
+@import "bootstrap/grid";
+@import "bootstrap/tables";
+@import "bootstrap/forms";
+@import "bootstrap/buttons";
+
+// Components
+@import "bootstrap/component-animations";
+@import "bootstrap/dropdowns";
+@import "bootstrap/button-groups";
+@import "bootstrap/input-groups";
+@import "bootstrap/navs";
+@import "bootstrap/navbar";
+@import "bootstrap/breadcrumbs";
+@import "bootstrap/pagination";
+@import "bootstrap/pager";
+@import "bootstrap/labels";
+@import "bootstrap/badges";
+@import "bootstrap/jumbotron";
+@import "bootstrap/thumbnails";
+@import "bootstrap/alerts";
+@import "bootstrap/progress-bars";
+@import "bootstrap/media";
+@import "bootstrap/list-group";
+@import "bootstrap/panels";
+@import "bootstrap/responsive-embed";
+@import "bootstrap/wells";
+@import "bootstrap/close";
+
+// Components w/ JavaScript
+@import "bootstrap/modals";
+@import "bootstrap/tooltip";
+@import "bootstrap/popovers";
+@import "bootstrap/carousel";
+
+// Utility classes
+@import "bootstrap/utilities";
+@import "bootstrap/responsive-utilities";
diff --git a/spree_theme/app/assets/stylesheets/admin/login_abc.scss b/spree_theme/app/assets/stylesheets/admin/login_abc.scss
new file mode 100644
index 00000000..1c0306d6
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/admin/login_abc.scss
@@ -0,0 +1,47 @@
+
+ .admin-container{
+ margin: 150px auto 0 auto;
+ width: 500px;
+ }
+ .login-container{
+
+ }
+ /*.login-container table tbody tr:hover{
+ background-color: #5498da;
+ }*/
+ .admin-container-title{
+ text-align:center;
+ color:white;
+ }
+
+
+ .login-container{
+
+ background-color: #5498da;
+ padding: 10px 75px ;
+
+ h2{ padding:10px; }
+
+ form{
+
+ p { padding: 5px; }
+ label { color:white; }
+ input[type='submit']{
+ background-color: #9FC820;
+ /* border: solid 1px #009DE6;
+ */
+ }
+
+ }
+
+ table{
+ tbody {
+ tr {
+ &:hover td {
+ background-color: #5498da;
+ }
+ }
+ }
+ }
+ }
+
diff --git a/spree_theme/app/assets/stylesheets/admin/plugins/font-awesome-extra.css b/spree_theme/app/assets/stylesheets/admin/plugins/font-awesome-extra.css
index 9479d3dd..25e7e4b7 100644
--- a/spree_theme/app/assets/stylesheets/admin/plugins/font-awesome-extra.css
+++ b/spree_theme/app/assets/stylesheets/admin/plugins/font-awesome-extra.css
@@ -1,6 +1,12 @@
-.icon-eye:before {
+.fa-eye:before {
content: "\f06e";
}
-.icon-check-circle:before {
+.fa-check-circle:before {
content: "\f058";
}
+.fa-mobile-phone:before{
+ content: "\f10b";
+}
+.fa-desktop:before{
+ content: "\f108";
+}
diff --git a/spree_theme/app/assets/stylesheets/admin_login.css b/spree_theme/app/assets/stylesheets/admin_login.css
deleted file mode 100644
index ce21cf89..00000000
--- a/spree_theme/app/assets/stylesheets/admin_login.css
+++ /dev/null
@@ -1,38 +0,0 @@
- body{
- background-color: #EFEFEF;
- font-size: 90%;
- }
-
- .admin-box{
- }
- .admin-container{
- margin: 250px auto 0 auto;
- width: 500px;
- background-color: #73CD54;
- padding:15px 40px;
- /* copy from http://www.cnblogs.com/leejersey/p/3187039.html */
- -moz-border-radius: 15px; /* Firefox */
- -webkit-border-radius: 15px; /* Safari 和 Chrome */
- border-radius: 15px; /* Opera 10.5+, 以及使用了IE-CSS3的IE浏览器 */
-
- -moz-box-shadow: 5px 5px 8px #000; /* Firefox */
- -webkit-box-shadow: 5px 5px 8px #000; /* Safari 和 Chrome */
- box-shadow: 5px 5px 8px #000; /* Opera 10.5+, 以及使用了IE-CSS3的IE浏览器 */
-
- }
- .admin-container-title{
- text-align:center;
- color:white;
- }
-
- .admin-container form{
- margin: 0 0 0 115px;
- }
- .admin-container label{ color:white; }
- .admin-container input[type='submit']{
- color: #009DE6;
- /* background-color: #009DE6;
- border: solid 1px #009DE6;
- */
- padding: 2px 25px;
- }
diff --git a/spree_theme/app/assets/stylesheets/image-zoom.css.erb b/spree_theme/app/assets/stylesheets/image-zoom.css.erb
new file mode 100644
index 00000000..ecc7f2e8
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/image-zoom.css.erb
@@ -0,0 +1,38 @@
+.image-zoom{
+ display: inline-block;
+ cursor: default;
+ position: relative;
+}
+.zoom-loading{
+ text-align: center;
+ width: 32px;
+ height: 32px;
+ background: url(/shops/shared/images/zoom/loading.gif) no-repeat 0 0 transparent;
+ z-index: 110;
+ position: absolute;
+}
+.zoom-lens{
+ background: url(/shops/shared/images/zoom/zoom.png) repeat scroll 0 0;
+ cursor: move;
+ z-index: 120;
+ position: absolute;
+}
+.zoom-viewer {
+ overflow: hidden;
+ position: absolute;
+ background: #FFF;
+ z-index: 110;
+ border: 1px solid #DDDDDD;
+
+}
+.zoom-viewer img {
+ position: absolute;
+}
+.zoom-iframe {
+ z-index: -1;
+ filter:alpha(opacity=0);
+ -moz-opacity: 0.80;
+ opacity: 0.80;
+ position:absolute;
+ display:block;
+}
\ No newline at end of file
diff --git a/spree_theme/app/assets/stylesheets/interface.css b/spree_theme/app/assets/stylesheets/interface.css
index 39437272..d8636a6d 100644
--- a/spree_theme/app/assets/stylesheets/interface.css
+++ b/spree_theme/app/assets/stylesheets/interface.css
@@ -2,7 +2,7 @@
.sg_cover /* for interface.js*/
{
position:absolute !important;
- z-index:999999 !important;
+ z-index:99 !important;
background:white !important;
margin:0px !important;
padding:0px !important;
@@ -24,7 +24,7 @@
}
.sg_border{
position:absolute !important;
- z-index:999999 !important;
+ z-index:99 !important;
background:white !important;
background-color:orange !important;
margin:0px !important;
@@ -53,4 +53,4 @@
.sg_rejected{
background-color:#F00 !important;
background-image:none !important;
-}
\ No newline at end of file
+}
diff --git a/spree_theme/app/assets/stylesheets/jquery.layout.css b/spree_theme/app/assets/stylesheets/jquery.layout.css
index 14e507b5..6185acf4 100644
--- a/spree_theme/app/assets/stylesheets/jquery.layout.css
+++ b/spree_theme/app/assets/stylesheets/jquery.layout.css
@@ -19,9 +19,10 @@
* Just to make demo-pages look better - not actually relevant to Layout!
*/
body {
- font-family: Geneva, Arial, Helvetica, sans-serif;
+/* font-family: Geneva, Arial, Helvetica, sans-serif;
font-size: 100%;
*font-size: 80%;
+*/
}
/*
diff --git a/spree_theme/app/assets/stylesheets/jquery.lightbox.css b/spree_theme/app/assets/stylesheets/jquery.lightbox.css
new file mode 100644
index 00000000..38c50475
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/jquery.lightbox.css
@@ -0,0 +1,110 @@
+#lightbox{
+ position: absolute;
+ left: 0;
+ width: 100%;
+ z-index: 100;
+ text-align: center;
+ line-height: 0;
+ }
+
+#lightbox a img{ border: none; }
+
+#outerImageContainer{
+ position: relative;
+ background-color: #fff;
+ width: 250px;
+ height: 250px;
+ margin: 0 auto;
+ }
+
+#imageContainer{
+ padding: 10px;
+ }
+
+.lightbox-loading{
+ position: absolute;
+ top: 40%;
+ left: 0%;
+ height: 25%;
+ width: 100%;
+ text-align: center;
+ line-height: 0;
+ }
+#hoverNav{
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ z-index: 10;
+ }
+#imageContainer>#hoverNav{ left: 0;}
+#hoverNav a{ outline: none;}
+
+#prevLink, #nextLink{
+ width: 49%;
+ height: 100%;
+ background: transparent url(/shops/shared/images/lightbox/blank.gif) no-repeat; /* Trick IE into showing hover */
+ display: block;
+ }
+#prevLink { left: 0; float: left;}
+#nextLink { right: 0; float: right;}
+#prevLink:hover, #prevLink:visited:hover { background: url(/shops/shared/images/lightbox/prev.gif) left 50% no-repeat; }
+#nextLink:hover, #nextLink:visited:hover { background: url(/shops/shared/images/lightbox/next.gif) right 50% no-repeat; }
+
+/*** START : next / previous text links ***/
+#nextLinkText, #prevLinkText{
+color: #FF9834;
+font-weight:bold;
+text-decoration: none;
+}
+#nextLinkText{
+padding-left: 20px;
+}
+#prevLinkText{
+padding-right: 20px;
+}
+/*** END : next / previous text links ***/
+/*** START : added padding when navbar is on top ***/
+
+.ontop #imageData {
+ padding-top: 5px;
+}
+
+/*** END : added padding when navbar is on top ***/
+
+#imageDataContainer{
+ font: 10px Verdana, Helvetica, sans-serif;
+ background-color: #fff;
+ margin: 0 auto;
+ line-height: 1.4em;
+ }
+
+#imageData{
+ padding:0 10px;
+ }
+#imageData #imageDetails{ width: 70%; float: left; text-align: left; }
+#imageData #caption{ font-weight: bold; }
+#imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em; }
+#imageData #numberDisplay a { color: black; padding-left: 5px; padding-right: 5px;}
+#imageData #bottomNavClose{ width: 66px; float: right; padding-bottom: 0.7em; }
+#imageData #helpDisplay {clear: left; float: left; display: block; }
+
+.lightbox-overlay{
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 90;
+ width: 100%;
+ height: 500px;
+ background-color: #000;
+ filter:alpha(opacity=60);
+ -moz-opacity: 0.6;
+ opacity: 0.6 !important;
+ display: none;
+ }
+
+
+#lightboxIframe {
+ display: none;
+}
diff --git a/spree_theme/app/assets/stylesheets/store/_spree_theme_variables.scss b/spree_theme/app/assets/stylesheets/store/_spree_theme_variables.scss
new file mode 100644
index 00000000..7cb6e8d7
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/store/_spree_theme_variables.scss
@@ -0,0 +1,62 @@
+/*--------------------------------------*/
+/* Colors
+/*--------------------------------------*/
+$c_green: #8dba53 !default; /* Spree green */
+$c_red: #e45353 !default; /* Error red */
+
+$layout_background_color: #FFFFFF !default;
+$title_text_color: #404042 !default;
+$body_text_color: #404042 !default;
+$link_text_color: #00ADEE !default;
+
+$product_background_color: #FFFFFF !default;
+$product_title_text_color: #404042 !default;
+$product_body_text_color: #404042 !default;
+$product_link_text_color: #BBBBBB !default;
+
+/*--------------------------------------*/
+/* Fonts import from remote
+/*--------------------------------------*/
+/*@import url(//fonts.googleapis.com/css?family=Ubuntu:400,700,400italic,700italic|&subset=latin,cyrillic,greek,greek-ext,latin-ext,cyrillic-ext);
+*/
+
+/*--------------------------------------*/
+/* Font families
+/*--------------------------------------*/
+$ff_base: 'Ubuntu', sans-serif !default;
+
+/*--------------------------------------
+ | Font sizes
+ |--------------------------------------
+ |- Navigation
+ | */
+ $header_navigation_font_size: 14px !default;
+ $horizontal_navigation_font_size: 16px !default;
+ $main_navigation_header_font_size: 14px !default;
+ $main_navigation_font_size: 12px !default;
+/*|------------------------------------
+ |- Product Listing
+ | */
+ $product_list_name_font_size: 12px !default;
+ $product_list_price_font_size: 16px !default;
+ $product_list_header_font_size: 20px !default;
+ $product_list_search_font_size: 14px !default;
+/*|------------------------------------
+ |- Product Details
+ | */
+ $product_detail_name_font_size: 24px !default;
+ $product_detail_description_font_size: 12px !default;
+ $product_detail_price_font_size: 20px !default;
+ $product_detail_title_font_size: 14px !default;
+/*|------------------------------------
+ |- Basic
+ | */
+ $heading_font_size: 24px !default;
+ $sub_heading_font_size: 14px !default;
+ $button_font_size: 12px !default;
+ $input_box_font_size: 13px !default;
+ $base_font_size: 12px !default;
+ $border_color: lighten($body_text_color, 60) !default;
+ $default_border: 1px solid $border_color !default;
+ $button_border_color: rgba(0, 138, 189, .75) !default;
+ $table_head_color: lighten($body_text_color, 60) !default;
diff --git a/spree_theme/app/assets/stylesheets/store/spree_theme.client.css b/spree_theme/app/assets/stylesheets/store/spree_theme.client.css
deleted file mode 100644
index b41fc6d9..00000000
--- a/spree_theme/app/assets/stylesheets/store/spree_theme.client.css
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- *= require normalize
-*/
-#embeded_content_wrapper{
- position: absolute;
- top:0;
- left:0;
- right:0;
- height:30px;
- border-bottom: solid 1px #EBEBEB;
- background-color: #F8F8F8;
- z-index: 100;
- display: none;
-}
-#embeded_content_wrapper .theme_selection_wrapper{
- text-align:right;
-}
-
-#embeded_content_wrapper_icon{
- position: absolute;
- top:0;
- right:0;
- height:30px;
- width:30px;
- border: solid 1px #EBEBEB;
- background-color: #F8F8F8;
- z-index: 99;
- font-size: 0.7em;
-}
diff --git a/spree_theme/app/assets/stylesheets/store/spree_theme.client.css.scss b/spree_theme/app/assets/stylesheets/store/spree_theme.client.css.scss
new file mode 100644
index 00000000..da681ede
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/store/spree_theme.client.css.scss
@@ -0,0 +1,63 @@
+@import 'store/spree_theme_variables';
+@import 'image-zoom';
+@import 'jquery.lightbox';
+@import 'store/spree_china_checkout';
+
+html.turbolinks-progress-bar::before {
+ background-color: red !important;
+ height: 2px !important;
+}
+
+/* mobile required it as well */
+#embeded_content_wrapper{
+ position: absolute;
+ top:0;
+ left:0;
+ right:0;
+ height:30px;
+ border-bottom: solid 1px #EBEBEB;
+ background-color: #F8F8F8;
+ z-index: 100;
+ display: none;
+}
+#embeded_content_wrapper .theme_selection_wrapper{
+ text-align:right;
+}
+
+#embeded_content_wrapper_icon{
+ position: absolute;
+ top:0;
+ right:0;
+ height:30px;
+ width:30px;
+ border: solid 1px #EBEBEB;
+ background-color: #F8F8F8;
+ z-index: 99;
+ font-size: 0.7em;
+}
+/* state name */
+.hidden {
+ display: none;
+}
+
+/*--------------------------------------*/
+/* Flash notices & errors
+/*--------------------------------------*/
+/*
+.flash {
+ padding: 10px;
+ color: $layout_background_color;
+ font-weight: bold;
+ margin-bottom: 10px;
+
+ &.notice {
+ background-color: $link_text_color;
+ }
+ &.success {
+ background-color: $c_green;
+ }
+ &.error {
+ background-color: $c_red;
+ }
+}
+*/
\ No newline at end of file
diff --git a/spree_theme/app/assets/stylesheets/store/spree_theme.css b/spree_theme/app/assets/stylesheets/store/spree_theme.css
deleted file mode 100644
index e9b929ef..00000000
--- a/spree_theme/app/assets/stylesheets/store/spree_theme.css
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- *= require spree_theme_base
- *= require jquery.layout
- *= require normalize
- *= require interface
-*/
-
-#editor_panel
-{height:260px;
-}
-#page_layout_tree_inner
-{
- height:200px;
- overflow: auto;
-}
-.param_value_editor
-{
- height:200px;
- overflow: auto;
-}
-.editor-header
-{
- background-color: #B6B6B6;
-}
-
-
-.block
-{
- border: solid 1px gray;
- padding: 2px;
- margin: 2px;
-}
-
-.menu li{
- padding:5px;
- float:left;
-}
-ul.tabs{list-style:none; margin:0;padding:0;}
-.tabs li{
- padding:5px;
- float:left;
-}
-
-#editors span.option_item
-{
- display:inline-block;
- width:170px;
-}
-
-#editors div.pv{
- padding:2px;
-
-}
-#editors span.pv-name
-{
- display:inline-block;
- width:150px;
-}
-
-#editors input.pv-psv, select.pv-psv
-{
- display:inline-block;
- width:120px;
-}
-#editors input.pv-pv
-{
- display:inline-block;
- width:120px;
-}
-#section_select_dialog ul
-{
- list-style:none; margin: 0; padding: 0;
-}
-#section_select_dialog ul.titles li
-{
- white-space:nowrap;
-}
-
-#section_select_dialog li.selected
-{
- background-color: silver;
-}
-#section_select_dialog .details .selected
-{
- display:block;
-}
-#section_select_dialog .details div
-{
- display:none;
-}
-
-#editors label, #menu_and_template label
-{
- margin:0;
- padding:0;
- display:inline;
-}
-#publish ul
-{
- margin:0;
- padding:0;
-}
-
-#editor_panel a.selected
-{
- background-color: #22A7F2;
- color: white;
- font-weight: bold;
-}
-
diff --git a/spree_theme/app/assets/stylesheets/store/spree_theme.css.scss b/spree_theme/app/assets/stylesheets/store/spree_theme.css.scss
new file mode 100644
index 00000000..547d9697
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/store/spree_theme.css.scss
@@ -0,0 +1,145 @@
+@import "spree_theme_base";
+@import "interface";
+
+#editor_panel
+{ position: fixed;
+ bottom:0;
+ left:0;
+ right:0;
+ height:248px;
+ border-bottom: solid 1px #EBEBEB;
+ background-color: #F8F8F8;
+ z-index: 100;
+ display: none;
+}
+#editor_panel a.close{
+ position: absolute;
+ top:0;
+ right:0;
+ display: inline-block;
+ padding:5px;
+}
+#editor_panel_icon{
+ position: fixed;
+ bottom:0;
+ right:0;
+ height:30px;
+ width:30px;
+ border: solid 1px #EBEBEB;
+ background-color: #F8F8F8;
+ z-index: 99;
+ font-size: 0.7em;
+}
+#page_layout_tree_inner
+{
+ height:200px;
+ overflow: auto;
+}
+.param_value_editor
+{
+ height:200px;
+ overflow: auto;
+}
+.editor-header
+{
+ background-color: #B6B6B6;
+}
+
+
+.block
+{
+ border: solid 1px gray;
+ padding: 2px;
+ margin: 2px;
+}
+.block_header{ height:32px; }
+
+.menu li{
+ padding:5px;
+ float:left;
+}
+ul.tabs{list-style:none; margin:0;padding:0;}
+.tabs li{
+ padding: 5px;
+ float:left;
+}
+
+#editors span.option_item
+{
+ display:inline-block;
+ width:170px;
+}
+
+#editors div.pv{
+ padding:2px;
+
+}
+#editors span.pv-name
+{
+ display:inline-block;
+ width:150px;
+}
+
+#editors input.pv-psv, select.pv-psv
+{
+ display:inline-block;
+ width:120px;
+}
+#editors input.pv-pv
+{
+ display:inline-block;
+ width:120px;
+}
+#editors [type="checkbox"]{
+ vertical-align: bottom;
+}
+
+#section_select_dialog ul
+{
+ list-style:none; margin: 0; padding: 0;
+}
+#section_select_dialog ul.titles li
+{
+ white-space:nowrap;
+}
+
+#section_select_dialog li.selected
+{
+ background-color: silver;
+}
+#section_select_dialog .details .selected
+{
+ display:block;
+}
+#section_select_dialog .details div
+{
+ display:none;
+}
+
+#editors label, #menu_and_template label
+{
+ margin:0;
+ padding:0;
+ display:inline;
+}
+#publish ul
+{
+ margin:0;
+ padding:0;
+}
+
+#editor_panel a.selected
+{
+ background-color: #22A7F2;
+ color: white;
+ font-weight: bold;
+}
+
+#dialog_for_editor{
+ background-color:white;
+ padding: 25px 35px;
+ display:none;
+}
+
+.simplemodal-overlay{ background-color:black; }
+form.editable input { color: black; }
diff --git a/spree_theme/app/assets/stylesheets/store/spree_theme.desktop.css.scss b/spree_theme/app/assets/stylesheets/store/spree_theme.desktop.css.scss
new file mode 100644
index 00000000..14aea5b9
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/store/spree_theme.desktop.css.scss
@@ -0,0 +1,4 @@
+
+@import 'normalize';
+@import 'store/spree_theme.client';
+
diff --git a/spree_theme/app/assets/stylesheets/store/spree_theme.mobile.css.scss b/spree_theme/app/assets/stylesheets/store/spree_theme.mobile.css.scss
new file mode 100644
index 00000000..9bdcda3a
--- /dev/null
+++ b/spree_theme/app/assets/stylesheets/store/spree_theme.mobile.css.scss
@@ -0,0 +1,3 @@
+@import "font-awesome";
+@import "bootstrap_custom";
+@import 'store/spree_theme.client';
diff --git a/spree_comments/app/controllers/spree/admin/comment_types_controller.rb b/spree_theme/app/controllers/spree/admin/comment_types_controller.rb
similarity index 100%
rename from spree_comments/app/controllers/spree/admin/comment_types_controller.rb
rename to spree_theme/app/controllers/spree/admin/comment_types_controller.rb
diff --git a/spree_comments/app/controllers/spree/admin/comments_controller.rb b/spree_theme/app/controllers/spree/admin/comments_controller.rb
similarity index 100%
rename from spree_comments/app/controllers/spree/admin/comments_controller.rb
rename to spree_theme/app/controllers/spree/admin/comments_controller.rb
diff --git a/spree_comments/app/controllers/spree/admin/orders_controller_decorator.rb b/spree_theme/app/controllers/spree/admin/orders_controller_decorator.rb
similarity index 100%
rename from spree_comments/app/controllers/spree/admin/orders_controller_decorator.rb
rename to spree_theme/app/controllers/spree/admin/orders_controller_decorator.rb
diff --git a/spree_theme/app/controllers/spree/admin/page_layout_controller.rb b/spree_theme/app/controllers/spree/admin/page_layout_controller.rb
deleted file mode 100644
index aebd2294..00000000
--- a/spree_theme/app/controllers/spree/admin/page_layout_controller.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-module Spree
- module Admin
- class PageLayoutController< ResourceController
- respond_to :html, :json, :js #update title required json
-
- def update_resource
- @template_theme = TemplateTheme.find( params[:template_theme_id])
- assigned_resource_ids = params[:assigned_resource_ids]
- #assigned_resource_ids could be ['']
- assigned_resource_ids.select!(&:present?) if assigned_resource_ids.kind_of? Array
- section_piece_with_resources = @page_layout.section_pieces.with_resources.first
- if assigned_resource_ids.present?
- if section_piece_with_resources.present?
- section_piece_with_resources.wrapped_resources.each_with_index{|wrapped_resource,index|
- resource_id = assigned_resource_ids[index]
- resource = wrapped_resource.resource_class.find resource_id
- @template_theme.assign_resource(resource, @page_layout, index)
- }
- else# assigned taxon
- assigned_resource_ids = assigned_resource_ids.split(',') if assigned_resource_ids.kind_of? String
- assigned_resource_ids.each_with_index{|resource_id, index|
- resource = SpreeTheme.taxon_class.find resource_id
- @template_theme.assign_resource(resource, @page_layout, index)
- }
- end
- else #unassign resource
- if section_piece_with_resources.present?
- section_piece_with_resources.wrapped_resources.each_with_index{|wrapped_resource,index|
- @template_theme.unassign_resource(wrapped_resource.resource_class , @page_layout, index)
- }
- else
- @template_theme.unassign_resource(SpreeTheme.taxon_class, @page_layout)
- end
- end
- @assigned_resources = @template_theme.assigned_resources_by_page_layout( @page_layout )
- end
-
- #update section_context
- def update_context
- section_contexts = params[:section_contexts]
- specific_taxon_ids = params[:specific_taxon_ids]
- if section_contexts.present?
- @page_layout.update_section_context(section_contexts )
- else
- @page_layout.update_section_context( PageLayout::ContextEnum.either )
- end
- @template_theme = TemplateTheme.find( params[:template_theme_id])
- if specific_taxon_ids.present?
- @specific_taxons = Spree::SpecificTaxon.find specific_taxon_ids.split(',')
- @specific_taxons.each_with_index{|resource, index|
- @template_theme.assign_resource(resource, @page_layout, index)
- }
- else
- @specific_taxons = []
- @template_theme.assigned_resources(Spree::SpecificTaxon,@page_layout).each_with_index{|assigned_resource,index|
- if assigned_resource.present?
- @template_theme.unassign_resource(Spree::SpecificTaxon, @page_layout, index)
- end
- }
- end
-
- end
-
- #update datasource
- def update_data_source
- section_data_source = params[:section_data_source]
- if section_data_source.present?
- @page_layout.update_data_source(section_data_source.to_sym )
- else
- @page_layout.update_data_source( PageLayout::DataSourceEmpty )
- end
- end
-
- def update_other
- view_as_clickable = params[:view_as_clickable]
- @page_layout.update_content_param( {:view_as_clickable=>view_as_clickable} )
- end
-
- def config_resource
- @template_theme = TemplateTheme.find( params[:template_theme_id] )
- end
-
- def config_context
- @template_theme = TemplateTheme.find( params[:template_theme_id] )
- end
-
- def config_data_source
- @template_theme = TemplateTheme.find( params[:template_theme_id] )
- end
-
- def config_other
- @template_theme = TemplateTheme.find( params[:template_theme_id] )
- end
-
- end
- end
-end
\ No newline at end of file
diff --git a/spree_theme/app/controllers/spree/admin/page_layouts_controller.rb b/spree_theme/app/controllers/spree/admin/page_layouts_controller.rb
new file mode 100644
index 00000000..48fe0e19
--- /dev/null
+++ b/spree_theme/app/controllers/spree/admin/page_layouts_controller.rb
@@ -0,0 +1,97 @@
+module Spree
+ module Admin
+ class PageLayoutsController< ResourceController
+ respond_to :html, :json, :js #update title required json
+
+ def update_resource
+ @template_theme = TemplateTheme.find( params[:template_theme_id])
+ assigned_resource_ids = params[:assigned_resource_ids]
+ #assigned_resource_ids could be ['']
+ assigned_resource_ids.select!(&:present?) if assigned_resource_ids.kind_of? Array
+ section_piece_with_resources = @page_layout.section_pieces.with_resources.first
+ if assigned_resource_ids.present?
+ if section_piece_with_resources.present?
+ section_piece_with_resources.wrapped_resources.each_with_index{|wrapped_resource,index|
+ resource_id = assigned_resource_ids[index]
+ resource = wrapped_resource.resource_class.find resource_id
+ @template_theme.assign_resource(resource, @page_layout, index)
+ }
+ else# assigned taxon
+ assigned_resource_ids = assigned_resource_ids.split(',') if assigned_resource_ids.kind_of? String
+ assigned_resource_ids.each_with_index{|resource_id, index|
+ resource = SpreeTheme.taxon_class.find resource_id
+ @template_theme.assign_resource(resource, @page_layout, index)
+ }
+ end
+ else #unassign resource
+ if section_piece_with_resources.present?
+ section_piece_with_resources.wrapped_resources.each_with_index{|wrapped_resource,index|
+ @template_theme.unassign_resource(wrapped_resource.resource_class , @page_layout, index)
+ }
+ else
+ @template_theme.unassign_resource(SpreeTheme.taxon_class, @page_layout)
+ end
+ end
+ @assigned_resources = @template_theme.assigned_resources_by_page_layout( @page_layout )
+ end
+
+ #update section_context
+ def update_context
+ section_contexts = params[:section_contexts]
+ specific_taxon_ids = params[:specific_taxon_ids]
+ if section_contexts.present?
+ @page_layout.update_section_context(section_contexts )
+ else
+ @page_layout.update_section_context( PageLayout::ContextEnum.either )
+ end
+ @template_theme = TemplateTheme.find( params[:template_theme_id])
+ if specific_taxon_ids.present?
+ @specific_taxons = Spree::SpecificTaxon.find specific_taxon_ids.split(',')
+ @specific_taxons.each_with_index{|resource, index|
+ @template_theme.assign_resource(resource, @page_layout, index)
+ }
+ else
+ @specific_taxons = []
+ @template_theme.assigned_resources(Spree::SpecificTaxon,@page_layout).each_with_index{|assigned_resource,index|
+ if assigned_resource.present?
+ @template_theme.unassign_resource(Spree::SpecificTaxon, @page_layout, index)
+ end
+ }
+ end
+
+ end
+
+ #update datasource
+ def update_data_source
+ section_data_source = params[:section_data_source]
+ if section_data_source.present?
+ @page_layout.update_data_source(section_data_source.to_sym )
+ else
+ @page_layout.update_data_source( PageLayout::DataSourceEmpty )
+ end
+ end
+
+ def update_other
+ view_as_clickable = params[:view_as_clickable]
+ @page_layout.update_content_param( {:view_as_clickable=>view_as_clickable} )
+ end
+
+ def config_resource
+ @template_theme = TemplateTheme.find( params[:template_theme_id] )
+ end
+
+ def config_context
+ @template_theme = TemplateTheme.find( params[:template_theme_id] )
+ end
+
+ def config_data_source
+ @template_theme = TemplateTheme.find( params[:template_theme_id] )
+ end
+
+ def config_other
+ @template_theme = TemplateTheme.find( params[:template_theme_id] )
+ end
+
+ end
+ end
+end
\ No newline at end of file
diff --git a/spree_comments/app/controllers/spree/admin/shipments_controller_decorator.rb b/spree_theme/app/controllers/spree/admin/shipments_controller_decorator.rb
similarity index 100%
rename from spree_comments/app/controllers/spree/admin/shipments_controller_decorator.rb
rename to spree_theme/app/controllers/spree/admin/shipments_controller_decorator.rb
diff --git a/spree_theme/app/controllers/spree/admin/template_files_controller.rb b/spree_theme/app/controllers/spree/admin/template_files_controller.rb
index c6a2a585..18ae0a68 100644
--- a/spree_theme/app/controllers/spree/admin/template_files_controller.rb
+++ b/spree_theme/app/controllers/spree/admin/template_files_controller.rb
@@ -1,11 +1,18 @@
module Spree
module Admin
class TemplateFilesController < Spree::Admin::ResourceController
-
-
+
+
def collection
- model_class.where( ["theme_id in (?)", Spree::Site.current.template_theme_ids] ).includes(:template_theme)
+ return @collection if @collection.present?
+ # params[:q] can be blank upon pagination
+ params[:q] = {} if params[:q].blank?
+
+ @collection = model_class.where( ["theme_id in (?)", Spree::Store.current.template_theme_ids] ).includes(:template_theme)
+ @search = @collection.ransack(params[:q])
+
+ @search.result.page(params[:page]).per(Spree::Config[:orders_per_page]).order('theme_id')
end
- end
+ end
end
-end
+end
diff --git a/spree_theme/app/controllers/spree/admin/template_themes_controller.rb b/spree_theme/app/controllers/spree/admin/template_themes_controller.rb
index c9dad796..c590faff 100644
--- a/spree_theme/app/controllers/spree/admin/template_themes_controller.rb
+++ b/spree_theme/app/controllers/spree/admin/template_themes_controller.rb
@@ -7,7 +7,7 @@ class TemplateThemesController < ResourceController #Spree::Admin::BaseControlle
def index
native
end
-
+
#list themes
def native
@themes = TemplateTheme.native
@@ -19,106 +19,76 @@ def foreign
@themes = @themes.select{|theme| theme.template_releases.present?}
end
- # description - import theme with taxonomy into current site
- # in this way, it is simpler for user, click 'buy', done.
- def import
- imported_theme = @template_theme.import_with_resource( )
- if imported_theme.present?
- if imported_theme.site.template_themes.count == 1
- imported_theme.site.apply_theme imported_theme
- end
- flash[:success] = Spree.t('notice_messages.theme_imported')
- else
- flash[:success] = Spree.t('notice_messages.theme_not_imported')
- end
-
- respond_to do |format|
- format.html { redirect_to(foreign_admin_template_themes_url) }
- end
- end
-
+
#apply this theme to site
def apply
- SpreeTheme.site_class.current.apply_theme @template_theme
- respond_with(@template_theme)
+ Spree::Store.current.apply_theme @template_theme
+ respond_with(@template_theme)
end
begin 'design shop'
-
- def prepare_import
- end
-
+
+ #def prepare_import
+ #end
+
#copy selected theme to new theme
def copy
@original_theme = TemplateTheme.find(params[:id])
#copy theme, layout, param_value
- @new_theme = @original_theme.copy_to_new
-
+ @new_theme = @original_theme.duplicate
+
respond_to do |format|
format.html { redirect_to(admin_template_themes_url) }
- end
+ end
end
def release
- #create template_release before call lg.release
- if @template_theme.has_native_layout?
+ #create template_release before call lg.release
+ if @template_theme.has_native_layout?
@template_theme.release
end
- @themes = TemplateTheme.native
- render :action=>'native'
- end
-
-
- def create
- invoke_callbacks(:create, :before)
- @object.attributes = params[object_name]
- if @object.save
- invoke_callbacks(:create, :after)
- flash[:success] = flash_message_for(@object, :successfully_created)
- respond_with(@object) do |format|
- format.html { redirect_to location_after_save }
- format.js { render :layout => false }
- end
- else
- invoke_callbacks(:create, :fails)
- respond_with(@object)
+ if @template_theme.mobile.present?
+ @template_theme.mobile.release
end
+ flash[:success] = Spree.t('notice_messages.theme_released')
+ @themes = TemplateTheme.native
+ render :action=>'native'
end
end
-
-
-
+
+
+
protected
def collection_actions
[:index, :native, :foreign]
end
-
- # description - it is not using
+
+ # description - it is not using
# params
# assigned_resource_ids: required, a hash, key is page_layout_id
- # ex. {"30"=>[""], "3"=>[""]}
- # template_files: required, a array of template_file attributes
+ # ex. {"30"=>[""], "3"=>[""]}
+ # template_files: required, a array of template_file attributes
#def import
# #FIXME support config template when import theme
- # #template_files = params[:template_files].collect{|file| TemplateFile.new( file) }.select{|file| file.attachment.present? }
+ # #template_files = params[:template_files].collect{|file| TemplateFile.new( file) }.select{|file| file.attachment.present? }
# #assigned_resource_ids = Hash[ params[:assigned_resource_ids].collect{|key,val|
# # [key.to_i,{ @template_theme.get_resource_class_key(SpreeTheme.taxon_class) => val.select(&:present?).collect(&:to_i)}]
# #}]
# #new_theme_attributes = { :assigned_resource_ids=>assigned_resource_ids,
# # :template_files => template_files
- # #}
+ # #}
# imported_theme = @template_theme.import( new_theme_attributes = {} )
# if imported_theme.present?
# flash[:success] = Spree.t('notice_messages.theme_imported')
# else
# flash[:success] = Spree.t('notice_messages.theme_not_imported')
- # end
+ # end
# respond_to do |format|
# format.html { redirect_to(foreign_admin_template_themes_url) }
- # end
+ # end
#end
-
+
end
end
end
diff --git a/spree_theme/app/controllers/spree/comments_controller.rb b/spree_theme/app/controllers/spree/comments_controller.rb
index 11244424..530d1256 100644
--- a/spree_theme/app/controllers/spree/comments_controller.rb
+++ b/spree_theme/app/controllers/spree/comments_controller.rb
@@ -1,15 +1,15 @@
module Spree
class CommentsController < StoreController
before_filter :initialize_comment, :only => [:create, :new_to_site]
-
+
def new_to_site
- @comment.commentable = Spree::Site.current
+ @comment.commentable = Spree::Store.current
end
-
+
def create
- @comment.attributes = object_params
+ @comment.attributes = permitted_resource_params
if @comment.save
- flash[:success] = Spree.t(:comment_successfully_created, :scope=>@comment.comment_scope)
+ flash[:success] = Spree.t(:comment_successfully_created)
respond_with(@comment) do |format|
format.html { redirect_to :back }
format.js { render :layout => false }
@@ -18,28 +18,17 @@ def create
respond_with(@comment)
end
end
-
+
private
-
+
def initialize_comment
@comment = Comment.new( )
@comment.user = try_spree_current_user
end
-
- # comment{commentable_id, commentable_type, user_email}
- def object_params
- comment_params = params[:comment]
- #user_email = comment_params.delete( :user_email )
- #if user_email
- # user = User.find_or_initialize_by_email( user_email )
- # if user.persited?
- # comment_params[:user_id] = user.id
- # else
- # comment_params[:user] = user
- # end
- #end
- comment_params
- end
+
+ def permitted_resource_params
+ params.require('comment').permit( permitted_attributes.comment_attributes )
+ end
end
-
-end
\ No newline at end of file
+
+end
diff --git a/spree_theme/app/controllers/spree/decorators/api_products_controller_decorator.rb b/spree_theme/app/controllers/spree/decorators/api_products_controller_decorator.rb
new file mode 100644
index 00000000..44e8e99e
--- /dev/null
+++ b/spree_theme/app/controllers/spree/decorators/api_products_controller_decorator.rb
@@ -0,0 +1,4 @@
+Spree::Api::ProductsController.class_eval do
+
+
+end
diff --git a/spree_theme/app/controllers/spree/decorators/base_controller_decorator.rb b/spree_theme/app/controllers/spree/decorators/base_controller_decorator.rb
index b2517309..2e9b95e3 100644
--- a/spree_theme/app/controllers/spree/decorators/base_controller_decorator.rb
+++ b/spree_theme/app/controllers/spree/decorators/base_controller_decorator.rb
@@ -17,15 +17,24 @@ module Spree
# end
#end
#override spree_core/controller_helper/auth#unauthorized
- def unauthorized
- url = new_admin_session_path
- if try_spree_current_user
- flash[:error] = Spree.t(:authorization_failure)
- redirect_to new_admin_session_path
- else
- store_location
- redirect_to new_admin_session_path
- end
- end
+ # def unauthorized
+ # url = new_admin_session_path
+ # if try_spree_current_user
+ # flash[:error] = Spree.t(:authorization_failure)
+ # redirect_to new_admin_session_path
+ # else
+ # store_location
+ # redirect_to new_admin_session_path
+ # end
+ # end
+ end
+
+end
+
+module Spree::Admin
+ BaseController.class_eval do
+ rescue_from CanCan::AccessDenied do |exception|
+ redirect_to new_admin_session_path
end
+ end
end
\ No newline at end of file
diff --git a/spree_theme/app/controllers/spree/decorators/checkout_controller_decorator.rb b/spree_theme/app/controllers/spree/decorators/checkout_controller_decorator.rb
index 871f2794..a046dd47 100644
--- a/spree_theme/app/controllers/spree/decorators/checkout_controller_decorator.rb
+++ b/spree_theme/app/controllers/spree/decorators/checkout_controller_decorator.rb
@@ -1,39 +1,15 @@
#encoding: utf-8
module Spree
CheckoutController.class_eval do
- # Updates the order and advances to the next state (when possible.)
- def update
- if @order.update_attributes(object_params)
- fire_event('spree.checkout.update')
+ before_action :associate_terminal
- while(@order.next) do
- if pay_with_billing_integration?
- break
- end
- end
- #since update is override, call it explicitly for alipay
- if pay_with_billing_integration?
- handle_billing_integration
- return
- end
-
- unless @order.completed?
- flash[:error] = @order.errors.full_messages.join("\n")
- redirect_to checkout_state_path(@order.state) and return
- end
-
- if @order.completed?
- session[:order_id] = nil
- flash.notice = Spree.t(:order_processed_successfully)
- flash[:commerce_tracking] = "nothing special"
- redirect_to completion_route
- else
- redirect_to checkout_state_path(@order.state)
- end
- else
- render :edit
+ def associate_terminal
+ @order ||= current_order
+ if @order
+ @order.associate_terminal!(current_terminal) if @order.user_terminal != current_terminal
end
end
+
private
# For payment step, filter order parameters to produce the expected nested
# attributes for a single payment and its source, discarding attributes
@@ -53,14 +29,6 @@ def object_params
end
params[:order]
end
-
- def pay_with_billing_integration?
- if @order.next_step_complete?
- if @order.pending_payments.first.payment_method.kind_of? BillingIntegration
- return true
- end
- end
- return false
- end
+
end
end
diff --git a/spree_theme/app/controllers/spree/decorators/orders_controller_decorator.rb b/spree_theme/app/controllers/spree/decorators/orders_controller_decorator.rb
index c086008a..e43c12b7 100644
--- a/spree_theme/app/controllers/spree/decorators/orders_controller_decorator.rb
+++ b/spree_theme/app/controllers/spree/decorators/orders_controller_decorator.rb
@@ -1,6 +1,7 @@
#encoding: utf-8
module Spree
OrdersController.class_eval do
- respond_to :html, :js
+ # action :update, :edit, :show, :populate support ajax
+ respond_to :html, :js
end
-end
\ No newline at end of file
+end
diff --git a/spree_theme/app/controllers/spree/decorators/store_controller_decorator.rb b/spree_theme/app/controllers/spree/decorators/store_controller_decorator.rb
index 82e4cbb2..2e9a3275 100644
--- a/spree_theme/app/controllers/spree/decorators/store_controller_decorator.rb
+++ b/spree_theme/app/controllers/spree/decorators/store_controller_decorator.rb
@@ -3,11 +3,18 @@ module Spree
StoreController.class_eval do
#override spree_front/store_controller#unauthorized
def unauthorized
- if @template.blank?
+ if @theme.blank?
# unlogged user access /account would trigger unauthorized without initialize_template,
initialize_template( root_path )
end
render 'spree/shared/unauthorized', :status => 401
- end
+ end
+
+ def config_locale
+ # under_construction,unauthorized @theme is nil
+ return @theme.locale if @theme && @theme.locale.present?
+ Spree::Frontend::Config[:locale]
+ end
+
end
end
\ No newline at end of file
diff --git a/spree_theme/app/controllers/spree/page_layouts_controller.rb b/spree_theme/app/controllers/spree/page_layouts_controller.rb
new file mode 100644
index 00000000..832d174f
--- /dev/null
+++ b/spree_theme/app/controllers/spree/page_layouts_controller.rb
@@ -0,0 +1,79 @@
+module Spree
+ class PageLayoutsController < Spree::StoreController
+
+ def edit
+ @template_theme = TemplateTheme.find( params[:template_theme_id] )
+ @page_layout = PageLayout.find( params[:id] )
+
+ respond_to do |format|
+ format.js{ render "application/dialog_for_editor"}
+ end
+
+ end
+
+ def update
+ @template_theme = TemplateTheme.find( params[:template_theme_id] )
+ @page_layout = PageLayout.find( params[:id] )
+
+ if @page_layout.update_attributes( permitted_resource_attributes )
+ respond_with(@page_layout) do |format|
+ format.js { render :layout => false }
+ end
+ else
+ respond_with(@page_layout) do |format|
+ format.js { render layout: false }
+ end
+ end
+ end
+
+ # params
+ # layout_id: selected page_layout_id
+ # selected_section_id: selected section_root_id
+ def update_layout_tree
+ @theme = TemplateTheme.find(params[:id])
+ op = params[:op]
+ selected_page_layout_id = params[:layout_id]
+ selected_section_id = params[:selected_section_id]
+ selected_type = params[:selected_type]
+ @selected_page_layout = @theme.page_layout.self_and_descendants.find(selected_page_layout_id)
+ if op=='promote'
+ @selected_page_layout.promote
+ elsif op=='demote'
+ @selected_page_layout.demote
+ elsif op=='move_left'
+ @selected_page_layout.move_left
+ elsif op=='move_right'
+ @selected_page_layout.move_right
+ elsif op=='add_child'
+ section = Spree::Section.roots.find(selected_section_id)
+ #if selected_type=='Section'
+ @theme.add_section(section,@selected_page_layout)
+ #else
+ # @selected_page_layout.add_layout_tree(selected_id)
+ #end
+ #@layout.reload
+ elsif op=='del_self'
+ @selected_page_layout.destroy unless @selected_page_layout.root?
+ @selected_page_layout = @selected_page_layout.parent
+ #FIXME update param_values in editor
+ #@layout.reload
+ end
+ @theme.page_layout.reload #layout is changed
+ render :partial=>"layout_tree1"
+ end
+
+ # user disable a section in the current layout tree
+ def disable_section
+ layout_id = params[:layout_id]
+ layout = PageLayout.find(layout_id)
+ se = PageEvent::SectionEvent.new("disable_section", layout )
+ se.notify
+ end
+
+ def permitted_resource_attributes
+ params.require('page_layout').permit( permitted_attributes.page_layout_attributes )
+ end
+
+ end
+
+end
\ No newline at end of file
diff --git a/spree_theme/app/controllers/spree/template_themes_controller.rb b/spree_theme/app/controllers/spree/template_themes_controller.rb
index 8058c1c8..e0982a57 100644
--- a/spree_theme/app/controllers/spree/template_themes_controller.rb
+++ b/spree_theme/app/controllers/spree/template_themes_controller.rb
@@ -5,65 +5,56 @@ class TemplateThemesController < Spree::StoreController
delegate :taxon_class,:site_class, :to=>:"SpreeTheme"
def page
- #if SpreeTheme.site_class.current.dalianshops?
- # redirect_to new_site_path
- #end
- end
-
- def under_construction
- #logger.debug "request.env[/devise/]= #{request.env['devise.mapping']},#{warden.inspect}"
+ end
+
+ def under_construction
+ #logger.debug "request.env[/devise/]= #{request.env['devise.mapping']},#{warden.inspect}"
#require spree_auth_devise
- render "under_construction", layout:"under_construction"
+ render "under_construction", layout: "under_construction"
end
-
+
# @theme is required for xhr
def new_admin_session
- @user = Spree::User.new
+ #@user = Spree::User.new
end
-
+
# @theme is required for xhr
def create_admin_session
user_params = params[:spree_user]
@user = Spree.user_class.unscoped.admin.find_for_authentication(:email => user_params[:email])
if @user.present?
if @user.valid_password?(user_params[:password])
- sign_in :spree_user, @user
- end
+ sign_in :spree_user, @user
+ end
end
#spree_user_signed_in? defined in devise/lib/controllers/helpers.rb
if spree_user_signed_in?
#warden.authenticate?
# host is required, current_user.site may not be current site, we allow user login from dalianshops.com
respond_with do |format|
- format.html{ redirect_to admin_url(:host=> current_spree_user.site.subdomain ) }
+ # site_custom_domain/admin conficlt with site.dalianshops.com/admin
+ # current host maybe dalianshops.com or custom domain
+ if is_from_system_domain?
+ format.html{ redirect_to admin_url(:host=> current_spree_user.site.subdomain ) }
+ else
+ format.html{ redirect_to admin_url }
+ end
end
else
- flash.now[:error] = t('devise.failure.invalid')
+ flash.now[:error] = t('devise.failure.invalid')
render "new_admin_session"
end
end
-
-
-
+
+
+
# params for preview
# d: domain of website
# c: menu_id
def preview
-
- # @lg = PageTag::PageGenerator.previewer( @menu, @theme, {:resource=>(@resource.nil? ? nil:@resource),:controller=>self})
- # html = @lg.generate
- # css,js = @lg.generate_assets
- #insert css to html
- # style = %Q!!
- #editor_panel require @theme, @editors, @editor ...
- # html.insert(html.index(""),style)
- # html.insert(html.index(" |