From 06860dcf29d73c0c4fbe5a42fde4db0ce9753937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 4 Feb 2010 14:14:11 +0100 Subject: Remove duplicated version check. --- railties/lib/rails/commands.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 4240038673..55744db275 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -60,8 +60,6 @@ when 'runner' require ENV_PATH -when '--version', '-v' - puts "Rails #{Rails::VERSION::STRING}" when '--help', '-h' puts HELP_TEXT when '--version', '-v' -- cgit v1.2.3 From 25b6b95459ae71218754e8469f77f86b676bf215 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Thu, 4 Feb 2010 17:00:50 +0000 Subject: Make RAILS_* give deprecation warning just once --- railties/lib/rails/deprecation.rb | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/deprecation.rb b/railties/lib/rails/deprecation.rb index f28da5a6b0..1eb6d804b6 100644 --- a/railties/lib/rails/deprecation.rb +++ b/railties/lib/rails/deprecation.rb @@ -2,6 +2,9 @@ require "active_support/string_inquirer" require "active_support/deprecation" RAILS_ROOT = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do + cattr_accessor :warned + self.warned = false + def target Rails.root end @@ -11,12 +14,17 @@ RAILS_ROOT = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do end def warn(callstack, called, args) - msg = "RAILS_ROOT is deprecated! Use Rails.root instead" - ActiveSupport::Deprecation.warn(msg, callstack) + unless warned + ActiveSupport::Deprecation.warn("RAILS_ROOT is deprecated! Use Rails.root instead", callstack) + self.warned = true + end end end).new RAILS_ENV = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do + cattr_accessor :warned + self.warned = false + def target Rails.env end @@ -26,12 +34,17 @@ RAILS_ENV = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do end def warn(callstack, called, args) - msg = "RAILS_ENV is deprecated! Use Rails.env instead" - ActiveSupport::Deprecation.warn(msg, callstack) + unless warned + ActiveSupport::Deprecation.warn("RAILS_ENV is deprecated! Use Rails.env instead", callstack) + self.warned = true + end end end).new RAILS_DEFAULT_LOGGER = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do + cattr_accessor :warned + self.warned = false + def target Rails.logger end @@ -41,7 +54,9 @@ RAILS_DEFAULT_LOGGER = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) end def warn(callstack, called, args) - msg = "RAILS_DEFAULT_LOGGER is deprecated! Use Rails.logger instead" - ActiveSupport::Deprecation.warn(msg, callstack) + unless warned + ActiveSupport::Deprecation.warn("RAILS_DEFAULT_LOGGER is deprecated! Use Rails.logger instead", callstack) + self.warned = true + end end end).new -- cgit v1.2.3 From 6b3fb384615003ae6cf74e8acfdb8bea9c0f683d Mon Sep 17 00:00:00 2001 From: Antonio Cangiano Date: Thu, 4 Feb 2010 12:21:27 -0500 Subject: Updated the database.yml file generated for ibm_db to the latest version of DB2 and the gem. [#3852 state:committed] Signed-off-by: Jeremy Kemper --- .../app/templates/config/databases/ibm_db.yml | 31 ++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml index 2cecb5c879..2784a949fb 100644 --- a/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml @@ -4,23 +4,32 @@ # http://rubyforge.org/projects/rubyibm/ # # To install the ibm_db gem: +# # On Linux: -# Source the db2profile file and set the necessary environment variables: +# . /home/db2inst1/sqllib/db2profile +# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include +# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib32 +# gem install ibm_db # +# On Mac OS X 10.5: # . /home/db2inst1/sqllib/db2profile -# export IBM_DB_DIR=/opt/ibm/db2/V9.1 -# export IBM_DB_LIB=/opt/ibm/db2/V9.1/lib32 +# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include +# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib32 +# export ARCHFLAGS="-arch i386" +# gem install ibm_db # -# Then issue the command: gem install ibm_db +# On Mac OS X 10.6: +# . /home/db2inst1/sqllib/db2profile +# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include +# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib64 +# export ARCHFLAGS="-arch x86_64" +# gem install ibm_db # # On Windows: -# Issue the command: gem install ibm_db -# If prompted, select the mswin32 option -# -# For more details on the installation refer to http://rubyforge.org/docman/view.php/2361/7682/IBM_DB_GEM.pdf +# Issue the command: gem install ibm_db # -# For more details on the connection parameters below refer to: -# http://rubyibm.rubyforge.org/docs/adapter/0.9.0/rdoc/classes/ActiveRecord/ConnectionAdapters/IBM_DBAdapter.html +# For more details on the installation and the connection parameters below, +# please refer to the latest documents at http://rubyforge.org/docman/?group_id=2361 development: adapter: ibm_db @@ -52,7 +61,7 @@ production: adapter: ibm_db username: db2inst1 password: - database: <%= app_name[0,4] %>_prd + database: <%= app_name[0,8] %> #schema: db2inst1 #host: localhost #port: 50000 -- cgit v1.2.3 From 5c07c33ab4de037aeb1f6cc6817fddd28f9a35d2 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 09:28:41 -0800 Subject: Move framework requires and Bundler.require from boot.rb to app.rb. Cut down the list of railtie choices to those that make sense. --- .../rails/app/templates/config/application.rb | 14 +++++++++++ .../generators/rails/app/templates/config/boot.rb | 29 ---------------------- 2 files changed, 14 insertions(+), 29 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/config/application.rb b/railties/lib/generators/rails/app/templates/config/application.rb index 78a355d2f4..2872d187ba 100644 --- a/railties/lib/generators/rails/app/templates/config/application.rb +++ b/railties/lib/generators/rails/app/templates/config/application.rb @@ -1,5 +1,19 @@ require File.expand_path('../boot', __FILE__) +<% unless options[:skip_activerecord] -%> +require 'rails/all' +<% else -%> +# Pick the frameworks you want: +# require "active_record/railtie" +require "action_controller/railtie" +require "action_mailer/railtie" +require "active_resource/railtie" +require "rails/test_unit/railtie" +<% end -%> + +# Auto-require all bundled libraries. +Bundler.require + module <%= app_const_base %> class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. diff --git a/railties/lib/generators/rails/app/templates/config/boot.rb b/railties/lib/generators/rails/app/templates/config/boot.rb index 03396113e8..29c9d506e5 100644 --- a/railties/lib/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/generators/rails/app/templates/config/boot.rb @@ -15,32 +15,3 @@ rescue LoadError # # require 'rubygems' end - -# Auto-require all bundled libraries. -Bundler.require - -<% unless options[:skip_activerecord] -%> -require 'rails/all' - -# To pick the frameworks you want, remove 'require "rails/all"' -# and list the framework railties that you want: -# -# require "active_support/railtie" -# require "active_model/railtie" -# require "active_record/railtie" -# require "action_controller/railtie" -# require "action_view/railtie" -# require "action_mailer/railtie" -# require "active_resource/railtie" -# require "rails/test_unit/railtie" -<% else -%> -# Pick the frameworks you want: -# require "active_model/railtie" -# require "active_record/railtie" -require "active_support/railtie" -require "action_controller/railtie" -require "action_view/railtie" -require "action_mailer/railtie" -require "active_resource/railtie" -require "rails/test_unit/railtie" -<% end -%> -- cgit v1.2.3 From 23ad1eff0dab4079b7bc68f71df537fc85582d05 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 09:29:18 -0800 Subject: Rationalize railtie dependencies: AC uses AV; AR uses AMo; and Rails always uses AS. --- railties/lib/rails/all.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb index 1a0b4a8d73..82775b7e3b 100644 --- a/railties/lib/rails/all.rb +++ b/railties/lib/rails/all.rb @@ -1,11 +1,8 @@ require "rails" %w( - active_support - active_model active_record action_controller - action_view action_mailer active_resource rails/test_unit @@ -14,4 +11,4 @@ require "rails" require "#{framework}/railtie" rescue LoadError end -end \ No newline at end of file +end -- cgit v1.2.3 From 358451c2194c5b89b576fd623811da708ee89d95 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 10:45:35 -0800 Subject: Rails script commands load the application rather than just boot --- railties/lib/generators/rails/app/templates/script/rails | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/script/rails b/railties/lib/generators/rails/app/templates/script/rails index 2fcf6d09b5..e99d50f695 100644 --- a/railties/lib/generators/rails/app/templates/script/rails +++ b/railties/lib/generators/rails/app/templates/script/rails @@ -5,5 +5,5 @@ BOOT_PATH = File.expand_path('../../config/boot', __FILE__) APP_PATH = File.expand_path('../../config/application', __FILE__) ROOT_PATH = File.expand_path('../..', __FILE__) -require BOOT_PATH +require APP_PATH require 'rails/commands' -- cgit v1.2.3 From ca273d171c2663317842dba2152ba930f03e8e81 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 10:49:41 -0800 Subject: Revert "Rails script commands load the application rather than just boot" This reverts commit 358451c2194c5b89b576fd623811da708ee89d95. --- railties/lib/generators/rails/app/templates/script/rails | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/script/rails b/railties/lib/generators/rails/app/templates/script/rails index e99d50f695..2fcf6d09b5 100644 --- a/railties/lib/generators/rails/app/templates/script/rails +++ b/railties/lib/generators/rails/app/templates/script/rails @@ -5,5 +5,5 @@ BOOT_PATH = File.expand_path('../../config/boot', __FILE__) APP_PATH = File.expand_path('../../config/application', __FILE__) ROOT_PATH = File.expand_path('../..', __FILE__) -require APP_PATH +require BOOT_PATH require 'rails/commands' -- cgit v1.2.3 From 293fd9daf82c99d1dd57528ad0b770fad4cb8ce2 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 10:50:14 -0800 Subject: server command loads the application --- railties/lib/rails/commands.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 55744db275..500dcf7f9e 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -33,6 +33,7 @@ when 'c', 'console' require APP_PATH Rails::Console.start(Rails::Application) when 's', 'server' + require APP_PATH require 'rails/commands/server' Dir.chdir(ROOT_PATH) Rails::Server.start @@ -68,4 +69,4 @@ when '--version', '-v' else puts "Error: Command not recognized" puts HELP_TEXT -end \ No newline at end of file +end -- cgit v1.2.3 From a74ed0c2eef87d7fd159d9ac294ced33f4b10bfc Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 11:04:50 -0800 Subject: Autorequire default libs and those in groups named after the current Rails environment --- railties/lib/generators/rails/app/templates/config/application.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/config/application.rb b/railties/lib/generators/rails/app/templates/config/application.rb index 2872d187ba..7c555c2542 100644 --- a/railties/lib/generators/rails/app/templates/config/application.rb +++ b/railties/lib/generators/rails/app/templates/config/application.rb @@ -11,8 +11,8 @@ require "active_resource/railtie" require "rails/test_unit/railtie" <% end -%> -# Auto-require all bundled libraries. -Bundler.require +# Auto-require default libraries and those for the current Rails environment. +Bundler.require :default, Rails.env module <%= app_const_base %> class Application < Rails::Application -- cgit v1.2.3 From 127e53453dc52e07aff877212e204084f7321529 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 12:22:26 -0800 Subject: Ensure javascripts are pulled in so UJS can hook the Delete link --- railties/lib/generators/erb/scaffold/templates/layout.html.erb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/generators/erb/scaffold/templates/layout.html.erb b/railties/lib/generators/erb/scaffold/templates/layout.html.erb index 7aa049fe80..496de90ebb 100644 --- a/railties/lib/generators/erb/scaffold/templates/layout.html.erb +++ b/railties/lib/generators/erb/scaffold/templates/layout.html.erb @@ -3,6 +3,7 @@ <%= controller_class_name %>: <%%= controller.action_name %> <%%= stylesheet_link_tag 'scaffold' %> + <%%= javascript_include_tag :defaults %> -- cgit v1.2.3 From 78de17cf7095af8e86d192af8d8fbe21e6f193d9 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 14:15:16 -0800 Subject: Expose CSRF tag for UJS adapters --- railties/lib/generators/erb/scaffold/templates/layout.html.erb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties/lib') diff --git a/railties/lib/generators/erb/scaffold/templates/layout.html.erb b/railties/lib/generators/erb/scaffold/templates/layout.html.erb index 496de90ebb..420d17f33c 100644 --- a/railties/lib/generators/erb/scaffold/templates/layout.html.erb +++ b/railties/lib/generators/erb/scaffold/templates/layout.html.erb @@ -4,6 +4,7 @@ <%= controller_class_name %>: <%%= controller.action_name %> <%%= stylesheet_link_tag 'scaffold' %> <%%= javascript_include_tag :defaults %> + <%%= csrf_meta_tag %> -- cgit v1.2.3 From 358968cd28b23c79a9311b5f88dce14fed686e97 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 17:46:29 -0800 Subject: Update prototype-ujs for data-confirm --- .../rails/app/templates/public/javascripts/rails.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js index 2a0a05d25f..8e2e0d259d 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js @@ -34,6 +34,12 @@ document.observe("dom:loaded", function() { } $(document.body).observe("click", function(event) { + var message = event.element().readAttribute('data-confirm'); + if (message && !confirm(message)) { + event.stop(); + return false; + } + var element = event.findElement("a[data-remote=true]"); if (element) { handleRemote(element); @@ -41,13 +47,14 @@ document.observe("dom:loaded", function() { } }); - $(document.body).observe("ajax:before", function(event) { - var message = event.element().readAttribute('data-confirm'); - if (message && !confirm(message)) event.stop(); - }); - // TODO: I don't think submit bubbles in IE $(document.body).observe("submit", function(event) { + var message = event.element().readAttribute('data-confirm'); + if (message && !confirm(message)) { + event.stop(); + return false; + } + var inputs = event.element().select("input[type=submit][data-disable-with]"); inputs.each(function(input) { input.disabled = true; -- cgit v1.2.3 From 7b1d3a0ca38c480ef65e78d28f2b18573b8abd74 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Thu, 4 Feb 2010 18:01:08 -0800 Subject: Add prototype ujs handler for data-method --- .../app/templates/public/javascripts/rails.js | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js index 8e2e0d259d..f7ddba390a 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js @@ -1,4 +1,11 @@ document.observe("dom:loaded", function() { + var authToken = $$('meta[name=csrf-token]').first().readAttribute('content'), + authParam = $$('meta[name=csrf-param]').first().readAttribute('content'), + formTemplate = '
\ + #{realmethod}\ +
', + realmethodTemplate = ''; + function handleRemote(element) { var method, url, params; @@ -45,6 +52,25 @@ document.observe("dom:loaded", function() { handleRemote(element); event.stop(); } + + var element = event.findElement("a[data-method]"); + if (element && element.readAttribute('data-remote') != 'true') { + var method = element.readAttribute('data-method'), + piggyback = method.toLowerCase() != 'post', + formHTML = formTemplate.interpolate({ + method: 'POST', + realmethod: piggyback ? realmethodTemplate.interpolate({ method: method }) : '', + action: element.readAttribute('href'), + token: authToken, + param: authParam + }); + + var form = new Element('div').update(formHTML).down().hide(); + this.insert({ bottom: form }); + + form.submit(); + event.stop(); + } }); // TODO: I don't think submit bubbles in IE -- cgit v1.2.3 From c548e213658386f3a5b00097bc5b30bf3736e6b4 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 5 Feb 2010 09:24:12 -0800 Subject: Bump git versions to 3.0.0.beta1 since we've released --- railties/lib/rails/tasks/documentation.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake index 7095046f21..f7cc6ff4be 100644 --- a/railties/lib/rails/tasks/documentation.rake +++ b/railties/lib/rails/tasks/documentation.rake @@ -14,7 +14,7 @@ namespace :doc do desc 'Generate documentation for the Rails framework. Specify path with PATH="/path/to/rails"' Rake::RDocTask.new("rails") { |rdoc| path = ENV['RAILS_PATH'] || 'vendor/gems/gems' - version = '-3.0.0.beta' unless ENV['RAILS_PATH'] + version = '-3.0.0.beta1' unless ENV['RAILS_PATH'] rdoc.rdoc_dir = 'doc/api' rdoc.template = "#{ENV['template']}.rb" if ENV['template'] rdoc.title = "Rails Framework Documentation" -- cgit v1.2.3 From 6201abe73f7100b93727c6a0d549651df737948a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:33:24 -0800 Subject: New style for path references --- railties/lib/generators/rails/app/templates/Gemfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index f51edc4d2f..1ceb5a7bcc 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -7,8 +7,7 @@ gem "rails", "<%= Rails::VERSION::STRING %>" ## Bundle edge rails: <%- if options.dev? -%> -path "<%= Rails::Generators::RAILS_DEV_PATH %>", :glob => "{*/,}*.gemspec" -gem "rails", "<%= Rails::VERSION::STRING %>" +gem "rails", "<%= Rails::VERSION::STRING %>", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" <%- else -%> <%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> -- cgit v1.2.3 From 0ce9c80c0a3a7d09ffd61f8b09093afbb6239c14 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:35:19 -0800 Subject: Path approach shouldnt specify version --- railties/lib/generators/rails/app/templates/Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 1ceb5a7bcc..54aa53a181 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -7,7 +7,7 @@ gem "rails", "<%= Rails::VERSION::STRING %>" ## Bundle edge rails: <%- if options.dev? -%> -gem "rails", "<%= Rails::VERSION::STRING %>", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" +gem "rails", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" <%- else -%> <%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> -- cgit v1.2.3 From cbb0b2f6f379df85959e95dce1e7b359197489c7 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:41:15 -0800 Subject: Simplify conditions for --dev and --edge --- railties/lib/generators/rails/app/templates/Gemfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 54aa53a181..2cc257fbd8 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -1,15 +1,15 @@ # Edit this Gemfile to bundle your application's dependencies. source 'http://gemcutter.org' -<% if !dev_or_edge? %> -gem "rails", "<%= Rails::VERSION::STRING %>" -<% end -%> - -## Bundle edge rails: <%- if options.dev? -%> gem "rails", :path => "<%= Rails::Generators::RAILS_DEV_PATH %>" +<%- elsif options.edge? -%> +gem "rails", :git => "git://github.com/rails/rails.git" <%- else -%> -<%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git" +gem "rails", "<%= Rails::VERSION::STRING %>" + +# Bundle edge Rails instead +# gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> <% unless options[:skip_activerecord] -%> -- cgit v1.2.3 From 33a90f5079617f0b3422d24ef72e6c4d88552427 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:41:46 -0800 Subject: Not a fan of the double ## --- railties/lib/generators/rails/app/templates/Gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 2cc257fbd8..3148269b6d 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -20,13 +20,13 @@ gem "rails", "<%= Rails::VERSION::STRING %>" gem "<%= gem_for_database %>"<% if require_for_database %>, :require => "<%= require_for_database %>"<% end %> <% end -%> -## Bundle the gems you use: +# Bundle the gems you use: # gem "bj" # gem "hpricot", "0.6" # gem "sqlite3-ruby", :require => "sqlite3" # gem "aws-s3", :require => "aws/s3" -## Bundle gems used only in certain environments: +# Bundle gems used only in certain environments: # gem "rspec", :group => :test # group :test do # gem "webrat" -- cgit v1.2.3 From c76df7a2d5b630adf52f89af01fe7fe8f097d199 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 5 Feb 2010 18:45:26 -0800 Subject: Cleanup comments --- railties/lib/generators/rails/app/templates/Gemfile | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile index 3148269b6d..f89dbe1e63 100644 --- a/railties/lib/generators/rails/app/templates/Gemfile +++ b/railties/lib/generators/rails/app/templates/Gemfile @@ -1,4 +1,3 @@ -# Edit this Gemfile to bundle your application's dependencies. source 'http://gemcutter.org' <%- if options.dev? -%> @@ -8,25 +7,21 @@ gem "rails", :git => "git://github.com/rails/rails.git" <%- else -%> gem "rails", "<%= Rails::VERSION::STRING %>" -# Bundle edge Rails instead +# Bundle edge Rails instead: # gem "rails", :git => "git://github.com/rails/rails.git" <%- end -%> <% unless options[:skip_activerecord] -%> -<% if options[:database] == 'sqlite3' -%> -# ActiveRecord requires a database adapter. By default, -# Rails has selected sqlite3. -<% end -%> gem "<%= gem_for_database %>"<% if require_for_database %>, :require => "<%= require_for_database %>"<% end %> <% end -%> -# Bundle the gems you use: +# Bundle the extra gems: # gem "bj" # gem "hpricot", "0.6" # gem "sqlite3-ruby", :require => "sqlite3" # gem "aws-s3", :require => "aws/s3" -# Bundle gems used only in certain environments: +# Bundle gems for certain environments: # gem "rspec", :group => :test # group :test do # gem "webrat" -- cgit v1.2.3 From 95b63c6a078527b747c99ab1c881fdfe6577518b Mon Sep 17 00:00:00 2001 From: Henrik N Date: Sat, 6 Feb 2010 12:48:02 +0100 Subject: Fix 'rails server -h' double help banner. Correct its usage line. [#3874 status:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/lib/rails/commands/server.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index b21ae2a17b..c27214d3c8 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -9,6 +9,7 @@ module Rails options = {} args = args.dup opt_parser = OptionParser.new do |opts| + opts.banner = "Usage: rails server [options]" opts.on("-p", "--port=port", Integer, "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v } opts.on("-b", "--binding=ip", String, @@ -48,7 +49,9 @@ module Rails super ensure - puts 'Exiting' unless options[:daemonize] + # The '-h' option calls exit before @options is set. + # If we call 'options' with it unset, we get double help banners. + puts 'Exiting' unless @options && options[:daemonize] end def middleware -- cgit v1.2.3 From 1d9d9d2d89a90a85f27a1909e3c435c070bc1b40 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sat, 6 Feb 2010 21:36:46 +0700 Subject: Fix tiny version number from '3.0.0beta' to '3.0.0.beta1', so 'rake install' will be run correctly [#3879 status:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/lib/rails/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb index c327d4545a..d0c7cb45db 100644 --- a/railties/lib/rails/version.rb +++ b/railties/lib/rails/version.rb @@ -2,7 +2,7 @@ module Rails module VERSION #:nodoc: MAJOR = 3 MINOR = 0 - TINY = "0.beta" + TINY = "0.beta1" STRING = [MAJOR, MINOR, TINY].join('.') end -- cgit v1.2.3 From 6958eac1a00a4ab33e3facc70c80a07492288196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 6 Feb 2010 17:32:06 +0100 Subject: Add config.generators.templates to provide alternative paths for template lookup. --- railties/lib/rails/configuration.rb | 3 ++- railties/lib/rails/engine.rb | 4 ++++ railties/lib/rails/engine/configuration.rb | 1 + railties/lib/rails/generators.rb | 5 +++++ railties/lib/rails/generators/base.rb | 3 +-- 5 files changed, 13 insertions(+), 3 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 7887a5d25f..50675d19b8 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -88,12 +88,13 @@ module Rails end class Generators #:nodoc: - attr_accessor :aliases, :options, :fallbacks, :colorize_logging + attr_accessor :aliases, :options, :templates, :fallbacks, :colorize_logging def initialize @aliases = Hash.new { |h,k| h[k] = {} } @options = Hash.new { |h,k| h[k] = {} } @fallbacks = {} + @templates = [] @colorize_logging = true end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 33d62c8155..5983a9ee6b 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -102,6 +102,10 @@ module Rails app.metal_loader.paths.unshift(*paths.app.metals.to_a) end + initializer :add_generator_templates do |app| + config.generators.templates.unshift(*paths.lib.templates.to_a) + end + initializer :load_application_initializers do paths.config.initializers.to_a.sort.each do |initializer| load(initializer) diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 7d6de91430..93b882f874 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -21,6 +21,7 @@ module Rails paths.app.views "app/views" paths.lib "lib", :load_path => true paths.lib.tasks "lib/tasks", :glob => "**/*.rake" + paths.lib.templates "lib/templates" paths.config "config" paths.config.initializers "config/initializers", :glob => "**/*.rb" paths.config.locales "config/locales", :glob => "*.{rb,yml}" diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 5d95f2fa52..5779357226 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -66,6 +66,11 @@ module Rails aliases.deep_merge! config.aliases options.deep_merge! config.options fallbacks.merge! config.fallbacks + templates_path.concat config.templates + end + + def self.templates_path + @templates_path ||= [] end def self.aliases #:nodoc: diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index dfa0d573c9..c801e2fec3 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -213,8 +213,7 @@ module Rails if base.name && base.name !~ /Base$/ Rails::Generators.subclasses << base - if defined?(Rails.root) && Rails.root - path = File.expand_path(File.join(Rails.root, 'lib', 'templates')) + Rails::Generators.templates_path.each do |path| if base.name.include?('::') base.source_paths << File.join(path, base.base_name, base.generator_name) else -- cgit v1.2.3 From bd5cb0562e93a1a0e225ee2bc9042c0e5bdb39dd Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sat, 6 Feb 2010 18:35:44 +0100 Subject: rack debugger needs active_support/core_ext/kernel/requires for require_library_or_gem --- railties/lib/rails/rack/debugger.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/rack/debugger.rb b/railties/lib/rails/rack/debugger.rb index 0a7b405553..93a743a747 100644 --- a/railties/lib/rails/rack/debugger.rb +++ b/railties/lib/rails/rack/debugger.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/kernel/requires' + module Rails module Rack class Debugger -- cgit v1.2.3 From f44a0b1d524064a2e919cd10d3013db680af9b17 Mon Sep 17 00:00:00 2001 From: RomD Date: Sat, 6 Feb 2010 17:18:10 +0100 Subject: fix usage examples and more to use new invocations Signed-off-by: Carl Lerche --- railties/lib/generators/rails/app/templates/README | 16 ++++++++-------- railties/lib/generators/rails/controller/USAGE | 2 +- railties/lib/generators/rails/generator/USAGE | 2 +- .../lib/generators/rails/generator/templates/USAGE.tt | 2 +- railties/lib/generators/rails/helper/USAGE | 2 +- railties/lib/generators/rails/integration_test/USAGE | 2 +- railties/lib/generators/rails/mailer/USAGE | 2 +- railties/lib/generators/rails/metal/USAGE | 2 +- railties/lib/generators/rails/migration/USAGE | 4 ++-- railties/lib/generators/rails/model/USAGE | 4 ++-- railties/lib/generators/rails/observer/USAGE | 2 +- railties/lib/generators/rails/performance_test/USAGE | 2 +- railties/lib/generators/rails/plugin/USAGE | 2 +- railties/lib/generators/rails/resource/USAGE | 6 +++--- railties/lib/generators/rails/scaffold/USAGE | 8 ++++---- railties/lib/generators/rails/scaffold_controller/USAGE | 2 +- railties/lib/generators/rails/session_migration/USAGE | 2 +- railties/lib/generators/rails/stylesheets/USAGE | 2 +- railties/lib/rails/commands/console.rb | 2 +- railties/lib/rails/commands/plugin.rb | 12 ++++++------ railties/lib/rails/generators/actions.rb | 4 ++-- railties/lib/rails/generators/base.rb | 8 ++++---- railties/lib/rails/rack/debugger.rb | 2 +- 23 files changed, 46 insertions(+), 46 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/README b/railties/lib/generators/rails/app/templates/README index 37ec8ea211..b175146797 100644 --- a/railties/lib/generators/rails/app/templates/README +++ b/railties/lib/generators/rails/app/templates/README @@ -29,14 +29,14 @@ link:files/vendor/rails/actionpack/README.html. 1. At the command prompt, start a new Rails application using the rails command and your application name. Ex: rails myapp -2. Change directory into myapp and start the web server: script/server (run with --help for options) +2. Change directory into myapp and start the web server: rails server (run with --help for options) 3. Go to http://localhost:3000/ and get "Welcome aboard: You're riding the Rails!" 4. Follow the guidelines to start developing your application == Web Servers -By default, Rails will try to use Mongrel if it's are installed when started with script/server, otherwise Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails +By default, Rails will try to use Mongrel if it's are installed when started with rails server, otherwise Rails will use WEBrick, the webserver that ships with Ruby. But you can also use Rails with a variety of other web servers. Mongrel is a Ruby-based webserver with a C component (which requires compilation) that is @@ -164,20 +164,20 @@ Finally, when you're ready to resume execution, you enter "cont" == Console -You can interact with the domain model by starting the console through script/console. +You can interact with the domain model by starting the console through rails console. Here you'll have all parts of the application configured, just like it is when the application is running. You can inspect domain models, change values, and save to the database. Starting the script without arguments will launch it in the development environment. -Passing an argument will specify a different environment, like script/console production. +Passing an argument will specify a different environment, like rails console production. To reload your controllers and models after launching the console run reload! == dbconsole -You can go to the command line of your database directly through script/dbconsole. +You can go to the command line of your database directly through rails dbconsole. You would be connected to the database with the credentials defined in database.yml. Starting the script without arguments will connect you to the development database. Passing an -argument will connect you to a different database, like script/dbconsole production. +argument will connect you to a different database, like rails dbconsole production. Currently works for mysql, postgresql and sqlite. == Description of Contents @@ -207,7 +207,7 @@ app/views/layouts app/helpers Holds view helpers that should be named like weblogs_helper.rb. These are generated - for you automatically when using script/generate for controllers. Helpers can be used to + for you automatically when using rails generate for controllers. Helpers can be used to wrap functionality for your views into methods. config @@ -234,7 +234,7 @@ script Helper scripts for automation and generation. test - Unit and functional tests along with fixtures. When using the script/generate scripts, template + Unit and functional tests along with fixtures. When using the rails generate scripts, template test files will be generated for you and placed in this directory. vendor diff --git a/railties/lib/generators/rails/controller/USAGE b/railties/lib/generators/rails/controller/USAGE index 6ed4b2edfc..70618a3906 100644 --- a/railties/lib/generators/rails/controller/USAGE +++ b/railties/lib/generators/rails/controller/USAGE @@ -9,7 +9,7 @@ Description: template engine and test framework generators. Example: - `./script/generate controller CreditCard open debit credit close` + `rails generate controller CreditCard open debit credit close` Credit card controller with URLs like /credit_card/debit. Controller: app/controllers/credit_card_controller.rb diff --git a/railties/lib/generators/rails/generator/USAGE b/railties/lib/generators/rails/generator/USAGE index ca7d3f62d0..d8c3f7f634 100644 --- a/railties/lib/generators/rails/generator/USAGE +++ b/railties/lib/generators/rails/generator/USAGE @@ -3,7 +3,7 @@ Description: CamelCased or under_scored, as an argument. Example: - `./script/generate generator Awesome` + `rails generate generator Awesome` creates a standard awesome generator: lib/generators/awesome/ diff --git a/railties/lib/generators/rails/generator/templates/USAGE.tt b/railties/lib/generators/rails/generator/templates/USAGE.tt index ea9f4f12cc..1bb8df840d 100644 --- a/railties/lib/generators/rails/generator/templates/USAGE.tt +++ b/railties/lib/generators/rails/generator/templates/USAGE.tt @@ -2,7 +2,7 @@ Description: Explain the generator Example: - ./script/generate <%= file_name %> Thing + rails generate <%= file_name %> Thing This will create: what/will/it/create diff --git a/railties/lib/generators/rails/helper/USAGE b/railties/lib/generators/rails/helper/USAGE index 531c9b390a..c0ddb0f606 100644 --- a/railties/lib/generators/rails/helper/USAGE +++ b/railties/lib/generators/rails/helper/USAGE @@ -9,7 +9,7 @@ Description: test framework. Example: - `./script/generate helper CreditCard` + `rails generate helper CreditCard` Credit card helper. Helper: app/helpers/credit_card_helper.rb diff --git a/railties/lib/generators/rails/integration_test/USAGE b/railties/lib/generators/rails/integration_test/USAGE index b76c35a702..57ee3543e6 100644 --- a/railties/lib/generators/rails/integration_test/USAGE +++ b/railties/lib/generators/rails/integration_test/USAGE @@ -6,5 +6,5 @@ Description: TestUnit. Example: - `./script/generate integration_test GeneralStories` creates a GeneralStories + `rails generate integration_test GeneralStories` creates a GeneralStories integration test in test/integration/general_stories_test.rb diff --git a/railties/lib/generators/rails/mailer/USAGE b/railties/lib/generators/rails/mailer/USAGE index beae79fbf4..a08d459739 100644 --- a/railties/lib/generators/rails/mailer/USAGE +++ b/railties/lib/generators/rails/mailer/USAGE @@ -6,7 +6,7 @@ Description: engine and test framework generators. Example: - `./script/generate mailer Notifications signup forgot_password invoice` + `rails generate mailer Notifications signup forgot_password invoice` creates a Notifications mailer class, views, test, and fixtures: Mailer: app/mailers/notifications.rb diff --git a/railties/lib/generators/rails/metal/USAGE b/railties/lib/generators/rails/metal/USAGE index 123ec6c03f..c88325a444 100644 --- a/railties/lib/generators/rails/metal/USAGE +++ b/railties/lib/generators/rails/metal/USAGE @@ -2,7 +2,7 @@ Description: Cast some metal! Examples: - `./script/generate metal poller` + `rails generate metal poller` This will create: Metal: app/metal/poller.rb diff --git a/railties/lib/generators/rails/migration/USAGE b/railties/lib/generators/rails/migration/USAGE index d91127aac3..d21c81b760 100644 --- a/railties/lib/generators/rails/migration/USAGE +++ b/railties/lib/generators/rails/migration/USAGE @@ -8,12 +8,12 @@ Description: column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable Example: - `./script/generate migration AddSslFlag` + `rails generate migration AddSslFlag` If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration db/migrate/20080514090912_add_ssl_flag.rb - `./script/generate migration AddTitleBodyToPost title:string body:text published:boolean` + `rails generate migration AddTitleBodyToPost title:string body:text published:boolean` This will create the AddTitleBodyToPost in db/migrate/20080514090912_add_title_body_to_post.rb with this in the Up migration: diff --git a/railties/lib/generators/rails/model/USAGE b/railties/lib/generators/rails/model/USAGE index b056d5df8b..d97e9ac103 100644 --- a/railties/lib/generators/rails/model/USAGE +++ b/railties/lib/generators/rails/model/USAGE @@ -16,7 +16,7 @@ Description: created model. This allows you create Single Table Inheritance models. Examples: - `./script/generate model account` + `rails generate model account` For ActiveRecord and TestUnit it creates: @@ -25,6 +25,6 @@ Examples: Fixtures: test/fixtures/accounts.yml Migration: db/migrate/XXX_add_accounts.rb - `./script/generate model post title:string body:text published:boolean` + `rails generate model post title:string body:text published:boolean` Creates a Post model with a string title, text body, and published flag. diff --git a/railties/lib/generators/rails/observer/USAGE b/railties/lib/generators/rails/observer/USAGE index 9a20f55a89..d8f32a6a48 100644 --- a/railties/lib/generators/rails/observer/USAGE +++ b/railties/lib/generators/rails/observer/USAGE @@ -5,7 +5,7 @@ Description: This generator only invokes your ORM and test framework generators. Example: - `./script/generate observer Account` + `rails generate observer Account` For ActiveRecord and TestUnit it creates: Observer: app/models/account_observer.rb diff --git a/railties/lib/generators/rails/performance_test/USAGE b/railties/lib/generators/rails/performance_test/USAGE index ee82578cdb..9dc799559c 100644 --- a/railties/lib/generators/rails/performance_test/USAGE +++ b/railties/lib/generators/rails/performance_test/USAGE @@ -6,5 +6,5 @@ Description: TestUnit. Example: - `./script/generate performance_test GeneralStories` creates a GeneralStories + `rails generate performance_test GeneralStories` creates a GeneralStories performance test in test/performance/general_stories_test.rb diff --git a/railties/lib/generators/rails/plugin/USAGE b/railties/lib/generators/rails/plugin/USAGE index 8a17fa4dec..00a429c585 100644 --- a/railties/lib/generators/rails/plugin/USAGE +++ b/railties/lib/generators/rails/plugin/USAGE @@ -3,7 +3,7 @@ Description: CamelCased or under_scored, as an argument. Example: - `./script/generate plugin BrowserFilters` + `rails generate plugin BrowserFilters` creates a standard browser_filters plugin: vendor/plugins/browser_filters/README diff --git a/railties/lib/generators/rails/resource/USAGE b/railties/lib/generators/rails/resource/USAGE index 936619b0db..e359cd574f 100644 --- a/railties/lib/generators/rails/resource/USAGE +++ b/railties/lib/generators/rails/resource/USAGE @@ -18,6 +18,6 @@ Description: views or add any methods to the generated controller. Examples: - `./script/generate resource post` # no attributes - `./script/generate resource post title:string body:text published:boolean` - `./script/generate resource purchase order_id:integer amount:decimal` + `rails generate resource post` # no attributes + `rails generate resource post title:string body:text published:boolean` + `rails generate resource purchase order_id:integer amount:decimal` diff --git a/railties/lib/generators/rails/scaffold/USAGE b/railties/lib/generators/rails/scaffold/USAGE index 530ccdaf0a..be1d113ed8 100644 --- a/railties/lib/generators/rails/scaffold/USAGE +++ b/railties/lib/generators/rails/scaffold/USAGE @@ -21,9 +21,9 @@ Description: declaration in config/routes.rb. If you want to remove all the generated files, run - 'script/destroy scaffold ModelName'. + 'rails destroy scaffold ModelName'. Examples: - `./script/generate scaffold post` - `./script/generate scaffold post title:string body:text published:boolean` - `./script/generate scaffold purchase order_id:integer amount:decimal` + `rails generate scaffold post` + `rails generate scaffold post title:string body:text published:boolean` + `rails generate scaffold purchase order_id:integer amount:decimal` diff --git a/railties/lib/generators/rails/scaffold_controller/USAGE b/railties/lib/generators/rails/scaffold_controller/USAGE index d60a3c3680..673f69bc81 100644 --- a/railties/lib/generators/rails/scaffold_controller/USAGE +++ b/railties/lib/generators/rails/scaffold_controller/USAGE @@ -11,7 +11,7 @@ Description: template engine and test framework generators. Example: - `./script/generate scaffold_controller CreditCard` + `rails generate scaffold_controller CreditCard` Credit card controller with URLs like /credit_card/debit. Controller: app/controllers/credit_cards_controller.rb diff --git a/railties/lib/generators/rails/session_migration/USAGE b/railties/lib/generators/rails/session_migration/USAGE index e106f6ecc8..564d1ffd78 100644 --- a/railties/lib/generators/rails/session_migration/USAGE +++ b/railties/lib/generators/rails/session_migration/USAGE @@ -5,4 +5,4 @@ Description: Before invoking this generator, be sure that your ORM supports session stores. Example: - `./script/generate session_migration CreateSessionTable` + `rails generate session_migration CreateSessionTable` diff --git a/railties/lib/generators/rails/stylesheets/USAGE b/railties/lib/generators/rails/stylesheets/USAGE index d6a81e51d0..59e5495d0b 100644 --- a/railties/lib/generators/rails/stylesheets/USAGE +++ b/railties/lib/generators/rails/stylesheets/USAGE @@ -2,4 +2,4 @@ Description: Copies scaffold stylesheets to public/stylesheets/. Examples: - `./script/generate stylesheets` + `rails generate stylesheets` diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index a984eff6e2..3fa4c939a8 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -19,7 +19,7 @@ module Rails opt.banner = "Usage: console [environment] [options]" opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v } opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v } - opt.on('--irb') { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/console` instead' } + opt.on('--irb') { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/rails console` instead' } opt.parse!(ARGV) end diff --git a/railties/lib/rails/commands/plugin.rb b/railties/lib/rails/commands/plugin.rb index af12df1425..8bcd92a33b 100644 --- a/railties/lib/rails/commands/plugin.rb +++ b/railties/lib/rails/commands/plugin.rb @@ -2,7 +2,7 @@ # # Installing plugins: # -# $ ./script/plugin install continuous_builder asset_timestamping +# $ rails plugin install continuous_builder asset_timestamping # # Specifying revisions: # @@ -319,13 +319,13 @@ module Commands o.separator "" o.separator "EXAMPLES" o.separator " Install a plugin:" - o.separator " #{@script_name} install continuous_builder\n" + o.separator " #{@script_name} plugin install continuous_builder\n" o.separator " Install a plugin from a subversion URL:" - o.separator " #{@script_name} install http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder\n" + o.separator " #{@script_name} plugin install http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder\n" o.separator " Install a plugin from a git URL:" - o.separator " #{@script_name} install git://github.com/SomeGuy/my_awesome_plugin.git\n" + o.separator " #{@script_name} plugin install git://github.com/SomeGuy/my_awesome_plugin.git\n" o.separator " Install a plugin and add a svn:externals entry to vendor/plugins" - o.separator " #{@script_name} install -x continuous_builder\n" + o.separator " #{@script_name} plugin install -x continuous_builder\n" end end @@ -381,7 +381,7 @@ module Commands "Exports the plugin, allowing you to check it into your local repository. Does not enable updates, or add an svn:externals entry.") { |v| @method = :export } o.on( "-q", "--quiet", "Suppresses the output from installation.", - "Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true } + "Ignored if -v is passed (rails plugin -v install ...)") { |v| @options[:quiet] = true } o.on( "-r REVISION", "--revision REVISION", "Checks out the given revision from subversion or git.", "Ignored if subversion/git is not used.") { |v| @options[:revision] = v } diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index f95b15acce..247a141943 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -32,7 +32,7 @@ module Rails options[:git] = "-b #{options[:branch]} #{options[:git]}" if options[:branch] options[:svn] = "-r #{options[:revision]} #{options[:svn]}" if options[:revision] in_root do - run_ruby_script "script/plugin install #{options[:svn] || options[:git]}", :verbose => false + run_ruby_script "script/rails plugin install #{options[:svn] || options[:git]}", :verbose => false end else log "! no git or svn provided for #{name}. Skipping..." @@ -226,7 +226,7 @@ module Rails log :generate, what argument = args.map {|arg| arg.to_s }.flatten.join(" ") - in_root { run_ruby_script("script/generate #{what} #{argument}", :verbose => false) } + in_root { run_ruby_script("script/rails generate #{what} #{argument}", :verbose => false) } end # Runs the supplied rake task diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index c801e2fec3..9624c35c0b 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -62,7 +62,7 @@ module Rails # # For example, if the user invoke the controller generator as: # - # ruby script/generate controller Account --test-framework=test_unit + # rails generate controller Account --test-framework=test_unit # # The controller generator will then try to invoke the following generators: # @@ -117,11 +117,11 @@ module Rails # All hooks come with switches for user interface. If the user don't want # to use any test framework, he can do: # - # ruby script/generate controller Account --skip-test-framework + # rails generate controller Account --skip-test-framework # # Or similarly: # - # ruby script/generate controller Account --no-test-framework + # rails generate controller Account --no-test-framework # # ==== Boolean hooks # @@ -133,7 +133,7 @@ module Rails # # Then, if you want, webrat to be invoked, just supply: # - # ruby script/generate controller Account --webrat + # rails generate controller Account --webrat # # The hooks lookup is similar as above: # diff --git a/railties/lib/rails/rack/debugger.rb b/railties/lib/rails/rack/debugger.rb index 0a7b405553..c0448f65e6 100644 --- a/railties/lib/rails/rack/debugger.rb +++ b/railties/lib/rails/rack/debugger.rb @@ -4,7 +4,7 @@ module Rails def initialize(app) @app = app - ARGV.clear # clear ARGV so that script/server options aren't passed to IRB + ARGV.clear # clear ARGV so that rails server options aren't passed to IRB require_library_or_gem 'ruby-debug' ::Debugger.start -- cgit v1.2.3 From ca1879b7308d0d7e096ff1bf17cc4f70ce4d5b8c Mon Sep 17 00:00:00 2001 From: Dan Kubb Date: Sun, 7 Feb 2010 08:29:18 +0100 Subject: Added newline to appended gem config in Gemfile Signed-off-by: Yehuda Katz --- railties/lib/rails/generators/actions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 247a141943..152fe6e33e 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -81,7 +81,7 @@ module Rails end in_root do - append_file "Gemfile", "gem #{parts.join(", ")}", :verbose => false + append_file "Gemfile", "gem #{parts.join(", ")}\n", :verbose => false end end -- cgit v1.2.3 From 345e0b274cb384f8d453256e90dd105e6c2ffa19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 7 Feb 2010 13:44:47 +0100 Subject: Add backtrace cleaner on test unit railtie. --- railties/lib/rails/test_unit/railtie.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'railties/lib') diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb index 21b9dbc074..f7f07ac053 100644 --- a/railties/lib/rails/test_unit/railtie.rb +++ b/railties/lib/rails/test_unit/railtie.rb @@ -13,5 +13,13 @@ module Rails rake_tasks do load "rails/test_unit/testing.rake" end + + initializer "test_unit.backtrace_cleaner" do + # TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit + unless defined?(Minitest) || ENV['BACKTRACE'] + require 'rails/backtrace_cleaner' + Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit } + end + end end end \ No newline at end of file -- cgit v1.2.3 From 518b4ff478984b74085239b0aa69fe67f7c01d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 7 Feb 2010 14:36:50 +0100 Subject: Check if Test::Unit is defined before adding backtrace filter. --- railties/lib/generators/rails/app/templates/test/test_helper.rb | 1 + railties/lib/rails/test_unit/railtie.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/test/test_helper.rb b/railties/lib/generators/rails/app/templates/test/test_helper.rb index 45b551fc7d..005149eba0 100644 --- a/railties/lib/generators/rails/app/templates/test/test_helper.rb +++ b/railties/lib/generators/rails/app/templates/test/test_helper.rb @@ -1,4 +1,5 @@ ENV["RAILS_ENV"] = "test" +require 'test/unit' require File.expand_path(File.dirname(__FILE__) + "/../config/environment") require 'rails/test_help' diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb index f7f07ac053..b0a4b460af 100644 --- a/railties/lib/rails/test_unit/railtie.rb +++ b/railties/lib/rails/test_unit/railtie.rb @@ -16,7 +16,7 @@ module Rails initializer "test_unit.backtrace_cleaner" do # TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit - unless defined?(Minitest) || ENV['BACKTRACE'] + if defined?(Test::Unit::Util::BacktraceFilter) && ENV['BACKTRACE'].nil? require 'rails/backtrace_cleaner' Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit } end -- cgit v1.2.3 From 17b451898c09f560cef105ea120d8e767256555a Mon Sep 17 00:00:00 2001 From: Mikel Lindsaar Date: Mon, 8 Feb 2010 18:57:00 +1100 Subject: Updating Prototype to 1.6.1 and script.aculo.us to 1.8.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../app/templates/public/javascripts/controls.js | 8 +- .../app/templates/public/javascripts/dragdrop.js | 13 +- .../app/templates/public/javascripts/effects.js | 21 +- .../app/templates/public/javascripts/prototype.js | 2592 ++++++++++++-------- 4 files changed, 1593 insertions(+), 1041 deletions(-) (limited to 'railties/lib') diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/controls.js b/railties/lib/generators/rails/app/templates/public/javascripts/controls.js index ca29aefdd1..7392fb664c 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/controls.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/controls.js @@ -1,6 +1,8 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) +// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2009 Jon Tirsen (http://www.tirsen.com) // Contributors: // Richard Livsey // Rahul Bhargava diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js b/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js index 07229f986f..15c6dbca68 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js @@ -1,5 +1,6 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) +// script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ @@ -311,7 +312,7 @@ var Draggable = Class.create({ tag_name=='TEXTAREA')) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = Position.cumulativeOffset(this.element); + var pos = this.element.cumulativeOffset(); this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); Draggables.activate(this); @@ -454,7 +455,7 @@ var Draggable = Class.create({ }, draw: function(point) { - var pos = Position.cumulativeOffset(this.element); + var pos = this.element.cumulativeOffset(); if(this.options.ghosting) { var r = Position.realOffset(this.element); pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; @@ -730,7 +731,7 @@ var Sortable = { } // keep reference - this.sortables[element.id] = options; + this.sortables[element.identify()] = options; // for onupdate Draggables.addObserver(new SortableObserver(element, options.onUpdate)); @@ -825,7 +826,7 @@ var Sortable = { hide().addClassName('dropmarker').setStyle({position:'absolute'}); document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); } - var offsets = Position.cumulativeOffset(dropon); + var offsets = dropon.cumulativeOffset(); Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); if(position=='after') diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/effects.js b/railties/lib/generators/rails/app/templates/public/javascripts/effects.js index 5a639d2dea..066ee5909c 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/effects.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/effects.js @@ -1,4 +1,6 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 + +// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Contributors: // Justin Palmer (http://encytemedia.com/) // Mark Pilgrim (http://diveintomark.org/) @@ -145,14 +147,13 @@ var Effect = { 'blind': ['BlindDown','BlindUp'], 'appear': ['Appear','Fade'] }, - toggle: function(element, effect) { + toggle: function(element, effect, options) { element = $(element); - effect = (effect || 'appear').toLowerCase(); - var options = Object.extend({ + effect = (effect || 'appear').toLowerCase(); + + return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({ queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, arguments[2] || { }); - Effect[element.visible() ? - Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + }, options || {})); } }; @@ -228,12 +229,6 @@ Effect.Queue = Effect.Queues.get('global'); Effect.Base = Class.create({ position: null, start: function(options) { - function codeForEvent(options,eventName){ - return ( - (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + - (options[eventName] ? 'this.options.'+eventName+'(this);' : '') - ); - } if (options && options.transition === false) options.transition = Effect.Transitions.linear; this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); this.currentFrame = 0; diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js index dfe8ab4e13..9fe6e1243b 100644 --- a/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js @@ -1,5 +1,5 @@ -/* Prototype JavaScript framework, version 1.6.0.3 - * (c) 2005-2008 Sam Stephenson +/* Prototype JavaScript framework, version 1.6.1 + * (c) 2005-2009 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://www.prototypejs.org/ @@ -7,26 +7,43 @@ *--------------------------------------------------------------------------*/ var Prototype = { - Version: '1.6.0.3', - - Browser: { - IE: !!(window.attachEvent && - navigator.userAgent.indexOf('Opera') === -1), - Opera: navigator.userAgent.indexOf('Opera') > -1, - WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, - Gecko: navigator.userAgent.indexOf('Gecko') > -1 && - navigator.userAgent.indexOf('KHTML') === -1, - MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) - }, + Version: '1.6.1', + + Browser: (function(){ + var ua = navigator.userAgent; + var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; + return { + IE: !!window.attachEvent && !isOpera, + Opera: isOpera, + WebKit: ua.indexOf('AppleWebKit/') > -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile.*Safari/.test(ua) + } + })(), BrowserFeatures: { XPath: !!document.evaluate, SelectorsAPI: !!document.querySelector, - ElementExtensions: !!window.HTMLElement, - SpecificElementExtensions: - document.createElement('div')['__proto__'] && - document.createElement('div')['__proto__'] !== - document.createElement('form')['__proto__'] + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'); + var form = document.createElement('form'); + var isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() }, ScriptFragment: ']*>([\\S\\s]*?)<\/script>', @@ -40,9 +57,30 @@ if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false; +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + /* Based on Alex Arnell's inheritance implementation. */ -var Class = { - create: function() { + +var Class = (function() { + function subclass() {}; + function create() { var parent = null, properties = $A(arguments); if (Object.isFunction(properties[0])) parent = properties.shift(); @@ -56,7 +94,6 @@ var Class = { klass.subclasses = []; if (parent) { - var subclass = function() { }; subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); @@ -69,18 +106,19 @@ var Class = { klass.prototype.initialize = Prototype.emptyFunction; klass.prototype.constructor = klass; - return klass; } -}; -Class.Methods = { - addMethods: function(source) { + function addMethods(source) { var ancestor = this.superclass && this.superclass.prototype; var properties = Object.keys(source); - if (!Object.keys({ toString: true }).length) - properties.push("toString", "valueOf"); + if (!Object.keys({ toString: true }).length) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } for (var i = 0, length = properties.length; i < length; i++) { var property = properties[i], value = source[property]; @@ -88,7 +126,7 @@ Class.Methods = { value.argumentNames().first() == "$super") { var method = value; value = (function(m) { - return function() { return ancestor[m].apply(this, arguments) }; + return function() { return ancestor[m].apply(this, arguments); }; })(property).wrap(method); value.valueOf = method.valueOf.bind(method); @@ -99,29 +137,36 @@ Class.Methods = { return this; } -}; -var Abstract = { }; + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { -Object.extend = function(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; -}; + var _toString = Object.prototype.toString; + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } -Object.extend(Object, { - inspect: function(object) { + function inspect(object) { try { - if (Object.isUndefined(object)) return 'undefined'; + if (isUndefined(object)) return 'undefined'; if (object === null) return 'null'; return object.inspect ? object.inspect() : String(object); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } - }, + } - toJSON: function(object) { + function toJSON(object) { var type = typeof object; switch (type) { case 'undefined': @@ -132,131 +177,180 @@ Object.extend(Object, { if (object === null) return 'null'; if (object.toJSON) return object.toJSON(); - if (Object.isElement(object)) return; + if (isElement(object)) return; var results = []; for (var property in object) { - var value = Object.toJSON(object[property]); - if (!Object.isUndefined(value)) + var value = toJSON(object[property]); + if (!isUndefined(value)) results.push(property.toJSON() + ': ' + value); } return '{' + results.join(', ') + '}'; - }, + } - toQueryString: function(object) { + function toQueryString(object) { return $H(object).toQueryString(); - }, + } - toHTML: function(object) { + function toHTML(object) { return object && object.toHTML ? object.toHTML() : String.interpret(object); - }, + } - keys: function(object) { - var keys = []; + function keys(object) { + var results = []; for (var property in object) - keys.push(property); - return keys; - }, + results.push(property); + return results; + } - values: function(object) { - var values = []; + function values(object) { + var results = []; for (var property in object) - values.push(object[property]); - return values; - }, + results.push(object[property]); + return results; + } - clone: function(object) { - return Object.extend({ }, object); - }, + function clone(object) { + return extend({ }, object); + } - isElement: function(object) { + function isElement(object) { return !!(object && object.nodeType == 1); - }, + } + + function isArray(object) { + return _toString.call(object) == "[object Array]"; + } - isArray: function(object) { - return object != null && typeof object == "object" && - 'splice' in object && 'join' in object; - }, - isHash: function(object) { + function isHash(object) { return object instanceof Hash; - }, + } - isFunction: function(object) { - return typeof object == "function"; - }, + function isFunction(object) { + return typeof object === "function"; + } - isString: function(object) { - return typeof object == "string"; - }, + function isString(object) { + return _toString.call(object) == "[object String]"; + } - isNumber: function(object) { - return typeof object == "number"; - }, + function isNumber(object) { + return _toString.call(object) == "[object Number]"; + } - isUndefined: function(object) { - return typeof object == "undefined"; + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); } -}); -Object.extend(Function.prototype, { - argumentNames: function() { - var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1] + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') .replace(/\s+/g, '').split(','); return names.length == 1 && !names[0] ? [] : names; - }, + } - bind: function() { + function bind(context) { if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = $A(arguments), object = args.shift(); + var __method = this, args = slice.call(arguments, 1); return function() { - return __method.apply(object, args.concat($A(arguments))); + var a = merge(args, arguments); + return __method.apply(context, a); } - }, + } - bindAsEventListener: function() { - var __method = this, args = $A(arguments), object = args.shift(); + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); return function(event) { - return __method.apply(object, [event || window.event].concat(args)); + var a = update([event || window.event], args); + return __method.apply(context, a); } - }, + } - curry: function() { + function curry() { if (!arguments.length) return this; - var __method = this, args = $A(arguments); + var __method = this, args = slice.call(arguments, 0); return function() { - return __method.apply(this, args.concat($A(arguments))); + var a = merge(args, arguments); + return __method.apply(this, a); } - }, + } - delay: function() { - var __method = this, args = $A(arguments), timeout = args.shift() * 1000; + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000 return window.setTimeout(function() { return __method.apply(__method, args); }, timeout); - }, + } - defer: function() { - var args = [0.01].concat($A(arguments)); + function defer() { + var args = update([0.01], arguments); return this.delay.apply(this, args); - }, + } - wrap: function(wrapper) { + function wrap(wrapper) { var __method = this; return function() { - return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); } - }, + } - methodize: function() { + function methodize() { if (this._methodized) return this._methodized; var __method = this; return this._methodized = function() { - return __method.apply(null, [this].concat($A(arguments))); + var a = update([this], arguments); + return __method.apply(null, a); }; } -}); + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + Date.prototype.toJSON = function() { return '"' + this.getUTCFullYear() + '-' + @@ -267,30 +361,12 @@ Date.prototype.toJSON = function() { this.getUTCSeconds().toPaddedString(2) + 'Z"'; }; -var Try = { - these: function() { - var returnValue; - - for (var i = 0, length = arguments.length; i < length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) { } - } - - return returnValue; - } -}; RegExp.prototype.match = RegExp.prototype.test; RegExp.escape = function(str) { return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); }; - -/*--------------------------------------------------------------------------*/ - var PeriodicalExecuter = Class.create({ initialize: function(callback, frequency) { this.callback = callback; @@ -319,8 +395,10 @@ var PeriodicalExecuter = Class.create({ try { this.currentlyExecuting = true; this.execute(); - } finally { this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; } } } @@ -339,10 +417,25 @@ Object.extend(String, { } }); -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { +Object.extend(String.prototype, (function() { + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } while (source.length > 0) { if (match = source.match(pattern)) { @@ -354,69 +447,64 @@ Object.extend(String.prototype, { } } return result; - }, + } - sub: function(pattern, replacement, count) { - replacement = this.gsub.prepareReplacement(replacement); + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); count = Object.isUndefined(count) ? 1 : count; return this.gsub(pattern, function(match) { if (--count < 0) return match[0]; return replacement(match); }); - }, + } - scan: function(pattern, iterator) { + function scan(pattern, iterator) { this.gsub(pattern, iterator); return String(this); - }, + } - truncate: function(length, truncation) { + function truncate(length, truncation) { length = length || 30; truncation = Object.isUndefined(truncation) ? '...' : truncation; return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this); - }, + } - strip: function() { + function strip() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, + } - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } - stripScripts: function() { + function stripScripts() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, + } - extractScripts: function() { + function extractScripts() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); - }, + } - evalScripts: function() { + function evalScripts() { return this.extractScripts().map(function(script) { return eval(script) }); - }, + } - escapeHTML: function() { - var self = arguments.callee; - self.text.data = this; - return self.div.innerHTML; - }, + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } - unescapeHTML: function() { - var div = new Element('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? (div.childNodes.length > 1 ? - $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : - div.childNodes[0].nodeValue) : ''; - }, - toQueryParams: function(separator) { + function toQueryParams(separator) { var match = this.strip().match(/([^?#]*)(#.*)?$/); if (!match) return { }; @@ -434,22 +522,22 @@ Object.extend(String.prototype, { } return hash; }); - }, + } - toArray: function() { + function toArray() { return this.split(''); - }, + } - succ: function() { + function succ() { return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); - }, + } - times: function(count) { + function times(count) { return count < 1 ? '' : new Array(count + 1).join(this); - }, + } - camelize: function() { + function camelize() { var parts = this.split('-'), len = parts.length; if (len == 1) return parts[0]; @@ -461,101 +549,117 @@ Object.extend(String.prototype, { camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); return camelized; - }, + } - capitalize: function() { + function capitalize() { return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); - }, + } - underscore: function() { - return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); - }, + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } - dasherize: function() { - return this.gsub(/_/,'-'); - }, + function dasherize() { + return this.replace(/_/g, '-'); + } - inspect: function(useDoubleQuotes) { - var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { - var character = String.specialChar[match[0]]; - return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); }); if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; return "'" + escapedString.replace(/'/g, '\\\'') + "'"; - }, + } - toJSON: function() { + function toJSON() { return this.inspect(true); - }, + } - unfilterJSON: function(filter) { - return this.sub(filter || Prototype.JSONFilter, '#{1}'); - }, + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } - isJSON: function() { + function isJSON() { var str = this; if (str.blank()) return false; str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); - }, + } - evalJSON: function(sanitize) { + function evalJSON(sanitize) { var json = this.unfilterJSON(); try { if (!sanitize || json.isJSON()) return eval('(' + json + ')'); } catch (e) { } throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); - }, + } - include: function(pattern) { + function include(pattern) { return this.indexOf(pattern) > -1; - }, + } - startsWith: function(pattern) { + function startsWith(pattern) { return this.indexOf(pattern) === 0; - }, + } - endsWith: function(pattern) { + function endsWith(pattern) { var d = this.length - pattern.length; return d >= 0 && this.lastIndexOf(pattern) === d; - }, + } - empty: function() { + function empty() { return this == ''; - }, + } - blank: function() { + function blank() { return /^\s*$/.test(this); - }, - - interpolate: function(object, pattern) { - return new Template(this, pattern).evaluate(object); } -}); -if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { - escapeHTML: function() { - return this.replace(/&/g,'&').replace(//g,'>'); - }, - unescapeHTML: function() { - return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); } -}); -String.prototype.gsub.prepareReplacement = function(replacement) { - if (Object.isFunction(replacement)) return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -}; - -String.prototype.parseQuery = String.prototype.toQueryParams; - -Object.extend(String.prototype.escapeHTML, { - div: document.createElement('div'), - text: document.createTextNode('') -}); - -String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text); + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim ? String.prototype.trim : strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + toJSON: toJSON, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); var Template = Class.create({ initialize: function(template, pattern) { @@ -564,11 +668,11 @@ var Template = Class.create({ }, evaluate: function(object) { - if (Object.isFunction(object.toTemplateReplacements)) + if (object && Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements(); return this.template.gsub(this.pattern, function(match) { - if (object == null) return ''; + if (object == null) return (match[1] + ''); var before = match[1] || ''; if (before == '\\') return match[2]; @@ -579,7 +683,7 @@ var Template = Class.create({ if (match == null) return before; while (match != null) { - var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; ctx = ctx[comp]; if (null == ctx || '' == match[3]) break; expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); @@ -594,8 +698,8 @@ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; var $break = { }; -var Enumerable = { - each: function(iterator, context) { +var Enumerable = (function() { + function each(iterator, context) { var index = 0; try { this._each(function(value) { @@ -605,17 +709,17 @@ var Enumerable = { if (e != $break) throw e; } return this; - }, + } - eachSlice: function(number, iterator, context) { + function eachSlice(number, iterator, context) { var index = -number, slices = [], array = this.toArray(); if (number < 1) return array; while ((index += number) < array.length) slices.push(array.slice(index, index+number)); return slices.collect(iterator, context); - }, + } - all: function(iterator, context) { + function all(iterator, context) { iterator = iterator || Prototype.K; var result = true; this.each(function(value, index) { @@ -623,9 +727,9 @@ var Enumerable = { if (!result) throw $break; }); return result; - }, + } - any: function(iterator, context) { + function any(iterator, context) { iterator = iterator || Prototype.K; var result = false; this.each(function(value, index) { @@ -633,18 +737,18 @@ var Enumerable = { throw $break; }); return result; - }, + } - collect: function(iterator, context) { + function collect(iterator, context) { iterator = iterator || Prototype.K; var results = []; this.each(function(value, index) { results.push(iterator.call(context, value, index)); }); return results; - }, + } - detect: function(iterator, context) { + function detect(iterator, context) { var result; this.each(function(value, index) { if (iterator.call(context, value, index)) { @@ -653,32 +757,32 @@ var Enumerable = { } }); return result; - }, + } - findAll: function(iterator, context) { + function findAll(iterator, context) { var results = []; this.each(function(value, index) { if (iterator.call(context, value, index)) results.push(value); }); return results; - }, + } - grep: function(filter, iterator, context) { + function grep(filter, iterator, context) { iterator = iterator || Prototype.K; var results = []; if (Object.isString(filter)) - filter = new RegExp(filter); + filter = new RegExp(RegExp.escape(filter)); this.each(function(value, index) { if (filter.match(value)) results.push(iterator.call(context, value, index)); }); return results; - }, + } - include: function(object) { + function include(object) { if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true; @@ -690,31 +794,31 @@ var Enumerable = { } }); return found; - }, + } - inGroupsOf: function(number, fillWith) { + function inGroupsOf(number, fillWith) { fillWith = Object.isUndefined(fillWith) ? null : fillWith; return this.eachSlice(number, function(slice) { while(slice.length < number) slice.push(fillWith); return slice; }); - }, + } - inject: function(memo, iterator, context) { + function inject(memo, iterator, context) { this.each(function(value, index) { memo = iterator.call(context, memo, value, index); }); return memo; - }, + } - invoke: function(method) { + function invoke(method) { var args = $A(arguments).slice(1); return this.map(function(value) { return value[method].apply(value, args); }); - }, + } - max: function(iterator, context) { + function max(iterator, context) { iterator = iterator || Prototype.K; var result; this.each(function(value, index) { @@ -723,9 +827,9 @@ var Enumerable = { result = value; }); return result; - }, + } - min: function(iterator, context) { + function min(iterator, context) { iterator = iterator || Prototype.K; var result; this.each(function(value, index) { @@ -734,9 +838,9 @@ var Enumerable = { result = value; }); return result; - }, + } - partition: function(iterator, context) { + function partition(iterator, context) { iterator = iterator || Prototype.K; var trues = [], falses = []; this.each(function(value, index) { @@ -744,26 +848,26 @@ var Enumerable = { trues : falses).push(value); }); return [trues, falses]; - }, + } - pluck: function(property) { + function pluck(property) { var results = []; this.each(function(value) { results.push(value[property]); }); return results; - }, + } - reject: function(iterator, context) { + function reject(iterator, context) { var results = []; this.each(function(value, index) { if (!iterator.call(context, value, index)) results.push(value); }); return results; - }, + } - sortBy: function(iterator, context) { + function sortBy(iterator, context) { return this.map(function(value, index) { return { value: value, @@ -773,13 +877,13 @@ var Enumerable = { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); - }, + } - toArray: function() { + function toArray() { return this.map(); - }, + } - zip: function() { + function zip() { var iterator = Prototype.K, args = $A(arguments); if (Object.isFunction(args.last())) iterator = args.pop(); @@ -788,130 +892,152 @@ var Enumerable = { return this.map(function(value, index) { return iterator(collections.pluck(index)); }); - }, + } - size: function() { + function size() { return this.toArray().length; - }, + } - inspect: function() { + function inspect() { return '#'; } -}; -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - filter: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray, - every: Enumerable.all, - some: Enumerable.any -}); + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); function $A(iterable) { if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); + if ('toArray' in Object(iterable)) return iterable.toArray(); var length = iterable.length || 0, results = new Array(length); while (length--) results[length] = iterable[length]; return results; } -if (Prototype.Browser.WebKit) { - $A = function(iterable) { - if (!iterable) return []; - // In Safari, only use the `toArray` method if it's not a NodeList. - // A NodeList is a function, has an function `item` property, and a numeric - // `length` property. Adapted from Google Doctype. - if (!(typeof iterable === 'function' && typeof iterable.length === - 'number' && typeof iterable.item === 'function') && iterable.toArray) - return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; - }; +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; } Array.from = $A; -Object.extend(Array.prototype, Enumerable); -if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available -Object.extend(Array.prototype, { - _each: function(iterator) { + function each(iterator) { for (var i = 0, length = this.length; i < length; i++) iterator(this[i]); - }, + } + if (!_each) _each = each; - clear: function() { + function clear() { this.length = 0; return this; - }, + } - first: function() { + function first() { return this[0]; - }, + } - last: function() { + function last() { return this[this.length - 1]; - }, + } - compact: function() { + function compact() { return this.select(function(value) { return value != null; }); - }, + } - flatten: function() { + function flatten() { return this.inject([], function(array, value) { - return array.concat(Object.isArray(value) ? - value.flatten() : [value]); + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; }); - }, + } - without: function() { - var values = $A(arguments); + function without() { + var values = slice.call(arguments, 0); return this.select(function(value) { return !values.include(value); }); - }, + } - reverse: function(inline) { + function reverse(inline) { return (inline !== false ? this : this.toArray())._reverse(); - }, - - reduce: function() { - return this.length > 1 ? this : this[0]; - }, + } - uniq: function(sorted) { + function uniq(sorted) { return this.inject([], function(array, value, index) { if (0 == index || (sorted ? array.last() != value : !array.include(value))) array.push(value); return array; }); - }, + } - intersect: function(array) { + function intersect(array) { return this.uniq().findAll(function(item) { return array.detect(function(value) { return item === value }); }); - }, + } - clone: function() { - return [].concat(this); - }, - size: function() { + function clone() { + return slice.call(this, 0); + } + + function size() { return this.length; - }, + } - inspect: function() { + function inspect() { return '[' + this.map(Object.inspect).join(', ') + ']'; - }, + } - toJSON: function() { + function toJSON() { var results = []; this.each(function(object) { var value = Object.toJSON(object); @@ -919,205 +1045,270 @@ Object.extend(Array.prototype, { }); return '[' + results.join(', ') + ']'; } -}); - -// use native browser JS 1.6 implementation if available -if (Object.isFunction(Array.prototype.forEach)) - Array.prototype._each = Array.prototype.forEach; - -if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { - i || (i = 0); - var length = this.length; - if (i < 0) i = length + i; - for (; i < length; i++) - if (this[i] === item) return i; - return -1; -}; - -if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { - i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; - var n = this.slice(0, i).reverse().indexOf(item); - return (n < 0) ? n : i - n - 1; -}; -Array.prototype.toArray = Array.prototype.clone; + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } -if (Prototype.Browser.Opera){ - Array.prototype.concat = function() { - var array = []; - for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + function concat() { + var array = slice.call(this, 0), item; for (var i = 0, length = arguments.length; i < length; i++) { - if (Object.isArray(arguments[i])) { - for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) - array.push(arguments[i][j]); + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); } else { - array.push(arguments[i]); + array.push(item); } } return array; - }; -} -Object.extend(Number.prototype, { - toColorPart: function() { - return this.toPaddedString(2, 16); - }, - - succ: function() { - return this + 1; - }, + } - times: function(iterator, context) { - $R(0, this, true).each(iterator, context); - return this; - }, + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); - toPaddedString: function(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - }, + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) - toJSON: function() { - return isFinite(this) ? this.toString() : 'null'; - } -}); + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; -$w('abs round ceil floor').each(function(method){ - Number.prototype[method] = Math[method].methodize(); -}); + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); function $H(object) { return new Hash(object); }; var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } function toQueryPair(key, value) { if (Object.isUndefined(value)) return key; return key + '=' + encodeURIComponent(String.interpret(value)); } - return { - initialize: function(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - }, - - _each: function(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; - set: function(key, value) { - return this._object[key] = value; - }, + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } - get: function(key) { - // simulating poorly supported hasOwnProperty - if (this._object[key] !== Object.prototype[key]) - return this._object[key]; - }, + function inspect() { + return '#'; + } - unset: function(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - }, + function toJSON() { + return Object.toJSON(this.toObject()); + } - toObject: function() { - return Object.clone(this._object); - }, + function clone() { + return new Hash(this); + } - keys: function() { - return this.pluck('key'); - }, + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; +})()); - values: function() { - return this.pluck('value'); - }, +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } - index: function(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - }, + function succ() { + return this + 1; + } - merge: function(object) { - return this.clone().update(object); - }, + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } - update: function(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - }, + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } - toQueryString: function() { - return this.inject([], function(results, pair) { - var key = encodeURIComponent(pair.key), values = pair.value; + function toJSON() { + return isFinite(this) ? this.toString() : 'null'; + } - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return results.concat(values.map(toQueryPair.curry(key))); - } else results.push(toQueryPair(key, values)); - return results; - }).join('&'); - }, + function abs() { + return Math.abs(this); + } - inspect: function() { - return '#'; - }, + function round() { + return Math.round(this); + } - toJSON: function() { - return Object.toJSON(this.toObject()); - }, + function ceil() { + return Math.ceil(this); + } - clone: function() { - return new Hash(this); - } + function floor() { + return Math.floor(this); } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + toJSON: toJSON, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; })()); -Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; -Hash.from = $H; -var ObjectRange = Class.create(Enumerable, { - initialize: function(start, end, exclusive) { +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; - }, + } - _each: function(iterator) { + function _each(iterator) { var value = this.start; while (this.include(value)) { iterator(value); value = value.succ(); } - }, + } - include: function(value) { + function include(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; } -}); -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -}; + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + var Ajax = { getTransport: function() { @@ -1164,7 +1355,6 @@ Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++ }, onComplete: function() { Ajax.activeRequestCount-- } }); - Ajax.Base = Class.create({ initialize: function(options) { this.options = { @@ -1186,7 +1376,6 @@ Ajax.Base = Class.create({ this.options.parameters = this.options.parameters.toObject(); } }); - Ajax.Request = Class.create(Ajax.Base, { _complete: false, @@ -1202,7 +1391,6 @@ Ajax.Request = Class.create(Ajax.Base, { var params = Object.clone(this.options.parameters); if (!['get', 'post'].include(this.method)) { - // simulate other verbs over post params['_method'] = this.method; this.method = 'post'; } @@ -1210,7 +1398,6 @@ Ajax.Request = Class.create(Ajax.Base, { this.parameters = params; if (params = Object.toQueryString(params)) { - // when GET, append parameters to URL if (this.method == 'get') this.url += (this.url.include('?') ? '&' : '?') + params; else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) @@ -1269,7 +1456,6 @@ Ajax.Request = Class.create(Ajax.Base, { headers['Connection'] = 'close'; } - // user-defined headers if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; @@ -1323,7 +1509,6 @@ Ajax.Request = Class.create(Ajax.Base, { } if (state == 'Complete') { - // avoid memory leak in MSIE: clean up this.transport.onreadystatechange = Prototype.emptyFunction; } }, @@ -1340,7 +1525,7 @@ Ajax.Request = Class.create(Ajax.Base, { getHeader: function(name) { try { return this.transport.getResponseHeader(name) || null; - } catch (e) { return null } + } catch (e) { return null; } }, evalResponse: function() { @@ -1360,6 +1545,13 @@ Ajax.Request = Class.create(Ajax.Base, { Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + Ajax.Response = Class.create({ initialize: function(request){ this.request = request; @@ -1381,6 +1573,7 @@ Ajax.Response = Class.create({ }, status: 0, + statusText: '', getStatus: Ajax.Request.prototype.getStatus, @@ -1510,6 +1703,9 @@ Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { this.updater = new Ajax.Updater(this.container, this.url, this.options); } }); + + + function $(element) { if (arguments.length > 1) { for (var i = 0, elements = [], length = arguments.length; i < length; i++) @@ -1537,7 +1733,6 @@ if (Prototype.BrowserFeatures.XPath) { if (!window.Node) var Node = { }; if (!Node.ELEMENT_NODE) { - // DOM level 2 ECMAScript Language Binding Object.extend(Node, { ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, @@ -1554,13 +1749,30 @@ if (!Node.ELEMENT_NODE) { }); } -(function() { - var element = this.Element; - this.Element = function(tagName, attributes) { + +(function(global) { + + var SETATTRIBUTE_IGNORES_NAME = (function(){ + var elForm = document.createElement("form"); + var elInput = document.createElement("input"); + var root = document.documentElement; + elInput.setAttribute("name", "test"); + elForm.appendChild(elInput); + root.appendChild(elForm); + var isBuggy = elForm.elements + ? (typeof elForm.elements.test == "undefined") + : null; + root.removeChild(elForm); + elForm = elInput = null; + return isBuggy; + })(); + + var element = global.Element; + global.Element = function(tagName, attributes) { attributes = attributes || { }; tagName = tagName.toLowerCase(); var cache = Element.cache; - if (Prototype.Browser.IE && attributes.name) { + if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { tagName = '<' + tagName + ' name="' + attributes.name + '">'; delete attributes.name; return Element.writeAttribute(document.createElement(tagName), attributes); @@ -1568,11 +1780,12 @@ if (!Node.ELEMENT_NODE) { if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); }; - Object.extend(this.Element, element || { }); - if (element) this.Element.prototype = element.prototype; -}).call(window); + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; +})(this); Element.cache = { }; +Element.idCounter = 1; Element.Methods = { visible: function(element) { @@ -1585,6 +1798,7 @@ Element.Methods = { return element; }, + hide: function(element) { element = $(element); element.style.display = 'none'; @@ -1603,15 +1817,89 @@ Element.Methods = { return element; }, - update: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - content = Object.toHTML(content); - element.innerHTML = content.stripScripts(); - content.evalScripts.bind(content).defer(); - return element; - }, + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), replace: function(element, content) { element = $(element); @@ -1696,11 +1984,11 @@ Element.Methods = { }, ancestors: function(element) { - return $(element).recursivelyCollect('parentNode'); + return Element.recursivelyCollect(element, 'parentNode'); }, descendants: function(element) { - return $(element).select("*"); + return Element.select(element, "*"); }, firstDescendant: function(element) { @@ -1717,16 +2005,17 @@ Element.Methods = { }, previousSiblings: function(element) { - return $(element).recursivelyCollect('previousSibling'); + return Element.recursivelyCollect(element, 'previousSibling'); }, nextSiblings: function(element) { - return $(element).recursivelyCollect('nextSibling'); + return Element.recursivelyCollect(element, 'nextSibling'); }, siblings: function(element) { element = $(element); - return element.previousSiblings().reverse().concat(element.nextSiblings()); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); }, match: function(element, selector) { @@ -1738,22 +2027,22 @@ Element.Methods = { up: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(element.parentNode); - var ancestors = element.ancestors(); + var ancestors = Element.ancestors(element); return Object.isNumber(expression) ? ancestors[expression] : Selector.findElement(ancestors, expression, index); }, down: function(element, expression, index) { element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - return Object.isNumber(expression) ? element.descendants()[expression] : + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : Element.select(element, expression)[index || 0]; }, previous: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); - var previousSiblings = element.previousSiblings(); + var previousSiblings = Element.previousSiblings(element); return Object.isNumber(expression) ? previousSiblings[expression] : Selector.findElement(previousSiblings, expression, index); }, @@ -1761,27 +2050,28 @@ Element.Methods = { next: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); - var nextSiblings = element.nextSiblings(); + var nextSiblings = Element.nextSiblings(element); return Object.isNumber(expression) ? nextSiblings[expression] : Selector.findElement(nextSiblings, expression, index); }, - select: function() { - var args = $A(arguments), element = $(args.shift()); + + select: function(element) { + var args = Array.prototype.slice.call(arguments, 1); return Selector.findChildElements(element, args); }, - adjacent: function() { - var args = $A(arguments), element = $(args.shift()); + adjacent: function(element) { + var args = Array.prototype.slice.call(arguments, 1); return Selector.findChildElements(element.parentNode, args).without(element); }, identify: function(element) { element = $(element); - var id = element.readAttribute('id'), self = arguments.callee; + var id = Element.readAttribute(element, 'id'); if (id) return id; - do { id = 'anonymous_element_' + self.counter++ } while ($(id)); - element.writeAttribute('id', id); + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); return id; }, @@ -1820,11 +2110,11 @@ Element.Methods = { }, getHeight: function(element) { - return $(element).getDimensions().height; + return Element.getDimensions(element).height; }, getWidth: function(element) { - return $(element).getDimensions().width; + return Element.getDimensions(element).width; }, classNames: function(element) { @@ -1840,7 +2130,7 @@ Element.Methods = { addClassName: function(element, className) { if (!(element = $(element))) return; - if (!element.hasClassName(className)) + if (!Element.hasClassName(element, className)) element.className += (element.className ? ' ' : '') + className; return element; }, @@ -1854,11 +2144,10 @@ Element.Methods = { toggleClassName: function(element, className) { if (!(element = $(element))) return; - return element[element.hasClassName(className) ? - 'removeClassName' : 'addClassName'](className); + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); }, - // removes whitespace-only text node children cleanWhitespace: function(element) { element = $(element); var node = element.firstChild; @@ -1892,7 +2181,7 @@ Element.Methods = { scrollTo: function(element) { element = $(element); - var pos = element.cumulativeOffset(); + var pos = Element.cumulativeOffset(element); window.scrollTo(pos[0], pos[1]); return element; }, @@ -1940,18 +2229,17 @@ Element.Methods = { getDimensions: function(element) { element = $(element); - var display = element.getStyle('display'); + var display = Element.getStyle(element, 'display'); if (display != 'none' && display != null) // Safari bug return {width: element.offsetWidth, height: element.offsetHeight}; - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; var originalDisplay = els.display; els.visibility = 'hidden'; - els.position = 'absolute'; + if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari + els.position = 'absolute'; els.display = 'block'; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; @@ -1967,8 +2255,6 @@ Element.Methods = { if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined if (Prototype.Browser.Opera) { element.style.top = 0; element.style.left = 0; @@ -2034,10 +2320,9 @@ Element.Methods = { absolutize: function(element) { element = $(element); - if (element.getStyle('position') == 'absolute') return element; - // Position.prepare(); // To be done manually by Scripty when it needs it. + if (Element.getStyle(element, 'position') == 'absolute') return element; - var offsets = element.positionedOffset(); + var offsets = Element.positionedOffset(element); var top = offsets[1]; var left = offsets[0]; var width = element.clientWidth; @@ -2058,8 +2343,7 @@ Element.Methods = { relativize: function(element) { element = $(element); - if (element.getStyle('position') == 'relative') return element; - // Position.prepare(); // To be done manually by Scripty when it needs it. + if (Element.getStyle(element, 'position') == 'relative') return element; element.style.position = 'relative'; var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); @@ -2101,7 +2385,6 @@ Element.Methods = { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; - // Safari fix if (element.offsetParent == document.body && Element.getStyle(element, 'position') == 'absolute') break; @@ -2128,28 +2411,22 @@ Element.Methods = { offsetLeft: 0 }, arguments[2] || { }); - // find page position of source source = $(source); - var p = source.viewportOffset(); + var p = Element.viewportOffset(source); - // find coordinate system to use element = $(element); var delta = [0, 0]; var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas if (Element.getStyle(element, 'position') == 'absolute') { - parent = element.getOffsetParent(); - delta = parent.viewportOffset(); + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); } - // correct by body offsets (fixes Safari) if (parent == document.body) { delta[0] -= document.body.offsetLeft; delta[1] -= document.body.offsetTop; } - // set position if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; if (options.setWidth) element.style.width = source.offsetWidth + 'px'; @@ -2158,10 +2435,9 @@ Element.Methods = { } }; -Element.Methods.identify.counter = 1; - Object.extend(Element.Methods, { getElementsBySelector: Element.Methods.select, + childElements: Element.Methods.immediateDescendants }); @@ -2182,11 +2458,8 @@ if (Prototype.Browser.Opera) { case 'left': case 'top': case 'right': case 'bottom': if (proceed(element, 'position') === 'static') return null; case 'height': case 'width': - // returns '0px' for hidden elements; we want it to return null if (!Element.visible(element)) return null; - // returns the border-box dimensions rather than the content-box - // dimensions, so we subtract padding and borders from the value var dim = parseInt(proceed(element, style), 10); if (dim !== element['offset' + style.capitalize()]) @@ -2219,12 +2492,9 @@ if (Prototype.Browser.Opera) { } else if (Prototype.Browser.IE) { - // IE doesn't report offsets correctly for static elements, so we change them - // to "relative" to get the values, then change them back. Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( function(proceed, element) { element = $(element); - // IE throws an error if element is not in document try { element.offsetParent } catch(e) { return $(document.body) } var position = element.getStyle('position'); @@ -2244,8 +2514,6 @@ else if (Prototype.Browser.IE) { catch(e) { return Element._returnOffset(0,0) } var position = element.getStyle('position'); if (position !== 'static') return proceed(element); - // Trigger hasLayout on the offset parent so that IE6 reports - // accurate offsetTop and offsetLeft values for position: fixed. var offsetParent = element.getOffsetParent(); if (offsetParent && offsetParent.getStyle('position') === 'fixed') offsetParent.setStyle({ zoom: 1 }); @@ -2306,36 +2574,92 @@ else if (Prototype.Browser.IE) { return element; }; - Element._attributeTranslations = { - read: { - names: { - 'class': 'className', - 'for': 'htmlFor' - }, - values: { - _getAttr: function(element, attribute) { - return element.getAttribute(attribute, 2); - }, - _getAttrNode: function(element, attribute) { - var node = element.getAttributeNode(attribute); - return node ? node.value : ""; - }, - _getEv: function(element, attribute) { - attribute = element.getAttribute(attribute); - return attribute ? attribute.toString().slice(23, -2) : null; - }, - _flag: function(element, attribute) { - return $(element).hasAttribute(attribute) ? attribute : null; - }, - style: function(element) { - return element.style.cssText.toLowerCase(); + Element._attributeTranslations = (function(){ + + var classProp = 'className'; + var forProp = 'for'; + + var el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp }, - title: function(element) { - return element.title; + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'); + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + var f; + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } } } } - }; + })(); Element._attributeTranslations.write = { names: Object.extend({ @@ -2363,8 +2687,8 @@ else if (Prototype.Browser.IE) { (function(v) { Object.extend(v, { - href: v._getAttr, - src: v._getAttr, + href: v._getAttr2, + src: v._getAttr2, type: v._getAttr, action: v._getAttrNode, disabled: v._flag, @@ -2391,6 +2715,26 @@ else if (Prototype.Browser.IE) { onchange: v._getEv }); })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + } else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { @@ -2420,9 +2764,6 @@ else if (Prototype.Browser.WebKit) { return element; }; - // Safari returns margins on body which is incorrect if the child is absolutely - // positioned. For performance reasons, redefine Element#cumulativeOffset for - // KHTML/WebKit only. Element.Methods.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { @@ -2438,30 +2779,7 @@ else if (Prototype.Browser.WebKit) { }; } -if (Prototype.Browser.IE || Prototype.Browser.Opera) { - // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements - Element.Methods.update = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - - content = Object.toHTML(content); - var tagName = element.tagName.toUpperCase(); - - if (tagName in Element._insertionTranslations.tags) { - $A(element.childNodes).each(function(node) { element.removeChild(node) }); - Element._getContentFromAnonymousElement(tagName, content.stripScripts()) - .each(function(node) { element.appendChild(node) }); - } - else element.innerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -if ('outerHTML' in document.createElement('div')) { +if ('outerHTML' in document.documentElement) { Element.Methods.replace = function(element, content) { element = $(element); @@ -2529,12 +2847,13 @@ Element._insertionTranslations = { }; (function() { - Object.extend(this.tags, { - THEAD: this.tags.TBODY, - TFOOT: this.tags.TBODY, - TH: this.tags.TD + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD }); -}).call(Element._insertionTranslations); +})(); Element.Methods.Simulated = { hasAttribute: function(element, attribute) { @@ -2548,41 +2867,81 @@ Element.Methods.ByTag = { }; Object.extend(Element, Element.Methods); -if (!Prototype.BrowserFeatures.ElementExtensions && - document.createElement('div')['__proto__']) { - window.HTMLElement = { }; - window.HTMLElement.prototype = document.createElement('div')['__proto__']; - Prototype.BrowserFeatures.ElementExtensions = true; -} +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')) Element.extend = (function() { - if (Prototype.BrowserFeatures.SpecificElementExtensions) + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2); + var el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } return Prototype.K; + } var Methods = { }, ByTag = Element.Methods.ByTag; var extend = Object.extend(function(element) { - if (!element || element._extendedByPrototype || + if (!element || typeof element._extendedByPrototype != 'undefined' || element.nodeType != 1 || element == window) return element; var methods = Object.clone(Methods), - tagName = element.tagName.toUpperCase(), property, value; + tagName = element.tagName.toUpperCase(); - // extend methods for specific tags if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); - for (property in methods) { - value = methods[property]; - if (Object.isFunction(value) && !(property in element)) - element[property] = value.methodize(); - } + extendElementWith(element, methods); element._extendedByPrototype = Prototype.emptyFunction; return element; }, { refresh: function() { - // extend methods for all tags (Safari doesn't need this) if (!Prototype.BrowserFeatures.ElementExtensions) { Object.extend(Methods, Element.Methods); Object.extend(Methods, Element.Methods.Simulated); @@ -2661,14 +3020,18 @@ Element.addMethods = function(methods) { klass = 'HTML' + tagName.capitalize() + 'Element'; if (window[klass]) return window[klass]; - window[klass] = { }; - window[klass].prototype = document.createElement(tagName)['__proto__']; - return window[klass]; + var element = document.createElement(tagName); + var proto = element['__proto__'] || element.constructor.prototype; + element = null; + return proto; } + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + if (F.ElementExtensions) { - copy(Element.Methods, HTMLElement.prototype); - copy(Element.Methods.Simulated, HTMLElement.prototype, true); + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); } if (F.SpecificElementExtensions) { @@ -2686,38 +3049,109 @@ Element.addMethods = function(methods) { Element.cache = { }; }; -document.viewport = { - getDimensions: function() { - var dimensions = { }, B = Prototype.Browser; - $w('width height').each(function(d) { - var D = d.capitalize(); - if (B.WebKit && !document.evaluate) { - // Safari <3.0 needs self.innerWidth/Height - dimensions[d] = self['inner' + D]; - } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) { - // Opera <9.5 needs document.body.clientWidth/Height - dimensions[d] = document.body['client' + D] - } else { - dimensions[d] = document.documentElement['client' + D]; - } - }); - return dimensions; - }, - getWidth: function() { - return this.getDimensions().width; - }, +document.viewport = { - getHeight: function() { - return this.getDimensions().height; + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; }, getScrollOffsets: function() { return Element._returnOffset( window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, - window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); } }; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = [Element.Storage.UID++]; + uid = element._prototypeUID[0]; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + } +}); /* Portions of the Selector class are derived from Jack Slocum's DomQuery, * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style * license. Please see http://www.yui-ext.com/ for more information. */ @@ -2738,31 +3172,52 @@ var Selector = Class.create({ }, - shouldUseXPath: function() { - if (!Prototype.BrowserFeatures.XPath) return false; + shouldUseXPath: (function() { - var e = this.expression; + var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ + var isBuggy = false; + if (document.evaluate && window.XPathResult) { + var el = document.createElement('div'); + el.innerHTML = '
'; - // Safari 3 chokes on :*-of-type and :empty - if (Prototype.Browser.WebKit && - (e.include("-of-type") || e.include(":empty"))) - return false; + var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; - // XPath can't do namespaced attributes, nor can it read - // the "checked" property from DOM nodes - if ((/(\[[\w-]*?:|:checked)/).test(e)) - return false; + var result = document.evaluate(xpath, el, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - return true; - }, + isBuggy = (result.snapshotLength !== 2); + el = null; + } + return isBuggy; + })(); + + return function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + if (IS_DESCENDANT_SELECTOR_BUGGY) return false; + + return true; + } + + })(), shouldUseSelectorsAPI: function() { if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; + if (!Selector._div) Selector._div = new Element('div'); - // Make sure the browser treats the selector as valid. Test on an - // isolated element to minimize cost of this check. try { Selector._div.querySelector(this.expression); } catch(e) { @@ -2774,7 +3229,7 @@ var Selector = Class.create({ compileMatcher: function() { var e = this.expression, ps = Selector.patterns, h = Selector.handlers, - c = Selector.criteria, le, p, m; + c = Selector.criteria, le, p, m, len = ps.length, name; if (Selector._cache[e]) { this.matcher = Selector._cache[e]; @@ -2786,11 +3241,12 @@ var Selector = Class.create({ while (e && le != e && (/\S/).test(e)) { le = e; - for (var i in ps) { - p = ps[i]; + for (var i = 0; i\s*/, - adjacent: /^\s*\+\s*/, - descendant: /^\s/, + patterns: [ + { name: 'laterSibling', re: /^\s*~\s*/ }, + { name: 'child', re: /^\s*>\s*/ }, + { name: 'adjacent', re: /^\s*\+\s*/ }, + { name: 'descendant', re: /^\s/ }, - // selectors follow - tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, - id: /^#([\w\-\*]+)(\b|$)/, - className: /^\.([\w\-\*]+)(\b|$)/, - pseudo: -/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, - attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/, - attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ - }, + { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, + { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, + { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, + { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, + { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, + { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } + ], - // for Selector.match and Element#match assertions: { tagName: function(element, matches) { return matches[1].toUpperCase() == element.tagName.toUpperCase(); @@ -3064,15 +3527,12 @@ Object.extend(Selector, { }, handlers: { - // UTILITY FUNCTIONS - // joins two collections concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) a.push(node); return a; }, - // marks an array of nodes for counting mark: function(nodes) { var _true = Prototype.emptyFunction; for (var i = 0, node; node = nodes[i]; i++) @@ -3080,15 +3540,32 @@ Object.extend(Selector, { return nodes; }, - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = undefined; - return nodes; - }, + unmark: (function(){ + + var PROPERTIES_ATTRIBUTES_MAP = (function(){ + var el = document.createElement('div'), + isBuggy = false, + propName = '_countedByPrototype', + value = 'x' + el[propName] = value; + isBuggy = (el.getAttribute(propName) === value); + el = null; + return isBuggy; + })(); + + return PROPERTIES_ATTRIBUTES_MAP ? + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } : + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = void 0; + return nodes; + } + })(), - // mark each child node with its position (for nth calls) - // "ofType" flag indicates whether we're indexing for nth-of-type - // rather than nth-child index: function(parentNode, reverse, ofType) { parentNode._countedByPrototype = Prototype.emptyFunction; if (reverse) { @@ -3102,19 +3579,17 @@ Object.extend(Selector, { } }, - // filters out duplicates and extends all nodes unique: function(nodes) { if (nodes.length == 0) return nodes; var results = [], n; for (var i = 0, l = nodes.length; i < l; i++) - if (!(n = nodes[i])._countedByPrototype) { + if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { n._countedByPrototype = Prototype.emptyFunction; results.push(Element.extend(n)); } return Selector.handlers.unmark(results); }, - // COMBINATOR FUNCTIONS descendant: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) @@ -3158,13 +3633,11 @@ Object.extend(Selector, { return null; }, - // TOKEN FUNCTIONS tagName: function(nodes, root, tagName, combinator) { var uTagName = tagName.toUpperCase(); var results = [], h = Selector.handlers; if (nodes) { if (combinator) { - // fastlane for ordinary descendant combinators if (combinator == "descendant") { for (var i = 0, node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName(tagName)); @@ -3180,8 +3653,19 @@ Object.extend(Selector, { id: function(nodes, root, id, combinator) { var targetNode = $(id), h = Selector.handlers; - if (!targetNode) return []; - if (!nodes && root == document) return [targetNode]; + + if (root == document) { + if (!targetNode) return []; + if (!nodes) return [targetNode]; + } else { + if (!root.sourceIndex || root.sourceIndex < 1) { + var nodes = root.getElementsByTagName('*'); + for (var j = 0, node; node = nodes[j]; j++) { + if (node.id === id) return [node]; + } + } + } + if (nodes) { if (combinator) { if (combinator == 'child') { @@ -3293,7 +3777,6 @@ Object.extend(Selector, { return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); }, - // handles the an+b logic getIndices: function(a, b, total) { if (a == 0) return b > 0 ? [b] : []; return $R(1, total).inject([], function(memo, i) { @@ -3302,7 +3785,6 @@ Object.extend(Selector, { }); }, - // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type nth: function(nodes, formula, root, reverse, ofType) { if (nodes.length == 0) return []; if (formula == 'even') formula = '2n+0'; @@ -3336,7 +3818,6 @@ Object.extend(Selector, { 'empty': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { - // IE treats comments as element nodes if (node.tagName == '!' || node.firstChild) continue; results.push(node); } @@ -3379,8 +3860,6 @@ Object.extend(Selector, { '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, - '$=': function(nv, v) { return nv.endsWith(v); }, - '*=': function(nv, v) { return nv.include(v); }, '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + '-').include('-' + (v || "").toUpperCase() + '-'); } @@ -3423,19 +3902,10 @@ Object.extend(Selector, { if (Prototype.Browser.IE) { Object.extend(Selector.handlers, { - // IE returns comment nodes on getElementsByTagName("*"). - // Filter them out. concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) if (node.tagName !== "!") a.push(node); return a; - }, - - // IE improperly serializes _countedByPrototype in (inner|outer)HTML. - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node.removeAttribute('_countedByPrototype'); - return nodes; } }); } @@ -3443,9 +3913,11 @@ if (Prototype.Browser.IE) { function $$() { return Selector.findChildElements(document, $A(arguments)); } + var Form = { reset: function(form) { - $(form).reset(); + form = $(form); + form.reset(); return form; }, @@ -3460,7 +3932,6 @@ var Form = { if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) { if (key in result) { - // a key is already present; construct an array of values if (!Object.isArray(result[key])) result[key] = [result[key]]; result[key].push(value); } @@ -3480,13 +3951,18 @@ Form.Methods = { }, getElements: function(form) { - return $A($(form).getElementsByTagName('*')).inject([], - function(elements, child) { - if (Form.Element.Serializers[child.tagName.toLowerCase()]) - elements.push(Element.extend(child)); - return elements; - } - ); + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) }, getInputs: function(form, typeName, name) { @@ -3526,7 +4002,7 @@ Form.Methods = { }).sortBy(function(element) { return element.tabIndex }).first(); return firstByIndex ? firstByIndex : elements.find(function(element) { - return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + return /^(?:input|select|textarea)$/i.test(element.tagName); }); }, @@ -3557,6 +4033,7 @@ Form.Methods = { /*--------------------------------------------------------------------------*/ + Form.Element = { focus: function(element) { $(element).focus(); @@ -3570,6 +4047,7 @@ Form.Element = { }; Form.Element.Methods = { + serialize: function(element) { element = $(element); if (!element.disabled && element.name) { @@ -3610,7 +4088,7 @@ Form.Element.Methods = { try { element.focus(); if (element.select && (element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type))) + !(/^(?:button|reset|submit)$/i.test(element.type)))) element.select(); } catch (e) { } return element; @@ -3632,6 +4110,7 @@ Form.Element.Methods = { /*--------------------------------------------------------------------------*/ var Field = Form.Element; + var $F = Form.Element.Methods.getValue; /*--------------------------------------------------------------------------*/ @@ -3694,13 +4173,13 @@ Form.Element.Serializers = { }, optionValue: function(opt) { - // extend element because hasAttribute may not be native return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; } }; /*--------------------------------------------------------------------------*/ + Abstract.TimedObserver = Class.create(PeriodicalExecuter, { initialize: function($super, element, frequency, callback) { $super(callback, frequency); @@ -3782,354 +4261,441 @@ Form.EventObserver = Class.create(Abstract.EventObserver, { return Form.serialize(this.element); } }); -if (!window.Event) var Event = { }; - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - KEY_HOME: 36, - KEY_END: 35, - KEY_PAGEUP: 33, - KEY_PAGEDOWN: 34, - KEY_INSERT: 45, - - cache: { }, - - relatedTarget: function(event) { - var element; - switch(event.type) { - case 'mouseover': element = event.fromElement; break; - case 'mouseout': element = event.toElement; break; - default: return null; - } - return Element.extend(element); - } -}); +(function() { + + var Event = { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; -Event.Methods = (function() { - var isButton; + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + var _isButton; if (Prototype.Browser.IE) { var buttonMap = { 0: 1, 1: 4, 2: 2 }; - isButton = function(event, code) { - return event.button == buttonMap[code]; + _isButton = function(event, code) { + return event.button === buttonMap[code]; }; - } else if (Prototype.Browser.WebKit) { - isButton = function(event, code) { + _isButton = function(event, code) { switch (code) { case 0: return event.which == 1 && !event.metaKey; case 1: return event.which == 1 && event.metaKey; default: return false; } }; - } else { - isButton = function(event, code) { + _isButton = function(event, code) { return event.which ? (event.which === code + 1) : (event.button === code); }; } - return { - isLeftClick: function(event) { return isButton(event, 0) }, - isMiddleClick: function(event) { return isButton(event, 1) }, - isRightClick: function(event) { return isButton(event, 2) }, - - element: function(event) { - event = Event.extend(event); - - var node = event.target, - type = event.type, - currentTarget = event.currentTarget; - - if (currentTarget && currentTarget.tagName) { - // Firefox screws up the "click" event when moving between radio buttons - // via arrow keys. It also screws up the "load" and "error" events on images, - // reporting the document as the target instead of the original image. - if (type === 'load' || type === 'error' || - (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' - && currentTarget.type === 'radio')) - node = currentTarget; - } - if (node.nodeType == Node.TEXT_NODE) node = node.parentNode; - return Element.extend(node); - }, + function isLeftClick(event) { return _isButton(event, 0) } - findElement: function(event, expression) { - var element = Event.element(event); - if (!expression) return element; - var elements = [element].concat(element.ancestors()); - return Selector.findElement(elements, expression, 0); - }, + function isMiddleClick(event) { return _isButton(event, 1) } - pointer: function(event) { - var docElement = document.documentElement, - body = document.body || { scrollLeft: 0, scrollTop: 0 }; - return { - x: event.pageX || (event.clientX + - (docElement.scrollLeft || body.scrollLeft) - - (docElement.clientLeft || 0)), - y: event.pageY || (event.clientY + - (docElement.scrollTop || body.scrollTop) - - (docElement.clientTop || 0)) - }; - }, + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); - pointerX: function(event) { return Event.pointer(event).x }, - pointerY: function(event) { return Event.pointer(event).y }, + var node = event.target, type = event.type, + currentTarget = event.currentTarget; - stop: function(event) { - Event.extend(event); - event.preventDefault(); - event.stopPropagation(); - event.stopped = true; + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop }; -})(); -Event.extend = (function() { + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { m[name] = Event.Methods[name].methodize(); return m; }); if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + Object.extend(methods, { stopPropagation: function() { this.cancelBubble = true }, preventDefault: function() { this.returnValue = false }, - inspect: function() { return "[object Event]" } + inspect: function() { return '[object Event]' } }); - return function(event) { + Event.extend = function(event, element) { if (!event) return false; if (event._extendedByPrototype) return event; event._extendedByPrototype = Prototype.emptyFunction; var pointer = Event.pointer(event); + Object.extend(event, { - target: event.srcElement, - relatedTarget: Event.relatedTarget(event), + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), pageX: pointer.x, pageY: pointer.y }); + return Object.extend(event, methods); }; - } else { - Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__']; + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; Object.extend(Event.prototype, methods); - return Prototype.K; + Event.extend = Prototype.K; } -})(); -Object.extend(Event, (function() { - var cache = Event.cache; - - function getEventID(element) { - if (element._prototypeEventID) return element._prototypeEventID[0]; - arguments.callee.id = arguments.callee.id || 1; - return element._prototypeEventID = [++arguments.callee.id]; - } + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); - function getDOMEventName(eventName) { - if (eventName && eventName.include(':')) return "dataavailable"; - return eventName; - } + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } - function getCacheForID(id) { - return cache[id] = cache[id] || { }; - } + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } - function getWrappersForEventName(id, eventName) { - var c = getCacheForID(id); - return c[eventName] = c[eventName] || []; - } + if (respondersForEvent.pluck('handler').include(handler)) return false; - function createWrapper(element, eventName, handler) { - var id = getEventID(element); - var c = getWrappersForEventName(id, eventName); - if (c.pluck("handler").include(handler)) return false; + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; - var wrapper = function(event) { - if (!Event || !Event.extend || - (event.eventName && event.eventName != eventName)) + if (event.eventName !== eventName) return false; - Event.extend(event); - handler.call(element, event); - }; + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } - wrapper.handler = handler; - c.push(wrapper); - return wrapper; - } + if (parent === element) return; - function findWrapper(id, eventName, handler) { - var c = getWrappersForEventName(id, eventName); - return c.find(function(wrapper) { return wrapper.handler == handler }); - } + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } - function destroyWrapper(id, eventName, handler) { - var c = getCacheForID(id); - if (!c[eventName]) return false; - c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + responder.handler = handler; + respondersForEvent.push(responder); + return responder; } - function destroyCache() { - for (var id in cache) - for (var eventName in cache[id]) - cache[id][eventName] = null; + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } } + var CACHE = []; - // Internet Explorer needs to remove event handlers on page unload - // in order to avoid memory leaks. - if (window.attachEvent) { - window.attachEvent("onunload", destroyCache); - } + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); - // Safari has a dummy event handler on page unload so that it won't - // use its bfcache. Safari <= 3.1 has an issue with restoring the "document" - // object when page is returned to via the back button using its bfcache. - if (Prototype.Browser.WebKit) { + if (Prototype.Browser.WebKit) window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; } - return { - observe: function(element, eventName, handler) { - element = $(element); - var name = getDOMEventName(eventName); + function observe(element, eventName, handler) { + element = $(element); - var wrapper = createWrapper(element, eventName, handler); - if (!wrapper) return element; + var responder = _createResponder(element, eventName, handler); - if (element.addEventListener) { - element.addEventListener(name, wrapper, false); - } else { - element.attachEvent("on" + name, wrapper); + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); } + } else { + var actualEventName = _getDOMEventName(eventName); - return element; - }, + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } - stopObserving: function(element, eventName, handler) { - element = $(element); - var id = getEventID(element), name = getDOMEventName(eventName); + return element; + } - if (!handler && eventName) { - getWrappersForEventName(id, eventName).each(function(wrapper) { - element.stopObserving(eventName, wrapper.handler); - }); - return element; + function stopObserving(element, eventName, handler) { + element = $(element); - } else if (!eventName) { - Object.keys(getCacheForID(id)).each(function(eventName) { - element.stopObserving(eventName); - }); - return element; - } + var registry = Element.retrieve(element, 'prototype_event_registry'); - var wrapper = findWrapper(id, eventName, handler); - if (!wrapper) return element; + if (Object.isUndefined(registry)) return element; - if (element.removeEventListener) { - element.removeEventListener(name, wrapper, false); - } else { - element.detachEvent("on" + name, wrapper); - } + if (eventName && !handler) { + var responders = registry.get(eventName); - destroyWrapper(id, eventName, handler); + if (Object.isUndefined(responders)) return element; + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); return element; - }, + } else if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key, responders = pair.value; - fire: function(element, eventName, memo) { - element = $(element); - if (element == document && document.createEvent && !element.dispatchEvent) - element = document.documentElement; + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + }); + return element; + } - var event; - if (document.createEvent) { - event = document.createEvent("HTMLEvents"); - event.initEvent("dataavailable", true, true); - } else { - event = document.createEventObject(); - event.eventType = "ondataavailable"; - } + var responders = registry.get(eventName); - event.eventName = eventName; - event.memo = memo || { }; + if (!responders) return; - if (document.createEvent) { - element.dispatchEvent(event); - } else { - element.fireEvent(event.eventType, event); + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + var actualEventName = _getDOMEventName(eventName); + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); } + } else { + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; - return Event.extend(event); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; } - }; -})()); -Object.extend(Event, Event.Methods); + event.eventName = eventName; + event.memo = memo || { }; -Element.addMethods({ - fire: Event.fire, - observe: Event.observe, - stopObserving: Event.stopObserving -}); + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); -Object.extend(document, { - fire: Element.Methods.fire.methodize(), - observe: Element.Methods.observe.methodize(), - stopObserving: Element.Methods.stopObserving.methodize(), - loaded: false -}); + return Event.extend(event); + } + + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); (function() { /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards and John Resig. */ + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ var timer; function fireContentLoadedEvent() { if (document.loaded) return; - if (timer) window.clearInterval(timer); - document.fire("dom:loaded"); + if (timer) window.clearTimeout(timer); document.loaded = true; + document.fire('dom:loaded'); } - if (document.addEventListener) { - if (Prototype.Browser.WebKit) { - timer = window.setInterval(function() { - if (/loaded|complete/.test(document.readyState)) - fireContentLoadedEvent(); - }, 0); - - Event.observe(window, "load", fireContentLoadedEvent); + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } - } else { - document.addEventListener("DOMContentLoaded", - fireContentLoadedEvent, false); + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; } + fireContentLoadedEvent(); + } + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); } else { - document.write("