aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile34
-rw-r--r--actionmailer/CHANGELOG.md11
-rw-r--r--actionmailer/README.rdoc6
-rw-r--r--actionmailer/actionmailer.gemspec3
-rw-r--r--actionmailer/lib/action_mailer/base.rb21
-rw-r--r--actionmailer/lib/action_mailer/delivery_job.rb4
-rw-r--r--actionmailer/lib/action_mailer/message_delivery.rb101
-rw-r--r--actionmailer/lib/action_mailer/test_case.rb9
-rw-r--r--actionmailer/lib/action_mailer/test_helper.rb12
-rw-r--r--actionmailer/test/abstract_unit.rb9
-rw-r--r--actionmailer/test/assert_select_email_test.rb4
-rw-r--r--actionmailer/test/asset_host_test.rb5
-rw-r--r--actionmailer/test/base_test.rb36
-rw-r--r--actionmailer/test/delivery_methods_test.rb24
-rw-r--r--actionmailer/test/i18n_with_controller_test.rb2
-rw-r--r--actionmailer/test/log_subscriber_test.rb2
-rw-r--r--actionmailer/test/message_delivery_test.rb33
-rw-r--r--actionmailer/test/test_helper_test.rb22
-rw-r--r--actionmailer/test/url_test.rb2
-rw-r--r--actionpack/CHANGELOG.md59
-rw-r--r--actionpack/actionpack.gemspec5
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb72
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb87
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb10
-rw-r--r--actionpack/lib/action_dispatch/journey/router.rb40
-rw-r--r--actionpack/lib/action_dispatch/middleware/public_exceptions.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/remote_ip.rb90
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb73
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/tag.rb3
-rw-r--r--actionpack/test/controller/parameters/accessors_test.rb125
-rw-r--r--actionpack/test/controller/parameters/mutators_test.rb99
-rw-r--r--actionpack/test/controller/parameters/parameters_permit_test.rb75
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb11
-rw-r--r--actionpack/test/dispatch/request_test.rb37
-rw-r--r--actionpack/test/dispatch/static_test.rb24
-rw-r--r--actionpack/test/fixtures/public/gzip/application-a71b3024f80aea3181c09774ca17e712.js4
-rw-r--r--actionpack/test/fixtures/public/gzip/application-a71b3024f80aea3181c09774ca17e712.js.gzbin0 -> 38457 bytes
-rw-r--r--actionpack/test/fixtures/公共/gzip/application-a71b3024f80aea3181c09774ca17e712.js4
-rw-r--r--actionpack/test/fixtures/公共/gzip/application-a71b3024f80aea3181c09774ca17e712.js.gzbin0 -> 38457 bytes
-rw-r--r--actionpack/test/journey/router_test.rb38
-rw-r--r--actionview/CHANGELOG.md6
-rw-r--r--actionview/actionview.gemspec3
-rw-r--r--actionview/lib/action_view/helpers/asset_tag_helper.rb4
-rw-r--r--actionview/lib/action_view/helpers/date_helper.rb12
-rw-r--r--actionview/lib/action_view/helpers/form_helper.rb2
-rw-r--r--actionview/lib/action_view/helpers/form_options_helper.rb6
-rw-r--r--actionview/lib/action_view/helpers/output_safety_helper.rb6
-rw-r--r--actionview/lib/action_view/helpers/rendering_helper.rb4
-rw-r--r--actionview/lib/action_view/helpers/sanitize_helper.rb2
-rw-r--r--actionview/lib/action_view/helpers/tags/placeholderable.rb32
-rw-r--r--actionview/lib/action_view/helpers/tags/text_area.rb4
-rw-r--r--actionview/lib/action_view/helpers/tags/text_field.rb4
-rw-r--r--actionview/test/activerecord/controller_runtime_test.rb2
-rw-r--r--actionview/test/template/form_helper_test.rb168
-rw-r--r--actionview/test/template/sanitize_helper_test.rb2
-rw-r--r--activejob/README.md2
-rw-r--r--activejob/Rakefile1
-rw-r--r--activejob/activejob.gemspec2
-rw-r--r--activejob/lib/active_job/callbacks.rb2
-rw-r--r--activejob/lib/active_job/gem_version.rb2
-rw-r--r--activejob/lib/active_job/logging.rb8
-rw-r--r--activejob/lib/active_job/queue_adapters/backburner_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/inline_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/qu_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/que_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb6
-rw-r--r--activejob/lib/active_job/queue_adapters/resque_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/sneakers_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb2
-rw-r--r--activejob/lib/active_job/queue_name.rb5
-rw-r--r--activejob/lib/active_job/version.rb2
-rw-r--r--activejob/test/cases/queue_naming_test.rb15
-rw-r--r--activemodel/lib/active_model/forbidden_attributes_protection.rb1
-rw-r--r--activerecord/CHANGELOG.md27
-rw-r--r--activerecord/RUNNING_UNIT_TESTS.rdoc4
-rw-r--r--activerecord/lib/active_record/associations.rb71
-rw-r--r--activerecord/lib/active_record/associations/association_scope.rb4
-rw-r--r--activerecord/lib/active_record/associations/through_association.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/transaction.rb30
-rw-r--r--activerecord/lib/active_record/fixtures.rb10
-rw-r--r--activerecord/lib/active_record/migration.rb37
-rw-r--r--activerecord/lib/active_record/reflection.rb2
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb2
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb16
-rw-r--r--activerecord/lib/active_record/transactions.rb26
-rw-r--r--activerecord/test/cases/finder_test.rb14
-rw-r--r--activerecord/test/cases/fixtures_test.rb15
-rw-r--r--activerecord/test/cases/forbidden_attributes_protection_test.rb30
-rw-r--r--activerecord/test/cases/helper.rb3
-rw-r--r--activerecord/test/cases/migration_test.rb15
-rw-r--r--activerecord/test/cases/relation/merging_test.rb13
-rw-r--r--activerecord/test/cases/relation/where_test.rb4
-rw-r--r--activerecord/test/cases/test_case.rb2
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb76
-rw-r--r--activerecord/test/models/comment.rb1
-rw-r--r--activerecord/test/models/developer.rb2
-rw-r--r--activerecord/test/models/post.rb1
-rw-r--r--activerecord/test/schema/schema.rb1
-rw-r--r--activesupport/activesupport.gemspec2
-rw-r--r--activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/object/itself.rb7
-rw-r--r--activesupport/lib/active_support/deprecation.rb2
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb2
-rw-r--r--activesupport/test/multibyte_chars_test.rb1
-rw-r--r--activesupport/test/number_helper_test.rb1
-rw-r--r--activesupport/test/test_case_test.rb (renamed from activesupport/test/test_test.rb)71
-rw-r--r--activesupport/test/time_travel_test.rb72
-rw-r--r--guides/rails_guides/markdown.rb2
-rw-r--r--guides/rails_guides/markdown/renderer.rb2
-rw-r--r--guides/source/2_2_release_notes.md2
-rw-r--r--guides/source/2_3_release_notes.md2
-rw-r--r--guides/source/3_0_release_notes.md2
-rw-r--r--guides/source/3_1_release_notes.md5
-rw-r--r--guides/source/3_2_release_notes.md5
-rw-r--r--guides/source/4_0_release_notes.md5
-rw-r--r--guides/source/4_1_release_notes.md8
-rw-r--r--guides/source/4_2_release_notes.md217
-rw-r--r--guides/source/action_mailer_basics.md32
-rw-r--r--guides/source/action_view_overview.md34
-rw-r--r--guides/source/active_job_basics.md56
-rw-r--r--guides/source/active_record_querying.md12
-rw-r--r--guides/source/configuring.md2
-rw-r--r--guides/source/debugging_rails_applications.md2
-rw-r--r--guides/source/development_dependencies_install.md2
-rw-r--r--guides/source/documents.yaml9
-rw-r--r--guides/source/generators.md8
-rw-r--r--guides/source/getting_started.md12
-rw-r--r--guides/source/layouts_and_rendering.md2
-rw-r--r--guides/source/nested_model_forms.md5
-rw-r--r--guides/source/plugins.md42
-rw-r--r--guides/source/testing.md4
-rw-r--r--guides/source/upgrading_ruby_on_rails.md42
-rw-r--r--rails.gemspec2
-rw-r--r--railties/CHANGELOG.md10
-rw-r--r--railties/lib/rails/application/configuration.rb14
-rw-r--r--railties/lib/rails/commands/console.rb6
-rw-r--r--railties/lib/rails/commands/server.rb18
-rw-r--r--railties/lib/rails/generators/app_base.rb12
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt2
-rw-r--r--railties/lib/rails/generators/rails/model/USAGE1
-rw-r--r--railties/test/application/configuration/custom_test.rb17
-rw-r--r--railties/test/application/middleware/remote_ip_test.rb16
-rw-r--r--railties/test/generators/app_generator_test.rb1
-rw-r--r--railties/test/isolation/abstract_unit.rb8
151 files changed, 1894 insertions, 846 deletions
diff --git a/Gemfile b/Gemfile
index df4c1e77ed..7616f2d0be 100644
--- a/Gemfile
+++ b/Gemfile
@@ -7,16 +7,11 @@ gemspec
# ensure correct loading order
gem 'mocha', '~> 0.14', require: false
-gem 'rack', github: 'rack/rack', branch: 'master'
gem 'rack-cache', '~> 1.2'
gem 'jquery-rails', '~> 3.1.0'
-gem 'turbolinks', github: 'rails/turbolinks', branch: 'master'
gem 'coffee-rails', '~> 4.0.0'
-gem 'rails-html-sanitizer', github: 'rails/rails-html-sanitizer'
-#temporary gem until a new version of loofah is released
-gem 'loofah', github: 'kaspth/loofah', branch: 'single-scrub'
-gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: 'master'
-gem 'i18n', github: 'svenfuchs/i18n', branch: 'master'
+gem 'rails-html-sanitizer'
+gem 'turbolinks', '~> 2.2.3'
# require: false so bcrypt is loaded only when has_secure_password is used.
# This is to avoid ActiveModel (and by extension the entire framework)
@@ -38,18 +33,19 @@ end
gem 'dalli', '>= 2.2.1'
# ActiveJob
-gem 'globalid', github: 'rails/globalid'
-gem 'resque', require: false
-gem 'resque-scheduler', require: false
-gem 'sidekiq', require: false
-gem 'sucker_punch', require: false
-gem 'delayed_job', require: false
-gem 'queue_classic', require: false
-gem 'sneakers', '0.1.1.pre', require: false
-gem 'que', require: false
-gem 'backburner', require: false
-gem 'qu-rails', github: "bkeepers/qu", branch: "master", require: false
-gem 'qu-redis', require: false
+group :job do
+ gem 'resque', require: false
+ gem 'resque-scheduler', require: false
+ gem 'sidekiq', require: false
+ gem 'sucker_punch', require: false
+ gem 'delayed_job', require: false
+ gem 'queue_classic', require: false, platforms: :ruby
+ gem 'sneakers', '0.1.1.pre', require: false
+ gem 'que', require: false
+ gem 'backburner', require: false
+ gem 'qu-rails', github: "bkeepers/qu", branch: "master", require: false
+ gem 'qu-redis', require: false
+end
# Add your own local bundler stuff
local_gemfile = File.dirname(__FILE__) + "/.Gemfile"
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index e6952a4b3b..1ff4db41a3 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -1,9 +1,10 @@
-* Added #deliver_later in addition to #deliver, which will enqueue a job to render and
- deliver the mail instead of delivering it right at that moment. The job is enqueued
- using the new Active Job framework in Rails, and will use whatever queue is configured for Rails.
-
+* Added #deliver_later, #deliver_now and deprecate #deliver in favour of
+ #deliver_now. #deliver_later will enqueue a job to render and deliver
+ the mail instead of delivering it right at that moment. The job is enqueued
+ using the new Active Job framework in Rails, and will use whatever queue is
+ configured for Rails.
+
*DHH/Abdelkader Boudih/Cristian Bica*
-
* Make ActionMailer::Previews methods class methods. Previously they were
instance methods and ActionMailer tries to render a message when they
diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc
index ceca912ada..3b8e3ed749 100644
--- a/actionmailer/README.rdoc
+++ b/actionmailer/README.rdoc
@@ -65,12 +65,12 @@ In order to send mails, you simply call the method and then call +deliver+ on th
Calling the method returns a Mail Message object:
- message = Notifier.welcome("david@loudthinking.com") # => Returns a Mail::Message object
- message.deliver # => delivers the email
+ message = Notifier.welcome("david@loudthinking.com") # => Returns a Mail::Message object
+ message.deliver_now # => delivers the email
Or you can just chain the methods together like:
- Notifier.welcome("david@loudthinking.com").deliver # Creates the email and sends it immediately
+ Notifier.welcome("david@loudthinking.com").deliver_now # Creates the email and sends it immediately
== Setting defaults
diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec
index 8452348e11..089e12ebf1 100644
--- a/actionmailer/actionmailer.gemspec
+++ b/actionmailer/actionmailer.gemspec
@@ -21,7 +21,8 @@ Gem::Specification.new do |s|
s.add_dependency 'actionpack', version
s.add_dependency 'actionview', version
+ s.add_dependency 'activejob', version
s.add_dependency 'mail', ['~> 2.5', '>= 2.5.4']
- s.add_dependency 'rails-dom-testing'
+ s.add_dependency 'rails-dom-testing', '~> 1.0', '>= 1.0.2'
end
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 9aae14ec8c..f539fc53c6 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -138,9 +138,20 @@ module ActionMailer
# Once a mailer action and template are defined, you can deliver your message or create it and save it
# for delivery later:
#
- # Notifier.welcome(david).deliver # sends the email
- # mail = Notifier.welcome(david) # => a Mail::Message object
- # mail.deliver # sends the email
+ # Notifier.welcome(User.first).deliver_now # sends the email
+ # mail = Notifier.welcome(User.first) # => an ActionMailer::MessageDelivery object
+ # mail.deliver_now # sends the email
+ #
+ # The <tt>ActionMailer::MessageDelivery</tt> class is a wrapper around a <tt>Mail::Message</tt> object. If
+ # you want direct access to the <tt>Mail::Message</tt> object you can call the <tt>message</tt> method on
+ # the <tt>ActionMailer::MessageDelivery</tt> object.
+ #
+ # Notifier.welcome(User.first).message # => a Mail::Message object
+ #
+ # Action Mailer is nicely integrated with Active Job so you can send emails in the background (example: outside
+ # of the request-response cycle, so the user doesn't have to wait on it):
+ #
+ # Notifier.welcome(User.first).deliver_later # enqueue the email sending to Active Job
#
# You never instantiate your mailer class. Rather, you just call the method you defined on the class itself.
#
@@ -322,8 +333,8 @@ module ActionMailer
# end
#
# Methods must return a <tt>Mail::Message</tt> object which can be generated by calling the mailer
- # method without the additional <tt>deliver</tt>. The location of the mailer previews
- # directory can be configured using the <tt>preview_path</tt> option which has a default
+ # method without the additional <tt>deliver_now</tt> / <tt>deliver_later</tt>. The location of the
+ # mailer previews directory can be configured using the <tt>preview_path</tt> option which has a default
# of <tt>test/mailers/previews</tt>:
#
# config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews"
diff --git a/actionmailer/lib/action_mailer/delivery_job.rb b/actionmailer/lib/action_mailer/delivery_job.rb
index b2cfa245fd..622f202695 100644
--- a/actionmailer/lib/action_mailer/delivery_job.rb
+++ b/actionmailer/lib/action_mailer/delivery_job.rb
@@ -1,10 +1,10 @@
require 'active_job'
module ActionMailer
- class DeliveryJob < ActiveJob::Base
+ class DeliveryJob < ActiveJob::Base #:nodoc:
queue_as :mailers
- def perform(mailer, mail_method, delivery_method, *args)
+ def perform(mailer, mail_method, delivery_method, *args) #:nodoc#
mailer.constantize.public_send(mail_method, *args).send(delivery_method)
end
end
diff --git a/actionmailer/lib/action_mailer/message_delivery.rb b/actionmailer/lib/action_mailer/message_delivery.rb
index 80a0517bff..30425d38f9 100644
--- a/actionmailer/lib/action_mailer/message_delivery.rb
+++ b/actionmailer/lib/action_mailer/message_delivery.rb
@@ -1,45 +1,112 @@
require 'delegate'
module ActionMailer
+
+ # The <tt>ActionMailer::MessageDelivery</tt> class is used by
+ # <tt>ActionMailer::Base</tt> when creating a new mailer.
+ # <tt>MessageDelivery</tt> is a wrapper (+Delegator+ subclass) around a lazy
+ # created <tt>Mail::Message</tt>. You can get direct access to the
+ # <tt>Mail::Message</tt>, deliver the email or schedule the email to be sent
+ # through Active Job.
+ #
+ # Notifier.welcome(User.first) # an ActionMailer::MessageDelivery object
+ # Notifier.welcome(User.first).deliver_now # sends the email
+ # Notifier.welcome(User.first).deliver_later # enqueue email delivery as a job through Active Job
+ # Notifier.welcome(User.first).message # a Mail::Message object
class MessageDelivery < Delegator
- def initialize(mailer, mail_method, *args)
+ def initialize(mailer, mail_method, *args) #:nodoc:
@mailer = mailer
@mail_method = mail_method
@args = args
end
- def __getobj__
+ def __getobj__ #:nodoc:
@obj ||= @mailer.send(:new, @mail_method, *@args).message
end
- def __setobj__(obj)
+ def __setobj__(obj) #:nodoc:
@obj = obj
end
- def message #:nodoc:
+ # Returns the Mail::Message object
+ def message
__getobj__
end
+ # Enqueues the email to be delivered through Active Job. When the
+ # job runs it will send the email using +deliver_now!+. That means
+ # that the message will be sent bypassing checking +perform_deliveries+
+ # and +raise_delivery_errors+, so use with caution.
+ #
+ # Notifier.welcome(User.first).deliver_later
+ # Notifier.welcome(User.first).deliver_later(in: 1.hour)
+ # Notifier.welcome(User.first).deliver_later(at: 10.hours.from_now)
+ #
+ # Options:
+ #
+ # * <tt>:in</tt> - Enqueue the email to be delivered with a delay
+ # * <tt>:at</tt> - Enqueue the email to be delivered at (after) a specific date / time
def deliver_later!(options={})
- enqueue_delivery :deliver!, options
+ enqueue_delivery :deliver_now!, options
end
+ # Enqueues the email to be delivered through Active Job. When the
+ # job runs it will send the email using +deliver_now+.
+ #
+ # Notifier.welcome(User.first).deliver_later
+ # Notifier.welcome(User.first).deliver_later(in: 1.hour)
+ # Notifier.welcome(User.first).deliver_later(at: 10.hours.from_now)
+ #
+ # Options:
+ #
+ # * <tt>:in</tt> - Enqueue the email to be delivered with a delay
+ # * <tt>:at</tt> - Enqueue the email to be delivered at (after) a specific date / time
def deliver_later(options={})
- enqueue_delivery :deliver, options
+ enqueue_delivery :deliver_now, options
+ end
+
+ # Delivers an email without checking +perform_deliveries+ and +raise_delivery_errors+,
+ # so use with caution.
+ #
+ # Notifier.welcome(User.first).deliver_now!
+ #
+ def deliver_now!
+ message.deliver!
+ end
+
+ # Delivers an email:
+ #
+ # Notifier.welcome(User.first).deliver_now
+ #
+ def deliver_now
+ message.deliver
+ end
+
+ def deliver! #:nodoc:
+ ActiveSupport::Deprecation.warn "#deliver! is deprecated and will be removed in Rails 5. " \
+ "Use #deliver_now! to deliver immediately or #deliver_later! to deliver through Active Job."
+ deliver_now!
+ end
+
+ def deliver #:nodoc:
+ ActiveSupport::Deprecation.warn "#deliver is deprecated and will be removed in Rails 5. " \
+ "Use #deliver_now to deliver immediately or #deliver_later to deliver through Active Job."
+ deliver_now
end
private
- def enqueue_delivery(delivery_method, options={})
- args = @mailer.name, @mail_method.to_s, delivery_method.to_s, *@args
- enqueue_method = :enqueue
- if options[:at]
- enqueue_method = :enqueue_at
- args.unshift options[:at]
- elsif options[:in]
- enqueue_method = :enqueue_in
- args.unshift options[:in]
+
+ def enqueue_delivery(delivery_method, options={})
+ args = @mailer.name, @mail_method.to_s, delivery_method.to_s, *@args
+ enqueue_method = :enqueue
+ if options[:at]
+ enqueue_method = :enqueue_at
+ args.unshift options[:at]
+ elsif options[:in]
+ enqueue_method = :enqueue_in
+ args.unshift options[:in]
+ end
+ ActionMailer::DeliveryJob.send enqueue_method, *args
end
- ActionMailer::DeliveryJob.send enqueue_method, *args
- end
end
end
diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb
index d507032838..b53d2b7fa0 100644
--- a/actionmailer/lib/action_mailer/test_case.rb
+++ b/actionmailer/lib/action_mailer/test_case.rb
@@ -68,6 +68,15 @@ module ActionMailer
ActionMailer::Base.deliveries.clear
end
+ def set_delivery_method(method)
+ @old_delivery_method = ActionMailer::Base.delivery_method
+ ActionMailer::Base.delivery_method = method
+ end
+
+ def restore_delivery_method
+ ActionMailer::Base.delivery_method = @old_delivery_method
+ end
+
def set_expected_mail
@expected = Mail.new
@expected.content_type ["text", "plain", { "charset" => charset }]
diff --git a/actionmailer/lib/action_mailer/test_helper.rb b/actionmailer/lib/action_mailer/test_helper.rb
index 06da0dd27e..6ddacf7b79 100644
--- a/actionmailer/lib/action_mailer/test_helper.rb
+++ b/actionmailer/lib/action_mailer/test_helper.rb
@@ -6,9 +6,9 @@ module ActionMailer
#
# def test_emails
# assert_emails 0
- # ContactMailer.welcome.deliver
+ # ContactMailer.welcome.deliver_now
# assert_emails 1
- # ContactMailer.welcome.deliver
+ # ContactMailer.welcome.deliver_now
# assert_emails 2
# end
#
@@ -17,12 +17,12 @@ module ActionMailer
#
# def test_emails_again
# assert_emails 1 do
- # ContactMailer.welcome.deliver
+ # ContactMailer.welcome.deliver_now
# end
#
# assert_emails 2 do
- # ContactMailer.welcome.deliver
- # ContactMailer.welcome.deliver
+ # ContactMailer.welcome.deliver_now
+ # ContactMailer.welcome.deliver_now
# end
# end
def assert_emails(number)
@@ -40,7 +40,7 @@ module ActionMailer
#
# def test_emails
# assert_no_emails
- # ContactMailer.welcome.deliver
+ # ContactMailer.welcome.deliver_now
# assert_emails 1
# end
#
diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb
index c549545674..c4dbbe25f6 100644
--- a/actionmailer/test/abstract_unit.rb
+++ b/actionmailer/test/abstract_unit.rb
@@ -32,15 +32,6 @@ module Rails
end
end
-def set_delivery_method(method)
- @old_delivery_method = ActionMailer::Base.delivery_method
- ActionMailer::Base.delivery_method = method
-end
-
-def restore_delivery_method
- ActionMailer::Base.delivery_method = @old_delivery_method
-end
-
# Skips the current run on Rubinius using Minitest::Assertions#skip
def rubinius_skip(message = '')
skip message if RUBY_ENGINE == 'rbx'
diff --git a/actionmailer/test/assert_select_email_test.rb b/actionmailer/test/assert_select_email_test.rb
index 57ae3436e1..cae2e20abd 100644
--- a/actionmailer/test/assert_select_email_test.rb
+++ b/actionmailer/test/assert_select_email_test.rb
@@ -26,7 +26,7 @@ class AssertSelectEmailTest < ActionMailer::TestCase
assert_select_email {}
end
- AssertSelectMailer.test("<div><p>foo</p><p>bar</p></div>").deliver
+ AssertSelectMailer.test("<div><p>foo</p><p>bar</p></div>").deliver_now
assert_select_email do
assert_select "div:root" do
assert_select "p:first-child", "foo"
@@ -36,7 +36,7 @@ class AssertSelectEmailTest < ActionMailer::TestCase
end
def test_assert_select_email_multipart
- AssertMultipartSelectMailer.test(html: "<div><p>foo</p><p>bar</p></div>", text: 'foo bar').deliver
+ AssertMultipartSelectMailer.test(html: "<div><p>foo</p><p>bar</p></div>", text: 'foo bar').deliver_now
assert_select_email do
assert_select "div:root" do
assert_select "p:first-child", "foo"
diff --git a/actionmailer/test/asset_host_test.rb b/actionmailer/test/asset_host_test.rb
index 9ba67c2842..dd3b38544f 100644
--- a/actionmailer/test/asset_host_test.rb
+++ b/actionmailer/test/asset_host_test.rb
@@ -9,11 +9,8 @@ class AssetHostMailer < ActionMailer::Base
end
end
-class AssetHostTest < ActiveSupport::TestCase
+class AssetHostTest < ActionMailer::TestCase
def setup
- set_delivery_method :test
- ActionMailer::Base.perform_deliveries = true
- ActionMailer::Base.deliveries.clear
AssetHostMailer.configure do |c|
c.asset_host = "http://www.example.com"
end
diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb
index fc24639bf4..d00f5aea47 100644
--- a/actionmailer/test/base_test.rb
+++ b/actionmailer/test/base_test.rb
@@ -466,12 +466,12 @@ class BaseTest < ActiveSupport::TestCase
test "calling deliver on the action should deliver the mail object" do
BaseMailer.expects(:deliver_mail).once
- mail = BaseMailer.welcome.deliver
+ mail = BaseMailer.welcome.deliver_now
assert_equal 'The first email on new API!', mail.subject
end
test "calling deliver on the action should increment the deliveries collection if using the test mailer" do
- BaseMailer.welcome.deliver
+ BaseMailer.welcome.deliver_now
assert_equal(1, BaseMailer.deliveries.length)
end
@@ -484,35 +484,35 @@ class BaseTest < ActiveSupport::TestCase
# Rendering
test "you can specify a different template for implicit render" do
- mail = BaseMailer.implicit_different_template('implicit_multipart').deliver
+ mail = BaseMailer.implicit_different_template('implicit_multipart').deliver_now
assert_equal("HTML Implicit Multipart", mail.html_part.body.decoded)
assert_equal("TEXT Implicit Multipart", mail.text_part.body.decoded)
end
test "should raise if missing template in implicit render" do
assert_raises ActionView::MissingTemplate do
- BaseMailer.implicit_different_template('missing_template').deliver
+ BaseMailer.implicit_different_template('missing_template').deliver_now
end
assert_equal(0, BaseMailer.deliveries.length)
end
test "you can specify a different template for explicit render" do
- mail = BaseMailer.explicit_different_template('explicit_multipart_templates').deliver
+ mail = BaseMailer.explicit_different_template('explicit_multipart_templates').deliver_now
assert_equal("HTML Explicit Multipart Templates", mail.html_part.body.decoded)
assert_equal("TEXT Explicit Multipart Templates", mail.text_part.body.decoded)
end
test "you can specify a different layout" do
- mail = BaseMailer.different_layout('different_layout').deliver
+ mail = BaseMailer.different_layout('different_layout').deliver_now
assert_equal("HTML -- HTML", mail.html_part.body.decoded)
assert_equal("PLAIN -- PLAIN", mail.text_part.body.decoded)
end
test "you can specify the template path for implicit lookup" do
- mail = BaseMailer.welcome_from_another_path('another.path/base_mailer').deliver
+ mail = BaseMailer.welcome_from_another_path('another.path/base_mailer').deliver_now
assert_equal("Welcome from another path", mail.body.encoded)
- mail = BaseMailer.welcome_from_another_path(['unknown/invalid', 'another.path/base_mailer']).deliver
+ mail = BaseMailer.welcome_from_another_path(['unknown/invalid', 'another.path/base_mailer']).deliver_now
assert_equal("Welcome from another path", mail.body.encoded)
end
@@ -542,13 +542,13 @@ class BaseTest < ActiveSupport::TestCase
test 'the view is not rendered when mail was never called' do
mail = BaseMailer.without_mail_call
assert_equal('', mail.body.to_s.strip)
- mail.deliver
+ mail.deliver_now
end
test 'the return value of mailer methods is not relevant' do
mail = BaseMailer.with_nil_as_return_value
assert_equal('Welcome', mail.body.to_s.strip)
- mail.deliver
+ mail.deliver_now
end
# Before and After hooks
@@ -568,7 +568,7 @@ class BaseTest < ActiveSupport::TestCase
ActionMailer::Base.register_observer(MyObserver)
mail = BaseMailer.welcome
MyObserver.expects(:delivered_email).with(mail)
- mail.deliver
+ mail.deliver_now
end
end
@@ -577,7 +577,7 @@ class BaseTest < ActiveSupport::TestCase
ActionMailer::Base.register_observer("BaseTest::MyObserver")
mail = BaseMailer.welcome
MyObserver.expects(:delivered_email).with(mail)
- mail.deliver
+ mail.deliver_now
end
end
@@ -586,7 +586,7 @@ class BaseTest < ActiveSupport::TestCase
ActionMailer::Base.register_observer(:"base_test/my_observer")
mail = BaseMailer.welcome
MyObserver.expects(:delivered_email).with(mail)
- mail.deliver
+ mail.deliver_now
end
end
@@ -596,7 +596,7 @@ class BaseTest < ActiveSupport::TestCase
mail = BaseMailer.welcome
MyObserver.expects(:delivered_email).with(mail)
MySecondObserver.expects(:delivered_email).with(mail)
- mail.deliver
+ mail.deliver_now
end
end
@@ -615,7 +615,7 @@ class BaseTest < ActiveSupport::TestCase
ActionMailer::Base.register_interceptor(MyInterceptor)
mail = BaseMailer.welcome
MyInterceptor.expects(:delivering_email).with(mail)
- mail.deliver
+ mail.deliver_now
end
end
@@ -624,7 +624,7 @@ class BaseTest < ActiveSupport::TestCase
ActionMailer::Base.register_interceptor("BaseTest::MyInterceptor")
mail = BaseMailer.welcome
MyInterceptor.expects(:delivering_email).with(mail)
- mail.deliver
+ mail.deliver_now
end
end
@@ -633,7 +633,7 @@ class BaseTest < ActiveSupport::TestCase
ActionMailer::Base.register_interceptor(:"base_test/my_interceptor")
mail = BaseMailer.welcome
MyInterceptor.expects(:delivering_email).with(mail)
- mail.deliver
+ mail.deliver_now
end
end
@@ -643,7 +643,7 @@ class BaseTest < ActiveSupport::TestCase
mail = BaseMailer.welcome
MyInterceptor.expects(:delivering_email).with(mail)
MySecondInterceptor.expects(:delivering_email).with(mail)
- mail.deliver
+ mail.deliver_now
end
end
diff --git a/actionmailer/test/delivery_methods_test.rb b/actionmailer/test/delivery_methods_test.rb
index a76ac6d295..2e4e019bf7 100644
--- a/actionmailer/test/delivery_methods_test.rb
+++ b/actionmailer/test/delivery_methods_test.rb
@@ -104,21 +104,21 @@ class MailDeliveryTest < ActiveSupport::TestCase
test "ActionMailer should be told when Mail gets delivered" do
DeliveryMailer.expects(:deliver_mail).once
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
end
test "delivery method can be customized per instance" do
Mail::SMTP.any_instance.expects(:deliver!)
- email = DeliveryMailer.welcome.deliver
+ email = DeliveryMailer.welcome.deliver_now
assert_instance_of Mail::SMTP, email.delivery_method
- email = DeliveryMailer.welcome(delivery_method: :test).deliver
+ email = DeliveryMailer.welcome(delivery_method: :test).deliver_now
assert_instance_of Mail::TestMailer, email.delivery_method
end
test "delivery method can be customized in subclasses not changing the parent" do
DeliveryMailer.delivery_method = :test
assert_equal :smtp, ActionMailer::Base.delivery_method
- email = DeliveryMailer.welcome.deliver
+ email = DeliveryMailer.welcome.deliver_now
assert_instance_of Mail::TestMailer, email.delivery_method
end
@@ -162,14 +162,14 @@ class MailDeliveryTest < ActiveSupport::TestCase
test "non registered delivery methods raises errors" do
DeliveryMailer.delivery_method = :unknown
assert_raise RuntimeError do
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
end
end
test "undefined delivery methods raises errors" do
DeliveryMailer.delivery_method = nil
assert_raise RuntimeError do
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
end
end
@@ -178,7 +178,7 @@ class MailDeliveryTest < ActiveSupport::TestCase
begin
DeliveryMailer.perform_deliveries = false
Mail::Message.any_instance.expects(:deliver!).never
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
ensure
DeliveryMailer.perform_deliveries = old_perform_deliveries
end
@@ -188,7 +188,7 @@ class MailDeliveryTest < ActiveSupport::TestCase
old_perform_deliveries = DeliveryMailer.perform_deliveries
begin
DeliveryMailer.perform_deliveries = false
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
assert_equal [], DeliveryMailer.deliveries
ensure
DeliveryMailer.perform_deliveries = old_perform_deliveries
@@ -198,14 +198,14 @@ class MailDeliveryTest < ActiveSupport::TestCase
test "raise errors on bogus deliveries" do
DeliveryMailer.delivery_method = BogusDelivery
assert_raise RuntimeError do
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
end
end
test "does not increment the deliveries collection on error" do
DeliveryMailer.delivery_method = BogusDelivery
assert_raise RuntimeError do
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
end
assert_equal [], DeliveryMailer.deliveries
end
@@ -216,7 +216,7 @@ class MailDeliveryTest < ActiveSupport::TestCase
DeliveryMailer.delivery_method = BogusDelivery
DeliveryMailer.raise_delivery_errors = false
assert_nothing_raised do
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
end
ensure
DeliveryMailer.raise_delivery_errors = old_raise_delivery_errors
@@ -228,7 +228,7 @@ class MailDeliveryTest < ActiveSupport::TestCase
begin
DeliveryMailer.delivery_method = BogusDelivery
DeliveryMailer.raise_delivery_errors = false
- DeliveryMailer.welcome.deliver
+ DeliveryMailer.welcome.deliver_now
assert_equal [], DeliveryMailer.deliveries
ensure
DeliveryMailer.raise_delivery_errors = old_raise_delivery_errors
diff --git a/actionmailer/test/i18n_with_controller_test.rb b/actionmailer/test/i18n_with_controller_test.rb
index ee36b89dd6..010e44d045 100644
--- a/actionmailer/test/i18n_with_controller_test.rb
+++ b/actionmailer/test/i18n_with_controller_test.rb
@@ -17,7 +17,7 @@ end
class TestController < ActionController::Base
def send_mail
- email = I18nTestMailer.mail_with_i18n_subject("test@localhost").deliver
+ email = I18nTestMailer.mail_with_i18n_subject("test@localhost").deliver_now
render text: "Mail sent - Subject: #{email.subject}"
end
end
diff --git a/actionmailer/test/log_subscriber_test.rb b/actionmailer/test/log_subscriber_test.rb
index e7a73d6c8e..3871b16840 100644
--- a/actionmailer/test/log_subscriber_test.rb
+++ b/actionmailer/test/log_subscriber_test.rb
@@ -22,7 +22,7 @@ class AMLogSubscriberTest < ActionMailer::TestCase
end
def test_deliver_is_notified
- BaseMailer.welcome.deliver
+ BaseMailer.welcome.deliver_now
wait
assert_equal(1, @logger.logged(:info).size)
diff --git a/actionmailer/test/message_delivery_test.rb b/actionmailer/test/message_delivery_test.rb
index a097d0e84d..8402fc130f 100644
--- a/actionmailer/test/message_delivery_test.rb
+++ b/actionmailer/test/message_delivery_test.rb
@@ -37,6 +37,17 @@ class MessageDeliveryTest < ActiveSupport::TestCase
assert_respond_to @mail, :deliver!
end
+ test '.deliver is deprecated' do
+ assert_deprecated do
+ @mail.deliver
+ end
+ end
+ test '.deliver! is deprecated' do
+ assert_deprecated do
+ @mail.deliver!
+ end
+ end
+
test 'should respond to .deliver_later' do
assert_respond_to @mail, :deliver_later
end
@@ -45,30 +56,40 @@ class MessageDeliveryTest < ActiveSupport::TestCase
assert_respond_to @mail, :deliver_later!
end
- test 'should enqueue and run correctly in activejob' do
+ test 'should respond to .deliver_now' do
+ assert_respond_to @mail, :deliver_now
+ end
+
+ test 'should respond to .deliver_now!' do
+ assert_respond_to @mail, :deliver_now!
+ end
+
+ def test_should_enqueue_and_run_correctly_in_activejob
@mail.deliver_later!
- assert_equal 1 , ActionMailer::Base.deliveries.size
+ assert_equal 1, ActionMailer::Base.deliveries.size
+ ensure
+ ActionMailer::Base.deliveries.clear
end
test 'should enqueue the email with :deliver delivery method' do
ret = ActionMailer::DeliveryJob.stub :enqueue, ->(*args){ args } do
@mail.deliver_later
end
- assert_equal ['DelayedMailer', 'test_message', 'deliver', 1, 2, 3], ret
+ assert_equal ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3], ret
end
test 'should enqueue the email with :deliver! delivery method' do
ret = ActionMailer::DeliveryJob.stub :enqueue, ->(*args){ args } do
@mail.deliver_later!
end
- assert_equal ['DelayedMailer', 'test_message', 'deliver!', 1, 2, 3], ret
+ assert_equal ['DelayedMailer', 'test_message', 'deliver_now!', 1, 2, 3], ret
end
test 'should enqueue a delivery with a delay' do
ret = ActionMailer::DeliveryJob.stub :enqueue_in, ->(*args){ args } do
@mail.deliver_later in: 600
end
- assert_equal [600, 'DelayedMailer', 'test_message', 'deliver', 1, 2, 3], ret
+ assert_equal [600, 'DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3], ret
end
test 'should enqueue a delivery at a specific time' do
@@ -76,7 +97,7 @@ class MessageDeliveryTest < ActiveSupport::TestCase
ret = ActionMailer::DeliveryJob.stub :enqueue_at, ->(*args){ args } do
@mail.deliver_later at: later_time
end
- assert_equal [later_time, 'DelayedMailer', 'test_message', 'deliver', 1, 2, 3], ret
+ assert_equal [later_time, 'DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3], ret
end
end
diff --git a/actionmailer/test/test_helper_test.rb b/actionmailer/test/test_helper_test.rb
index 1ff08a3b6e..96b75ff2e0 100644
--- a/actionmailer/test/test_helper_test.rb
+++ b/actionmailer/test/test_helper_test.rb
@@ -48,7 +48,7 @@ class TestHelperMailerTest < ActionMailer::TestCase
def test_assert_emails
assert_nothing_raised do
assert_emails 1 do
- TestHelperMailer.test.deliver
+ TestHelperMailer.test.deliver_now
end
end
end
@@ -56,27 +56,27 @@ class TestHelperMailerTest < ActionMailer::TestCase
def test_repeated_assert_emails_calls
assert_nothing_raised do
assert_emails 1 do
- TestHelperMailer.test.deliver
+ TestHelperMailer.test.deliver_now
end
end
assert_nothing_raised do
assert_emails 2 do
- TestHelperMailer.test.deliver
- TestHelperMailer.test.deliver
+ TestHelperMailer.test.deliver_now
+ TestHelperMailer.test.deliver_now
end
end
end
def test_assert_emails_with_no_block
assert_nothing_raised do
- TestHelperMailer.test.deliver
+ TestHelperMailer.test.deliver_now
assert_emails 1
end
assert_nothing_raised do
- TestHelperMailer.test.deliver
- TestHelperMailer.test.deliver
+ TestHelperMailer.test.deliver_now
+ TestHelperMailer.test.deliver_now
assert_emails 3
end
end
@@ -92,7 +92,7 @@ class TestHelperMailerTest < ActionMailer::TestCase
def test_assert_emails_too_few_sent
error = assert_raise ActiveSupport::TestCase::Assertion do
assert_emails 2 do
- TestHelperMailer.test.deliver
+ TestHelperMailer.test.deliver_now
end
end
@@ -102,8 +102,8 @@ class TestHelperMailerTest < ActionMailer::TestCase
def test_assert_emails_too_many_sent
error = assert_raise ActiveSupport::TestCase::Assertion do
assert_emails 1 do
- TestHelperMailer.test.deliver
- TestHelperMailer.test.deliver
+ TestHelperMailer.test.deliver_now
+ TestHelperMailer.test.deliver_now
end
end
@@ -113,7 +113,7 @@ class TestHelperMailerTest < ActionMailer::TestCase
def test_assert_no_emails_failure
error = assert_raise ActiveSupport::TestCase::Assertion do
assert_no_emails do
- TestHelperMailer.test.deliver
+ TestHelperMailer.test.deliver_now
end
end
diff --git a/actionmailer/test/url_test.rb b/actionmailer/test/url_test.rb
index 589944fa69..e79b2ca978 100644
--- a/actionmailer/test/url_test.rb
+++ b/actionmailer/test/url_test.rb
@@ -68,7 +68,7 @@ class ActionMailerUrlTest < ActionMailer::TestCase
created.message_id = '<123@456>'
assert_equal expected.encoded, created.encoded
- assert_nothing_raised { UrlTestMailer.signed_up_with_url(@recipient).deliver }
+ assert_nothing_raised { UrlTestMailer.signed_up_with_url(@recipient).deliver_now }
assert_not_nil ActionMailer::Base.deliveries.first
delivered = ActionMailer::Base.deliveries.first
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index ddacbe2aa2..050ec5e649 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,4 +1,61 @@
-* Deleted the deprecated TagAssertions.
+* Allow `config.action_dispatch.trusted_proxies` to accept an IPAddr object.
+
+ Example:
+ # config/environments/production.rb
+ config.action_dispatch.trusted_proxies = IPAddr.new('4.8.15.0/16')
+
+ *Sam Aarons*
+
+* Avoid duplicating routes for HEAD requests.
+
+ Instead of duplicating the routes, we will first match the HEAD request to
+ HEAD routes. If no match is found, we will then map the HEAD request to
+ GET routes.
+
+ *Guo Xiang Tan*, *Andrew White*
+
+* Requests that hit `ActionDispatch::Static` can now take advantage
+ of gzipped assets on disk. By default a gzip asset will be served if
+ the client supports gzip and a compressed file is on disk.
+
+ *Richard Schneeman*
+
+* `ActionController::Parameters` will stop inheriting from `Hash` and
+ `HashWithIndifferentAccess` in the next major release. If you use any method
+ that is not available on `ActionController::Parameters` you should consider
+ calling `#to_h` to convert it to a `Hash` first before calling that method.
+
+ *Prem Sichanugrist*
+
+* `ActionController::Parameters#to_h` now returns a `Hash` with unpermitted
+ keys removed. This change is to reflect on a security concern where some
+ method performed on an `ActionController::Parameters` may yield a `Hash`
+ object which does not maintain `permitted?` status. If you would like to
+ get a `Hash` with all the keys intact, duplicate and mark it as permitted
+ before calling `#to_h`.
+
+ params = ActionController::Parameters.new({
+ name: 'Senjougahara Hitagi',
+ oddity: 'Heavy stone crab'
+ })
+ params.to_h
+ # => {}
+
+ unsafe_params = params.dup.permit!
+ unsafe_params.to_h
+ # => {"name"=>"Senjougahara Hitagi", "oddity"=>"Heavy stone crab"}
+
+ safe_params = params.permit(:name)
+ safe_params.to_h
+ # => {"name"=>"Senjougahara Hitagi"}
+
+ This change is consider a stopgap as we cannot change the code to stop
+ `ActionController::Parameters` to inherit from `HashWithIndifferentAccess`
+ in the next minor release.
+
+ *Prem Sichanugrist*
+
+* Deprecated TagAssertions.
*Kasper Timm Hansen*
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index 5834e79668..a39b3e86d4 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -21,9 +21,10 @@ Gem::Specification.new do |s|
s.add_dependency 'activesupport', version
- s.add_dependency 'rack', '~> 1.6.0.alpha'
+ s.add_dependency 'rack', '~> 1.6.0.beta'
s.add_dependency 'rack-test', '~> 0.6.2'
- s.add_dependency 'rails-deprecated_sanitizer'
+ s.add_dependency 'rails-deprecated_sanitizer', '~> 1.0', '>= 1.0.2'
+ s.add_dependency 'rails-dom-testing', '~> 1.0', '>= 1.0.2'
s.add_dependency 'actionview', version
s.add_development_dependency 'activemodel', version
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 0efa0fb259..a4f376816f 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -9,7 +9,7 @@ module ActionController #:nodoc:
end
# Controller actions are protected from Cross-Site Request Forgery (CSRF) attacks
- # by including a token in the rendered html for your application. This token is
+ # by including a token in the rendered HTML for your application. This token is
# stored as a random string in the session, to which an attacker does not have
# access. When a request reaches your application, \Rails verifies the received
# token with the token in the session. Only HTML and JavaScript requests are checked,
@@ -44,7 +44,7 @@ module ActionController #:nodoc:
#
# The token parameter is named <tt>authenticity_token</tt> by default. The name and
# value of this token must be added to every layout that renders forms by including
- # <tt>csrf_meta_tags</tt> in the html +head+.
+ # <tt>csrf_meta_tags</tt> in the HTML +head+.
#
# Learn more about CSRF attacks and securing your application in the
# {Ruby on Rails Security Guide}[http://guides.rubyonrails.org/security.html].
@@ -240,6 +240,8 @@ module ActionController #:nodoc:
content_type =~ %r(\Atext/javascript) && !request.xhr?
end
+ AUTHENTICITY_TOKEN_LENGTH = 32
+
# Returns true or false if a request is verified. Checks:
#
# * is it a GET or HEAD request? Gets should be safe and idempotent
@@ -247,13 +249,73 @@ module ActionController #:nodoc:
# * Does the X-CSRF-Token header match the form_authenticity_token
def verified_request?
!protect_against_forgery? || request.get? || request.head? ||
- form_authenticity_token == form_authenticity_param ||
- form_authenticity_token == request.headers['X-CSRF-Token']
+ valid_authenticity_token?(session, form_authenticity_param) ||
+ valid_authenticity_token?(session, request.headers['X-CSRF-Token'])
end
# Sets the token value for the current session.
def form_authenticity_token
- session[:_csrf_token] ||= SecureRandom.base64(32)
+ masked_authenticity_token(session)
+ end
+
+ # Creates a masked version of the authenticity token that varies
+ # on each request. The masking is used to mitigate SSL attacks
+ # like BREACH.
+ def masked_authenticity_token(session)
+ one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
+ encrypted_csrf_token = xor_byte_strings(one_time_pad, real_csrf_token(session))
+ masked_token = one_time_pad + encrypted_csrf_token
+ Base64.strict_encode64(masked_token)
+ end
+
+ # Checks the client's masked token to see if it matches the
+ # session token. Essentially the inverse of
+ # +masked_authenticity_token+.
+ def valid_authenticity_token?(session, encoded_masked_token)
+ return false if encoded_masked_token.nil? || encoded_masked_token.empty?
+
+ begin
+ masked_token = Base64.strict_decode64(encoded_masked_token)
+ rescue ArgumentError # encoded_masked_token is invalid Base64
+ return false
+ end
+
+ # See if it's actually a masked token or not. In order to
+ # deploy this code, we should be able to handle any unmasked
+ # tokens that we've issued without error.
+
+ if masked_token.length == AUTHENTICITY_TOKEN_LENGTH
+ # This is actually an unmasked token. This is expected if
+ # you have just upgraded to masked tokens, but should stop
+ # happening shortly after installing this gem
+ compare_with_real_token masked_token, session
+
+ elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
+ # Split the token into the one-time pad and the encrypted
+ # value and decrypt it
+ one_time_pad = masked_token[0...AUTHENTICITY_TOKEN_LENGTH]
+ encrypted_csrf_token = masked_token[AUTHENTICITY_TOKEN_LENGTH..-1]
+ csrf_token = xor_byte_strings(one_time_pad, encrypted_csrf_token)
+
+ compare_with_real_token csrf_token, session
+
+ else
+ false # Token is malformed
+ end
+ end
+
+ def compare_with_real_token(token, session)
+ # Borrow a constant-time comparison from Rack
+ Rack::Utils.secure_compare(token, real_csrf_token(session))
+ end
+
+ def real_csrf_token(session)
+ session[:_csrf_token] ||= SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH)
+ Base64.strict_decode64(session[:_csrf_token])
+ end
+
+ def xor_byte_strings(s1, s2)
+ s1.bytes.zip(s2.bytes).map { |(c1,c2)| c1 ^ c2 }.pack('c*')
end
# The form's authenticity parameter. Override to provide your own.
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index bc27ecaa20..7038f0997f 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -141,6 +141,37 @@ module ActionController
@permitted = self.class.permit_all_parameters
end
+ # Returns a safe +Hash+ representation of this parameter with all
+ # unpermitted keys removed.
+ #
+ # params = ActionController::Parameters.new({
+ # name: 'Senjougahara Hitagi',
+ # oddity: 'Heavy stone crab'
+ # })
+ # params.to_h # => {}
+ #
+ # safe_params = params.permit(:name)
+ # safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
+ def to_h
+ if permitted?
+ to_hash
+ else
+ slice(*self.class.always_permitted_parameters).permit!.to_h
+ end
+ end
+
+ # Convert all hashes in values into parameters, then yield each pair like
+ # the same way as <tt>Hash#each_pair</tt>
+ def each_pair(&block)
+ super do |key, value|
+ convert_hashes_to_parameters(key, value)
+ end
+
+ super
+ end
+
+ alias_method :each, :each_pair
+
# Attribute that keeps track of converted arrays, if any, to avoid double
# looping in the common use case permit + mass-assignment. Defined in a
# method to instantiate it only if needed.
@@ -176,7 +207,6 @@ module ActionController
# Person.new(params) # => #<Person id: nil, name: "Francesco">
def permit!
each_pair do |key, value|
- value = convert_hashes_to_parameters(key, value)
Array.wrap(value).each do |v|
v.permit! if v.respond_to? :permit!
end
@@ -331,11 +361,56 @@ module ActionController
# params.slice(:a, :b) # => {"a"=>1, "b"=>2}
# params.slice(:d) # => {}
def slice(*keys)
- self.class.new(super).tap do |new_instance|
- new_instance.permitted = @permitted
+ new_instance_with_inherited_permitted_status(super)
+ end
+
+ # Removes and returns the key/value pairs matching the given keys.
+ #
+ # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
+ # params.extract!(:a, :b) # => {"a"=>1, "b"=>2}
+ # params # => {"c"=>3}
+ def extract!(*keys)
+ new_instance_with_inherited_permitted_status(super)
+ end
+
+ # Returns a new <tt>ActionController::Parameters</tt> with the results of
+ # running +block+ once for every value. The keys are unchanged.
+ #
+ # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
+ # params.transform_values { |x| x * 2 }
+ # # => {"a"=>2, "b"=>4, "c"=>6}
+ def transform_values
+ if block_given?
+ new_instance_with_inherited_permitted_status(super)
+ else
+ super
+ end
+ end
+
+ # This method is here only to make sure that the returned object has the
+ # correct +permitted+ status. It should not matter since the parent of
+ # this object is +HashWithIndifferentAccess+
+ def transform_keys # :nodoc:
+ if block_given?
+ new_instance_with_inherited_permitted_status(super)
+ else
+ super
end
end
+ # Deletes and returns a key-value pair from +Parameters+ whose key is equal
+ # to key. If the key is not found, returns the default value. If the
+ # optional code block is given and the key is not found, pass in the key
+ # and return the result of block.
+ def delete(key, &block)
+ convert_hashes_to_parameters(key, super, false)
+ end
+
+ # Equivalent to Hash#keep_if, but returns nil if no changes were made.
+ def select!(&block)
+ convert_value_to_parameters(super)
+ end
+
# Returns an exact copy of the <tt>ActionController::Parameters</tt>
# instance. +permitted+ state is kept on the duped object.
#
@@ -356,6 +431,12 @@ module ActionController
end
private
+ def new_instance_with_inherited_permitted_status(hash)
+ self.class.new(hash).tap do |new_instance|
+ new_instance.permitted = @permitted
+ end
+ end
+
def convert_hashes_to_parameters(key, value, assign_if_converted=true)
converted = convert_value_to_parameters(value)
self[key] = converted if assign_if_converted && !converted.equal?(value)
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 8c035c3c6c..c441f7f95b 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -105,6 +105,12 @@ module ActionDispatch
@request_method ||= check_method(env["REQUEST_METHOD"])
end
+ def request_method=(request_method) #:nodoc:
+ if check_method(request_method)
+ @request_method = env["REQUEST_METHOD"] = request_method
+ end
+ end
+
# Returns a symbol form of the #request_method
def request_method_symbol
HTTP_METHOD_LOOKUP[request_method]
@@ -292,7 +298,7 @@ module ActionDispatch
# Override Rack's GET method to support indifferent access
def GET
@env["action_dispatch.request.query_parameters"] ||= Utils.deep_munge(normalize_encode_params(super || {}))
- rescue TypeError => e
+ rescue TypeError, Rack::Utils::InvalidParameterError => e
raise ActionController::BadRequest.new(:query, e)
end
alias :query_parameters :GET
@@ -300,7 +306,7 @@ module ActionDispatch
# Override Rack's POST method to support indifferent access
def POST
@env["action_dispatch.request.request_parameters"] ||= Utils.deep_munge(normalize_encode_params(super || {}))
- rescue TypeError => e
+ rescue TypeError, Rack::Utils::InvalidParameterError => e
raise ActionController::BadRequest.new(:request, e)
end
alias :request_parameters :POST
diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb
index 21817b374c..9131b65380 100644
--- a/actionpack/lib/action_dispatch/journey/router.rb
+++ b/actionpack/lib/action_dispatch/journey/router.rb
@@ -101,11 +101,13 @@ module ActionDispatch
r.path.match(req.path_info)
}
- if req.env["REQUEST_METHOD"] === "HEAD"
- routes.concat get_routes_as_head(routes)
- end
+ routes =
+ if req.request_method == "HEAD"
+ match_head_routes(routes, req)
+ else
+ match_routes(routes, req)
+ end
- routes.select! { |r| r.matches?(req) }
routes.sort_by!(&:precedence)
routes.map! { |r|
@@ -118,19 +120,23 @@ module ActionDispatch
}
end
- def get_routes_as_head(routes)
- precedence = (routes.map(&:precedence).max || 0) + 1
- routes.select { |r|
- r.verb === "GET" && !(r.verb === "HEAD")
- }.map! { |r|
- Route.new(r.name,
- r.app,
- r.path,
- r.conditions.merge(request_method: "HEAD"),
- r.defaults).tap do |route|
- route.precedence = r.precedence + precedence
- end
- }
+ def match_head_routes(routes, req)
+ head_routes = match_routes(routes, req)
+
+ if head_routes.empty?
+ begin
+ req.request_method = "GET"
+ match_routes(routes, req)
+ ensure
+ req.request_method = "HEAD"
+ end
+ else
+ head_routes
+ end
+ end
+
+ def match_routes(routes, req)
+ routes.select { |r| r.matches?(req) }
end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
index 6c8944e067..040cb215b7 100644
--- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
@@ -1,4 +1,14 @@
module ActionDispatch
+ # When called, this middleware renders an error page. By default if an HTML
+ # response is expected it will render static error pages from the `/public`
+ # directory. For example when this middleware receives a 500 response it will
+ # render the template found in `/public/500.html`.
+ # If an internationalized locale is set, this middleware will attempt to render
+ # the template in `/public/500.<locale>.html`. If an internationalized template
+ # is not found it will fall back on `/public/500.html`.
+ #
+ # When a request with a content type other than HTML is made, this middleware
+ # will attempt to convert error information into the appropriate response type.
class PublicExceptions
attr_accessor :public_path
diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
index 6a79b4e859..b022fea001 100644
--- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb
+++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
@@ -1,3 +1,5 @@
+require 'ipaddr'
+
module ActionDispatch
# This middleware calculates the IP address of the remote client that is
# making the request. It does this by checking various headers that could
@@ -28,14 +30,14 @@ module ActionDispatch
# guaranteed by the IP specification to be private addresses. Those will
# not be the ultimate client IP in production, and so are discarded. See
# http://en.wikipedia.org/wiki/Private_network for details.
- TRUSTED_PROXIES = %r{
- ^127\.0\.0\.1$ | # localhost IPv4
- ^::1$ | # localhost IPv6
- ^[fF][cCdD] | # private IPv6 range fc00::/7
- ^10\. | # private IPv4 range 10.x.x.x
- ^172\.(1[6-9]|2[0-9]|3[0-1])\.| # private IPv4 range 172.16.0.0 .. 172.31.255.255
- ^192\.168\. # private IPv4 range 192.168.x.x
- }x
+ TRUSTED_PROXIES = [
+ "127.0.0.1", # localhost IPv4
+ "::1", # localhost IPv6
+ "fc00::/7", # private IPv6 range fc00::/7
+ "10.0.0.0/8", # private IPv4 range 10.x.x.x
+ "172.16.0.0/12", # private IPv4 range 172.16.0.0 .. 172.31.255.255
+ "192.168.0.0/16", # private IPv4 range 192.168.x.x
+ ].map { |proxy| IPAddr.new(proxy) }
attr_reader :check_ip, :proxies
@@ -47,24 +49,24 @@ module ActionDispatch
# clients (like WAP devices), or behind proxies that set headers in an
# incorrect or confusing way (like AWS ELB).
#
- # The +custom_proxies+ argument can take a regex, which will be used
- # instead of +TRUSTED_PROXIES+, or a string, which will be used in addition
- # to +TRUSTED_PROXIES+. Any proxy setup will put the value you want in the
- # middle (or at the beginning) of the X-Forwarded-For list, with your proxy
- # servers after it. If your proxies aren't removed, pass them in via the
- # +custom_proxies+ parameter. That way, the middleware will ignore those
- # IP addresses, and return the one that you want.
+ # The +custom_proxies+ argument can take an Array of string, IPAddr, or
+ # Regexp objects which will be used instead of +TRUSTED_PROXIES+. If a
+ # single string, IPAddr, or Regexp object is provided, it will be used in
+ # addition to +TRUSTED_PROXIES+. Any proxy setup will put the value you
+ # want in the middle (or at the beginning) of the X-Forwarded-For list,
+ # with your proxy servers after it. If your proxies aren't removed, pass
+ # them in via the +custom_proxies+ parameter. That way, the middleware will
+ # ignore those IP addresses, and return the one that you want.
def initialize(app, check_ip_spoofing = true, custom_proxies = nil)
@app = app
@check_ip = check_ip_spoofing
- @proxies = case custom_proxies
- when Regexp
- custom_proxies
- when nil
- TRUSTED_PROXIES
- else
- Regexp.union(TRUSTED_PROXIES, custom_proxies)
- end
+ @proxies = if custom_proxies.blank?
+ TRUSTED_PROXIES
+ elsif custom_proxies.respond_to?(:any?)
+ custom_proxies
+ else
+ Array(custom_proxies) + TRUSTED_PROXIES
+ end
end
# Since the IP address may not be needed, we store the object here
@@ -80,32 +82,6 @@ module ActionDispatch
# into an actual IP address. If the ActionDispatch::Request#remote_ip method
# is called, this class will calculate the value and then memoize it.
class GetIp
-
- # This constant contains a regular expression that validates every known
- # form of IP v4 and v6 address, with or without abbreviations, adapted
- # from {this gist}[https://gist.github.com/gazay/1289635].
- VALID_IP = %r{
- (^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})){3}$) | # ip v4
- (^(
- (([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}) | # ip v6 not abbreviated
- (([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4}) | # ip v6 with double colon in the end
- (([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4}) | # - ip addresses v6
- (([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4}) | # - with
- (([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4}) | # - double colon
- (([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4}) | # - in the middle
- (([0-9A-Fa-f]{1,4}:){6} ((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3} (\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
- (([0-9A-Fa-f]{1,4}:){1,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
- (([0-9A-Fa-f]{1,4}:){1}:([0-9A-Fa-f]{1,4}:){0,4}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
- (([0-9A-Fa-f]{1,4}:){0,2}:([0-9A-Fa-f]{1,4}:){0,3}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
- (([0-9A-Fa-f]{1,4}:){0,3}:([0-9A-Fa-f]{1,4}:){0,2}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
- (([0-9A-Fa-f]{1,4}:){0,4}:([0-9A-Fa-f]{1,4}:){1}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
- (::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d) |(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)) | # ip v6 with compatible to v4
- ([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4}) | # ip v6 with compatible to v4
- (::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4}) | # ip v6 with double colon at the beginning
- (([0-9A-Fa-f]{1,4}:){1,7}:) # ip v6 without ending
- )$)
- }x
-
def initialize(env, middleware)
@env = env
@check_ip = middleware.check_ip
@@ -173,12 +149,22 @@ module ActionDispatch
def ips_from(header)
# Split the comma-separated list into an array of strings
ips = @env[header] ? @env[header].strip.split(/[,\s]+/) : []
- # Only return IPs that are valid according to the regex
- ips.select{ |ip| ip =~ VALID_IP }
+ ips.select do |ip|
+ begin
+ # Only return IPs that are valid according to the IPAddr#new method
+ range = IPAddr.new(ip).to_range
+ # we want to make sure nobody is sneaking a netmask in
+ range.begin == range.end
+ rescue ArgumentError, IPAddr::InvalidAddressError
+ nil
+ end
+ end
end
def filter_proxies(ips)
- ips.reject { |ip| ip =~ @proxies }
+ ips.reject do |ip|
+ @proxies.any? { |proxy| proxy === ip }
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index 2764584fe9..a3e8126ace 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -2,12 +2,23 @@ require 'rack/utils'
require 'active_support/core_ext/uri'
module ActionDispatch
+ # This middleware returns a file's contents from disk in the body response.
+ # When initialized it can accept an optional 'Cache-Control' header which
+ # will be set when a response containing a file's contents is delivered.
+ #
+ # This middleware will render the file specified in `env["PATH_INFO"]`
+ # where the base path is in the +root+ directory. For example if the +root+
+ # is set to `public/` then a request with `env["PATH_INFO"]` of
+ # `assets/application.js` will return a response with contents of a file
+ # located at `public/assets/application.js` if the file exists. If the file
+ # does not exist a 404 "File not Found" response will be returned.
class FileHandler
def initialize(root, cache_control)
@root = root.chomp('/')
@compiled_root = /^#{Regexp.escape(root)}/
- headers = cache_control && { 'Cache-Control' => cache_control }
- @file_server = ::Rack::File.new(@root, headers)
+ headers = {}
+ headers['Cache-Control'] = cache_control if cache_control
+ @file_server = ::Rack::File.new(@root, headers)
end
def match?(path)
@@ -26,25 +37,59 @@ module ActionDispatch
end
def call(env)
- @file_server.call(env)
+ path = env['PATH_INFO']
+ gzip_file_exists = gzip_file_exists?(path)
+ if gzip_file_exists && gzip_encoding_accepted?(env)
+ env['PATH_INFO'] = "#{path}.gz"
+ status, headers, body = @file_server.call(env)
+ headers['Content-Encoding'] = 'gzip'
+ headers['Content-Type'] = content_type(path)
+ else
+ status, headers, body = @file_server.call(env)
+ end
+
+ headers['Vary'] = 'Accept-Encoding' if gzip_file_exists
+ return [status, headers, body]
end
- def ext
- @ext ||= begin
- ext = ::ActionController::Base.default_static_extension
- "{,#{ext},/index#{ext}}"
+ private
+ def ext
+ @ext ||= begin
+ ext = ::ActionController::Base.default_static_extension
+ "{,#{ext},/index#{ext}}"
+ end
end
- end
- def unescape_path(path)
- URI.parser.unescape(path)
- end
+ def unescape_path(path)
+ URI.parser.unescape(path)
+ end
- def escape_glob_chars(path)
- path.gsub(/[*?{}\[\]]/, "\\\\\\&")
- end
+ def escape_glob_chars(path)
+ path.gsub(/[*?{}\[\]]/, "\\\\\\&")
+ end
+
+ def content_type(path)
+ ::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
+ end
+
+ def gzip_encoding_accepted?(env)
+ env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/
+ end
+
+ def gzip_file_exists?(path)
+ File.exist?(File.join(@root, "#{::Rack::Utils.unescape(path)}.gz"))
+ end
end
+ # This middleware will attempt to return the contents of a file's body from
+ # disk in the response. If a file is not found on disk, the request will be
+ # delegated to the application stack. This middleware is commonly initialized
+ # to serve assets from a server's `public/` directory.
+ #
+ # This middleware verifies the path to ensure that only files
+ # living in the root directory can be rendered. A request cannot
+ # produce a directory traversal using this middleware. Only 'GET' and 'HEAD'
+ # requests will result in a file being returned.
class Static
def initialize(app, path, cache_control=nil)
@app = app
diff --git a/actionpack/lib/action_dispatch/testing/assertions/tag.rb b/actionpack/lib/action_dispatch/testing/assertions/tag.rb
new file mode 100644
index 0000000000..d5348d80e1
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/assertions/tag.rb
@@ -0,0 +1,3 @@
+require 'active_support/deprecation'
+
+ActiveSupport::Deprecation.warn("ActionDispatch::Assertions::TagAssertions has been has been extracted to the rails-dom-testing gem.")
diff --git a/actionpack/test/controller/parameters/accessors_test.rb b/actionpack/test/controller/parameters/accessors_test.rb
new file mode 100644
index 0000000000..97875c3cbb
--- /dev/null
+++ b/actionpack/test/controller/parameters/accessors_test.rb
@@ -0,0 +1,125 @@
+require 'abstract_unit'
+require 'action_controller/metal/strong_parameters'
+require 'active_support/core_ext/hash/transform_values'
+
+class ParametersAccessorsTest < ActiveSupport::TestCase
+ setup do
+ @params = ActionController::Parameters.new(
+ person: {
+ age: '32',
+ name: {
+ first: 'David',
+ last: 'Heinemeier Hansson'
+ },
+ addresses: [{city: 'Chicago', state: 'Illinois'}]
+ }
+ )
+ end
+
+ test "[] retains permitted status" do
+ @params.permit!
+ assert @params[:person].permitted?
+ assert @params[:person][:name].permitted?
+ end
+
+ test "[] retains unpermitted status" do
+ assert_not @params[:person].permitted?
+ assert_not @params[:person][:name].permitted?
+ end
+
+ test "each carries permitted status" do
+ @params.permit!
+ @params.each { |key, value| assert(value.permitted?) if key == "person" }
+ end
+
+ test "each carries unpermitted status" do
+ @params.each { |key, value| assert_not(value.permitted?) if key == "person" }
+ end
+
+ test "each_pair carries permitted status" do
+ @params.permit!
+ @params.each_pair { |key, value| assert(value.permitted?) if key == "person" }
+ end
+
+ test "each_pair carries unpermitted status" do
+ @params.each_pair { |key, value| assert_not(value.permitted?) if key == "person" }
+ end
+
+ test "except retains permitted status" do
+ @params.permit!
+ assert @params.except(:person).permitted?
+ assert @params[:person].except(:name).permitted?
+ end
+
+ test "except retains unpermitted status" do
+ assert_not @params.except(:person).permitted?
+ assert_not @params[:person].except(:name).permitted?
+ end
+
+ test "fetch retains permitted status" do
+ @params.permit!
+ assert @params.fetch(:person).permitted?
+ assert @params[:person].fetch(:name).permitted?
+ end
+
+ test "fetch retains unpermitted status" do
+ assert_not @params.fetch(:person).permitted?
+ assert_not @params[:person].fetch(:name).permitted?
+ end
+
+ test "reject retains permitted status" do
+ assert_not @params.reject { |k| k == "person" }.permitted?
+ end
+
+ test "reject retains unpermitted status" do
+ @params.permit!
+ assert @params.reject { |k| k == "person" }.permitted?
+ end
+
+ test "select retains permitted status" do
+ @params.permit!
+ assert @params.select { |k| k == "person" }.permitted?
+ end
+
+ test "select retains unpermitted status" do
+ assert_not @params.select { |k| k == "person" }.permitted?
+ end
+
+ test "slice retains permitted status" do
+ @params.permit!
+ assert @params.slice(:person).permitted?
+ end
+
+ test "slice retains unpermitted status" do
+ assert_not @params.slice(:person).permitted?
+ end
+
+ test "transform_keys retains permitted status" do
+ @params.permit!
+ assert @params.transform_keys { |k| k }.permitted?
+ end
+
+ test "transform_keys retains unpermitted status" do
+ assert_not @params.transform_keys { |k| k }.permitted?
+ end
+
+ test "transform_values retains permitted status" do
+ @params.permit!
+ assert @params.transform_values { |v| v }.permitted?
+ end
+
+ test "transform_values retains unpermitted status" do
+ assert_not @params.transform_values { |v| v }.permitted?
+ end
+
+ test "values_at retains permitted status" do
+ @params.permit!
+ assert @params.values_at(:person).first.permitted?
+ assert @params[:person].values_at(:name).first.permitted?
+ end
+
+ test "values_at retains unpermitted status" do
+ assert_not @params.values_at(:person).first.permitted?
+ assert_not @params[:person].values_at(:name).first.permitted?
+ end
+end
diff --git a/actionpack/test/controller/parameters/mutators_test.rb b/actionpack/test/controller/parameters/mutators_test.rb
new file mode 100644
index 0000000000..744d8664be
--- /dev/null
+++ b/actionpack/test/controller/parameters/mutators_test.rb
@@ -0,0 +1,99 @@
+require 'abstract_unit'
+require 'action_controller/metal/strong_parameters'
+require 'active_support/core_ext/hash/transform_values'
+
+class ParametersMutatorsTest < ActiveSupport::TestCase
+ setup do
+ @params = ActionController::Parameters.new(
+ person: {
+ age: '32',
+ name: {
+ first: 'David',
+ last: 'Heinemeier Hansson'
+ },
+ addresses: [{city: 'Chicago', state: 'Illinois'}]
+ }
+ )
+ end
+
+ test "delete retains permitted status" do
+ @params.permit!
+ assert @params.delete(:person).permitted?
+ end
+
+ test "delete retains unpermitted status" do
+ assert_not @params.delete(:person).permitted?
+ end
+
+ test "delete_if retains permitted status" do
+ @params.permit!
+ assert @params.delete_if { |k| k == "person" }.permitted?
+ end
+
+ test "delete_if retains unpermitted status" do
+ assert_not @params.delete_if { |k| k == "person" }.permitted?
+ end
+
+ test "extract! retains permitted status" do
+ @params.permit!
+ assert @params.extract!(:person).permitted?
+ end
+
+ test "extract! retains unpermitted status" do
+ assert_not @params.extract!(:person).permitted?
+ end
+
+ test "keep_if retains permitted status" do
+ @params.permit!
+ assert @params.keep_if { |k,v| k == "person" }.permitted?
+ end
+
+ test "keep_if retains unpermitted status" do
+ assert_not @params.keep_if { |k,v| k == "person" }.permitted?
+ end
+
+ test "reject! retains permitted status" do
+ @params.permit!
+ assert @params.reject! { |k| k == "person" }.permitted?
+ end
+
+ test "reject! retains unpermitted status" do
+ assert_not @params.reject! { |k| k == "person" }.permitted?
+ end
+
+ test "select! retains permitted status" do
+ @params.permit!
+ assert @params.select! { |k| k != "person" }.permitted?
+ end
+
+ test "select! retains unpermitted status" do
+ assert_not @params.select! { |k| k != "person" }.permitted?
+ end
+
+ test "slice! retains permitted status" do
+ @params.permit!
+ assert @params.slice!(:person).permitted?
+ end
+
+ test "slice! retains unpermitted status" do
+ assert_not @params.slice!(:person).permitted?
+ end
+
+ test "transform_keys! retains permitted status" do
+ @params.permit!
+ assert @params.transform_keys! { |k| k }.permitted?
+ end
+
+ test "transform_keys! retains unpermitted status" do
+ assert_not @params.transform_keys! { |k| k }.permitted?
+ end
+
+ test "transform_values! retains permitted status" do
+ @params.permit!
+ assert @params.transform_values! { |v| v }.permitted?
+ end
+
+ test "transform_values! retains unpermitted status" do
+ assert_not @params.transform_values! { |v| v }.permitted?
+ end
+end
diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb
index aa894ffa17..ba98ad7605 100644
--- a/actionpack/test/controller/parameters/parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/parameters_permit_test.rb
@@ -194,42 +194,6 @@ class ParametersPermitTest < ActiveSupport::TestCase
assert_equal "monkey", @params.fetch(:foo) { "monkey" }
end
- test "not permitted is sticky on accessors" do
- assert !@params.slice(:person).permitted?
- assert !@params[:person][:name].permitted?
- assert !@params[:person].except(:name).permitted?
-
- @params.each { |key, value| assert(!value.permitted?) if key == "person" }
-
- assert !@params.fetch(:person).permitted?
-
- assert !@params.values_at(:person).first.permitted?
- end
-
- test "permitted is sticky on accessors" do
- @params.permit!
- assert @params.slice(:person).permitted?
- assert @params[:person][:name].permitted?
- assert @params[:person].except(:name).permitted?
-
- @params.each { |key, value| assert(value.permitted?) if key == "person" }
-
- assert @params.fetch(:person).permitted?
-
- assert @params.values_at(:person).first.permitted?
- end
-
- test "not permitted is sticky on mutators" do
- assert !@params.delete_if { |k| k == "person" }.permitted?
- assert !@params.keep_if { |k,v| k == "person" }.permitted?
- end
-
- test "permitted is sticky on mutators" do
- @params.permit!
- assert @params.delete_if { |k| k == "person" }.permitted?
- assert @params.keep_if { |k,v| k == "person" }.permitted?
- end
-
test "not permitted is sticky beyond merges" do
assert !@params.merge(a: "b").permitted?
end
@@ -277,4 +241,43 @@ class ParametersPermitTest < ActiveSupport::TestCase
test "permitting parameters as an array" do
assert_equal "32", @params[:person].permit([ :age ])[:age]
end
+
+ test "to_h returns empty hash on unpermitted params" do
+ assert @params.to_h.is_a? Hash
+ assert_not @params.to_h.is_a? ActionController::Parameters
+ assert @params.to_h.empty?
+ end
+
+ test "to_h returns converted hash on permitted params" do
+ @params.permit!
+
+ assert @params.to_h.is_a? Hash
+ assert_not @params.to_h.is_a? ActionController::Parameters
+ assert_equal @params.to_hash, @params.to_h
+ end
+
+ test "to_h returns converted hash when .permit_all_parameters is set" do
+ begin
+ ActionController::Parameters.permit_all_parameters = true
+ params = ActionController::Parameters.new(crab: "Senjougahara Hitagi")
+
+ assert params.to_h.is_a? Hash
+ assert_not @params.to_h.is_a? ActionController::Parameters
+ assert_equal({ "crab" => "Senjougahara Hitagi" }, params.to_h)
+ ensure
+ ActionController::Parameters.permit_all_parameters = false
+ end
+ end
+
+ test "to_h returns always permitted parameter on unpermitted params" do
+ params = ActionController::Parameters.new(
+ controller: "users",
+ action: "create",
+ user: {
+ name: "Sengoku Nadeko"
+ }
+ )
+
+ assert_equal({ "controller" => "users", "action" => "create" }, params.to_h)
+ end
end
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index 05ad8b6cdc..3e0bfe8d14 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -125,8 +125,9 @@ end
module RequestForgeryProtectionTests
def setup
@token = "cf50faa3fe97702ca1ae"
-
- SecureRandom.stubs(:base64).returns(@token)
+ @controller.stubs(:form_authenticity_token).returns(@token)
+ @controller.stubs(:valid_authenticity_token?).with{ |_, t| t == @token }.returns(true)
+ @controller.stubs(:valid_authenticity_token?).with{ |_, t| t != @token }.returns(false)
@old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token
ActionController::Base.request_forgery_protection_token = :custom_authenticity_token
end
@@ -386,7 +387,7 @@ class RequestForgeryProtectionControllerUsingResetSessionTest < ActionController
end
test 'should emit a csrf-param meta tag and a csrf-token meta tag' do
- SecureRandom.stubs(:base64).returns(@token + '<=?')
+ @controller.stubs(:form_authenticity_token).returns(@token + '<=?')
get :meta
assert_select 'meta[name=?][content=?]', 'csrf-param', 'custom_authenticity_token'
assert_select 'meta[name=?]', 'csrf-token'
@@ -467,7 +468,7 @@ class CustomAuthenticityParamControllerTest < ActionController::TestCase
super
@old_logger = ActionController::Base.logger
@logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
- @token = "foobar"
+ @token = Base64.strict_encode64(SecureRandom.random_bytes(32))
@old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token
ActionController::Base.request_forgery_protection_token = @token
end
@@ -479,7 +480,7 @@ class CustomAuthenticityParamControllerTest < ActionController::TestCase
def test_should_not_warn_if_form_authenticity_param_matches_form_authenticity_token
ActionController::Base.logger = @logger
- SecureRandom.stubs(:base64).returns(@token)
+ @controller.stubs(:valid_authenticity_token?).returns(:true)
begin
post :index, :custom_token_name => 'foobar'
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index fe9ee6f73d..00b80c7357 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -650,6 +650,18 @@ class RequestMethod < BaseRequestTest
end
end
+ test "allow request method hacking" do
+ request = stub_request('REQUEST_METHOD' => 'POST')
+
+ assert_equal 'POST', request.request_method
+ assert_equal 'POST', request.env["REQUEST_METHOD"]
+
+ request.request_method = 'GET'
+
+ assert_equal 'GET', request.request_method
+ assert_equal 'GET', request.env["REQUEST_METHOD"]
+ end
+
test "invalid http method raises exception" do
assert_raise(ActionController::UnknownHttpMethod) do
stub_request('REQUEST_METHOD' => 'RANDOM_METHOD').request_method
@@ -909,6 +921,31 @@ class RequestParameters < BaseRequestTest
end
end
+ test "parameters not accessible after rack parse error of invalid UTF8 character" do
+ request = stub_request("QUERY_STRING" => "foo%81E=1")
+
+ 2.times do
+ assert_raises(ActionController::BadRequest) do
+ # rack will raise a Rack::Utils::InvalidParameterError when parsing this query string
+ request.parameters
+ end
+ end
+ end
+
+ test "parameters not accessible after rack parse error 1" do
+ request = stub_request(
+ 'REQUEST_METHOD' => 'POST',
+ 'CONTENT_LENGTH' => "a%=".length,
+ 'CONTENT_TYPE' => 'application/x-www-form-urlencoded; charset=utf-8',
+ 'rack.input' => StringIO.new("a%=")
+ )
+
+ assert_raises(ActionController::BadRequest) do
+ # rack will raise a TypeError when parsing this query string
+ request.parameters
+ end
+ end
+
test "we have access to the original exception" do
request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2")
diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb
index afdda70748..f4b3a8cb93 100644
--- a/actionpack/test/dispatch/static_test.rb
+++ b/actionpack/test/dispatch/static_test.rb
@@ -1,6 +1,7 @@
# encoding: utf-8
require 'abstract_unit'
require 'rbconfig'
+require 'zlib'
module StaticTests
def test_serves_dynamic_content
@@ -106,6 +107,18 @@ module StaticTests
end
end
+ def test_serves_gzip_files_when_header_set
+ file_name = "/gzip/application-a71b3024f80aea3181c09774ca17e712.js"
+ response = get(file_name, 'HTTP_ACCEPT_ENCODING' => 'gzip')
+ assert_gzip file_name, response
+ assert_equal 'application/javascript', response.headers['Content-Type']
+ assert_equal 'Accept-Encoding', response.headers["Vary"]
+ assert_equal 'gzip', response.headers["Content-Encoding"]
+
+ response = get(file_name, 'HTTP_ACCEPT_ENCODING' => '')
+ refute_equal 'gzip', response.headers["Content-Encoding"]
+ end
+
# Windows doesn't allow \ / : * ? " < > | in filenames
unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
def test_serves_static_file_with_colon
@@ -125,13 +138,20 @@ module StaticTests
private
+ def assert_gzip(file_name, response)
+ expected = File.read("#{FIXTURE_LOAD_PATH}/#{public_path}" + file_name)
+ actual = Zlib::GzipReader.new(StringIO.new(response.body)).read
+ assert_equal expected, actual
+ end
+
def assert_html(body, response)
assert_equal body, response.body
assert_equal "text/html", response.headers["Content-Type"]
+ refute response.headers.key?("Vary")
end
- def get(path)
- Rack::MockRequest.new(@app).request("GET", path)
+ def get(path, headers = {})
+ Rack::MockRequest.new(@app).request("GET", path, headers)
end
def with_static_file(file)
diff --git a/actionpack/test/fixtures/public/gzip/application-a71b3024f80aea3181c09774ca17e712.js b/actionpack/test/fixtures/public/gzip/application-a71b3024f80aea3181c09774ca17e712.js
new file mode 100644
index 0000000000..1826a7660e
--- /dev/null
+++ b/actionpack/test/fixtures/public/gzip/application-a71b3024f80aea3181c09774ca17e712.js
@@ -0,0 +1,4 @@
+!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t=e.length,n=it.type(e);return"function"===n||it.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e}function r(e,t,n){if(it.isFunction(t))return it.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return it.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(ft.test(t))return it.filter(t,e,n);t=it.filter(t,e)}return it.grep(e,function(e){return it.inArray(e,t)>=0!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t=xt[e]={};return it.each(e.match(bt)||[],function(e,n){t[n]=!0}),t}function a(){ht.addEventListener?(ht.removeEventListener("DOMContentLoaded",s,!1),e.removeEventListener("load",s,!1)):(ht.detachEvent("onreadystatechange",s),e.detachEvent("onload",s))}function s(){(ht.addEventListener||"load"===event.type||"complete"===ht.readyState)&&(a(),it.ready())}function l(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(Ct,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:kt.test(n)?it.parseJSON(n):n}catch(i){}it.data(e,t,n)}else n=void 0}return n}function u(e){var t;for(t in e)if(("data"!==t||!it.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function c(e,t,n,r){if(it.acceptData(e)){var i,o,a=it.expando,s=e.nodeType,l=s?it.cache:e,u=s?e[a]:e[a]&&a;if(u&&l[u]&&(r||l[u].data)||void 0!==n||"string"!=typeof t)return u||(u=s?e[a]=G.pop()||it.guid++:a),l[u]||(l[u]=s?{}:{toJSON:it.noop}),("object"==typeof t||"function"==typeof t)&&(r?l[u]=it.extend(l[u],t):l[u].data=it.extend(l[u].data,t)),o=l[u],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[it.camelCase(t)]=n),"string"==typeof t?(i=o[t],null==i&&(i=o[it.camelCase(t)])):i=o,i}}function d(e,t,n){if(it.acceptData(e)){var r,i,o=e.nodeType,a=o?it.cache:e,s=o?e[it.expando]:it.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){it.isArray(t)?t=t.concat(it.map(t,it.camelCase)):t in r?t=[t]:(t=it.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;for(;i--;)delete r[t[i]];if(n?!u(r):!it.isEmptyObject(r))return}(n||(delete a[s].data,u(a[s])))&&(o?it.cleanData([e],!0):nt.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}function f(){return!0}function p(){return!1}function h(){try{return ht.activeElement}catch(e){}}function m(e){var t=Mt.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function g(e,t){var n,r,i=0,o=typeof e.getElementsByTagName!==Et?e.getElementsByTagName(t||"*"):typeof e.querySelectorAll!==Et?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||it.nodeName(r,t)?o.push(r):it.merge(o,g(r,t));return void 0===t||t&&it.nodeName(e,t)?it.merge([e],o):o}function v(e){Dt.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t){return it.nodeName(e,"table")&&it.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function b(e){return e.type=(null!==it.find.attr(e,"type"))+"/"+e.type,e}function x(e){var t=Vt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function w(e,t){for(var n,r=0;null!=(n=e[r]);r++)it._data(n,"globalEval",!t||it._data(t[r],"globalEval"))}function T(e,t){if(1===t.nodeType&&it.hasData(e)){var n,r,i,o=it._data(e),a=it._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)it.event.add(t,n,s[n][r])}a.data&&(a.data=it.extend({},a.data))}}function E(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!nt.noCloneEvent&&t[it.expando]){i=it._data(t);for(r in i.events)it.removeEvent(t,r,i.handle);t.removeAttribute(it.expando)}"script"===n&&t.text!==e.text?(b(t).text=e.text,x(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),nt.html5Clone&&e.innerHTML&&!it.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Dt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function k(t,n){var r,i=it(n.createElement(t)).appendTo(n.body),o=e.getDefaultComputedStyle&&(r=e.getDefaultComputedStyle(i[0]))?r.display:it.css(i[0],"display");return i.detach(),o}function C(e){var t=ht,n=Zt[e];return n||(n=k(e,t),"none"!==n&&n||(Qt=(Qt||it("<iframe frameborder='0' width='0' height='0'/>")).appendTo(t.documentElement),t=(Qt[0].contentWindow||Qt[0].contentDocument).document,t.write(),t.close(),n=k(e,t),Qt.detach()),Zt[e]=n),n}function N(e,t){return{get:function(){var n=e();if(null!=n)return n?void delete this.get:(this.get=t).apply(this,arguments)}}}function S(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=pn.length;i--;)if(t=pn[i]+n,t in e)return t;return r}function j(e,t){for(var n,r,i,o=[],a=0,s=e.length;s>a;a++)r=e[a],r.style&&(o[a]=it._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&jt(r)&&(o[a]=it._data(r,"olddisplay",C(r.nodeName)))):(i=jt(r),(n&&"none"!==n||!i)&&it._data(r,"olddisplay",i?n:it.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}function A(e,t,n){var r=un.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function D(e,t,n,r,i){for(var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;4>o;o+=2)"margin"===n&&(a+=it.css(e,n+St[o],!0,i)),r?("content"===n&&(a-=it.css(e,"padding"+St[o],!0,i)),"margin"!==n&&(a-=it.css(e,"border"+St[o]+"Width",!0,i))):(a+=it.css(e,"padding"+St[o],!0,i),"padding"!==n&&(a+=it.css(e,"border"+St[o]+"Width",!0,i)));return a}function L(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=en(e),a=nt.boxSizing&&"border-box"===it.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=tn(e,t,o),(0>i||null==i)&&(i=e.style[t]),rn.test(i))return i;r=a&&(nt.boxSizingReliable()||i===e.style[t]),i=parseFloat(i)||0}return i+D(e,t,n||(a?"border":"content"),r,o)+"px"}function H(e,t,n,r,i){return new H.prototype.init(e,t,n,r,i)}function _(){return setTimeout(function(){hn=void 0}),hn=it.now()}function q(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=St[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function F(e,t,n){for(var r,i=(xn[t]||[]).concat(xn["*"]),o=0,a=i.length;a>o;o++)if(r=i[o].call(n,t,e))return r}function M(e,t,n){var r,i,o,a,s,l,u,c,d=this,f={},p=e.style,h=e.nodeType&&jt(e),m=it._data(e,"fxshow");n.queue||(s=it._queueHooks(e,"fx"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,d.always(function(){d.always(function(){s.unqueued--,it.queue(e,"fx").length||s.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],u=it.css(e,"display"),c="none"===u?it._data(e,"olddisplay")||C(e.nodeName):u,"inline"===c&&"none"===it.css(e,"float")&&(nt.inlineBlockNeedsLayout&&"inline"!==C(e.nodeName)?p.zoom=1:p.display="inline-block")),n.overflow&&(p.overflow="hidden",nt.shrinkWrapBlocks()||d.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],gn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(h?"hide":"show")){if("show"!==i||!m||void 0===m[r])continue;h=!0}f[r]=m&&m[r]||it.style(e,r)}else u=void 0;if(it.isEmptyObject(f))"inline"===("none"===u?C(e.nodeName):u)&&(p.display=u);else{m?"hidden"in m&&(h=m.hidden):m=it._data(e,"fxshow",{}),o&&(m.hidden=!h),h?it(e).show():d.done(function(){it(e).hide()}),d.done(function(){var t;it._removeData(e,"fxshow");for(t in f)it.style(e,t,f[t])});for(r in f)a=F(h?m[r]:0,r,d),r in m||(m[r]=a.start,h&&(a.end=a.start,a.start="width"===r||"height"===r?1:0))}}function O(e,t){var n,r,i,o,a;for(n in e)if(r=it.camelCase(n),i=t[r],o=e[n],it.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=it.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function R(e,t,n){var r,i,o=0,a=bn.length,s=it.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;for(var t=hn||_(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:it.extend({},t),opts:it.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:hn||_(),duration:n.duration,tweens:[],createTween:function(t,n){var r=it.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(O(c,u.opts.specialEasing);a>o;o++)if(r=bn[o].call(u,e,c,u.opts))return r;return it.map(c,F,u),it.isFunction(u.opts.start)&&u.opts.start.call(e,u),it.fx.timer(it.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function B(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(bt)||[];if(it.isFunction(n))for(;r=o[i++];)"+"===r.charAt(0)?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function P(e,t,n,r){function i(s){var l;return o[s]=!0,it.each(e[s]||[],function(e,s){var u=s(t,n,r);return"string"!=typeof u||a||o[u]?a?!(l=u):void 0:(t.dataTypes.unshift(u),i(u),!1)}),l}var o={},a=e===zn;return i(t.dataTypes[0])||!o["*"]&&i("*")}function I(e,t){var n,r,i=it.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&it.extend(!0,e,n),e}function W(e,t,n){for(var r,i,o,a,s=e.contents,l=e.dataTypes;"*"===l[0];)l.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader("Content-Type"));if(i)for(a in s)if(s[a]&&s[a].test(i)){l.unshift(a);break}if(l[0]in n)o=l[0];else{for(a in n){if(!l[0]||e.converters[a+" "+l[0]]){o=a;break}r||(r=a)}o=o||r}return o?(o!==l[0]&&l.unshift(o),n[o]):void 0}function $(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(a=u[l+" "+o]||u["* "+o],!a)for(i in u)if(s=i.split(" "),s[1]===o&&(a=u[l+" "+s[0]]||u["* "+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(d){return{state:"parsererror",error:a?d:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}function z(e,t,n,r){var i;if(it.isArray(t))it.each(t,function(t,i){n||Gn.test(e)?r(e,i):z(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==it.type(t))r(e,t);else for(i in t)z(e+"["+i+"]",t[i],n,r)}function X(){try{return new e.XMLHttpRequest}catch(t){}}function U(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function V(e){return it.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}var G=[],Y=G.slice,J=G.concat,K=G.push,Q=G.indexOf,Z={},et=Z.toString,tt=Z.hasOwnProperty,nt={},rt="1.11.1",it=function(e,t){return new it.fn.init(e,t)},ot=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,at=/^-ms-/,st=/-([\da-z])/gi,lt=function(e,t){return t.toUpperCase()};it.fn=it.prototype={jquery:rt,constructor:it,selector:"",length:0,toArray:function(){return Y.call(this)},get:function(e){return null!=e?0>e?this[e+this.length]:this[e]:Y.call(this)},pushStack:function(e){var t=it.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return it.each(this,e,t)},map:function(e){return this.pushStack(it.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(Y.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:K,sort:G.sort,splice:G.splice},it.extend=it.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,l=arguments.length,u=!1;for("boolean"==typeof a&&(u=a,a=arguments[s]||{},s++),"object"==typeof a||it.isFunction(a)||(a={}),s===l&&(a=this,s--);l>s;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(u&&n&&(it.isPlainObject(n)||(t=it.isArray(n)))?(t?(t=!1,o=e&&it.isArray(e)?e:[]):o=e&&it.isPlainObject(e)?e:{},a[r]=it.extend(u,o,n)):void 0!==n&&(a[r]=n));return a},it.extend({expando:"jQuery"+(rt+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return"function"===it.type(e)},isArray:Array.isArray||function(e){return"array"===it.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!it.isArray(e)&&e-parseFloat(e)>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||"object"!==it.type(e)||e.nodeType||it.isWindow(e))return!1;try{if(e.constructor&&!tt.call(e,"constructor")&&!tt.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}if(nt.ownLast)for(t in e)return tt.call(e,t);for(t in e);return void 0===t||tt.call(e,t)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?Z[et.call(e)]||"object":typeof e},globalEval:function(t){t&&it.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(at,"ms-").replace(st,lt)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,r){var i,o=0,a=e.length,s=n(e);if(r){if(s)for(;a>o&&(i=t.apply(e[o],r),i!==!1);o++);else for(o in e)if(i=t.apply(e[o],r),i===!1)break}else if(s)for(;a>o&&(i=t.call(e[o],o,e[o]),i!==!1);o++);else for(o in e)if(i=t.call(e[o],o,e[o]),i===!1)break;return e},trim:function(e){return null==e?"":(e+"").replace(ot,"")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?it.merge(r,"string"==typeof e?[e]:e):K.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(Q)return Q.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;n>r;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;a>o;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o=0,a=e.length,s=n(e),l=[];if(s)for(;a>o;o++)i=t(e[o],o,r),null!=i&&l.push(i);else for(o in e)i=t(e[o],o,r),null!=i&&l.push(i);return J.apply([],l)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(i=e[t],t=e,e=i),it.isFunction(e)?(n=Y.call(arguments,2),r=function(){return e.apply(t||this,n.concat(Y.call(arguments)))},r.guid=e.guid=e.guid||it.guid++,r):void 0},now:function(){return+new Date},support:nt}),it.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){Z["[object "+t+"]"]=t.toLowerCase()});var ut=function(e){function t(e,t,n,r){var i,o,a,s,l,u,d,p,h,m;if((t?t.ownerDocument||t:P)!==H&&L(t),t=t||H,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(q&&!r){if(i=yt.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&R(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return Z.apply(n,t.getElementsByTagName(e)),n;if((a=i[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Z.apply(n,t.getElementsByClassName(a)),n}if(w.qsa&&(!F||!F.test(e))){if(p=d=B,h=t,m=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){for(u=C(e),(d=t.getAttribute("id"))?p=d.replace(xt,"\\$&"):t.setAttribute("id",p),p="[id='"+p+"'] ",l=u.length;l--;)u[l]=p+f(u[l]);h=bt.test(e)&&c(t.parentNode)||t,m=u.join(",")}if(m)try{return Z.apply(n,h.querySelectorAll(m)),n}catch(g){}finally{d||t.removeAttribute("id")}}}return S(e.replace(lt,"$1"),t,n,r)}function n(){function e(n,r){return t.push(n+" ")>T.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[B]=!0,e}function i(e){var t=H.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=e.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||G)-(~e.sourceIndex||G);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function l(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function u(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&typeof e.getElementsByTagName!==V&&e}function d(){}function f(e){for(var t=0,n=e.length,r="";n>t;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&"parentNode"===r,o=W++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,l,u=[I,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[B]||(t[B]={}),(s=l[r])&&s[0]===I&&s[1]===o)return u[2]=s[2];if(l[r]=u,u[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function m(e,n,r){for(var i=0,o=n.length;o>i;i++)t(e,n[i],r);return r}function g(e,t,n,r,i){for(var o,a=[],s=0,l=e.length,u=null!=t;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function v(e,t,n,i,o,a){return i&&!i[B]&&(i=v(i)),o&&!o[B]&&(o=v(o,a)),r(function(r,a,s,l){var u,c,d,f=[],p=[],h=a.length,v=r||m(t||"*",s.nodeType?[s]:s,[]),y=!e||!r&&t?v:g(v,f,e,s,l),b=n?o||(r?e:h||i)?[]:a:y;if(n&&n(y,b,s,l),i)for(u=g(b,p),i(u,[],s,l),c=u.length;c--;)(d=u[c])&&(b[p[c]]=!(y[p[c]]=d));if(r){if(o||e){if(o){for(u=[],c=b.length;c--;)(d=b[c])&&u.push(y[c]=d);o(null,b=[],u,l)}for(c=b.length;c--;)(d=b[c])&&(u=o?tt.call(r,d):f[c])>-1&&(r[u]=!(a[u]=d))}}else b=g(b===a?b.splice(h,b.length):b),o?o(null,a,b,l):Z.apply(a,b)})}function y(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[" "],s=o?1:0,l=p(function(e){return e===t},a,!0),u=p(function(e){return tt.call(t,e)>-1},a,!0),c=[function(e,n,r){return!o&&(r||n!==j)||((t=n).nodeType?l(e,n,r):u(e,n,r))}];i>s;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[B]){for(r=++s;i>r&&!T.relative[e[r].type];r++);return v(s>1&&h(c),s>1&&f(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(lt,"$1"),n,r>s&&y(e.slice(s,r)),i>r&&y(e=e.slice(r)),i>r&&f(e))}c.push(n)}return h(c)}function b(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,l,u){var c,d,f,p=0,h="0",m=r&&[],v=[],y=j,b=r||o&&T.find.TAG("*",u),x=I+=null==y?1:Math.random()||.1,w=b.length;for(u&&(j=a!==H&&a);h!==w&&null!=(c=b[h]);h++){if(o&&c){for(d=0;f=e[d++];)if(f(c,a,s)){l.push(c);break}u&&(I=x)}i&&((c=!f&&c)&&p--,r&&m.push(c))}if(p+=h,i&&h!==p){for(d=0;f=n[d++];)f(m,v,a,s);if(r){if(p>0)for(;h--;)m[h]||v[h]||(v[h]=K.call(l));v=g(v)}Z.apply(l,v),u&&!r&&v.length>0&&p+n.length>1&&t.uniqueSort(l)}return u&&(I=x,j=y),m};return i?r(a):a}var x,w,T,E,k,C,N,S,j,A,D,L,H,_,q,F,M,O,R,B="sizzle"+-new Date,P=e.document,I=0,W=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(D=!0),0},V="undefined",G=1<<31,Y={}.hasOwnProperty,J=[],K=J.pop,Q=J.push,Z=J.push,et=J.slice,tt=J.indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(this[t]===e)return t;return-1},nt="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",rt="[\\x20\\t\\r\\n\\f]",it="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",ot=it.replace("w","w#"),at="\\["+rt+"*("+it+")(?:"+rt+"*([*^$|!~]?=)"+rt+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+ot+"))|)"+rt+"*\\]",st=":("+it+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+at+")*)|.*)\\)|)",lt=new RegExp("^"+rt+"+|((?:^|[^\\\\])(?:\\\\.)*)"+rt+"+$","g"),ut=new RegExp("^"+rt+"*,"+rt+"*"),ct=new RegExp("^"+rt+"*([>+~]|"+rt+")"+rt+"*"),dt=new RegExp("="+rt+"*([^\\]'\"]*?)"+rt+"*\\]","g"),ft=new RegExp(st),pt=new RegExp("^"+ot+"$"),ht={ID:new RegExp("^#("+it+")"),CLASS:new RegExp("^\\.("+it+")"),TAG:new RegExp("^("+it.replace("w","w*")+")"),ATTR:new RegExp("^"+at),PSEUDO:new RegExp("^"+st),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+rt+"*(even|odd|(([+-]|)(\\d*)n|)"+rt+"*(?:([+-]|)"+rt+"*(\\d+)|))"+rt+"*\\)|)","i"),bool:new RegExp("^(?:"+nt+")$","i"),needsContext:new RegExp("^"+rt+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+rt+"*((?:-\\d)?\\d*)"+rt+"*\\)|)(?=[^-]|$)","i")},mt=/^(?:input|select|textarea|button)$/i,gt=/^h\d$/i,vt=/^[^{]+\{\s*\[native \w/,yt=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,bt=/[+~]/,xt=/'|\\/g,wt=new RegExp("\\\\([\\da-f]{1,6}"+rt+"?|("+rt+")|.)","ig"),Tt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)};try{Z.apply(J=et.call(P.childNodes),P.childNodes),J[P.childNodes.length].nodeType}catch(Et){Z={apply:J.length?function(e,t){Q.apply(e,et.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},k=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},L=t.setDocument=function(e){var t,n=e?e.ownerDocument||e:P,r=n.defaultView;return n!==H&&9===n.nodeType&&n.documentElement?(H=n,_=n.documentElement,q=!k(n),r&&r!==r.top&&(r.addEventListener?r.addEventListener("unload",function(){L()},!1):r.attachEvent&&r.attachEvent("onunload",function(){L()})),w.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),w.getElementsByTagName=i(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),w.getElementsByClassName=vt.test(n.getElementsByClassName)&&i(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),w.getById=i(function(e){return _.appendChild(e).id=B,!n.getElementsByName||!n.getElementsByName(B).length}),w.getById?(T.find.ID=function(e,t){if(typeof t.getElementById!==V&&q){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},T.filter.ID=function(e){var t=e.replace(wt,Tt);return function(e){return e.getAttribute("id")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(wt,Tt);return function(e){var n=typeof e.getAttributeNode!==V&&e.getAttributeNode("id");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==V?t.getElementsByTagName(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==V&&q?t.getElementsByClassName(e):void 0},M=[],F=[],(w.qsa=vt.test(n.querySelectorAll))&&(i(function(e){e.innerHTML="<select msallowclip=''><option selected=''></option></select>",e.querySelectorAll("[msallowclip^='']").length&&F.push("[*^$]="+rt+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||F.push("\\["+rt+"*(?:value|"+nt+")"),e.querySelectorAll(":checked").length||F.push(":checked")}),i(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&F.push("name"+rt+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||F.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),F.push(",.*:")})),(w.matchesSelector=vt.test(O=_.matches||_.webkitMatchesSelector||_.mozMatchesSelector||_.oMatchesSelector||_.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),M.push("!=",st)}),F=F.length&&new RegExp(F.join("|")),M=M.length&&new RegExp(M.join("|")),t=vt.test(_.compareDocumentPosition),R=t||vt.test(_.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return D=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r?r:(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&r||!w.sortDetached&&t.compareDocumentPosition(e)===r?e===n||e.ownerDocument===P&&R(P,e)?-1:t===n||t.ownerDocument===P&&R(P,t)?1:A?tt.call(A,e)-tt.call(A,t):0:4&r?-1:1)}:function(e,t){if(e===t)return D=!0,0;var r,i=0,o=e.parentNode,s=t.parentNode,l=[e],u=[t];if(!o||!s)return e===n?-1:t===n?1:o?-1:s?1:A?tt.call(A,e)-tt.call(A,t):0;if(o===s)return a(e,t);for(r=e;r=r.parentNode;)l.unshift(r);for(r=t;r=r.parentNode;)u.unshift(r);for(;l[i]===u[i];)i++;return i?a(l[i],u[i]):l[i]===P?-1:u[i]===P?1:0},n):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(dt,"='$1']"),!(!w.matchesSelector||!q||M&&M.test(n)||F&&F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!q):void 0;return void 0!==r?r:w.attributes||!q?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(D=!w.detectDuplicates,A=!w.sortStable&&e.slice(0),e.sort(U),D){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return A=null,e},E=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=E(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=E(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:ht,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(wt,Tt),e[3]=(e[3]||e[4]||e[5]||"").replace(wt,Tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return ht.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&ft.test(n)&&(t=C(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(wt,Tt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+rt+")"+e+"("+rt+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==V&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:n?(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o+" ").indexOf(r)>-1:"|="===n?o===r||o.slice(0,r.length+1)===r+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,d,f,p,h,m=o!==a?"nextSibling":"previousSibling",g=t.parentNode,v=s&&t.nodeName.toLowerCase(),y=!l&&!s;if(g){if(o){for(;m;){for(d=t;d=d[m];)if(s?d.nodeName.toLowerCase()===v:1===d.nodeType)return!1;h=m="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?g.firstChild:g.lastChild],a&&y){for(c=g[B]||(g[B]={}),u=c[e]||[],p=u[0]===I&&u[1],f=u[0]===I&&u[2],d=p&&g.childNodes[p];d=++p&&d&&d[m]||(f=p=0)||h.pop();)if(1===d.nodeType&&++f&&d===t){c[e]=[I,p,f];break}}else if(y&&(u=(t[B]||(t[B]={}))[e])&&u[0]===I)f=u[1];else for(;(d=++p&&d&&d[m]||(f=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==v:1!==d.nodeType)||!++f||(y&&((d[B]||(d[B]={}))[e]=[I,f]),d!==t)););return f-=i,f===r||f%r===0&&f/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[B]?o(n):o.length>1?(i=[e,e,"",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=tt.call(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=N(e.replace(lt,"$1"));return i[B]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return function(t){return(t.textContent||t.innerText||E(t)).indexOf(e)>-1}}),lang:r(function(e){return pt.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(wt,Tt).toLowerCase(),function(t){var n;do if(n=q?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===_},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return gt.test(e.nodeName)},input:function(e){return mt.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:u(function(){return[0]}),last:u(function(e,t){return[t-1]}),eq:u(function(e,t,n){return[0>n?n+t:n]}),even:u(function(e,t){for(var n=0;t>n;n+=2)e.push(n);return e}),odd:u(function(e,t){for(var n=1;t>n;n+=2)e.push(n);return e}),lt:u(function(e,t,n){for(var r=0>n?n+t:n;--r>=0;)e.push(r);return e}),gt:u(function(e,t,n){for(var r=0>n?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(x in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[x]=s(x);for(x in{submit:!0,reset:!0})T.pseudos[x]=l(x);return d.prototype=T.filters=T.pseudos,T.setFilters=new d,C=t.tokenize=function(e,n){var r,i,o,a,s,l,u,c=z[e+" "];if(c)return n?0:c.slice(0);for(s=e,l=[],u=T.preFilter;s;){(!r||(i=ut.exec(s)))&&(i&&(s=s.slice(i[0].length)||s),l.push(o=[])),r=!1,(i=ct.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(lt," ")}),s=s.slice(r.length));for(a in T.filter)!(i=ht[a].exec(s))||u[a]&&!(i=u[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,l).slice(0)},N=t.compile=function(e,t){var n,r=[],i=[],o=X[e+" "];if(!o){for(t||(t=C(e)),n=t.length;n--;)o=y(t[n]),o[B]?r.push(o):i.push(o);o=X(e,b(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,l,u="function"==typeof e&&e,d=!r&&C(e=u.selector||e);if(n=n||[],1===d.length){if(o=d[0]=d[0].slice(0),o.length>2&&"ID"===(a=o[0]).type&&w.getById&&9===t.nodeType&&q&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(wt,Tt),t)||[])[0],!t)return n;u&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=ht.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((l=T.find[s])&&(r=l(a.matches[0].replace(wt,Tt),bt.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&f(o),!e)return Z.apply(n,r),n;
+break}}return(u||N(e,d))(r,t,!q,n,bt.test(e)&&c(t.parentNode)||t),n},w.sortStable=B.split("").sort(U).join("")===B,w.detectDuplicates=!!D,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement("div"))}),i(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){return n?void 0:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?void 0:e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(nt,function(e,t,n){var r;return n?void 0:e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);it.find=ut,it.expr=ut.selectors,it.expr[":"]=it.expr.pseudos,it.unique=ut.uniqueSort,it.text=ut.getText,it.isXMLDoc=ut.isXML,it.contains=ut.contains;var ct=it.expr.match.needsContext,dt=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,ft=/^.[^:#\[\.,]*$/;it.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?it.find.matchesSelector(r,e)?[r]:[]:it.find.matches(e,it.grep(t,function(e){return 1===e.nodeType}))},it.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(it(e).filter(function(){for(t=0;i>t;t++)if(it.contains(r[t],this))return!0}));for(t=0;i>t;t++)it.find(e,r[t],n);return n=this.pushStack(i>1?it.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,"string"==typeof e&&ct.test(e)?it(e):e||[],!1).length}});var pt,ht=e.document,mt=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,gt=it.fn.init=function(e,t){var n,r;if(!e)return this;if("string"==typeof e){if(n="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:mt.exec(e),!n||!n[1]&&t)return!t||t.jquery?(t||pt).find(e):this.constructor(t).find(e);if(n[1]){if(t=t instanceof it?t[0]:t,it.merge(this,it.parseHTML(n[1],t&&t.nodeType?t.ownerDocument||t:ht,!0)),dt.test(n[1])&&it.isPlainObject(t))for(n in t)it.isFunction(this[n])?this[n](t[n]):this.attr(n,t[n]);return this}if(r=ht.getElementById(n[2]),r&&r.parentNode){if(r.id!==n[2])return pt.find(e);this.length=1,this[0]=r}return this.context=ht,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):it.isFunction(e)?"undefined"!=typeof pt.ready?pt.ready(e):e(it):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),it.makeArray(e,this))};gt.prototype=it.fn,pt=it(ht);var vt=/^(?:parents|prev(?:Until|All))/,yt={children:!0,contents:!0,next:!0,prev:!0};it.extend({dir:function(e,t,n){for(var r=[],i=e[t];i&&9!==i.nodeType&&(void 0===n||1!==i.nodeType||!it(i).is(n));)1===i.nodeType&&r.push(i),i=i[t];return r},sibling:function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}}),it.fn.extend({has:function(e){var t,n=it(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(it.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=ct.test(e)||"string"!=typeof e?it(e,t||this.context):0;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&it.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?it.unique(o):o)},index:function(e){return e?"string"==typeof e?it.inArray(this[0],it(e)):it.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(it.unique(it.merge(this.get(),it(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),it.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return it.dir(e,"parentNode")},parentsUntil:function(e,t,n){return it.dir(e,"parentNode",n)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return it.dir(e,"nextSibling")},prevAll:function(e){return it.dir(e,"previousSibling")},nextUntil:function(e,t,n){return it.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return it.dir(e,"previousSibling",n)},siblings:function(e){return it.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return it.sibling(e.firstChild)},contents:function(e){return it.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:it.merge([],e.childNodes)}},function(e,t){it.fn[e]=function(n,r){var i=it.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=it.filter(r,i)),this.length>1&&(yt[e]||(i=it.unique(i)),vt.test(e)&&(i=i.reverse())),this.pushStack(i)}});var bt=/\S+/g,xt={};it.Callbacks=function(e){e="string"==typeof e?xt[e]||o(e):it.extend({},e);var t,n,r,i,a,s,l=[],u=!e.once&&[],c=function(o){for(n=e.memory&&o,r=!0,a=s||0,s=0,i=l.length,t=!0;l&&i>a;a++)if(l[a].apply(o[0],o[1])===!1&&e.stopOnFalse){n=!1;break}t=!1,l&&(u?u.length&&c(u.shift()):n?l=[]:d.disable())},d={add:function(){if(l){var r=l.length;!function o(t){it.each(t,function(t,n){var r=it.type(n);"function"===r?e.unique&&d.has(n)||l.push(n):n&&n.length&&"string"!==r&&o(n)})}(arguments),t?i=l.length:n&&(s=r,c(n))}return this},remove:function(){return l&&it.each(arguments,function(e,n){for(var r;(r=it.inArray(n,l,r))>-1;)l.splice(r,1),t&&(i>=r&&i--,a>=r&&a--)}),this},has:function(e){return e?it.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],i=0,this},disable:function(){return l=u=n=void 0,this},disabled:function(){return!l},lock:function(){return u=void 0,n||d.disable(),this},locked:function(){return!u},fireWith:function(e,n){return!l||r&&!u||(n=n||[],n=[e,n.slice?n.slice():n],t?u.push(n):c(n)),this},fire:function(){return d.fireWith(this,arguments),this},fired:function(){return!!r}};return d},it.extend({Deferred:function(e){var t=[["resolve","done",it.Callbacks("once memory"),"resolved"],["reject","fail",it.Callbacks("once memory"),"rejected"],["notify","progress",it.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return it.Deferred(function(n){it.each(t,function(t,o){var a=it.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&it.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[o[0]+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?it.extend(e,r):r}},i={};return r.pipe=r.then,it.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=Y.call(arguments),a=o.length,s=1!==a||e&&it.isFunction(e.promise)?a:0,l=1===s?e:it.Deferred(),u=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?Y.call(arguments):i,r===t?l.notifyWith(n,r):--s||l.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);a>i;i++)o[i]&&it.isFunction(o[i].promise)?o[i].promise().done(u(i,r,o)).fail(l.reject).progress(u(i,n,t)):--s;return s||l.resolveWith(r,o),l.promise()}});var wt;it.fn.ready=function(e){return it.ready.promise().done(e),this},it.extend({isReady:!1,readyWait:1,holdReady:function(e){e?it.readyWait++:it.ready(!0)},ready:function(e){if(e===!0?!--it.readyWait:!it.isReady){if(!ht.body)return setTimeout(it.ready);it.isReady=!0,e!==!0&&--it.readyWait>0||(wt.resolveWith(ht,[it]),it.fn.triggerHandler&&(it(ht).triggerHandler("ready"),it(ht).off("ready")))}}}),it.ready.promise=function(t){if(!wt)if(wt=it.Deferred(),"complete"===ht.readyState)setTimeout(it.ready);else if(ht.addEventListener)ht.addEventListener("DOMContentLoaded",s,!1),e.addEventListener("load",s,!1);else{ht.attachEvent("onreadystatechange",s),e.attachEvent("onload",s);var n=!1;try{n=null==e.frameElement&&ht.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!it.isReady){try{n.doScroll("left")}catch(e){return setTimeout(i,50)}a(),it.ready()}}()}return wt.promise(t)};var Tt,Et="undefined";for(Tt in it(nt))break;nt.ownLast="0"!==Tt,nt.inlineBlockNeedsLayout=!1,it(function(){var e,t,n,r;n=ht.getElementsByTagName("body")[0],n&&n.style&&(t=ht.createElement("div"),r=ht.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),typeof t.style.zoom!==Et&&(t.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",nt.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=ht.createElement("div");if(null==nt.deleteExpando){nt.deleteExpando=!0;try{delete e.test}catch(t){nt.deleteExpando=!1}}e=null}(),it.acceptData=function(e){var t=it.noData[(e.nodeName+" ").toLowerCase()],n=+e.nodeType||1;return 1!==n&&9!==n?!1:!t||t!==!0&&e.getAttribute("classid")===t};var kt=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Ct=/([A-Z])/g;it.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?it.cache[e[it.expando]]:e[it.expando],!!e&&!u(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return d(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return d(e,t,!0)}}),it.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=it.data(o),1===o.nodeType&&!it._data(o,"parsedAttrs"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf("data-")&&(r=it.camelCase(r.slice(5)),l(o,r,i[r])));it._data(o,"parsedAttrs",!0)}return i}return"object"==typeof e?this.each(function(){it.data(this,e)}):arguments.length>1?this.each(function(){it.data(this,e,t)}):o?l(o,e,it.data(o,e)):void 0},removeData:function(e){return this.each(function(){it.removeData(this,e)})}}),it.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=it._data(e,t),n&&(!r||it.isArray(n)?r=it._data(e,t,it.makeArray(n)):r.push(n)),r||[]):void 0},dequeue:function(e,t){t=t||"fx";var n=it.queue(e,t),r=n.length,i=n.shift(),o=it._queueHooks(e,t),a=function(){it.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return it._data(e,n)||it._data(e,n,{empty:it.Callbacks("once memory").add(function(){it._removeData(e,t+"queue"),it._removeData(e,n)})})}}),it.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?it.queue(this[0],e):void 0===t?this:this.each(function(){var n=it.queue(this,e,t);it._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&it.dequeue(this,e)})},dequeue:function(e){return this.each(function(){it.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=it.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for("string"!=typeof e&&(t=e,e=void 0),e=e||"fx";a--;)n=it._data(o[a],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var Nt=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,St=["Top","Right","Bottom","Left"],jt=function(e,t){return e=t||e,"none"===it.css(e,"display")||!it.contains(e.ownerDocument,e)},At=it.access=function(e,t,n,r,i,o,a){var s=0,l=e.length,u=null==n;if("object"===it.type(n)){i=!0;for(s in n)it.access(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,it.isFunction(r)||(a=!0),u&&(a?(t.call(e,r),t=null):(u=t,t=function(e,t,n){return u.call(it(e),n)})),t))for(;l>s;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:u?t.call(e):l?t(e[0],n):o},Dt=/^(?:checkbox|radio)$/i;!function(){var e=ht.createElement("input"),t=ht.createElement("div"),n=ht.createDocumentFragment();if(t.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",nt.leadingWhitespace=3===t.firstChild.nodeType,nt.tbody=!t.getElementsByTagName("tbody").length,nt.htmlSerialize=!!t.getElementsByTagName("link").length,nt.html5Clone="<:nav></:nav>"!==ht.createElement("nav").cloneNode(!0).outerHTML,e.type="checkbox",e.checked=!0,n.appendChild(e),nt.appendChecked=e.checked,t.innerHTML="<textarea>x</textarea>",nt.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue,n.appendChild(t),t.innerHTML="<input type='radio' checked='checked' name='t'/>",nt.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,nt.noCloneEvent=!0,t.attachEvent&&(t.attachEvent("onclick",function(){nt.noCloneEvent=!1}),t.cloneNode(!0).click()),null==nt.deleteExpando){nt.deleteExpando=!0;try{delete t.test}catch(r){nt.deleteExpando=!1}}}(),function(){var t,n,r=ht.createElement("div");for(t in{submit:!0,change:!0,focusin:!0})n="on"+t,(nt[t+"Bubbles"]=n in e)||(r.setAttribute(n,"t"),nt[t+"Bubbles"]=r.attributes[n].expando===!1);r=null}();var Lt=/^(?:input|select|textarea)$/i,Ht=/^key/,_t=/^(?:mouse|pointer|contextmenu)|click/,qt=/^(?:focusinfocus|focusoutblur)$/,Ft=/^([^.]*)(?:\.(.+)|)$/;it.event={global:{},add:function(e,t,n,r,i){var o,a,s,l,u,c,d,f,p,h,m,g=it._data(e);if(g){for(n.handler&&(l=n,n=l.handler,i=l.selector),n.guid||(n.guid=it.guid++),(a=g.events)||(a=g.events={}),(c=g.handle)||(c=g.handle=function(e){return typeof it===Et||e&&it.event.triggered===e.type?void 0:it.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||"").match(bt)||[""],s=t.length;s--;)o=Ft.exec(t[s])||[],p=m=o[1],h=(o[2]||"").split(".").sort(),p&&(u=it.event.special[p]||{},p=(i?u.delegateType:u.bindType)||p,u=it.event.special[p]||{},d=it.extend({type:p,origType:m,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&it.expr.match.needsContext.test(i),namespace:h.join(".")},l),(f=a[p])||(f=a[p]=[],f.delegateCount=0,u.setup&&u.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent("on"+p,c))),u.add&&(u.add.call(e,d),d.handler.guid||(d.handler.guid=n.guid)),i?f.splice(f.delegateCount++,0,d):f.push(d),it.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,d,f,p,h,m,g=it.hasData(e)&&it._data(e);if(g&&(c=g.events)){for(t=(t||"").match(bt)||[""],u=t.length;u--;)if(s=Ft.exec(t[u])||[],p=m=s[1],h=(s[2]||"").split(".").sort(),p){for(d=it.event.special[p]||{},p=(r?d.delegateType:d.bindType)||p,f=c[p]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;o--;)a=f[o],!i&&m!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,d.remove&&d.remove.call(e,a));l&&!f.length&&(d.teardown&&d.teardown.call(e,h,g.handle)!==!1||it.removeEvent(e,p,g.handle),delete c[p])}else for(p in c)it.event.remove(e,p+t[u],n,r,!0);it.isEmptyObject(c)&&(delete g.handle,it._removeData(e,"events"))}},trigger:function(t,n,r,i){var o,a,s,l,u,c,d,f=[r||ht],p=tt.call(t,"type")?t.type:t,h=tt.call(t,"namespace")?t.namespace.split("."):[];if(s=c=r=r||ht,3!==r.nodeType&&8!==r.nodeType&&!qt.test(p+it.event.triggered)&&(p.indexOf(".")>=0&&(h=p.split("."),p=h.shift(),h.sort()),a=p.indexOf(":")<0&&"on"+p,t=t[it.expando]?t:new it.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.namespace_re=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:it.makeArray(n,[t]),u=it.event.special[p]||{},i||!u.trigger||u.trigger.apply(r,n)!==!1)){if(!i&&!u.noBubble&&!it.isWindow(r)){for(l=u.delegateType||p,qt.test(l+p)||(s=s.parentNode);s;s=s.parentNode)f.push(s),c=s;c===(r.ownerDocument||ht)&&f.push(c.defaultView||c.parentWindow||e)}for(d=0;(s=f[d++])&&!t.isPropagationStopped();)t.type=d>1?l:u.bindType||p,o=(it._data(s,"events")||{})[t.type]&&it._data(s,"handle"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&it.acceptData(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!u._default||u._default.apply(f.pop(),n)===!1)&&it.acceptData(r)&&a&&r[p]&&!it.isWindow(r)){c=r[a],c&&(r[a]=null),it.event.triggered=p;try{r[p]()}catch(m){}it.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=it.event.fix(e);var t,n,r,i,o,a=[],s=Y.call(arguments),l=(it._data(this,"events")||{})[e.type]||[],u=it.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!u.preDispatch||u.preDispatch.call(this,e)!==!1){for(a=it.event.handlers.call(this,e,l),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,o=0;(r=i.handlers[o++])&&!e.isImmediatePropagationStopped();)(!e.namespace_re||e.namespace_re.test(r.namespace))&&(e.handleObj=r,e.data=r.data,n=((it.event.special[r.origType]||{}).handle||r.handler).apply(i.elem,s),void 0!==n&&(e.result=n)===!1&&(e.preventDefault(),e.stopPropagation()));return u.postDispatch&&u.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,l=e.target;if(s&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(i=[],o=0;s>o;o++)r=t[o],n=r.selector+" ",void 0===i[n]&&(i[n]=r.needsContext?it(n,this).index(l)>=0:it.find(n,this,null,[l]).length),i[n]&&i.push(r);i.length&&a.push({elem:l,handlers:i})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[it.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=_t.test(i)?this.mouseHooks:Ht.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new it.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||ht),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||ht,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==h()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===h()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return it.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(e){return it.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=it.extend(new it.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?it.event.trigger(i,null,t):it.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},it.removeEvent=ht.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===Et&&(e[r]=null),e.detachEvent(r,n))},it.Event=function(e,t){return this instanceof it.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?f:p):this.type=e,t&&it.extend(this,t),this.timeStamp=e&&e.timeStamp||it.now(),void(this[it.expando]=!0)):new it.Event(e,t)},it.Event.prototype={isDefaultPrevented:p,isPropagationStopped:p,isImmediatePropagationStopped:p,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=f,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=f,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=f,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},it.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){it.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!it.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),nt.submitBubbles||(it.event.special.submit={setup:function(){return it.nodeName(this,"form")?!1:void it.event.add(this,"click._submit keypress._submit",function(e){var t=e.target,n=it.nodeName(t,"input")||it.nodeName(t,"button")?t.form:void 0;n&&!it._data(n,"submitBubbles")&&(it.event.add(n,"submit._submit",function(e){e._submit_bubble=!0}),it._data(n,"submitBubbles",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&it.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return it.nodeName(this,"form")?!1:void it.event.remove(this,"._submit")}}),nt.changeBubbles||(it.event.special.change={setup:function(){return Lt.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(it.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),it.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),it.event.simulate("change",this,e,!0)})),!1):void it.event.add(this,"beforeactivate._change",function(e){var t=e.target;Lt.test(t.nodeName)&&!it._data(t,"changeBubbles")&&(it.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||it.event.simulate("change",this.parentNode,e,!0)}),it._data(t,"changeBubbles",!0))})},handle:function(e){var t=e.target;return this!==t||e.isSimulated||e.isTrigger||"radio"!==t.type&&"checkbox"!==t.type?e.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return it.event.remove(this,"._change"),!Lt.test(this.nodeName)}}),nt.focusinBubbles||it.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){it.event.simulate(t,e.target,it.event.fix(e),!0)};it.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=it._data(r,t);i||r.addEventListener(e,n,!0),it._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=it._data(r,t)-1;i?it._data(r,t,i):(r.removeEventListener(e,n,!0),it._removeData(r,t))}}}),it.fn.extend({on:function(e,t,n,r,i){var o,a;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=void 0);for(o in e)this.on(o,t,n,e[o],i);return this}if(null==n&&null==r?(r=t,n=t=void 0):null==r&&("string"==typeof t?(r=n,n=void 0):(r=n,n=t,t=void 0)),r===!1)r=p;else if(!r)return this;return 1===i&&(a=r,r=function(e){return it().off(e),a.apply(this,arguments)},r.guid=a.guid||(a.guid=it.guid++)),this.each(function(){it.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,it(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=void 0),n===!1&&(n=p),this.each(function(){it.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){it.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?it.event.trigger(e,t,n,!0):void 0}});var Mt="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",Ot=/ jQuery\d+="(?:null|\d+)"/g,Rt=new RegExp("<(?:"+Mt+")[\\s/>]","i"),Bt=/^\s+/,Pt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,It=/<([\w:]+)/,Wt=/<tbody/i,$t=/<|&#?\w+;/,zt=/<(?:script|style|link)/i,Xt=/checked\s*(?:[^=]|=\s*.checked.)/i,Ut=/^$|\/(?:java|ecma)script/i,Vt=/^true\/(.*)/,Gt=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Yt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:nt.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},Jt=m(ht),Kt=Jt.appendChild(ht.createElement("div"));Yt.optgroup=Yt.option,Yt.tbody=Yt.tfoot=Yt.colgroup=Yt.caption=Yt.thead,Yt.th=Yt.td,it.extend({clone:function(e,t,n){var r,i,o,a,s,l=it.contains(e.ownerDocument,e);if(nt.html5Clone||it.isXMLDoc(e)||!Rt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Kt.innerHTML=e.outerHTML,Kt.removeChild(o=Kt.firstChild)),!(nt.noCloneEvent&&nt.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||it.isXMLDoc(e)))for(r=g(o),s=g(e),a=0;null!=(i=s[a]);++a)r[a]&&E(i,r[a]);if(t)if(n)for(s=s||g(e),r=r||g(o),a=0;null!=(i=s[a]);a++)T(i,r[a]);else T(e,o);return r=g(o,"script"),r.length>0&&w(r,!l&&g(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){for(var i,o,a,s,l,u,c,d=e.length,f=m(t),p=[],h=0;d>h;h++)if(o=e[h],o||0===o)if("object"===it.type(o))it.merge(p,o.nodeType?[o]:o);else if($t.test(o)){for(s=s||f.appendChild(t.createElement("div")),l=(It.exec(o)||["",""])[1].toLowerCase(),c=Yt[l]||Yt._default,s.innerHTML=c[1]+o.replace(Pt,"<$1></$2>")+c[2],i=c[0];i--;)s=s.lastChild;if(!nt.leadingWhitespace&&Bt.test(o)&&p.push(t.createTextNode(Bt.exec(o)[0])),!nt.tbody)for(o="table"!==l||Wt.test(o)?"<table>"!==c[1]||Wt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;i--;)it.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u);for(it.merge(p,s.childNodes),s.textContent="";s.firstChild;)s.removeChild(s.firstChild);s=f.lastChild}else p.push(t.createTextNode(o));for(s&&f.removeChild(s),nt.appendChecked||it.grep(g(p,"input"),v),h=0;o=p[h++];)if((!r||-1===it.inArray(o,r))&&(a=it.contains(o.ownerDocument,o),s=g(f.appendChild(o),"script"),a&&w(s),n))for(i=0;o=s[i++];)Ut.test(o.type||"")&&n.push(o);return s=null,f},cleanData:function(e,t){for(var n,r,i,o,a=0,s=it.expando,l=it.cache,u=nt.deleteExpando,c=it.event.special;null!=(n=e[a]);a++)if((t||it.acceptData(n))&&(i=n[s],o=i&&l[i])){if(o.events)for(r in o.events)c[r]?it.event.remove(n,r):it.removeEvent(n,r,o.handle);l[i]&&(delete l[i],u?delete n[s]:typeof n.removeAttribute!==Et?n.removeAttribute(s):n[s]=null,G.push(i))}}}),it.fn.extend({text:function(e){return At(this,function(e){return void 0===e?it.text(this):this.empty().append((this[0]&&this[0].ownerDocument||ht).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=y(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=y(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){for(var n,r=e?it.filter(e,this):this,i=0;null!=(n=r[i]);i++)t||1!==n.nodeType||it.cleanData(g(n)),n.parentNode&&(t&&it.contains(n.ownerDocument,n)&&w(g(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&it.cleanData(g(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&it.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return it.clone(this,e,t)})},html:function(e){return At(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ot,""):void 0;if(!("string"!=typeof e||zt.test(e)||!nt.htmlSerialize&&Rt.test(e)||!nt.leadingWhitespace&&Bt.test(e)||Yt[(It.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(Pt,"<$1></$2>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(it.cleanData(g(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=arguments[0];return this.domManip(arguments,function(t){e=this.parentNode,it.cleanData(g(this)),e&&e.replaceChild(t,this)}),e&&(e.length||e.nodeType)?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t){e=J.apply([],e);var n,r,i,o,a,s,l=0,u=this.length,c=this,d=u-1,f=e[0],p=it.isFunction(f);if(p||u>1&&"string"==typeof f&&!nt.checkClone&&Xt.test(f))return this.each(function(n){var r=c.eq(n);p&&(e[0]=f.call(this,n,r.html())),r.domManip(e,t)});if(u&&(s=it.buildFragment(e,this[0].ownerDocument,!1,this),n=s.firstChild,1===s.childNodes.length&&(s=n),n)){for(o=it.map(g(s,"script"),b),i=o.length;u>l;l++)r=s,l!==d&&(r=it.clone(r,!0,!0),i&&it.merge(o,g(r,"script"))),t.call(this[l],r,l);if(i)for(a=o[o.length-1].ownerDocument,it.map(o,x),l=0;i>l;l++)r=o[l],Ut.test(r.type||"")&&!it._data(r,"globalEval")&&it.contains(a,r)&&(r.src?it._evalUrl&&it._evalUrl(r.src):it.globalEval((r.text||r.textContent||r.innerHTML||"").replace(Gt,"")));s=n=null}return this}}),it.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){it.fn[e]=function(e){for(var n,r=0,i=[],o=it(e),a=o.length-1;a>=r;r++)n=r===a?this:this.clone(!0),it(o[r])[t](n),K.apply(i,n.get());return this.pushStack(i)}});var Qt,Zt={};!function(){var e;nt.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=ht.getElementsByTagName("body")[0],n&&n.style?(t=ht.createElement("div"),r=ht.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),typeof t.style.zoom!==Et&&(t.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",t.appendChild(ht.createElement("div")).style.width="5px",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var en,tn,nn=/^margin/,rn=new RegExp("^("+Nt+")(?!px)[a-z%]+$","i"),on=/^(top|right|bottom|left)$/;e.getComputedStyle?(en=function(e){return e.ownerDocument.defaultView.getComputedStyle(e,null)},tn=function(e,t,n){var r,i,o,a,s=e.style;return n=n||en(e),a=n?n.getPropertyValue(t)||n[t]:void 0,n&&(""!==a||it.contains(e.ownerDocument,e)||(a=it.style(e,t)),rn.test(a)&&nn.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0===a?a:a+""}):ht.documentElement.currentStyle&&(en=function(e){return e.currentStyle},tn=function(e,t,n){var r,i,o,a,s=e.style;return n=n||en(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),rn.test(a)&&!on.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left="fontSize"===t?"1em":a,a=s.pixelLeft+"px",s.left=r,o&&(i.left=o)),void 0===a?a:a+""||"auto"}),function(){function t(){var t,n,r,i;n=ht.getElementsByTagName("body")[0],n&&n.style&&(t=ht.createElement("div"),r=ht.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),t.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",o=a=!1,l=!0,e.getComputedStyle&&(o="1%"!==(e.getComputedStyle(t,null)||{}).top,a="4px"===(e.getComputedStyle(t,null)||{width:"4px"}).width,i=t.appendChild(ht.createElement("div")),i.style.cssText=t.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",t.style.width="1px",l=!parseFloat((e.getComputedStyle(i,null)||{}).marginRight)),t.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=t.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",s=0===i[0].offsetHeight,s&&(i[0].style.display="",i[1].style.display="none",s=0===i[0].offsetHeight),n.removeChild(r))}var n,r,i,o,a,s,l;n=ht.createElement("div"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",i=n.getElementsByTagName("a")[0],r=i&&i.style,r&&(r.cssText="float:left;opacity:.5",nt.opacity="0.5"===r.opacity,nt.cssFloat=!!r.cssFloat,n.style.backgroundClip="content-box",n.cloneNode(!0).style.backgroundClip="",nt.clearCloneStyle="content-box"===n.style.backgroundClip,nt.boxSizing=""===r.boxSizing||""===r.MozBoxSizing||""===r.WebkitBoxSizing,it.extend(nt,{reliableHiddenOffsets:function(){return null==s&&t(),s
+},boxSizingReliable:function(){return null==a&&t(),a},pixelPosition:function(){return null==o&&t(),o},reliableMarginRight:function(){return null==l&&t(),l}}))}(),it.swap=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};var an=/alpha\([^)]*\)/i,sn=/opacity\s*=\s*([^)]*)/,ln=/^(none|table(?!-c[ea]).+)/,un=new RegExp("^("+Nt+")(.*)$","i"),cn=new RegExp("^([+-])=("+Nt+")","i"),dn={position:"absolute",visibility:"hidden",display:"block"},fn={letterSpacing:"0",fontWeight:"400"},pn=["Webkit","O","Moz","ms"];it.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=tn(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":nt.cssFloat?"cssFloat":"styleFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=it.camelCase(t),l=e.style;if(t=it.cssProps[s]||(it.cssProps[s]=S(l,s)),a=it.cssHooks[t]||it.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];if(o=typeof n,"string"===o&&(i=cn.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(it.css(e,t)),o="number"),null!=n&&n===n&&("number"!==o||it.cssNumber[s]||(n+="px"),nt.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),!(a&&"set"in a&&void 0===(n=a.set(e,n,r)))))try{l[t]=n}catch(u){}}},css:function(e,t,n,r){var i,o,a,s=it.camelCase(t);return t=it.cssProps[s]||(it.cssProps[s]=S(e.style,s)),a=it.cssHooks[t]||it.cssHooks[s],a&&"get"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=tn(e,t,r)),"normal"===o&&t in fn&&(o=fn[t]),""===n||n?(i=parseFloat(o),n===!0||it.isNumeric(i)?i||0:o):o}}),it.each(["height","width"],function(e,t){it.cssHooks[t]={get:function(e,n,r){return n?ln.test(it.css(e,"display"))&&0===e.offsetWidth?it.swap(e,dn,function(){return L(e,t,r)}):L(e,t,r):void 0},set:function(e,n,r){var i=r&&en(e);return A(e,n,r?D(e,t,r,nt.boxSizing&&"border-box"===it.css(e,"boxSizing",!1,i),i):0)}}}),nt.opacity||(it.cssHooks.opacity={get:function(e,t){return sn.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=it.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===it.trim(o.replace(an,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=an.test(o)?o.replace(an,i):o+" "+i)}}),it.cssHooks.marginRight=N(nt.reliableMarginRight,function(e,t){return t?it.swap(e,{display:"inline-block"},tn,[e,"marginRight"]):void 0}),it.each({margin:"",padding:"",border:"Width"},function(e,t){it.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];4>r;r++)i[e+St[r]+t]=o[r]||o[r-2]||o[0];return i}},nn.test(e)||(it.cssHooks[e+t].set=A)}),it.fn.extend({css:function(e,t){return At(this,function(e,t,n){var r,i,o={},a=0;if(it.isArray(t)){for(r=en(e),i=t.length;i>a;a++)o[t[a]]=it.css(e,t[a],!1,r);return o}return void 0!==n?it.style(e,t,n):it.css(e,t)},e,t,arguments.length>1)},show:function(){return j(this,!0)},hide:function(){return j(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){jt(this)?it(this).show():it(this).hide()})}}),it.Tween=H,H.prototype={constructor:H,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(it.cssNumber[n]?"":"px")},cur:function(){var e=H.propHooks[this.prop];return e&&e.get?e.get(this):H.propHooks._default.get(this)},run:function(e){var t,n=H.propHooks[this.prop];return this.pos=t=this.options.duration?it.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):H.propHooks._default.set(this),this}},H.prototype.init.prototype=H.prototype,H.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=it.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){it.fx.step[e.prop]?it.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[it.cssProps[e.prop]]||it.cssHooks[e.prop])?it.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},H.propHooks.scrollTop=H.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},it.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},it.fx=H.prototype.init,it.fx.step={};var hn,mn,gn=/^(?:toggle|show|hide)$/,vn=new RegExp("^(?:([+-])=|)("+Nt+")([a-z%]*)$","i"),yn=/queueHooks$/,bn=[M],xn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=vn.exec(t),o=i&&i[3]||(it.cssNumber[e]?"":"px"),a=(it.cssNumber[e]||"px"!==o&&+r)&&vn.exec(it.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||".5",a/=s,it.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};it.Animation=it.extend(R,{tweener:function(e,t){it.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");for(var n,r=0,i=e.length;i>r;r++)n=e[r],xn[n]=xn[n]||[],xn[n].unshift(t)},prefilter:function(e,t){t?bn.unshift(e):bn.push(e)}}),it.speed=function(e,t,n){var r=e&&"object"==typeof e?it.extend({},e):{complete:n||!n&&t||it.isFunction(e)&&e,duration:e,easing:n&&t||t&&!it.isFunction(t)&&t};return r.duration=it.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in it.fx.speeds?it.fx.speeds[r.duration]:it.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){it.isFunction(r.old)&&r.old.call(this),r.queue&&it.dequeue(this,r.queue)},r},it.fn.extend({fadeTo:function(e,t,n,r){return this.filter(jt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=it.isEmptyObject(e),o=it.speed(t,n,r),a=function(){var t=R(this,it.extend({},e),o);(i||it._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=it.timers,a=it._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&yn.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));(t||!n)&&it.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=it._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=it.timers,a=r?r.length:0;for(n.finish=!0,it.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),it.each(["toggle","show","hide"],function(e,t){var n=it.fn[t];it.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(q(t,!0),e,r,i)}}),it.each({slideDown:q("show"),slideUp:q("hide"),slideToggle:q("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){it.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),it.timers=[],it.fx.tick=function(){var e,t=it.timers,n=0;for(hn=it.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||it.fx.stop(),hn=void 0},it.fx.timer=function(e){it.timers.push(e),e()?it.fx.start():it.timers.pop()},it.fx.interval=13,it.fx.start=function(){mn||(mn=setInterval(it.fx.tick,it.fx.interval))},it.fx.stop=function(){clearInterval(mn),mn=null},it.fx.speeds={slow:600,fast:200,_default:400},it.fn.delay=function(e,t){return e=it.fx?it.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},function(){var e,t,n,r,i;t=ht.createElement("div"),t.setAttribute("className","t"),t.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",r=t.getElementsByTagName("a")[0],n=ht.createElement("select"),i=n.appendChild(ht.createElement("option")),e=t.getElementsByTagName("input")[0],r.style.cssText="top:1px",nt.getSetAttribute="t"!==t.className,nt.style=/top/.test(r.getAttribute("style")),nt.hrefNormalized="/a"===r.getAttribute("href"),nt.checkOn=!!e.value,nt.optSelected=i.selected,nt.enctype=!!ht.createElement("form").enctype,n.disabled=!0,nt.optDisabled=!i.disabled,e=ht.createElement("input"),e.setAttribute("value",""),nt.input=""===e.getAttribute("value"),e.value="t",e.setAttribute("type","radio"),nt.radioValue="t"===e.value}();var wn=/\r/g;it.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=it.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,it(this).val()):e,null==i?i="":"number"==typeof i?i+="":it.isArray(i)&&(i=it.map(i,function(e){return null==e?"":e+""})),t=it.valHooks[this.type]||it.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return t=it.valHooks[i.type]||it.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(wn,""):null==n?"":n)}}}),it.extend({valHooks:{option:{get:function(e){var t=it.find.attr(e,"value");return null!=t?t:it.trim(it.text(e))}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(nt.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&it.nodeName(n.parentNode,"optgroup"))){if(t=it(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=it.makeArray(t),a=i.length;a--;)if(r=i[a],it.inArray(it.valHooks.option.get(r),o)>=0)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),it.each(["radio","checkbox"],function(){it.valHooks[this]={set:function(e,t){return it.isArray(t)?e.checked=it.inArray(it(e).val(),t)>=0:void 0}},nt.checkOn||(it.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Tn,En,kn=it.expr.attrHandle,Cn=/^(?:checked|selected)$/i,Nn=nt.getSetAttribute,Sn=nt.input;it.fn.extend({attr:function(e,t){return At(this,it.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){it.removeAttr(this,e)})}}),it.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(e&&3!==o&&8!==o&&2!==o)return typeof e.getAttribute===Et?it.prop(e,t,n):(1===o&&it.isXMLDoc(e)||(t=t.toLowerCase(),r=it.attrHooks[t]||(it.expr.match.bool.test(t)?En:Tn)),void 0===n?r&&"get"in r&&null!==(i=r.get(e,t))?i:(i=it.find.attr(e,t),null==i?void 0:i):null!==n?r&&"set"in r&&void 0!==(i=r.set(e,n,t))?i:(e.setAttribute(t,n+""),n):void it.removeAttr(e,t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(bt);if(o&&1===e.nodeType)for(;n=o[i++];)r=it.propFix[n]||n,it.expr.match.bool.test(n)?Sn&&Nn||!Cn.test(n)?e[r]=!1:e[it.camelCase("default-"+n)]=e[r]=!1:it.attr(e,n,""),e.removeAttribute(Nn?n:r)},attrHooks:{type:{set:function(e,t){if(!nt.radioValue&&"radio"===t&&it.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}}}),En={set:function(e,t,n){return t===!1?it.removeAttr(e,n):Sn&&Nn||!Cn.test(n)?e.setAttribute(!Nn&&it.propFix[n]||n,n):e[it.camelCase("default-"+n)]=e[n]=!0,n}},it.each(it.expr.match.bool.source.match(/\w+/g),function(e,t){var n=kn[t]||it.find.attr;kn[t]=Sn&&Nn||!Cn.test(t)?function(e,t,r){var i,o;return r||(o=kn[t],kn[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,kn[t]=o),i}:function(e,t,n){return n?void 0:e[it.camelCase("default-"+t)]?t.toLowerCase():null}}),Sn&&Nn||(it.attrHooks.value={set:function(e,t,n){return it.nodeName(e,"input")?void(e.defaultValue=t):Tn&&Tn.set(e,t,n)}}),Nn||(Tn={set:function(e,t,n){var r=e.getAttributeNode(n);return r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+="","value"===n||t===e.getAttribute(n)?t:void 0}},kn.id=kn.name=kn.coords=function(e,t,n){var r;return n?void 0:(r=e.getAttributeNode(t))&&""!==r.value?r.value:null},it.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);return n&&n.specified?n.value:void 0},set:Tn.set},it.attrHooks.contenteditable={set:function(e,t,n){Tn.set(e,""===t?!1:t,n)}},it.each(["width","height"],function(e,t){it.attrHooks[t]={set:function(e,n){return""===n?(e.setAttribute(t,"auto"),n):void 0}}})),nt.style||(it.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+""}});var jn=/^(?:input|select|textarea|button|object)$/i,An=/^(?:a|area)$/i;it.fn.extend({prop:function(e,t){return At(this,it.prop,e,t,arguments.length>1)},removeProp:function(e){return e=it.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),it.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,a=e.nodeType;if(e&&3!==a&&8!==a&&2!==a)return o=1!==a||!it.isXMLDoc(e),o&&(t=it.propFix[t]||t,i=it.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=it.find.attr(e,"tabindex");return t?parseInt(t,10):jn.test(e.nodeName)||An.test(e.nodeName)&&e.href?0:-1}}}}),nt.hrefNormalized||it.each(["href","src"],function(e,t){it.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),nt.optSelected||(it.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),it.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){it.propFix[this.toLowerCase()]=this}),nt.enctype||(it.propFix.enctype="encoding");var Dn=/[\t\r\n\f]/g;it.fn.extend({addClass:function(e){var t,n,r,i,o,a,s=0,l=this.length,u="string"==typeof e&&e;if(it.isFunction(e))return this.each(function(t){it(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(bt)||[];l>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(Dn," "):" ")){for(o=0;i=t[o++];)r.indexOf(" "+i+" ")<0&&(r+=i+" ");a=it.trim(r),n.className!==a&&(n.className=a)}return this},removeClass:function(e){var t,n,r,i,o,a,s=0,l=this.length,u=0===arguments.length||"string"==typeof e&&e;if(it.isFunction(e))return this.each(function(t){it(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(bt)||[];l>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(Dn," "):"")){for(o=0;i=t[o++];)for(;r.indexOf(" "+i+" ")>=0;)r=r.replace(" "+i+" "," ");a=e?it.trim(r):"",n.className!==a&&(n.className=a)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):this.each(it.isFunction(e)?function(n){it(this).toggleClass(e.call(this,n,this.className,t),t)}:function(){if("string"===n)for(var t,r=0,i=it(this),o=e.match(bt)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else(n===Et||"boolean"===n)&&(this.className&&it._data(this,"__className__",this.className),this.className=this.className||e===!1?"":it._data(this,"__className__")||"")})},hasClass:function(e){for(var t=" "+e+" ",n=0,r=this.length;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(Dn," ").indexOf(t)>=0)return!0;return!1}}),it.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){it.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),it.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var Ln=it.now(),Hn=/\?/,_n=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;it.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+"");var n,r=null,i=it.trim(t+"");return i&&!it.trim(i.replace(_n,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,"")}))?Function("return "+i)():it.error("Invalid JSON: "+t)},it.parseXML=function(t){var n,r;if(!t||"string"!=typeof t)return null;try{e.DOMParser?(r=new DOMParser,n=r.parseFromString(t,"text/xml")):(n=new ActiveXObject("Microsoft.XMLDOM"),n.async="false",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName("parsererror").length||it.error("Invalid XML: "+t),n};var qn,Fn,Mn=/#.*$/,On=/([?&])_=[^&]*/,Rn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Bn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Pn=/^(?:GET|HEAD)$/,In=/^\/\//,Wn=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,$n={},zn={},Xn="*/".concat("*");try{Fn=location.href}catch(Un){Fn=ht.createElement("a"),Fn.href="",Fn=Fn.href}qn=Wn.exec(Fn.toLowerCase())||[],it.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Fn,type:"GET",isLocal:Bn.test(qn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Xn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":it.parseJSON,"text xml":it.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?I(I(e,it.ajaxSettings),t):I(it.ajaxSettings,e)},ajaxPrefilter:B($n),ajaxTransport:B(zn),ajax:function(e,t){function n(e,t,n,r){var i,c,v,y,x,T=t;2!==b&&(b=2,s&&clearTimeout(s),u=void 0,a=r||"",w.readyState=e>0?4:0,i=e>=200&&300>e||304===e,n&&(y=W(d,w,n)),y=$(d,y,w,i),i?(d.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(it.lastModified[o]=x),x=w.getResponseHeader("etag"),x&&(it.etag[o]=x)),204===e||"HEAD"===d.type?T="nocontent":304===e?T="notmodified":(T=y.state,c=y.data,v=y.error,i=!v)):(v=T,(e||!T)&&(T="error",0>e&&(e=0))),w.status=e,w.statusText=(t||T)+"",i?h.resolveWith(f,[c,T,w]):h.rejectWith(f,[w,T,v]),w.statusCode(g),g=void 0,l&&p.trigger(i?"ajaxSuccess":"ajaxError",[w,d,i?c:v]),m.fireWith(f,[w,T]),l&&(p.trigger("ajaxComplete",[w,d]),--it.active||it.event.trigger("ajaxStop")))}"object"==typeof e&&(t=e,e=void 0),t=t||{};var r,i,o,a,s,l,u,c,d=it.ajaxSetup({},t),f=d.context||d,p=d.context&&(f.nodeType||f.jquery)?it(f):it.event,h=it.Deferred(),m=it.Callbacks("once memory"),g=d.statusCode||{},v={},y={},b=0,x="canceled",w={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c)for(c={};t=Rn.exec(a);)c[t[1].toLowerCase()]=t[2];t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=y[n]=y[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)g[t]=[g[t],e[t]];else w.always(e[w.status]);return this},abort:function(e){var t=e||x;return u&&u.abort(t),n(0,t),this}};if(h.promise(w).complete=m.add,w.success=w.done,w.error=w.fail,d.url=((e||d.url||Fn)+"").replace(Mn,"").replace(In,qn[1]+"//"),d.type=t.method||t.type||d.method||d.type,d.dataTypes=it.trim(d.dataType||"*").toLowerCase().match(bt)||[""],null==d.crossDomain&&(r=Wn.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]===qn[1]&&r[2]===qn[2]&&(r[3]||("http:"===r[1]?"80":"443"))===(qn[3]||("http:"===qn[1]?"80":"443")))),d.data&&d.processData&&"string"!=typeof d.data&&(d.data=it.param(d.data,d.traditional)),P($n,d,t,w),2===b)return w;l=d.global,l&&0===it.active++&&it.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!Pn.test(d.type),o=d.url,d.hasContent||(d.data&&(o=d.url+=(Hn.test(o)?"&":"?")+d.data,delete d.data),d.cache===!1&&(d.url=On.test(o)?o.replace(On,"$1_="+Ln++):o+(Hn.test(o)?"&":"?")+"_="+Ln++)),d.ifModified&&(it.lastModified[o]&&w.setRequestHeader("If-Modified-Since",it.lastModified[o]),it.etag[o]&&w.setRequestHeader("If-None-Match",it.etag[o])),(d.data&&d.hasContent&&d.contentType!==!1||t.contentType)&&w.setRequestHeader("Content-Type",d.contentType),w.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Xn+"; q=0.01":""):d.accepts["*"]);for(i in d.headers)w.setRequestHeader(i,d.headers[i]);if(d.beforeSend&&(d.beforeSend.call(f,w,d)===!1||2===b))return w.abort();x="abort";for(i in{success:1,error:1,complete:1})w[i](d[i]);if(u=P(zn,d,t,w)){w.readyState=1,l&&p.trigger("ajaxSend",[w,d]),d.async&&d.timeout>0&&(s=setTimeout(function(){w.abort("timeout")},d.timeout));try{b=1,u.send(v,n)}catch(T){if(!(2>b))throw T;n(-1,T)}}else n(-1,"No Transport");return w},getJSON:function(e,t,n){return it.get(e,t,n,"json")},getScript:function(e,t){return it.get(e,void 0,t,"script")}}),it.each(["get","post"],function(e,t){it[t]=function(e,n,r,i){return it.isFunction(n)&&(i=i||r,r=n,n=void 0),it.ajax({url:e,type:t,dataType:i,data:n,success:r})}}),it.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){it.fn[t]=function(e){return this.on(t,e)}}),it._evalUrl=function(e){return it.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},it.fn.extend({wrapAll:function(e){if(it.isFunction(e))return this.each(function(t){it(this).wrapAll(e.call(this,t))});if(this[0]){var t=it(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return this.each(it.isFunction(e)?function(t){it(this).wrapInner(e.call(this,t))}:function(){var t=it(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=it.isFunction(e);return this.each(function(n){it(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){it.nodeName(this,"body")||it(this).replaceWith(this.childNodes)}).end()}}),it.expr.filters.hidden=function(e){return e.offsetWidth<=0&&e.offsetHeight<=0||!nt.reliableHiddenOffsets()&&"none"===(e.style&&e.style.display||it.css(e,"display"))},it.expr.filters.visible=function(e){return!it.expr.filters.hidden(e)};var Vn=/%20/g,Gn=/\[\]$/,Yn=/\r?\n/g,Jn=/^(?:submit|button|image|reset|file)$/i,Kn=/^(?:input|select|textarea|keygen)/i;it.param=function(e,t){var n,r=[],i=function(e,t){t=it.isFunction(t)?t():null==t?"":t,r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(void 0===t&&(t=it.ajaxSettings&&it.ajaxSettings.traditional),it.isArray(e)||e.jquery&&!it.isPlainObject(e))it.each(e,function(){i(this.name,this.value)});else for(n in e)z(n,e[n],t,i);return r.join("&").replace(Vn,"+")},it.fn.extend({serialize:function(){return it.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=it.prop(this,"elements");return e?it.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!it(this).is(":disabled")&&Kn.test(this.nodeName)&&!Jn.test(e)&&(this.checked||!Dt.test(e))}).map(function(e,t){var n=it(this).val();return null==n?null:it.isArray(n)?it.map(n,function(e){return{name:t.name,value:e.replace(Yn,"\r\n")}}):{name:t.name,value:n.replace(Yn,"\r\n")}}).get()}}),it.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&X()||U()}:X;var Qn=0,Zn={},er=it.ajaxSettings.xhr();e.ActiveXObject&&it(e).on("unload",function(){for(var e in Zn)Zn[e](void 0,!0)}),nt.cors=!!er&&"withCredentials"in er,er=nt.ajax=!!er,er&&it.ajaxTransport(function(e){if(!e.crossDomain||nt.cors){var t;return{send:function(n,r){var i,o=e.xhr(),a=++Qn;if(o.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(i in e.xhrFields)o[i]=e.xhrFields[i];e.mimeType&&o.overrideMimeType&&o.overrideMimeType(e.mimeType),e.crossDomain||n["X-Requested-With"]||(n["X-Requested-With"]="XMLHttpRequest");for(i in n)void 0!==n[i]&&o.setRequestHeader(i,n[i]+"");o.send(e.hasContent&&e.data||null),t=function(n,i){var s,l,u;if(t&&(i||4===o.readyState))if(delete Zn[a],t=void 0,o.onreadystatechange=it.noop,i)4!==o.readyState&&o.abort();else{u={},s=o.status,"string"==typeof o.responseText&&(u.text=o.responseText);try{l=o.statusText}catch(c){l=""}s||!e.isLocal||e.crossDomain?1223===s&&(s=204):s=u.text?200:404}u&&r(s,l,u,o.getAllResponseHeaders())},e.async?4===o.readyState?setTimeout(t):o.onreadystatechange=Zn[a]=t:t()},abort:function(){t&&t(void 0,!0)}}}}),it.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return it.globalEval(e),e}}}),it.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),it.ajaxTransport("script",function(e){if(e.crossDomain){var t,n=ht.head||it("head")[0]||ht.documentElement;return{send:function(r,i){t=ht.createElement("script"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,"success"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var tr=[],nr=/(=)\?(?=&|$)|\?\?/;it.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=tr.pop()||it.expando+"_"+Ln++;return this[e]=!0,e}}),it.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(nr.test(t.url)?"url":"string"==typeof t.data&&!(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&nr.test(t.data)&&"data");return s||"jsonp"===t.dataTypes[0]?(i=t.jsonpCallback=it.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(nr,"$1"+i):t.jsonp!==!1&&(t.url+=(Hn.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||it.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,tr.push(i)),a&&it.isFunction(o)&&o(a[0]),a=o=void 0}),"script"):void 0}),it.parseHTML=function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||ht;var r=dt.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=it.buildFragment([e],t,i),i&&i.length&&it(i).remove(),it.merge([],r.childNodes))};var rr=it.fn.load;it.fn.load=function(e,t,n){if("string"!=typeof e&&rr)return rr.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(" ");return s>=0&&(r=it.trim(e.slice(s,e.length)),e=e.slice(0,s)),it.isFunction(t)?(n=t,t=void 0):t&&"object"==typeof t&&(o="POST"),a.length>0&&it.ajax({url:e,type:o,dataType:"html",data:t}).done(function(e){i=arguments,a.html(r?it("<div>").append(it.parseHTML(e)).find(r):e)}).complete(n&&function(e,t){a.each(n,i||[e.responseText,t,e])}),this},it.expr.filters.animated=function(e){return it.grep(it.timers,function(t){return e===t.elem}).length};var ir=e.document.documentElement;it.offset={setOffset:function(e,t,n){var r,i,o,a,s,l,u,c=it.css(e,"position"),d=it(e),f={};"static"===c&&(e.style.position="relative"),s=d.offset(),o=it.css(e,"top"),l=it.css(e,"left"),u=("absolute"===c||"fixed"===c)&&it.inArray("auto",[o,l])>-1,u?(r=d.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(l)||0),it.isFunction(t)&&(t=t.call(e,n,s)),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):d.css(f)}},it.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){it.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,it.contains(t,i)?(typeof i.getBoundingClientRect!==Et&&(r=i.getBoundingClientRect()),n=V(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===it.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),it.nodeName(e[0],"html")||(n=e.offset()),n.top+=it.css(e[0],"borderTopWidth",!0),n.left+=it.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-it.css(r,"marginTop",!0),left:t.left-n.left-it.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent||ir;e&&!it.nodeName(e,"html")&&"static"===it.css(e,"position");)e=e.offsetParent;return e||ir})}}),it.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n=/Y/.test(t);it.fn[e]=function(r){return At(this,function(e,r,i){var o=V(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?it(o).scrollLeft():i,n?i:it(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),it.each(["top","left"],function(e,t){it.cssHooks[t]=N(nt.pixelPosition,function(e,n){return n?(n=tn(e,t),rn.test(n)?it(e).position()[t]+"px":n):void 0})}),it.each({Height:"height",Width:"width"},function(e,t){it.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){it.fn[r]=function(r,i){var o=arguments.length&&(n||"boolean"!=typeof r),a=n||(r===!0||i===!0?"margin":"border");return At(this,function(t,n,r){var i;return it.isWindow(t)?t.document.documentElement["client"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body["scroll"+e],i["scroll"+e],t.body["offset"+e],i["offset"+e],i["client"+e])):void 0===r?it.css(t,n,a):it.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),it.fn.size=function(){return this.length},it.fn.andSelf=it.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return it});var or=e.jQuery,ar=e.$;return it.noConflict=function(t){return e.$===it&&(e.$=ar),t&&e.jQuery===it&&(e.jQuery=or),it},typeof t===Et&&(e.jQuery=e.$=it),it}),function(e,t){e.rails!==t&&e.error("jquery-ujs has already been loaded!");var n,r=e(document);e.rails=n={linkClickSelector:"a[data-confirm], a[data-method], a[data-remote], a[data-disable-with], a[data-disable]",buttonClickSelector:"button[data-remote], button[data-confirm]",inputChangeSelector:"select[data-remote], input[data-remote], textarea[data-remote]",formSubmitSelector:"form",formInputClickSelector:"form input[type=submit], form input[type=image], form button[type=submit], form button:not([type])",disableSelector:"input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled",enableSelector:"input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled",requiredInputSelector:"input[name][required]:not([disabled]),textarea[name][required]:not([disabled])",fileInputSelector:"input[type=file]",linkDisableSelector:"a[data-disable-with], a[data-disable]",buttonDisableSelector:"button[data-remote][data-disable-with], button[data-remote][data-disable]",CSRFProtection:function(t){var n=e('meta[name="csrf-token"]').attr("content");n&&t.setRequestHeader("X-CSRF-Token",n)},refreshCSRFTokens:function(){var t=e("meta[name=csrf-token]").attr("content"),n=e("meta[name=csrf-param]").attr("content");e('form input[name="'+n+'"]').val(t)},fire:function(t,n,r){var i=e.Event(n);return t.trigger(i,r),i.result!==!1},confirm:function(e){return confirm(e)},ajax:function(t){return e.ajax(t)},href:function(e){return e.attr("href")},handleRemote:function(r){var i,o,a,s,l,u,c,d;if(n.fire(r,"ajax:before")){if(s=r.data("cross-domain"),l=s===t?null:s,u=r.data("with-credentials")||null,c=r.data("type")||e.ajaxSettings&&e.ajaxSettings.dataType,r.is("form")){i=r.attr("method"),o=r.attr("action"),a=r.serializeArray();var f=r.data("ujs:submit-button");f&&(a.push(f),r.data("ujs:submit-button",null))}else r.is(n.inputChangeSelector)?(i=r.data("method"),o=r.data("url"),a=r.serialize(),r.data("params")&&(a=a+"&"+r.data("params"))):r.is(n.buttonClickSelector)?(i=r.data("method")||"get",o=r.data("url"),a=r.serialize(),r.data("params")&&(a=a+"&"+r.data("params"))):(i=r.data("method"),o=n.href(r),a=r.data("params")||null);return d={type:i||"GET",data:a,dataType:c,beforeSend:function(e,i){return i.dataType===t&&e.setRequestHeader("accept","*/*;q=0.5, "+i.accepts.script),n.fire(r,"ajax:beforeSend",[e,i])?void r.trigger("ajax:send",e):!1
+},success:function(e,t,n){r.trigger("ajax:success",[e,t,n])},complete:function(e,t){r.trigger("ajax:complete",[e,t])},error:function(e,t,n){r.trigger("ajax:error",[e,t,n])},crossDomain:l},u&&(d.xhrFields={withCredentials:u}),o&&(d.url=o),n.ajax(d)}return!1},handleMethod:function(r){var i=n.href(r),o=r.data("method"),a=r.attr("target"),s=e("meta[name=csrf-token]").attr("content"),l=e("meta[name=csrf-param]").attr("content"),u=e('<form method="post" action="'+i+'"></form>'),c='<input name="_method" value="'+o+'" type="hidden" />';l!==t&&s!==t&&(c+='<input name="'+l+'" value="'+s+'" type="hidden" />'),a&&u.attr("target",a),u.hide().append(c).appendTo("body"),u.submit()},formElements:function(t,n){return t.is("form")?e(t[0].elements).filter(n):t.find(n)},disableFormElements:function(t){n.formElements(t,n.disableSelector).each(function(){n.disableFormElement(e(this))})},disableFormElement:function(e){var n,r;n=e.is("button")?"html":"val",r=e.data("disable-with"),e.data("ujs:enable-with",e[n]()),r!==t&&e[n](r),e.prop("disabled",!0)},enableFormElements:function(t){n.formElements(t,n.enableSelector).each(function(){n.enableFormElement(e(this))})},enableFormElement:function(e){var t=e.is("button")?"html":"val";e.data("ujs:enable-with")&&e[t](e.data("ujs:enable-with")),e.prop("disabled",!1)},allowAction:function(e){var t,r=e.data("confirm"),i=!1;return r?(n.fire(e,"confirm")&&(i=n.confirm(r),t=n.fire(e,"confirm:complete",[i])),i&&t):!0},blankInputs:function(t,n,r){var i,o,a=e(),s=n||"input,textarea",l=t.find(s);return l.each(function(){if(i=e(this),o=i.is("input[type=checkbox],input[type=radio]")?i.is(":checked"):i.val(),!o==!r){if(i.is("input[type=radio]")&&l.filter('input[type=radio]:checked[name="'+i.attr("name")+'"]').length)return!0;a=a.add(i)}}),a.length?a:!1},nonBlankInputs:function(e,t){return n.blankInputs(e,t,!0)},stopEverything:function(t){return e(t.target).trigger("ujs:everythingStopped"),t.stopImmediatePropagation(),!1},disableElement:function(e){var r=e.data("disable-with");e.data("ujs:enable-with",e.html()),r!==t&&e.html(r),e.bind("click.railsDisable",function(e){return n.stopEverything(e)})},enableElement:function(e){e.data("ujs:enable-with")!==t&&(e.html(e.data("ujs:enable-with")),e.removeData("ujs:enable-with")),e.unbind("click.railsDisable")}},n.fire(r,"rails:attachBindings")&&(e.ajaxPrefilter(function(e,t,r){e.crossDomain||n.CSRFProtection(r)}),r.delegate(n.linkDisableSelector,"ajax:complete",function(){n.enableElement(e(this))}),r.delegate(n.buttonDisableSelector,"ajax:complete",function(){n.enableFormElement(e(this))}),r.delegate(n.linkClickSelector,"click.rails",function(r){var i=e(this),o=i.data("method"),a=i.data("params"),s=r.metaKey||r.ctrlKey;if(!n.allowAction(i))return n.stopEverything(r);if(!s&&i.is(n.linkDisableSelector)&&n.disableElement(i),i.data("remote")!==t){if(s&&(!o||"GET"===o)&&!a)return!0;var l=n.handleRemote(i);return l===!1?n.enableElement(i):l.error(function(){n.enableElement(i)}),!1}return i.data("method")?(n.handleMethod(i),!1):void 0}),r.delegate(n.buttonClickSelector,"click.rails",function(t){var r=e(this);if(!n.allowAction(r))return n.stopEverything(t);r.is(n.buttonDisableSelector)&&n.disableFormElement(r);var i=n.handleRemote(r);return i===!1?n.enableFormElement(r):i.error(function(){n.enableFormElement(r)}),!1}),r.delegate(n.inputChangeSelector,"change.rails",function(t){var r=e(this);return n.allowAction(r)?(n.handleRemote(r),!1):n.stopEverything(t)}),r.delegate(n.formSubmitSelector,"submit.rails",function(r){var i,o,a=e(this),s=a.data("remote")!==t;if(!n.allowAction(a))return n.stopEverything(r);if(a.attr("novalidate")==t&&(i=n.blankInputs(a,n.requiredInputSelector),i&&n.fire(a,"ajax:aborted:required",[i])))return n.stopEverything(r);if(s){if(o=n.nonBlankInputs(a,n.fileInputSelector)){setTimeout(function(){n.disableFormElements(a)},13);var l=n.fire(a,"ajax:aborted:file",[o]);return l||setTimeout(function(){n.enableFormElements(a)},13),l}return n.handleRemote(a),!1}setTimeout(function(){n.disableFormElements(a)},13)}),r.delegate(n.formInputClickSelector,"click.rails",function(t){var r=e(this);if(!n.allowAction(r))return n.stopEverything(t);var i=r.attr("name"),o=i?{name:i,value:r.val()}:null;r.closest("form").data("ujs:submit-button",o)}),r.delegate(n.formSubmitSelector,"ajax:send.rails",function(t){this==t.target&&n.disableFormElements(e(this))}),r.delegate(n.formSubmitSelector,"ajax:complete.rails",function(t){this==t.target&&n.enableFormElements(e(this))}),e(function(){n.refreshCSRFTokens()}))}(jQuery),function(){var e,t,n,r,i,o,a,s,l,u,c,d,f,p,h,m,g,v,y,b,x,w,T,E,k,C,N,S,j,A,D,L,H,_,q,F,M,O,R,B,P,I,W,$,z,X,U,V,G,Y=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1},J={}.hasOwnProperty,K=function(e,t){function n(){this.constructor=e}for(var r in t)J.call(t,r)&&(e[r]=t[r]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},Q=[].slice;j={},d=10,$=!1,m=null,S=null,q=null,h=null,V=null,b=function(e){var t;return e=new n(e),B(),c(),F(e),$&&(t=z(e.absolute))?(x(t),w(e)):w(e,W)},z=function(e){var t;return t=j[e],t&&!t.transitionCacheDisabled?t:void 0},g=function(e){return null==e&&(e=!0),$=e},w=function(e,t){return null==t&&(t=function(){return function(){}}(this)),X("page:fetch",{url:e.absolute}),null!=V&&V.abort(),V=new XMLHttpRequest,V.open("GET",e.withoutHashForIE10compatibility(),!0),V.setRequestHeader("Accept","text/html, application/xhtml+xml, application/xml"),V.setRequestHeader("X-XHR-Referer",q),V.onload=function(){var n;return X("page:receive"),(n=H())?(f.apply(null,y(n)),M(),t(),X("page:load")):document.location.href=e.absolute},V.onloadend=function(){return V=null},V.onerror=function(){return document.location.href=e.absolute},V.send()},x=function(e){return null!=V&&V.abort(),f(e.title,e.body),_(e),X("page:restore")},c=function(){var e;return e=new n(m.url),j[e.absolute]={url:e.relative,body:document.body,title:document.title,positionY:window.pageYOffset,positionX:window.pageXOffset,cachedAt:(new Date).getTime(),transitionCacheDisabled:null!=document.querySelector("[data-no-transition-cache]")},p(d)},D=function(e){return null==e&&(e=d),/^[\d]+$/.test(e)?d=parseInt(e):void 0},p=function(e){var t,n,r,i,o,a;for(r=Object.keys(j),t=r.map(function(e){return j[e].cachedAt}).sort(function(e,t){return t-e}),a=[],i=0,o=r.length;o>i;i++)n=r[i],j[n].cachedAt<=t[e]&&(X("page:expire",j[n]),a.push(delete j[n]));return a},f=function(t,n,r,i){return document.title=t,document.documentElement.replaceChild(n,document.body),null!=r&&e.update(r),i&&v(),m=window.history.state,X("page:change"),X("page:update")},v=function(){var e,t,n,r,i,o,a,s,l,u,c,d;for(o=Array.prototype.slice.call(document.body.querySelectorAll('script:not([data-turbolinks-eval="false"])')),a=0,l=o.length;l>a;a++)if(i=o[a],""===(c=i.type)||"text/javascript"===c){for(t=document.createElement("script"),d=i.attributes,s=0,u=d.length;u>s;s++)e=d[s],t.setAttribute(e.name,e.value);t.appendChild(document.createTextNode(i.innerHTML)),r=i.parentNode,n=i.nextSibling,r.removeChild(i),r.insertBefore(t,n)}},P=function(e){return e.innerHTML=e.innerHTML.replace(/<noscript[\S\s]*?<\/noscript>/gi,""),e},F=function(e){return(e=new n(e)).absolute!==q?window.history.pushState({turbolinks:!0,url:e.absolute},"",e.absolute):void 0},M=function(){var e,t;return(e=V.getResponseHeader("X-XHR-Redirected-To"))?(e=new n(e),t=e.hasNoHash()?document.location.hash:"",window.history.replaceState(m,"",e.href+t)):void 0},B=function(){return q=document.location.href},R=function(){return window.history.replaceState({turbolinks:!0,url:document.location.href},"",document.location.href)},O=function(){return m=window.history.state},_=function(e){return window.scrollTo(e.positionX,e.positionY)},W=function(){return document.location.hash?document.location.href=document.location.href:window.scrollTo(0,0)},L=function(e){var t,n;return t=(null!=(n=document.cookie.match(new RegExp(e+"=(\\w+)")))?n[1].toUpperCase():void 0)||"",document.cookie=e+"=; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/",t},X=function(e,t){var n;return n=document.createEvent("Events"),t&&(n.data=t),n.initEvent(e,!0,!0),document.dispatchEvent(n)},A=function(){return!X("page:before-change")},H=function(){var e,t,n,r,i,o;return t=function(){var e;return 400<=(e=V.status)&&600>e},o=function(){return V.getResponseHeader("Content-Type").match(/^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/)},r=function(e){var t,n,r,i,o;for(i=e.head.childNodes,o=[],n=0,r=i.length;r>n;n++)t=i[n],null!=("function"==typeof t.getAttribute?t.getAttribute("data-turbolinks-track"):void 0)&&o.push(t.getAttribute("src")||t.getAttribute("href"));return o},e=function(e){var t;return S||(S=r(document)),t=r(e),t.length!==S.length||i(t,S).length!==S.length},i=function(e,t){var n,r,i,o,a;for(e.length>t.length&&(o=[t,e],e=o[0],t=o[1]),a=[],r=0,i=e.length;i>r;r++)n=e[r],Y.call(t,n)>=0&&a.push(n);return a},!t()&&o()&&(n=h(V.responseText),n&&!e(n))?n:void 0},y=function(t){var n;return n=t.querySelector("title"),[null!=n?n.textContent:void 0,P(t.body),e.get(t).token,"runScripts"]},e={get:function(e){var t;return null==e&&(e=document),{node:t=e.querySelector('meta[name="csrf-token"]'),token:null!=t&&"function"==typeof t.getAttribute?t.getAttribute("content"):void 0}},update:function(e){var t;return t=this.get(),null!=t.token&&null!=e&&t.token!==e?t.node.setAttribute("content",e):void 0}},i=function(){var e,t,n,r,i,o;t=function(e){return(new DOMParser).parseFromString(e,"text/html")},e=function(e){var t;return t=document.implementation.createHTMLDocument(""),t.documentElement.innerHTML=e,t},n=function(e){var t;return t=document.implementation.createHTMLDocument(""),t.open("replace"),t.write(e),t.close(),t};try{if(window.DOMParser)return i=t("<html><body><p>test"),t}catch(a){return r=a,i=e("<html><body><p>test"),e}finally{if(1!==(null!=i&&null!=(o=i.body)?o.childNodes.length:void 0))return n}},n=function(){function e(t){return this.original=null!=t?t:document.location.href,this.original.constructor===e?this.original:void this._parse()}return e.prototype.withoutHash=function(){return this.href.replace(this.hash,"")},e.prototype.withoutHashForIE10compatibility=function(){return this.withoutHash()},e.prototype.hasNoHash=function(){return 0===this.hash.length},e.prototype._parse=function(){var e;return(null!=this.link?this.link:this.link=document.createElement("a")).href=this.original,e=this.link,this.href=e.href,this.protocol=e.protocol,this.host=e.host,this.hostname=e.hostname,this.port=e.port,this.pathname=e.pathname,this.search=e.search,this.hash=e.hash,this.origin=[this.protocol,"//",this.hostname].join(""),0!==this.port.length&&(this.origin+=":"+this.port),this.relative=[this.pathname,this.search,this.hash].join(""),this.absolute=this.href},e}(),r=function(e){function t(e){return this.link=e,this.link.constructor===t?this.link:(this.original=this.link.href,void t.__super__.constructor.apply(this,arguments))}return K(t,e),t.HTML_EXTENSIONS=["html"],t.allowExtensions=function(){var e,n,r,i;for(n=1<=arguments.length?Q.call(arguments,0):[],r=0,i=n.length;i>r;r++)e=n[r],t.HTML_EXTENSIONS.push(e);return t.HTML_EXTENSIONS},t.prototype.shouldIgnore=function(){return this._crossOrigin()||this._anchored()||this._nonHtml()||this._optOut()||this._target()},t.prototype._crossOrigin=function(){return this.origin!==(new n).origin},t.prototype._anchored=function(){var e;return(this.hash&&this.withoutHash())===(e=new n).withoutHash()||this.href===e.href+"#"},t.prototype._nonHtml=function(){return this.pathname.match(/\.[a-z]+$/g)&&!this.pathname.match(new RegExp("\\.(?:"+t.HTML_EXTENSIONS.join("|")+")?$","g"))},t.prototype._optOut=function(){var e,t;for(t=this.link;!e&&t!==document;)e=null!=t.getAttribute("data-no-turbolink"),t=t.parentNode;return e},t.prototype._target=function(){return 0!==this.link.target.length},t}(n),t=function(){function e(e){this.event=e,this.event.defaultPrevented||(this._extractLink(),this._validForTurbolinks()&&(A()||U(this.link.href),this.event.preventDefault()))}return e.installHandlerLast=function(t){return t.defaultPrevented?void 0:(document.removeEventListener("click",e.handle,!1),document.addEventListener("click",e.handle,!1))},e.handle=function(t){return new e(t)},e.prototype._extractLink=function(){var e;for(e=this.event.target;e.parentNode&&"A"!==e.nodeName;)e=e.parentNode;return"A"===e.nodeName&&0!==e.href.length?this.link=new r(e):void 0},e.prototype._validForTurbolinks=function(){return null!=this.link&&!(this.link.shouldIgnore()||this._nonStandardClick())},e.prototype._nonStandardClick=function(){return this.event.which>1||this.event.metaKey||this.event.ctrlKey||this.event.shiftKey||this.event.altKey},e}(),u=function(e){return setTimeout(e,500)},k=function(){return document.addEventListener("DOMContentLoaded",function(){return X("page:change"),X("page:update")},!0)},N=function(){return"undefined"!=typeof jQuery?jQuery(document).on("ajaxSuccess",function(e,t){return jQuery.trim(t.responseText)?X("page:update"):void 0}):void 0},C=function(e){var t,r;return(null!=(r=e.state)?r.turbolinks:void 0)?(t=j[new n(e.state.url).absolute])?(c(),x(t)):U(e.target.location.href):void 0},E=function(){return R(),O(),h=i(),document.addEventListener("click",t.installHandlerLast,!0),u(function(){return window.addEventListener("popstate",C,!1)})},T=void 0!==window.history.state||navigator.userAgent.match(/Firefox\/2[6|7]/),s=window.history&&window.history.pushState&&window.history.replaceState&&T,o=!navigator.userAgent.match(/CriOS\//),I="GET"===(G=L("request_method"))||""===G,l=s&&o&&I,a=document.addEventListener&&document.createEvent,a&&(k(),N()),l?(U=b,E()):U=function(e){return document.location.href=e},this.Turbolinks={visit:U,pagesCached:D,enableTransitionCache:g,allowLinkExtensions:r.allowExtensions,supported:l}}.call(this),function(){}.call(this); \ No newline at end of file
diff --git a/actionpack/test/fixtures/public/gzip/application-a71b3024f80aea3181c09774ca17e712.js.gz b/actionpack/test/fixtures/public/gzip/application-a71b3024f80aea3181c09774ca17e712.js.gz
new file mode 100644
index 0000000000..f62c656dc8
--- /dev/null
+++ b/actionpack/test/fixtures/public/gzip/application-a71b3024f80aea3181c09774ca17e712.js.gz
Binary files differ
diff --git a/actionpack/test/fixtures/公共/gzip/application-a71b3024f80aea3181c09774ca17e712.js b/actionpack/test/fixtures/公共/gzip/application-a71b3024f80aea3181c09774ca17e712.js
new file mode 100644
index 0000000000..1826a7660e
--- /dev/null
+++ b/actionpack/test/fixtures/公共/gzip/application-a71b3024f80aea3181c09774ca17e712.js
@@ -0,0 +1,4 @@
+!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t=e.length,n=it.type(e);return"function"===n||it.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e}function r(e,t,n){if(it.isFunction(t))return it.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return it.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(ft.test(t))return it.filter(t,e,n);t=it.filter(t,e)}return it.grep(e,function(e){return it.inArray(e,t)>=0!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t=xt[e]={};return it.each(e.match(bt)||[],function(e,n){t[n]=!0}),t}function a(){ht.addEventListener?(ht.removeEventListener("DOMContentLoaded",s,!1),e.removeEventListener("load",s,!1)):(ht.detachEvent("onreadystatechange",s),e.detachEvent("onload",s))}function s(){(ht.addEventListener||"load"===event.type||"complete"===ht.readyState)&&(a(),it.ready())}function l(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(Ct,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:kt.test(n)?it.parseJSON(n):n}catch(i){}it.data(e,t,n)}else n=void 0}return n}function u(e){var t;for(t in e)if(("data"!==t||!it.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function c(e,t,n,r){if(it.acceptData(e)){var i,o,a=it.expando,s=e.nodeType,l=s?it.cache:e,u=s?e[a]:e[a]&&a;if(u&&l[u]&&(r||l[u].data)||void 0!==n||"string"!=typeof t)return u||(u=s?e[a]=G.pop()||it.guid++:a),l[u]||(l[u]=s?{}:{toJSON:it.noop}),("object"==typeof t||"function"==typeof t)&&(r?l[u]=it.extend(l[u],t):l[u].data=it.extend(l[u].data,t)),o=l[u],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[it.camelCase(t)]=n),"string"==typeof t?(i=o[t],null==i&&(i=o[it.camelCase(t)])):i=o,i}}function d(e,t,n){if(it.acceptData(e)){var r,i,o=e.nodeType,a=o?it.cache:e,s=o?e[it.expando]:it.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){it.isArray(t)?t=t.concat(it.map(t,it.camelCase)):t in r?t=[t]:(t=it.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;for(;i--;)delete r[t[i]];if(n?!u(r):!it.isEmptyObject(r))return}(n||(delete a[s].data,u(a[s])))&&(o?it.cleanData([e],!0):nt.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}function f(){return!0}function p(){return!1}function h(){try{return ht.activeElement}catch(e){}}function m(e){var t=Mt.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function g(e,t){var n,r,i=0,o=typeof e.getElementsByTagName!==Et?e.getElementsByTagName(t||"*"):typeof e.querySelectorAll!==Et?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||it.nodeName(r,t)?o.push(r):it.merge(o,g(r,t));return void 0===t||t&&it.nodeName(e,t)?it.merge([e],o):o}function v(e){Dt.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t){return it.nodeName(e,"table")&&it.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function b(e){return e.type=(null!==it.find.attr(e,"type"))+"/"+e.type,e}function x(e){var t=Vt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function w(e,t){for(var n,r=0;null!=(n=e[r]);r++)it._data(n,"globalEval",!t||it._data(t[r],"globalEval"))}function T(e,t){if(1===t.nodeType&&it.hasData(e)){var n,r,i,o=it._data(e),a=it._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)it.event.add(t,n,s[n][r])}a.data&&(a.data=it.extend({},a.data))}}function E(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!nt.noCloneEvent&&t[it.expando]){i=it._data(t);for(r in i.events)it.removeEvent(t,r,i.handle);t.removeAttribute(it.expando)}"script"===n&&t.text!==e.text?(b(t).text=e.text,x(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),nt.html5Clone&&e.innerHTML&&!it.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Dt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function k(t,n){var r,i=it(n.createElement(t)).appendTo(n.body),o=e.getDefaultComputedStyle&&(r=e.getDefaultComputedStyle(i[0]))?r.display:it.css(i[0],"display");return i.detach(),o}function C(e){var t=ht,n=Zt[e];return n||(n=k(e,t),"none"!==n&&n||(Qt=(Qt||it("<iframe frameborder='0' width='0' height='0'/>")).appendTo(t.documentElement),t=(Qt[0].contentWindow||Qt[0].contentDocument).document,t.write(),t.close(),n=k(e,t),Qt.detach()),Zt[e]=n),n}function N(e,t){return{get:function(){var n=e();if(null!=n)return n?void delete this.get:(this.get=t).apply(this,arguments)}}}function S(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=pn.length;i--;)if(t=pn[i]+n,t in e)return t;return r}function j(e,t){for(var n,r,i,o=[],a=0,s=e.length;s>a;a++)r=e[a],r.style&&(o[a]=it._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&jt(r)&&(o[a]=it._data(r,"olddisplay",C(r.nodeName)))):(i=jt(r),(n&&"none"!==n||!i)&&it._data(r,"olddisplay",i?n:it.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}function A(e,t,n){var r=un.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function D(e,t,n,r,i){for(var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;4>o;o+=2)"margin"===n&&(a+=it.css(e,n+St[o],!0,i)),r?("content"===n&&(a-=it.css(e,"padding"+St[o],!0,i)),"margin"!==n&&(a-=it.css(e,"border"+St[o]+"Width",!0,i))):(a+=it.css(e,"padding"+St[o],!0,i),"padding"!==n&&(a+=it.css(e,"border"+St[o]+"Width",!0,i)));return a}function L(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=en(e),a=nt.boxSizing&&"border-box"===it.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=tn(e,t,o),(0>i||null==i)&&(i=e.style[t]),rn.test(i))return i;r=a&&(nt.boxSizingReliable()||i===e.style[t]),i=parseFloat(i)||0}return i+D(e,t,n||(a?"border":"content"),r,o)+"px"}function H(e,t,n,r,i){return new H.prototype.init(e,t,n,r,i)}function _(){return setTimeout(function(){hn=void 0}),hn=it.now()}function q(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=St[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function F(e,t,n){for(var r,i=(xn[t]||[]).concat(xn["*"]),o=0,a=i.length;a>o;o++)if(r=i[o].call(n,t,e))return r}function M(e,t,n){var r,i,o,a,s,l,u,c,d=this,f={},p=e.style,h=e.nodeType&&jt(e),m=it._data(e,"fxshow");n.queue||(s=it._queueHooks(e,"fx"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,d.always(function(){d.always(function(){s.unqueued--,it.queue(e,"fx").length||s.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],u=it.css(e,"display"),c="none"===u?it._data(e,"olddisplay")||C(e.nodeName):u,"inline"===c&&"none"===it.css(e,"float")&&(nt.inlineBlockNeedsLayout&&"inline"!==C(e.nodeName)?p.zoom=1:p.display="inline-block")),n.overflow&&(p.overflow="hidden",nt.shrinkWrapBlocks()||d.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],gn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(h?"hide":"show")){if("show"!==i||!m||void 0===m[r])continue;h=!0}f[r]=m&&m[r]||it.style(e,r)}else u=void 0;if(it.isEmptyObject(f))"inline"===("none"===u?C(e.nodeName):u)&&(p.display=u);else{m?"hidden"in m&&(h=m.hidden):m=it._data(e,"fxshow",{}),o&&(m.hidden=!h),h?it(e).show():d.done(function(){it(e).hide()}),d.done(function(){var t;it._removeData(e,"fxshow");for(t in f)it.style(e,t,f[t])});for(r in f)a=F(h?m[r]:0,r,d),r in m||(m[r]=a.start,h&&(a.end=a.start,a.start="width"===r||"height"===r?1:0))}}function O(e,t){var n,r,i,o,a;for(n in e)if(r=it.camelCase(n),i=t[r],o=e[n],it.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=it.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function R(e,t,n){var r,i,o=0,a=bn.length,s=it.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;for(var t=hn||_(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:it.extend({},t),opts:it.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:hn||_(),duration:n.duration,tweens:[],createTween:function(t,n){var r=it.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(O(c,u.opts.specialEasing);a>o;o++)if(r=bn[o].call(u,e,c,u.opts))return r;return it.map(c,F,u),it.isFunction(u.opts.start)&&u.opts.start.call(e,u),it.fx.timer(it.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function B(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(bt)||[];if(it.isFunction(n))for(;r=o[i++];)"+"===r.charAt(0)?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function P(e,t,n,r){function i(s){var l;return o[s]=!0,it.each(e[s]||[],function(e,s){var u=s(t,n,r);return"string"!=typeof u||a||o[u]?a?!(l=u):void 0:(t.dataTypes.unshift(u),i(u),!1)}),l}var o={},a=e===zn;return i(t.dataTypes[0])||!o["*"]&&i("*")}function I(e,t){var n,r,i=it.ajaxSettings.flatOptions||{};for(r in t)void 0!==t[r]&&((i[r]?e:n||(n={}))[r]=t[r]);return n&&it.extend(!0,e,n),e}function W(e,t,n){for(var r,i,o,a,s=e.contents,l=e.dataTypes;"*"===l[0];)l.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader("Content-Type"));if(i)for(a in s)if(s[a]&&s[a].test(i)){l.unshift(a);break}if(l[0]in n)o=l[0];else{for(a in n){if(!l[0]||e.converters[a+" "+l[0]]){o=a;break}r||(r=a)}o=o||r}return o?(o!==l[0]&&l.unshift(o),n[o]):void 0}function $(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(a=u[l+" "+o]||u["* "+o],!a)for(i in u)if(s=i.split(" "),s[1]===o&&(a=u[l+" "+s[0]]||u["* "+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(d){return{state:"parsererror",error:a?d:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}function z(e,t,n,r){var i;if(it.isArray(t))it.each(t,function(t,i){n||Gn.test(e)?r(e,i):z(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==it.type(t))r(e,t);else for(i in t)z(e+"["+i+"]",t[i],n,r)}function X(){try{return new e.XMLHttpRequest}catch(t){}}function U(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function V(e){return it.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}var G=[],Y=G.slice,J=G.concat,K=G.push,Q=G.indexOf,Z={},et=Z.toString,tt=Z.hasOwnProperty,nt={},rt="1.11.1",it=function(e,t){return new it.fn.init(e,t)},ot=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,at=/^-ms-/,st=/-([\da-z])/gi,lt=function(e,t){return t.toUpperCase()};it.fn=it.prototype={jquery:rt,constructor:it,selector:"",length:0,toArray:function(){return Y.call(this)},get:function(e){return null!=e?0>e?this[e+this.length]:this[e]:Y.call(this)},pushStack:function(e){var t=it.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return it.each(this,e,t)},map:function(e){return this.pushStack(it.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(Y.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:K,sort:G.sort,splice:G.splice},it.extend=it.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,l=arguments.length,u=!1;for("boolean"==typeof a&&(u=a,a=arguments[s]||{},s++),"object"==typeof a||it.isFunction(a)||(a={}),s===l&&(a=this,s--);l>s;s++)if(null!=(i=arguments[s]))for(r in i)e=a[r],n=i[r],a!==n&&(u&&n&&(it.isPlainObject(n)||(t=it.isArray(n)))?(t?(t=!1,o=e&&it.isArray(e)?e:[]):o=e&&it.isPlainObject(e)?e:{},a[r]=it.extend(u,o,n)):void 0!==n&&(a[r]=n));return a},it.extend({expando:"jQuery"+(rt+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return"function"===it.type(e)},isArray:Array.isArray||function(e){return"array"===it.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!it.isArray(e)&&e-parseFloat(e)>=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||"object"!==it.type(e)||e.nodeType||it.isWindow(e))return!1;try{if(e.constructor&&!tt.call(e,"constructor")&&!tt.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}if(nt.ownLast)for(t in e)return tt.call(e,t);for(t in e);return void 0===t||tt.call(e,t)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?Z[et.call(e)]||"object":typeof e},globalEval:function(t){t&&it.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(at,"ms-").replace(st,lt)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,r){var i,o=0,a=e.length,s=n(e);if(r){if(s)for(;a>o&&(i=t.apply(e[o],r),i!==!1);o++);else for(o in e)if(i=t.apply(e[o],r),i===!1)break}else if(s)for(;a>o&&(i=t.call(e[o],o,e[o]),i!==!1);o++);else for(o in e)if(i=t.call(e[o],o,e[o]),i===!1)break;return e},trim:function(e){return null==e?"":(e+"").replace(ot,"")},makeArray:function(e,t){var r=t||[];return null!=e&&(n(Object(e))?it.merge(r,"string"==typeof e?[e]:e):K.call(r,e)),r},inArray:function(e,t,n){var r;if(t){if(Q)return Q.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;n>r;)e[i++]=t[r++];if(n!==n)for(;void 0!==t[r];)e[i++]=t[r++];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;a>o;o++)r=!t(e[o],o),r!==s&&i.push(e[o]);return i},map:function(e,t,r){var i,o=0,a=e.length,s=n(e),l=[];if(s)for(;a>o;o++)i=t(e[o],o,r),null!=i&&l.push(i);else for(o in e)i=t(e[o],o,r),null!=i&&l.push(i);return J.apply([],l)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(i=e[t],t=e,e=i),it.isFunction(e)?(n=Y.call(arguments,2),r=function(){return e.apply(t||this,n.concat(Y.call(arguments)))},r.guid=e.guid=e.guid||it.guid++,r):void 0},now:function(){return+new Date},support:nt}),it.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){Z["[object "+t+"]"]=t.toLowerCase()});var ut=function(e){function t(e,t,n,r){var i,o,a,s,l,u,d,p,h,m;if((t?t.ownerDocument||t:P)!==H&&L(t),t=t||H,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(q&&!r){if(i=yt.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&R(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return Z.apply(n,t.getElementsByTagName(e)),n;if((a=i[3])&&w.getElementsByClassName&&t.getElementsByClassName)return Z.apply(n,t.getElementsByClassName(a)),n}if(w.qsa&&(!F||!F.test(e))){if(p=d=B,h=t,m=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){for(u=C(e),(d=t.getAttribute("id"))?p=d.replace(xt,"\\$&"):t.setAttribute("id",p),p="[id='"+p+"'] ",l=u.length;l--;)u[l]=p+f(u[l]);h=bt.test(e)&&c(t.parentNode)||t,m=u.join(",")}if(m)try{return Z.apply(n,h.querySelectorAll(m)),n}catch(g){}finally{d||t.removeAttribute("id")}}}return S(e.replace(lt,"$1"),t,n,r)}function n(){function e(n,r){return t.push(n+" ")>T.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[B]=!0,e}function i(e){var t=H.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=e.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||G)-(~e.sourceIndex||G);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function l(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function u(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&typeof e.getElementsByTagName!==V&&e}function d(){}function f(e){for(var t=0,n=e.length,r="";n>t;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&"parentNode"===r,o=W++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,l,u=[I,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[B]||(t[B]={}),(s=l[r])&&s[0]===I&&s[1]===o)return u[2]=s[2];if(l[r]=u,u[2]=e(t,n,a))return!0}}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function m(e,n,r){for(var i=0,o=n.length;o>i;i++)t(e,n[i],r);return r}function g(e,t,n,r,i){for(var o,a=[],s=0,l=e.length,u=null!=t;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function v(e,t,n,i,o,a){return i&&!i[B]&&(i=v(i)),o&&!o[B]&&(o=v(o,a)),r(function(r,a,s,l){var u,c,d,f=[],p=[],h=a.length,v=r||m(t||"*",s.nodeType?[s]:s,[]),y=!e||!r&&t?v:g(v,f,e,s,l),b=n?o||(r?e:h||i)?[]:a:y;if(n&&n(y,b,s,l),i)for(u=g(b,p),i(u,[],s,l),c=u.length;c--;)(d=u[c])&&(b[p[c]]=!(y[p[c]]=d));if(r){if(o||e){if(o){for(u=[],c=b.length;c--;)(d=b[c])&&u.push(y[c]=d);o(null,b=[],u,l)}for(c=b.length;c--;)(d=b[c])&&(u=o?tt.call(r,d):f[c])>-1&&(r[u]=!(a[u]=d))}}else b=g(b===a?b.splice(h,b.length):b),o?o(null,a,b,l):Z.apply(a,b)})}function y(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[" "],s=o?1:0,l=p(function(e){return e===t},a,!0),u=p(function(e){return tt.call(t,e)>-1},a,!0),c=[function(e,n,r){return!o&&(r||n!==j)||((t=n).nodeType?l(e,n,r):u(e,n,r))}];i>s;s++)if(n=T.relative[e[s].type])c=[p(h(c),n)];else{if(n=T.filter[e[s].type].apply(null,e[s].matches),n[B]){for(r=++s;i>r&&!T.relative[e[r].type];r++);return v(s>1&&h(c),s>1&&f(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(lt,"$1"),n,r>s&&y(e.slice(s,r)),i>r&&y(e=e.slice(r)),i>r&&f(e))}c.push(n)}return h(c)}function b(e,n){var i=n.length>0,o=e.length>0,a=function(r,a,s,l,u){var c,d,f,p=0,h="0",m=r&&[],v=[],y=j,b=r||o&&T.find.TAG("*",u),x=I+=null==y?1:Math.random()||.1,w=b.length;for(u&&(j=a!==H&&a);h!==w&&null!=(c=b[h]);h++){if(o&&c){for(d=0;f=e[d++];)if(f(c,a,s)){l.push(c);break}u&&(I=x)}i&&((c=!f&&c)&&p--,r&&m.push(c))}if(p+=h,i&&h!==p){for(d=0;f=n[d++];)f(m,v,a,s);if(r){if(p>0)for(;h--;)m[h]||v[h]||(v[h]=K.call(l));v=g(v)}Z.apply(l,v),u&&!r&&v.length>0&&p+n.length>1&&t.uniqueSort(l)}return u&&(I=x,j=y),m};return i?r(a):a}var x,w,T,E,k,C,N,S,j,A,D,L,H,_,q,F,M,O,R,B="sizzle"+-new Date,P=e.document,I=0,W=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(D=!0),0},V="undefined",G=1<<31,Y={}.hasOwnProperty,J=[],K=J.pop,Q=J.push,Z=J.push,et=J.slice,tt=J.indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(this[t]===e)return t;return-1},nt="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",rt="[\\x20\\t\\r\\n\\f]",it="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",ot=it.replace("w","w#"),at="\\["+rt+"*("+it+")(?:"+rt+"*([*^$|!~]?=)"+rt+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+ot+"))|)"+rt+"*\\]",st=":("+it+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+at+")*)|.*)\\)|)",lt=new RegExp("^"+rt+"+|((?:^|[^\\\\])(?:\\\\.)*)"+rt+"+$","g"),ut=new RegExp("^"+rt+"*,"+rt+"*"),ct=new RegExp("^"+rt+"*([>+~]|"+rt+")"+rt+"*"),dt=new RegExp("="+rt+"*([^\\]'\"]*?)"+rt+"*\\]","g"),ft=new RegExp(st),pt=new RegExp("^"+ot+"$"),ht={ID:new RegExp("^#("+it+")"),CLASS:new RegExp("^\\.("+it+")"),TAG:new RegExp("^("+it.replace("w","w*")+")"),ATTR:new RegExp("^"+at),PSEUDO:new RegExp("^"+st),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+rt+"*(even|odd|(([+-]|)(\\d*)n|)"+rt+"*(?:([+-]|)"+rt+"*(\\d+)|))"+rt+"*\\)|)","i"),bool:new RegExp("^(?:"+nt+")$","i"),needsContext:new RegExp("^"+rt+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+rt+"*((?:-\\d)?\\d*)"+rt+"*\\)|)(?=[^-]|$)","i")},mt=/^(?:input|select|textarea|button)$/i,gt=/^h\d$/i,vt=/^[^{]+\{\s*\[native \w/,yt=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,bt=/[+~]/,xt=/'|\\/g,wt=new RegExp("\\\\([\\da-f]{1,6}"+rt+"?|("+rt+")|.)","ig"),Tt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)};try{Z.apply(J=et.call(P.childNodes),P.childNodes),J[P.childNodes.length].nodeType}catch(Et){Z={apply:J.length?function(e,t){Q.apply(e,et.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},k=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},L=t.setDocument=function(e){var t,n=e?e.ownerDocument||e:P,r=n.defaultView;return n!==H&&9===n.nodeType&&n.documentElement?(H=n,_=n.documentElement,q=!k(n),r&&r!==r.top&&(r.addEventListener?r.addEventListener("unload",function(){L()},!1):r.attachEvent&&r.attachEvent("onunload",function(){L()})),w.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),w.getElementsByTagName=i(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),w.getElementsByClassName=vt.test(n.getElementsByClassName)&&i(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),w.getById=i(function(e){return _.appendChild(e).id=B,!n.getElementsByName||!n.getElementsByName(B).length}),w.getById?(T.find.ID=function(e,t){if(typeof t.getElementById!==V&&q){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},T.filter.ID=function(e){var t=e.replace(wt,Tt);return function(e){return e.getAttribute("id")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(wt,Tt);return function(e){var n=typeof e.getAttributeNode!==V&&e.getAttributeNode("id");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==V?t.getElementsByTagName(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==V&&q?t.getElementsByClassName(e):void 0},M=[],F=[],(w.qsa=vt.test(n.querySelectorAll))&&(i(function(e){e.innerHTML="<select msallowclip=''><option selected=''></option></select>",e.querySelectorAll("[msallowclip^='']").length&&F.push("[*^$]="+rt+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||F.push("\\["+rt+"*(?:value|"+nt+")"),e.querySelectorAll(":checked").length||F.push(":checked")}),i(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&F.push("name"+rt+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||F.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),F.push(",.*:")})),(w.matchesSelector=vt.test(O=_.matches||_.webkitMatchesSelector||_.mozMatchesSelector||_.oMatchesSelector||_.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),M.push("!=",st)}),F=F.length&&new RegExp(F.join("|")),M=M.length&&new RegExp(M.join("|")),t=vt.test(_.compareDocumentPosition),R=t||vt.test(_.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return D=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r?r:(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&r||!w.sortDetached&&t.compareDocumentPosition(e)===r?e===n||e.ownerDocument===P&&R(P,e)?-1:t===n||t.ownerDocument===P&&R(P,t)?1:A?tt.call(A,e)-tt.call(A,t):0:4&r?-1:1)}:function(e,t){if(e===t)return D=!0,0;var r,i=0,o=e.parentNode,s=t.parentNode,l=[e],u=[t];if(!o||!s)return e===n?-1:t===n?1:o?-1:s?1:A?tt.call(A,e)-tt.call(A,t):0;if(o===s)return a(e,t);for(r=e;r=r.parentNode;)l.unshift(r);for(r=t;r=r.parentNode;)u.unshift(r);for(;l[i]===u[i];)i++;return i?a(l[i],u[i]):l[i]===P?-1:u[i]===P?1:0},n):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(dt,"='$1']"),!(!w.matchesSelector||!q||M&&M.test(n)||F&&F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!q):void 0;return void 0!==r?r:w.attributes||!q?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(D=!w.detectDuplicates,A=!w.sortStable&&e.slice(0),e.sort(U),D){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return A=null,e},E=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=E(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=E(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:ht,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(wt,Tt),e[3]=(e[3]||e[4]||e[5]||"").replace(wt,Tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return ht.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&ft.test(n)&&(t=C(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(wt,Tt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+rt+")"+e+"("+rt+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==V&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:n?(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o+" ").indexOf(r)>-1:"|="===n?o===r||o.slice(0,r.length+1)===r+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,d,f,p,h,m=o!==a?"nextSibling":"previousSibling",g=t.parentNode,v=s&&t.nodeName.toLowerCase(),y=!l&&!s;if(g){if(o){for(;m;){for(d=t;d=d[m];)if(s?d.nodeName.toLowerCase()===v:1===d.nodeType)return!1;h=m="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?g.firstChild:g.lastChild],a&&y){for(c=g[B]||(g[B]={}),u=c[e]||[],p=u[0]===I&&u[1],f=u[0]===I&&u[2],d=p&&g.childNodes[p];d=++p&&d&&d[m]||(f=p=0)||h.pop();)if(1===d.nodeType&&++f&&d===t){c[e]=[I,p,f];break}}else if(y&&(u=(t[B]||(t[B]={}))[e])&&u[0]===I)f=u[1];else for(;(d=++p&&d&&d[m]||(f=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==v:1!==d.nodeType)||!++f||(y&&((d[B]||(d[B]={}))[e]=[I,f]),d!==t)););return f-=i,f===r||f%r===0&&f/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[B]?o(n):o.length>1?(i=[e,e,"",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=tt.call(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=N(e.replace(lt,"$1"));return i[B]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return function(t){return(t.textContent||t.innerText||E(t)).indexOf(e)>-1}}),lang:r(function(e){return pt.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(wt,Tt).toLowerCase(),function(t){var n;do if(n=q?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===_},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return gt.test(e.nodeName)},input:function(e){return mt.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:u(function(){return[0]}),last:u(function(e,t){return[t-1]}),eq:u(function(e,t,n){return[0>n?n+t:n]}),even:u(function(e,t){for(var n=0;t>n;n+=2)e.push(n);return e}),odd:u(function(e,t){for(var n=1;t>n;n+=2)e.push(n);return e}),lt:u(function(e,t,n){for(var r=0>n?n+t:n;--r>=0;)e.push(r);return e}),gt:u(function(e,t,n){for(var r=0>n?n+t:n;++r<t;)e.push(r);return e})}},T.pseudos.nth=T.pseudos.eq;for(x in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})T.pseudos[x]=s(x);for(x in{submit:!0,reset:!0})T.pseudos[x]=l(x);return d.prototype=T.filters=T.pseudos,T.setFilters=new d,C=t.tokenize=function(e,n){var r,i,o,a,s,l,u,c=z[e+" "];if(c)return n?0:c.slice(0);for(s=e,l=[],u=T.preFilter;s;){(!r||(i=ut.exec(s)))&&(i&&(s=s.slice(i[0].length)||s),l.push(o=[])),r=!1,(i=ct.exec(s))&&(r=i.shift(),o.push({value:r,type:i[0].replace(lt," ")}),s=s.slice(r.length));for(a in T.filter)!(i=ht[a].exec(s))||u[a]&&!(i=u[a](i))||(r=i.shift(),o.push({value:r,type:a,matches:i}),s=s.slice(r.length));if(!r)break}return n?s.length:s?t.error(e):z(e,l).slice(0)},N=t.compile=function(e,t){var n,r=[],i=[],o=X[e+" "];if(!o){for(t||(t=C(e)),n=t.length;n--;)o=y(t[n]),o[B]?r.push(o):i.push(o);o=X(e,b(i,r)),o.selector=e}return o},S=t.select=function(e,t,n,r){var i,o,a,s,l,u="function"==typeof e&&e,d=!r&&C(e=u.selector||e);if(n=n||[],1===d.length){if(o=d[0]=d[0].slice(0),o.length>2&&"ID"===(a=o[0]).type&&w.getById&&9===t.nodeType&&q&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(wt,Tt),t)||[])[0],!t)return n;u&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=ht.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((l=T.find[s])&&(r=l(a.matches[0].replace(wt,Tt),bt.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&f(o),!e)return Z.apply(n,r),n;
+break}}return(u||N(e,d))(r,t,!q,n,bt.test(e)&&c(t.parentNode)||t),n},w.sortStable=B.split("").sort(U).join("")===B,w.detectDuplicates=!!D,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement("div"))}),i(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){return n?void 0:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?void 0:e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(nt,function(e,t,n){var r;return n?void 0:e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);it.find=ut,it.expr=ut.selectors,it.expr[":"]=it.expr.pseudos,it.unique=ut.uniqueSort,it.text=ut.getText,it.isXMLDoc=ut.isXML,it.contains=ut.contains;var ct=it.expr.match.needsContext,dt=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,ft=/^.[^:#\[\.,]*$/;it.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?it.find.matchesSelector(r,e)?[r]:[]:it.find.matches(e,it.grep(t,function(e){return 1===e.nodeType}))},it.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(it(e).filter(function(){for(t=0;i>t;t++)if(it.contains(r[t],this))return!0}));for(t=0;i>t;t++)it.find(e,r[t],n);return n=this.pushStack(i>1?it.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,"string"==typeof e&&ct.test(e)?it(e):e||[],!1).length}});var pt,ht=e.document,mt=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,gt=it.fn.init=function(e,t){var n,r;if(!e)return this;if("string"==typeof e){if(n="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:mt.exec(e),!n||!n[1]&&t)return!t||t.jquery?(t||pt).find(e):this.constructor(t).find(e);if(n[1]){if(t=t instanceof it?t[0]:t,it.merge(this,it.parseHTML(n[1],t&&t.nodeType?t.ownerDocument||t:ht,!0)),dt.test(n[1])&&it.isPlainObject(t))for(n in t)it.isFunction(this[n])?this[n](t[n]):this.attr(n,t[n]);return this}if(r=ht.getElementById(n[2]),r&&r.parentNode){if(r.id!==n[2])return pt.find(e);this.length=1,this[0]=r}return this.context=ht,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):it.isFunction(e)?"undefined"!=typeof pt.ready?pt.ready(e):e(it):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),it.makeArray(e,this))};gt.prototype=it.fn,pt=it(ht);var vt=/^(?:parents|prev(?:Until|All))/,yt={children:!0,contents:!0,next:!0,prev:!0};it.extend({dir:function(e,t,n){for(var r=[],i=e[t];i&&9!==i.nodeType&&(void 0===n||1!==i.nodeType||!it(i).is(n));)1===i.nodeType&&r.push(i),i=i[t];return r},sibling:function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}}),it.fn.extend({has:function(e){var t,n=it(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(it.contains(this,n[t]))return!0})},closest:function(e,t){for(var n,r=0,i=this.length,o=[],a=ct.test(e)||"string"!=typeof e?it(e,t||this.context):0;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&it.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?it.unique(o):o)},index:function(e){return e?"string"==typeof e?it.inArray(this[0],it(e)):it.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(it.unique(it.merge(this.get(),it(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),it.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return it.dir(e,"parentNode")},parentsUntil:function(e,t,n){return it.dir(e,"parentNode",n)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return it.dir(e,"nextSibling")},prevAll:function(e){return it.dir(e,"previousSibling")},nextUntil:function(e,t,n){return it.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return it.dir(e,"previousSibling",n)},siblings:function(e){return it.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return it.sibling(e.firstChild)},contents:function(e){return it.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:it.merge([],e.childNodes)}},function(e,t){it.fn[e]=function(n,r){var i=it.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=it.filter(r,i)),this.length>1&&(yt[e]||(i=it.unique(i)),vt.test(e)&&(i=i.reverse())),this.pushStack(i)}});var bt=/\S+/g,xt={};it.Callbacks=function(e){e="string"==typeof e?xt[e]||o(e):it.extend({},e);var t,n,r,i,a,s,l=[],u=!e.once&&[],c=function(o){for(n=e.memory&&o,r=!0,a=s||0,s=0,i=l.length,t=!0;l&&i>a;a++)if(l[a].apply(o[0],o[1])===!1&&e.stopOnFalse){n=!1;break}t=!1,l&&(u?u.length&&c(u.shift()):n?l=[]:d.disable())},d={add:function(){if(l){var r=l.length;!function o(t){it.each(t,function(t,n){var r=it.type(n);"function"===r?e.unique&&d.has(n)||l.push(n):n&&n.length&&"string"!==r&&o(n)})}(arguments),t?i=l.length:n&&(s=r,c(n))}return this},remove:function(){return l&&it.each(arguments,function(e,n){for(var r;(r=it.inArray(n,l,r))>-1;)l.splice(r,1),t&&(i>=r&&i--,a>=r&&a--)}),this},has:function(e){return e?it.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],i=0,this},disable:function(){return l=u=n=void 0,this},disabled:function(){return!l},lock:function(){return u=void 0,n||d.disable(),this},locked:function(){return!u},fireWith:function(e,n){return!l||r&&!u||(n=n||[],n=[e,n.slice?n.slice():n],t?u.push(n):c(n)),this},fire:function(){return d.fireWith(this,arguments),this},fired:function(){return!!r}};return d},it.extend({Deferred:function(e){var t=[["resolve","done",it.Callbacks("once memory"),"resolved"],["reject","fail",it.Callbacks("once memory"),"rejected"],["notify","progress",it.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return it.Deferred(function(n){it.each(t,function(t,o){var a=it.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&it.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[o[0]+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?it.extend(e,r):r}},i={};return r.pipe=r.then,it.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=Y.call(arguments),a=o.length,s=1!==a||e&&it.isFunction(e.promise)?a:0,l=1===s?e:it.Deferred(),u=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?Y.call(arguments):i,r===t?l.notifyWith(n,r):--s||l.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);a>i;i++)o[i]&&it.isFunction(o[i].promise)?o[i].promise().done(u(i,r,o)).fail(l.reject).progress(u(i,n,t)):--s;return s||l.resolveWith(r,o),l.promise()}});var wt;it.fn.ready=function(e){return it.ready.promise().done(e),this},it.extend({isReady:!1,readyWait:1,holdReady:function(e){e?it.readyWait++:it.ready(!0)},ready:function(e){if(e===!0?!--it.readyWait:!it.isReady){if(!ht.body)return setTimeout(it.ready);it.isReady=!0,e!==!0&&--it.readyWait>0||(wt.resolveWith(ht,[it]),it.fn.triggerHandler&&(it(ht).triggerHandler("ready"),it(ht).off("ready")))}}}),it.ready.promise=function(t){if(!wt)if(wt=it.Deferred(),"complete"===ht.readyState)setTimeout(it.ready);else if(ht.addEventListener)ht.addEventListener("DOMContentLoaded",s,!1),e.addEventListener("load",s,!1);else{ht.attachEvent("onreadystatechange",s),e.attachEvent("onload",s);var n=!1;try{n=null==e.frameElement&&ht.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!it.isReady){try{n.doScroll("left")}catch(e){return setTimeout(i,50)}a(),it.ready()}}()}return wt.promise(t)};var Tt,Et="undefined";for(Tt in it(nt))break;nt.ownLast="0"!==Tt,nt.inlineBlockNeedsLayout=!1,it(function(){var e,t,n,r;n=ht.getElementsByTagName("body")[0],n&&n.style&&(t=ht.createElement("div"),r=ht.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),typeof t.style.zoom!==Et&&(t.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",nt.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=ht.createElement("div");if(null==nt.deleteExpando){nt.deleteExpando=!0;try{delete e.test}catch(t){nt.deleteExpando=!1}}e=null}(),it.acceptData=function(e){var t=it.noData[(e.nodeName+" ").toLowerCase()],n=+e.nodeType||1;return 1!==n&&9!==n?!1:!t||t!==!0&&e.getAttribute("classid")===t};var kt=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Ct=/([A-Z])/g;it.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?it.cache[e[it.expando]]:e[it.expando],!!e&&!u(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return d(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return d(e,t,!0)}}),it.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=it.data(o),1===o.nodeType&&!it._data(o,"parsedAttrs"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf("data-")&&(r=it.camelCase(r.slice(5)),l(o,r,i[r])));it._data(o,"parsedAttrs",!0)}return i}return"object"==typeof e?this.each(function(){it.data(this,e)}):arguments.length>1?this.each(function(){it.data(this,e,t)}):o?l(o,e,it.data(o,e)):void 0},removeData:function(e){return this.each(function(){it.removeData(this,e)})}}),it.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=it._data(e,t),n&&(!r||it.isArray(n)?r=it._data(e,t,it.makeArray(n)):r.push(n)),r||[]):void 0},dequeue:function(e,t){t=t||"fx";var n=it.queue(e,t),r=n.length,i=n.shift(),o=it._queueHooks(e,t),a=function(){it.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return it._data(e,n)||it._data(e,n,{empty:it.Callbacks("once memory").add(function(){it._removeData(e,t+"queue"),it._removeData(e,n)})})}}),it.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?it.queue(this[0],e):void 0===t?this:this.each(function(){var n=it.queue(this,e,t);it._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&it.dequeue(this,e)})},dequeue:function(e){return this.each(function(){it.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=it.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};for("string"!=typeof e&&(t=e,e=void 0),e=e||"fx";a--;)n=it._data(o[a],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var Nt=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,St=["Top","Right","Bottom","Left"],jt=function(e,t){return e=t||e,"none"===it.css(e,"display")||!it.contains(e.ownerDocument,e)},At=it.access=function(e,t,n,r,i,o,a){var s=0,l=e.length,u=null==n;if("object"===it.type(n)){i=!0;for(s in n)it.access(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,it.isFunction(r)||(a=!0),u&&(a?(t.call(e,r),t=null):(u=t,t=function(e,t,n){return u.call(it(e),n)})),t))for(;l>s;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:u?t.call(e):l?t(e[0],n):o},Dt=/^(?:checkbox|radio)$/i;!function(){var e=ht.createElement("input"),t=ht.createElement("div"),n=ht.createDocumentFragment();if(t.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",nt.leadingWhitespace=3===t.firstChild.nodeType,nt.tbody=!t.getElementsByTagName("tbody").length,nt.htmlSerialize=!!t.getElementsByTagName("link").length,nt.html5Clone="<:nav></:nav>"!==ht.createElement("nav").cloneNode(!0).outerHTML,e.type="checkbox",e.checked=!0,n.appendChild(e),nt.appendChecked=e.checked,t.innerHTML="<textarea>x</textarea>",nt.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue,n.appendChild(t),t.innerHTML="<input type='radio' checked='checked' name='t'/>",nt.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,nt.noCloneEvent=!0,t.attachEvent&&(t.attachEvent("onclick",function(){nt.noCloneEvent=!1}),t.cloneNode(!0).click()),null==nt.deleteExpando){nt.deleteExpando=!0;try{delete t.test}catch(r){nt.deleteExpando=!1}}}(),function(){var t,n,r=ht.createElement("div");for(t in{submit:!0,change:!0,focusin:!0})n="on"+t,(nt[t+"Bubbles"]=n in e)||(r.setAttribute(n,"t"),nt[t+"Bubbles"]=r.attributes[n].expando===!1);r=null}();var Lt=/^(?:input|select|textarea)$/i,Ht=/^key/,_t=/^(?:mouse|pointer|contextmenu)|click/,qt=/^(?:focusinfocus|focusoutblur)$/,Ft=/^([^.]*)(?:\.(.+)|)$/;it.event={global:{},add:function(e,t,n,r,i){var o,a,s,l,u,c,d,f,p,h,m,g=it._data(e);if(g){for(n.handler&&(l=n,n=l.handler,i=l.selector),n.guid||(n.guid=it.guid++),(a=g.events)||(a=g.events={}),(c=g.handle)||(c=g.handle=function(e){return typeof it===Et||e&&it.event.triggered===e.type?void 0:it.event.dispatch.apply(c.elem,arguments)},c.elem=e),t=(t||"").match(bt)||[""],s=t.length;s--;)o=Ft.exec(t[s])||[],p=m=o[1],h=(o[2]||"").split(".").sort(),p&&(u=it.event.special[p]||{},p=(i?u.delegateType:u.bindType)||p,u=it.event.special[p]||{},d=it.extend({type:p,origType:m,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&it.expr.match.needsContext.test(i),namespace:h.join(".")},l),(f=a[p])||(f=a[p]=[],f.delegateCount=0,u.setup&&u.setup.call(e,r,h,c)!==!1||(e.addEventListener?e.addEventListener(p,c,!1):e.attachEvent&&e.attachEvent("on"+p,c))),u.add&&(u.add.call(e,d),d.handler.guid||(d.handler.guid=n.guid)),i?f.splice(f.delegateCount++,0,d):f.push(d),it.event.global[p]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,d,f,p,h,m,g=it.hasData(e)&&it._data(e);if(g&&(c=g.events)){for(t=(t||"").match(bt)||[""],u=t.length;u--;)if(s=Ft.exec(t[u])||[],p=m=s[1],h=(s[2]||"").split(".").sort(),p){for(d=it.event.special[p]||{},p=(r?d.delegateType:d.bindType)||p,f=c[p]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;o--;)a=f[o],!i&&m!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,d.remove&&d.remove.call(e,a));l&&!f.length&&(d.teardown&&d.teardown.call(e,h,g.handle)!==!1||it.removeEvent(e,p,g.handle),delete c[p])}else for(p in c)it.event.remove(e,p+t[u],n,r,!0);it.isEmptyObject(c)&&(delete g.handle,it._removeData(e,"events"))}},trigger:function(t,n,r,i){var o,a,s,l,u,c,d,f=[r||ht],p=tt.call(t,"type")?t.type:t,h=tt.call(t,"namespace")?t.namespace.split("."):[];if(s=c=r=r||ht,3!==r.nodeType&&8!==r.nodeType&&!qt.test(p+it.event.triggered)&&(p.indexOf(".")>=0&&(h=p.split("."),p=h.shift(),h.sort()),a=p.indexOf(":")<0&&"on"+p,t=t[it.expando]?t:new it.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.namespace_re=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:it.makeArray(n,[t]),u=it.event.special[p]||{},i||!u.trigger||u.trigger.apply(r,n)!==!1)){if(!i&&!u.noBubble&&!it.isWindow(r)){for(l=u.delegateType||p,qt.test(l+p)||(s=s.parentNode);s;s=s.parentNode)f.push(s),c=s;c===(r.ownerDocument||ht)&&f.push(c.defaultView||c.parentWindow||e)}for(d=0;(s=f[d++])&&!t.isPropagationStopped();)t.type=d>1?l:u.bindType||p,o=(it._data(s,"events")||{})[t.type]&&it._data(s,"handle"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&it.acceptData(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!u._default||u._default.apply(f.pop(),n)===!1)&&it.acceptData(r)&&a&&r[p]&&!it.isWindow(r)){c=r[a],c&&(r[a]=null),it.event.triggered=p;try{r[p]()}catch(m){}it.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=it.event.fix(e);var t,n,r,i,o,a=[],s=Y.call(arguments),l=(it._data(this,"events")||{})[e.type]||[],u=it.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!u.preDispatch||u.preDispatch.call(this,e)!==!1){for(a=it.event.handlers.call(this,e,l),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,o=0;(r=i.handlers[o++])&&!e.isImmediatePropagationStopped();)(!e.namespace_re||e.namespace_re.test(r.namespace))&&(e.handleObj=r,e.data=r.data,n=((it.event.special[r.origType]||{}).handle||r.handler).apply(i.elem,s),void 0!==n&&(e.result=n)===!1&&(e.preventDefault(),e.stopPropagation()));return u.postDispatch&&u.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,l=e.target;if(s&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(i=[],o=0;s>o;o++)r=t[o],n=r.selector+" ",void 0===i[n]&&(i[n]=r.needsContext?it(n,this).index(l)>=0:it.find(n,this,null,[l]).length),i[n]&&i.push(r);i.length&&a.push({elem:l,handlers:i})}return s<t.length&&a.push({elem:this,handlers:t.slice(s)}),a},fix:function(e){if(e[it.expando])return e;var t,n,r,i=e.type,o=e,a=this.fixHooks[i];for(a||(this.fixHooks[i]=a=_t.test(i)?this.mouseHooks:Ht.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new it.Event(o),t=r.length;t--;)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||ht),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,a.filter?a.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,o=t.button,a=t.fromElement;return null==e.pageX&&null!=t.clientX&&(r=e.target.ownerDocument||ht,i=r.documentElement,n=r.body,e.pageX=t.clientX+(i&&i.scrollLeft||n&&n.scrollLeft||0)-(i&&i.clientLeft||n&&n.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||n&&n.scrollTop||0)-(i&&i.clientTop||n&&n.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?t.toElement:a),e.which||void 0===o||(e.which=1&o?1:2&o?3:4&o?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==h()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===h()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return it.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(e){return it.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=it.extend(new it.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?it.event.trigger(i,null,t):it.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},it.removeEvent=ht.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===Et&&(e[r]=null),e.detachEvent(r,n))},it.Event=function(e,t){return this instanceof it.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?f:p):this.type=e,t&&it.extend(this,t),this.timeStamp=e&&e.timeStamp||it.now(),void(this[it.expando]=!0)):new it.Event(e,t)},it.Event.prototype={isDefaultPrevented:p,isPropagationStopped:p,isImmediatePropagationStopped:p,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=f,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=f,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=f,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},it.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){it.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!it.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),nt.submitBubbles||(it.event.special.submit={setup:function(){return it.nodeName(this,"form")?!1:void it.event.add(this,"click._submit keypress._submit",function(e){var t=e.target,n=it.nodeName(t,"input")||it.nodeName(t,"button")?t.form:void 0;n&&!it._data(n,"submitBubbles")&&(it.event.add(n,"submit._submit",function(e){e._submit_bubble=!0}),it._data(n,"submitBubbles",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&it.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return it.nodeName(this,"form")?!1:void it.event.remove(this,"._submit")}}),nt.changeBubbles||(it.event.special.change={setup:function(){return Lt.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(it.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),it.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),it.event.simulate("change",this,e,!0)})),!1):void it.event.add(this,"beforeactivate._change",function(e){var t=e.target;Lt.test(t.nodeName)&&!it._data(t,"changeBubbles")&&(it.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||it.event.simulate("change",this.parentNode,e,!0)}),it._data(t,"changeBubbles",!0))})},handle:function(e){var t=e.target;return this!==t||e.isSimulated||e.isTrigger||"radio"!==t.type&&"checkbox"!==t.type?e.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return it.event.remove(this,"._change"),!Lt.test(this.nodeName)}}),nt.focusinBubbles||it.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){it.event.simulate(t,e.target,it.event.fix(e),!0)};it.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=it._data(r,t);i||r.addEventListener(e,n,!0),it._data(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=it._data(r,t)-1;i?it._data(r,t,i):(r.removeEventListener(e,n,!0),it._removeData(r,t))}}}),it.fn.extend({on:function(e,t,n,r,i){var o,a;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=void 0);for(o in e)this.on(o,t,n,e[o],i);return this}if(null==n&&null==r?(r=t,n=t=void 0):null==r&&("string"==typeof t?(r=n,n=void 0):(r=n,n=t,t=void 0)),r===!1)r=p;else if(!r)return this;return 1===i&&(a=r,r=function(e){return it().off(e),a.apply(this,arguments)},r.guid=a.guid||(a.guid=it.guid++)),this.each(function(){it.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,it(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=void 0),n===!1&&(n=p),this.each(function(){it.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){it.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?it.event.trigger(e,t,n,!0):void 0}});var Mt="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",Ot=/ jQuery\d+="(?:null|\d+)"/g,Rt=new RegExp("<(?:"+Mt+")[\\s/>]","i"),Bt=/^\s+/,Pt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,It=/<([\w:]+)/,Wt=/<tbody/i,$t=/<|&#?\w+;/,zt=/<(?:script|style|link)/i,Xt=/checked\s*(?:[^=]|=\s*.checked.)/i,Ut=/^$|\/(?:java|ecma)script/i,Vt=/^true\/(.*)/,Gt=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Yt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:nt.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},Jt=m(ht),Kt=Jt.appendChild(ht.createElement("div"));Yt.optgroup=Yt.option,Yt.tbody=Yt.tfoot=Yt.colgroup=Yt.caption=Yt.thead,Yt.th=Yt.td,it.extend({clone:function(e,t,n){var r,i,o,a,s,l=it.contains(e.ownerDocument,e);if(nt.html5Clone||it.isXMLDoc(e)||!Rt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Kt.innerHTML=e.outerHTML,Kt.removeChild(o=Kt.firstChild)),!(nt.noCloneEvent&&nt.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||it.isXMLDoc(e)))for(r=g(o),s=g(e),a=0;null!=(i=s[a]);++a)r[a]&&E(i,r[a]);if(t)if(n)for(s=s||g(e),r=r||g(o),a=0;null!=(i=s[a]);a++)T(i,r[a]);else T(e,o);return r=g(o,"script"),r.length>0&&w(r,!l&&g(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){for(var i,o,a,s,l,u,c,d=e.length,f=m(t),p=[],h=0;d>h;h++)if(o=e[h],o||0===o)if("object"===it.type(o))it.merge(p,o.nodeType?[o]:o);else if($t.test(o)){for(s=s||f.appendChild(t.createElement("div")),l=(It.exec(o)||["",""])[1].toLowerCase(),c=Yt[l]||Yt._default,s.innerHTML=c[1]+o.replace(Pt,"<$1></$2>")+c[2],i=c[0];i--;)s=s.lastChild;if(!nt.leadingWhitespace&&Bt.test(o)&&p.push(t.createTextNode(Bt.exec(o)[0])),!nt.tbody)for(o="table"!==l||Wt.test(o)?"<table>"!==c[1]||Wt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;i--;)it.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u);for(it.merge(p,s.childNodes),s.textContent="";s.firstChild;)s.removeChild(s.firstChild);s=f.lastChild}else p.push(t.createTextNode(o));for(s&&f.removeChild(s),nt.appendChecked||it.grep(g(p,"input"),v),h=0;o=p[h++];)if((!r||-1===it.inArray(o,r))&&(a=it.contains(o.ownerDocument,o),s=g(f.appendChild(o),"script"),a&&w(s),n))for(i=0;o=s[i++];)Ut.test(o.type||"")&&n.push(o);return s=null,f},cleanData:function(e,t){for(var n,r,i,o,a=0,s=it.expando,l=it.cache,u=nt.deleteExpando,c=it.event.special;null!=(n=e[a]);a++)if((t||it.acceptData(n))&&(i=n[s],o=i&&l[i])){if(o.events)for(r in o.events)c[r]?it.event.remove(n,r):it.removeEvent(n,r,o.handle);l[i]&&(delete l[i],u?delete n[s]:typeof n.removeAttribute!==Et?n.removeAttribute(s):n[s]=null,G.push(i))}}}),it.fn.extend({text:function(e){return At(this,function(e){return void 0===e?it.text(this):this.empty().append((this[0]&&this[0].ownerDocument||ht).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=y(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=y(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){for(var n,r=e?it.filter(e,this):this,i=0;null!=(n=r[i]);i++)t||1!==n.nodeType||it.cleanData(g(n)),n.parentNode&&(t&&it.contains(n.ownerDocument,n)&&w(g(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&it.cleanData(g(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&it.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return it.clone(this,e,t)})},html:function(e){return At(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(Ot,""):void 0;if(!("string"!=typeof e||zt.test(e)||!nt.htmlSerialize&&Rt.test(e)||!nt.leadingWhitespace&&Bt.test(e)||Yt[(It.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(Pt,"<$1></$2>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(it.cleanData(g(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=arguments[0];return this.domManip(arguments,function(t){e=this.parentNode,it.cleanData(g(this)),e&&e.replaceChild(t,this)}),e&&(e.length||e.nodeType)?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t){e=J.apply([],e);var n,r,i,o,a,s,l=0,u=this.length,c=this,d=u-1,f=e[0],p=it.isFunction(f);if(p||u>1&&"string"==typeof f&&!nt.checkClone&&Xt.test(f))return this.each(function(n){var r=c.eq(n);p&&(e[0]=f.call(this,n,r.html())),r.domManip(e,t)});if(u&&(s=it.buildFragment(e,this[0].ownerDocument,!1,this),n=s.firstChild,1===s.childNodes.length&&(s=n),n)){for(o=it.map(g(s,"script"),b),i=o.length;u>l;l++)r=s,l!==d&&(r=it.clone(r,!0,!0),i&&it.merge(o,g(r,"script"))),t.call(this[l],r,l);if(i)for(a=o[o.length-1].ownerDocument,it.map(o,x),l=0;i>l;l++)r=o[l],Ut.test(r.type||"")&&!it._data(r,"globalEval")&&it.contains(a,r)&&(r.src?it._evalUrl&&it._evalUrl(r.src):it.globalEval((r.text||r.textContent||r.innerHTML||"").replace(Gt,"")));s=n=null}return this}}),it.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){it.fn[e]=function(e){for(var n,r=0,i=[],o=it(e),a=o.length-1;a>=r;r++)n=r===a?this:this.clone(!0),it(o[r])[t](n),K.apply(i,n.get());return this.pushStack(i)}});var Qt,Zt={};!function(){var e;nt.shrinkWrapBlocks=function(){if(null!=e)return e;e=!1;var t,n,r;return n=ht.getElementsByTagName("body")[0],n&&n.style?(t=ht.createElement("div"),r=ht.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),typeof t.style.zoom!==Et&&(t.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",t.appendChild(ht.createElement("div")).style.width="5px",e=3!==t.offsetWidth),n.removeChild(r),e):void 0}}();var en,tn,nn=/^margin/,rn=new RegExp("^("+Nt+")(?!px)[a-z%]+$","i"),on=/^(top|right|bottom|left)$/;e.getComputedStyle?(en=function(e){return e.ownerDocument.defaultView.getComputedStyle(e,null)},tn=function(e,t,n){var r,i,o,a,s=e.style;return n=n||en(e),a=n?n.getPropertyValue(t)||n[t]:void 0,n&&(""!==a||it.contains(e.ownerDocument,e)||(a=it.style(e,t)),rn.test(a)&&nn.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0===a?a:a+""}):ht.documentElement.currentStyle&&(en=function(e){return e.currentStyle},tn=function(e,t,n){var r,i,o,a,s=e.style;return n=n||en(e),a=n?n[t]:void 0,null==a&&s&&s[t]&&(a=s[t]),rn.test(a)&&!on.test(t)&&(r=s.left,i=e.runtimeStyle,o=i&&i.left,o&&(i.left=e.currentStyle.left),s.left="fontSize"===t?"1em":a,a=s.pixelLeft+"px",s.left=r,o&&(i.left=o)),void 0===a?a:a+""||"auto"}),function(){function t(){var t,n,r,i;n=ht.getElementsByTagName("body")[0],n&&n.style&&(t=ht.createElement("div"),r=ht.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),t.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",o=a=!1,l=!0,e.getComputedStyle&&(o="1%"!==(e.getComputedStyle(t,null)||{}).top,a="4px"===(e.getComputedStyle(t,null)||{width:"4px"}).width,i=t.appendChild(ht.createElement("div")),i.style.cssText=t.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",t.style.width="1px",l=!parseFloat((e.getComputedStyle(i,null)||{}).marginRight)),t.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=t.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",s=0===i[0].offsetHeight,s&&(i[0].style.display="",i[1].style.display="none",s=0===i[0].offsetHeight),n.removeChild(r))}var n,r,i,o,a,s,l;n=ht.createElement("div"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",i=n.getElementsByTagName("a")[0],r=i&&i.style,r&&(r.cssText="float:left;opacity:.5",nt.opacity="0.5"===r.opacity,nt.cssFloat=!!r.cssFloat,n.style.backgroundClip="content-box",n.cloneNode(!0).style.backgroundClip="",nt.clearCloneStyle="content-box"===n.style.backgroundClip,nt.boxSizing=""===r.boxSizing||""===r.MozBoxSizing||""===r.WebkitBoxSizing,it.extend(nt,{reliableHiddenOffsets:function(){return null==s&&t(),s
+},boxSizingReliable:function(){return null==a&&t(),a},pixelPosition:function(){return null==o&&t(),o},reliableMarginRight:function(){return null==l&&t(),l}}))}(),it.swap=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};var an=/alpha\([^)]*\)/i,sn=/opacity\s*=\s*([^)]*)/,ln=/^(none|table(?!-c[ea]).+)/,un=new RegExp("^("+Nt+")(.*)$","i"),cn=new RegExp("^([+-])=("+Nt+")","i"),dn={position:"absolute",visibility:"hidden",display:"block"},fn={letterSpacing:"0",fontWeight:"400"},pn=["Webkit","O","Moz","ms"];it.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=tn(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":nt.cssFloat?"cssFloat":"styleFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=it.camelCase(t),l=e.style;if(t=it.cssProps[s]||(it.cssProps[s]=S(l,s)),a=it.cssHooks[t]||it.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];if(o=typeof n,"string"===o&&(i=cn.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(it.css(e,t)),o="number"),null!=n&&n===n&&("number"!==o||it.cssNumber[s]||(n+="px"),nt.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),!(a&&"set"in a&&void 0===(n=a.set(e,n,r)))))try{l[t]=n}catch(u){}}},css:function(e,t,n,r){var i,o,a,s=it.camelCase(t);return t=it.cssProps[s]||(it.cssProps[s]=S(e.style,s)),a=it.cssHooks[t]||it.cssHooks[s],a&&"get"in a&&(o=a.get(e,!0,n)),void 0===o&&(o=tn(e,t,r)),"normal"===o&&t in fn&&(o=fn[t]),""===n||n?(i=parseFloat(o),n===!0||it.isNumeric(i)?i||0:o):o}}),it.each(["height","width"],function(e,t){it.cssHooks[t]={get:function(e,n,r){return n?ln.test(it.css(e,"display"))&&0===e.offsetWidth?it.swap(e,dn,function(){return L(e,t,r)}):L(e,t,r):void 0},set:function(e,n,r){var i=r&&en(e);return A(e,n,r?D(e,t,r,nt.boxSizing&&"border-box"===it.css(e,"boxSizing",!1,i),i):0)}}}),nt.opacity||(it.cssHooks.opacity={get:function(e,t){return sn.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=it.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===it.trim(o.replace(an,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=an.test(o)?o.replace(an,i):o+" "+i)}}),it.cssHooks.marginRight=N(nt.reliableMarginRight,function(e,t){return t?it.swap(e,{display:"inline-block"},tn,[e,"marginRight"]):void 0}),it.each({margin:"",padding:"",border:"Width"},function(e,t){it.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];4>r;r++)i[e+St[r]+t]=o[r]||o[r-2]||o[0];return i}},nn.test(e)||(it.cssHooks[e+t].set=A)}),it.fn.extend({css:function(e,t){return At(this,function(e,t,n){var r,i,o={},a=0;if(it.isArray(t)){for(r=en(e),i=t.length;i>a;a++)o[t[a]]=it.css(e,t[a],!1,r);return o}return void 0!==n?it.style(e,t,n):it.css(e,t)},e,t,arguments.length>1)},show:function(){return j(this,!0)},hide:function(){return j(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){jt(this)?it(this).show():it(this).hide()})}}),it.Tween=H,H.prototype={constructor:H,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(it.cssNumber[n]?"":"px")},cur:function(){var e=H.propHooks[this.prop];return e&&e.get?e.get(this):H.propHooks._default.get(this)},run:function(e){var t,n=H.propHooks[this.prop];return this.pos=t=this.options.duration?it.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):H.propHooks._default.set(this),this}},H.prototype.init.prototype=H.prototype,H.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=it.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){it.fx.step[e.prop]?it.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[it.cssProps[e.prop]]||it.cssHooks[e.prop])?it.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},H.propHooks.scrollTop=H.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},it.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},it.fx=H.prototype.init,it.fx.step={};var hn,mn,gn=/^(?:toggle|show|hide)$/,vn=new RegExp("^(?:([+-])=|)("+Nt+")([a-z%]*)$","i"),yn=/queueHooks$/,bn=[M],xn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=vn.exec(t),o=i&&i[3]||(it.cssNumber[e]?"":"px"),a=(it.cssNumber[e]||"px"!==o&&+r)&&vn.exec(it.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||".5",a/=s,it.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};it.Animation=it.extend(R,{tweener:function(e,t){it.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");for(var n,r=0,i=e.length;i>r;r++)n=e[r],xn[n]=xn[n]||[],xn[n].unshift(t)},prefilter:function(e,t){t?bn.unshift(e):bn.push(e)}}),it.speed=function(e,t,n){var r=e&&"object"==typeof e?it.extend({},e):{complete:n||!n&&t||it.isFunction(e)&&e,duration:e,easing:n&&t||t&&!it.isFunction(t)&&t};return r.duration=it.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in it.fx.speeds?it.fx.speeds[r.duration]:it.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){it.isFunction(r.old)&&r.old.call(this),r.queue&&it.dequeue(this,r.queue)},r},it.fn.extend({fadeTo:function(e,t,n,r){return this.filter(jt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=it.isEmptyObject(e),o=it.speed(t,n,r),a=function(){var t=R(this,it.extend({},e),o);(i||it._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=it.timers,a=it._data(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&yn.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));(t||!n)&&it.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=it._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=it.timers,a=r?r.length:0;for(n.finish=!0,it.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),it.each(["toggle","show","hide"],function(e,t){var n=it.fn[t];it.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(q(t,!0),e,r,i)}}),it.each({slideDown:q("show"),slideUp:q("hide"),slideToggle:q("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){it.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),it.timers=[],it.fx.tick=function(){var e,t=it.timers,n=0;for(hn=it.now();n<t.length;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||it.fx.stop(),hn=void 0},it.fx.timer=function(e){it.timers.push(e),e()?it.fx.start():it.timers.pop()},it.fx.interval=13,it.fx.start=function(){mn||(mn=setInterval(it.fx.tick,it.fx.interval))},it.fx.stop=function(){clearInterval(mn),mn=null},it.fx.speeds={slow:600,fast:200,_default:400},it.fn.delay=function(e,t){return e=it.fx?it.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},function(){var e,t,n,r,i;t=ht.createElement("div"),t.setAttribute("className","t"),t.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",r=t.getElementsByTagName("a")[0],n=ht.createElement("select"),i=n.appendChild(ht.createElement("option")),e=t.getElementsByTagName("input")[0],r.style.cssText="top:1px",nt.getSetAttribute="t"!==t.className,nt.style=/top/.test(r.getAttribute("style")),nt.hrefNormalized="/a"===r.getAttribute("href"),nt.checkOn=!!e.value,nt.optSelected=i.selected,nt.enctype=!!ht.createElement("form").enctype,n.disabled=!0,nt.optDisabled=!i.disabled,e=ht.createElement("input"),e.setAttribute("value",""),nt.input=""===e.getAttribute("value"),e.value="t",e.setAttribute("type","radio"),nt.radioValue="t"===e.value}();var wn=/\r/g;it.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=it.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,it(this).val()):e,null==i?i="":"number"==typeof i?i+="":it.isArray(i)&&(i=it.map(i,function(e){return null==e?"":e+""})),t=it.valHooks[this.type]||it.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return t=it.valHooks[i.type]||it.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(wn,""):null==n?"":n)}}}),it.extend({valHooks:{option:{get:function(e){var t=it.find.attr(e,"value");return null!=t?t:it.trim(it.text(e))}},select:{get:function(e){for(var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(nt.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&it.nodeName(n.parentNode,"optgroup"))){if(t=it(n).val(),o)return t;a.push(t)}return a},set:function(e,t){for(var n,r,i=e.options,o=it.makeArray(t),a=i.length;a--;)if(r=i[a],it.inArray(it.valHooks.option.get(r),o)>=0)try{r.selected=n=!0}catch(s){r.scrollHeight}else r.selected=!1;return n||(e.selectedIndex=-1),i}}}}),it.each(["radio","checkbox"],function(){it.valHooks[this]={set:function(e,t){return it.isArray(t)?e.checked=it.inArray(it(e).val(),t)>=0:void 0}},nt.checkOn||(it.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Tn,En,kn=it.expr.attrHandle,Cn=/^(?:checked|selected)$/i,Nn=nt.getSetAttribute,Sn=nt.input;it.fn.extend({attr:function(e,t){return At(this,it.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){it.removeAttr(this,e)})}}),it.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(e&&3!==o&&8!==o&&2!==o)return typeof e.getAttribute===Et?it.prop(e,t,n):(1===o&&it.isXMLDoc(e)||(t=t.toLowerCase(),r=it.attrHooks[t]||(it.expr.match.bool.test(t)?En:Tn)),void 0===n?r&&"get"in r&&null!==(i=r.get(e,t))?i:(i=it.find.attr(e,t),null==i?void 0:i):null!==n?r&&"set"in r&&void 0!==(i=r.set(e,n,t))?i:(e.setAttribute(t,n+""),n):void it.removeAttr(e,t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(bt);if(o&&1===e.nodeType)for(;n=o[i++];)r=it.propFix[n]||n,it.expr.match.bool.test(n)?Sn&&Nn||!Cn.test(n)?e[r]=!1:e[it.camelCase("default-"+n)]=e[r]=!1:it.attr(e,n,""),e.removeAttribute(Nn?n:r)},attrHooks:{type:{set:function(e,t){if(!nt.radioValue&&"radio"===t&&it.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}}}),En={set:function(e,t,n){return t===!1?it.removeAttr(e,n):Sn&&Nn||!Cn.test(n)?e.setAttribute(!Nn&&it.propFix[n]||n,n):e[it.camelCase("default-"+n)]=e[n]=!0,n}},it.each(it.expr.match.bool.source.match(/\w+/g),function(e,t){var n=kn[t]||it.find.attr;kn[t]=Sn&&Nn||!Cn.test(t)?function(e,t,r){var i,o;return r||(o=kn[t],kn[t]=i,i=null!=n(e,t,r)?t.toLowerCase():null,kn[t]=o),i}:function(e,t,n){return n?void 0:e[it.camelCase("default-"+t)]?t.toLowerCase():null}}),Sn&&Nn||(it.attrHooks.value={set:function(e,t,n){return it.nodeName(e,"input")?void(e.defaultValue=t):Tn&&Tn.set(e,t,n)}}),Nn||(Tn={set:function(e,t,n){var r=e.getAttributeNode(n);return r||e.setAttributeNode(r=e.ownerDocument.createAttribute(n)),r.value=t+="","value"===n||t===e.getAttribute(n)?t:void 0}},kn.id=kn.name=kn.coords=function(e,t,n){var r;return n?void 0:(r=e.getAttributeNode(t))&&""!==r.value?r.value:null},it.valHooks.button={get:function(e,t){var n=e.getAttributeNode(t);return n&&n.specified?n.value:void 0},set:Tn.set},it.attrHooks.contenteditable={set:function(e,t,n){Tn.set(e,""===t?!1:t,n)}},it.each(["width","height"],function(e,t){it.attrHooks[t]={set:function(e,n){return""===n?(e.setAttribute(t,"auto"),n):void 0}}})),nt.style||(it.attrHooks.style={get:function(e){return e.style.cssText||void 0},set:function(e,t){return e.style.cssText=t+""}});var jn=/^(?:input|select|textarea|button|object)$/i,An=/^(?:a|area)$/i;it.fn.extend({prop:function(e,t){return At(this,it.prop,e,t,arguments.length>1)},removeProp:function(e){return e=it.propFix[e]||e,this.each(function(){try{this[e]=void 0,delete this[e]}catch(t){}})}}),it.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,a=e.nodeType;if(e&&3!==a&&8!==a&&2!==a)return o=1!==a||!it.isXMLDoc(e),o&&(t=it.propFix[t]||t,i=it.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=it.find.attr(e,"tabindex");return t?parseInt(t,10):jn.test(e.nodeName)||An.test(e.nodeName)&&e.href?0:-1}}}}),nt.hrefNormalized||it.each(["href","src"],function(e,t){it.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),nt.optSelected||(it.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),it.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){it.propFix[this.toLowerCase()]=this}),nt.enctype||(it.propFix.enctype="encoding");var Dn=/[\t\r\n\f]/g;it.fn.extend({addClass:function(e){var t,n,r,i,o,a,s=0,l=this.length,u="string"==typeof e&&e;if(it.isFunction(e))return this.each(function(t){it(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(bt)||[];l>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(Dn," "):" ")){for(o=0;i=t[o++];)r.indexOf(" "+i+" ")<0&&(r+=i+" ");a=it.trim(r),n.className!==a&&(n.className=a)}return this},removeClass:function(e){var t,n,r,i,o,a,s=0,l=this.length,u=0===arguments.length||"string"==typeof e&&e;if(it.isFunction(e))return this.each(function(t){it(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(bt)||[];l>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(Dn," "):"")){for(o=0;i=t[o++];)for(;r.indexOf(" "+i+" ")>=0;)r=r.replace(" "+i+" "," ");a=e?it.trim(r):"",n.className!==a&&(n.className=a)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):this.each(it.isFunction(e)?function(n){it(this).toggleClass(e.call(this,n,this.className,t),t)}:function(){if("string"===n)for(var t,r=0,i=it(this),o=e.match(bt)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else(n===Et||"boolean"===n)&&(this.className&&it._data(this,"__className__",this.className),this.className=this.className||e===!1?"":it._data(this,"__className__")||"")})},hasClass:function(e){for(var t=" "+e+" ",n=0,r=this.length;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(Dn," ").indexOf(t)>=0)return!0;return!1}}),it.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){it.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),it.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var Ln=it.now(),Hn=/\?/,_n=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;it.parseJSON=function(t){if(e.JSON&&e.JSON.parse)return e.JSON.parse(t+"");var n,r=null,i=it.trim(t+"");return i&&!it.trim(i.replace(_n,function(e,t,i,o){return n&&t&&(r=0),0===r?e:(n=i||t,r+=!o-!i,"")}))?Function("return "+i)():it.error("Invalid JSON: "+t)},it.parseXML=function(t){var n,r;if(!t||"string"!=typeof t)return null;try{e.DOMParser?(r=new DOMParser,n=r.parseFromString(t,"text/xml")):(n=new ActiveXObject("Microsoft.XMLDOM"),n.async="false",n.loadXML(t))}catch(i){n=void 0}return n&&n.documentElement&&!n.getElementsByTagName("parsererror").length||it.error("Invalid XML: "+t),n};var qn,Fn,Mn=/#.*$/,On=/([?&])_=[^&]*/,Rn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Bn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Pn=/^(?:GET|HEAD)$/,In=/^\/\//,Wn=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,$n={},zn={},Xn="*/".concat("*");try{Fn=location.href}catch(Un){Fn=ht.createElement("a"),Fn.href="",Fn=Fn.href}qn=Wn.exec(Fn.toLowerCase())||[],it.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Fn,type:"GET",isLocal:Bn.test(qn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Xn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":it.parseJSON,"text xml":it.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?I(I(e,it.ajaxSettings),t):I(it.ajaxSettings,e)},ajaxPrefilter:B($n),ajaxTransport:B(zn),ajax:function(e,t){function n(e,t,n,r){var i,c,v,y,x,T=t;2!==b&&(b=2,s&&clearTimeout(s),u=void 0,a=r||"",w.readyState=e>0?4:0,i=e>=200&&300>e||304===e,n&&(y=W(d,w,n)),y=$(d,y,w,i),i?(d.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(it.lastModified[o]=x),x=w.getResponseHeader("etag"),x&&(it.etag[o]=x)),204===e||"HEAD"===d.type?T="nocontent":304===e?T="notmodified":(T=y.state,c=y.data,v=y.error,i=!v)):(v=T,(e||!T)&&(T="error",0>e&&(e=0))),w.status=e,w.statusText=(t||T)+"",i?h.resolveWith(f,[c,T,w]):h.rejectWith(f,[w,T,v]),w.statusCode(g),g=void 0,l&&p.trigger(i?"ajaxSuccess":"ajaxError",[w,d,i?c:v]),m.fireWith(f,[w,T]),l&&(p.trigger("ajaxComplete",[w,d]),--it.active||it.event.trigger("ajaxStop")))}"object"==typeof e&&(t=e,e=void 0),t=t||{};var r,i,o,a,s,l,u,c,d=it.ajaxSetup({},t),f=d.context||d,p=d.context&&(f.nodeType||f.jquery)?it(f):it.event,h=it.Deferred(),m=it.Callbacks("once memory"),g=d.statusCode||{},v={},y={},b=0,x="canceled",w={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c)for(c={};t=Rn.exec(a);)c[t[1].toLowerCase()]=t[2];t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=y[n]=y[n]||e,v[e]=t),this},overrideMimeType:function(e){return b||(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)g[t]=[g[t],e[t]];else w.always(e[w.status]);return this},abort:function(e){var t=e||x;return u&&u.abort(t),n(0,t),this}};if(h.promise(w).complete=m.add,w.success=w.done,w.error=w.fail,d.url=((e||d.url||Fn)+"").replace(Mn,"").replace(In,qn[1]+"//"),d.type=t.method||t.type||d.method||d.type,d.dataTypes=it.trim(d.dataType||"*").toLowerCase().match(bt)||[""],null==d.crossDomain&&(r=Wn.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]===qn[1]&&r[2]===qn[2]&&(r[3]||("http:"===r[1]?"80":"443"))===(qn[3]||("http:"===qn[1]?"80":"443")))),d.data&&d.processData&&"string"!=typeof d.data&&(d.data=it.param(d.data,d.traditional)),P($n,d,t,w),2===b)return w;l=d.global,l&&0===it.active++&&it.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!Pn.test(d.type),o=d.url,d.hasContent||(d.data&&(o=d.url+=(Hn.test(o)?"&":"?")+d.data,delete d.data),d.cache===!1&&(d.url=On.test(o)?o.replace(On,"$1_="+Ln++):o+(Hn.test(o)?"&":"?")+"_="+Ln++)),d.ifModified&&(it.lastModified[o]&&w.setRequestHeader("If-Modified-Since",it.lastModified[o]),it.etag[o]&&w.setRequestHeader("If-None-Match",it.etag[o])),(d.data&&d.hasContent&&d.contentType!==!1||t.contentType)&&w.setRequestHeader("Content-Type",d.contentType),w.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+Xn+"; q=0.01":""):d.accepts["*"]);for(i in d.headers)w.setRequestHeader(i,d.headers[i]);if(d.beforeSend&&(d.beforeSend.call(f,w,d)===!1||2===b))return w.abort();x="abort";for(i in{success:1,error:1,complete:1})w[i](d[i]);if(u=P(zn,d,t,w)){w.readyState=1,l&&p.trigger("ajaxSend",[w,d]),d.async&&d.timeout>0&&(s=setTimeout(function(){w.abort("timeout")},d.timeout));try{b=1,u.send(v,n)}catch(T){if(!(2>b))throw T;n(-1,T)}}else n(-1,"No Transport");return w},getJSON:function(e,t,n){return it.get(e,t,n,"json")},getScript:function(e,t){return it.get(e,void 0,t,"script")}}),it.each(["get","post"],function(e,t){it[t]=function(e,n,r,i){return it.isFunction(n)&&(i=i||r,r=n,n=void 0),it.ajax({url:e,type:t,dataType:i,data:n,success:r})}}),it.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){it.fn[t]=function(e){return this.on(t,e)}}),it._evalUrl=function(e){return it.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},it.fn.extend({wrapAll:function(e){if(it.isFunction(e))return this.each(function(t){it(this).wrapAll(e.call(this,t))});if(this[0]){var t=it(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstChild&&1===e.firstChild.nodeType;)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return this.each(it.isFunction(e)?function(t){it(this).wrapInner(e.call(this,t))}:function(){var t=it(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=it.isFunction(e);return this.each(function(n){it(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){it.nodeName(this,"body")||it(this).replaceWith(this.childNodes)}).end()}}),it.expr.filters.hidden=function(e){return e.offsetWidth<=0&&e.offsetHeight<=0||!nt.reliableHiddenOffsets()&&"none"===(e.style&&e.style.display||it.css(e,"display"))},it.expr.filters.visible=function(e){return!it.expr.filters.hidden(e)};var Vn=/%20/g,Gn=/\[\]$/,Yn=/\r?\n/g,Jn=/^(?:submit|button|image|reset|file)$/i,Kn=/^(?:input|select|textarea|keygen)/i;it.param=function(e,t){var n,r=[],i=function(e,t){t=it.isFunction(t)?t():null==t?"":t,r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(void 0===t&&(t=it.ajaxSettings&&it.ajaxSettings.traditional),it.isArray(e)||e.jquery&&!it.isPlainObject(e))it.each(e,function(){i(this.name,this.value)});else for(n in e)z(n,e[n],t,i);return r.join("&").replace(Vn,"+")},it.fn.extend({serialize:function(){return it.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=it.prop(this,"elements");return e?it.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!it(this).is(":disabled")&&Kn.test(this.nodeName)&&!Jn.test(e)&&(this.checked||!Dt.test(e))}).map(function(e,t){var n=it(this).val();return null==n?null:it.isArray(n)?it.map(n,function(e){return{name:t.name,value:e.replace(Yn,"\r\n")}}):{name:t.name,value:n.replace(Yn,"\r\n")}}).get()}}),it.ajaxSettings.xhr=void 0!==e.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&X()||U()}:X;var Qn=0,Zn={},er=it.ajaxSettings.xhr();e.ActiveXObject&&it(e).on("unload",function(){for(var e in Zn)Zn[e](void 0,!0)}),nt.cors=!!er&&"withCredentials"in er,er=nt.ajax=!!er,er&&it.ajaxTransport(function(e){if(!e.crossDomain||nt.cors){var t;return{send:function(n,r){var i,o=e.xhr(),a=++Qn;if(o.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(i in e.xhrFields)o[i]=e.xhrFields[i];e.mimeType&&o.overrideMimeType&&o.overrideMimeType(e.mimeType),e.crossDomain||n["X-Requested-With"]||(n["X-Requested-With"]="XMLHttpRequest");for(i in n)void 0!==n[i]&&o.setRequestHeader(i,n[i]+"");o.send(e.hasContent&&e.data||null),t=function(n,i){var s,l,u;if(t&&(i||4===o.readyState))if(delete Zn[a],t=void 0,o.onreadystatechange=it.noop,i)4!==o.readyState&&o.abort();else{u={},s=o.status,"string"==typeof o.responseText&&(u.text=o.responseText);try{l=o.statusText}catch(c){l=""}s||!e.isLocal||e.crossDomain?1223===s&&(s=204):s=u.text?200:404}u&&r(s,l,u,o.getAllResponseHeaders())},e.async?4===o.readyState?setTimeout(t):o.onreadystatechange=Zn[a]=t:t()},abort:function(){t&&t(void 0,!0)}}}}),it.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return it.globalEval(e),e}}}),it.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),it.ajaxTransport("script",function(e){if(e.crossDomain){var t,n=ht.head||it("head")[0]||ht.documentElement;return{send:function(r,i){t=ht.createElement("script"),t.async=!0,e.scriptCharset&&(t.charset=e.scriptCharset),t.src=e.url,t.onload=t.onreadystatechange=function(e,n){(n||!t.readyState||/loaded|complete/.test(t.readyState))&&(t.onload=t.onreadystatechange=null,t.parentNode&&t.parentNode.removeChild(t),t=null,n||i(200,"success"))},n.insertBefore(t,n.firstChild)},abort:function(){t&&t.onload(void 0,!0)}}}});var tr=[],nr=/(=)\?(?=&|$)|\?\?/;it.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=tr.pop()||it.expando+"_"+Ln++;return this[e]=!0,e}}),it.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=t.jsonp!==!1&&(nr.test(t.url)?"url":"string"==typeof t.data&&!(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&nr.test(t.data)&&"data");return s||"jsonp"===t.dataTypes[0]?(i=t.jsonpCallback=it.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(nr,"$1"+i):t.jsonp!==!1&&(t.url+=(Hn.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||it.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,tr.push(i)),a&&it.isFunction(o)&&o(a[0]),a=o=void 0}),"script"):void 0}),it.parseHTML=function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||ht;var r=dt.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=it.buildFragment([e],t,i),i&&i.length&&it(i).remove(),it.merge([],r.childNodes))};var rr=it.fn.load;it.fn.load=function(e,t,n){if("string"!=typeof e&&rr)return rr.apply(this,arguments);var r,i,o,a=this,s=e.indexOf(" ");return s>=0&&(r=it.trim(e.slice(s,e.length)),e=e.slice(0,s)),it.isFunction(t)?(n=t,t=void 0):t&&"object"==typeof t&&(o="POST"),a.length>0&&it.ajax({url:e,type:o,dataType:"html",data:t}).done(function(e){i=arguments,a.html(r?it("<div>").append(it.parseHTML(e)).find(r):e)}).complete(n&&function(e,t){a.each(n,i||[e.responseText,t,e])}),this},it.expr.filters.animated=function(e){return it.grep(it.timers,function(t){return e===t.elem}).length};var ir=e.document.documentElement;it.offset={setOffset:function(e,t,n){var r,i,o,a,s,l,u,c=it.css(e,"position"),d=it(e),f={};"static"===c&&(e.style.position="relative"),s=d.offset(),o=it.css(e,"top"),l=it.css(e,"left"),u=("absolute"===c||"fixed"===c)&&it.inArray("auto",[o,l])>-1,u?(r=d.position(),a=r.top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(l)||0),it.isFunction(t)&&(t=t.call(e,n,s)),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):d.css(f)}},it.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){it.offset.setOffset(this,e,t)});var t,n,r={top:0,left:0},i=this[0],o=i&&i.ownerDocument;if(o)return t=o.documentElement,it.contains(t,i)?(typeof i.getBoundingClientRect!==Et&&(r=i.getBoundingClientRect()),n=V(o),{top:r.top+(n.pageYOffset||t.scrollTop)-(t.clientTop||0),left:r.left+(n.pageXOffset||t.scrollLeft)-(t.clientLeft||0)}):r},position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===it.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),it.nodeName(e[0],"html")||(n=e.offset()),n.top+=it.css(e[0],"borderTopWidth",!0),n.left+=it.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-it.css(r,"marginTop",!0),left:t.left-n.left-it.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent||ir;e&&!it.nodeName(e,"html")&&"static"===it.css(e,"position");)e=e.offsetParent;return e||ir})}}),it.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n=/Y/.test(t);it.fn[e]=function(r){return At(this,function(e,r,i){var o=V(e);return void 0===i?o?t in o?o[t]:o.document.documentElement[r]:e[r]:void(o?o.scrollTo(n?it(o).scrollLeft():i,n?i:it(o).scrollTop()):e[r]=i)},e,r,arguments.length,null)}}),it.each(["top","left"],function(e,t){it.cssHooks[t]=N(nt.pixelPosition,function(e,n){return n?(n=tn(e,t),rn.test(n)?it(e).position()[t]+"px":n):void 0})}),it.each({Height:"height",Width:"width"},function(e,t){it.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){it.fn[r]=function(r,i){var o=arguments.length&&(n||"boolean"!=typeof r),a=n||(r===!0||i===!0?"margin":"border");return At(this,function(t,n,r){var i;return it.isWindow(t)?t.document.documentElement["client"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body["scroll"+e],i["scroll"+e],t.body["offset"+e],i["offset"+e],i["client"+e])):void 0===r?it.css(t,n,a):it.style(t,n,r,a)},t,o?r:void 0,o,null)}})}),it.fn.size=function(){return this.length},it.fn.andSelf=it.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return it});var or=e.jQuery,ar=e.$;return it.noConflict=function(t){return e.$===it&&(e.$=ar),t&&e.jQuery===it&&(e.jQuery=or),it},typeof t===Et&&(e.jQuery=e.$=it),it}),function(e,t){e.rails!==t&&e.error("jquery-ujs has already been loaded!");var n,r=e(document);e.rails=n={linkClickSelector:"a[data-confirm], a[data-method], a[data-remote], a[data-disable-with], a[data-disable]",buttonClickSelector:"button[data-remote], button[data-confirm]",inputChangeSelector:"select[data-remote], input[data-remote], textarea[data-remote]",formSubmitSelector:"form",formInputClickSelector:"form input[type=submit], form input[type=image], form button[type=submit], form button:not([type])",disableSelector:"input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled",enableSelector:"input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled",requiredInputSelector:"input[name][required]:not([disabled]),textarea[name][required]:not([disabled])",fileInputSelector:"input[type=file]",linkDisableSelector:"a[data-disable-with], a[data-disable]",buttonDisableSelector:"button[data-remote][data-disable-with], button[data-remote][data-disable]",CSRFProtection:function(t){var n=e('meta[name="csrf-token"]').attr("content");n&&t.setRequestHeader("X-CSRF-Token",n)},refreshCSRFTokens:function(){var t=e("meta[name=csrf-token]").attr("content"),n=e("meta[name=csrf-param]").attr("content");e('form input[name="'+n+'"]').val(t)},fire:function(t,n,r){var i=e.Event(n);return t.trigger(i,r),i.result!==!1},confirm:function(e){return confirm(e)},ajax:function(t){return e.ajax(t)},href:function(e){return e.attr("href")},handleRemote:function(r){var i,o,a,s,l,u,c,d;if(n.fire(r,"ajax:before")){if(s=r.data("cross-domain"),l=s===t?null:s,u=r.data("with-credentials")||null,c=r.data("type")||e.ajaxSettings&&e.ajaxSettings.dataType,r.is("form")){i=r.attr("method"),o=r.attr("action"),a=r.serializeArray();var f=r.data("ujs:submit-button");f&&(a.push(f),r.data("ujs:submit-button",null))}else r.is(n.inputChangeSelector)?(i=r.data("method"),o=r.data("url"),a=r.serialize(),r.data("params")&&(a=a+"&"+r.data("params"))):r.is(n.buttonClickSelector)?(i=r.data("method")||"get",o=r.data("url"),a=r.serialize(),r.data("params")&&(a=a+"&"+r.data("params"))):(i=r.data("method"),o=n.href(r),a=r.data("params")||null);return d={type:i||"GET",data:a,dataType:c,beforeSend:function(e,i){return i.dataType===t&&e.setRequestHeader("accept","*/*;q=0.5, "+i.accepts.script),n.fire(r,"ajax:beforeSend",[e,i])?void r.trigger("ajax:send",e):!1
+},success:function(e,t,n){r.trigger("ajax:success",[e,t,n])},complete:function(e,t){r.trigger("ajax:complete",[e,t])},error:function(e,t,n){r.trigger("ajax:error",[e,t,n])},crossDomain:l},u&&(d.xhrFields={withCredentials:u}),o&&(d.url=o),n.ajax(d)}return!1},handleMethod:function(r){var i=n.href(r),o=r.data("method"),a=r.attr("target"),s=e("meta[name=csrf-token]").attr("content"),l=e("meta[name=csrf-param]").attr("content"),u=e('<form method="post" action="'+i+'"></form>'),c='<input name="_method" value="'+o+'" type="hidden" />';l!==t&&s!==t&&(c+='<input name="'+l+'" value="'+s+'" type="hidden" />'),a&&u.attr("target",a),u.hide().append(c).appendTo("body"),u.submit()},formElements:function(t,n){return t.is("form")?e(t[0].elements).filter(n):t.find(n)},disableFormElements:function(t){n.formElements(t,n.disableSelector).each(function(){n.disableFormElement(e(this))})},disableFormElement:function(e){var n,r;n=e.is("button")?"html":"val",r=e.data("disable-with"),e.data("ujs:enable-with",e[n]()),r!==t&&e[n](r),e.prop("disabled",!0)},enableFormElements:function(t){n.formElements(t,n.enableSelector).each(function(){n.enableFormElement(e(this))})},enableFormElement:function(e){var t=e.is("button")?"html":"val";e.data("ujs:enable-with")&&e[t](e.data("ujs:enable-with")),e.prop("disabled",!1)},allowAction:function(e){var t,r=e.data("confirm"),i=!1;return r?(n.fire(e,"confirm")&&(i=n.confirm(r),t=n.fire(e,"confirm:complete",[i])),i&&t):!0},blankInputs:function(t,n,r){var i,o,a=e(),s=n||"input,textarea",l=t.find(s);return l.each(function(){if(i=e(this),o=i.is("input[type=checkbox],input[type=radio]")?i.is(":checked"):i.val(),!o==!r){if(i.is("input[type=radio]")&&l.filter('input[type=radio]:checked[name="'+i.attr("name")+'"]').length)return!0;a=a.add(i)}}),a.length?a:!1},nonBlankInputs:function(e,t){return n.blankInputs(e,t,!0)},stopEverything:function(t){return e(t.target).trigger("ujs:everythingStopped"),t.stopImmediatePropagation(),!1},disableElement:function(e){var r=e.data("disable-with");e.data("ujs:enable-with",e.html()),r!==t&&e.html(r),e.bind("click.railsDisable",function(e){return n.stopEverything(e)})},enableElement:function(e){e.data("ujs:enable-with")!==t&&(e.html(e.data("ujs:enable-with")),e.removeData("ujs:enable-with")),e.unbind("click.railsDisable")}},n.fire(r,"rails:attachBindings")&&(e.ajaxPrefilter(function(e,t,r){e.crossDomain||n.CSRFProtection(r)}),r.delegate(n.linkDisableSelector,"ajax:complete",function(){n.enableElement(e(this))}),r.delegate(n.buttonDisableSelector,"ajax:complete",function(){n.enableFormElement(e(this))}),r.delegate(n.linkClickSelector,"click.rails",function(r){var i=e(this),o=i.data("method"),a=i.data("params"),s=r.metaKey||r.ctrlKey;if(!n.allowAction(i))return n.stopEverything(r);if(!s&&i.is(n.linkDisableSelector)&&n.disableElement(i),i.data("remote")!==t){if(s&&(!o||"GET"===o)&&!a)return!0;var l=n.handleRemote(i);return l===!1?n.enableElement(i):l.error(function(){n.enableElement(i)}),!1}return i.data("method")?(n.handleMethod(i),!1):void 0}),r.delegate(n.buttonClickSelector,"click.rails",function(t){var r=e(this);if(!n.allowAction(r))return n.stopEverything(t);r.is(n.buttonDisableSelector)&&n.disableFormElement(r);var i=n.handleRemote(r);return i===!1?n.enableFormElement(r):i.error(function(){n.enableFormElement(r)}),!1}),r.delegate(n.inputChangeSelector,"change.rails",function(t){var r=e(this);return n.allowAction(r)?(n.handleRemote(r),!1):n.stopEverything(t)}),r.delegate(n.formSubmitSelector,"submit.rails",function(r){var i,o,a=e(this),s=a.data("remote")!==t;if(!n.allowAction(a))return n.stopEverything(r);if(a.attr("novalidate")==t&&(i=n.blankInputs(a,n.requiredInputSelector),i&&n.fire(a,"ajax:aborted:required",[i])))return n.stopEverything(r);if(s){if(o=n.nonBlankInputs(a,n.fileInputSelector)){setTimeout(function(){n.disableFormElements(a)},13);var l=n.fire(a,"ajax:aborted:file",[o]);return l||setTimeout(function(){n.enableFormElements(a)},13),l}return n.handleRemote(a),!1}setTimeout(function(){n.disableFormElements(a)},13)}),r.delegate(n.formInputClickSelector,"click.rails",function(t){var r=e(this);if(!n.allowAction(r))return n.stopEverything(t);var i=r.attr("name"),o=i?{name:i,value:r.val()}:null;r.closest("form").data("ujs:submit-button",o)}),r.delegate(n.formSubmitSelector,"ajax:send.rails",function(t){this==t.target&&n.disableFormElements(e(this))}),r.delegate(n.formSubmitSelector,"ajax:complete.rails",function(t){this==t.target&&n.enableFormElements(e(this))}),e(function(){n.refreshCSRFTokens()}))}(jQuery),function(){var e,t,n,r,i,o,a,s,l,u,c,d,f,p,h,m,g,v,y,b,x,w,T,E,k,C,N,S,j,A,D,L,H,_,q,F,M,O,R,B,P,I,W,$,z,X,U,V,G,Y=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1},J={}.hasOwnProperty,K=function(e,t){function n(){this.constructor=e}for(var r in t)J.call(t,r)&&(e[r]=t[r]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},Q=[].slice;j={},d=10,$=!1,m=null,S=null,q=null,h=null,V=null,b=function(e){var t;return e=new n(e),B(),c(),F(e),$&&(t=z(e.absolute))?(x(t),w(e)):w(e,W)},z=function(e){var t;return t=j[e],t&&!t.transitionCacheDisabled?t:void 0},g=function(e){return null==e&&(e=!0),$=e},w=function(e,t){return null==t&&(t=function(){return function(){}}(this)),X("page:fetch",{url:e.absolute}),null!=V&&V.abort(),V=new XMLHttpRequest,V.open("GET",e.withoutHashForIE10compatibility(),!0),V.setRequestHeader("Accept","text/html, application/xhtml+xml, application/xml"),V.setRequestHeader("X-XHR-Referer",q),V.onload=function(){var n;return X("page:receive"),(n=H())?(f.apply(null,y(n)),M(),t(),X("page:load")):document.location.href=e.absolute},V.onloadend=function(){return V=null},V.onerror=function(){return document.location.href=e.absolute},V.send()},x=function(e){return null!=V&&V.abort(),f(e.title,e.body),_(e),X("page:restore")},c=function(){var e;return e=new n(m.url),j[e.absolute]={url:e.relative,body:document.body,title:document.title,positionY:window.pageYOffset,positionX:window.pageXOffset,cachedAt:(new Date).getTime(),transitionCacheDisabled:null!=document.querySelector("[data-no-transition-cache]")},p(d)},D=function(e){return null==e&&(e=d),/^[\d]+$/.test(e)?d=parseInt(e):void 0},p=function(e){var t,n,r,i,o,a;for(r=Object.keys(j),t=r.map(function(e){return j[e].cachedAt}).sort(function(e,t){return t-e}),a=[],i=0,o=r.length;o>i;i++)n=r[i],j[n].cachedAt<=t[e]&&(X("page:expire",j[n]),a.push(delete j[n]));return a},f=function(t,n,r,i){return document.title=t,document.documentElement.replaceChild(n,document.body),null!=r&&e.update(r),i&&v(),m=window.history.state,X("page:change"),X("page:update")},v=function(){var e,t,n,r,i,o,a,s,l,u,c,d;for(o=Array.prototype.slice.call(document.body.querySelectorAll('script:not([data-turbolinks-eval="false"])')),a=0,l=o.length;l>a;a++)if(i=o[a],""===(c=i.type)||"text/javascript"===c){for(t=document.createElement("script"),d=i.attributes,s=0,u=d.length;u>s;s++)e=d[s],t.setAttribute(e.name,e.value);t.appendChild(document.createTextNode(i.innerHTML)),r=i.parentNode,n=i.nextSibling,r.removeChild(i),r.insertBefore(t,n)}},P=function(e){return e.innerHTML=e.innerHTML.replace(/<noscript[\S\s]*?<\/noscript>/gi,""),e},F=function(e){return(e=new n(e)).absolute!==q?window.history.pushState({turbolinks:!0,url:e.absolute},"",e.absolute):void 0},M=function(){var e,t;return(e=V.getResponseHeader("X-XHR-Redirected-To"))?(e=new n(e),t=e.hasNoHash()?document.location.hash:"",window.history.replaceState(m,"",e.href+t)):void 0},B=function(){return q=document.location.href},R=function(){return window.history.replaceState({turbolinks:!0,url:document.location.href},"",document.location.href)},O=function(){return m=window.history.state},_=function(e){return window.scrollTo(e.positionX,e.positionY)},W=function(){return document.location.hash?document.location.href=document.location.href:window.scrollTo(0,0)},L=function(e){var t,n;return t=(null!=(n=document.cookie.match(new RegExp(e+"=(\\w+)")))?n[1].toUpperCase():void 0)||"",document.cookie=e+"=; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/",t},X=function(e,t){var n;return n=document.createEvent("Events"),t&&(n.data=t),n.initEvent(e,!0,!0),document.dispatchEvent(n)},A=function(){return!X("page:before-change")},H=function(){var e,t,n,r,i,o;return t=function(){var e;return 400<=(e=V.status)&&600>e},o=function(){return V.getResponseHeader("Content-Type").match(/^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/)},r=function(e){var t,n,r,i,o;for(i=e.head.childNodes,o=[],n=0,r=i.length;r>n;n++)t=i[n],null!=("function"==typeof t.getAttribute?t.getAttribute("data-turbolinks-track"):void 0)&&o.push(t.getAttribute("src")||t.getAttribute("href"));return o},e=function(e){var t;return S||(S=r(document)),t=r(e),t.length!==S.length||i(t,S).length!==S.length},i=function(e,t){var n,r,i,o,a;for(e.length>t.length&&(o=[t,e],e=o[0],t=o[1]),a=[],r=0,i=e.length;i>r;r++)n=e[r],Y.call(t,n)>=0&&a.push(n);return a},!t()&&o()&&(n=h(V.responseText),n&&!e(n))?n:void 0},y=function(t){var n;return n=t.querySelector("title"),[null!=n?n.textContent:void 0,P(t.body),e.get(t).token,"runScripts"]},e={get:function(e){var t;return null==e&&(e=document),{node:t=e.querySelector('meta[name="csrf-token"]'),token:null!=t&&"function"==typeof t.getAttribute?t.getAttribute("content"):void 0}},update:function(e){var t;return t=this.get(),null!=t.token&&null!=e&&t.token!==e?t.node.setAttribute("content",e):void 0}},i=function(){var e,t,n,r,i,o;t=function(e){return(new DOMParser).parseFromString(e,"text/html")},e=function(e){var t;return t=document.implementation.createHTMLDocument(""),t.documentElement.innerHTML=e,t},n=function(e){var t;return t=document.implementation.createHTMLDocument(""),t.open("replace"),t.write(e),t.close(),t};try{if(window.DOMParser)return i=t("<html><body><p>test"),t}catch(a){return r=a,i=e("<html><body><p>test"),e}finally{if(1!==(null!=i&&null!=(o=i.body)?o.childNodes.length:void 0))return n}},n=function(){function e(t){return this.original=null!=t?t:document.location.href,this.original.constructor===e?this.original:void this._parse()}return e.prototype.withoutHash=function(){return this.href.replace(this.hash,"")},e.prototype.withoutHashForIE10compatibility=function(){return this.withoutHash()},e.prototype.hasNoHash=function(){return 0===this.hash.length},e.prototype._parse=function(){var e;return(null!=this.link?this.link:this.link=document.createElement("a")).href=this.original,e=this.link,this.href=e.href,this.protocol=e.protocol,this.host=e.host,this.hostname=e.hostname,this.port=e.port,this.pathname=e.pathname,this.search=e.search,this.hash=e.hash,this.origin=[this.protocol,"//",this.hostname].join(""),0!==this.port.length&&(this.origin+=":"+this.port),this.relative=[this.pathname,this.search,this.hash].join(""),this.absolute=this.href},e}(),r=function(e){function t(e){return this.link=e,this.link.constructor===t?this.link:(this.original=this.link.href,void t.__super__.constructor.apply(this,arguments))}return K(t,e),t.HTML_EXTENSIONS=["html"],t.allowExtensions=function(){var e,n,r,i;for(n=1<=arguments.length?Q.call(arguments,0):[],r=0,i=n.length;i>r;r++)e=n[r],t.HTML_EXTENSIONS.push(e);return t.HTML_EXTENSIONS},t.prototype.shouldIgnore=function(){return this._crossOrigin()||this._anchored()||this._nonHtml()||this._optOut()||this._target()},t.prototype._crossOrigin=function(){return this.origin!==(new n).origin},t.prototype._anchored=function(){var e;return(this.hash&&this.withoutHash())===(e=new n).withoutHash()||this.href===e.href+"#"},t.prototype._nonHtml=function(){return this.pathname.match(/\.[a-z]+$/g)&&!this.pathname.match(new RegExp("\\.(?:"+t.HTML_EXTENSIONS.join("|")+")?$","g"))},t.prototype._optOut=function(){var e,t;for(t=this.link;!e&&t!==document;)e=null!=t.getAttribute("data-no-turbolink"),t=t.parentNode;return e},t.prototype._target=function(){return 0!==this.link.target.length},t}(n),t=function(){function e(e){this.event=e,this.event.defaultPrevented||(this._extractLink(),this._validForTurbolinks()&&(A()||U(this.link.href),this.event.preventDefault()))}return e.installHandlerLast=function(t){return t.defaultPrevented?void 0:(document.removeEventListener("click",e.handle,!1),document.addEventListener("click",e.handle,!1))},e.handle=function(t){return new e(t)},e.prototype._extractLink=function(){var e;for(e=this.event.target;e.parentNode&&"A"!==e.nodeName;)e=e.parentNode;return"A"===e.nodeName&&0!==e.href.length?this.link=new r(e):void 0},e.prototype._validForTurbolinks=function(){return null!=this.link&&!(this.link.shouldIgnore()||this._nonStandardClick())},e.prototype._nonStandardClick=function(){return this.event.which>1||this.event.metaKey||this.event.ctrlKey||this.event.shiftKey||this.event.altKey},e}(),u=function(e){return setTimeout(e,500)},k=function(){return document.addEventListener("DOMContentLoaded",function(){return X("page:change"),X("page:update")},!0)},N=function(){return"undefined"!=typeof jQuery?jQuery(document).on("ajaxSuccess",function(e,t){return jQuery.trim(t.responseText)?X("page:update"):void 0}):void 0},C=function(e){var t,r;return(null!=(r=e.state)?r.turbolinks:void 0)?(t=j[new n(e.state.url).absolute])?(c(),x(t)):U(e.target.location.href):void 0},E=function(){return R(),O(),h=i(),document.addEventListener("click",t.installHandlerLast,!0),u(function(){return window.addEventListener("popstate",C,!1)})},T=void 0!==window.history.state||navigator.userAgent.match(/Firefox\/2[6|7]/),s=window.history&&window.history.pushState&&window.history.replaceState&&T,o=!navigator.userAgent.match(/CriOS\//),I="GET"===(G=L("request_method"))||""===G,l=s&&o&&I,a=document.addEventListener&&document.createEvent,a&&(k(),N()),l?(U=b,E()):U=function(e){return document.location.href=e},this.Turbolinks={visit:U,pagesCached:D,enableTransitionCache:g,allowLinkExtensions:r.allowExtensions,supported:l}}.call(this),function(){}.call(this); \ No newline at end of file
diff --git a/actionpack/test/fixtures/公共/gzip/application-a71b3024f80aea3181c09774ca17e712.js.gz b/actionpack/test/fixtures/公共/gzip/application-a71b3024f80aea3181c09774ca17e712.js.gz
new file mode 100644
index 0000000000..f62c656dc8
--- /dev/null
+++ b/actionpack/test/fixtures/公共/gzip/application-a71b3024f80aea3181c09774ca17e712.js.gz
Binary files differ
diff --git a/actionpack/test/journey/router_test.rb b/actionpack/test/journey/router_test.rb
index 2e7e8e1bea..8e90d4100f 100644
--- a/actionpack/test/journey/router_test.rb
+++ b/actionpack/test/journey/router_test.rb
@@ -503,6 +503,25 @@ module ActionDispatch
assert called
end
+ def test_recognize_head_route
+ path = Path::Pattern.from_string "/books(/:action(.:format))"
+ app = Object.new
+ conditions = { request_method: 'HEAD' }
+ @router.routes.add_route(app, path, conditions, {})
+
+ env = rails_env(
+ 'PATH_INFO' => '/books/list.rss',
+ 'REQUEST_METHOD' => 'HEAD'
+ )
+
+ called = false
+ @router.recognize(env) do |r, params|
+ called = true
+ end
+
+ assert called
+ end
+
def test_recognize_head_request_as_get_route
path = Path::Pattern.from_string "/books(/:action(.:format))"
app = Object.new
@@ -525,19 +544,24 @@ module ActionDispatch
def test_recognize_cares_about_verbs
path = Path::Pattern.from_string "/books(/:action(.:format))"
app = Object.new
- conditions = {
- :request_method => 'GET'
- }
+ conditions = { request_method: 'GET' }
@router.routes.add_route(app, path, conditions, {})
+ env = rails_env 'PATH_INFO' => '/books/list.rss',
+ "REQUEST_METHOD" => "POST"
+
+ called = false
+ @router.recognize(env) do |r, params|
+ called = true
+ end
+
+ assert_not called
+
conditions = conditions.dup
conditions[:request_method] = 'POST'
post = @router.routes.add_route(app, path, conditions, {})
- env = rails_env 'PATH_INFO' => '/books/list.rss',
- "REQUEST_METHOD" => "POST"
-
called = false
@router.recognize(env) do |r, params|
assert_equal post, r
@@ -561,7 +585,7 @@ module ActionDispatch
end
def rails_env env, klass = ActionDispatch::Request
- klass.new env
+ klass.new(rack_env(env))
end
def rack_env env
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 552a902349..3fc2ab178c 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,9 +1,3 @@
-* Add I18n support for input/textarea placeholder text.
-
- Placeholder I18n follows the same convention as `label` I18n.
-
- *Alex Robbin*
-
* Fix that render layout: 'messages/layout' should also be added to the dependency tracker tree.
*DHH*
diff --git a/actionview/actionview.gemspec b/actionview/actionview.gemspec
index 1ea00cff22..565c22e1e8 100644
--- a/actionview/actionview.gemspec
+++ b/actionview/actionview.gemspec
@@ -23,7 +23,8 @@ Gem::Specification.new do |s|
s.add_dependency 'builder', '~> 3.1'
s.add_dependency 'erubis', '~> 2.7.0'
- s.add_dependency 'rails-deprecated_sanitizer'
+ s.add_dependency 'rails-deprecated_sanitizer', '~> 1.0', '>= 1.0.2'
+ s.add_dependency 'rails-dom-testing', '~> 1.0', '>= 1.0.2'
s.add_development_dependency 'actionpack', version
s.add_development_dependency 'activemodel', version
diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb
index 669050e7a7..b7fdc16a9d 100644
--- a/actionview/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb
@@ -218,7 +218,7 @@ module ActionView
tag("img", options)
end
- # Returns a string suitable for an html image tag alt attribute.
+ # Returns a string suitable for an HTML image tag alt attribute.
# The +src+ argument is meant to be an image file path.
# The method removes the basename of the file path and the digest,
# if any. It also removes hyphens and underscores from file names and
@@ -239,7 +239,7 @@ module ActionView
File.basename(src, '.*').sub(/-[[:xdigit:]]{32}\z/, '').tr('-_', ' ').capitalize
end
- # Returns an html video tag for the +sources+. If +sources+ is a string,
+ # Returns an HTML video tag for the +sources+. If +sources+ is a string,
# a single video tag will be returned. If +sources+ is an array, a video
# tag with nested source tags for each source will be returned. The
# +sources+ can be full paths or files that exists in your public videos
diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb
index 27c7a26098..9272bb5c10 100644
--- a/actionview/lib/action_view/helpers/date_helper.rb
+++ b/actionview/lib/action_view/helpers/date_helper.rb
@@ -330,7 +330,7 @@ module ActionView
Tags::DatetimeSelect.new(object_name, method, self, options, html_options).render
end
- # Returns a set of html select-tags (one for year, month, day, hour, minute, and second) pre-selected with the
+ # Returns a set of HTML select-tags (one for year, month, day, hour, minute, and second) pre-selected with the
# +datetime+. It's also possible to explicitly set the order of the tags using the <tt>:order</tt> option with
# an array of symbols <tt>:year</tt>, <tt>:month</tt> and <tt>:day</tt> in the desired order. If you do not
# supply a Symbol, it will be appended onto the <tt>:order</tt> passed in. You can also add
@@ -379,7 +379,7 @@ module ActionView
DateTimeSelector.new(datetime, options, html_options).select_datetime
end
- # Returns a set of html select-tags (one for year, month, and day) pre-selected with the +date+.
+ # Returns a set of HTML select-tags (one for year, month, and day) pre-selected with the +date+.
# It's possible to explicitly set the order of the tags using the <tt>:order</tt> option with an array of
# symbols <tt>:year</tt>, <tt>:month</tt> and <tt>:day</tt> in the desired order.
# If the array passed to the <tt>:order</tt> option does not contain all the three symbols, all tags will be hidden.
@@ -418,7 +418,7 @@ module ActionView
DateTimeSelector.new(date, options, html_options).select_date
end
- # Returns a set of html select-tags (one for hour and minute).
+ # Returns a set of HTML select-tags (one for hour and minute).
# You can set <tt>:time_separator</tt> key to format the output, and
# the <tt>:include_seconds</tt> option to include an input for seconds.
#
@@ -635,7 +635,7 @@ module ActionView
DateTimeSelector.new(date, options, html_options).select_year
end
- # Returns an html time tag for the given date or time.
+ # Returns an HTML time tag for the given date or time.
#
# time_tag Date.today # =>
# <time datetime="2010-11-04">November 04, 2010</time>
@@ -914,7 +914,7 @@ module ActionView
build_select(type, build_options(selected, options))
end
- # Build select option html from date value and options.
+ # Build select option HTML from date value and options.
# build_options(15, start: 1, end: 31)
# => "<option value="1">1</option>
# <option value="2">2</option>
@@ -954,7 +954,7 @@ module ActionView
(select_options.join("\n") + "\n").html_safe
end
- # Builds select tag from date type and html select options.
+ # Builds select tag from date type and HTML select options.
# build_select(:month, "<option value="1">January</option>...")
# => "<select id="post_written_on_2i" name="post[written_on(2i)]">
# <option value="1">January</option>...
diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb
index 0582cb3e12..09843ca70d 100644
--- a/actionview/lib/action_view/helpers/form_helper.rb
+++ b/actionview/lib/action_view/helpers/form_helper.rb
@@ -142,7 +142,7 @@ module ActionView
# will get expanded to
#
# <%= text_field :person, :first_name %>
- # which results in an html <tt><input></tt> tag whose +name+ attribute is
+ # which results in an HTML <tt><input></tt> tag whose +name+ attribute is
# <tt>person[first_name]</tt>. This means that when the form is submitted,
# the value entered by the user will be available in the controller as
# <tt>params[:person][:first_name]</tt>.
diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb
index 8ade7c6a74..83b07a00d4 100644
--- a/actionview/lib/action_view/helpers/form_options_helper.rb
+++ b/actionview/lib/action_view/helpers/form_options_helper.rb
@@ -314,7 +314,7 @@ module ActionView
# # => <option>MasterCard</option>
# # => <option selected="selected">Discover</option>
#
- # You can optionally provide html attributes as the last element of the array.
+ # You can optionally provide HTML attributes as the last element of the array.
#
# options_for_select([ "Denmark", ["USA", {class: 'bold'}], "Sweden" ], ["USA", "Sweden"])
# # => <option value="Denmark">Denmark</option>
@@ -633,7 +633,7 @@ module ActionView
# even use the label as wrapper, as in the example above.
#
# The builder methods <tt>label</tt> and <tt>radio_button</tt> also accept
- # extra html options:
+ # extra HTML options:
# collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial) do |b|
# b.label(class: "radio_button") { b.radio_button(class: "radio_button") }
# end
@@ -696,7 +696,7 @@ module ActionView
# use the label as wrapper, as in the example above.
#
# The builder methods <tt>label</tt> and <tt>check_box</tt> also accept
- # extra html options:
+ # extra HTML options:
# collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
# b.label(class: "check_box") { b.check_box(class: "check_box") }
# end
diff --git a/actionview/lib/action_view/helpers/output_safety_helper.rb b/actionview/lib/action_view/helpers/output_safety_helper.rb
index f03362d0f5..1c2a400245 100644
--- a/actionview/lib/action_view/helpers/output_safety_helper.rb
+++ b/actionview/lib/action_view/helpers/output_safety_helper.rb
@@ -17,10 +17,10 @@ module ActionView #:nodoc:
stringish.to_s.html_safe
end
- # This method returns an html safe string similar to what <tt>Array#join</tt>
+ # This method returns an HTML safe string similar to what <tt>Array#join</tt>
# would return. The array is flattened, and all items, including
- # the supplied separator, are html escaped unless they are html
- # safe, and the returned string is marked as html safe.
+ # the supplied separator, are HTML escaped unless they are HTML
+ # safe, and the returned string is marked as HTML safe.
#
# safe_join(["<p>foo</p>".html_safe, "<p>bar</p>"], "<br />")
# # => "<p>foo</p>&lt;br /&gt;&lt;p&gt;bar&lt;/p&gt;"
diff --git a/actionview/lib/action_view/helpers/rendering_helper.rb b/actionview/lib/action_view/helpers/rendering_helper.rb
index 6cd6e858dd..e11670e00d 100644
--- a/actionview/lib/action_view/helpers/rendering_helper.rb
+++ b/actionview/lib/action_view/helpers/rendering_helper.rb
@@ -14,8 +14,8 @@ module ActionView
# * <tt>:text</tt> - Renders the text passed in out.
# * <tt>:plain</tt> - Renders the text passed in out. Setting the content
# type as <tt>text/plain</tt>.
- # * <tt>:html</tt> - Renders the html safe string passed in out, otherwise
- # performs html escape on the string first. Setting the content type as
+ # * <tt>:html</tt> - Renders the HTML safe string passed in out, otherwise
+ # performs HTML escape on the string first. Setting the content type as
# <tt>text/html</tt>.
# * <tt>:body</tt> - Renders the text passed in, and inherits the content
# type of <tt>text/html</tt> from <tt>ActionDispatch::Response</tt>
diff --git a/actionview/lib/action_view/helpers/sanitize_helper.rb b/actionview/lib/action_view/helpers/sanitize_helper.rb
index 153c64d691..dfbc52e3ac 100644
--- a/actionview/lib/action_view/helpers/sanitize_helper.rb
+++ b/actionview/lib/action_view/helpers/sanitize_helper.rb
@@ -9,7 +9,7 @@ module ActionView
# These helper methods extend Action View making them callable within your template files.
module SanitizeHelper
extend ActiveSupport::Concern
- # This +sanitize+ helper will html encode all tags and strip all attributes that
+ # This +sanitize+ helper will HTML encode all tags and strip all attributes that
# aren't specifically allowed.
#
# It also strips href/src tags with invalid protocols, like javascript: especially.
diff --git a/actionview/lib/action_view/helpers/tags/placeholderable.rb b/actionview/lib/action_view/helpers/tags/placeholderable.rb
deleted file mode 100644
index 313aa725c9..0000000000
--- a/actionview/lib/action_view/helpers/tags/placeholderable.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-module ActionView
- module Helpers
- module Tags # :nodoc:
- module Placeholderable # :nodoc:
- def initialize(*)
- super
-
- if tag_value = @options[:placeholder]
- object_name = @object_name.gsub(/\[(.*)_attributes\]\[\d+\]/, '.\1')
- method_and_value = tag_value.is_a?(TrueClass) ? @method_name : "#{@method_name}.#{tag_value}"
-
- if object.respond_to?(:to_model)
- key = object.class.model_name.i18n_key
- i18n_default = ["#{key}.#{method_and_value}".to_sym, ""]
- end
-
- i18n_default ||= ""
- placeholder = I18n.t("#{object_name}.#{method_and_value}", :default => i18n_default, :scope => "helpers.placeholder").presence
-
- placeholder ||= if object && object.class.respond_to?(:human_attribute_name)
- object.class.human_attribute_name(method_and_value)
- end
-
- placeholder ||= @method_name.humanize
-
- @options[:placeholder] = placeholder
- end
- end
- end
- end
- end
-end
diff --git a/actionview/lib/action_view/helpers/tags/text_area.rb b/actionview/lib/action_view/helpers/tags/text_area.rb
index 69038c1498..9ee83ee7c2 100644
--- a/actionview/lib/action_view/helpers/tags/text_area.rb
+++ b/actionview/lib/action_view/helpers/tags/text_area.rb
@@ -1,11 +1,7 @@
-require 'action_view/helpers/tags/placeholderable'
-
module ActionView
module Helpers
module Tags # :nodoc:
class TextArea < Base # :nodoc:
- include Placeholderable
-
def render
options = @options.stringify_keys
add_default_name_and_id(options)
diff --git a/actionview/lib/action_view/helpers/tags/text_field.rb b/actionview/lib/action_view/helpers/tags/text_field.rb
index 5c576a20ca..e0b80d81c2 100644
--- a/actionview/lib/action_view/helpers/tags/text_field.rb
+++ b/actionview/lib/action_view/helpers/tags/text_field.rb
@@ -1,11 +1,7 @@
-require 'action_view/helpers/tags/placeholderable'
-
module ActionView
module Helpers
module Tags # :nodoc:
class TextField < Base # :nodoc:
- include Placeholderable
-
def render
options = @options.stringify_keys
options["size"] = options["maxlength"] unless options.key?("size")
diff --git a/actionview/test/activerecord/controller_runtime_test.rb b/actionview/test/activerecord/controller_runtime_test.rb
index b5bfcf12a3..469adff39a 100644
--- a/actionview/test/activerecord/controller_runtime_test.rb
+++ b/actionview/test/activerecord/controller_runtime_test.rb
@@ -18,7 +18,7 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase
def create
ActiveRecord::LogSubscriber.runtime += 100
- project = Project.last
+ Project.last
redirect_to "/"
end
diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb
index d944214961..a9f137aec6 100644
--- a/actionview/test/template/form_helper_test.rb
+++ b/actionview/test/template/form_helper_test.rb
@@ -59,35 +59,6 @@ class FormHelperTest < ActionView::TestCase
}
}
- I18n.backend.store_translations 'placeholder', {
- activemodel: {
- attributes: {
- post: {
- cost: "Total cost"
- },
- :"post/cost" => {
- uk: "Pounds"
- }
- }
- },
- helpers: {
- placeholder: {
- post: {
- title: "What is this about?",
- written_on: {
- spanish: "Escrito en"
- },
- comments: {
- body: "Write body here"
- }
- },
- tag: {
- value: "Tag"
- }
- }
- }
- }
-
@post = Post.new
@comment = Comment.new
def @post.errors()
@@ -326,68 +297,6 @@ class FormHelperTest < ActionView::TestCase
)
end
- def test_text_field_placeholder_without_locales
- with_locale :placeholder do
- assert_dom_equal('<input id="post_body" name="post[body]" placeholder="Body" type="text" value="Back to the hill and over it again!" />', text_field(:post, :body, placeholder: true))
- end
- end
-
- def test_text_field_placeholder_with_locales
- with_locale :placeholder do
- assert_dom_equal('<input id="post_title" name="post[title]" placeholder="What is this about?" type="text" value="Hello World" />', text_field(:post, :title, placeholder: true))
- end
- end
-
- def test_text_field_placeholder_with_human_attribute_name
- with_locale :placeholder do
- assert_dom_equal('<input id="post_cost" name="post[cost]" placeholder="Total cost" type="text" />', text_field(:post, :cost, placeholder: true))
- end
- end
-
- def test_text_field_placeholder_with_human_attribute_name_and_value
- with_locale :placeholder do
- assert_dom_equal('<input id="post_cost" name="post[cost]" placeholder="Pounds" type="text" />', text_field(:post, :cost, placeholder: "uk"))
- end
- end
-
- def test_text_field_placeholder_with_locales_and_value
- with_locale :placeholder do
- assert_dom_equal('<input id="post_written_on" name="post[written_on]" placeholder="Escrito en" type="text" value="2004-06-15" />', text_field(:post, :written_on, placeholder: "spanish"))
- end
- end
-
- def test_text_field_placeholder_with_locales_and_nested_attributes
- with_locale :placeholder do
- form_for(@post, html: { id: 'create-post' }) do |f|
- f.fields_for(:comments) do |cf|
- concat cf.text_field(:body, placeholder: true)
- end
- end
-
- expected = whole_form("/posts/123", "create-post", "edit_post", method: "patch") do
- '<input id="post_comments_attributes_0_body" name="post[comments_attributes][0][body]" placeholder="Write body here" type="text" />'
- end
-
- assert_dom_equal expected, output_buffer
- end
- end
-
- def test_text_field_placeholder_with_locales_fallback_and_nested_attributes
- with_locale :placeholder do
- form_for(@post, html: { id: 'create-post' }) do |f|
- f.fields_for(:tags) do |cf|
- concat cf.text_field(:value, placeholder: true)
- end
- end
-
- expected = whole_form("/posts/123", "create-post", "edit_post", method: "patch") do
- '<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" placeholder="Tag" type="text" value="new tag" />'
- end
-
- assert_dom_equal expected, output_buffer
- end
- end
-
def test_text_field
assert_dom_equal(
'<input id="post_title" name="post[title]" type="text" value="Hello World" />',
@@ -756,83 +665,6 @@ class FormHelperTest < ActionView::TestCase
)
end
- def test_text_area_placeholder_without_locales
- with_locale :placeholder do
- assert_dom_equal(
- %{<textarea id="post_body" name="post[body]" placeholder="Body">\nBack to the hill and over it again!</textarea>},
- text_area(:post, :body, placeholder: true)
- )
- end
- end
-
- def test_text_area_placeholder_with_locales
- with_locale :placeholder do
- assert_dom_equal(
- %{<textarea id="post_title" name="post[title]" placeholder="What is this about?">\nHello World</textarea>},
- text_area(:post, :title, placeholder: true)
- )
- end
- end
-
- def test_text_area_placeholder_with_human_attribute_name
- with_locale :placeholder do
- assert_dom_equal(
- %{<textarea id="post_cost" name="post[cost]" placeholder="Total cost">\n</textarea>},
- text_area(:post, :cost, placeholder: true)
- )
- end
- end
-
- def test_text_area_placeholder_with_human_attribute_name_and_value
- with_locale :placeholder do
- assert_dom_equal(
- %{<textarea id="post_cost" name="post[cost]" placeholder="Pounds">\n</textarea>},
- text_area(:post, :cost, placeholder: "uk")
- )
- end
- end
-
- def test_text_area_placeholder_with_locales_and_value
- with_locale :placeholder do
- assert_dom_equal(
- %{<textarea id="post_written_on" name="post[written_on]" placeholder="Escrito en">\n2004-06-15</textarea>},
- text_area(:post, :written_on, placeholder: "spanish")
- )
- end
- end
-
- def test_text_area_placeholder_with_locales_and_nested_attributes
- with_locale :placeholder do
- form_for(@post, html: { id: 'create-post' }) do |f|
- f.fields_for(:comments) do |cf|
- concat cf.text_area(:body, placeholder: true)
- end
- end
-
- expected = whole_form("/posts/123", "create-post", "edit_post", method: "patch") do
- %{<textarea id="post_comments_attributes_0_body" name="post[comments_attributes][0][body]" placeholder="Write body here">\n</textarea>}
- end
-
- assert_dom_equal expected, output_buffer
- end
- end
-
- def test_text_area_placeholder_with_locales_fallback_and_nested_attributes
- with_locale :placeholder do
- form_for(@post, html: { id: 'create-post' }) do |f|
- f.fields_for(:tags) do |cf|
- concat cf.text_area(:value, placeholder: true)
- end
- end
-
- expected = whole_form("/posts/123", "create-post", "edit_post", method: "patch") do
- %{<textarea id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" placeholder="Tag">\nnew tag</textarea>}
- end
-
- assert_dom_equal expected, output_buffer
- end
- end
-
def test_text_area
assert_dom_equal(
%{<textarea id="post_body" name="post[body]">\nBack to the hill and over it again!</textarea>},
diff --git a/actionview/test/template/sanitize_helper_test.rb b/actionview/test/template/sanitize_helper_test.rb
index e4be21be2c..a27258a870 100644
--- a/actionview/test/template/sanitize_helper_test.rb
+++ b/actionview/test/template/sanitize_helper_test.rb
@@ -18,7 +18,7 @@ class SanitizeHelperTest < ActionView::TestCase
def test_should_sanitize_illegal_style_properties
raw = %(display:block; position:absolute; left:0; top:0; width:100%; height:100%; z-index:1; background-color:black; background-image:url(http://www.ragingplatypus.com/i/cam-full.jpg); background-x:center; background-y:center; background-repeat:repeat;)
- expected = %(display: block; width: 100%; height: 100%; background-color: black; background-x: center; background-y: center;)
+ expected = %(display: block; width: 100%; height: 100%; background-color: black; background-image: ; background-x: center; background-y: center;)
assert_equal expected, sanitize_css(raw)
end
diff --git a/activejob/README.md b/activejob/README.md
index e48070bcfc..1f300fcf62 100644
--- a/activejob/README.md
+++ b/activejob/README.md
@@ -2,7 +2,7 @@
Active Job is a framework for declaring jobs and making them run on a variety
of queueing backends. These jobs can be everything from regularly scheduled
-clean-ups, billing charges, or mailings. Anything that can be chopped up into
+clean-ups, to billing charges, to mailings. Anything that can be chopped up into
small units of work and run in parallel, really.
It also serves as the backend for ActionMailer's #deliver_later functionality
diff --git a/activejob/Rakefile b/activejob/Rakefile
index e661622165..484cd1d0b8 100644
--- a/activejob/Rakefile
+++ b/activejob/Rakefile
@@ -20,6 +20,7 @@ end
task default: :test
ACTIVEJOB_ADAPTERS = %w(inline delayed_job qu que queue_classic resque sidekiq sneakers sucker_punch backburner)
+ACTIVEJOB_ADAPTERS -= %w(queue_classic) if defined?(JRUBY_VERSION)
desc 'Run all adapter tests'
task :test do
diff --git a/activejob/activejob.gemspec b/activejob/activejob.gemspec
index d609bb8fce..c74daa5045 100644
--- a/activejob/activejob.gemspec
+++ b/activejob/activejob.gemspec
@@ -18,5 +18,5 @@ Gem::Specification.new do |s|
s.files = Dir['CHANGELOG.md', 'MIT-LICENSE', 'README.md', 'lib/**/*']
s.require_path = 'lib'
- s.add_dependency 'globalid'
+ s.add_dependency 'globalid', '>= 0.2.3'
end
diff --git a/activejob/lib/active_job/callbacks.rb b/activejob/lib/active_job/callbacks.rb
index af92031bc9..8901fa77f2 100644
--- a/activejob/lib/active_job/callbacks.rb
+++ b/activejob/lib/active_job/callbacks.rb
@@ -3,7 +3,7 @@ require 'active_support/callbacks'
module ActiveJob
# = Active Job Callbacks
#
- # Active Job provides hooks during the lifecycle of a job. Callbacks allows you to trigger
+ # Active Job provides hooks during the lifecycle of a job. Callbacks allow you to trigger
# logic during the lifecycle of a job. Available callbacks:
#
# * <tt>before_enqueue</tt>
diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb
index c166020b28..2545e09845 100644
--- a/activejob/lib/active_job/gem_version.rb
+++ b/activejob/lib/active_job/gem_version.rb
@@ -1,5 +1,5 @@
module ActiveJob
- # Returns the version of the currently loaded ActiveJob as a <tt>Gem::Version</tt>
+ # Returns the version of the currently loaded Active Job as a <tt>Gem::Version</tt>
def self.gem_version
Gem::Version.new VERSION::STRING
end
diff --git a/activejob/lib/active_job/logging.rb b/activejob/lib/active_job/logging.rb
index d9e544acf5..ae098a80f3 100644
--- a/activejob/lib/active_job/logging.rb
+++ b/activejob/lib/active_job/logging.rb
@@ -52,19 +52,19 @@ module ActiveJob
class LogSubscriber < ActiveSupport::LogSubscriber
def enqueue(event)
- info "Enqueued #{event.payload[:job].name} (Job ID: #{event.payload[:job_id]}) to #{queue_name(event)}" + args_info(event)
+ info { "Enqueued #{event.payload[:job].name} (Job ID: #{event.payload[:job_id]}) to #{queue_name(event)}" + args_info(event) }
end
def enqueue_at(event)
- info "Enqueued #{event.payload[:job].name} (Job ID: #{event.payload[:job_id]}) to #{queue_name(event)} at #{enqueued_at(event)}" + args_info(event)
+ info { "Enqueued #{event.payload[:job].name} (Job ID: #{event.payload[:job_id]}) to #{queue_name(event)} at #{enqueued_at(event)}" + args_info(event) }
end
def perform_start(event)
- info "Performing #{event.payload[:job].name} from #{queue_name(event)}" + args_info(event)
+ info { "Performing #{event.payload[:job].name} from #{queue_name(event)}" + args_info(event) }
end
def perform(event)
- info "Performed #{event.payload[:job].name} from #{queue_name(event)} in #{event.duration.round(2).to_s}ms"
+ info { "Performed #{event.payload[:job].name} from #{queue_name(event)} in #{event.duration.round(2).to_s}ms" }
end
private
diff --git a/activejob/lib/active_job/queue_adapters/backburner_adapter.rb b/activejob/lib/active_job/queue_adapters/backburner_adapter.rb
index 7a6032e56b..6fe2d4eb53 100644
--- a/activejob/lib/active_job/queue_adapters/backburner_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/backburner_adapter.rb
@@ -16,7 +16,7 @@ module ActiveJob
class JobWrapper
class << self
def perform(job_name, *args)
- job_name.constantize.new.execute *args
+ job_name.constantize.new.execute(*args)
end
end
end
diff --git a/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb b/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb
index bfeaa836d2..a00569833a 100644
--- a/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb
@@ -15,7 +15,7 @@ module ActiveJob
class JobWrapper
def perform(job, *args)
- job.new.execute *args
+ job.new.execute(*args)
end
end
end
diff --git a/activejob/lib/active_job/queue_adapters/inline_adapter.rb b/activejob/lib/active_job/queue_adapters/inline_adapter.rb
index 50d14a321d..5805340fb0 100644
--- a/activejob/lib/active_job/queue_adapters/inline_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/inline_adapter.rb
@@ -3,7 +3,7 @@ module ActiveJob
class InlineAdapter
class << self
def enqueue(job, *args)
- job.new.execute *args
+ job.new.execute(*args)
end
def enqueue_at(*)
diff --git a/activejob/lib/active_job/queue_adapters/qu_adapter.rb b/activejob/lib/active_job/queue_adapters/qu_adapter.rb
index cdf4ae4ce9..5cb741c094 100644
--- a/activejob/lib/active_job/queue_adapters/qu_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/qu_adapter.rb
@@ -22,7 +22,7 @@ module ActiveJob
end
def perform
- @job.new.execute *@args
+ @job.new.execute(*@args)
end
end
end
diff --git a/activejob/lib/active_job/queue_adapters/que_adapter.rb b/activejob/lib/active_job/queue_adapters/que_adapter.rb
index 15a607bcb6..0b87deb4e0 100644
--- a/activejob/lib/active_job/queue_adapters/que_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/que_adapter.rb
@@ -15,7 +15,7 @@ module ActiveJob
class JobWrapper < Que::Job
def run(job_name, *args)
- job_name.constantize.new.execute *args
+ job_name.constantize.new.execute(*args)
end
end
end
diff --git a/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb b/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb
index c61e0e30db..d74f8cf90e 100644
--- a/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb
@@ -14,8 +14,10 @@ module ActiveJob
end
class JobWrapper
- def self.perform(job_name, *args)
- job_name.constantize.new.execute *args
+ class << self
+ def perform(job_name, *args)
+ job_name.constantize.new.execute(*args)
+ end
end
end
end
diff --git a/activejob/lib/active_job/queue_adapters/resque_adapter.rb b/activejob/lib/active_job/queue_adapters/resque_adapter.rb
index 384aa0c4cc..da8212fc9b 100644
--- a/activejob/lib/active_job/queue_adapters/resque_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/resque_adapter.rb
@@ -32,7 +32,7 @@ module ActiveJob
class JobWrapper
class << self
def perform(job_name, *args)
- job_name.constantize.new.execute *args
+ job_name.constantize.new.execute(*args)
end
end
end
diff --git a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
index f738a7d91c..3e20bec44c 100644
--- a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
@@ -27,7 +27,7 @@ module ActiveJob
include Sidekiq::Worker
def perform(job_name, *args)
- job_name.constantize.new.execute *args
+ job_name.constantize.new.execute(*args)
end
end
end
diff --git a/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb b/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb
index 051a8c3bd7..48b3df6a46 100644
--- a/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb
@@ -25,7 +25,7 @@ module ActiveJob
def work(msg)
job_name, *args = ActiveSupport::JSON.decode(msg)
- job_name.constantize.new.execute *args
+ job_name.constantize.new.execute(*args)
ack!
end
end
diff --git a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
index 64b9c3ca15..16f05744f3 100644
--- a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
@@ -17,7 +17,7 @@ module ActiveJob
include SuckerPunch::Job
def perform(job, *args)
- job.new.execute *args
+ job.new.execute(*args)
end
end
end
diff --git a/activejob/lib/active_job/queue_name.rb b/activejob/lib/active_job/queue_name.rb
index c2186d9fe9..9698835b6e 100644
--- a/activejob/lib/active_job/queue_name.rb
+++ b/activejob/lib/active_job/queue_name.rb
@@ -3,10 +3,13 @@ module ActiveJob
extend ActiveSupport::Concern
module ClassMethods
+ mattr_accessor(:queue_name_prefix)
mattr_accessor(:default_queue_name) { "default" }
def queue_as(part_name)
- self.queue_name = part_name.to_s.presence || default_queue_name
+ queue_name = part_name.to_s.presence || default_queue_name
+ name_parts = [queue_name_prefix.presence, queue_name]
+ self.queue_name = name_parts.compact.join('_')
end
end
diff --git a/activejob/lib/active_job/version.rb b/activejob/lib/active_job/version.rb
index 7e646fa3c4..971ba9fe0c 100644
--- a/activejob/lib/active_job/version.rb
+++ b/activejob/lib/active_job/version.rb
@@ -1,7 +1,7 @@
require_relative 'gem_version'
module ActiveJob
- # Returns the version of the currently loaded ActiveJob as a <tt>Gem::Version</tt>
+ # Returns the version of the currently loaded Active Job as a <tt>Gem::Version</tt>
def self.version
gem_version
end
diff --git a/activejob/test/cases/queue_naming_test.rb b/activejob/test/cases/queue_naming_test.rb
index 426af608f0..fdfd1afceb 100644
--- a/activejob/test/cases/queue_naming_test.rb
+++ b/activejob/test/cases/queue_naming_test.rb
@@ -20,4 +20,19 @@ class QueueNamingTest < ActiveSupport::TestCase
HelloJob.queue_name = LoggingJob.queue_name = ActiveJob::Base.default_queue_name
end
end
+
+ test 'should prefix the queue name' do
+ begin
+ original_queue_name_prefix = ActiveJob::Base.queue_name_prefix
+ original_queue_name = HelloJob.queue_name
+
+ ActiveJob::Base.queue_name_prefix = 'aj'
+ HelloJob.queue_as :low
+ assert_equal 'aj_low', HelloJob.queue_name
+ ensure
+ ActiveJob::Base.queue_name_prefix = original_queue_name_prefix
+ HelloJob.queue_name = original_queue_name
+ end
+ end
+
end
diff --git a/activemodel/lib/active_model/forbidden_attributes_protection.rb b/activemodel/lib/active_model/forbidden_attributes_protection.rb
index 7468f95548..b4fa378601 100644
--- a/activemodel/lib/active_model/forbidden_attributes_protection.rb
+++ b/activemodel/lib/active_model/forbidden_attributes_protection.rb
@@ -23,5 +23,6 @@ module ActiveModel
attributes
end
end
+ alias :sanitize_forbidden_attributes :sanitize_for_mass_assignment
end
end
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index b09d9e336b..c2e79e9f02 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,30 @@
+* Fix has_many :through relation merging failing when dynamic conditions are
+ passed as a lambda with an arity of one.
+
+ Fixes #16128
+
+ *Agis Anastasopoulos*
+
+* Fixed the `Relation#exists?` to work with polymorphic associations.
+
+ Fixes #15821.
+
+ *Kassio Borges*
+
+* Currently, Active Record will rescue any errors raised within
+ after_rollback/after_create callbacks and print them to the logs. Next versions of rails
+ will not rescue those errors anymore, and just bubble them up, as the other callbacks.
+
+ This adds a opt-in flag to enable that behaviour, of not rescuing the errors.
+ Example:
+
+ # For not swallow errors in after_commit/after_rollback callbacks.
+ config.active_record.raise_in_transactional_callbacks = true
+
+ Fixes #13460.
+
+ *arthurnn*
+
* Fixed an issue where custom accessor methods (such as those generated by
`enum`) with the same name as a global method are incorrectly overridden
when subclassing.
diff --git a/activerecord/RUNNING_UNIT_TESTS.rdoc b/activerecord/RUNNING_UNIT_TESTS.rdoc
index ca1f2fd665..569685bd45 100644
--- a/activerecord/RUNNING_UNIT_TESTS.rdoc
+++ b/activerecord/RUNNING_UNIT_TESTS.rdoc
@@ -32,8 +32,8 @@ defined in +Rakefile+)
== Config File
-If +test/config.yml+ is present, it's parameters are obeyed. Otherwise, the
-parameters in +test/config.example.yml+ are obeyed.
+If +test/config.yml+ is present, then its parameters are obeyed; otherwise, the
+parameters in +test/config.example.yml+ are.
You can override the +connections:+ parameter in either file using the +ARCONN+
(Active Record CONNection) environment variable:
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index d3b9b8251a..4ec1c8d545 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -447,9 +447,11 @@ module ActiveRecord
#
# Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
#
- # Should any of the +before_add+ callbacks throw an exception, the object does not get
- # added to the collection. Same with the +before_remove+ callbacks; if an exception is
- # thrown the object doesn't get removed.
+ # If any of the +before_add+ callbacks throw an exception, the object will not be
+ # added to the collection.
+ #
+ # Similarly, if any of the +before_remove+ callbacks throw an exception, the object
+ # will not be removed from the collection.
#
# == Association extensions
#
@@ -647,7 +649,7 @@ module ActiveRecord
# belongs_to :commenter
# end
#
- # When using nested association, you will not be able to modify the association because there
+ # When using a nested association, you will not be able to modify the association because there
# is not enough information to know what modification to make. For example, if you tried to
# add a <tt>Commenter</tt> in the example above, there would be no way to tell how to set up the
# intermediate <tt>Post</tt> and <tt>Comment</tt> objects.
@@ -717,7 +719,7 @@ module ActiveRecord
# == Eager loading of associations
#
# Eager loading is a way to find objects of a certain class and a number of named associations.
- # This is one of the easiest ways of to prevent the dreaded N+1 problem in which fetching 100
+ # It is one of the easiest ways to prevent the dreaded N+1 problem in which fetching 100
# posts that each need to display their author triggers 101 database queries. Through the
# use of eager loading, the number of queries will be reduced from 101 to 2.
#
@@ -749,16 +751,16 @@ module ActiveRecord
# Post.includes(:author, :comments).each do |post|
#
# This will load all comments with a single query. This reduces the total number of queries
- # to 3. More generally the number of queries will be 1 plus the number of associations
+ # to 3. In general, the number of queries will be 1 plus the number of associations
# named (except if some of the associations are polymorphic +belongs_to+ - see below).
#
# To include a deep hierarchy of associations, use a hash:
#
- # Post.includes(:author, {comments: {author: :gravatar}}).each do |post|
+ # Post.includes(:author, { comments: { author: :gravatar } }).each do |post|
#
- # That'll grab not only all the comments but all their authors and gravatar pictures.
- # You can mix and match symbols, arrays and hashes in any combination to describe the
- # associations you want to load.
+ # The above code will load all the comments and all of their associated
+ # authors and gravatars. You can mix and match any combination of symbols,
+ # arrays, and hashes to retrieve the associations you want to load.
#
# All of this power shouldn't fool you into thinking that you can pull out huge amounts
# of data with no performance penalty just because you've reduced the number of queries.
@@ -767,8 +769,8 @@ module ActiveRecord
# cut down on the number of queries in a situation as the one described above.
#
# Since only one table is loaded at a time, conditions or orders cannot reference tables
- # other than the main one. If this is the case Active Record falls back to the previously
- # used LEFT OUTER JOIN based strategy. For example
+ # other than the main one. If this is the case, Active Record falls back to the previously
+ # used LEFT OUTER JOIN based strategy. For example:
#
# Post.includes([:author, :comments]).where(['comments.approved = ?', true])
#
@@ -1133,6 +1135,17 @@ module ActiveRecord
# * <tt>Firm#clients.create!</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save!</tt>)
# The declaration can also include an +options+ hash to specialize the behavior of the association.
#
+ # === Scopes
+ #
+ # You can pass a second argument +scope+ as a callable (i.e. proc or
+ # lambda) to retrieve a specific set of records or customize the generated
+ # query when you access the associated collection.
+ #
+ # Scope examples:
+ # has_many :comments, -> { where(author_id: 1) }
+ # has_many :employees, -> { joins(:address) }
+ # has_many :posts, ->(post) { where("max_post_length > ?", post.length) }
+ #
# === Options
# [:class_name]
# Specify the class name of the association. Use it only if that name can't be inferred
@@ -1257,6 +1270,17 @@ module ActiveRecord
# * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
# * <tt>Account#create_beneficiary!</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save!; b</tt>)
#
+ # === Scopes
+ #
+ # You can pass a second argument +scope+ as a callable (i.e. proc or
+ # lambda) to retrieve a specific record or customize the generated query
+ # when you access the associated object.
+ #
+ # Scope examples:
+ # has_one :auther, -> { where(comment_id: 1) }
+ # has_one :employer, -> { joins(:company) }
+ # has_one :dob, ->(dob) { where("Date.new(2000, 01, 01) > ?", dob) }
+ #
# === Options
#
# The declaration can also include an +options+ hash to specialize the behavior of the association.
@@ -1366,6 +1390,17 @@ module ActiveRecord
# * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
# The declaration can also include an +options+ hash to specialize the behavior of the association.
#
+ # === Scopes
+ #
+ # You can pass a second argument +scope+ as a callable (i.e. proc or
+ # lambda) to retrieve a specific record or customize the generated query
+ # when you access the associated object.
+ #
+ # Scope examples:
+ # belongs_to :user, -> { where(id: 2) }
+ # belongs_to :user, -> { joins(:friends) }
+ # belongs_to :level, ->(level) { where("game_level > ?", level.current) }
+ #
# === Options
#
# [:class_name]
@@ -1543,6 +1578,18 @@ module ActiveRecord
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("developer_id" => id); c.save; c</tt>)
# The declaration may include an +options+ hash to specialize the behavior of the association.
#
+ # === Scopes
+ #
+ # You can pass a second argument +scope+ as a callable (i.e. proc or
+ # lambda) to retrieve a specific set of records or customize the generated
+ # query when you access the associated collection.
+ #
+ # Scope examples:
+ # has_and_belongs_to_many :projects, -> { includes :milestones, :manager }
+ # has_and_belongs_to_many :categories, ->(category) {
+ # where("default_category = ?", category.name)
+ # }
+ #
# === Options
#
# [:class_name]
diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb
index 519d4d8651..4c47af8cb0 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -115,7 +115,7 @@ module ActiveRecord
if reflection.type
value = owner.class.base_class.name
- bind_val = bind scope, table.table_name, reflection.type.to_s, value, tracker
+ bind_val = bind scope, table.table_name, reflection.type, value, tracker
scope = scope.where(table[reflection.type].eq(bind_val))
end
else
@@ -123,7 +123,7 @@ module ActiveRecord
if reflection.type
value = chain[i + 1].klass.base_class.name
- bind_val = bind scope, table.table_name, reflection.type.to_s, value, tracker
+ bind_val = bind scope, table.table_name, reflection.type, value, tracker
scope = scope.where(table[reflection.type].eq(bind_val))
end
diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb
index 611d471e62..e47e81aa0f 100644
--- a/activerecord/lib/active_record/associations/through_association.rb
+++ b/activerecord/lib/active_record/associations/through_association.rb
@@ -15,7 +15,11 @@ module ActiveRecord
scope = super
reflection.chain.drop(1).each do |reflection|
relation = reflection.klass.all
- relation.merge!(reflection.scope) if reflection.scope
+
+ reflection_scope = reflection.scope
+ if reflection_scope && reflection_scope.arity.zero?
+ relation.merge!(reflection_scope)
+ end
scope.merge!(
relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index a5fa9d6adc..bc1a670b42 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -234,7 +234,7 @@ module ActiveRecord
@spec = spec
- @checkout_timeout = spec.config[:checkout_timeout] || 5
+ @checkout_timeout = (spec.config[:checkout_timeout] && spec.config[:checkout_timeout].to_f) || 5
@reaper = Reaper.new self, spec.config[:reaping_frequency]
@reaper.run
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 9e07e9a5c4..92ac607a3c 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -2,6 +2,7 @@ require 'date'
require 'set'
require 'bigdecimal'
require 'bigdecimal/util'
+require 'active_support/core_ext/string/strip'
module ActiveRecord
module ConnectionAdapters #:nodoc:
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
index 8f06cf3a1f..90be835d8a 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
@@ -22,6 +22,10 @@ module ActiveRecord
@state == :rolledback
end
+ def completed?
+ committed? || rolledback?
+ end
+
def set_state(state)
if !VALID_STATES.include?(state)
raise ArgumentError, "Invalid transaction state: #{state}"
@@ -63,13 +67,19 @@ module ActiveRecord
end
def rollback_records
- records.uniq.each do |record|
+ ite = records.uniq
+ while record = ite.shift
begin
record.rolledback! full_rollback?
rescue => e
+ raise if ActiveRecord::Base.raise_in_transactional_callbacks
record.logger.error(e) if record.respond_to?(:logger) && record.logger
end
end
+ ensure
+ ite.each do |i|
+ i.rolledback!(full_rollback?, false)
+ end
end
def commit
@@ -77,13 +87,19 @@ module ActiveRecord
end
def commit_records
- records.uniq.each do |record|
+ ite = records.uniq
+ while record = ite.shift
begin
record.committed!
rescue => e
+ raise if ActiveRecord::Base.raise_in_transactional_callbacks
record.logger.error(e) if record.respond_to?(:logger) && record.logger
end
end
+ ensure
+ ite.each do |i|
+ i.committed!(false)
+ end
end
def full_rollback?; true; end
@@ -103,14 +119,14 @@ module ActiveRecord
end
def rollback
- super
connection.rollback_to_savepoint(savepoint_name)
+ super
rollback_records
end
def commit
- super
connection.release_savepoint(savepoint_name)
+ super
parent = connection.transaction_manager.current_transaction
records.each { |r| parent.add_record(r) }
end
@@ -130,14 +146,14 @@ module ActiveRecord
end
def rollback
- super
connection.rollback_db_transaction
+ super
rollback_records
end
def commit
- super
connection.commit_db_transaction
+ super
commit_records
end
end
@@ -177,7 +193,7 @@ module ActiveRecord
begin
commit_transaction unless error
rescue Exception
- transaction.rollback
+ transaction.rollback unless transaction.state.completed?
raise
end
end
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 4306b36ae1..727f12103a 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -870,11 +870,11 @@ module ActiveRecord
def try_to_load_dependency(file_name)
require_dependency file_name
rescue LoadError => e
- # Let's hope the developer has included it
- # Let's warn in case this is a subdependency, otherwise
- # subdependency error messages are totally cryptic
- if ActiveRecord::Base.logger
- ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
+ unless fixture_class_names.key?(file_name.pluralize)
+ if ActiveRecord::Base.logger
+ ActiveRecord::Base.logger.warn("Unable to load #{file_name}, make sure you added it to ActiveSupport::TestCase.set_fixture_class")
+ ActiveRecord::Base.logger.warn("underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
+ end
end
end
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index a6847e28c2..d0d9304a36 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -161,21 +161,14 @@ module ActiveRecord
# in the <tt>db/migrate/</tt> directory where <tt>timestamp</tt> is the
# UTC formatted date and time that the migration was generated.
#
- # You may then edit the <tt>up</tt> and <tt>down</tt> methods of
- # MyNewMigration.
- #
# There is a special syntactic shortcut to generate migrations that add fields to a table.
#
# rails generate migration add_fieldname_to_tablename fieldname:string
#
# This will generate the file <tt>timestamp_add_fieldname_to_tablename</tt>, which will look like this:
# class AddFieldnameToTablename < ActiveRecord::Migration
- # def up
- # add_column :tablenames, :fieldname, :string
- # end
- #
- # def down
- # remove_column :tablenames, :fieldname
+ # def change
+ # add_column :tablenames, :field, :string
# end
# end
#
@@ -188,9 +181,12 @@ module ActiveRecord
#
# To roll the database back to a previous migration version, use
# <tt>rake db:migrate VERSION=X</tt> where <tt>X</tt> is the version to which
- # you wish to downgrade. If any of the migrations throw an
- # <tt>ActiveRecord::IrreversibleMigration</tt> exception, that step will fail and you'll
- # have some manual work to do.
+ # you wish to downgrade. Alternatively, you can also use the STEP option if you
+ # wish to rollback last few migrations. <tt>rake db:migrate STEP=2</tt> will rollback
+ # the latest two migrations.
+ #
+ # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
+ # that step will fail and you'll have some manual work to do.
#
# == Database support
#
@@ -836,21 +832,20 @@ module ActiveRecord
SchemaMigration.table_name
end
- def get_all_versions
- SchemaMigration.all.map { |x| x.version.to_i }.sort
+ def get_all_versions(connection = Base.connection)
+ if connection.table_exists?(schema_migrations_table_name)
+ SchemaMigration.all.map { |x| x.version.to_i }.sort
+ else
+ []
+ end
end
def current_version(connection = Base.connection)
- sm_table = schema_migrations_table_name
- if connection.table_exists?(sm_table)
- get_all_versions.max || 0
- else
- 0
- end
+ get_all_versions(connection).max || 0
end
def needs_migration?(connection = Base.connection)
- current_version(connection) < last_version
+ (migrations(migrations_paths).collect(&:version) - get_all_versions(connection)).size > 0
end
def last_version
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 1547c8e3f4..331b6b0698 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -38,7 +38,7 @@ module ActiveRecord
ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
end
- # \Reflection enables interrogating Active Record classes and objects
+ # \Reflection enables interrogating of Active Record classes and objects
# about their associations and aggregations. This information can,
# for example, be used in a form builder that takes an Active Record object
# and creates input fields for all of the attributes depending on their type
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 0c9c761f97..a7899da3a8 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -304,7 +304,7 @@ module ActiveRecord
end
end
- connection.select_value(relation, "#{name} Exists", relation.bind_values) ? true : false
+ connection.select_value(relation, "#{name} Exists", relation.arel.bind_values + relation.bind_values) ? true : false
end
# This method is called whenever no records are found with either a single
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index c8f382ad78..067966321d 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -1,9 +1,12 @@
require 'active_support/core_ext/array/wrap'
+require 'active_model/forbidden_attributes_protection'
module ActiveRecord
module QueryMethods
extend ActiveSupport::Concern
+ include ActiveModel::ForbiddenAttributesProtection
+
# WhereChain objects act as placeholder for queries in which #where does not have any parameter.
# In this case, #where must be chained with #not to return a new relation.
class WhereChain
@@ -574,7 +577,10 @@ WARNING
end
def where!(opts, *rest) # :nodoc:
- references!(PredicateBuilder.references(opts)) if Hash === opts
+ if Hash === opts
+ opts = sanitize_forbidden_attributes(opts)
+ references!(PredicateBuilder.references(opts))
+ end
self.where_values += build_where(opts, rest)
self
@@ -723,7 +729,13 @@ WARNING
end
def create_with!(value) # :nodoc:
- self.create_with_value = value ? create_with_value.merge(value) : {}
+ if value
+ value = sanitize_forbidden_attributes(value)
+ self.create_with_value = create_with_value.merge(value)
+ else
+ self.create_with_value = {}
+ end
+
self
end
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 7e4dc4c895..1bb7aab8fb 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -3,11 +3,23 @@ module ActiveRecord
module Transactions
extend ActiveSupport::Concern
ACTIONS = [:create, :destroy, :update]
+ CALLBACK_WARN_MESSAGE = <<-EOF
+Currently, Active Record will rescue any errors raised within
+after_rollback/after_commit callbacks and print them to the logs. In the next
+version, these errors will no longer be rescued. Instead, they will simply
+bubble just like other Active Record callbacks.
+
+You can opt into the new behavior and remove this warning by setting
+config.active_record.raise_in_transactional_callbacks to true.
+EOF
included do
define_callbacks :commit, :rollback,
terminator: ->(_, result) { result == false },
scope: [:kind, :name]
+
+ mattr_accessor :raise_in_transactional_callbacks, instance_writer: false
+ self.raise_in_transactional_callbacks = false
end
# = Active Record Transactions
@@ -223,6 +235,9 @@ module ActiveRecord
def after_commit(*args, &block)
set_options_for_callbacks!(args)
set_callback(:commit, :after, *args, &block)
+ unless ActiveRecord::Base.raise_in_transactional_callbacks
+ ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
+ end
end
# This callback is called after a create, update, or destroy are rolled back.
@@ -231,6 +246,9 @@ module ActiveRecord
def after_rollback(*args, &block)
set_options_for_callbacks!(args)
set_callback(:rollback, :after, *args, &block)
+ unless ActiveRecord::Base.raise_in_transactional_callbacks
+ ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
+ end
end
private
@@ -290,16 +308,16 @@ module ActiveRecord
#
# Ensure that it is not called if the object was never persisted (failed create),
# but call it after the commit of a destroyed object.
- def committed! #:nodoc:
- run_callbacks :commit if destroyed? || persisted?
+ def committed!(should_run_callbacks = true) #:nodoc:
+ run_callbacks :commit if should_run_callbacks && destroyed? || persisted?
ensure
force_clear_transaction_record_state
end
# Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
# state should be rolled back to the beginning or just to the last savepoint.
- def rolledback!(force_restore_state = false) #:nodoc:
- run_callbacks :rollback
+ def rolledback!(force_restore_state = false, should_run_callbacks = true) #:nodoc:
+ run_callbacks :rollback if should_run_callbacks
ensure
restore_transaction_record_state(force_restore_state)
clear_transaction_record_state
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 95d006279d..b42a60fea5 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -4,6 +4,7 @@ require 'models/author'
require 'models/categorization'
require 'models/comment'
require 'models/company'
+require 'models/tagging'
require 'models/topic'
require 'models/reply'
require 'models/entrant'
@@ -78,6 +79,19 @@ class FinderTest < ActiveRecord::TestCase
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
end
+ def test_exists_with_polymorphic_relation
+ post = Post.create!(title: 'Post', body: 'default', taggings: [Tagging.new(comment: 'tagging comment')])
+ relation = Post.tagged_with_comment('tagging comment')
+
+ assert_equal true, relation.exists?(title: ['Post'])
+ assert_equal true, relation.exists?(['title LIKE ?', 'Post%'])
+ assert_equal true, relation.exists?
+ assert_equal true, relation.exists?(post.id)
+ assert_equal true, relation.exists?(post.id.to_s)
+
+ assert_equal false, relation.exists?(false)
+ end
+
def test_exists_passing_active_record_object_is_deprecated
assert_deprecated do
Topic.exists?(Topic.new)
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 042fdaf0bb..d7bbe0df62 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -823,15 +823,20 @@ end
class FixtureLoadingTest < ActiveRecord::TestCase
def test_logs_message_for_failed_dependency_load
- ActiveRecord::TestCase.expects(:require_dependency).with(:does_not_exist).raises(LoadError)
- ActiveRecord::Base.logger.expects(:warn)
- ActiveRecord::TestCase.try_to_load_dependency(:does_not_exist)
+ ActiveRecord::Base.logger.expects(:warn).twice
+ ActiveRecord::TestCase.try_to_load_dependency('does_not_exist')
+ end
+
+ def test_does_not_logs_message_for_dependency_that_has_been_defined_with_set_fixture_class
+ ActiveRecord::TestCase.set_fixture_class unknown_dead_parrots: DeadParrot
+ ActiveRecord::Base.logger.expects(:warn).never
+ ActiveRecord::TestCase.try_to_load_dependency('unknown_dead_parrot')
end
def test_does_not_logs_message_for_successful_dependency_load
- ActiveRecord::TestCase.expects(:require_dependency).with(:works_out_fine)
+ ActiveRecord::TestCase.expects(:require_dependency).with('works_out_fine')
ActiveRecord::Base.logger.expects(:warn).never
- ActiveRecord::TestCase.try_to_load_dependency(:works_out_fine)
+ ActiveRecord::TestCase.try_to_load_dependency('works_out_fine')
end
end
diff --git a/activerecord/test/cases/forbidden_attributes_protection_test.rb b/activerecord/test/cases/forbidden_attributes_protection_test.rb
index 981a75faf6..f4e7646f03 100644
--- a/activerecord/test/cases/forbidden_attributes_protection_test.rb
+++ b/activerecord/test/cases/forbidden_attributes_protection_test.rb
@@ -66,4 +66,34 @@ class ForbiddenAttributesProtectionTest < ActiveRecord::TestCase
person = Person.new
assert_nil person.assign_attributes(ProtectedParams.new({}))
end
+
+ def test_create_with_checks_permitted
+ params = ProtectedParams.new(first_name: 'Guille', gender: 'm')
+
+ assert_raises(ActiveModel::ForbiddenAttributesError) do
+ Person.create_with(params).create!
+ end
+ end
+
+ def test_create_with_works_with_params_values
+ params = ProtectedParams.new(first_name: 'Guille')
+
+ person = Person.create_with(first_name: params[:first_name]).create!
+ assert_equal 'Guille', person.first_name
+ end
+
+ def test_where_checks_permitted
+ params = ProtectedParams.new(first_name: 'Guille', gender: 'm')
+
+ assert_raises(ActiveModel::ForbiddenAttributesError) do
+ Person.where(params).create!
+ end
+ end
+
+ def test_where_works_with_params_values
+ params = ProtectedParams.new(first_name: 'Guille')
+
+ person = Person.where(first_name: params[:first_name]).create!
+ assert_equal 'Guille', person.first_name
+ end
end
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index 6a8aff4b69..e43b796237 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -24,6 +24,9 @@ ActiveSupport::Deprecation.debug = true
# Disable available locale checks to avoid warnings running the test suite.
I18n.enforce_available_locales = false
+# Enable raise errors in after_commit and after_rollback.
+ActiveRecord::Base.raise_in_transactional_callbacks = true
+
# Connect to the database
ARTest.connect
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 11338e1fb6..034a0f567e 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -81,6 +81,21 @@ class MigrationTest < ActiveRecord::TestCase
assert_equal 0, ActiveRecord::Migrator.current_version
assert_equal 3, ActiveRecord::Migrator.last_version
assert_equal true, ActiveRecord::Migrator.needs_migration?
+
+ ActiveRecord::SchemaMigration.create!(:version => ActiveRecord::Migrator.last_version)
+ assert_equal true, ActiveRecord::Migrator.needs_migration?
+ ensure
+ ActiveRecord::Migrator.migrations_paths = old_path
+ end
+
+ def test_migration_detection_without_schema_migration_table
+ ActiveRecord::Base.connection.drop_table('schema_migrations') if ActiveRecord::Base.connection.table_exists?('schema_migrations')
+
+ migrations_path = MIGRATIONS_ROOT + "/valid"
+ old_path = ActiveRecord::Migrator.migrations_paths
+ ActiveRecord::Migrator.migrations_paths = migrations_path
+
+ assert_equal true, ActiveRecord::Migrator.needs_migration?
ensure
ActiveRecord::Migrator.migrations_paths = old_path
end
diff --git a/activerecord/test/cases/relation/merging_test.rb b/activerecord/test/cases/relation/merging_test.rb
index 2b5c2fd5a4..0d537fbfe3 100644
--- a/activerecord/test/cases/relation/merging_test.rb
+++ b/activerecord/test/cases/relation/merging_test.rb
@@ -4,6 +4,7 @@ require 'models/comment'
require 'models/developer'
require 'models/post'
require 'models/project'
+require 'models/rating'
class RelationMergingTest < ActiveRecord::TestCase
fixtures :developers, :comments, :authors, :posts
@@ -144,4 +145,16 @@ class MergingDifferentRelationsTest < ActiveRecord::TestCase
assert_equal ["Mary", "Mary", "Mary", "David"], posts_by_author_name
end
+
+ test "relation merging (using a proc argument)" do
+ dev = Developer.where(name: "Jamis").first
+
+ comment_1 = dev.comments.create!(body: "I'm Jamis", post: Post.first)
+ rating_1 = comment_1.ratings.create!
+
+ comment_2 = dev.comments.create!(body: "I'm John", post: Post.first)
+ comment_2.ratings.create!
+
+ assert_equal dev.ratings, [rating_1]
+ end
end
diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb
index b4804aa9d7..580ea98910 100644
--- a/activerecord/test/cases/relation/where_test.rb
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -180,6 +180,10 @@ module ActiveRecord
assert_equal 0, Post.where(:id => []).count
end
+ def test_where_with_table_name_and_nested_empty_array
+ assert_equal [], Post.where(:id => [[]]).to_a
+ end
+
def test_where_with_empty_hash_and_no_foreign_key
assert_equal 0, Edge.where(:sink => {}).count
end
diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb
index 4070216733..eb44c4a83c 100644
--- a/activerecord/test/cases/test_case.rb
+++ b/activerecord/test/cases/test_case.rb
@@ -94,7 +94,7 @@ module ActiveRecord
# instead examining the SQL content.
oracle_ignored = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im, /^\s*select .* from all_constraints/im, /^\s*select .* from all_tab_cols/im]
mysql_ignored = [/^SHOW TABLES/i, /^SHOW FULL FIELDS/, /^SHOW CREATE TABLE /i, /^SHOW VARIABLES /]
- postgresql_ignored = [/^\s*select\b.*\bfrom\b.*pg_namespace\b/im, /^\s*select\b.*\battname\b.*\bfrom\b.*\bpg_attribute\b/im, /^SHOW search_path/i]
+ postgresql_ignored = [/^\s*select\b.*\bfrom\b.*pg_namespace\b/im, /^\s*select tablename\b.*from pg_tables\b/im, /^\s*select\b.*\battname\b.*\bfrom\b.*\bpg_attribute\b/im, /^SHOW search_path/i]
sqlite3_ignored = [/^\s*SELECT name\b.*\bFROM sqlite_master/im]
[oracle_ignored, mysql_ignored, postgresql_ignored, sqlite3_ignored].each do |db_ignored_sql|
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index a3f39804b7..b5ac1bdaf9 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -267,6 +267,9 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
end
def test_after_transaction_callbacks_should_prevent_callbacks_from_being_called
+ old_transaction_config = ActiveRecord::Base.raise_in_transactional_callbacks
+ ActiveRecord::Base.raise_in_transactional_callbacks = false
+
def @first.last_after_transaction_error=(e); @last_transaction_error = e; end
def @first.last_after_transaction_error; @last_transaction_error; end
@first.after_commit_block{|r| r.last_after_transaction_error = :commit; raise "fail!";}
@@ -291,6 +294,79 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
end
assert_equal :rollback, @first.last_after_transaction_error
assert_equal [:after_rollback], second.history
+ ensure
+ ActiveRecord::Base.raise_in_transactional_callbacks = old_transaction_config
+ end
+
+ def test_after_commit_should_not_raise_when_raise_in_transactional_callbacks_false
+ old_transaction_config = ActiveRecord::Base.raise_in_transactional_callbacks
+ ActiveRecord::Base.raise_in_transactional_callbacks = false
+ @first.after_commit_block{ fail "boom" }
+ Topic.transaction { @first.save! }
+ ensure
+ ActiveRecord::Base.raise_in_transactional_callbacks = old_transaction_config
+ end
+
+ def test_after_commit_callback_should_not_swallow_errors
+ @first.after_commit_block{ fail "boom" }
+ assert_raises(RuntimeError) do
+ Topic.transaction do
+ @first.save!
+ end
+ end
+ end
+
+ def test_after_commit_callback_when_raise_should_not_restore_state
+ first = TopicWithCallbacks.new
+ second = TopicWithCallbacks.new
+ first.after_commit_block{ fail "boom" }
+ second.after_commit_block{ fail "boom" }
+
+ begin
+ Topic.transaction do
+ first.save!
+ assert_not_nil first.id
+ second.save!
+ assert_not_nil second.id
+ end
+ rescue
+ end
+ assert_not_nil first.id
+ assert_not_nil second.id
+ assert first.reload
+ end
+
+ def test_after_rollback_callback_should_not_swallow_errors_when_set_to_raise
+ error_class = Class.new(StandardError)
+ @first.after_rollback_block{ raise error_class }
+ assert_raises(error_class) do
+ Topic.transaction do
+ @first.save!
+ raise ActiveRecord::Rollback
+ end
+ end
+ end
+
+ def test_after_rollback_callback_when_raise_should_restore_state
+ error_class = Class.new(StandardError)
+
+ first = TopicWithCallbacks.new
+ second = TopicWithCallbacks.new
+ first.after_rollback_block{ raise error_class }
+ second.after_rollback_block{ raise error_class }
+
+ begin
+ Topic.transaction do
+ first.save!
+ assert_not_nil first.id
+ second.save!
+ assert_not_nil second.id
+ raise ActiveRecord::Rollback
+ end
+ rescue error_class
+ end
+ assert_nil first.id
+ assert_nil second.id
end
def test_after_rollback_callbacks_should_validate_on_condition
diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb
index 15970758db..7a88299d08 100644
--- a/activerecord/test/models/comment.rb
+++ b/activerecord/test/models/comment.rb
@@ -9,6 +9,7 @@ class Comment < ActiveRecord::Base
belongs_to :post, :counter_cache => true
belongs_to :author, polymorphic: true
belongs_to :resource, polymorphic: true
+ belongs_to :developer
has_many :ratings
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index 5bd2f00129..3627cfdd09 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -46,6 +46,8 @@ class Developer < ActiveRecord::Base
has_many :audit_logs
has_many :contracts
has_many :firms, :through => :contracts, :source => :firm
+ has_many :comments, ->(developer) { where(body: "I'm #{developer.name}") }
+ has_many :ratings, through: :comments
scope :jamises, -> { where(:name => 'Jamis') }
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index a29858213b..56a31011da 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -41,6 +41,7 @@ class Post < ActiveRecord::Base
scope :with_tags, -> { preload(:taggings) }
scope :tagged_with, ->(id) { joins(:taggings).where(taggings: { tag_id: id }) }
+ scope :tagged_with_comment, ->(comment) { joins(:taggings).where(taggings: { comment: comment }) }
has_many :comments do
def find_most_recent
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 98f2492ef8..0584df87c6 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -198,6 +198,7 @@ ActiveRecord::Schema.define do
t.references :author, polymorphic: true
t.string :resource_id
t.string :resource_type
+ t.integer :developer_id
end
create_table :companies, force: true do |t|
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index c0b457c341..80d1d35888 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
s.rdoc_options.concat ['--encoding', 'UTF-8']
- s.add_dependency 'i18n', '>= 0.7.0.dev', '< 0.8'
+ s.add_dependency 'i18n', '>= 0.7.0.beta1', '< 0.8'
s.add_dependency 'json', '~> 1.7', '>= 1.7.7'
s.add_dependency 'tzinfo', '~> 1.1'
s.add_dependency 'minitest', '~> 5.1'
diff --git a/activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb b/activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb
index 901c2e05a8..a6f24b1a3c 100644
--- a/activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb
+++ b/activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb
@@ -1,4 +1,6 @@
require 'rack/body_proxy'
+require 'rack/utils'
+
module ActiveSupport
module Cache
module Strategy
@@ -28,6 +30,9 @@ module ActiveSupport
LocalCacheRegistry.set_cache_for(local_cache_key, nil)
end
response
+ rescue Rack::Utils::InvalidParameterError
+ LocalCacheRegistry.set_cache_for(local_cache_key, nil)
+ [400, {}, []]
rescue Exception
LocalCacheRegistry.set_cache_for(local_cache_key, nil)
raise
diff --git a/activesupport/lib/active_support/core_ext/object/itself.rb b/activesupport/lib/active_support/core_ext/object/itself.rb
index adedc20169..d71cea6674 100644
--- a/activesupport/lib/active_support/core_ext/object/itself.rb
+++ b/activesupport/lib/active_support/core_ext/object/itself.rb
@@ -1,6 +1,9 @@
class Object
- unless respond_to?(:itself) # TODO: Remove this file when we drop support for Ruby < 2.2
- # Returns the object itself. Useful when dealing with a chaining scenario, like Active Record scopes:
+ # TODO: Remove this file when we drop support for Ruby < 2.2
+ unless respond_to?(:itself)
+ # Returns the object itself.
+ #
+ # Useful for chaining methods, such as Active Record scopes:
#
# Event.public_send(state.presence_in([ :trashed, :drafted ]) || :itself).order(:created_at)
#
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index ab16977bda..46e9996d59 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -32,7 +32,7 @@ module ActiveSupport
# and the second is a library name
#
# ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
- def initialize(deprecation_horizon = '4.2', gem_name = 'Rails')
+ def initialize(deprecation_horizon = '5.0', gem_name = 'Rails')
self.gem_name = gem_name
self.deprecation_horizon = deprecation_horizon
# By default, warnings are not silenced and debugging is off.
diff --git a/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb b/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb
index 01597b288a..47028e9ecf 100644
--- a/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb
@@ -59,7 +59,7 @@ module ActiveSupport
end
def digit_count(number)
- (Math.log10(absolute_number(number)) + 1).floor
+ number.zero? ? 1 : (Math.log10(absolute_number(number)) + 1).floor
end
def strip_insignificant_zeros
diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb
index 73f640e8e5..feca013675 100644
--- a/activesupport/test/multibyte_chars_test.rb
+++ b/activesupport/test/multibyte_chars_test.rb
@@ -48,7 +48,6 @@ class MultibyteCharsTest < ActiveSupport::TestCase
end
def test_methods_are_forwarded_to_wrapped_string_for_byte_strings
- original_encoding = BYTE_STRING.encoding
assert_equal BYTE_STRING.length, BYTE_STRING.mb_chars.length
end
diff --git a/activesupport/test/number_helper_test.rb b/activesupport/test/number_helper_test.rb
index bb51cc68f2..50d84a9470 100644
--- a/activesupport/test/number_helper_test.rb
+++ b/activesupport/test/number_helper_test.rb
@@ -135,6 +135,7 @@ module ActiveSupport
assert_equal("111.23460000000000000000", number_helper.number_to_rounded(BigDecimal(111.2346, Float::DIG), :precision => 20))
assert_equal("111.2346" + "0"*96, number_helper.number_to_rounded('111.2346', :precision => 100))
assert_equal("111.2346", number_helper.number_to_rounded(Rational(1112346, 10000), :precision => 4))
+ assert_equal('0.00', number_helper.number_to_rounded(Rational(0, 1), :precision => 2))
end
end
diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_case_test.rb
index b74bc9bf20..c93192f207 100644
--- a/activesupport/test/test_test.rb
+++ b/activesupport/test/test_case_test.rb
@@ -1,6 +1,4 @@
require 'abstract_unit'
-require 'active_support/core_ext/date'
-require 'active_support/core_ext/numeric/time'
class AssertDifferenceTest < ActiveSupport::TestCase
def setup
@@ -174,72 +172,3 @@ class TestCaseTaggedLoggingTest < ActiveSupport::TestCase
assert_match "#{self.class}: #{name}\n", @out.string
end
end
-
-class TimeHelperTest < ActiveSupport::TestCase
- setup do
- Time.stubs now: Time.now
- end
-
- teardown do
- travel_back
- end
-
- def test_time_helper_travel
- expected_time = Time.now + 1.day
- travel 1.day
-
- assert_equal expected_time.to_s(:db), Time.now.to_s(:db)
- assert_equal expected_time.to_date, Date.today
- end
-
- def test_time_helper_travel_with_block
- expected_time = Time.now + 1.day
-
- travel 1.day do
- assert_equal expected_time.to_s(:db), Time.now.to_s(:db)
- assert_equal expected_time.to_date, Date.today
- end
-
- assert_not_equal expected_time.to_s(:db), Time.now.to_s(:db)
- assert_not_equal expected_time.to_date, Date.today
- end
-
- def test_time_helper_travel_to
- expected_time = Time.new(2004, 11, 24, 01, 04, 44)
- travel_to expected_time
-
- assert_equal expected_time, Time.now
- assert_equal Date.new(2004, 11, 24), Date.today
- end
-
- def test_time_helper_travel_to_with_block
- expected_time = Time.new(2004, 11, 24, 01, 04, 44)
-
- travel_to expected_time do
- assert_equal expected_time, Time.now
- assert_equal Date.new(2004, 11, 24), Date.today
- end
-
- assert_not_equal expected_time, Time.now
- assert_not_equal Date.new(2004, 11, 24), Date.today
- end
-
- def test_time_helper_travel_back
- expected_time = Time.new(2004, 11, 24, 01, 04, 44)
-
- travel_to expected_time
- assert_equal expected_time, Time.now
- assert_equal Date.new(2004, 11, 24), Date.today
- travel_back
-
- assert_not_equal expected_time, Time.now
- assert_not_equal Date.new(2004, 11, 24), Date.today
- end
-
- def test_travel_to_will_reset_the_usec_to_avoid_mysql_rouding
- travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do
- assert_equal 50, Time.now.sec
- assert_equal 0, Time.now.usec
- end
- end
-end
diff --git a/activesupport/test/time_travel_test.rb b/activesupport/test/time_travel_test.rb
new file mode 100644
index 0000000000..065539671d
--- /dev/null
+++ b/activesupport/test/time_travel_test.rb
@@ -0,0 +1,72 @@
+require 'abstract_unit'
+require 'active_support/core_ext/date'
+require 'active_support/core_ext/numeric/time'
+
+class TimeTravelTest < ActiveSupport::TestCase
+ setup do
+ Time.stubs now: Time.now
+ end
+
+ teardown do
+ travel_back
+ end
+
+ def test_time_helper_travel
+ expected_time = Time.now + 1.day
+ travel 1.day
+
+ assert_equal expected_time.to_s(:db), Time.now.to_s(:db)
+ assert_equal expected_time.to_date, Date.today
+ end
+
+ def test_time_helper_travel_with_block
+ expected_time = Time.now + 1.day
+
+ travel 1.day do
+ assert_equal expected_time.to_s(:db), Time.now.to_s(:db)
+ assert_equal expected_time.to_date, Date.today
+ end
+
+ assert_not_equal expected_time.to_s(:db), Time.now.to_s(:db)
+ assert_not_equal expected_time.to_date, Date.today
+ end
+
+ def test_time_helper_travel_to
+ expected_time = Time.new(2004, 11, 24, 01, 04, 44)
+ travel_to expected_time
+
+ assert_equal expected_time, Time.now
+ assert_equal Date.new(2004, 11, 24), Date.today
+ end
+
+ def test_time_helper_travel_to_with_block
+ expected_time = Time.new(2004, 11, 24, 01, 04, 44)
+
+ travel_to expected_time do
+ assert_equal expected_time, Time.now
+ assert_equal Date.new(2004, 11, 24), Date.today
+ end
+
+ assert_not_equal expected_time, Time.now
+ assert_not_equal Date.new(2004, 11, 24), Date.today
+ end
+
+ def test_time_helper_travel_back
+ expected_time = Time.new(2004, 11, 24, 01, 04, 44)
+
+ travel_to expected_time
+ assert_equal expected_time, Time.now
+ assert_equal Date.new(2004, 11, 24), Date.today
+ travel_back
+
+ assert_not_equal expected_time, Time.now
+ assert_not_equal Date.new(2004, 11, 24), Date.today
+ end
+
+ def test_travel_to_will_reset_the_usec_to_avoid_mysql_rouding
+ travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do
+ assert_equal 50, Time.now.sec
+ assert_equal 0, Time.now.usec
+ end
+ end
+end
diff --git a/guides/rails_guides/markdown.rb b/guides/rails_guides/markdown.rb
index 1ea18ba9f5..b422a80759 100644
--- a/guides/rails_guides/markdown.rb
+++ b/guides/rails_guides/markdown.rb
@@ -47,7 +47,7 @@ module RailsGuides
end
def dom_id_text(text)
- text.downcase.gsub(/\?/, '-questionmark').gsub(/!/, '-bang').gsub(/\s+/, '-')
+ text.downcase.gsub(/\?/, '-questionmark').gsub(/!/, '-bang').gsub(/[^a-z0-9]+/, ' ').strip.gsub(/\s+/, '-')
end
def engine
diff --git a/guides/rails_guides/markdown/renderer.rb b/guides/rails_guides/markdown/renderer.rb
index 2eb7ca17a3..688f177578 100644
--- a/guides/rails_guides/markdown/renderer.rb
+++ b/guides/rails_guides/markdown/renderer.rb
@@ -50,7 +50,7 @@ HTML
when 'erb'
'ruby; html-script: true'
when 'html'
- 'xml' # html is understood, but there are .xml rules in the CSS
+ 'xml' # HTML is understood, but there are .xml rules in the CSS
else
'plain'
end
diff --git a/guides/source/2_2_release_notes.md b/guides/source/2_2_release_notes.md
index 522f628a7e..b11aaa15a8 100644
--- a/guides/source/2_2_release_notes.md
+++ b/guides/source/2_2_release_notes.md
@@ -1,7 +1,7 @@
Ruby on Rails 2.2 Release Notes
===============================
-Rails 2.2 delivers a number of new and improved features. This list covers the major upgrades, but doesn't include every little bug fix and change. If you want to see everything, check out the [list of commits](http://github.com/rails/rails/commits/master) in the main Rails repository on GitHub.
+Rails 2.2 delivers a number of new and improved features. This list covers the major upgrades, but doesn't include every little bug fix and change. If you want to see everything, check out the [list of commits](http://github.com/rails/rails/commits/2-2-stable) in the main Rails repository on GitHub.
Along with Rails, 2.2 marks the launch of the [Ruby on Rails Guides](http://guides.rubyonrails.org/), the first results of the ongoing [Rails Guides hackfest](http://hackfest.rubyonrails.org/guide). This site will deliver high-quality documentation of the major features of Rails.
diff --git a/guides/source/2_3_release_notes.md b/guides/source/2_3_release_notes.md
index 52eeb4c2bc..20566c9155 100644
--- a/guides/source/2_3_release_notes.md
+++ b/guides/source/2_3_release_notes.md
@@ -1,7 +1,7 @@
Ruby on Rails 2.3 Release Notes
===============================
-Rails 2.3 delivers a variety of new and improved features, including pervasive Rack integration, refreshed support for Rails Engines, nested transactions for Active Record, dynamic and default scopes, unified rendering, more efficient routing, application templates, and quiet backtraces. This list covers the major upgrades, but doesn't include every little bug fix and change. If you want to see everything, check out the [list of commits](http://github.com/rails/rails/commits/master) in the main Rails repository on GitHub or review the `CHANGELOG` files for the individual Rails components.
+Rails 2.3 delivers a variety of new and improved features, including pervasive Rack integration, refreshed support for Rails Engines, nested transactions for Active Record, dynamic and default scopes, unified rendering, more efficient routing, application templates, and quiet backtraces. This list covers the major upgrades, but doesn't include every little bug fix and change. If you want to see everything, check out the [list of commits](http://github.com/rails/rails/commits/2-3-stable) in the main Rails repository on GitHub or review the `CHANGELOG` files for the individual Rails components.
--------------------------------------------------------------------------------
diff --git a/guides/source/3_0_release_notes.md b/guides/source/3_0_release_notes.md
index aec3a383d6..8122d6c235 100644
--- a/guides/source/3_0_release_notes.md
+++ b/guides/source/3_0_release_notes.md
@@ -15,7 +15,7 @@ Even if you don't give a hoot about any of our internal cleanups, Rails 3.0 is g
On top of all that, we've tried our best to deprecate the old APIs with nice warnings. That means that you can move your existing application to Rails 3 without immediately rewriting all your old code to the latest best practices.
-These release notes cover the major upgrades, but don't include every little bug fix and change. Rails 3.0 consists of almost 4,000 commits by more than 250 authors! If you want to see everything, check out the [list of commits](http://github.com/rails/rails/commits/master) in the main Rails repository on GitHub.
+These release notes cover the major upgrades, but don't include every little bug fix and change. Rails 3.0 consists of almost 4,000 commits by more than 250 authors! If you want to see everything, check out the [list of commits](http://github.com/rails/rails/commits/3-0-stable) in the main Rails repository on GitHub.
--------------------------------------------------------------------------------
diff --git a/guides/source/3_1_release_notes.md b/guides/source/3_1_release_notes.md
index 7626296e7d..b7ed285b96 100644
--- a/guides/source/3_1_release_notes.md
+++ b/guides/source/3_1_release_notes.md
@@ -8,7 +8,10 @@ Highlights in Rails 3.1:
* Assets Pipeline
* jQuery as the default JavaScript library
-This release notes cover the major changes, but don't include every little bug fix and change. If you want to see everything, check out the [list of commits](https://github.com/rails/rails/commits/master) in the main Rails repository on GitHub.
+These release notes cover only the major changes. To learn about various bug
+fixes and changes, please refer to the change logs or check out the [list of
+commits](https://github.com/rails/rails/commits/3-1-stable) in the main Rails
+repository on GitHub.
--------------------------------------------------------------------------------
diff --git a/guides/source/3_2_release_notes.md b/guides/source/3_2_release_notes.md
index 2416e1a228..c5db0262e9 100644
--- a/guides/source/3_2_release_notes.md
+++ b/guides/source/3_2_release_notes.md
@@ -8,7 +8,10 @@ Highlights in Rails 3.2:
* Automatic Query Explains
* Tagged Logging
-These release notes cover the major changes, but do not include each bug-fix and changes. If you want to see everything, check out the [list of commits](https://github.com/rails/rails/commits/3-2-stable) in the main Rails repository on GitHub.
+These release notes cover only the major changes. To learn about various bug
+fixes and changes, please refer to the change logs or check out the [list of
+commits](https://github.com/rails/rails/commits/3-2-stable) in the main Rails
+repository on GitHub.
--------------------------------------------------------------------------------
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index 19c690233c..1aaf5ebc94 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -8,7 +8,10 @@ Highlights in Rails 4.0:
* Turbolinks
* Russian Doll Caching
-These release notes cover only the major changes. To know about various bug fixes and changes, please refer to the change logs or check out the [list of commits](https://github.com/rails/rails/commits/master) in the main Rails repository on GitHub.
+These release notes cover only the major changes. To learn about various bug
+fixes and changes, please refer to the change logs or check out the [list of
+commits](https://github.com/rails/rails/commits/4-0-stable) in the main Rails
+repository on GitHub.
--------------------------------------------------------------------------------
diff --git a/guides/source/4_1_release_notes.md b/guides/source/4_1_release_notes.md
index 5f4bdaaa8f..52a5acb75e 100644
--- a/guides/source/4_1_release_notes.md
+++ b/guides/source/4_1_release_notes.md
@@ -8,10 +8,10 @@ Highlights in Rails 4.1:
* Action Pack variants
* Action Mailer previews
-These release notes cover only the major changes. To know about various bug
-fixes and changes, please refer to the change logs or check out the
-[list of commits](https://github.com/rails/rails/commits/master) in the main
-Rails repository on GitHub.
+These release notes cover only the major changes. To learn about various bug
+fixes and changes, please refer to the change logs or check out the [list of
+commits](https://github.com/rails/rails/commits/4-1-stable) in the main Rails
+repository on GitHub.
--------------------------------------------------------------------------------
diff --git a/guides/source/4_2_release_notes.md b/guides/source/4_2_release_notes.md
index e8d1dc361a..39655447e3 100644
--- a/guides/source/4_2_release_notes.md
+++ b/guides/source/4_2_release_notes.md
@@ -3,20 +3,28 @@ Ruby on Rails 4.2 Release Notes
Highlights in Rails 4.2:
-These release notes cover only the major changes. To know about various bug
-fixes and changes, please refer to the change logs or check out the
-[list of commits](https://github.com/rails/rails/commits/master) in the main
-Rails repository on GitHub.
+* Active Job, Action Mailer #deliver_later
+* Adequate Record
+* Web Console
+* Foreign key support
+
+These release notes cover only the major changes. To learn about various bug
+fixes and changes, please refer to the change logs or check out the [list of
+commits](https://github.com/rails/rails/commits/master) in the main Rails
+repository on GitHub.
--------------------------------------------------------------------------------
+NOTE: This document is a work in progress, please help to improve this by sending
+a [pull request](https://github.com/rails/rails/edit/master/guides/source/4_2_release_notes.md).
+
Upgrading to Rails 4.2
----------------------
If you're upgrading an existing application, it's a great idea to have good test
coverage before going in. You should also first upgrade to Rails 4.1 in case you
haven't and make sure your application still runs as expected before attempting
-an update to Rails 4.2. A list of things to watch out for when upgrading is
+to upgrade to Rails 4.2. A list of things to watch out for when upgrading is
available in the
[Upgrading Ruby on Rails](upgrading_ruby_on_rails.html#upgrading-from-rails-4-1-to-rails-4-2)
guide.
@@ -25,6 +33,41 @@ guide.
Major Features
--------------
+### Active Job, Action Mailer #deliver_later
+
+Active Job is a new framework in Rails 4.2. It is an adapter layer on top of
+queuing systems like Resque, Delayed Job, Sidekiq, and more. You can write your
+jobs to Active Job, and it'll run on all these queues with no changes. (It comes
+pre-configured with an inline runner.)
+
+Building on top of Active Job, Action Mailer now comes with a #deliver_later
+method, which adds your email to be sent as a job to a queue, so it doesn't
+bog down the controller or model.
+
+The new GlobalID library makes it easy to pass Active Record objects to jobs by
+serializing them in a generic form. This means you no longer have to manually
+pack and unpack your Active Records by passing ids. Just give the job the
+straight Active Record object, and it'll serialize it using GlobalID, and
+deserialize it at run time.
+
+### Adequate Record
+
+Rails 4.2 comes with a performance improvement feature called Adequate Record
+for Active Record. A lot of common queries are now up to twice as fast in Rails
+4.2!
+
+TODO: add some technical details
+
+### Web Console
+
+New applications generated from Rails 4.2 now comes with the Web Console gem by
+default.
+
+Web Console is an IRB console available in the browser. In development mode, you
+can go to /console and do your work right there. It will also be made available
+on all exception pages and allows you to jump between the different points in
+the backtrace.
+
### Foreign key support
The migration DSL now supports adding and removing foreign keys. They are dumped
@@ -69,11 +112,60 @@ Please refer to the [Changelog][railties] for detailed changes.
### Notable changes
-* Introduced `--skip-gems` option in the app generator to skip gems such as
- `turbolinks` and `coffee-rails` that does not have their own specific flags.
+* Introduced `web-console` in the default application Gemfile.
+ ([Pull Request](https://github.com/rails/rails/pull/16532))
+
+* Added a `required` option to the model generator for associations.
+ ([Pull Request](https://github.com/rails/rails/pull/16062))
+
+* Introduced an `after_bundle` callback for use in Rails templates.
+ ([Pull Request](https://github.com/rails/rails/pull/16359))
+
+* Introduced the `x` namespace for defining custom configuration options:
+
+ ```ruby
+ # config/environments/production.rb
+ config.x.payment_processing.schedule = :daily
+ config.x.payment_processing.retries = 3
+ config.x.super_debugger = true
+ ```
+
+ These options are then available through the configuration object:
+
+ ```ruby
+ Rails.configuration.x.payment_processing.schedule # => :daily
+ Rails.configuration.x.payment_processing.retries # => 3
+ Rails.configuration.x.super_debugger # => true
+ ```
+
+ ([Commit](https://github.com/rails/rails/commit/611849772dd66c2e4d005dcfe153f7ce79a8a7db))
+
+* Introduced `Rails::Application.config_for` to load a configuration for the
+ current environment.
+
+ ```ruby
+ # config/exception_notification.yml:
+ production:
+ url: http://127.0.0.1:8080
+ namespace: my_app_production
+ development:
+ url: http://localhost:3001
+ namespace: my_app_development
+
+ # config/production.rb
+ MyApp::Application.configure do
+ config.middleware.use ExceptionNotifier, config_for(:exception_notification)
+ end
+ ```
+
+ ([Pull Request](https://github.com/rails/rails/pull/16129))
+
+* Introduced a `--skip-gems` option in the app generator to skip gems such as
+ `turbolinks` and `coffee-rails` that do not have their own specific flags.
([Commit](https://github.com/rails/rails/commit/10565895805887d4faf004a6f71219da177f78b7))
-* Introduced `bin/setup` script to bootstrap an application.
+* Introduced a `bin/setup` script to enable automated setup code when
+ bootstrapping an application.
([Pull Request](https://github.com/rails/rails/pull/15189))
* Changed default value for `config.assets.digest` to `true` in development.
@@ -85,9 +177,6 @@ Please refer to the [Changelog][railties] for detailed changes.
* Introduced `Rails.gem_version` as a convenience method to return `Gem::Version.new(Rails.version)`.
([Pull Request](https://github.com/rails/rails/pull/14101))
-* Introduced an `after_bundle` callback in the Rails templates.
- ([Pull Request](https://github.com/rails/rails/pull/16359))
-
Action Pack
-----------
@@ -96,12 +185,21 @@ Please refer to the [Changelog][action-pack] for detailed changes.
### Removals
+* `respond_with` and the class-level `respond_to` were removed from Rails and
+ moved to the `responders` gem (version 2.0). Add `gem 'responders', '~> 2.0'`
+ to your `Gemfile` to continue using these features.
+ ([Pull Request](https://github.com/rails/rails/pull/16526))
+
* Removed deprecated `AbstractController::Helpers::ClassMethods::MissingHelperError`
in favor of `AbstractController::Helpers::MissingHelperError`.
([Commit](https://github.com/rails/rails/commit/a1ddde15ae0d612ff2973de9cf768ed701b594e8))
### Deprecations
+* Deprecated `assert_tag`, `assert_no_tag`, `find_tag` and `find_all_tag` in
+ favor of `assert_select`.
+ ([Commit](https://github.com/rails/rails-dom-testing/commit/b12850bc5ff23ba4b599bf2770874dd4f11bf750))
+
* Deprecated support for setting the `:to` option of a router to a symbol or a
string that does not contain a `#` character:
@@ -116,6 +214,9 @@ Please refer to the [Changelog][action-pack] for detailed changes.
### Notable changes
+* Rails will now automatically include the template's digest in ETags.
+ ([Pull Request](https://github.com/rails/rails/pull/16527))
+
* `render nothing: true` or rendering a `nil` body no longer add a single
space padding to the response body.
([Pull Request](https://github.com/rails/rails/pull/14883))
@@ -125,8 +226,8 @@ Please refer to the [Changelog][action-pack] for detailed changes.
is `['controller', 'action']`.
([Pull Request](https://github.com/rails/rails/pull/15933))
-* The `*_filter` family methods has been removed from the documentation. Their
- usage are discouraged in favor of the `*_action` family methods:
+* The `*_filter` family methods have been removed from the documentation. Their
+ usage is discouraged in favor of the `*_action` family methods:
```
after_filter => after_action
@@ -161,10 +262,10 @@ Please refer to the [Changelog][action-pack] for detailed changes.
* Segments that are passed into URL helpers are now automatically escaped.
([Commit](https://github.com/rails/rails/commit/5460591f0226a9d248b7b4f89186bd5553e7768f))
-* Improved Routing Error page with fuzzy matching for route search.
+* Improved the Routing Error page with fuzzy matching for route search.
([Pull Request](https://github.com/rails/rails/pull/14619))
-* Added option to disable logging of CSRF failures.
+* Added an option to disable logging of CSRF failures.
([Pull Request](https://github.com/rails/rails/pull/14280))
@@ -180,24 +281,45 @@ Please refer to the [Changelog][action-view] for detailed changes.
where to find views.
([Pull Request](https://github.com/rails/rails/pull/15026))
-* Deprecated `ActionView::Digestor#digest(name, format, finder, options = {})`,
- arguments should be passed as a hash instead.
+* Deprecated `ActionView::Digestor#digest(name, format, finder, options = {})`.
+ Arguments should be passed as a hash instead.
([Pull Request](https://github.com/rails/rails/pull/14243))
### Notable changes
+* Introduced a `#{partial_name}_iteration` special local variable for use with
+ partials that are rendered with a collection. It provides access to the
+ current state of the iteration via the `#index`, `#size`, `#first?` and
+ `#last?` methods.
+ ([Pull Request](https://github.com/rails/rails/pull/7698))
+
* The form helpers no longer generate a `<div>` element with inline CSS around
the hidden fields.
([Pull Request](https://github.com/rails/rails/pull/14738))
+* Placeholder I18n follows the same convention as `label` I18n.
+ ([Pull Request](https://github.com/rails/rails/pull/16438))
+
Action Mailer
-------------
Please refer to the [Changelog][action-mailer] for detailed changes.
+### Deprecations
+
+* Deprecated `*_path` helpers in mailers. Always use `*_url` helpers instead.
+ ([Pull Request](https://github.com/rails/rails/pull/15840))
+
+* Deprecated `deliver` / `deliver!` in favour of `deliver_now` / `deliver_now!`.
+ ([Pull Request](https://github.com/rails/rails/pull/16582))
+
### Notable changes
+* Introduced `deliver_later` which enqueues a job on the application's queue
+ to deliver the mailer asynchronously.
+ ([Pull Request](https://github.com/rails/rails/pull/16485))
+
* Added the `show_previews` configuration option for enabling mailer previews
outside of the development environment.
([Pull Request](https://github.com/rails/rails/pull/15970))
@@ -229,6 +351,17 @@ for detailed changes.
### Deprecations
+* Deprecated swallowing of errors inside `after_commit` and `after_rollback`.
+ ([Pull Request](https://github.com/rails/rails/pull/16537))
+
+* Deprecated calling `DatabaseTasks.load_schema` without a connection. Use
+ `DatabaseTasks.load_schema_current` instead.
+ ([Commit](https://github.com/rails/rails/commit/f15cef67f75e4b52fd45655d7c6ab6b35623c608))
+
+* Deprecated `Reflection#source_macro` without replacement as it is no longer
+ needed in Active Record.
+ ([Pull Request](https://github.com/rails/rails/pull/16373))
+
* Deprecated broken support for automatic detection of counter caches on
`has_many :through` associations. You should instead manually specify the
counter cache on the `has_many` and `belongs_to` associations for the
@@ -266,6 +399,13 @@ for detailed changes.
### Notable changes
+* The PostgreSQL adapter now supports the `JSONB` datatype in PostgreSQL 9.4+.
+ ([Pull Request](https://github.com/rails/rails/pull/16220))
+
+* The `#references` method in migrations now supports a `type` option for
+ specifying the type of the foreign key (e.g. `:uuid`).
+ ([Pull Request](https://github.com/rails/rails/pull/16231))
+
* Added a `:required` option to singular associations, which defines a
presence validation on the association.
([Pull Request](https://github.com/rails/rails/pull/16056))
@@ -329,13 +469,25 @@ Please refer to the [Changelog][active-model] for detailed changes.
### Removals
* Removed deprecated `Validator#setup` without replacement.
- ([Pull Request](https://github.com/rails/rails/pull/15617))
+ ([Pull Request](https://github.com/rails/rails/pull/10716))
+
+### Deprecations
+
+* Deprecated reset_#{attribute} in favor of restore_#{attribute}.
+ ([Pull Request](https://github.com/rails/rails/pull/16180))
+
+* Deprecated ActiveModel::Dirty#reset_changes in favor of #clear_changes_information.
+ ([Pull Request](https://github.com/rails/rails/pull/16180))
### Notable changes
-* Introduced `undo_changes` method in `ActiveModel::Dirty` to restore the
- changed (dirty) attributes to their previous values.
- ([Pull Request](https://github.com/rails/rails/pull/14861))
+* Introduced the `restore_attributes` method in `ActiveModel::Dirty` to restore
+ the changed (dirty) attributes to their previous values.
+ (Pull Request [1](https://github.com/rails/rails/pull/14861), [2](https://github.com/rails/rails/pull/16180))
+
+* `has_secure_password` no longer disallow blank passwords (i.e. passwords
+ that contains only spaces) by default.
+ ([Pull Request](https://github.com/rails/rails/pull/16412))
* `has_secure_password` now verifies that the given password is less than 72
characters if validations are enabled.
@@ -361,6 +513,10 @@ Please refer to the [Changelog][active-support] for detailed changes.
### Deprecations
+* Deprecated `Kernel#silence_stderr`, `Kernel#capture` and `Kernel#quietly`
+ without replacement.
+ ([Pull Request](https://github.com/rails/rails/pull/13392))
+
* Deprecated `Class#superclass_delegating_accessor`, use
`Class#class_attribute` instead.
([Pull Request](https://github.com/rails/rails/pull/14271))
@@ -371,6 +527,23 @@ Please refer to the [Changelog][active-support] for detailed changes.
### Notable changes
+* The `travel_to` test helper now truncates the `usec` component to 0.
+ ([Commit](https://github.com/rails/rails/commit/9f6e82ee4783e491c20f5244a613fdeb4024beb5))
+
+* `ActiveSupport::TestCase` now randomizes the order that test cases are ran
+ by default.
+ ([Commit](https://github.com/rails/rails/commit/6ffb29d24e05abbd9ffe3ea974140d6c70221807))
+
+* Introduced `Object#itself` as an identity function.
+ (Commit [1](https://github.com/rails/rails/commit/702ad710b57bef45b081ebf42e6fa70820fdd810),
+ [2](https://github.com/rails/rails/commit/64d91122222c11ad3918cc8e2e3ebc4b0a03448a))
+
+* `Object#with_options` can now be used without an explicit receiver.
+ ([Pull Request](https://github.com/rails/rails/pull/16339))
+
+* Introduced `String#truncate_words` to truncate a string by a number of words.
+ ([Pull Request](https://github.com/rails/rails/pull/16190))
+
* Added `Hash#transform_values` and `Hash#transform_values!` to simplify a
common pattern where the values of a hash must change, but the keys are left
the same.
@@ -379,7 +552,7 @@ Please refer to the [Changelog][active-support] for detailed changes.
* The `humanize` inflector helper now strips any leading underscores.
([Commit](https://github.com/rails/rails/commit/daaa21bc7d20f2e4ff451637423a25ff2d5e75c7))
-* Introduce `Concern#class_methods` as an alternative to
+* Introduced `Concern#class_methods` as an alternative to
`module ClassMethods`, as well as `Kernel#concern` to avoid the
`module Foo; extend ActiveSupport::Concern; end` boilerplate.
([Commit](https://github.com/rails/rails/commit/b16c36e688970df2f96f793a759365b248b582ad))
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 9ad9319255..f981d0da47 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -159,7 +159,10 @@ $ bin/rake db:migrate
Now that we have a user model to play with, we will just edit the
`app/controllers/users_controller.rb` make it instruct the `UserMailer` to deliver
an email to the newly created user by editing the create action and inserting a
-call to `UserMailer.welcome_email` right after the user is successfully saved:
+call to `UserMailer.welcome_email` right after the user is successfully saved.
+
+Action Mailer is nicely integrated with Active Job so you can send emails outside
+of the request-response cycle, so the user doesn't have to wait on it:
```ruby
class UsersController < ApplicationController
@@ -171,7 +174,7 @@ class UsersController < ApplicationController
respond_to do |format|
if @user.save
# Tell the UserMailer to send a welcome email after save
- UserMailer.welcome_email(@user).deliver
+ UserMailer.welcome_email(@user).deliver_later
format.html { redirect_to(@user, notice: 'User was successfully created.') }
format.json { render json: @user, status: :created, location: @user }
@@ -184,8 +187,29 @@ class UsersController < ApplicationController
end
```
-The method `welcome_email` returns a `Mail::Message` object which can then just
-be told `deliver` to send itself out.
+NOTE: Active Job's default behavior is to execute jobs ':inline'. So, you can use
+`deliver_later` now to send emails, and when you later decide to start sending
+them from a background job, you'll only need to set up Active Job to use a queueing
+backend (Sidekiq, Resque, etc).
+
+If you want to send emails right away (from a cronjob for example) just call
+`deliver_now`:
+
+```ruby
+class SendWeeklySummary
+ def run
+ User.find_each do |user|
+ UserMailer.weekly_summary(user).deliver_now
+ end
+ end
+end
+```
+
+The method `welcome_email` returns a `ActionMailer::MessageDelivery` object which
+can then just be told `deliver_now` or `deliver_later` to send itself out. The
+`ActionMailer::MessageDelivery` object is just a wrapper around a `Mail::Message`. If
+you want to inspect, alter or do anything else with the `Mail::Message` object you can
+access it with the `message` method on the `ActionMailer::MessageDelivery` object.
### Auto encoding header values
diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md
index ef7ef5a50e..683e633668 100644
--- a/guides/source/action_view_overview.md
+++ b/guides/source/action_view_overview.md
@@ -44,18 +44,18 @@ $ bin/rails generate scaffold article
There is a naming convention for views in Rails. Typically, the views share their name with the associated controller action, as you can see above.
For example, the index controller action of the `articles_controller.rb` will use the `index.html.erb` view file in the `app/views/articles` directory.
-The complete HTML returned to the client is composed of a combination of this ERB file, a layout template that wraps it, and all the partials that the view may reference. Later on this guide you can find a more detailed documentation of each one of these three components.
+The complete HTML returned to the client is composed of a combination of this ERB file, a layout template that wraps it, and all the partials that the view may reference. Within this guide you will find more detailed documentation about each of these three components.
Templates, Partials and Layouts
-------------------------------
-As mentioned before, the final HTML output is a composition of three Rails elements: `Templates`, `Partials` and `Layouts`.
-Below is a brief overview of each one of them.
+As mentioned, the final HTML output is a composition of three Rails elements: `Templates`, `Partials` and `Layouts`.
+Below is a brief overview of each of them.
### Templates
-Action View templates can be written in several ways. If the template file has a `.erb` extension then it uses a mixture of ERB (included in Ruby) and HTML. If the template file has a `.builder` extension then a fresh instance of `Builder::XmlMarkup` library is used.
+Action View templates can be written in several ways. If the template file has a `.erb` extension then it uses a mixture of ERB (Embedded Ruby) and HTML. If the template file has a `.builder` extension then the `Builder::XmlMarkup` library is used.
Rails supports multiple template systems and uses a file extension to distinguish amongst them. For example, an HTML file using the ERB template system will have `.html.erb` as a file extension.
@@ -72,7 +72,7 @@ Consider the following loop for names:
<% end %>
```
-The loop is set up in regular embedding tags (`<% %>`) and the name is written using the output embedding tags (`<%= %>`). Note that this is not just a usage suggestion, for regular output functions like `print` or `puts` won't work with ERB templates. So this would be wrong:
+The loop is set up using regular embedding tags (`<% %>`) and the name is inserted using the output embedding tags (`<%= %>`). Note that this is not just a usage suggestion: regular output functions such as `print` and `puts` won't be rendered to the view with ERB templates. So this would be wrong:
```html+erb
<%# WRONG %>
@@ -231,7 +231,7 @@ The `object` and `as` options can also be used together:
#### Rendering Collections
-It is very common that a template needs to iterate over a collection and render a sub-template for each of the elements. This pattern has been implemented as a single method that accepts an array and renders a partial for each one of the elements in the array.
+It is very common that a template will need to iterate over a collection and render a sub-template for each of the elements. This pattern has been implemented as a single method that accepts an array and renders a partial for each one of the elements in the array.
So this example for rendering all the products:
@@ -247,7 +247,7 @@ can be rewritten in a single line:
<%= render partial: "product", collection: @products %>
```
-When a partial is called like this (eg. with a collection), the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is `_product`, and within it you can refer to `product` to get the instance that is being rendered.
+When a partial is called with a collection, the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is `_product`, and within it you can refer to `product` to get the collection member that is being rendered.
You can use a shorthand syntax for rendering collections. Assuming `@products` is a collection of `Product` instances, you can simply write the following to produce the same result:
@@ -255,7 +255,7 @@ You can use a shorthand syntax for rendering collections. Assuming `@products` i
<%= render @products %>
```
-Rails determines the name of the partial to use by looking at the model name in the collection, `Product` in this case. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection.
+Rails determines the name of the partial to use by looking at the model name in the collection, `Product` in this case. In fact, you can even render a collection made up of instances of different models using this shorthand, and Rails will choose the proper partial for each member of the collection.
#### Spacer Templates
@@ -269,14 +269,14 @@ Rails will render the `_product_ruler` partial (with no data passed to it) betwe
### Layouts
-Layouts can be used to render a common view template around the results of Rails controller actions. Typically, every Rails application has a couple of overall layouts that most pages are rendered within. For example, a site might have a layout for a logged in user, and a layout for the marketing or sales side of the site. The logged in user layout might include top-level navigation that should be present across many controller actions. The sales layout for a SaaS app might include top-level navigation for things like "Pricing" and "Contact Us." You would expect each layout to have a different look and feel. You can read more details about Layouts in the [Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
+Layouts can be used to render a common view template around the results of Rails controller actions. Typically, a Rails application will have a couple of layouts that pages will be rendered within. For example, a site might have one layout for a logged in user and another for the marketing or sales side of the site. The logged in user layout might include top-level navigation that should be present across many controller actions. The sales layout for a SaaS app might include top-level navigation for things like "Pricing" and "Contact Us" pages. You would expect each layout to have a different look and feel. You can read about layouts in more detail in the [Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
Partial Layouts
---------------
-Partials can have their own layouts applied to them. These layouts are different than the ones that are specified globally for the entire action, but they work in a similar fashion.
+Partials can have their own layouts applied to them. These layouts are different from those applied to a controller action, but they work in a similar fashion.
-Let's say we're displaying an article on a page, that should be wrapped in a `div` for display purposes. First, we'll create a new `Article`:
+Let's say we're displaying an article on a page which should be wrapped in a `div` for display purposes. Firstly, we'll create a new `Article`:
```ruby
Article.create(body: 'Partial Layouts are cool!')
@@ -495,7 +495,7 @@ image_url("edit.png") # => http://www.example.com/assets/edit.png
#### image_tag
-Returns an html image tag for the source. The source can be a full path or a file that exists in your `app/assets/images` directory.
+Returns an HTML image tag for the source. The source can be a full path or a file that exists in your `app/assets/images` directory.
```ruby
image_tag("icon.png") # => <img src="/assets/icon.png" alt="Icon" />
@@ -503,7 +503,7 @@ image_tag("icon.png") # => <img src="/assets/icon.png" alt="Icon" />
#### javascript_include_tag
-Returns an html script tag for each of the sources provided. You can pass in the filename (`.js` extension is optional) of JavaScript files that exist in your `app/assets/javascripts` directory for inclusion into the current page or you can pass the full path relative to your document root.
+Returns an HTML script tag for each of the sources provided. You can pass in the filename (`.js` extension is optional) of JavaScript files that exist in your `app/assets/javascripts` directory for inclusion into the current page or you can pass the full path relative to your document root.
```ruby
javascript_include_tag "common" # => <script src="/assets/common.js"></script>
@@ -736,7 +736,7 @@ distance_of_time_in_words(Time.now, Time.now + 15.seconds, include_seconds: true
#### select_date
-Returns a set of html select-tags (one for year, month, and day) pre-selected with the `date` provided.
+Returns a set of HTML select-tags (one for year, month, and day) pre-selected with the `date` provided.
```ruby
# Generates a date select that defaults to the date provided (six days after today)
@@ -748,7 +748,7 @@ select_date()
#### select_datetime
-Returns a set of html select-tags (one for year, month, day, hour, and minute) pre-selected with the `datetime` provided.
+Returns a set of HTML select-tags (one for year, month, day, hour, and minute) pre-selected with the `datetime` provided.
```ruby
# Generates a datetime select that defaults to the datetime provided (four days after today)
@@ -808,7 +808,7 @@ select_second(Time.now + 16.minutes)
#### select_time
-Returns a set of html select-tags (one for hour and minute).
+Returns a set of HTML select-tags (one for hour and minute).
```ruby
# Generates a time select that defaults to the time provided
@@ -1526,7 +1526,7 @@ The SanitizeHelper module provides a set of methods for scrubbing text of undesi
#### sanitize
-This sanitize helper will html encode all tags and strip all attributes that aren't specifically allowed.
+This sanitize helper will HTML encode all tags and strip all attributes that aren't specifically allowed.
```ruby
sanitize @article.body
diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md
index ae5d21d546..58e828d1b5 100644
--- a/guides/source/active_job_basics.md
+++ b/guides/source/active_job_basics.md
@@ -13,12 +13,13 @@ After reading this guide, you will know:
--------------------------------------------------------------------------------
+
Introduction
------------
Active Job is a framework for declaring jobs and making them run on a variety
of queueing backends. These jobs can be everything from regularly scheduled
-clean-ups, billing charges, or mailings. Anything that can be chopped up
+clean-ups, to billing charges, to mailings. Anything that can be chopped up
into small units of work and run in parallel, really.
@@ -35,12 +36,12 @@ then. And you'll be able to switch between them without having to rewrite your j
Creating a Job
--------------
-This section will provide a step-by-step guide to creating a job and enqueue it.
+This section will provide a step-by-step guide to creating a job and enqueuing it.
### Create the Job
Active Job provides a Rails generator to create jobs. The following will create a
-job in app/jobs:
+job in `app/jobs`:
```bash
$ bin/rails generate job guests_cleanup
@@ -58,9 +59,9 @@ As you can see, you can generate jobs just like you use other generators with
Rails.
If you don't want to use a generator, you could create your own file inside of
-app/jobs, just make sure that it inherits from `ActiveJob::Base`.
+`app/jobs`, just make sure that it inherits from `ActiveJob::Base`.
-Here's how a job looks like:
+Here's what a job looks like:
```ruby
class GuestsCleanupJob < ActiveJob::Base
@@ -94,7 +95,7 @@ That's it!
Job Execution
-------------
-If not adapter is set, the job is immediately executed.
+If no adapter is set, the job is immediately executed.
### Backends
@@ -127,7 +128,7 @@ Active Job has adapters for the following queueing backends:
### Change Backends
-You can easy change your adapter:
+You can easily change your adapter:
```ruby
# be sure to have the adapter gem in your Gemfile and follow the adapter specific
@@ -135,11 +136,12 @@ You can easy change your adapter:
YourApp::Application.config.active_job.queue_adapter = :sidekiq
```
+
Queues
------
-Most of the adapters supports multiple queues. With Active Job you can schedule the job
-to run on a specific queue:
+Most of the adapters support multiple queues. With Active Job you can schedule
+the job to run on a specific queue:
```ruby
class GuestsCleanupJob < ActiveJob::Base
@@ -155,17 +157,17 @@ you need to specify the queues to listen to.
Callbacks
---------
-Active Job provides hooks during the lifecycle of a job. Callbacks allows you to trigger
-logic during the lifecycle of a job.
+Active Job provides hooks during the lifecycle of a job. Callbacks allow you to
+trigger logic during the lifecycle of a job.
### Available callbacks
-* before_enqueue
-* around_enqueue
-* after_enqueue
-* before_perform
-* around_perform
-* after_perform
+* `before_enqueue`
+* `around_enqueue`
+* `after_enqueue`
+* `before_perform`
+* `around_perform`
+* `after_perform`
### Usage
@@ -189,25 +191,28 @@ class GuestsCleanupJob < ActiveJob::Base
end
```
+
ActionMailer
------------
+
One of the most common jobs in a modern web application is sending emails outside
of the request-response cycle, so the user doesn't have to wait on it. Active Job
-is integrated with Action Mailer so you can easily send emails async:
+is integrated with Action Mailer so you can easily send emails asynchronously:
```ruby
-# Instead of the classic
-UserMailer.welcome(@user).deliver
+# If you want to send the email now use #deliver_now
+UserMailer.welcome(@user).deliver_now
-# use #deliver later to send the email async
+# If you want to send the email through Active Job use #deliver_later
UserMailer.welcome(@user).deliver_later
```
+
GlobalID
--------
-Active Job supports GlobalID for parameters. This makes it possible
-to pass live Active Record objects to your job instead of class/id pairs, which
-you then have to manually deserialize. Before, jobs would look like this:
+Active Job supports GlobalID for parameters. This makes it possible to pass live
+Active Record objects to your job instead of class/id pairs, which you then have
+to manually deserialize. Before, jobs would look like this:
```ruby
class TrashableCleanupJob
@@ -228,12 +233,13 @@ class TrashableCleanupJob
end
```
-This works with any class that mixes in ActiveModel::GlobalIdentification, which
+This works with any class that mixes in `ActiveModel::GlobalIdentification`, which
by default has been mixed into Active Model classes.
Exceptions
----------
+
Active Job provides a way to catch exceptions raised during the execution of the
job:
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 35467fe95b..cb243c95f5 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -276,7 +276,7 @@ This may appear straightforward:
```ruby
# This is very inefficient when the users table has thousands of rows.
User.all.each do |user|
- NewsMailer.weekly(user).deliver
+ NewsMailer.weekly(user).deliver_now
end
```
@@ -292,7 +292,7 @@ The `find_each` method retrieves a batch of records and then yields _each_ recor
```ruby
User.find_each do |user|
- NewsMailer.weekly(user).deliver
+ NewsMailer.weekly(user).deliver_now
end
```
@@ -300,7 +300,7 @@ To add conditions to a `find_each` operation you can chain other Active Record m
```ruby
User.where(weekly_subscriber: true).find_each do |user|
- NewsMailer.weekly(user).deliver
+ NewsMailer.weekly(user).deliver_now
end
```
@@ -316,7 +316,7 @@ The `:batch_size` option allows you to specify the number of records to be retri
```ruby
User.find_each(batch_size: 5000) do |user|
- NewsMailer.weekly(user).deliver
+ NewsMailer.weekly(user).deliver_now
end
```
@@ -328,7 +328,7 @@ For example, to send newsletters only to users with the primary key starting fro
```ruby
User.find_each(start: 2000, batch_size: 5000) do |user|
- NewsMailer.weekly(user).deliver
+ NewsMailer.weekly(user).deliver_now
end
```
@@ -1464,7 +1464,7 @@ Client.connection.select_all("SELECT first_name, created_at FROM clients WHERE i
### `pluck`
-`pluck` can be used to query a single or multiple columns from the underlying table of a model. It accepts a list of column names as argument and returns an array of values of the specified columns with the corresponding data type.
+`pluck` can be used to query single or multiple columns from the underlying table of a model. It accepts a list of column names as argument and returns an array of values of the specified columns with the corresponding data type.
```ruby
Client.where(active: true).pluck(:id)
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 801cef5ca6..38f9609287 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -290,8 +290,6 @@ All these configuration options are delegated to the `I18n` library.
* `config.active_record.partial_writes` is a boolean value and controls whether or not partial writes are used (i.e. whether updates only set attributes that are dirty). Note that when using partial writes, you should also use optimistic locking `config.active_record.lock_optimistically` since concurrent updates may write attributes based on a possibly stale read state. The default value is `true`.
-* `config.active_record.attribute_types_cached_by_default` sets the attribute types that `ActiveRecord::AttributeMethods` will cache by default on reads. The default is `[:datetime, :timestamp, :time, :date]`.
-
* `config.active_record.maintain_test_schema` is a boolean value which controls whether Active Record should try to keep your test database schema up-to-date with `db/schema.rb` (or `db/structure.sql`) when you run your tests. The default is true.
* `config.active_record.dump_schema_after_migration` is a flag which
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index 53b8566d83..88c6210296 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -211,7 +211,7 @@ logger.tagged("BCX") { logger.tagged("Jason") { logger.info "Stuff" } } # Logs "
### Impact of Logs on Performance
Logging will always have a small impact on performance of your rails app,
- particularly when logging to disk.However, there are a few subtleties:
+ particularly when logging to disk. However, there are a few subtleties:
Using the `:debug` level will have a greater performance penalty than `:fatal`,
as a far greater number of strings are being evaluated and written to the
diff --git a/guides/source/development_dependencies_install.md b/guides/source/development_dependencies_install.md
index b134c9d2d0..54b4230e16 100644
--- a/guides/source/development_dependencies_install.md
+++ b/guides/source/development_dependencies_install.md
@@ -100,7 +100,7 @@ For FreeBSD users, you're done with:
Or compile the `databases/sqlite3` port.
-Get a recent version of [Bundler](http://gembundler.com/)
+Get a recent version of [Bundler](http://bundler.io/)
```bash
$ gem install bundler
diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml
index 82e248ee38..5c37837a1c 100644
--- a/guides/source/documents.yaml
+++ b/guides/source/documents.yaml
@@ -75,6 +75,10 @@
url: action_mailer_basics.html
description: This guide describes how to use Action Mailer to send and receive emails.
-
+ name: Active Job Basics
+ url: active_job_basics.html
+ description: This guide provides you with all you need to get started in creating, enqueueing and executing background jobs.
+ -
name: Testing Rails Applications
url: testing.html
work_in_progress: true
@@ -159,6 +163,11 @@
url: upgrading_ruby_on_rails.html
description: This guide helps in upgrading applications to latest Ruby on Rails versions.
-
+ name: Ruby on Rails 4.2 Release Notes
+ url: 4_2_release_notes.html
+ description: Release notes for Rails 4.2.
+ work_in_progress: true
+ -
name: Ruby on Rails 4.1 Release Notes
url: 4_1_release_notes.html
description: Release notes for Rails 4.1.
diff --git a/guides/source/generators.md b/guides/source/generators.md
index 2349908979..f5d2c67cb4 100644
--- a/guides/source/generators.md
+++ b/guides/source/generators.md
@@ -341,15 +341,17 @@ end
If you generate another resource, you can see that we get exactly the same result! This is useful if you want to customize your scaffold templates and/or layout by just creating `edit.html.erb`, `index.html.erb` and so on inside `lib/templates/erb/scaffold`.
-Many scaffold templates in Rails are written in ERB tags which needs to be escaped, so that the output is a valid ERB code, that can be used correctly in Rails app.
+Scaffold templates in Rails frequently use ERB tags; these tags need to be
+escaped so that the generated output is valid ERB code.
-The following code in one of the generator file,
+For example, the following escaped ERB tag would be needed in the template
+(note the extra `%`)...
```ruby
<%%= stylesheet_include_tag :application %>
```
-when passed through the generator, would generate the following output.
+...to generate the following output:
```ruby
<%= stylesheet_include_tag :application %>
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 1f91352c82..964bb30856 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -21,10 +21,10 @@ application from scratch. It does not assume that you have any prior experience
with Rails. However, to get the most out of it, you need to have some
prerequisites installed:
-* The [Ruby](http://www.ruby-lang.org/en/downloads) language version 1.9.3 or newer.
-* The [RubyGems](http://rubygems.org) packaging system, which is installed with Ruby
+* The [Ruby](https://www.ruby-lang.org/en/downloads) language version 1.9.3 or newer.
+* The [RubyGems](https://rubygems.org) packaging system, which is installed with Ruby
versions 1.9 and later. To learn more about RubyGems, please read the [RubyGems Guides](http://guides.rubygems.org).
-* A working installation of the [SQLite3 Database](http://www.sqlite.org).
+* A working installation of the [SQLite3 Database](https://www.sqlite.org).
Rails is a web application framework running on the Ruby programming language.
If you have no prior experience with Ruby, you will find a very steep learning
@@ -101,7 +101,7 @@ If you don't have Ruby installed have a look at
install Ruby on your platform.
Many popular UNIX-like OSes ship with an acceptable version of SQLite3. Windows
-users and others can find installation instructions at [the SQLite3 website](http://www.sqlite.org).
+users and others can find installation instructions at [the SQLite3 website](https://www.sqlite.org).
Verify that it is correctly installed and in your PATH:
```bash
@@ -199,7 +199,7 @@ Rails adds the `therubyracer` gem to the generated `Gemfile` in a
commented line for new apps and you can uncomment if you need it.
`therubyrhino` is the recommended runtime for JRuby users and is added by
default to the `Gemfile` in apps generated under JRuby. You can investigate
-about all the supported runtimes at [ExecJS](https://github.com/sstephenson/execjs#readme).
+all the supported runtimes at [ExecJS](https://github.com/sstephenson/execjs#readme).
This will fire up WEBrick, a web server distributed with Ruby by default. To see
your application in action, open a browser window and navigate to
@@ -748,7 +748,7 @@ to create an article. Try it! You should get an error that looks like this:
(images/getting_started/forbidden_attributes_for_new_article.png)
Rails has several security features that help you write secure applications,
-and you're running into one of them now. This one is called [strong parameters](http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters),
+and you're running into one of them now. This one is called [strong parameters](action_controller_overview.html#strong-parameters),
which requires us to tell Rails exactly which parameters are allowed into our
controller actions.
diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md
index 8b37b92139..60571750a1 100644
--- a/guides/source/layouts_and_rendering.md
+++ b/guides/source/layouts_and_rendering.md
@@ -263,7 +263,7 @@ TIP: This is useful when you're rendering a small snippet of HTML code.
However, you might want to consider moving it to a template file if the markup
is complex.
-NOTE: This option will escape HTML entities if the string is not html safe.
+NOTE: This option will escape HTML entities if the string is not HTML safe.
#### Rendering JSON
diff --git a/guides/source/nested_model_forms.md b/guides/source/nested_model_forms.md
index 4f0634d955..f0ee34cfb1 100644
--- a/guides/source/nested_model_forms.md
+++ b/guides/source/nested_model_forms.md
@@ -1,4 +1,4 @@
-Rails nested model forms
+Rails Nested Model Forms
========================
Creating a form for a model _and_ its associations can become quite tedious. Therefore Rails provides helpers to assist in dealing with the complexities of generating these forms _and_ the required CRUD operations to create, update, and destroy associations.
@@ -54,6 +54,9 @@ class Person < ActiveRecord::Base
end
```
+NOTE: For greater detail on associations see [Active Record Associations](association_basics.html).
+For a complete reference on associations please visit the API documentation for [ActiveRecord::Associations::ClassMethods](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html).
+
### Custom model
As you might have inflected from this explanation, you _don't_ necessarily need an ActiveRecord::Base model to use this functionality. The following examples are sufficient to enable the nested model form behavior:
diff --git a/guides/source/plugins.md b/guides/source/plugins.md
index f10699fbeb..dbccfd4021 100644
--- a/guides/source/plugins.md
+++ b/guides/source/plugins.md
@@ -57,7 +57,7 @@ You can navigate to the directory that contains the plugin, run the `bundle inst
You should see:
```bash
- 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
+ 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
```
This will tell you that everything got generated properly and you are ready to start adding functionality.
@@ -85,9 +85,9 @@ Run `rake` to run the test. This test should fail because we haven't implemented
```bash
1) Error:
- test_to_squawk_prepends_the_word_squawk(CoreExtTest):
- NoMethodError: undefined method `to_squawk' for [Hello World](String)
- test/core_ext_test.rb:5:in `test_to_squawk_prepends_the_word_squawk'
+ CoreExtTest#test_to_squawk_prepends_the_word_squawk:
+ NoMethodError: undefined method `to_squawk' for "Hello World":String
+ /path/to/yaffle/test/core_ext_test.rb:5:in `test_to_squawk_prepends_the_word_squawk'
```
Great - now you are ready to start development.
@@ -118,7 +118,7 @@ end
To test that your method does what it says it does, run the unit tests with `rake` from your plugin directory.
```bash
- 3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
+ 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
```
To see this in action, change to the test/dummy directory, fire up a console and start squawking:
@@ -196,16 +196,16 @@ When you run `rake`, you should see the following:
```
1) Error:
- test_a_hickwalls_yaffle_text_field_should_be_last_squawk(ActsAsYaffleTest):
+ ActsAsYaffleTest#test_a_hickwalls_yaffle_text_field_should_be_last_squawk:
NameError: uninitialized constant ActsAsYaffleTest::Hickwall
- test/acts_as_yaffle_test.rb:6:in `test_a_hickwalls_yaffle_text_field_should_be_last_squawk'
+ /path/to/yaffle/test/acts_as_yaffle_test.rb:6:in `test_a_hickwalls_yaffle_text_field_should_be_last_squawk'
2) Error:
- test_a_wickwalls_yaffle_text_field_should_be_last_tweet(ActsAsYaffleTest):
+ ActsAsYaffleTest#test_a_wickwalls_yaffle_text_field_should_be_last_tweet:
NameError: uninitialized constant ActsAsYaffleTest::Wickwall
- test/acts_as_yaffle_test.rb:10:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
+ /path/to/yaffle/test/acts_as_yaffle_test.rb:10:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
- 5 tests, 3 assertions, 0 failures, 2 errors, 0 skips
+ 4 runs, 2 assertions, 0 failures, 2 errors, 0 skips
```
This tells us that we don't have the necessary models (Hickwall and Wickwall) that we are trying to test.
@@ -270,18 +270,18 @@ You can then return to the root directory (`cd ../..`) of your plugin and rerun
```
1) Error:
- test_a_hickwalls_yaffle_text_field_should_be_last_squawk(ActsAsYaffleTest):
- NoMethodError: undefined method `yaffle_text_field' for #<Class:0x000001016661b8>
- /Users/xxx/.rvm/gems/ruby-1.9.2-p136@xxx/gems/activerecord-3.0.3/lib/active_record/base.rb:1008:in `method_missing'
- test/acts_as_yaffle_test.rb:5:in `test_a_hickwalls_yaffle_text_field_should_be_last_squawk'
+ ActsAsYaffleTest#test_a_hickwalls_yaffle_text_field_should_be_last_squawk:
+ NoMethodError: undefined method `yaffle_text_field' for #<Class:0x007fd105e3b218>
+ activerecord (4.1.5) lib/active_record/dynamic_matchers.rb:26:in `method_missing'
+ /path/to/yaffle/test/acts_as_yaffle_test.rb:6:in `test_a_hickwalls_yaffle_text_field_should_be_last_squawk'
2) Error:
- test_a_wickwalls_yaffle_text_field_should_be_last_tweet(ActsAsYaffleTest):
- NoMethodError: undefined method `yaffle_text_field' for #<Class:0x00000101653748>
- Users/xxx/.rvm/gems/ruby-1.9.2-p136@xxx/gems/activerecord-3.0.3/lib/active_record/base.rb:1008:in `method_missing'
- test/acts_as_yaffle_test.rb:9:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
+ ActsAsYaffleTest#test_a_wickwalls_yaffle_text_field_should_be_last_tweet:
+ NoMethodError: undefined method `yaffle_text_field' for #<Class:0x007fd105e409c0>
+ activerecord (4.1.5) lib/active_record/dynamic_matchers.rb:26:in `method_missing'
+ /path/to/yaffle/test/acts_as_yaffle_test.rb:10:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
- 5 tests, 3 assertions, 0 failures, 2 errors, 0 skips
+ 4 runs, 2 assertions, 0 failures, 2 errors, 0 skips
```
@@ -312,7 +312,7 @@ ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
When you run `rake`, you should see the tests all pass:
```bash
- 5 tests, 5 assertions, 0 failures, 0 errors, 0 skips
+ 4 runs, 4 assertions, 0 failures, 0 errors, 0 skips
```
### Add an Instance Method
@@ -386,7 +386,7 @@ ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
Run `rake` one final time and you should see:
```
- 7 tests, 7 assertions, 0 failures, 0 errors, 0 skips
+ 6 runs, 6 assertions, 0 failures, 0 errors, 0 skips
```
NOTE: The use of `write_attribute` to write to the field in model is just one example of how a plugin can interact with the model, and will not always be the right method to use. For example, you could also use:
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 2ecd560a87..29724ae011 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -99,7 +99,7 @@ one:
Note: For associations to reference one another by name, you cannot specify the `id:`
attribute on the fixtures. Rails will auto assign a primary key to be consistent between
runs. If you manually specify an `id:` attribute, this behavior will not work. For more
- information on this assocation behavior please read the
+ information on this association behavior please read the
[fixture api documentation](http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html).
#### ERB'in It Up
@@ -949,7 +949,7 @@ class UserMailerTest < ActionMailer::TestCase
test "invite" do
# Send the email, then test that it got queued
email = UserMailer.create_invite('me@example.com',
- 'friend@example.com', Time.now).deliver
+ 'friend@example.com', Time.now).deliver_now
assert_not ActionMailer::Base.deliveries.empty?
# Test the body of the sent email contains what we expect it to
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 799d5f3bc9..407445f449 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -50,7 +50,20 @@ Don't forget to review the difference, to see if there were any unexpected chang
Upgrading from Rails 4.1 to Rails 4.2
-------------------------------------
-NOTE: This section is a work in progress.
+NOTE: This section is a work in progress, please help to improve this by sending
+a [pull request](https://github.com/rails/rails/edit/master/guides/source/upgrading_ruby_on_rails.md).
+
+### Web Console
+
+TODO: setup instructions for web console on existing apps.
+
+### Responders
+
+TODO: mention https://github.com/rails/rails/pull/16526
+
+### Error handling in transaction callbacks
+
+TODO: mention https://github.com/rails/rails/pull/16537
### Serialized attributes
@@ -123,6 +136,10 @@ Read the [gem's readme](https://github.com/rails/rails-html-sanitizer) for more
The documentation for `PermitScrubber` and `TargetScrubber` explains how you
can gain complete control over when and how elements should be stripped.
+### Rails DOM Testing
+
+TODO: Mention https://github.com/rails/rails/commit/4e97d7585a2f4788b9eed98c6cdaf4bb6f2cf5ce
+
Upgrading from Rails 4.0 to Rails 4.1
-------------------------------------
@@ -131,7 +148,7 @@ Upgrading from Rails 4.0 to Rails 4.1
Or, "whaaat my tests are failing!!!?"
Cross-site request forgery (CSRF) protection now covers GET requests with
-JavaScript responses, too. That prevents a third-party site from referencing
+JavaScript responses, too. This prevents a third-party site from referencing
your JavaScript URL and attempting to run it to extract sensitive data.
This means that your functional and integration tests that use
@@ -182,8 +199,8 @@ secrets, you need to:
```
2. Use your existing `secret_key_base` from the `secret_token.rb` initializer to
- set the SECRET_KEY_BASE environment variable for whichever users run the Rails
- app in production mode. Alternately, you can simply copy the existing
+ set the SECRET_KEY_BASE environment variable for whichever users running the
+ Rails application in production mode. Alternatively, you can simply copy the existing
`secret_key_base` from the `secret_token.rb` initializer to `secrets.yml`
under the `production` section, replacing '<%= ENV["SECRET_KEY_BASE"] %>'.
@@ -197,7 +214,7 @@ secrets, you need to:
If your test helper contains a call to
`ActiveRecord::Migration.check_pending!` this can be removed. The check
-is now done automatically when you `require 'test_help'`, although
+is now done automatically when you `require 'rails/test_help'`, although
leaving this line in your helper is not harmful in any way.
### Cookies serializer
@@ -386,8 +403,8 @@ ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers
### I18n enforcing available locales
-Rails 4.1 now defaults the I18n option `enforce_available_locales` to `true`,
-meaning that it will make sure that all locales passed to it must be declared in
+Rails 4.1 now defaults the I18n option `enforce_available_locales` to `true`. This
+means that it will make sure that all locales passed to it must be declared in
the `available_locales` list.
To disable it (and allow I18n to accept *any* locale option) add the following
@@ -397,9 +414,10 @@ configuration to your application:
config.i18n.enforce_available_locales = false
```
-Note that this option was added as a security measure, to ensure user input could
-not be used as locale information unless previously known, so it's recommended not
-to disable this option unless you have a strong reason for doing so.
+Note that this option was added as a security measure, to ensure user input
+cannot be used as locale information unless it is previously known. Therefore,
+it's recommended not to disable this option unless you have a strong reason for
+doing so.
### Mutator methods called on Relation
@@ -507,7 +525,7 @@ Using `render :text` may pose a security risk, as the content is sent as
### PostgreSQL json and hstore datatypes
Rails 4.1 will map `json` and `hstore` columns to a string-keyed Ruby `Hash`.
-In earlier versions a `HashWithIndifferentAccess` was used. This means that
+In earlier versions, a `HashWithIndifferentAccess` was used. This means that
symbol access is no longer supported. This is also the case for
`store_accessors` based on top of `json` or `hstore` columns. Make sure to use
string keys consistently.
@@ -597,7 +615,7 @@ being used, you can update your form to use the `PUT` method instead:
<%= form_for [ :update_name, @user ], method: :put do |f| %>
```
-For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/)
+For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/26/edge-rails-patch-is-the-new-primary-http-method-for-updates/)
on the Rails blog.
#### A note about media types
diff --git a/rails.gemspec b/rails.gemspec
index b1a7d16722..a304b16f57 100644
--- a/rails.gemspec
+++ b/rails.gemspec
@@ -28,5 +28,5 @@ Gem::Specification.new do |s|
s.add_dependency 'railties', version
s.add_dependency 'bundler', '>= 1.3.0', '< 2.0'
- s.add_dependency 'sprockets-rails', '~> 2.1'
+ s.add_dependency 'sprockets-rails', '~> 3.0.0.beta1'
end
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 5e2b82c3e9..2a09ccf61a 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,10 @@
+* The [web-console](https://github.com/rails/web-console) gem is now
+ installed by default for new applications. It can help you debug
+ development exceptions by spawnig an interactive console in its cause
+ binding.
+
+ *Ryan Dao*, *Genadi Samokovarov*, *Guillermo Iguaran*
+
* Add a `required` option to the model generator for associations
*Sean Griffin*
@@ -15,14 +22,13 @@
# config/environments/production.rb
config.x.payment_processing.schedule = :daily
config.x.payment_processing.retries = 3
- config.x.super_debugger = true
+ config.x.super_debugger = true
These configuration points are then available through the configuration object:
Rails.configuration.x.payment_processing.schedule # => :daily
Rails.configuration.x.payment_processing.retries # => 3
Rails.configuration.x.super_debugger # => true
- Rails.configuration.x.super_debugger.not_set # => nil
*DHH*
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 782bc4b0f1..9a6a4a52c7 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -155,15 +155,21 @@ module Rails
def annotations
SourceAnnotationExtractor::Annotation
end
-
+
private
- class Custom
+ class Custom #:nodoc:
def initialize
@configurations = Hash.new
end
-
+
def method_missing(method, *args)
- @configurations[method] ||= ActiveSupport::OrderedOptions.new
+ if method =~ /=$/
+ @configurations[$`.to_sym] = args.first
+ else
+ @configurations.fetch(method) {
+ @configurations[method] = ActiveSupport::OrderedOptions.new
+ }
+ end
end
end
end
diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb
index 555d8f31e1..96ced3c2f9 100644
--- a/railties/lib/rails/commands/console.rb
+++ b/railties/lib/rails/commands/console.rb
@@ -18,12 +18,12 @@ module Rails
opt.on("-e", "--environment=name", String,
"Specifies the environment to run this console under (test/development/production).",
"Default: development") { |v| options[:environment] = v.strip }
- opt.on("--debugger", 'Enable the debugger.') do |v|
+ opt.on("--debugger", 'Enables the debugger.') do |v|
if RUBY_VERSION < '2.0.0'
options[:debugger] = v
else
- puts "=> Notice: debugger option is ignored since ruby 2.0 and " \
- "it will be removed in future versions"
+ puts "=> Notice: debugger option is ignored since Ruby 2.0 and " \
+ "it will be removed in future versions."
end
end
opt.parse!(arguments)
diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
index c3b7bb6f84..c479e92ae0 100644
--- a/railties/lib/rails/commands/server.rb
+++ b/railties/lib/rails/commands/server.rb
@@ -20,20 +20,20 @@ module Rails
def option_parser(options)
OptionParser.new do |opts|
- opts.banner = "Usage: rails server [mongrel, thin, etc] [options]"
+ opts.banner = "Usage: rails server [mongrel, thin etc] [options]"
opts.on("-p", "--port=port", Integer,
"Runs Rails on the specified port.", "Default: 3000") { |v| options[:Port] = v }
- opts.on("-b", "--binding=ip", String,
- "Binds Rails to the specified ip.", "Default: 0.0.0.0") { |v| options[:Host] = v }
+ opts.on("-b", "--binding=IP", String,
+ "Binds Rails to the specified IP.", "Default: 0.0.0.0") { |v| options[:Host] = v }
opts.on("-c", "--config=file", String,
- "Use custom rackup configuration file") { |v| options[:config] = v }
- opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:daemonize] = true }
- opts.on("-u", "--debugger", "Enable the debugger") do
+ "Uses a custom rackup configuration.") { |v| options[:config] = v }
+ opts.on("-d", "--daemon", "Runs server as a Daemon.") { options[:daemonize] = true }
+ opts.on("-u", "--debugger", "Enables the debugger.") do
if RUBY_VERSION < '2.0.0'
options[:debugger] = true
else
- puts "=> Notice: debugger option is ignored since ruby 2.0 and " \
- "it will be removed in future versions"
+ puts "=> Notice: debugger option is ignored since Ruby 2.0 and " \
+ "it will be removed in future versions."
end
end
opts.on("-e", "--environment=name", String,
@@ -45,7 +45,7 @@ module Rails
opts.separator ""
- opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
+ opts.on("-h", "--help", "Shows this help message.") { puts opts; exit }
end
end
end
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index caaaae09e6..b3a67266f7 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -198,15 +198,9 @@ module Rails
def rails_gemfile_entry
if options.dev?
- [GemfileEntry.path('rails', Rails::Generators::RAILS_DEV_PATH),
- GemfileEntry.github('arel', 'rails/arel'),
- GemfileEntry.github('rack', 'rack/rack'),
- GemfileEntry.github('i18n', 'svenfuchs/i18n')]
+ [GemfileEntry.path('rails', Rails::Generators::RAILS_DEV_PATH)]
elsif options.edge?
- [GemfileEntry.github('rails', 'rails/rails'),
- GemfileEntry.github('arel', 'rails/arel'),
- GemfileEntry.github('rack', 'rack/rack'),
- GemfileEntry.github('i18n', 'svenfuchs/i18n')]
+ [GemfileEntry.github('rails', 'rails/rails')]
else
[GemfileEntry.version('rails',
Rails::VERSION::STRING,
@@ -252,7 +246,7 @@ module Rails
'Use SCSS for stylesheets')
else
gems << GemfileEntry.version('sass-rails',
- '~> 4.0.3',
+ '~> 5.0.0.beta1',
'Use SCSS for stylesheets')
end
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile
index 337f4dd6c1..72143301a6 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile
@@ -16,9 +16,7 @@ source 'https://rubygems.org'
# gem 'bcrypt', '~> 3.1.7'
# Use Rails Html Sanitizer for HTML sanitization
-gem 'rails-html-snaitizer', github: 'rails/rails', branch: 'master'
-#temporary gem until a new version of loofah is released
-gem 'loofah', github: 'kaspth/loofah', branch: 'single-scrub'
+gem 'rails-html-sanitizer', '~> 1.0'
# Use Unicorn as the app server
# gem 'unicorn'
@@ -36,7 +34,7 @@ group :development, :test do
<%- end -%>
# Access an IRB console on exceptions page and /console in development
- gem 'web-console', '2.0.0.beta1'
+ gem 'web-console', '~> 2.0.0.beta2'
<%- if spring_install? %>
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb
index 16fe50bab8..80393a16ba 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb
@@ -5,6 +5,7 @@ require 'rails/all'
<% else -%>
# Pick the frameworks you want:
require "active_model/railtie"
+require "active_job/railtie"
<%= comment_if :skip_active_record %>require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
@@ -30,5 +31,10 @@ module <%= app_const_base %>
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
+ <%- unless options.skip_active_record? -%>
+
+ # For not swallow errors in after_commit/after_rollback callbacks.
+ config.active_record.raise_in_transactional_callbacks = true
+ <%- end -%>
end
end
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
index 35e3035a0b..d8326d1728 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
@@ -30,7 +30,7 @@ Rails.application.configure do
# number of complex assets.
config.assets.debug = true
- # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
index bec7716a9b..bbfd9505bc 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -30,7 +30,7 @@ Rails.application.configure do
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
- # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
diff --git a/railties/lib/rails/generators/rails/model/USAGE b/railties/lib/rails/generators/rails/model/USAGE
index 2a6b8700e3..8c3b63c3b4 100644
--- a/railties/lib/rails/generators/rails/model/USAGE
+++ b/railties/lib/rails/generators/rails/model/USAGE
@@ -46,7 +46,6 @@ Available field types:
date
time
datetime
- timestamp
You can also consider `references` as a kind of type. For instance, if you run:
diff --git a/railties/test/application/configuration/custom_test.rb b/railties/test/application/configuration/custom_test.rb
index 045537fc28..f8d22f6d97 100644
--- a/railties/test/application/configuration/custom_test.rb
+++ b/railties/test/application/configuration/custom_test.rb
@@ -3,13 +3,20 @@ require 'application/configuration/base_test'
class ApplicationTests::ConfigurationTests::CustomTest < ApplicationTests::ConfigurationTests::BaseTest
test 'access custom configuration point' do
add_to_config <<-RUBY
- config.x.resque.inline_jobs = :always
- config.x.resque.timeout = 60
+ config.x.payment_processing.schedule = :daily
+ config.x.payment_processing.retries = 3
+ config.x.super_debugger = true
+ config.x.hyper_debugger = false
+ config.x.nil_debugger = nil
RUBY
require_environment
- assert_equal :always, Rails.configuration.x.resque.inline_jobs
- assert_equal 60, Rails.configuration.x.resque.timeout
- assert_nil Rails.configuration.x.resque.nothing
+ x = Rails.configuration.x
+ assert_equal :daily, x.payment_processing.schedule
+ assert_equal 3, x.payment_processing.retries
+ assert_equal true, x.super_debugger
+ assert_equal false, x.hyper_debugger
+ assert_equal nil, x.nil_debugger
+ assert_nil x.i_do_not_exist.zomg
end
end
diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb
index 946b82eeb3..97d5b5c698 100644
--- a/railties/test/application/middleware/remote_ip_test.rb
+++ b/railties/test/application/middleware/remote_ip_test.rb
@@ -1,3 +1,4 @@
+require 'ipaddr'
require 'isolation/abstract_unit'
require 'active_support/key_generator'
@@ -53,12 +54,25 @@ module ApplicationTests
end
end
+ test "remote_ip works with HTTP_X_FORWARDED_FOR" do
+ make_basic_app
+ assert_equal "4.2.42.42", remote_ip("REMOTE_ADDR" => "1.1.1.1", "HTTP_X_FORWARDED_FOR" => "4.2.42.42")
+ end
+
test "the user can set trusted proxies" do
make_basic_app do |app|
app.config.action_dispatch.trusted_proxies = /^4\.2\.42\.42$/
end
- assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "4.2.42.42,1.1.1.1")
+ assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1", "HTTP_X_FORWARDED_FOR" => "4.2.42.42")
+ end
+
+ test "the user can set trusted proxies with an IPAddr argument" do
+ make_basic_app do |app|
+ app.config.action_dispatch.trusted_proxies = IPAddr.new('4.2.42.0/24')
+ end
+
+ assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1", "HTTP_X_FORWARDED_FOR" => "10.0.0.0,4.2.42.42")
end
end
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 70c439672f..d687a8f506 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -395,6 +395,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
run_generator [destination_root, "--skip-test-unit", "--skip-active-record"]
assert_file "config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
+ assert_file "config/application.rb", /\s+require\s+["']active_job\/railtie["']/
end
def test_new_hash_style
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 92d6a1729c..b38cc4277e 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -276,8 +276,12 @@ module TestHelpers
end
def use_frameworks(arr)
- to_remove = [:actionmailer,
- :activerecord] - arr
+ to_remove = [:actionmailer, :activerecord] - arr
+
+ if to_remove.include?(:activerecord)
+ remove_from_config 'config.active_record.*'
+ end
+
$:.reject! {|path| path =~ %r'/(#{to_remove.join('|')})/' }
end