From 547407a9fb375601deb0834fb1c2d9a108c9aea1 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 16 Mar 2011 23:16:15 +0530 Subject: remove to from to to :) --- railties/guides/source/2_3_release_notes.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/2_3_release_notes.textile b/railties/guides/source/2_3_release_notes.textile index 67743a4797..15abba66ab 100644 --- a/railties/guides/source/2_3_release_notes.textile +++ b/railties/guides/source/2_3_release_notes.textile @@ -410,7 +410,7 @@ You're likely familiar with Rails' practice of adding timestamps to static asset h4. Asset Hosts as Objects -Asset hosts get more flexible in edge Rails with the ability to declare an asset host as a specific object that responds to a call. This allows you to to implement any complex logic you need in your asset hosting. +Asset hosts get more flexible in edge Rails with the ability to declare an asset host as a specific object that responds to a call. This allows you to implement any complex logic you need in your asset hosting. * More Information: "asset-hosting-with-minimum-ssl":http://github.com/dhh/asset-hosting-with-minimum-ssl/tree/master -- cgit v1.2.3 From 3e7985c9c1a6899ac06857bd8e6f29b48ad87cea Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 21 Mar 2011 17:58:28 -0500 Subject: Add sprockets environment to Application --- railties/lib/rails/application.rb | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 94819820bc..3415cc5a5d 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -137,6 +137,40 @@ module Rails @config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd)) end + def self.default_sprockets_paths + [ + "app/assets", + "app/javascripts", + "app/stylesheets", + "vendor/plugins/*/app/assets", + "vendor/plugins/*/app/javascripts", + "vendor/plugins/*/app/stylesheets", + "vendor/plugins/*/assets", + "vendor/plugins/*/javascripts", + "vendor/plugins/*/stylesheets" + ] + end + + def assets + @assets ||= build_asset_environment + end + + def build_asset_environment + require 'sprockets' + + env = Sprockets::Environment.new(root.to_s) + env.logger = Rails.logger + env.ensure_fresh_assets = !config.action_controller.perform_caching + + self.class.default_sprockets_paths.each do |pattern| + Dir[root.join(pattern)].each do |dir| + env.paths << dir + end + end + + env + end + protected def default_asset_path -- cgit v1.2.3 From 77ad4ca058c9a845257cbeb58a84cf511bae1040 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 21 Mar 2011 18:05:56 -0500 Subject: Add sprockets task to compile assets --- railties/lib/rails/application/configuration.rb | 4 +++- railties/lib/rails/tasks/assets.rake | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 railties/lib/rails/tasks/assets.rake (limited to 'railties') diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index c74bcbedf2..6901748d04 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -9,7 +9,8 @@ module Rails :filter_parameters, :helpers_paths, :logger, :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, - :time_zone, :whiny_nils + :time_zone, :whiny_nils, + :compile_assets attr_writer :log_level @@ -28,6 +29,7 @@ module Rails @log_level = nil @middleware = app_middleware @generators = app_generators + @compile_assets = [] end def compiled_asset_path diff --git a/railties/lib/rails/tasks/assets.rake b/railties/lib/rails/tasks/assets.rake new file mode 100644 index 0000000000..b6604a49c2 --- /dev/null +++ b/railties/lib/rails/tasks/assets.rake @@ -0,0 +1,14 @@ +namespace :assets do + task :compile => :environment do + env = Rails.application.assets + + assets = Rails.root.join("public/assets") + assets.mkdir unless assets.exist? + + Rails.application.config.compile_assets.each do |path| + assets.join(path).open('w') do |f| + f.write env[path].to_s + end + end + end +end -- cgit v1.2.3 From 10c7e61825eb7fbcee9368420ce6fa1e5fa06785 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 21 Mar 2011 18:09:23 -0500 Subject: Need to load assets task file --- railties/lib/rails/tasks.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties') diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index af52014728..4d09b0c2c0 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -3,6 +3,7 @@ $VERBOSE = nil # Load Rails rakefile extensions %w( annotations + assets documentation framework log -- cgit v1.2.3 From cef10d8ec58a661c231c5a9e0dc3e01165831807 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Mar 2011 11:15:24 -0500 Subject: Assign sprockets static root --- railties/lib/rails/application.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 3415cc5a5d..81896a1596 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -160,6 +160,7 @@ module Rails env = Sprockets::Environment.new(root.to_s) env.logger = Rails.logger + env.static_root = Rails.root.join("public/assets") env.ensure_fresh_assets = !config.action_controller.perform_caching self.class.default_sprockets_paths.each do |pattern| -- cgit v1.2.3 From 6aff1d0f6f0bcd82d2f99a757b9ae58caa3290c5 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Mar 2011 14:40:18 -0500 Subject: Remove ensure_fresh_assets flag --- railties/lib/rails/application.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 81896a1596..d2777ed5f1 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -161,7 +161,6 @@ module Rails env = Sprockets::Environment.new(root.to_s) env.logger = Rails.logger env.static_root = Rails.root.join("public/assets") - env.ensure_fresh_assets = !config.action_controller.perform_caching self.class.default_sprockets_paths.each do |pattern| Dir[root.join(pattern)].each do |dir| -- cgit v1.2.3 From 989103a2334648c5b63e51a9480bcc435283f559 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Mar 2011 16:15:05 -0500 Subject: Move app/javascripts and app/stylesheets under app/assets --- railties/lib/rails/application.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index d2777ed5f1..ff9272c837 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -140,14 +140,14 @@ module Rails def self.default_sprockets_paths [ "app/assets", - "app/javascripts", - "app/stylesheets", + "app/assets/javascripts", + "app/assets/stylesheets", "vendor/plugins/*/app/assets", - "vendor/plugins/*/app/javascripts", - "vendor/plugins/*/app/stylesheets", + "vendor/plugins/*/app/assets/javascripts", + "vendor/plugins/*/app/assets/stylesheets", "vendor/plugins/*/assets", - "vendor/plugins/*/javascripts", - "vendor/plugins/*/stylesheets" + "vendor/plugins/*/assets/javascripts", + "vendor/plugins/*/assets/stylesheets" ] end -- cgit v1.2.3 From 8c26d0dba6538a29ae117e5f3dbf1dd2d569183d Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Mar 2011 16:24:01 -0500 Subject: Use sprockets precompile --- railties/lib/rails/tasks/assets.rake | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/tasks/assets.rake b/railties/lib/rails/tasks/assets.rake index b6604a49c2..63e49ad2de 100644 --- a/railties/lib/rails/tasks/assets.rake +++ b/railties/lib/rails/tasks/assets.rake @@ -1,14 +1,6 @@ namespace :assets do task :compile => :environment do - env = Rails.application.assets - - assets = Rails.root.join("public/assets") - assets.mkdir unless assets.exist? - - Rails.application.config.compile_assets.each do |path| - assets.join(path).open('w') do |f| - f.write env[path].to_s - end - end + assets = ENV['assets'].split(',') + Rails.application.assets.precompile(*assets) end end -- cgit v1.2.3 From ce52c6f4a74f7cb9d9e321203bb47f0f3364bfb2 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 22 Mar 2011 16:36:21 -0500 Subject: Change static root to /public --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index ff9272c837..57672a1324 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -160,7 +160,7 @@ module Rails env = Sprockets::Environment.new(root.to_s) env.logger = Rails.logger - env.static_root = Rails.root.join("public/assets") + env.static_root = Rails.root.join("public") self.class.default_sprockets_paths.each do |pattern| Dir[root.join(pattern)].each do |dir| -- cgit v1.2.3 From 62dd3458e326b1f2927d43401e7b10004410fdf0 Mon Sep 17 00:00:00 2001 From: mhutchin Date: Sun, 27 Mar 2011 23:50:51 -0700 Subject: Minor typo correction. --- railties/guides/source/configuring.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index 298335d484..9ca567129b 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -149,7 +149,7 @@ h4. Configuring Middleware Every Rails application comes with a standard set of middleware which it uses in this order in the development environment: -* +Rack::SSL+ Will force every requests to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_. +* +Rack::SSL+ Will force every request to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_. * +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_. * +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default. * +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread. -- cgit v1.2.3 From 170680ae9179ea6ce35e1a2ca50ea474bf2126ab Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 28 Mar 2011 11:04:31 -0500 Subject: Add route for assets --- railties/lib/rails/application.rb | 34 ---------------------------------- railties/lib/rails/engine.rb | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 34 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 57672a1324..94819820bc 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -137,40 +137,6 @@ module Rails @config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd)) end - def self.default_sprockets_paths - [ - "app/assets", - "app/assets/javascripts", - "app/assets/stylesheets", - "vendor/plugins/*/app/assets", - "vendor/plugins/*/app/assets/javascripts", - "vendor/plugins/*/app/assets/stylesheets", - "vendor/plugins/*/assets", - "vendor/plugins/*/assets/javascripts", - "vendor/plugins/*/assets/stylesheets" - ] - end - - def assets - @assets ||= build_asset_environment - end - - def build_asset_environment - require 'sprockets' - - env = Sprockets::Environment.new(root.to_s) - env.logger = Rails.logger - env.static_root = Rails.root.join("public") - - self.class.default_sprockets_paths.each do |pattern| - Dir[root.join(pattern)].each do |dir| - env.paths << dir - end - end - - env - end - protected def default_asset_path diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 4fc23fe277..d0b245c595 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -434,10 +434,45 @@ module Rails def routes @routes ||= ActionDispatch::Routing::RouteSet.new + @routes.add_route(assets, {}, {}, {}, nil, false) @routes.append(&Proc.new) if block_given? @routes end + def self.default_sprockets_paths + [ + "app/assets", + "app/assets/javascripts", + "app/assets/stylesheets", + "vendor/plugins/*/app/assets", + "vendor/plugins/*/app/assets/javascripts", + "vendor/plugins/*/app/assets/stylesheets", + "vendor/plugins/*/assets", + "vendor/plugins/*/assets/javascripts", + "vendor/plugins/*/assets/stylesheets" + ] + end + + def assets + @assets ||= build_asset_environment + end + + def build_asset_environment + require 'sprockets' + + env = Sprockets::Environment.new(root.to_s) + env.logger = Rails.logger + env.static_root = root.join("public") + + self.class.default_sprockets_paths.each do |pattern| + Dir[root.join(pattern)].each do |dir| + env.paths << dir + end + end + + env + end + def initializers initializers = [] railties.all { |r| initializers += r.initializers } -- cgit v1.2.3 From 7197eb77d593768a5278c4fcaac157a2a0f704ca Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 28 Mar 2011 11:10:45 -0500 Subject: Logger isn't set here --- railties/lib/rails/engine.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index d0b245c595..23177df11f 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -461,7 +461,7 @@ module Rails require 'sprockets' env = Sprockets::Environment.new(root.to_s) - env.logger = Rails.logger + # env.logger = Rails.logger env.static_root = root.join("public") self.class.default_sprockets_paths.each do |pattern| -- cgit v1.2.3 From 954d73df5312f4829c96a76f1929e45597e85680 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 28 Mar 2011 13:22:13 -0500 Subject: Add use_sprockets flag --- railties/lib/rails/application/configuration.rb | 4 +--- railties/lib/rails/engine.rb | 4 +++- railties/lib/rails/engine/configuration.rb | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 6901748d04..c74bcbedf2 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -9,8 +9,7 @@ module Rails :filter_parameters, :helpers_paths, :logger, :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, - :time_zone, :whiny_nils, - :compile_assets + :time_zone, :whiny_nils attr_writer :log_level @@ -29,7 +28,6 @@ module Rails @log_level = nil @middleware = app_middleware @generators = app_generators - @compile_assets = [] end def compiled_asset_path diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 23177df11f..1c4e5dadc7 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -434,7 +434,7 @@ module Rails def routes @routes ||= ActionDispatch::Routing::RouteSet.new - @routes.add_route(assets, {}, {}, {}, nil, false) + @routes.add_route(assets, {}, {}, {}, nil, false) if config.use_sprockets @routes.append(&Proc.new) if block_given? @routes end @@ -458,6 +458,8 @@ module Rails end def build_asset_environment + return nil if !use_sprockets + require 'sprockets' env = Sprockets::Environment.new(root.to_s) diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 4f458b0aee..1b4a712c75 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -5,12 +5,15 @@ module Rails class Configuration < ::Rails::Railtie::Configuration attr_reader :root attr_writer :middleware, :eager_load_paths, :autoload_once_paths, :autoload_paths - attr_accessor :plugins, :asset_path + attr_accessor :plugins, :asset_path, :use_sprockets, :compile_assets def initialize(root=nil) super() @root = root @generators = app_generators.dup + + @use_sprockets = false + @compile_assets = [] end # Returns the middleware stack for the engine. -- cgit v1.2.3 From 8ceec5c6c27fab782732834f088eff4cb0ac73f3 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 28 Mar 2011 13:44:14 -0500 Subject: Fix reference to config.use_sprockets --- railties/lib/rails/engine.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 1c4e5dadc7..04676a42dd 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -458,7 +458,7 @@ module Rails end def build_asset_environment - return nil if !use_sprockets + return nil if !config.use_sprockets require 'sprockets' -- cgit v1.2.3 From 70779a08a0bec1b890c1b7d77114dedc7f1b69e2 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Mon, 28 Mar 2011 22:46:13 -0300 Subject: Updated Basic Authentication guides to reflect new Base.http_basic_authenticate_with method --- .../source/action_controller_overview.textile | 17 +++----------- railties/guides/source/getting_started.textile | 27 ++++------------------ 2 files changed, 8 insertions(+), 36 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile index 178d98c2d6..9dffdce8de 100644 --- a/railties/guides/source/action_controller_overview.textile +++ b/railties/guides/source/action_controller_overview.textile @@ -615,26 +615,15 @@ Rails comes with two built-in HTTP authentication mechanisms: h4. HTTP Basic Authentication -HTTP basic authentication is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser's HTTP basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, +authenticate_or_request_with_http_basic+. +HTTP basic authentication is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser's HTTP basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, +http_basic_authenticate_with+. class AdminController < ApplicationController - USERNAME, PASSWORD = "humbaba", "5baa61e4" - - before_filter :authenticate - - private - - def authenticate - authenticate_or_request_with_http_basic do |username, password| - username == USERNAME && - Digest::SHA1.hexdigest(password) == PASSWORD - end - end + http_basic_authenticate_with :name => "humbaba", "5baa61e4" end -With this in place, you can create namespaced controllers that inherit from +AdminController+. The before filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication. +With this in place, you can create namespaced controllers that inherit from +AdminController+. The filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication. h4. HTTP Digest Authentication diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 0661549644..0bc2d9144e 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1201,33 +1201,16 @@ h3. Security If you were to publish your blog online, anybody would be able to add, edit and delete posts or delete comments. -Rails provides a very simple HTTP authentication system that will work nicely in this situation. First, we enable simple HTTP based authentication in our app/controllers/application_controller.rb: +Rails provides a very simple HTTP authentication system that will work nicely in this situation. - -class ApplicationController < ActionController::Base - protect_from_forgery - - private - - def authenticate - authenticate_or_request_with_http_basic do |user_name, password| - user_name == 'admin' && password == 'password' - end - end - -end - - -You can obviously change the username and password to whatever you want. We put this method inside of +ApplicationController+ so that it is available to all of our controllers. - -Then in the +PostsController+ we need to have a way to block access to the various actions if the person is not authenticated, here we can use the Rails before_filter method, which allows us to specify that Rails must run a method and only then allow access to the requested action if that method allows it. +In the +PostsController+ we need to have a way to block access to the various actions if the person is not authenticated, here we can use the Rails http_basic_authenticate_with method, allowing access to the requested action if that method allows it. -To use the before filter, we specify it at the top of our +PostsController+, in this case, we want the user to be authenticated on every action, except for +index+ and +show+, so we write that: +To use the authentication system, we specify it at the top of our +PostsController+, in this case, we want the user to be authenticated on every action, except for +index+ and +show+, so we write that: class PostsController < ApplicationController - before_filter :authenticate, :except => [:index, :show] + http_basic_authenticate_with :name => "dhh", "secret", :except => :index # GET /posts # GET /posts.xml @@ -1242,7 +1225,7 @@ We also only want to allow authenticated users to delete comments, so in the +Co class CommentsController < ApplicationController - before_filter :authenticate, :only => :destroy + http_basic_authenticate_with :name => "dhh", "secret", :only => :destroy def create @post = Post.find(params[:post_id]) -- cgit v1.2.3 From 54af8dfbfc4122494235d817cd98b83874241215 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Mon, 28 Mar 2011 22:49:43 -0300 Subject: Fix Basic Authentication examples --- railties/guides/source/action_controller_overview.textile | 2 +- railties/guides/source/getting_started.textile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile index 9dffdce8de..496dc7224b 100644 --- a/railties/guides/source/action_controller_overview.textile +++ b/railties/guides/source/action_controller_overview.textile @@ -619,7 +619,7 @@ HTTP basic authentication is an authentication scheme that is supported by the m class AdminController < ApplicationController - http_basic_authenticate_with :name => "humbaba", "5baa61e4" + http_basic_authenticate_with :name => "humbaba", :password => "5baa61e4" end diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 0bc2d9144e..1122a4b9e3 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -1210,7 +1210,7 @@ To use the authentication system, we specify it at the top of our +PostsControll class PostsController < ApplicationController - http_basic_authenticate_with :name => "dhh", "secret", :except => :index + http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index # GET /posts # GET /posts.xml @@ -1225,7 +1225,7 @@ We also only want to allow authenticated users to delete comments, so in the +Co class CommentsController < ApplicationController - http_basic_authenticate_with :name => "dhh", "secret", :only => :destroy + http_basic_authenticate_with :name => "dhh", :password => "secret", :only => :destroy def create @post = Post.find(params[:post_id]) -- cgit v1.2.3 From 9fdfe2ec1e4451b9dd4c3cdfdf22c895659f53e7 Mon Sep 17 00:00:00 2001 From: mhutchin Date: Tue, 29 Mar 2011 00:39:33 -0700 Subject: Fixed typo and improved readability. --- railties/guides/source/testing.textile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile index d3f72509c6..d937f30609 100644 --- a/railties/guides/source/testing.textile +++ b/railties/guides/source/testing.textile @@ -748,7 +748,8 @@ You don't need to set up and run your tests by hand on a test-by-test basis. Rai h3. Brief Note About +Test::Unit+ -Ruby ships with a boat load of libraries. One little gem of a library is +Test::Unit+, a framework for unit testing in Ruby. All the basic assertions discussed above are actually defined in +Test::Unit::Assertions+. The class +ActiveSupport::TestCase+ which we have been using in our unit and functional tests extends +Test::Unit::TestCase+ that it is how we can use all the basic assertions in our tests. +Ruby ships with a boat load of libraries. One little gem of a library is +Test::Unit+, a framework for unit testing in Ruby. All the basic assertions discussed above are actually defined in +Test::Unit::Assertions+. The class +ActiveSupport::TestCase+ which we have been using in our unit and functional tests extends +Test::Unit::TestCase+, allowing +us to use all of the basic assertions in our tests. NOTE: For more information on +Test::Unit+, refer to "test/unit Documentation":http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/ -- cgit v1.2.3 From ff09d4bd5b19d478def54648251c78d97027040c Mon Sep 17 00:00:00 2001 From: mhutchin Date: Tue, 29 Mar 2011 01:50:00 -0700 Subject: Minor rephrasing to improve grammar and readability. --- railties/guides/source/layout.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb index f2681c6461..911655e0f4 100644 --- a/railties/guides/source/layout.html.erb +++ b/railties/guides/source/layout.html.erb @@ -111,7 +111,7 @@

Feedback

- You're encouraged to help in keeping the quality of this guide. + You're encouraged to help improve the quality of this guide.

If you see any typos or factual errors you are confident to -- cgit v1.2.3 From e646385993668a3b54c21c7f60b032cd842f3790 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 29 Mar 2011 17:02:29 -0500 Subject: Fix sprockets logger --- railties/lib/rails/engine.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 04676a42dd..82ce4c8cbb 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -463,7 +463,6 @@ module Rails require 'sprockets' env = Sprockets::Environment.new(root.to_s) - # env.logger = Rails.logger env.static_root = root.join("public") self.class.default_sprockets_paths.each do |pattern| @@ -572,6 +571,10 @@ module Rails # consistently executed after all the initializers above across all engines. end + initializer "sprockets.logger" do + assets.logger = Rails.logger + end + rake_tasks do next if self.is_a?(Rails::Application) -- cgit v1.2.3 From 8e4d0b118bbcdfe6b41d15400d092c871c5a1114 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 29 Mar 2011 17:28:46 -0500 Subject: Fix building route set with sprockets in production --- railties/lib/rails/engine.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 82ce4c8cbb..85f7d22fc9 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -433,12 +433,24 @@ module Rails end def routes - @routes ||= ActionDispatch::Routing::RouteSet.new - @routes.add_route(assets, {}, {}, {}, nil, false) if config.use_sprockets + @routes ||= build_route_set @routes.append(&Proc.new) if block_given? @routes end + def build_route_set + routes = ActionDispatch::Routing::RouteSet.new + + engine = self + routes.append do + if engine.config.use_sprockets + routes.add_route(engine.assets, {}, {}, {}, nil, false) + end + end + + routes + end + def self.default_sprockets_paths [ "app/assets", -- cgit v1.2.3 From db3e310d6b327b2b58cfbc0318abd3b4ddca5e30 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 29 Mar 2011 18:05:23 -0500 Subject: Change back to /assets prefix --- railties/lib/rails/engine.rb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 85f7d22fc9..79d48889c9 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -444,7 +444,7 @@ module Rails engine = self routes.append do if engine.config.use_sprockets - routes.add_route(engine.assets, {}, {}, {}, nil, false) + routes.add_route(engine.assets, {:path_info => "/assets"}, {}, {}, nil, false) end end @@ -453,15 +453,12 @@ module Rails def self.default_sprockets_paths [ - "app/assets", - "app/assets/javascripts", - "app/assets/stylesheets", - "vendor/plugins/*/app/assets", - "vendor/plugins/*/app/assets/javascripts", - "vendor/plugins/*/app/assets/stylesheets", - "vendor/plugins/*/assets", - "vendor/plugins/*/assets/javascripts", - "vendor/plugins/*/assets/stylesheets" + "app/javascripts", + "app/stylesheets", + "vendor/plugins/*/app/javascripts", + "vendor/plugins/*/app/stylesheets", + "vendor/plugins/*/javascripts", + "vendor/plugins/*/stylesheets" ] end @@ -475,7 +472,7 @@ module Rails require 'sprockets' env = Sprockets::Environment.new(root.to_s) - env.static_root = root.join("public") + env.static_root = root.join("public/assets") self.class.default_sprockets_paths.each do |pattern| Dir[root.join(pattern)].each do |dir| -- cgit v1.2.3 From 612454e00ee4ff48c4e03f8d8daf92c2a2d3ae3f Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 29 Mar 2011 21:16:44 -0500 Subject: Move sprockets initializers back to application --- railties/lib/rails/application.rb | 27 ++++++++++++++ railties/lib/rails/application/configuration.rb | 5 ++- railties/lib/rails/application/finisher.rb | 8 +++++ railties/lib/rails/engine.rb | 47 +------------------------ railties/lib/rails/engine/configuration.rb | 5 +-- 5 files changed, 41 insertions(+), 51 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 94819820bc..032a505f26 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -137,6 +137,33 @@ module Rails @config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd)) end + def assets + @assets ||= build_asset_environment + end + + def build_asset_environment + return nil if !config.use_sprockets + require 'sprockets' + env = Sprockets::Environment.new(root.to_s) + env.static_root = root.join("public/assets") + env + end + + initializer :add_sprockets_paths do |app| + [ + "app/javascripts", + "app/stylesheets", + "vendor/plugins/*/app/javascripts", + "vendor/plugins/*/app/stylesheets", + "vendor/plugins/*/javascripts", + "vendor/plugins/*/stylesheets" + ].each do |pattern| + Dir[app.root.join(pattern)].each do |dir| + app.assets.paths << dir + end + end + end + protected def default_asset_path diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index c74bcbedf2..8dbc596357 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -9,7 +9,8 @@ module Rails :filter_parameters, :helpers_paths, :logger, :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, - :time_zone, :whiny_nils + :time_zone, :whiny_nils, + :use_sprockets, :compile_assets attr_writer :log_level @@ -28,6 +29,8 @@ module Rails @log_level = nil @middleware = app_middleware @generators = app_generators + @use_sprockets = false + @compile_assets = [] end def compiled_asset_path diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index a45b61c99c..b57af48615 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -33,6 +33,14 @@ module Rails end end + initializer :add_sprockets_route do |app| + if config.use_sprockets + app.routes.append do + mount app.assets => "/assets" + end + end + end + initializer :build_middleware_stack do build_middleware_stack end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 79d48889c9..8adeafaff5 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -433,56 +433,11 @@ module Rails end def routes - @routes ||= build_route_set + @routes ||= ActionDispatch::Routing::RouteSet.new @routes.append(&Proc.new) if block_given? @routes end - def build_route_set - routes = ActionDispatch::Routing::RouteSet.new - - engine = self - routes.append do - if engine.config.use_sprockets - routes.add_route(engine.assets, {:path_info => "/assets"}, {}, {}, nil, false) - end - end - - routes - end - - def self.default_sprockets_paths - [ - "app/javascripts", - "app/stylesheets", - "vendor/plugins/*/app/javascripts", - "vendor/plugins/*/app/stylesheets", - "vendor/plugins/*/javascripts", - "vendor/plugins/*/stylesheets" - ] - end - - def assets - @assets ||= build_asset_environment - end - - def build_asset_environment - return nil if !config.use_sprockets - - require 'sprockets' - - env = Sprockets::Environment.new(root.to_s) - env.static_root = root.join("public/assets") - - self.class.default_sprockets_paths.each do |pattern| - Dir[root.join(pattern)].each do |dir| - env.paths << dir - end - end - - env - end - def initializers initializers = [] railties.all { |r| initializers += r.initializers } diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 1b4a712c75..4f458b0aee 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -5,15 +5,12 @@ module Rails class Configuration < ::Rails::Railtie::Configuration attr_reader :root attr_writer :middleware, :eager_load_paths, :autoload_once_paths, :autoload_paths - attr_accessor :plugins, :asset_path, :use_sprockets, :compile_assets + attr_accessor :plugins, :asset_path def initialize(root=nil) super() @root = root @generators = app_generators.dup - - @use_sprockets = false - @compile_assets = [] end # Returns the middleware stack for the engine. -- cgit v1.2.3 From 651d371a247b0c473fb35a62076e480d95d84a35 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 29 Mar 2011 21:23:05 -0500 Subject: Rename option to config.asset_pipeline --- railties/lib/rails/application.rb | 24 +++++++++++++----------- railties/lib/rails/application/configuration.rb | 4 ++-- railties/lib/rails/application/finisher.rb | 8 +++++++- railties/lib/rails/engine.rb | 4 ---- 4 files changed, 22 insertions(+), 18 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 032a505f26..754b03258a 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -142,7 +142,7 @@ module Rails end def build_asset_environment - return nil if !config.use_sprockets + return unless config.asset_pipeline require 'sprockets' env = Sprockets::Environment.new(root.to_s) env.static_root = root.join("public/assets") @@ -150,16 +150,18 @@ module Rails end initializer :add_sprockets_paths do |app| - [ - "app/javascripts", - "app/stylesheets", - "vendor/plugins/*/app/javascripts", - "vendor/plugins/*/app/stylesheets", - "vendor/plugins/*/javascripts", - "vendor/plugins/*/stylesheets" - ].each do |pattern| - Dir[app.root.join(pattern)].each do |dir| - app.assets.paths << dir + if config.asset_pipeline + [ + "app/javascripts", + "app/stylesheets", + "vendor/plugins/*/app/javascripts", + "vendor/plugins/*/app/stylesheets", + "vendor/plugins/*/javascripts", + "vendor/plugins/*/stylesheets" + ].each do |pattern| + Dir[app.root.join(pattern)].each do |dir| + app.assets.paths << dir + end end end end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 8dbc596357..81127e5e5f 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -10,7 +10,7 @@ module Rails :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, :time_zone, :whiny_nils, - :use_sprockets, :compile_assets + :asset_pipeline, :compile_assets attr_writer :log_level @@ -29,7 +29,7 @@ module Rails @log_level = nil @middleware = app_middleware @generators = app_generators - @use_sprockets = false + @asset_pipeline = false @compile_assets = [] end diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index b57af48615..3cfd8f5707 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -34,13 +34,19 @@ module Rails end initializer :add_sprockets_route do |app| - if config.use_sprockets + if config.asset_pipeline app.routes.append do mount app.assets => "/assets" end end end + initializer :set_sprockets_logger do |app| + if config.asset_pipeline + app.assets.logger = Rails.logger + end + end + initializer :build_middleware_stack do build_middleware_stack end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 8adeafaff5..4fc23fe277 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -535,10 +535,6 @@ module Rails # consistently executed after all the initializers above across all engines. end - initializer "sprockets.logger" do - assets.logger = Rails.logger - end - rake_tasks do next if self.is_a?(Rails::Application) -- cgit v1.2.3 From 25c0b569f5bac0cfdf2c863cabf3b528165cebca Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 29 Mar 2011 22:11:47 -0500 Subject: Precompile configured assets --- railties/lib/rails/application/configuration.rb | 4 ++-- railties/lib/rails/tasks/assets.rake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 81127e5e5f..9e87714e4f 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -10,7 +10,7 @@ module Rails :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, :time_zone, :whiny_nils, - :asset_pipeline, :compile_assets + :asset_pipeline, :precompile_assets attr_writer :log_level @@ -30,7 +30,7 @@ module Rails @middleware = app_middleware @generators = app_generators @asset_pipeline = false - @compile_assets = [] + @precompile_assets = [] end def compiled_asset_path diff --git a/railties/lib/rails/tasks/assets.rake b/railties/lib/rails/tasks/assets.rake index 63e49ad2de..8c85180b34 100644 --- a/railties/lib/rails/tasks/assets.rake +++ b/railties/lib/rails/tasks/assets.rake @@ -1,6 +1,6 @@ namespace :assets do task :compile => :environment do - assets = ENV['assets'].split(',') + assets = Rails.application.config.precompile_assets Rails.application.assets.precompile(*assets) end end -- cgit v1.2.3 From 28fee29e383258c38649e20dc9508188010020c8 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 30 Mar 2011 21:56:15 -0500 Subject: Unify sprockets config options --- railties/lib/rails/application.rb | 24 +++++++++++++----------- railties/lib/rails/application/configuration.rb | 10 +++++++--- railties/lib/rails/application/finisher.rb | 7 ++++--- 3 files changed, 24 insertions(+), 17 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 5b8841fd97..d9c183d93e 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -142,23 +142,25 @@ module Rails end def build_asset_environment - return unless config.asset_pipeline + return unless config.assets.enabled require 'sprockets' env = Sprockets::Environment.new(root.to_s) - env.static_root = root.join("public/assets") + env.static_root = root.join("public/#{config.assets.prefix}") env end initializer :add_sprockets_paths do |app| - if config.asset_pipeline - [ - "app/javascripts", - "app/stylesheets", - "vendor/plugins/*/app/javascripts", - "vendor/plugins/*/app/stylesheets", - "vendor/plugins/*/javascripts", - "vendor/plugins/*/stylesheets" - ].each do |pattern| + if config.assets.enabled + paths = [ + "app/javascripts", + "app/stylesheets", + "vendor/plugins/*/app/javascripts", + "vendor/plugins/*/app/stylesheets", + "vendor/plugins/*/javascripts", + "vendor/plugins/*/stylesheets" + ] + config.assets.paths + + paths.each do |pattern| Dir[app.root.join(pattern)].each do |dir| app.assets.paths << dir end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 4ec5336f6c..4a042e0033 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -10,7 +10,7 @@ module Rails :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, :time_zone, :whiny_nils, :force_ssl, - :asset_pipeline, :precompile_assets + :assets attr_writer :log_level @@ -30,8 +30,12 @@ module Rails @log_level = nil @middleware = app_middleware @generators = app_generators - @asset_pipeline = false - @precompile_assets = [] + + @assets = ActiveSupport::OrderedOptions.new + @assets.enabled = false + @assets.paths = [] + @assets.precompile = [] + @assets.prefix = "/assets" end def compiled_asset_path diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index 3cfd8f5707..be063e5f25 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -34,15 +34,16 @@ module Rails end initializer :add_sprockets_route do |app| - if config.asset_pipeline + assets = config.assets + if assets.enabled app.routes.append do - mount app.assets => "/assets" + mount app.assets => assets.prefix end end end initializer :set_sprockets_logger do |app| - if config.asset_pipeline + if config.assets.enabled app.assets.logger = Rails.logger end end -- cgit v1.2.3 From 203b151af79d3c65e87bc0e695e65a811b35fd49 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 30 Mar 2011 22:00:16 -0500 Subject: Fix config.assets.precompile option --- railties/lib/rails/tasks/assets.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/tasks/assets.rake b/railties/lib/rails/tasks/assets.rake index 8c85180b34..396ce728a1 100644 --- a/railties/lib/rails/tasks/assets.rake +++ b/railties/lib/rails/tasks/assets.rake @@ -1,6 +1,6 @@ namespace :assets do task :compile => :environment do - assets = Rails.application.config.precompile_assets + assets = Rails.application.config.assets.precompile Rails.application.assets.precompile(*assets) end end -- cgit v1.2.3 From bcde6cdf27e96a934466ee16b273846a76c4e335 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 30 Mar 2011 22:12:00 -0500 Subject: Fix assets prefix joining --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index d9c183d93e..ef3cb794c1 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -145,7 +145,7 @@ module Rails return unless config.assets.enabled require 'sprockets' env = Sprockets::Environment.new(root.to_s) - env.static_root = root.join("public/#{config.assets.prefix}") + env.static_root = root.join("public").join(config.assets.prefix) env end -- cgit v1.2.3 From d7b521db1297c1b95a441b3928fc31ab3abd5ed5 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 30 Mar 2011 22:17:43 -0500 Subject: Fix assets prefix joining --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index ef3cb794c1..66a1f88c61 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -145,7 +145,7 @@ module Rails return unless config.assets.enabled require 'sprockets' env = Sprockets::Environment.new(root.to_s) - env.static_root = root.join("public").join(config.assets.prefix) + env.static_root = File.join(root.join("public"), config.assets.prefix) env end -- cgit v1.2.3 From f44d85a030f6e22421b26f0d5a0c869fae3efe5f Mon Sep 17 00:00:00 2001 From: Josiah Ivey Date: Thu, 31 Mar 2011 00:16:45 -0500 Subject: Grammar tweaks to the guides guidelines --- .../source/ruby_on_rails_guides_guidelines.textile | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/ruby_on_rails_guides_guidelines.textile b/railties/guides/source/ruby_on_rails_guides_guidelines.textile index 6576758856..8e55780dca 100644 --- a/railties/guides/source/ruby_on_rails_guides_guidelines.textile +++ b/railties/guides/source/ruby_on_rails_guides_guidelines.textile @@ -10,10 +10,10 @@ Guides are written in "Textile":http://www.textism.com/tools/textile/. There's c h3. Prologue -Each guide should start with motivational text at the top. That's the little introduction in the blue area. The prologue should tell the readers what's the guide about, and what will they learn. See for example the "Routing Guide":routing.html. +Each guide should start with motivational text at the top (that's the little introduction in the blue area.) The prologue should tell the reader what the guide is about, and what they will learn. See for example the "Routing Guide":routing.html. h3. Titles - + The title of every guide uses +h2+, guide sections use +h3+, subsections +h4+, etc. Capitalize all words except for internal articles, prepositions, conjunctions, and forms of the verb to be: @@ -23,7 +23,7 @@ h5. Middleware Stack is an Array h5. When are Objects Saved? -Use same typography as in regular text: +Use the same typography as in regular text: h6. The +:content_type+ Option @@ -42,13 +42,13 @@ Those guidelines apply also to guides. h3. HTML Generation -To generate all the guides just cd into the +railties+ directory and execute +To generate all the guides, just +cd+ into the +railties+ directory and execute: bundle exec rake generate_guides -You'll need the gems erubis, i18n, and RedCloth. +(You may need to run +bundle install+ first to install the required gems.) To process +my_guide.textile+ and nothing else use the +ONLY+ environment variable: @@ -56,13 +56,13 @@ To process +my_guide.textile+ and nothing else use the +ONLY+ environment variab bundle exec rake generate_guides ONLY=my_guide -Although by default guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice. +By default, guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice. To force process of all the guides, pass +ALL=1+. -It is also recommended that you work with +WARNINGS=1+, this detects duplicate IDs and warns about broken internal links. +It is also recommended that you work with +WARNINGS=1+. This detects duplicate IDs and warns about broken internal links. -If you want to generate guides in languages other than English, you can keep them in a separate directory under +source+ (eg. source/es) and use the +LANGUAGE+ environment variable. +If you want to generate guides in languages other than English, you can keep them in a separate directory under +source+ (eg. source/es) and use the +LANGUAGE+ environment variable: rake generate_guides LANGUAGE=es @@ -70,7 +70,7 @@ rake generate_guides LANGUAGE=es h3. HTML Validation -Please do validate the generated HTML with +Please validate the generated HTML with: rake validate_guides @@ -80,4 +80,5 @@ Particularly, titles get an ID generated from their content and this often leads h3. Changelog +* March 31, 2011: grammar tweaks by "Josiah Ivey":http://twitter.com/josiahivey * October 5, 2010: ported from the docrails wiki and revised by "Xavier Noria":credits.html#fxn -- cgit v1.2.3 From 63e4e218c57a1b5f19ba18acaa3c83ff0034a2dc Mon Sep 17 00:00:00 2001 From: burningTyger Date: Fri, 1 Apr 2011 00:12:58 +0200 Subject: fix typo --- railties/guides/source/testing.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile index d937f30609..b42ea15f62 100644 --- a/railties/guides/source/testing.textile +++ b/railties/guides/source/testing.textile @@ -391,7 +391,7 @@ There are a bunch of different types of assertions you can use. Here's the compl |+assert_nil( obj, [msg] )+ |Ensures that +obj.nil?+ is true.| |+assert_not_nil( obj, [msg] )+ |Ensures that +obj.nil?+ is false.| |+assert_match( regexp, string, [msg] )+ |Ensures that a string matches the regular expression.| -|+assert_no_match( regexp, string, [msg] )+ |Ensures that a string doesn't matches the regular expression.| +|+assert_no_match( regexp, string, [msg] )+ |Ensures that a string doesn't match the regular expression.| |+assert_in_delta( expecting, actual, delta, [msg] )+ |Ensures that the numbers +expecting+ and +actual+ are within +delta+ of each other.| |+assert_throws( symbol, [msg] ) { block }+ |Ensures that the given block throws the symbol.| |+assert_raise( exception1, exception2, ... ) { block }+ |Ensures that the given block raises one of the given exceptions.| -- cgit v1.2.3 From bd3cdeea354ebff97b0d5102a0857ce85eedcfa4 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sun, 3 Apr 2011 12:47:51 +0900 Subject: s/ERb/ERB/g The author of ERB sais, his eRuby implementation was originally named "ERb/ERbLight" and then renamed to "ERB" when started bundled as a Ruby standard lib. http://www2a.biglobe.ne.jp/~seki/ruby/erb.html --- railties/lib/rails/source_annotation_extractor.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index 591fd6f6bd..302206bbcd 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -11,7 +11,7 @@ # # Annotations are looked for in comments and modulus whitespace they have to # start with the tag optionally followed by a colon. Everything up to the end -# of the line (or closing ERb comment tag) is considered to be their text. +# of the line (or closing ERB comment tag) is considered to be their text. class SourceAnnotationExtractor class Annotation < Struct.new(:line, :tag, :text) @@ -99,4 +99,4 @@ class SourceAnnotationExtractor puts end end -end \ No newline at end of file +end -- cgit v1.2.3 From 9bf5cddd2835ba4f5d5597f421acf8c9f7385c3b Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sun, 3 Apr 2011 16:59:37 +0900 Subject: s/ERb/ERB/g (part II) --- railties/guides/source/action_view_overview.textile | 2 +- railties/guides/source/api_documentation_guidelines.textile | 2 +- railties/guides/source/command_line.textile | 2 +- railties/guides/source/testing.textile | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile index cfd71ad287..d0b3ee6bfc 100644 --- a/railties/guides/source/action_view_overview.textile +++ b/railties/guides/source/action_view_overview.textile @@ -1295,7 +1295,7 @@ end h5. update_page_tag -Works like update_page but wraps the generated JavaScript in a +script+ tag. Use this to include generated JavaScript in an ERb template. +Works like update_page but wraps the generated JavaScript in a +script+ tag. Use this to include generated JavaScript in an ERB template. h4. PrototypeHelper::JavaScriptGenerator::GeneratorMethods diff --git a/railties/guides/source/api_documentation_guidelines.textile b/railties/guides/source/api_documentation_guidelines.textile index 7433507866..e22ffa4c04 100644 --- a/railties/guides/source/api_documentation_guidelines.textile +++ b/railties/guides/source/api_documentation_guidelines.textile @@ -29,7 +29,7 @@ Documentation has to be concise but comprehensive. Explore and document edge cas The proper names of Rails components have a space in between the words, like "Active Support". +ActiveRecord+ is a Ruby module, whereas Active Record is an ORM. All Rails documentation should consistently refer to Rails components by their proper name, and if in your next blog post or presentation you remember this tidbit and take it into account that'd be phenomenal. -Spell names correctly: Arel, Test::Unit, RSpec, HTML, MySQL, JavaScript, ERb. When in doubt, please have a look at some authoritative source like their official documentation. +Spell names correctly: Arel, Test::Unit, RSpec, HTML, MySQL, JavaScript, ERB. When in doubt, please have a look at some authoritative source like their official documentation. Use the article "an" for "SQL", as in "an SQL statement". Also "an SQLite database". diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile index 581fece1ab..f3e8d880df 100644 --- a/railties/guides/source/command_line.textile +++ b/railties/guides/source/command_line.textile @@ -484,7 +484,7 @@ end We take whatever args are supplied, save them to an instance variable, and literally copying from the Rails source, implement a +manifest+ method, which calls +record+ with a block, and we: * Check there's a *public* directory. You bet there is. -* Run the ERb template called "tutorial.erb". +* Run the ERB template called "tutorial.erb". * Save it into "Rails.root/public/tutorial.txt". * Pass in the arguments we saved through the +:assigns+ parameter. diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile index b42ea15f62..2809c6d076 100644 --- a/railties/guides/source/testing.textile +++ b/railties/guides/source/testing.textile @@ -79,9 +79,9 @@ steve: Each fixture is given a name followed by an indented list of colon-separated key/value pairs. Records are separated by a blank space. You can place comments in a fixture file by using the # character in the first column. -h5. ERb'in It Up +h5. ERB'in It Up -ERb allows you to embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERb when you load fixtures. This allows you to use Ruby to help you generate some sample data. +ERB allows you to embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERB when you load fixtures. This allows you to use Ruby to help you generate some sample data. <% earth_size = 20 %> -- cgit v1.2.3 From 4c323bc25a69ba8fd8b080775335184fe6868747 Mon Sep 17 00:00:00 2001 From: orta Date: Mon, 14 Mar 2011 12:37:43 +0000 Subject: added .'s to headings in the initialization textile page --- railties/guides/source/initialization.textile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile index 0cbbe1f389..7c01f01b24 100644 --- a/railties/guides/source/initialization.textile +++ b/railties/guides/source/initialization.textile @@ -478,8 +478,7 @@ The next line in +config/application.rb+ is: require 'rails/all' -h4 +railties/lib/rails/all.rb+ - +h4. +railties/lib/rails/all.rb+ This file is responsible for requiring all the individual parts of Rails like so: @@ -591,7 +590,7 @@ h4. +activesupport/lib/active_support/deprecation/behaviors.rb+ This file defines the behavior of the +ActiveSupport::Deprecation+ module, setting up the +DEFAULT_BEHAVIORS+ hash constant which contains the three defaults to outputting deprecation warnings: +:stderr+, +:log+ and +:notify+. This file begins by requiring +activesupport/notifications+ and +activesupport/core_ext/array/wrap+. -h4 +activesupport/lib/active_support/notifications.rb+ +h4. +activesupport/lib/active_support/notifications.rb+ TODO: document +ActiveSupport::Notifications+. -- cgit v1.2.3 From 284ca810c17a89d15d809ba203289487044fcff9 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Sat, 2 Apr 2011 10:51:47 +0200 Subject: remove AM delegating register_observer and register_interceptor to Mail and instead implement smarter versions allowing for string class names, also added proper Railtie support with tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/test/application/configuration_test.rb | 65 +++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'railties') diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 044fd2a278..ce530b4b77 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -1,5 +1,18 @@ require "isolation/abstract_unit" +class ::MyMailInterceptor + def self.delivering_email(email); email; end +end + +class ::MyOtherMailInterceptor < ::MyMailInterceptor; end + +class ::MyMailObserver + def self.delivered_email(email); email; end +end + +class ::MyOtherMailObserver < ::MyMailObserver; end + + module ApplicationTests class ConfigurationTest < Test::Unit::TestCase include ActiveSupport::Testing::Isolation @@ -245,6 +258,58 @@ module ApplicationTests assert_equal res, last_response.body # value should be unchanged end + test "registers interceptors with ActionMailer" do + add_to_config <<-RUBY + config.action_mailer.interceptors = MyMailInterceptor + RUBY + + require "#{app_path}/config/environment" + require "mail" + + ActionMailer::Base + + assert_equal [::MyMailInterceptor], ::Mail.send(:class_variable_get, "@@delivery_interceptors") + end + + test "registers multiple interceptors with ActionMailer" do + add_to_config <<-RUBY + config.action_mailer.interceptors = [MyMailInterceptor, "MyOtherMailInterceptor"] + RUBY + + require "#{app_path}/config/environment" + require "mail" + + ActionMailer::Base + + assert_equal [::MyMailInterceptor, ::MyOtherMailInterceptor], ::Mail.send(:class_variable_get, "@@delivery_interceptors") + end + + test "registers observers with ActionMailer" do + add_to_config <<-RUBY + config.action_mailer.observers = MyMailObserver + RUBY + + require "#{app_path}/config/environment" + require "mail" + + ActionMailer::Base + + assert_equal [::MyMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers") + end + + test "registers multiple observers with ActionMailer" do + add_to_config <<-RUBY + config.action_mailer.observers = [MyMailObserver, "MyOtherMailObserver"] + RUBY + + require "#{app_path}/config/environment" + require "mail" + + ActionMailer::Base + + assert_equal [::MyMailObserver, ::MyOtherMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers") + end + test "config.action_controller.perform_caching = false" do make_basic_app do |app| app.config.action_controller.perform_caching = false -- cgit v1.2.3 From e9020b4b5dbd4a19e288c613a86c78e32010c361 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Tue, 5 Apr 2011 00:33:29 +0200 Subject: added find_zone and find_zone! to AS timezones and changed the AS Railtie to use find_zone! as well as adding Railtie tests Signed-off-by: Santiago Pastorino --- railties/test/application/configuration_test.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'railties') diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index ce530b4b77..62697b1bf9 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -310,6 +310,28 @@ module ApplicationTests assert_equal [::MyMailObserver, ::MyOtherMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers") end + test "valid timezone is setup correctly" do + add_to_config <<-RUBY + config.root = "#{app_path}" + config.time_zone = "Wellington" + RUBY + + require "#{app_path}/config/environment" + + assert_equal "Wellington", Rails.application.config.time_zone + end + + test "raises when an invalid timezone is defined in the config" do + add_to_config <<-RUBY + config.root = "#{app_path}" + config.time_zone = "That big hill over yonder hill" + RUBY + + assert_raise(ArgumentError) do + require "#{app_path}/config/environment" + end + end + test "config.action_controller.perform_caching = false" do make_basic_app do |app| app.config.action_controller.perform_caching = false -- cgit v1.2.3 From e836fc1bd2f3df0b8b0a2ef5deb182bcf1f0f3c2 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Wed, 6 Apr 2011 15:14:47 +0530 Subject: fix example query --- railties/guides/source/active_record_querying.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index f3a10b8b92..df8e35ed33 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -790,7 +790,7 @@ Post.includes(:comments).where("comments.visible", true) This would generate a query which contains a +LEFT OUTER JOIN+ whereas the +joins+ method would generate one using the +INNER JOIN+ function instead. - SELECT "posts"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE (comments.visible) + SELECT "posts"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE (comments.visible = 1) If there was no +where+ condition, this would generate the normal set of two queries. -- cgit v1.2.3 From bd79172e430ffd8c60154d5d98a2d5ea0c93743b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 8 Apr 2011 09:40:33 -0700 Subject: make turn a soft dependency. generate a Gemfile that contains turn and require turn if it is available --- railties/lib/rails/generators/rails/app/templates/Gemfile | 10 +++++++--- railties/lib/rails/test_help.rb | 10 +++++++--- railties/railties.gemspec | 1 - 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index c383d4842f..61daefef90 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -23,9 +23,13 @@ source 'http://rubygems.org' # Bundle gems for the local environment. Make sure to # put test-only gems in this group so their generators # and rake tasks are available in development mode: -# group :development, :test do -# gem 'webrat' -# end + +group :development, :test do + # Depend "turn" for pretty printing test output, but disable autorequire. + gem 'turn', :require => false + + # gem 'webrat' +end # Needed for guides generation # gem "RedCloth", "~> 4.2" diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index b9f7bdc2eb..41485c8bac 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -14,10 +14,14 @@ if defined?(Test::Unit::Util::BacktraceFilter) && ENV['BACKTRACE'].nil? end if defined?(MiniTest) - require 'turn' + # Enable turn if it is available + begin + require 'turn' - if MiniTest::Unit.respond_to?(:use_natural_language_case_names=) - MiniTest::Unit.use_natural_language_case_names = true + if MiniTest::Unit.respond_to?(:use_natural_language_case_names=) + MiniTest::Unit.use_natural_language_case_names = true + end + rescue LoadError end end diff --git a/railties/railties.gemspec b/railties/railties.gemspec index b1eda71c7f..cd0646b8ed 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -21,7 +21,6 @@ Gem::Specification.new do |s| s.add_dependency('rake', '>= 0.8.7') s.add_dependency('thor', '~> 0.14.4') s.add_dependency('rack-ssl', '~> 1.3.2') - s.add_dependency('turn', '~> 0.8.2') s.add_dependency('activesupport', version) s.add_dependency('actionpack', version) end -- cgit v1.2.3 From c0efc4009adb870ee23e93d46ac374f772d8cb4f Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sun, 10 Apr 2011 00:54:43 +0800 Subject: Make scaffold_controller generator generate code for JSON response instead of XML It seems like a lot of people are using JSON in their API more than XML nowadays, so Rails should follow that convention by providing the JSON format block in scaffold_controller by default. This patch has been requested by DHH --- railties/CHANGELOG | 2 ++ .../scaffold_controller/templates/controller.rb | 28 +++++++++++----------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'railties') diff --git a/railties/CHANGELOG b/railties/CHANGELOG index f159247308..7f1be02cd2 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.1.0 (unreleased)* +* Changed scaffold_controller generator to create format block for JSON instead of XML [Prem Sichanugrist] + * Add using Turn with natural language test case names for test_help.rb when running with minitest (Ruby 1.9.2+) [DHH] * Direct logging of Active Record to STDOUT so it's shown inline with the results in the console [DHH] diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index b5317a055b..5fb8895654 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -1,35 +1,35 @@ <% module_namespacing do -%> class <%= controller_class_name %>Controller < ApplicationController # GET <%= route_url %> - # GET <%= route_url %>.xml + # GET <%= route_url %>.json def index @<%= plural_table_name %> = <%= orm_class.all(class_name) %> respond_to do |format| format.html # index.html.erb - format.xml { render :xml => @<%= plural_table_name %> } + format.json { render :json => @<%= plural_table_name %> } end end # GET <%= route_url %>/1 - # GET <%= route_url %>/1.xml + # GET <%= route_url %>/1.json def show @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> respond_to do |format| format.html # show.html.erb - format.xml { render :xml => @<%= singular_table_name %> } + format.json { render :json => @<%= singular_table_name %> } end end # GET <%= route_url %>/new - # GET <%= route_url %>/new.xml + # GET <%= route_url %>/new.json def new @<%= singular_table_name %> = <%= orm_class.build(class_name) %> respond_to do |format| format.html # new.html.erb - format.xml { render :xml => @<%= singular_table_name %> } + format.json { render :json => @<%= singular_table_name %> } end end @@ -39,46 +39,46 @@ class <%= controller_class_name %>Controller < ApplicationController end # POST <%= route_url %> - # POST <%= route_url %>.xml + # POST <%= route_url %>.json def create @<%= singular_table_name %> = <%= orm_class.build(class_name, "params[:#{singular_table_name}]") %> respond_to do |format| if @<%= orm_instance.save %> format.html { redirect_to(@<%= singular_table_name %>, :notice => '<%= human_name %> was successfully created.') } - format.xml { render :xml => @<%= singular_table_name %>, :status => :created, :location => @<%= singular_table_name %> } + format.json { render :json => @<%= singular_table_name %>, :status => :created, :location => @<%= singular_table_name %> } else format.html { render :action => "new" } - format.xml { render :xml => @<%= orm_instance.errors %>, :status => :unprocessable_entity } + format.json { render :json => @<%= orm_instance.errors %>, :status => :unprocessable_entity } end end end # PUT <%= route_url %>/1 - # PUT <%= route_url %>/1.xml + # PUT <%= route_url %>/1.json def update @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> respond_to do |format| if @<%= orm_instance.update_attributes("params[:#{singular_table_name}]") %> format.html { redirect_to(@<%= singular_table_name %>, :notice => '<%= human_name %> was successfully updated.') } - format.xml { head :ok } + format.json { render :json => {}, :status => :ok } else format.html { render :action => "edit" } - format.xml { render :xml => @<%= orm_instance.errors %>, :status => :unprocessable_entity } + format.json { render :json => @<%= orm_instance.errors %>, :status => :unprocessable_entity } end end end # DELETE <%= route_url %>/1 - # DELETE <%= route_url %>/1.xml + # DELETE <%= route_url %>/1.json def destroy @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %> @<%= orm_instance.destroy %> respond_to do |format| format.html { redirect_to(<%= index_helper %>_url) } - format.xml { head :ok } + format.json { render :json => {}, :status => :ok } end end end -- cgit v1.2.3 From 63cd92f9f346acefca1ad014873c971837843cdb Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sun, 10 Apr 2011 12:27:26 +0800 Subject: Rails will now generate Ruby 1.9 style hash when running scaffold_controller generator on Ruby 1.9.x The new hash syntax of Ruby 1.9 looks more superior, so we decide to switch to it in the places that appropriate. This patch has been requested by DHH. --- railties/CHANGELOG | 10 +++++++++ .../erb/scaffold/templates/index.html.erb | 2 +- railties/lib/rails/generators/named_base.rb | 10 +++++++++ .../scaffold_controller/templates/controller.rb | 26 +++++++++++----------- .../scaffold/templates/functional_test.rb | 10 ++++----- .../scaffold_controller_generator_test.rb | 11 +++++++++ 6 files changed, 50 insertions(+), 19 deletions(-) (limited to 'railties') diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 7f1be02cd2..b5050440bb 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,15 @@ *Rails 3.1.0 (unreleased)* +* Changed scaffold generator to create Ruby 1.9 style hash when running on Ruby 1.9 [Prem Sichanugrist] + + So instead of creating something like: + + redirect_to users_path, :notice => "User has been created" + + it will now be like this: + + redirect_to users_path, notice: "User has been created" + * Changed scaffold_controller generator to create format block for JSON instead of XML [Prem Sichanugrist] * Add using Turn with natural language test case names for test_help.rb when running with minitest (Ruby 1.9.2+) [DHH] diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb index 4c46db4d67..a7393cfe18 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb @@ -17,7 +17,7 @@ <% end -%> <%%= link_to 'Show', <%= singular_table_name %> %> <%%= link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>) %> - <%%= link_to 'Destroy', <%= singular_table_name %>, :confirm => 'Are you sure?', :method => :delete %> + <%%= link_to 'Destroy', <%= singular_table_name %>, <%= key_value :confirm, "'Are you sure?'" %>, <%= key_value :method, ":delete" %> %> <%% end %> diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 2af7f85463..3d19b372ff 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -181,6 +181,16 @@ module Rails class_collisions "#{options[:prefix]}#{name}#{options[:suffix]}" end end + + # Returns Ruby 1.9 style key-value pair if current code is running on + # Ruby 1.9.x. Returns the old-style (with hash rocket) otherwise. + def key_value(key, value) + if RUBY_VERSION < '1.9' + ":#{key} => #{value}" + else + "#{key}: #{value}" + end + end end end end diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index 5fb8895654..a8a1c07d1f 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -7,7 +7,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| format.html # index.html.erb - format.json { render :json => @<%= plural_table_name %> } + format.json { render <%= key_value :json, "@#{plural_table_name}" %> } end end @@ -18,7 +18,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| format.html # show.html.erb - format.json { render :json => @<%= singular_table_name %> } + format.json { render <%= key_value :json, "@#{singular_table_name}" %> } end end @@ -29,7 +29,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| format.html # new.html.erb - format.json { render :json => @<%= singular_table_name %> } + format.json { render <%= key_value :json, "@#{singular_table_name}" %> } end end @@ -45,11 +45,11 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| if @<%= orm_instance.save %> - format.html { redirect_to(@<%= singular_table_name %>, :notice => '<%= human_name %> was successfully created.') } - format.json { render :json => @<%= singular_table_name %>, :status => :created, :location => @<%= singular_table_name %> } + format.html { redirect_to @<%= singular_table_name %>, <%= key_value :notice, "'#{human_name} was successfully created.'" %> } + format.json { render <%= key_value :json, "@#{singular_table_name}" %>, <%= key_value :status, ':created' %>, <%= key_value :location, "@#{singular_table_name}" %> } else - format.html { render :action => "new" } - format.json { render :json => @<%= orm_instance.errors %>, :status => :unprocessable_entity } + format.html { render <%= key_value :action, '"new"' %> } + format.json { render <%= key_value :json, "@#{orm_instance.errors}" %>, <%= key_value :status, ':unprocessable_entity' %> } end end end @@ -61,11 +61,11 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| if @<%= orm_instance.update_attributes("params[:#{singular_table_name}]") %> - format.html { redirect_to(@<%= singular_table_name %>, :notice => '<%= human_name %> was successfully updated.') } - format.json { render :json => {}, :status => :ok } + format.html { redirect_to @<%= singular_table_name %>, <%= key_value :notice, "'#{human_name} was successfully updated.'" %> } + format.json { render <%= key_value :json, '{}' %>, <%= key_value :status, ':ok' %> } else - format.html { render :action => "edit" } - format.json { render :json => @<%= orm_instance.errors %>, :status => :unprocessable_entity } + format.html { render <%= key_value :action, '"edit"' %> } + format.json { render <%= key_value :json, "@#{orm_instance.errors}" %>, <%= key_value :status, ':unprocessable_entity' %> } end end end @@ -77,8 +77,8 @@ class <%= controller_class_name %>Controller < ApplicationController @<%= orm_instance.destroy %> respond_to do |format| - format.html { redirect_to(<%= index_helper %>_url) } - format.json { render :json => {}, :status => :ok } + format.html { redirect_to <%= index_helper %>_url } + format.json { render <%= key_value :json, '{}' %>, <%= key_value :status, ':ok' %> } end end end diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb index 964d59d84c..01fe6dda7a 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb +++ b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb @@ -19,30 +19,30 @@ class <%= controller_class_name %>ControllerTest < ActionController::TestCase test "should create <%= singular_table_name %>" do assert_difference('<%= class_name %>.count') do - post :create, :<%= singular_table_name %> => @<%= singular_table_name %>.attributes + post :create, <%= key_value singular_table_name, "@#{singular_table_name}.attributes" %> end assert_redirected_to <%= singular_table_name %>_path(assigns(:<%= singular_table_name %>)) end test "should show <%= singular_table_name %>" do - get :show, :id => @<%= singular_table_name %>.to_param + get :show, <%= key_value :id, "@#{singular_table_name}.to_param" %> assert_response :success end test "should get edit" do - get :edit, :id => @<%= singular_table_name %>.to_param + get :edit, <%= key_value :id, "@#{singular_table_name}.to_param" %> assert_response :success end test "should update <%= singular_table_name %>" do - put :update, :id => @<%= singular_table_name %>.to_param, :<%= singular_table_name %> => @<%= singular_table_name %>.attributes + put :update, <%= key_value :id, "@#{singular_table_name}.to_param" %>, <%= key_value singular_table_name, "@#{singular_table_name}.attributes" %> assert_redirected_to <%= singular_table_name %>_path(assigns(:<%= singular_table_name %>)) end test "should destroy <%= singular_table_name %>" do assert_difference('<%= class_name %>.count', -1) do - delete :destroy, :id => @<%= singular_table_name %>.to_param + delete :destroy, <%= key_value :id, "@#{singular_table_name}.to_param" %> end assert_redirected_to <%= index_helper %>_path diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb index d55ed22975..ff82cdb744 100644 --- a/railties/test/generators/scaffold_controller_generator_test.rb +++ b/railties/test/generators/scaffold_controller_generator_test.rb @@ -122,4 +122,15 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase ensure Unknown::Generators.send :remove_const, :ActiveModel end + + def test_new_hash_style + run_generator + assert_file "app/controllers/users_controller.rb" do |content| + if RUBY_VERSION < "1.9" + assert_match /\{ render :action => "new" \}/, content + else + assert_match /\{ render action: "new" \}/, content + end + end + end end -- cgit v1.2.3 From 74960c3976a69b3c7d9aa6bf28edb42ea82df0ce Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sun, 10 Apr 2011 12:30:58 +0800 Subject: Rails will now generate Ruby 1.9 style hash when running app generator on Ruby 1.9.x The new hash syntax of Ruby 1.9 looks more superior, so we decide to switch to it in the places that appropriate. --- railties/CHANGELOG | 2 +- railties/lib/rails/generators/app_base.rb | 9 +++++++++ .../app/templates/config/initializers/session_store.rb.tt | 2 +- railties/lib/rails/generators/rails/app/templates/db/seeds.rb | 4 ++-- railties/test/generators/app_generator_test.rb | 10 ++++++++++ 5 files changed, 23 insertions(+), 4 deletions(-) (limited to 'railties') diff --git a/railties/CHANGELOG b/railties/CHANGELOG index b5050440bb..e81d20c3ac 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,6 +1,6 @@ *Rails 3.1.0 (unreleased)* -* Changed scaffold generator to create Ruby 1.9 style hash when running on Ruby 1.9 [Prem Sichanugrist] +* Changed scaffold and app generator to create Ruby 1.9 style hash when running on Ruby 1.9 [Prem Sichanugrist] So instead of creating something like: diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index a2eaf7a6fb..47dc6ce103 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -174,6 +174,15 @@ module Rails create_file("#{destination}/.gitkeep") unless options[:skip_git] end + # Returns Ruby 1.9 style key-value pair if current code is running on + # Ruby 1.9.x. Returns the old-style (with hash rocket) otherwise. + def key_value(key, value) + if RUBY_VERSION < '1.9' + ":#{key} => #{value}" + else + "#{key}: #{value}" + end + end end end end diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt index 62aa06dc3e..ddfe4ba1e1 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt @@ -1,6 +1,6 @@ # Be sure to restart your server when you modify this file. -<%= app_const %>.config.session_store :cookie_store, :key => '_<%= app_name %>_session' +<%= app_const %>.config.session_store :cookie_store, <%= key_value :key, "'_#{app_name}_session'" %> # Use the database for sessions instead of the cookie-based default, # which shouldn't be used to store highly confidential information diff --git a/railties/lib/rails/generators/rails/app/templates/db/seeds.rb b/railties/lib/rails/generators/rails/app/templates/db/seeds.rb index 664d8c74c8..9a2efa68a7 100644 --- a/railties/lib/rails/generators/rails/app/templates/db/seeds.rb +++ b/railties/lib/rails/generators/rails/app/templates/db/seeds.rb @@ -3,5 +3,5 @@ # # Examples: # -# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) -# Mayor.create(:name => 'Daley', :city => cities.first) +# cities = City.create([{ <%= key_value :name, "'Chicago'" %> }, { <%= key_value :name, "'Copenhagen'" %> }]) +# Mayor.create(<%= key_value :name, "'Daley'" %>, <%= key_value :city, "cities.first" %>) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 018c2fa6bf..e440885adf 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -216,6 +216,16 @@ class AppGeneratorTest < Rails::Generators::TestCase end end + def test_new_hash_style + run_generator [destination_root] + assert_file "config/initializers/session_store.rb" do |file| + if RUBY_VERSION < "1.9" + assert_match /config.session_store :cookie_store, :key => '_.+_session'/, file + else + assert_match /config.session_store :cookie_store, key: '_.+_session'/, file + end + end + end protected def action(*args, &block) -- cgit v1.2.3 From 22a3416298523d5e8ecb432a263e4bee9441e6c5 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sun, 10 Apr 2011 12:38:59 +0800 Subject: Add --old-style-hash option to force creating old style hash on Ruby 1.9 That means if you don't like the new syntax, you can pass --old-style-hash to force Rails to generate code with hash rockets. --- railties/CHANGELOG | 2 ++ railties/lib/rails/generators/app_base.rb | 5 ++++- railties/lib/rails/generators/named_base.rb | 5 ++++- railties/test/generators/app_generator_test.rb | 8 ++++++++ railties/test/generators/scaffold_controller_generator_test.rb | 7 +++++++ 5 files changed, 25 insertions(+), 2 deletions(-) (limited to 'railties') diff --git a/railties/CHANGELOG b/railties/CHANGELOG index e81d20c3ac..90faad6131 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -10,6 +10,8 @@ redirect_to users_path, notice: "User has been created" + You can also passing `--old-style-hash` to make Rails generate old style hash even you're on Ruby 1.9 + * Changed scaffold_controller generator to create format block for JSON instead of XML [Prem Sichanugrist] * Add using Turn with natural language test case names for test_help.rb when running with minitest (Ruby 1.9.2+) [DHH] diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 47dc6ce103..93db5106ce 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -53,6 +53,9 @@ module Rails class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, :desc => "Show this help message and quit" + + class_option :old_style_hash, :type => :boolean, :default => false, + :desc => "Force using old style hash (:foo => 'bar') on Ruby >= 1.9" end def initialize(*args) @@ -177,7 +180,7 @@ module Rails # Returns Ruby 1.9 style key-value pair if current code is running on # Ruby 1.9.x. Returns the old-style (with hash rocket) otherwise. def key_value(key, value) - if RUBY_VERSION < '1.9' + if options[:old_style_hash] || RUBY_VERSION < '1.9' ":#{key} => #{value}" else "#{key}: #{value}" diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 3d19b372ff..36bc9e055c 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -8,6 +8,9 @@ module Rails class_option :skip_namespace, :type => :boolean, :default => false, :desc => "Skip namespace (affects only isolated applications)" + class_option :old_style_hash, :type => :boolean, :default => false, + :desc => "Force using old style hash (:foo => 'bar') on Ruby >= 1.9" + def initialize(args, *options) #:nodoc: # Unfreeze name in case it's given as a frozen string args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen? @@ -185,7 +188,7 @@ module Rails # Returns Ruby 1.9 style key-value pair if current code is running on # Ruby 1.9.x. Returns the old-style (with hash rocket) otherwise. def key_value(key, value) - if RUBY_VERSION < '1.9' + if options[:old_style_hash] || RUBY_VERSION < '1.9' ":#{key} => #{value}" else "#{key}: #{value}" diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index e440885adf..43f2fbd71c 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -226,6 +226,14 @@ class AppGeneratorTest < Rails::Generators::TestCase end end end + + def test_force_old_style_hash + run_generator [destination_root, "--old-style-hash"] + assert_file "config/initializers/session_store.rb" do |file| + assert_match /config.session_store :cookie_store, :key => '_.+_session'/, file + end + end + protected def action(*args, &block) diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb index ff82cdb744..c7f45a807d 100644 --- a/railties/test/generators/scaffold_controller_generator_test.rb +++ b/railties/test/generators/scaffold_controller_generator_test.rb @@ -133,4 +133,11 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase end end end + + def test_force_old_style_hash + run_generator ["User", "--old-style-hash"] + assert_file "app/controllers/users_controller.rb" do |content| + assert_match /\{ render :action => "new" \}/, content + end + end end -- cgit v1.2.3 From a9f3c9da01d721963d05949604ead909aaabbf36 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Mon, 11 Apr 2011 00:52:42 +0800 Subject: Using Object#in? and Object#either? in various places There're a lot of places in Rails source code which make a lot of sense to switching to Object#in? or Object#either? instead of using [].include?. --- railties/guides/rails_guides/textile_extensions.rb | 6 ++++-- railties/lib/rails/commands.rb | 4 +++- railties/lib/rails/commands/application.rb | 4 +++- railties/lib/rails/commands/benchmarker.rb | 4 +++- railties/lib/rails/commands/destroy.rb | 4 +++- railties/lib/rails/commands/generate.rb | 4 +++- railties/lib/rails/commands/profiler.rb | 4 +++- railties/lib/rails/generators/base.rb | 3 ++- railties/lib/rails/generators/generated_attribute.rb | 3 ++- 9 files changed, 26 insertions(+), 10 deletions(-) (limited to 'railties') diff --git a/railties/guides/rails_guides/textile_extensions.rb b/railties/guides/rails_guides/textile_extensions.rb index affef1ccb0..f1486a7c10 100644 --- a/railties/guides/rails_guides/textile_extensions.rb +++ b/railties/guides/rails_guides/textile_extensions.rb @@ -1,9 +1,11 @@ +require 'active_support/core_ext/object/inclusion' + module RailsGuides module TextileExtensions def notestuff(body) body.gsub!(/^(IMPORTANT|CAUTION|WARNING|NOTE|INFO)[.:](.*)$/) do |m| css_class = $1.downcase - css_class = 'warning' if ['caution', 'important'].include?(css_class) + css_class = 'warning' if css_class.either?('caution', 'important') result = "

" result << $2.strip @@ -33,7 +35,7 @@ module RailsGuides def code(body) body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)}m) do |m| es = ERB::Util.h($2) - css_class = ['erb', 'shell'].include?($1) ? 'html' : $1 + css_class = $1.either?('erb', 'shell') ? 'html' : $1 %{

#{es}
} end end diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 02ccdf8060..28dff23890 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/inclusion' + ARGV << '--help' if ARGV.empty? aliases = { @@ -69,7 +71,7 @@ when '--version', '-v' require 'rails/commands/application' else - puts "Error: Command not recognized" unless %w(-h --help).include?(command) + puts "Error: Command not recognized" unless command.either?('-h', '--help') puts <<-EOT Usage: rails COMMAND [ARGS] diff --git a/railties/lib/rails/commands/application.rb b/railties/lib/rails/commands/application.rb index 3b57b925ba..20eb8b485e 100644 --- a/railties/lib/rails/commands/application.rb +++ b/railties/lib/rails/commands/application.rb @@ -1,5 +1,7 @@ require 'rails/version' -if %w(--version -v).include? ARGV.first +require 'active_support/core_ext/object/inclusion' + +if ARGV.first.either?('--version', '-v') puts "Rails #{Rails::VERSION::STRING}" exit(0) end diff --git a/railties/lib/rails/commands/benchmarker.rb b/railties/lib/rails/commands/benchmarker.rb index 0432261802..ecdcccfd8d 100644 --- a/railties/lib/rails/commands/benchmarker.rb +++ b/railties/lib/rails/commands/benchmarker.rb @@ -1,4 +1,6 @@ -if [nil, "-h", "--help"].include?(ARGV.first) +require 'active_support/core_ext/object/inclusion' + +if ARGV.first.either?(nil, "-h", "--help") puts "Usage: rails benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ..." exit 1 end diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb index db59cd8ad9..829d29dad7 100644 --- a/railties/lib/rails/commands/destroy.rb +++ b/railties/lib/rails/commands/destroy.rb @@ -1,7 +1,9 @@ require 'rails/generators' +require 'active_support/core_ext/object/inclusion' + Rails::Generators.configure! -if [nil, "-h", "--help"].include?(ARGV.first) +if ARGV.first.either?(nil, "-h", "--help") Rails::Generators.help 'destroy' exit end diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb index 1b3eef504a..bef4c6df14 100644 --- a/railties/lib/rails/commands/generate.rb +++ b/railties/lib/rails/commands/generate.rb @@ -1,7 +1,9 @@ require 'rails/generators' +require 'active_support/core_ext/object/inclusion' + Rails::Generators.configure! -if [nil, "-h", "--help"].include?(ARGV.first) +if ARGV.first.either?(nil, "-h", "--help") Rails::Generators.help 'generate' exit end diff --git a/railties/lib/rails/commands/profiler.rb b/railties/lib/rails/commands/profiler.rb index 6d9717b5cd..baa3baaec0 100644 --- a/railties/lib/rails/commands/profiler.rb +++ b/railties/lib/rails/commands/profiler.rb @@ -1,4 +1,6 @@ -if [nil, "-h", "--help"].include?(ARGV.first) +require 'active_support/core_ext/object/inclusion' + +if ARGV.first.either?(nil, "-h", "--help") $stderr.puts "Usage: rails profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]" exit(1) end diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index dfecd2a6e4..e2c19340f4 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -8,6 +8,7 @@ rescue LoadError end require 'rails/generators/actions' +require 'active_support/core_ext/object/inclusion' module Rails module Generators @@ -164,7 +165,7 @@ module Rails names.each do |name| defaults = if options[:type] == :boolean { } - elsif [true, false].include?(default_value_for_option(name, options)) + elsif default_value_for_option(name, options).either?(true, false) { :banner => "" } else { :desc => "#{name.to_s.humanize} to be invoked", :banner => "NAME" } diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb index 64273e4ca4..8ed3b18872 100644 --- a/railties/lib/rails/generators/generated_attribute.rb +++ b/railties/lib/rails/generators/generated_attribute.rb @@ -1,4 +1,5 @@ require 'active_support/time' +require 'active_support/core_ext/object/inclusion' module Rails module Generators @@ -44,7 +45,7 @@ module Rails end def reference? - [ :references, :belongs_to ].include?(self.type) + self.type.either?(:references, :belongs_to) end end end -- cgit v1.2.3 From 1d8bf4f4f900a905e6350e246a683659b5480ec9 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 11 Apr 2011 15:25:39 +0200 Subject: Cant use inclusion in commands/application.rb as the frameworks havent all been required yet --- railties/lib/rails/commands/application.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/commands/application.rb b/railties/lib/rails/commands/application.rb index 20eb8b485e..f3fa1fd54d 100644 --- a/railties/lib/rails/commands/application.rb +++ b/railties/lib/rails/commands/application.rb @@ -1,7 +1,6 @@ require 'rails/version' -require 'active_support/core_ext/object/inclusion' -if ARGV.first.either?('--version', '-v') +if ['--version', '-v'].include?(ARGV.first) puts "Rails #{Rails::VERSION::STRING}" exit(0) end -- cgit v1.2.3 From b93199b547303a1656282a2591db84de0b6d2a9f Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 11 Apr 2011 15:50:05 +0200 Subject: Keep the same API semantics for update/delete as we had for XML (just return 200 OK, no body) --- .../generators/rails/scaffold_controller/templates/controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index a8a1c07d1f..32b961d9fc 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -62,7 +62,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| if @<%= orm_instance.update_attributes("params[:#{singular_table_name}]") %> format.html { redirect_to @<%= singular_table_name %>, <%= key_value :notice, "'#{human_name} was successfully updated.'" %> } - format.json { render <%= key_value :json, '{}' %>, <%= key_value :status, ':ok' %> } + format.json { head :ok } else format.html { render <%= key_value :action, '"edit"' %> } format.json { render <%= key_value :json, "@#{orm_instance.errors}" %>, <%= key_value :status, ':unprocessable_entity' %> } @@ -78,7 +78,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| format.html { redirect_to <%= index_helper %>_url } - format.json { render <%= key_value :json, '{}' %>, <%= key_value :status, ':ok' %> } + format.json { head :ok } end end end -- cgit v1.2.3 From 5265650d51713a883e6cacde8f6faf52708abc1b Mon Sep 17 00:00:00 2001 From: Oge Nnadi Date: Mon, 11 Apr 2011 14:26:23 -0700 Subject: Edited railties/guides/source/active_support_core_extensions.textile via GitHub --- railties/guides/source/active_support_core_extensions.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 788f528654..0d868d0c6c 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -20,7 +20,7 @@ Thus, after a simple require like: require 'active_support' -objects do not even respond to +blank?+. Let's see how to load its definition. +objects begin responding to +blank?+. Let's see how to load only its definition. h5. Cherry-picking a Definition -- cgit v1.2.3 From d1575ae1b9658c91145d6a46ec2a144a5a089207 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 12 Apr 2011 00:23:07 +0200 Subject: Change Object#either? to Object#among? -- thanks to @jamesarosen for the suggestion! --- railties/guides/rails_guides/textile_extensions.rb | 4 ++-- railties/lib/rails/commands.rb | 2 +- railties/lib/rails/commands/benchmarker.rb | 2 +- railties/lib/rails/commands/destroy.rb | 2 +- railties/lib/rails/commands/generate.rb | 2 +- railties/lib/rails/commands/profiler.rb | 2 +- railties/lib/rails/generators/base.rb | 2 +- railties/lib/rails/generators/generated_attribute.rb | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) (limited to 'railties') diff --git a/railties/guides/rails_guides/textile_extensions.rb b/railties/guides/rails_guides/textile_extensions.rb index f1486a7c10..9beeefb551 100644 --- a/railties/guides/rails_guides/textile_extensions.rb +++ b/railties/guides/rails_guides/textile_extensions.rb @@ -5,7 +5,7 @@ module RailsGuides def notestuff(body) body.gsub!(/^(IMPORTANT|CAUTION|WARNING|NOTE|INFO)[.:](.*)$/) do |m| css_class = $1.downcase - css_class = 'warning' if css_class.either?('caution', 'important') + css_class = 'warning' if css_class.among?('caution', 'important') result = "

" result << $2.strip @@ -35,7 +35,7 @@ module RailsGuides def code(body) body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)}m) do |m| es = ERB::Util.h($2) - css_class = $1.either?('erb', 'shell') ? 'html' : $1 + css_class = $1.among?('erb', 'shell') ? 'html' : $1 %{

#{es}
} end end diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 28dff23890..7108d4157e 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -71,7 +71,7 @@ when '--version', '-v' require 'rails/commands/application' else - puts "Error: Command not recognized" unless command.either?('-h', '--help') + puts "Error: Command not recognized" unless command.among?('-h', '--help') puts <<-EOT Usage: rails COMMAND [ARGS] diff --git a/railties/lib/rails/commands/benchmarker.rb b/railties/lib/rails/commands/benchmarker.rb index ecdcccfd8d..e10ec8fd38 100644 --- a/railties/lib/rails/commands/benchmarker.rb +++ b/railties/lib/rails/commands/benchmarker.rb @@ -1,6 +1,6 @@ require 'active_support/core_ext/object/inclusion' -if ARGV.first.either?(nil, "-h", "--help") +if ARGV.first.among?(nil, "-h", "--help") puts "Usage: rails benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ..." exit 1 end diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb index 829d29dad7..d082ba592c 100644 --- a/railties/lib/rails/commands/destroy.rb +++ b/railties/lib/rails/commands/destroy.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/object/inclusion' Rails::Generators.configure! -if ARGV.first.either?(nil, "-h", "--help") +if ARGV.first.among?(nil, "-h", "--help") Rails::Generators.help 'destroy' exit end diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb index bef4c6df14..789e5ebedb 100644 --- a/railties/lib/rails/commands/generate.rb +++ b/railties/lib/rails/commands/generate.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/object/inclusion' Rails::Generators.configure! -if ARGV.first.either?(nil, "-h", "--help") +if ARGV.first.among?(nil, "-h", "--help") Rails::Generators.help 'generate' exit end diff --git a/railties/lib/rails/commands/profiler.rb b/railties/lib/rails/commands/profiler.rb index baa3baaec0..d3195a204e 100644 --- a/railties/lib/rails/commands/profiler.rb +++ b/railties/lib/rails/commands/profiler.rb @@ -1,6 +1,6 @@ require 'active_support/core_ext/object/inclusion' -if ARGV.first.either?(nil, "-h", "--help") +if ARGV.first.among?(nil, "-h", "--help") $stderr.puts "Usage: rails profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]" exit(1) end diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index e2c19340f4..2b0eaea3a4 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -165,7 +165,7 @@ module Rails names.each do |name| defaults = if options[:type] == :boolean { } - elsif default_value_for_option(name, options).either?(true, false) + elsif default_value_for_option(name, options).among?(true, false) { :banner => "" } else { :desc => "#{name.to_s.humanize} to be invoked", :banner => "NAME" } diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb index 8ed3b18872..f85375b2a3 100644 --- a/railties/lib/rails/generators/generated_attribute.rb +++ b/railties/lib/rails/generators/generated_attribute.rb @@ -45,7 +45,7 @@ module Rails end def reference? - self.type.either?(:references, :belongs_to) + self.type.among?(:references, :belongs_to) end end end -- cgit v1.2.3 From 3f283c2dd597db2b517edee0cd64cca19abc35b8 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 12 Apr 2011 00:37:02 +0200 Subject: Revert "Edited railties/guides/source/active_support_core_extensions.textile via GitHub" Reason: The original sentence is correct. Please note the guide covers the stable version of Active Support. This reverts commit 5265650d51713a883e6cacde8f6faf52708abc1b. --- railties/guides/source/active_support_core_extensions.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 0d868d0c6c..788f528654 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -20,7 +20,7 @@ Thus, after a simple require like: require 'active_support' -objects begin responding to +blank?+. Let's see how to load only its definition. +objects do not even respond to +blank?+. Let's see how to load its definition. h5. Cherry-picking a Definition -- cgit v1.2.3 From 7a1189a2c75b16f86a11c1d2379c50b11a7a2d66 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Mon, 11 Apr 2011 20:09:22 -0300 Subject: Updated AS guide with new Object#in? and Object#either? methods --- .../source/active_support_core_extensions.textile | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'railties') diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index 788f528654..3ba840c044 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -442,6 +442,28 @@ require_library_or_gem('mysql') NOTE: Defined in +active_support/core_ext/kernel/requires.rb+. +h4. +in?+ and +either?+ + +The predicate +in?+ tests if an object is included in another object, and the predicate +either?+ tests if an object is included in a list of objects which will be passed as arguments. + +Examples of +in?+: + + + 1.in?([1,2]) # => true + "lo".in?("hello") # => true + 25.in?(30..50) # => false + + +Examples of +either?+: + + + 1.either?(1,2,3) # => true + 5.either?(1,2,3) # => false + [1,2,3].either?([1,2,3], 2, [3,4,5]) # => true + + +NOTE: Defined in +active_support/core_ext/object/inclusion.rb+. + h3. Extensions to +Module+ h4. +alias_method_chain+ -- cgit v1.2.3 From 40d156955c82c19b14494c1bf60ad48980e29a4e Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Mon, 11 Apr 2011 22:43:27 -0300 Subject: Update guides reflecting that scaffold_controller generator generates now code for JSON response instead of XML --- railties/guides/source/getting_started.textile | 37 +++++++++++++------------- 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index 1122a4b9e3..5906f953bf 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -501,8 +501,8 @@ def index @posts = Post.all respond_to do |format| - format.html # index.html.erb - format.xml { render :xml => @posts } + format.html # index.html.erb + format.json { render :json => @posts } end end @@ -511,7 +511,7 @@ end TIP: For more information on finding records with Active Record, see "Active Record Query Interface":active_record_querying.html. -The +respond_to+ block handles both HTML and XML calls to this action. If you browse to "http://localhost:3000/posts.xml":http://localhost:3000/posts.xml, you'll see all of the posts in XML format. The HTML format looks for a view in +app/views/posts/+ with a name that corresponds to the action name. Rails makes all of the instance variables from the action available to the view. Here's +app/views/posts/index.html.erb+: +The +respond_to+ block handles both HTML and JSON calls to this action. If you browse to "http://localhost:3000/posts.json":http://localhost:3000/posts.json, you'll see a JSON containing all of the posts. The HTML format looks for a view in +app/views/posts/+ with a name that corresponds to the action name. Rails makes all of the instance variables from the action available to the view. Here's +app/views/posts/index.html.erb+:

Listing posts

@@ -584,8 +584,8 @@ def new @post = Post.new respond_to do |format| - format.html # new.html.erb - format.xml { render :xml => @post } + format.html # new.html.erb + format.json { render :json => @post } end end @@ -653,13 +653,13 @@ def create respond_to do |format| if @post.save - format.html { redirect_to(@post, + format.html { redirect_to(@post, :notice => 'Post was successfully created.') } - format.xml { render :xml => @post, + format.json { render :json => @post, :status => :created, :location => @post } else - format.html { render :action => "new" } - format.xml { render :xml => @post.errors, + format.html { render :action => "new" } + format.json { render :json => @post.errors, :status => :unprocessable_entity } end end @@ -681,8 +681,8 @@ def show @post = Post.find(params[:id]) respond_to do |format| - format.html # show.html.erb - format.xml { render :xml => @post } + format.html # show.html.erb + format.json { render :json => @post } end end @@ -743,12 +743,12 @@ def update respond_to do |format| if @post.update_attributes(params[:post]) - format.html { redirect_to(@post, + format.html { redirect_to(@post, :notice => 'Post was successfully updated.') } - format.xml { head :ok } + format.json { render :json => {}, :status => :ok } else - format.html { render :action => "edit" } - format.xml { render :xml => @post.errors, + format.html { render :action => "edit" } + format.json { render :json => @post.errors, :status => :unprocessable_entity } end end @@ -767,8 +767,8 @@ def destroy @post.destroy respond_to do |format| - format.html { redirect_to(posts_url) } - format.xml { head :ok } + format.html { redirect_to(posts_url) } + format.json { render :json => {}, :status => :ok } end end @@ -1213,7 +1213,7 @@ class PostsController < ApplicationController http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index # GET /posts - # GET /posts.xml + # GET /posts.json def index @posts = Post.all respond_to do |format| @@ -1458,6 +1458,7 @@ Two very common sources of data that are not UTF-8: h3. Changelog +* April 11, 2011: Changed scaffold_controller generator to create format block for JSON instead of XML "Sebastian Martinez":http://www.wyeworks.com * August 30, 2010: Minor editing after Rails 3 release by "Joost Baaij":http://www.spacebabies.nl * July 12, 2010: Fixes, editing and updating of code samples by "Jaime Iniesta":http://jaimeiniesta.com * May 16, 2010: Added a section on configuration gotchas to address common encoding problems that people might have by "Yehuda Katz":http://www.yehudakatz.com -- cgit v1.2.3 From a4518517f77055cea0d9fe552d2df393140679de Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Tue, 12 Apr 2011 22:12:27 -0500 Subject: Index sprockets environment if perform caching is enabled --- railties/lib/rails/application.rb | 1 + railties/lib/rails/application/finisher.rb | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 66a1f88c61..92f03f06bf 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -140,6 +140,7 @@ module Rails def assets @assets ||= build_asset_environment end + attr_writer :assets def build_asset_environment return unless config.assets.enabled diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index be063e5f25..bae464a840 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -48,6 +48,12 @@ module Rails end end + initializer :index_sprockets_environment do |app| + if config.assets.enabled && config.action_controller.perform_caching + app.assets = app.assets.index + end + end + initializer :build_middleware_stack do build_middleware_stack end -- cgit v1.2.3 From 096fa1b60f537c7c30db35f5576ab351c67a5064 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Thu, 24 Mar 2011 23:43:37 +0100 Subject: jQuery is the new default --- .../guides/source/layouts_and_rendering.textile | 14 ++++++++++++-- railties/lib/rails/generators/app_base.rb | 8 ++++---- .../rails/app/templates/config/application.rb | 6 +++--- railties/test/generators/app_generator_test.rb | 19 ++++++++----------- .../test/generators/plugin_new_generator_test.rb | 21 ++++++--------------- 5 files changed, 33 insertions(+), 35 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index 1548da0eb5..8ea63f2ce3 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -707,18 +707,28 @@ To include +http://example.com/main.js+: <%= javascript_include_tag "http://example.com/main.js" %>
-The +defaults+ option loads the Prototype and Scriptaculous libraries: +The +:defaults+ option loads jQuery by default: <%= javascript_include_tag :defaults %> -The +all+ option loads every JavaScript file in +public/javascripts+, starting with the Prototype and Scriptaculous libraries: +If the application was generated with "-j prototype" :defaults loads Prototype and Scriptaculous. And you can in any case override the expansion in config/application.rb: + + +config.action_view.javascript_expansions[:defaults] = %w(foo.js bar.js) + + +When using :defaults, if an application.js file exists in public/javascripts it will be included as well at then end. + +The +:all+ option loads every JavaScript file in +public/javascripts+: <%= javascript_include_tag :all %> +Note that your defaults of choice will be included first, so they will be available to all subsequently included files. + You can supply the +:recursive+ option to load files in subfolders of +public/javascripts+ as well: diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 93db5106ce..5a8906f035 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -10,7 +10,7 @@ module Rails module Generators class AppBase < Base DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) - JAVASCRIPTS = %w( prototype jquery ) + JAVASCRIPTS = %w( jquery prototype ) attr_accessor :rails_template add_shebang_option! @@ -36,11 +36,11 @@ module Rails class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" - class_option :javascript, :type => :string, :aliases => "-j", :default => "prototype", - :desc => "Preconfigure for selected javascript library (options: #{JAVASCRIPTS.join('/')})" + class_option :javascript, :type => :string, :aliases => "-j", :default => "jquery", + :desc => "Preconfigure for selected JavaScript library (options: #{JAVASCRIPTS.join('/')})" class_option :skip_javascript, :type => :boolean, :aliases => "-J", :default => false, - :desc => "Skip javascript files" + :desc => "Skip JavaScript files" class_option :dev, :type => :boolean, :default => false, :desc => "Setup the #{name} with Gemfile pointing to your Rails checkout" diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index b7f64af339..68b2457af5 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -42,10 +42,10 @@ module <%= app_const_base %> # JavaScript files you want as :defaults (application.js is always included). <% if options[:skip_javascript] -%> config.action_view.javascript_expansions[:defaults] = %w() -<% elsif options[:javascript] == 'jquery' -%> - config.action_view.javascript_expansions[:defaults] = %w(jquery rails) +<% elsif options[:javascript] == 'prototype' -%> + config.action_view.javascript_expansions[:defaults] = %w(prototype effects dragdrop controls rails) <% else -%> - # config.action_view.javascript_expansions[:defaults] = %w(jquery rails) + # config.action_view.javascript_expansions[:defaults] = %w(prototype effects dragdrop controls rails) <% end -%> <% if options[:skip_test_unit] -%> diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 43f2fbd71c..dfb7adf459 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -146,15 +146,12 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/ end - def test_prototype_and_test_unit_are_added_by_default + def test_jquery_and_test_unit_are_added_by_default run_generator - assert_file "config/application.rb", /#\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(jquery rails\)/ + assert_file "config/application.rb", /#\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(prototype effects dragdrop controls rails\)/ assert_file "public/javascripts/application.js" - assert_file "public/javascripts/prototype.js" + assert_file "public/javascripts/jquery.js" assert_file "public/javascripts/rails.js" - assert_file "public/javascripts/controls.js" - assert_file "public/javascripts/dragdrop.js" - assert_file "public/javascripts/effects.js" assert_file "test" end @@ -162,24 +159,24 @@ class AppGeneratorTest < Rails::Generators::TestCase run_generator [destination_root, "--skip-javascript"] assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(\)/ assert_file "public/javascripts/application.js" - assert_no_file "public/javascripts/prototype.js" + assert_no_file "public/javascripts/jquery.js" assert_no_file "public/javascripts/rails.js" end def test_config_prototype_javascript_library run_generator [destination_root, "-j", "prototype"] - assert_file "config/application.rb", /#\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(jquery rails\)/ + assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(prototype effects dragdrop controls rails\)/ assert_file "public/javascripts/application.js" assert_file "public/javascripts/prototype.js" - assert_file "public/javascripts/controls.js" - assert_file "public/javascripts/dragdrop.js" assert_file "public/javascripts/effects.js" + assert_file "public/javascripts/dragdrop.js" + assert_file "public/javascripts/controls.js" assert_file "public/javascripts/rails.js", /prototype/ end def test_config_jquery_javascript_library run_generator [destination_root, "-j", "jquery"] - assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(jquery rails\)/ + assert_file "config/application.rb", /#\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(prototype effects dragdrop controls rails\)/ assert_file "public/javascripts/application.js" assert_file "public/javascripts/jquery.js" assert_file "public/javascripts/rails.js", /jQuery/ diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 3c11c8dbaf..402fd25b14 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -95,41 +95,32 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_skipping_javascripts_without_mountable_option run_generator - assert_no_file "public/javascripts/prototype.js" + assert_no_file "public/javascripts/jquery.js" assert_no_file "public/javascripts/rails.js" - assert_no_file "public/javascripts/controls.js" - assert_no_file "public/javascripts/dragdrop.js" - assert_no_file "public/javascripts/dragdrop.js" assert_no_file "public/javascripts/application.js" end def test_javascripts_generation run_generator [destination_root, "--mountable"] + assert_file "public/javascripts/jquery.js" assert_file "public/javascripts/rails.js" - assert_file "public/javascripts/prototype.js" - assert_file "public/javascripts/controls.js" - assert_file "public/javascripts/dragdrop.js" - assert_file "public/javascripts/dragdrop.js" assert_file "public/javascripts/application.js" end def test_skip_javascripts run_generator [destination_root, "--skip-javascript", "--mountable"] - assert_no_file "public/javascripts/prototype.js" + assert_no_file "public/javascripts/jquery.js" assert_no_file "public/javascripts/rails.js" - assert_no_file "public/javascripts/controls.js" - assert_no_file "public/javascripts/dragdrop.js" - assert_no_file "public/javascripts/dragdrop.js" end def test_ensure_that_javascript_option_is_passed_to_app_generator - run_generator [destination_root, "--javascript", "jquery"] - assert_file "test/dummy/public/javascripts/jquery.js" + run_generator [destination_root, "--javascript", "prototype"] + assert_file "test/dummy/public/javascripts/prototype.js" end def test_ensure_that_skip_javascript_option_is_passed_to_app_generator run_generator [destination_root, "--skip_javascript"] - assert_no_file "test/dummy/public/javascripts/prototype.js" + assert_no_file "test/dummy/public/javascripts/jquery.js" end def test_template_from_dir_pwd -- cgit v1.2.3 From b878757c5073eac7e4fcfd2093d38d8b841db846 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Thu, 24 Mar 2011 23:51:17 +0100 Subject: removes assert_select_rjs --- railties/guides/source/testing.textile | 1 - 1 file changed, 1 deletion(-) (limited to 'railties') diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile index 2809c6d076..e2317661ea 100644 --- a/railties/guides/source/testing.textile +++ b/railties/guides/source/testing.textile @@ -592,7 +592,6 @@ There are more assertions that are primarily used in testing views: |_.Assertion |_.Purpose| |+assert_select_email+ |Allows you to make assertions on the body of an e-mail. | -|+assert_select_rjs+ |Allows you to make assertions on an RJS response. +assert_select_rjs+ has variants which allow you to narrow down on the updated element or even a particular operation on an element.| |+assert_select_encoded+ |Allows you to make assertions on encoded HTML. It does this by un-encoding the contents of each element and then calling the block with all the un-encoded elements.| |+css_select(selector)+ or +css_select(element, selector)+ |Returns an array of all the elements selected by the _selector_. In the second variant it first matches the base _element_ and tries to match the _selector_ expression on any of its children. If there are no matches both variants return an empty array.| -- cgit v1.2.3 From eea66892c80d51c1b959171c2e3feac67124aaba Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 25 Mar 2011 20:08:13 +0100 Subject: removes support for render :update --- railties/guides/source/ajax_on_rails.textile | 126 --------------------- .../guides/source/layouts_and_rendering.textile | 12 -- 2 files changed, 138 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/ajax_on_rails.textile b/railties/guides/source/ajax_on_rails.textile index b80df4aa58..708a6f65a4 100644 --- a/railties/guides/source/ajax_on_rails.textile +++ b/railties/guides/source/ajax_on_rails.textile @@ -178,11 +178,6 @@ h5. +remote_function+ h5. +update_page+ - -h3. JavaScript the Rails way: RJS - -In the last section we sent some AJAX requests to the server, and inserted the HTML response into the page (with the +:update+ option). However, sometimes a more complicated interaction with the page is needed, which you can either achieve with JavaScript... or with RJS! You are sending JavaScript instructions to the server in both cases, but while in the former case you have to write vanilla JavaScript, in the second you can code Rails, and sit back while Rails generates the JavaScript for you - so basically RJS is a Ruby DSL to write JavaScript in your Rails code. - h4. JavaScript without RJS First we'll check out how to send JavaScript to the server manually. You are practically never going to need this, but it's interesting to understand what's going on under the hood. @@ -198,20 +193,6 @@ end What happens here is that by specifying the Content-Type header variable, we instruct the browser to evaluate the text we are sending over (rather than displaying it as plain text, which is the default behavior). -h4. Inline RJS - -As we said, the purpose of RJS is to write Ruby which is then auto-magically turned into JavaScript by Rails. The above example didn't look too Ruby-esque so let's see how to do it the Rails way: - - -def javascript_test - render :update do |page| - page.alert "Hello from inline RJS" - end -end - - -The above code snippet does exactly the same as the one in the previous section - going about it much more elegantly though. You don't need to worry about headers,write ugly JavaScript code into a string etc. When the first parameter to +render+ is +:update+, Rails expects a block with a single parameter (+page+ in our case, which is the traditional naming convention) which is an instance of the JavaScriptGenerator:"http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper/JavaScriptGenerator/GeneratorMethods.html" object. As it's name suggests, JavaScriptGenerator is responsible for generating JavaScript from your Ruby code. You can execute multiple method calls on the +page+ instance - it's all turned into JavaScript code and sent to the server with the appropriate Content Type, "text/javascript". - h4. RJS Templates If you don't want to clutter your controllers with view code (especially when your inline RJS is more than a few lines), you can move your RJS code to a template file. RJS templates should go to the +/app/views/+ directory, just as +.html.erb+ or any other view files of the appropriate controller, conventionally named +js.rjs+. @@ -222,113 +203,6 @@ To rewrite the above example, you can leave the body of the action empty, and cr page.alert "Hello from inline RJS" -h4. RJS Reference - -In this section we'll go through the methods RJS offers. - -h5. JavaScriptGenerator Methods - -h6. DOM Element Manipulation - -It is possible to manipulate multiple elements at once through the +page+ JavaScriptGenerator instance. Let's see this in action: - - -page.show :div_one, :div_two -page.hide :div_one -page.remove :div_one, :div_two, :div_three -page.toggle :other_div - - -The above methods (+show+, +hide+, +remove+, +toggle+) have the same semantics as the Prototype methods of the same name. You can pass an arbitrary number (but at least one) of DOM ids to these calls. - - -h6. Inserting and Replacing Content - -You can insert content into an element on the page with the +insert_html+ method: - - -page.insert_html :top, :result, '42' - - -The first parameter is the position of the new content relative to the element specified by the second parameter, a DOM id. - -Position can be one of these four values: - -*** +:before+ Inserts the response text just before the target element. -*** +:after+ The response is inserted after the target element. -*** +:top+ Inserts the text into the target element, before it's original content. -*** +:bottom+ The counterpart of +:top+: the response is inserted after the target element's original content. - -The third parameter can either be a string, or a hash of options to be passed to ActionView::Base#render - for example: - - -page.insert_html :top, :result, :partial => "the_answer" - - -You can replace the contents (innerHTML) of an element with the +replace_html+ method. The only difference is that since it's clear where should the new content go, there is no need for a position parameter - so +replace_html+ takes only two arguments, -the DOM id of the element you wish to modify and a string or a hash of options to be passed to ActionView::Base#render. - -h6. Delay - -You can delay the execution of a block of code with +delay+: - - -page.delay(10) { page.alert('Hey! Just waited 10 seconds') } - - -+delay+ takes one parameter (time to wait in seconds) and a block which will be executed after the specified time has passed - whatever else follows a +page.delay+ line is executed immediately, the delay affects only the code in the block. - -h6. Reloading and Redirecting - -You can reload the page with the +reload+ method: - - -page.reload - - -When using AJAX, you can't rely on the standard +redirect_to+ controller method - you have to use the +page+'s instance method, also called +redirect_to+: - - -page.redirect_to some_url - - -h6. Generating Arbitrary JavaScript - -Sometimes even the full power of RJS is not enough to accomplish everything, but you still don't want to drop to pure JavaScript. A nice golden mean is offered by the combination of +<<+, +assign+ and +call+ methods: - - - page << "alert('1+1 equals 3')" - - -So +<<+ is used to execute an arbitrary JavaScript statement, passed as string to the method. The above code is equivalent to: - - - page.assign :result, 3 - page.call :alert, '1+1 equals ' + result - - -+assign+ simply assigns a value to a variable. +call+ is similar to +<<+ with a slightly different syntax: the first parameter is the name of the function to call, followed by the list of parameters passed to the function. - -h6. Class Proxies - -h5. Element Proxies - -h5. Collection Proxies - -h5. RJS Helpers - - - -h3. I Want my Yellow Thingy: Quick overview of Script.aculo.us - -h4. Introduction - -h4. Visual Effects - -h4. Drag and Drop - - - h3. Testing JavaScript JavaScript testing reminds me the definition of the world 'classic' by Mark Twain: "A classic is something that everybody wants to have read and nobody wants to read." It's similar with JavaScript testing: everyone would like to have it, yet it's not done by too much developers as it is tedious, complicated, there is a proliferation of tools and no consensus/accepted best practices, but we will nevertheless take a stab at it: diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index 8ea63f2ce3..da316a2db3 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -250,18 +250,6 @@ render :inline => "xml.p {'Horrid coding practice!'}", :type => :builder -h5. Using +render+ with +:update+ - -You can also render JavaScript-based page updates inline using the +:update+ option to +render+: - - -render :update do |page| - page.replace_html 'warning', "Invalid options supplied" -end - - -WARNING: Placing JavaScript updates in your controller may seem to streamline small updates, but it defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. We recommend using a separate RJS template instead, no matter how small the update. - h5. Rendering Text You can send plain text - with no markup at all - back to the browser by using the +:text+ option to +render+: -- cgit v1.2.3 From 5850f1693546f14420bf0bc630a48650f0d606d5 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 25 Mar 2011 23:12:09 +0100 Subject: removes the RJS template handler --- railties/guides/source/ajax_on_rails.textile | 17 ++++------------- railties/guides/source/layouts_and_rendering.textile | 4 ++-- 2 files changed, 6 insertions(+), 15 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/ajax_on_rails.textile b/railties/guides/source/ajax_on_rails.textile index 708a6f65a4..38a63ea483 100644 --- a/railties/guides/source/ajax_on_rails.textile +++ b/railties/guides/source/ajax_on_rails.textile @@ -3,14 +3,14 @@ h2. AJAX on Rails This guide covers the built-in Ajax/JavaScript functionality of Rails (and more); it will enable you to create rich and dynamic AJAX applications with ease! We will cover the following topics: * Quick introduction to AJAX and related technologies -* Handling JavaScript the Rails way: Rails helpers, RJS, Prototype and script.aculo.us +* Handling JavaScript the Rails way: Rails helpers, Prototype and script.aculo.us * Testing JavaScript functionality endprologue. h3. Hello AJAX - a Quick Intro -If you are a 'show me the code' type of person, you might want to skip this part and jump to the RJS section right away. However, I would really recommend to read it - you'll need the basics of DOM, http requests and other topics discussed here to really understand Ajax on Rails. +You'll need the basics of DOM, HTTP requests and other topics discussed here to really understand Ajax on Rails. h4. Asynchronous JavaScript + XML @@ -62,7 +62,7 @@ link_to_remote "Add to cart", * The second parameter, the +options+ hash is the most interesting part as it has the AJAX specific stuff: ** *:url* This is the only parameter that is always required to generate the simplest remote link (technically speaking, it is not required, you can pass an empty +options+ hash to +link_to_remote+ - but in this case the URL used for the POST request will be equal to your current URL which is probably not your intention). This URL points to your AJAX action handler. The URL is typically specified by Rails REST view helpers, but you can use the +url_for+ format too. -** *:update* There are basically two ways of injecting the server response into the page: One is involving RJS and we will discuss it in the next chapter, and the other is specifying a DOM id of the element we would like to update. The above example demonstrates the simplest way of accomplishing this - however, we are in trouble if the server responds with an error message because that will be injected into the page too! However, Rails has a solution for this situation: +** *:update* Specifying a DOM id of the element we would like to update. The above example demonstrates the simplest way of accomplishing this - however, we are in trouble if the server responds with an error message because that will be injected into the page too! However, Rails has a solution for this situation: link_to_remote "Add to cart", @@ -178,7 +178,7 @@ h5. +remote_function+ h5. +update_page+ -h4. JavaScript without RJS +h4. Serving JavaScript First we'll check out how to send JavaScript to the server manually. You are practically never going to need this, but it's interesting to understand what's going on under the hood. @@ -193,15 +193,6 @@ end What happens here is that by specifying the Content-Type header variable, we instruct the browser to evaluate the text we are sending over (rather than displaying it as plain text, which is the default behavior). -h4. RJS Templates - -If you don't want to clutter your controllers with view code (especially when your inline RJS is more than a few lines), you can move your RJS code to a template file. RJS templates should go to the +/app/views/+ directory, just as +.html.erb+ or any other view files of the appropriate controller, conventionally named +js.rjs+. - -To rewrite the above example, you can leave the body of the action empty, and create a RJS template named +javascript_test.js.rjs+, containing the following line: - - -page.alert "Hello from inline RJS" - h3. Testing JavaScript diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index da316a2db3..8dab578e6b 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -90,7 +90,7 @@ If we want to display the properties of all the books in our view, we can do so <%= link_to 'New book', new_book_path %> -NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), +.rjs+ for RJS (JavaScript with embedded ruby) and +.builder+ for Builder (XML generator). +NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), and +.builder+ for Builder (XML generator). h4. Using +render+ @@ -284,7 +284,7 @@ TIP: You don't need to call +to_xml+ on the object that you want to render. If y h5. Rendering Vanilla JavaScript -Rails can render vanilla JavaScript (as an alternative to using +update+ with an +.rjs+ file): +Rails can render vanilla JavaScript: render :js => "alert('Hello Rails');" -- cgit v1.2.3 From d8f23ca627df85b33fe8db87db5483c10b62bfe6 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sun, 27 Mar 2011 22:23:32 +0200 Subject: removes debug_rjs from ActionView::Base --- railties/guides/source/configuring.textile | 2 -- .../source/debugging_rails_applications.textile | 20 -------------------- .../templates/config/environments/development.rb.tt | 1 - 3 files changed, 23 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index 9ca567129b..53460b8c36 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -291,8 +291,6 @@ h4. Configuring Action View There are only a few configuration options for Action View, starting with four on +ActionView::Base+: -* +config.action_view.debug_rjs+ specifies whether RJS responses should be wrapped in a try/catch block that alerts the caught exception (and then re-raises it). The default is +false+. - * +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is Proc.new{ |html_tag, instance| %Q(%<div class="field_with_errors">#{html_tag}</div>).html_safe } * +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+. diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile index 045b8823ca..fb17dccfb8 100644 --- a/railties/guides/source/debugging_rails_applications.textile +++ b/railties/guides/source/debugging_rails_applications.textile @@ -96,26 +96,6 @@ Will be rendered as follows: Title: Rails debugging guide -h4. Debugging RJS - -Rails has optional built-in support to debug RJS. When enabled, responses are wrapped in a try/catch block that displays the caught exception using +alert()+, and then re-raises it. - -The flag to enable RJS debugging in your configuration files is +config.action_view.debug_rjs+: - - -config.action_view.debug_rjs = true - - -or at any time setting +ActionView::Base.debug_rjs+: - - -ActionView::Base.debug_rjs = true - - -It is enabled by default in development mode, and disabled in the rest. - -TIP: For more information on debugging JavaScript, refer to "Firebug":http://getfirebug.com/, the popular debugger for Firefox. - h3. The Logger It can also be useful to save information to log files at runtime. Rails maintains a separate log file for each runtime environment. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index bdb897ad33..41b2374eda 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -11,7 +11,6 @@ # Show full error reports and disable caching config.consider_all_requests_local = true - config.action_view.debug_rjs = true config.action_controller.perform_caching = false # Don't care if the mailer can't send -- cgit v1.2.3 From 6cf1fc5cda56896cad0239905dc8f4bfe73f8280 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 29 Mar 2011 22:14:11 +0200 Subject: removes mentions to RJS in the security guide --- railties/guides/source/security.textile | 6 ------ 1 file changed, 6 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile index 893f65856c..c9dc1c2d7c 100644 --- a/railties/guides/source/security.textile +++ b/railties/guides/source/security.textile @@ -893,12 +893,6 @@ h4. Ajax Injection If you use the "in_place_editor plugin":http://dev.rubyonrails.org/browser/plugins/in_place_editing, or actions that return a string, rather than rendering a view, _(highlight)you have to escape the return value in the action_. Otherwise, if the return value contains a XSS string, the malicious code will be executed upon return to the browser. Escape any input value using the h() method. -h4. RJS Injection - --- _Don't forget to escape in JavaScript (RJS) templates, too._ - -The RJS API generates blocks of JavaScript code based on Ruby code, thus allowing you to manipulate a view or parts of a view from the server side. If you allow user input in RJS templates, do escape it using +escape_javascript()+ within JavaScript functions, and in HTML parts using +h()+. Otherwise an attacker could execute arbitrary JavaScript. - h4. Command Line Injection -- _Use user-supplied command line parameters with caution._ -- cgit v1.2.3 From 06ae5769e1d61b9b0e8e3dedd63244804c8130f5 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Wed, 30 Mar 2011 22:25:41 +0200 Subject: removes some remaining .rjs occurrences --- railties/lib/rails/source_annotation_extractor.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index 302206bbcd..6d6e7f8b59 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -30,7 +30,7 @@ class SourceAnnotationExtractor # Prints all annotations with tag +tag+ under the root directories +app+, +lib+, # and +test+ (recursively). Only filenames with extension +.builder+, +.rb+, - # +.rxml+, +.rjs+, +.rhtml+, or +.erb+ are taken into account. The +options+ + # +.rxml+, +.rhtml+, or +.erb+ are taken into account. The +options+ # hash is passed to each annotation's +to_s+. # # This class method is the single entry point for the rake tasks. @@ -47,7 +47,7 @@ class SourceAnnotationExtractor # Returns a hash that maps filenames under +dirs+ (recursively) to arrays # with their annotations. Only files with annotations are included, and only - # those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+ + # those with extension +.builder+, +.rb+, +.rxml+, +.rhtml+, and +.erb+ # are taken into account. def find(dirs=%w(app lib test)) dirs.inject({}) { |h, dir| h.update(find_in(dir)) } @@ -55,7 +55,7 @@ class SourceAnnotationExtractor # Returns a hash that maps filenames under +dir+ (recursively) to arrays # with their annotations. Only files with annotations are included, and only - # those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+ + # those with extension +.builder+, +.rb+, +.rxml+, +.rhtml+, and +.erb+ # are taken into account. def find_in(dir) results = {} -- cgit v1.2.3 From 66e43aa1a817690c836a23370b73cd6b7bb00458 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Wed, 13 Apr 2011 13:40:43 +0200 Subject: updates railties CHANGELOG --- railties/CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) (limited to 'railties') diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 90faad6131..e136dd0279 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.1.0 (unreleased)* +* jQuery is the new default JavaScript library. [fxn] + * Changed scaffold and app generator to create Ruby 1.9 style hash when running on Ruby 1.9 [Prem Sichanugrist] So instead of creating something like: -- cgit v1.2.3 From 733bfa63f5d8d3b963202b6d3e9f00b4db070b91 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Wed, 13 Apr 2011 00:04:40 +0800 Subject: Remove `#among?` from Active Support After a long list of discussion about the performance problem from using varargs and the reason that we can't find a great pair for it, it would be best to remove support for it for now. It will come back if we can find a good pair for it. For now, Bon Voyage, `#among?`. --- railties/guides/rails_guides/textile_extensions.rb | 4 ++-- railties/lib/rails/commands.rb | 2 +- railties/lib/rails/commands/benchmarker.rb | 2 +- railties/lib/rails/commands/destroy.rb | 2 +- railties/lib/rails/commands/generate.rb | 2 +- railties/lib/rails/commands/profiler.rb | 2 +- railties/lib/rails/generators/base.rb | 2 +- railties/lib/rails/generators/generated_attribute.rb | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) (limited to 'railties') diff --git a/railties/guides/rails_guides/textile_extensions.rb b/railties/guides/rails_guides/textile_extensions.rb index 9beeefb551..352c5e91dd 100644 --- a/railties/guides/rails_guides/textile_extensions.rb +++ b/railties/guides/rails_guides/textile_extensions.rb @@ -5,7 +5,7 @@ module RailsGuides def notestuff(body) body.gsub!(/^(IMPORTANT|CAUTION|WARNING|NOTE|INFO)[.:](.*)$/) do |m| css_class = $1.downcase - css_class = 'warning' if css_class.among?('caution', 'important') + css_class = 'warning' if css_class.in?(['caution', 'important']) result = "

" result << $2.strip @@ -35,7 +35,7 @@ module RailsGuides def code(body) body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)}m) do |m| es = ERB::Util.h($2) - css_class = $1.among?('erb', 'shell') ? 'html' : $1 + css_class = $1.in?(['erb', 'shell']) ? 'html' : $1 %{

#{es}
} end end diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 7108d4157e..4182757346 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -71,7 +71,7 @@ when '--version', '-v' require 'rails/commands/application' else - puts "Error: Command not recognized" unless command.among?('-h', '--help') + puts "Error: Command not recognized" unless command.in?(['-h', '--help']) puts <<-EOT Usage: rails COMMAND [ARGS] diff --git a/railties/lib/rails/commands/benchmarker.rb b/railties/lib/rails/commands/benchmarker.rb index e10ec8fd38..f230f405c0 100644 --- a/railties/lib/rails/commands/benchmarker.rb +++ b/railties/lib/rails/commands/benchmarker.rb @@ -1,6 +1,6 @@ require 'active_support/core_ext/object/inclusion' -if ARGV.first.among?(nil, "-h", "--help") +if ARGV.first.in?([nil, "-h", "--help"]) puts "Usage: rails benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ..." exit 1 end diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb index d082ba592c..2a84e2a6df 100644 --- a/railties/lib/rails/commands/destroy.rb +++ b/railties/lib/rails/commands/destroy.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/object/inclusion' Rails::Generators.configure! -if ARGV.first.among?(nil, "-h", "--help") +if ARGV.first.in?([nil, "-h", "--help"]) Rails::Generators.help 'destroy' exit end diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb index 789e5ebedb..28c1c56352 100644 --- a/railties/lib/rails/commands/generate.rb +++ b/railties/lib/rails/commands/generate.rb @@ -3,7 +3,7 @@ require 'active_support/core_ext/object/inclusion' Rails::Generators.configure! -if ARGV.first.among?(nil, "-h", "--help") +if ARGV.first.in?([nil, "-h", "--help"]) Rails::Generators.help 'generate' exit end diff --git a/railties/lib/rails/commands/profiler.rb b/railties/lib/rails/commands/profiler.rb index d3195a204e..7959d8a981 100644 --- a/railties/lib/rails/commands/profiler.rb +++ b/railties/lib/rails/commands/profiler.rb @@ -1,6 +1,6 @@ require 'active_support/core_ext/object/inclusion' -if ARGV.first.among?(nil, "-h", "--help") +if ARGV.first.in?([nil, "-h", "--help"]) $stderr.puts "Usage: rails profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]" exit(1) end diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 2b0eaea3a4..8d03cb911b 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -165,7 +165,7 @@ module Rails names.each do |name| defaults = if options[:type] == :boolean { } - elsif default_value_for_option(name, options).among?(true, false) + elsif default_value_for_option(name, options).in?([true, false]) { :banner => "" } else { :desc => "#{name.to_s.humanize} to be invoked", :banner => "NAME" } diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb index f85375b2a3..b26161f1d0 100644 --- a/railties/lib/rails/generators/generated_attribute.rb +++ b/railties/lib/rails/generators/generated_attribute.rb @@ -45,7 +45,7 @@ module Rails end def reference? - self.type.among?(:references, :belongs_to) + self.type.in?([:references, :belongs_to]) end end end -- cgit v1.2.3 From ab1f91394f630a0a5a9c3de6ed0cb797d3bf56e2 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 13 Apr 2011 14:13:54 +0200 Subject: Until the latest sprockets gem is released, we need new apps to reference it directly --- railties/lib/rails/generators/app_base.rb | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 5a8906f035..eba4ea0c95 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -130,24 +130,27 @@ module Rails def rails_gemfile_entry if options.dev? <<-GEMFILE.strip_heredoc - gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}' - gem 'arel', :git => 'git://github.com/rails/arel.git' - gem 'rack', :git => 'git://github.com/rack/rack.git' + gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}' + gem 'arel', :git => 'git://github.com/rails/arel.git' + gem 'rack', :git => 'git://github.com/rack/rack.git' + gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" GEMFILE elsif options.edge? <<-GEMFILE.strip_heredoc - gem 'rails', :git => 'git://github.com/rails/rails.git' - gem 'arel', :git => 'git://github.com/rails/arel.git' - gem 'rack', :git => 'git://github.com/rack/rack.git' + gem 'rails', :git => 'git://github.com/rails/rails.git' + gem 'arel', :git => 'git://github.com/rails/arel.git' + gem 'rack', :git => 'git://github.com/rack/rack.git' + gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" GEMFILE else <<-GEMFILE.strip_heredoc gem 'rails', '#{Rails::VERSION::STRING}' # Bundle edge Rails instead: - # gem 'rails', :git => 'git://github.com/rails/rails.git' - # gem 'arel', :git => 'git://github.com/rails/arel.git' - # gem 'rack', :git => 'git://github.com/rack/rack.git' + # gem 'rails', :git => 'git://github.com/rails/rails.git' + # gem 'arel', :git => 'git://github.com/rails/arel.git' + # gem 'rack', :git => 'git://github.com/rack/rack.git' + # gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" GEMFILE end end -- cgit v1.2.3 From 101406d7430ce7d9350abdcbf2e7d04fa84779e7 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 13 Apr 2011 14:30:39 +0200 Subject: Move to app/assets in anticipation of image support being added as well. Also add vendor/assets to default load path --- railties/lib/rails/application.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 92f03f06bf..e3942f0f1f 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -153,8 +153,10 @@ module Rails initializer :add_sprockets_paths do |app| if config.assets.enabled paths = [ - "app/javascripts", - "app/stylesheets", + "app/assets/javascripts", + "app/assets/stylesheets", + "vendor/assets/javascripts", + "vendor/assets/stylesheets", "vendor/plugins/*/app/javascripts", "vendor/plugins/*/app/stylesheets", "vendor/plugins/*/javascripts", -- cgit v1.2.3 From 6d5e86eb6be6ee925a835bf248c0932945cbc54c Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Wed, 13 Apr 2011 16:19:46 +0200 Subject: Clean up the generator, switch to assets usage, use vendor/assets for the default scripts, and more --- railties/lib/rails/generators/app_base.rb | 403 + .../rails/generators/rails/app/app_generator.rb | 70 +- .../app/assets/javascripts/application.js | 2 + .../app/assets/stylesheets/application.css | 1 + .../rails/app/templates/config/application.rb | 5 - .../config/initializers/new_rails_defaults.rb.tt | 8 + .../templates/public/javascripts/application.js | 2 - .../app/templates/public/javascripts/controls.js | 965 --- .../app/templates/public/javascripts/dragdrop.js | 974 --- .../app/templates/public/javascripts/effects.js | 1123 --- .../app/templates/public/javascripts/jquery.js | 8176 -------------------- .../app/templates/public/javascripts/jquery_ujs.js | 148 - .../app/templates/public/javascripts/prototype.js | 6082 --------------- .../templates/public/javascripts/prototype_ujs.js | 208 - .../vendor/assets/javascripts/controls.js | 965 +++ .../vendor/assets/javascripts/dragdrop.js | 974 +++ .../templates/vendor/assets/javascripts/effects.js | 1123 +++ .../templates/vendor/assets/javascripts/jquery.js | 8176 ++++++++++++++++++++ .../vendor/assets/javascripts/jquery_ujs.js | 148 + .../vendor/assets/javascripts/prototype.js | 6082 +++++++++++++++ .../vendor/assets/javascripts/prototype_ujs.js | 208 + 21 files changed, 18121 insertions(+), 17722 deletions(-) create mode 100644 railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js create mode 100644 railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css create mode 100644 railties/lib/rails/generators/rails/app/templates/config/initializers/new_rails_defaults.rb.tt delete mode 100644 railties/lib/rails/generators/rails/app/templates/public/javascripts/application.js delete mode 100644 railties/lib/rails/generators/rails/app/templates/public/javascripts/controls.js delete mode 100644 railties/lib/rails/generators/rails/app/templates/public/javascripts/dragdrop.js delete mode 100644 railties/lib/rails/generators/rails/app/templates/public/javascripts/effects.js delete mode 100644 railties/lib/rails/generators/rails/app/templates/public/javascripts/jquery.js delete mode 100644 railties/lib/rails/generators/rails/app/templates/public/javascripts/jquery_ujs.js delete mode 100644 railties/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js delete mode 100644 railties/lib/rails/generators/rails/app/templates/public/javascripts/prototype_ujs.js create mode 100644 railties/lib/rails/generators/rails/app/templates/vendor/assets/javascripts/controls.js create mode 100644 railties/lib/rails/generators/rails/app/templates/vendor/assets/javascripts/dragdrop.js create mode 100644 railties/lib/rails/generators/rails/app/templates/vendor/assets/javascripts/effects.js create mode 100644 railties/lib/rails/generators/rails/app/templates/vendor/assets/javascripts/jquery.js create mode 100644 railties/lib/rails/generators/rails/app/templates/vendor/assets/javascripts/jquery_ujs.js create mode 100644 railties/lib/rails/generators/rails/app/templates/vendor/assets/javascripts/prototype.js create mode 100644 railties/lib/rails/generators/rails/app/templates/vendor/assets/javascripts/prototype_ujs.js (limited to 'railties') diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index eba4ea0c95..b08137eb6d 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -177,6 +177,409 @@ module Rails def empty_directory_with_gitkeep(destination, config = {}) empty_directory(destination, config) + git_keep(destination) + end + + def git_keep(destination) + create_file("#{destination}/.gitkeep") unless options[:skip_git] + end + + # Returns Ruby 1.9 style key-value pair if current code is running on + # Ruby 1.9.x. Returns the old-style (with hash rocket) otherwise. + def key_value(key, value) + if options[:old_style_hash] || RUBY_VERSION < '1.9' + ":#{key} => #{value}" + else + "#{key}: #{value}" + end + end + end + end +end +require 'digest/md5' +require 'active_support/secure_random' +require 'active_support/core_ext/string/strip' +require 'rails/version' unless defined?(Rails::VERSION) +require 'rbconfig' +require 'open-uri' +require 'uri' + +module Rails + module Generators + class AppBase < Base + DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) + JAVASCRIPTS = %w( jquery prototype ) + + attr_accessor :rails_template + add_shebang_option! + + argument :app_path, :type => :string + + def self.add_shared_options_for(name) + class_option :builder, :type => :string, :aliases => "-b", + :desc => "Path to a #{name} builder (can be a filesystem path or URL)" + + class_option :template, :type => :string, :aliases => "-m", + :desc => "Path to an #{name} template (can be a filesystem path or URL)" + + class_option :skip_gemfile, :type => :boolean, :default => false, + :desc => "Don't create a Gemfile" + + class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, + :desc => "Skip Git ignores and keeps" + + class_option :skip_active_record, :type => :boolean, :aliases => "-O", :default => false, + :desc => "Skip Active Record files" + + class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", + :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" + + class_option :javascript, :type => :string, :aliases => "-j", :default => "jquery", + :desc => "Preconfigure for selected JavaScript library (options: #{JAVASCRIPTS.join('/')})" + + class_option :skip_javascript, :type => :boolean, :aliases => "-J", :default => false, + :desc => "Skip JavaScript files" + + class_option :dev, :type => :boolean, :default => false, + :desc => "Setup the #{name} with Gemfile pointing to your Rails checkout" + + class_option :edge, :type => :boolean, :default => false, + :desc => "Setup the #{name} with Gemfile pointing to Rails repository" + + class_option :skip_test_unit, :type => :boolean, :aliases => "-T", :default => false, + :desc => "Skip Test::Unit files" + + class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, + :desc => "Show this help message and quit" + + class_option :old_style_hash, :type => :boolean, :default => false, + :desc => "Force using old style hash (:foo => 'bar') on Ruby >= 1.9" + end + + def initialize(*args) + @original_wd = Dir.pwd + + super + end + + protected + + def builder + @builder ||= begin + if path = options[:builder] + if URI(path).is_a?(URI::HTTP) + contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read } + else + contents = open(File.expand_path(path, @original_wd)) {|io| io.read } + end + + prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1) + instance_eval(&prok) + end + + builder_class = get_builder_class + builder_class.send(:include, ActionMethods) + builder_class.new(self) + end + end + + def build(meth, *args) + builder.send(meth, *args) if builder.respond_to?(meth) + end + + def create_root + self.destination_root = File.expand_path(app_path, destination_root) + valid_const? + + empty_directory '.' + set_default_accessors! + FileUtils.cd(destination_root) unless options[:pretend] + end + + def apply_rails_template + apply rails_template if rails_template + rescue Thor::Error, LoadError, Errno::ENOENT => e + raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}" + end + + def set_default_accessors! + self.rails_template = case options[:template] + when /^https?:\/\// + options[:template] + when String + File.expand_path(options[:template], Dir.pwd) + else + options[:template] + end + end + + def database_gemfile_entry + entry = options[:skip_active_record] ? "" : "gem '#{gem_for_database}'" + if options[:database] == 'mysql' + if options.dev? || options.edge? + entry += ", :git => 'git://github.com/brianmario/mysql2.git'" + else + entry += "\n# gem 'mysql2', :git => 'git://github.com/brianmario/mysql2.git'" + end + end + entry + end + + def rails_gemfile_entry + if options.dev? + <<-GEMFILE.strip_heredoc + gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}' + gem 'arel', :git => 'git://github.com/rails/arel.git' + gem 'rack', :git => 'git://github.com/rack/rack.git' + gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" + gem 'json' # Sprockets dependency + GEMFILE + elsif options.edge? + <<-GEMFILE.strip_heredoc + gem 'rails', :git => 'git://github.com/rails/rails.git' + gem 'arel', :git => 'git://github.com/rails/arel.git' + gem 'rack', :git => 'git://github.com/rack/rack.git' + gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" + gem 'json' # Sprockets dependency + GEMFILE + else + <<-GEMFILE.strip_heredoc + gem 'rails', '#{Rails::VERSION::STRING}' + + # Bundle edge Rails instead: + # gem 'rails', :git => 'git://github.com/rails/rails.git' + # gem 'arel', :git => 'git://github.com/rails/arel.git' + # gem 'rack', :git => 'git://github.com/rack/rack.git' + # gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" + # gem 'json' # Sprockets dependency + GEMFILE + end + end + + def gem_for_database + # %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) + case options[:database] + when "oracle" then "ruby-oci8" + when "postgresql" then "pg" + when "frontbase" then "ruby-frontbase" + when "mysql" then "mysql2" + else options[:database] + end + end + + def bundle_if_dev_or_edge + bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') + run "#{bundle_command} install" if dev_or_edge? + end + + def dev_or_edge? + options.dev? || options.edge? + end + + def empty_directory_with_gitkeep(destination, config = {}) + empty_directory(destination, config) + git_keep(destination) + end + + def git_keep(destination) + create_file("#{destination}/.gitkeep") unless options[:skip_git] + end + + # Returns Ruby 1.9 style key-value pair if current code is running on + # Ruby 1.9.x. Returns the old-style (with hash rocket) otherwise. + def key_value(key, value) + if options[:old_style_hash] || RUBY_VERSION < '1.9' + ":#{key} => #{value}" + else + "#{key}: #{value}" + end + end + end + end +end +require 'digest/md5' +require 'active_support/secure_random' +require 'active_support/core_ext/string/strip' +require 'rails/version' unless defined?(Rails::VERSION) +require 'rbconfig' +require 'open-uri' +require 'uri' + +module Rails + module Generators + class AppBase < Base + DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) + JAVASCRIPTS = %w( jquery prototype ) + + attr_accessor :rails_template + add_shebang_option! + + argument :app_path, :type => :string + + def self.add_shared_options_for(name) + class_option :builder, :type => :string, :aliases => "-b", + :desc => "Path to a #{name} builder (can be a filesystem path or URL)" + + class_option :template, :type => :string, :aliases => "-m", + :desc => "Path to an #{name} template (can be a filesystem path or URL)" + + class_option :skip_gemfile, :type => :boolean, :default => false, + :desc => "Don't create a Gemfile" + + class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, + :desc => "Skip Git ignores and keeps" + + class_option :skip_active_record, :type => :boolean, :aliases => "-O", :default => false, + :desc => "Skip Active Record files" + + class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", + :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" + + class_option :javascript, :type => :string, :aliases => "-j", :default => "jquery", + :desc => "Preconfigure for selected JavaScript library (options: #{JAVASCRIPTS.join('/')})" + + class_option :skip_javascript, :type => :boolean, :aliases => "-J", :default => false, + :desc => "Skip JavaScript files" + + class_option :dev, :type => :boolean, :default => false, + :desc => "Setup the #{name} with Gemfile pointing to your Rails checkout" + + class_option :edge, :type => :boolean, :default => false, + :desc => "Setup the #{name} with Gemfile pointing to Rails repository" + + class_option :skip_test_unit, :type => :boolean, :aliases => "-T", :default => false, + :desc => "Skip Test::Unit files" + + class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, + :desc => "Show this help message and quit" + + class_option :old_style_hash, :type => :boolean, :default => false, + :desc => "Force using old style hash (:foo => 'bar') on Ruby >= 1.9" + end + + def initialize(*args) + @original_wd = Dir.pwd + + super + end + + protected + + def builder + @builder ||= begin + if path = options[:builder] + if URI(path).is_a?(URI::HTTP) + contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read } + else + contents = open(File.expand_path(path, @original_wd)) {|io| io.read } + end + + prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1) + instance_eval(&prok) + end + + builder_class = get_builder_class + builder_class.send(:include, ActionMethods) + builder_class.new(self) + end + end + + def build(meth, *args) + builder.send(meth, *args) if builder.respond_to?(meth) + end + + def create_root + self.destination_root = File.expand_path(app_path, destination_root) + valid_const? + + empty_directory '.' + set_default_accessors! + FileUtils.cd(destination_root) unless options[:pretend] + end + + def apply_rails_template + apply rails_template if rails_template + rescue Thor::Error, LoadError, Errno::ENOENT => e + raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}" + end + + def set_default_accessors! + self.rails_template = case options[:template] + when /^https?:\/\// + options[:template] + when String + File.expand_path(options[:template], Dir.pwd) + else + options[:template] + end + end + + def database_gemfile_entry + entry = options[:skip_active_record] ? "" : "gem '#{gem_for_database}'" + if options[:database] == 'mysql' + if options.dev? || options.edge? + entry += ", :git => 'git://github.com/brianmario/mysql2.git'" + else + entry += "\n# gem 'mysql2', :git => 'git://github.com/brianmario/mysql2.git'" + end + end + entry + end + + def rails_gemfile_entry + if options.dev? + <<-GEMFILE.strip_heredoc + gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}' + gem 'arel', :git => 'git://github.com/rails/arel.git' + gem 'rack', :git => 'git://github.com/rack/rack.git' + gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" + GEMFILE + elsif options.edge? + <<-GEMFILE.strip_heredoc + gem 'rails', :git => 'git://github.com/rails/rails.git' + gem 'arel', :git => 'git://github.com/rails/arel.git' + gem 'rack', :git => 'git://github.com/rack/rack.git' + gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" + GEMFILE + else + <<-GEMFILE.strip_heredoc + gem 'rails', '#{Rails::VERSION::STRING}' + + # Bundle edge Rails instead: + # gem 'rails', :git => 'git://github.com/rails/rails.git' + # gem 'arel', :git => 'git://github.com/rails/arel.git' + # gem 'rack', :git => 'git://github.com/rack/rack.git' + # gem 'sprockets', :git => "git://github.com/sstephenson/sprockets.git" + GEMFILE + end + end + + def gem_for_database + # %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) + case options[:database] + when "oracle" then "ruby-oci8" + when "postgresql" then "pg" + when "frontbase" then "ruby-frontbase" + when "mysql" then "mysql2" + else options[:database] + end + end + + def bundle_if_dev_or_edge + bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') + run "#{bundle_command} install" if dev_or_edge? + end + + def dev_or_edge? + options.dev? || options.edge? + end + + def empty_directory_with_gitkeep(destination, config = {}) + empty_directory(destination, config) + git_keep(destination) + end + + def git_keep(destination) create_file("#{destination}/.gitkeep") unless options[:skip_git] end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 3f6ff35a86..ef5c6f628c 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -46,6 +46,8 @@ module Rails def app directory 'app' + git_keep 'app/mailers' + git_keep 'app/models' end def config @@ -80,14 +82,7 @@ module Rails end def log - empty_directory "log" - - inside "log" do - %w( server production development test ).each do |file| - create_file "#{file}.log" - chmod "#{file}.log", 0666, :verbose => false - end - end + empty_directory_with_gitkeep "log" end def public_directory @@ -98,27 +93,6 @@ module Rails directory "public/images" end - def stylesheets - empty_directory_with_gitkeep "public/stylesheets" - end - - def javascripts - empty_directory "public/javascripts" - - unless options[:skip_javascript] - copy_file "public/javascripts/#{options[:javascript]}.js" - copy_file "public/javascripts/#{options[:javascript]}_ujs.js", "public/javascripts/rails.js" - - if options[:javascript] == "prototype" - copy_file "public/javascripts/controls.js" - copy_file "public/javascripts/dragdrop.js" - copy_file "public/javascripts/effects.js" - end - end - - copy_file "public/javascripts/application.js" - end - def script directory "script" do |content| "#{shebang}\n" + content @@ -127,19 +101,38 @@ module Rails end def test - directory "test" + empty_directory_with_gitkeep "test/fixtures" + empty_directory_with_gitkeep "test/functional" + empty_directory_with_gitkeep "test/integration" + empty_directory_with_gitkeep "test/unit" + + #empty_directory "test/performance" + copy_file "test/performance/browsing_test.rb" end def tmp - empty_directory "tmp" + empty_directory_with_gitkeep "tmp" + end + + def vendor_javascripts + if options[:skip_javascript] + empty_directory_with_gitkeep "vendor/assets/javascripts" + else + copy_file "vendor/assets/javascripts/#{options[:javascript]}.js" + copy_file "vendor/assets/javascripts/#{options[:javascript]}_ujs.js" - inside "tmp" do - %w(sessions sockets cache pids).each do |dir| - empty_directory(dir) + if options[:javascript] == "prototype" + copy_file "vendor/assets/javascripts/controls.js" + copy_file "vendor/assets/javascripts/dragdrop.js" + copy_file "vendor/assets/javascripts/effects.js" end end end + def vendor_stylesheets + empty_directory_with_gitkeep "vendor/assets/stylesheets" + end + def vendor_plugins empty_directory_with_gitkeep "vendor/plugins" end @@ -150,15 +143,14 @@ module Rails # can change in Ruby 1.8.7 when we FileUtils.cd. RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__)) - RESERVED_NAMES = %w[application destroy benchmarker profiler - plugin runner test] + RESERVED_NAMES = %w[application destroy benchmarker profiler plugin runner test] class AppGenerator < AppBase add_shared_options_for "application" # Add bin/rails options - class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, - :desc => "Show Rails version number and quit" + class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, + :desc => "Show Rails version number and quit" def initialize(*args) raise Error, "Options should be given after the application name. For details run: rails --help" if args[0].blank? @@ -246,7 +238,7 @@ module Rails end def create_vendor_files - build(:vendor_plugins) + build(:vendor) end def finish_template diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js new file mode 100644 index 0000000000..40a433a58d --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js @@ -0,0 +1,2 @@ +// Place your application-specific JavaScript functions and classes here +// FIXME: Tell people how Sprockets and Coffe works diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css new file mode 100644 index 0000000000..1f006c092e --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css @@ -0,0 +1 @@ +/* Introduce SCSS & Sprockets */ \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 68b2457af5..906f912a33 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -57,10 +57,5 @@ module <%= app_const_base %> # Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password] - -<% unless options[:skip_active_record] -%> - # Enable IdentityMap for Active Record, to disable set to false or remove the line below. - config.active_record.identity_map = true -<% end -%> end end diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_rails_defaults.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_rails_defaults.rb.tt new file mode 100644 index 0000000000..b04b9ccee7 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_rails_defaults.rb.tt @@ -0,0 +1,8 @@ +<%= app_const %>.configure do + config.assets.enabled = true + +<% unless options[:skip_active_record] -%> + # Enable IdentityMap for Active Record, to disable set to false or remove the line below. + config.active_record.identity_map = true +<% end -%> +end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/public/javascripts/application.js b/railties/lib/rails/generators/rails/app/templates/public/javascripts/application.js deleted file mode 100644 index fe4577696b..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/public/javascripts/application.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place your application-specific JavaScript functions and classes here -// This file is automatically included by javascript_include_tag :defaults diff --git a/railties/lib/rails/generators/rails/app/templates/public/javascripts/controls.js b/railties/lib/rails/generators/rails/app/templates/public/javascripts/controls.js deleted file mode 100644 index 7392fb664c..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/public/javascripts/controls.js +++ /dev/null @@ -1,965 +0,0 @@ -// 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 -// Rob Wills -// -// 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/ - -// Autocompleter.Base handles all the autocompletion functionality -// that's independent of the data source for autocompletion. This -// includes drawing the autocompletion menu, observing keyboard -// and mouse events, and similar. -// -// Specific autocompleters need to provide, at the very least, -// a getUpdatedChoices function that will be invoked every time -// the text inside the monitored textbox changes. This method -// should get the text for which to provide autocompletion by -// invoking this.getToken(), NOT by directly accessing -// this.element.value. This is to allow incremental tokenized -// autocompletion. Specific auto-completion logic (AJAX, etc) -// belongs in getUpdatedChoices. -// -// Tokenized incremental autocompletion is enabled automatically -// when an autocompleter is instantiated with the 'tokens' option -// in the options parameter, e.g.: -// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); -// will incrementally autocomplete with a comma as the token. -// Additionally, ',' in the above example can be replaced with -// a token array, e.g. { tokens: [',', '\n'] } which -// enables autocompletion on multiple tokens. This is most -// useful when one of the tokens is \n (a newline), as it -// allows smart autocompletion after linebreaks. - -if(typeof Effect == 'undefined') - throw("controls.js requires including script.aculo.us' effects.js library"); - -var Autocompleter = { }; -Autocompleter.Base = Class.create({ - baseInitialize: function(element, update, options) { - element = $(element); - this.element = element; - this.update = $(update); - this.hasFocus = false; - this.changed = false; - this.active = false; - this.index = 0; - this.entryCount = 0; - this.oldElementValue = this.element.value; - - if(this.setOptions) - this.setOptions(options); - else - this.options = options || { }; - - this.options.paramName = this.options.paramName || this.element.name; - this.options.tokens = this.options.tokens || []; - this.options.frequency = this.options.frequency || 0.4; - this.options.minChars = this.options.minChars || 1; - this.options.onShow = this.options.onShow || - function(element, update){ - if(!update.style.position || update.style.position=='absolute') { - update.style.position = 'absolute'; - Position.clone(element, update, { - setHeight: false, - offsetTop: element.offsetHeight - }); - } - Effect.Appear(update,{duration:0.15}); - }; - this.options.onHide = this.options.onHide || - function(element, update){ new Effect.Fade(update,{duration:0.15}) }; - - if(typeof(this.options.tokens) == 'string') - this.options.tokens = new Array(this.options.tokens); - // Force carriage returns as token delimiters anyway - if (!this.options.tokens.include('\n')) - this.options.tokens.push('\n'); - - this.observer = null; - - this.element.setAttribute('autocomplete','off'); - - Element.hide(this.update); - - Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); - }, - - show: function() { - if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); - if(!this.iefix && - (Prototype.Browser.IE) && - (Element.getStyle(this.update, 'position')=='absolute')) { - new Insertion.After(this.update, - ''); - this.iefix = $(this.update.id+'_iefix'); - } - if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); - }, - - fixIEOverlapping: function() { - Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); - this.iefix.style.zIndex = 1; - this.update.style.zIndex = 2; - Element.show(this.iefix); - }, - - hide: function() { - this.stopIndicator(); - if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); - if(this.iefix) Element.hide(this.iefix); - }, - - startIndicator: function() { - if(this.options.indicator) Element.show(this.options.indicator); - }, - - stopIndicator: function() { - if(this.options.indicator) Element.hide(this.options.indicator); - }, - - onKeyPress: function(event) { - if(this.active) - switch(event.keyCode) { - case Event.KEY_TAB: - case Event.KEY_RETURN: - this.selectEntry(); - Event.stop(event); - case Event.KEY_ESC: - this.hide(); - this.active = false; - Event.stop(event); - return; - case Event.KEY_LEFT: - case Event.KEY_RIGHT: - return; - case Event.KEY_UP: - this.markPrevious(); - this.render(); - Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - Event.stop(event); - return; - } - else - if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; - - this.changed = true; - this.hasFocus = true; - - if(this.observer) clearTimeout(this.observer); - this.observer = - setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) - { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index--; - else this.index = this.entryCount-1; - this.getEntry(this.index).scrollIntoView(true); - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++; - else this.index = 0; - this.getEntry(this.index).scrollIntoView(false); - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = $(selectedElement).select('.' + this.options.select) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var bounds = this.getTokenBounds(); - if (bounds[0] != -1) { - var newValue = this.element.value.substr(0, bounds[0]); - var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value + this.element.value.substr(bounds[1]); - } else { - this.element.value = value; - } - this.oldElementValue = this.element.value; - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.down()); - - if(this.update.firstChild && this.update.down().childNodes) { - this.entryCount = - this.update.down().childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { - this.entryCount = 0; - } - - this.stopIndicator(); - this.index = 0; - - if(this.entryCount==1 && this.options.autoSelect) { - this.selectEntry(); - this.hide(); - } else { - this.render(); - } - } - }, - - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - this.tokenBounds = null; - if(this.getToken().length>=this.options.minChars) { - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - this.oldElementValue = this.element.value; - }, - - getToken: function() { - var bounds = this.getTokenBounds(); - return this.element.value.substring(bounds[0], bounds[1]).strip(); - }, - - getTokenBounds: function() { - if (null != this.tokenBounds) return this.tokenBounds; - var value = this.element.value; - if (value.strip().empty()) return [-1, 0]; - var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); - var offset = (diff == this.oldElementValue.length ? 1 : 0); - var prevTokenPos = -1, nextTokenPos = value.length; - var tp; - for (var index = 0, l = this.options.tokens.length; index < l; ++index) { - tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); - if (tp > prevTokenPos) prevTokenPos = tp; - tp = value.indexOf(this.options.tokens[index], diff + offset); - if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; - } - return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); - } -}); - -Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { - var boundary = Math.min(newS.length, oldS.length); - for (var index = 0; index < boundary; ++index) - if (newS[index] != oldS[index]) - return index; - return boundary; -}; - -Ajax.Autocompleter = Class.create(Autocompleter.Base, { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - this.startIndicator(); - - var entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } -}); - -// The local array autocompleter. Used when you'd prefer to -// inject an array of autocompletion options into the page, rather -// than sending out Ajax queries, which can be quite slow sometimes. -// -// The constructor takes four parameters. The first two are, as usual, -// the id of the monitored textbox, and id of the autocompletion menu. -// The third is the array you want to autocomplete from, and the fourth -// is the options block. -// -// Extra local autocompletion options: -// - choices - How many autocompletion choices to offer -// -// - partialSearch - If false, the autocompleter will match entered -// text only at the beginning of strings in the -// autocomplete array. Defaults to true, which will -// match text at the beginning of any *word* in the -// strings in the autocomplete array. If you want to -// search anywhere in the string, additionally set -// the option fullSearch to true (default: off). -// -// - fullSsearch - Search anywhere in autocomplete array strings. -// -// - partialChars - How many characters to enter before triggering -// a partial match (unlike minChars, which defines -// how many characters are required to do any match -// at all). Defaults to 2. -// -// - ignoreCase - Whether to ignore case when autocompleting. -// Defaults to true. -// -// It's possible to pass in a custom function as the 'selector' -// option, if you prefer to write your own autocompletion logic. -// In that case, the other options above will not apply unless -// you support them. - -Autocompleter.Local = Class.create(Autocompleter.Base, { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("
  • " + elem.substr(0, entry.length) + "" + - elem.substr(entry.length) + "
  • "); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("
  • " + elem.substr(0, foundPos) + "" + - elem.substr(foundPos, entry.length) + "" + elem.substr( - foundPos + entry.length) + "
  • "); - break; - } - } - - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); - return "
      " + ret.join('') + "
    "; - } - }, options || { }); - } -}); - -// AJAX in-place editor and collection editor -// Full rewrite by Christophe Porteneuve (April 2007). - -// Use this if you notice weird scrolling problems on some browsers, -// the DOM might be a bit confused when this gets called so do this -// waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); -}; - -Ajax.InPlaceEditor = Class.create({ - initialize: function(element, url, options) { - this.url = url; - this.element = element = $(element); - this.prepareOptions(); - this._controls = { }; - arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! - Object.extend(this.options, options || { }); - if (!this.options.formId && this.element.id) { - this.options.formId = this.element.id + '-inplaceeditor'; - if ($(this.options.formId)) - this.options.formId = ''; - } - if (this.options.externalControl) - this.options.externalControl = $(this.options.externalControl); - if (!this.options.externalControl) - this.options.externalControlOnly = false; - this._originalBackground = this.element.getStyle('background-color') || 'transparent'; - this.element.title = this.options.clickToEditText; - this._boundCancelHandler = this.handleFormCancellation.bind(this); - this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); - this._boundFailureHandler = this.handleAJAXFailure.bind(this); - this._boundSubmitHandler = this.handleFormSubmission.bind(this); - this._boundWrapperHandler = this.wrapUp.bind(this); - this.registerListeners(); - }, - checkForEscapeOrReturn: function(e) { - if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; - if (Event.KEY_ESC == e.keyCode) - this.handleFormCancellation(e); - else if (Event.KEY_RETURN == e.keyCode) - this.handleFormSubmission(e); - }, - createControl: function(mode, handler, extraClasses) { - var control = this.options[mode + 'Control']; - var text = this.options[mode + 'Text']; - if ('button' == control) { - var btn = document.createElement('input'); - btn.type = 'submit'; - btn.value = text; - btn.className = 'editor_' + mode + '_button'; - if ('cancel' == mode) - btn.onclick = this._boundCancelHandler; - this._form.appendChild(btn); - this._controls[mode] = btn; - } else if ('link' == control) { - var link = document.createElement('a'); - link.href = '#'; - link.appendChild(document.createTextNode(text)); - link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; - link.className = 'editor_' + mode + '_link'; - if (extraClasses) - link.className += ' ' + extraClasses; - this._form.appendChild(link); - this._controls[mode] = link; - } - }, - createEditField: function() { - var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); - var fld; - if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { - fld = document.createElement('input'); - fld.type = 'text'; - var size = this.options.size || this.options.cols || 0; - if (0 < size) fld.size = size; - } else { - fld = document.createElement('textarea'); - fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); - fld.cols = this.options.cols || 40; - } - fld.name = this.options.paramName; - fld.value = text; // No HTML breaks conversion anymore - fld.className = 'editor_field'; - if (this.options.submitOnBlur) - fld.onblur = this._boundSubmitHandler; - this._controls.editor = fld; - if (this.options.loadTextURL) - this.loadExternalText(); - this._form.appendChild(this._controls.editor); - }, - createForm: function() { - var ipe = this; - function addText(mode, condition) { - var text = ipe.options['text' + mode + 'Controls']; - if (!text || condition === false) return; - ipe._form.appendChild(document.createTextNode(text)); - }; - this._form = $(document.createElement('form')); - this._form.id = this.options.formId; - this._form.addClassName(this.options.formClassName); - this._form.onsubmit = this._boundSubmitHandler; - this.createEditField(); - if ('textarea' == this._controls.editor.tagName.toLowerCase()) - this._form.appendChild(document.createElement('br')); - if (this.options.onFormCustomization) - this.options.onFormCustomization(this, this._form); - addText('Before', this.options.okControl || this.options.cancelControl); - this.createControl('ok', this._boundSubmitHandler); - addText('Between', this.options.okControl && this.options.cancelControl); - this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); - addText('After', this.options.okControl || this.options.cancelControl); - }, - destroy: function() { - if (this._oldInnerHTML) - this.element.innerHTML = this._oldInnerHTML; - this.leaveEditMode(); - this.unregisterListeners(); - }, - enterEditMode: function(e) { - if (this._saving || this._editing) return; - this._editing = true; - this.triggerCallback('onEnterEditMode'); - if (this.options.externalControl) - this.options.externalControl.hide(); - this.element.hide(); - this.createForm(); - this.element.parentNode.insertBefore(this._form, this.element); - if (!this.options.loadTextURL) - this.postProcessEditField(); - if (e) Event.stop(e); - }, - enterHover: function(e) { - if (this.options.hoverClassName) - this.element.addClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onEnterHover'); - }, - getText: function() { - return this.element.innerHTML.unescapeHTML(); - }, - handleAJAXFailure: function(transport) { - this.triggerCallback('onFailure', transport); - if (this._oldInnerHTML) { - this.element.innerHTML = this._oldInnerHTML; - this._oldInnerHTML = null; - } - }, - handleFormCancellation: function(e) { - this.wrapUp(); - if (e) Event.stop(e); - }, - handleFormSubmission: function(e) { - var form = this._form; - var value = $F(this._controls.editor); - this.prepareSubmission(); - var params = this.options.callback(form, value) || ''; - if (Object.isString(params)) - params = params.toQueryParams(); - params.editorId = this.element.id; - if (this.options.htmlResponse) { - var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Updater({ success: this.element }, this.url, options); - } else { - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.url, options); - } - if (e) Event.stop(e); - }, - leaveEditMode: function() { - this.element.removeClassName(this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - if (this.options.externalControl) - this.options.externalControl.show(); - this._saving = false; - this._editing = false; - this._oldInnerHTML = null; - this.triggerCallback('onLeaveEditMode'); - }, - leaveHover: function(e) { - if (this.options.hoverClassName) - this.element.removeClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onLeaveHover'); - }, - loadExternalText: function() { - this._form.addClassName(this.options.loadingClassName); - this._controls.editor.disabled = true; - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._form.removeClassName(this.options.loadingClassName); - var text = transport.responseText; - if (this.options.stripLoadedTextTags) - text = text.stripTags(); - this._controls.editor.value = text; - this._controls.editor.disabled = false; - this.postProcessEditField(); - }.bind(this), - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - postProcessEditField: function() { - var fpc = this.options.fieldPostCreation; - if (fpc) - $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); - }, - prepareOptions: function() { - this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); - Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); - [this._extraDefaultOptions].flatten().compact().each(function(defs) { - Object.extend(this.options, defs); - }.bind(this)); - }, - prepareSubmission: function() { - this._saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - registerListeners: function() { - this._listeners = { }; - var listener; - $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { - listener = this[pair.value].bind(this); - this._listeners[pair.key] = listener; - if (!this.options.externalControlOnly) - this.element.observe(pair.key, listener); - if (this.options.externalControl) - this.options.externalControl.observe(pair.key, listener); - }.bind(this)); - }, - removeForm: function() { - if (!this._form) return; - this._form.remove(); - this._form = null; - this._controls = { }; - }, - showSaving: function() { - this._oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - this.element.addClassName(this.options.savingClassName); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - }, - triggerCallback: function(cbName, arg) { - if ('function' == typeof this.options[cbName]) { - this.options[cbName](this, arg); - } - }, - unregisterListeners: function() { - $H(this._listeners).each(function(pair) { - if (!this.options.externalControlOnly) - this.element.stopObserving(pair.key, pair.value); - if (this.options.externalControl) - this.options.externalControl.stopObserving(pair.key, pair.value); - }.bind(this)); - }, - wrapUp: function(transport) { - this.leaveEditMode(); - // Can't use triggerCallback due to backward compatibility: requires - // binding + direct element - this._boundComplete(transport, this.element); - } -}); - -Object.extend(Ajax.InPlaceEditor.prototype, { - dispose: Ajax.InPlaceEditor.prototype.destroy -}); - -Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { - initialize: function($super, element, url, options) { - this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; - $super(element, url, options); - }, - - createEditField: function() { - var list = document.createElement('select'); - list.name = this.options.paramName; - list.size = 1; - this._controls.editor = list; - this._collection = this.options.collection || []; - if (this.options.loadCollectionURL) - this.loadCollection(); - else - this.checkForExternalText(); - this._form.appendChild(this._controls.editor); - }, - - loadCollection: function() { - this._form.addClassName(this.options.loadingClassName); - this.showLoadingText(this.options.loadingCollectionText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - var js = transport.responseText.strip(); - if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check - throw('Server returned an invalid collection representation.'); - this._collection = eval(js); - this.checkForExternalText(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadCollectionURL, options); - }, - - showLoadingText: function(text) { - this._controls.editor.disabled = true; - var tempOption = this._controls.editor.firstChild; - if (!tempOption) { - tempOption = document.createElement('option'); - tempOption.value = ''; - this._controls.editor.appendChild(tempOption); - tempOption.selected = true; - } - tempOption.update((text || '').stripScripts().stripTags()); - }, - - checkForExternalText: function() { - this._text = this.getText(); - if (this.options.loadTextURL) - this.loadExternalText(); - else - this.buildOptionList(); - }, - - loadExternalText: function() { - this.showLoadingText(this.options.loadingText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._text = transport.responseText.strip(); - this.buildOptionList(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - - buildOptionList: function() { - this._form.removeClassName(this.options.loadingClassName); - this._collection = this._collection.map(function(entry) { - return 2 === entry.length ? entry : [entry, entry].flatten(); - }); - var marker = ('value' in this.options) ? this.options.value : this._text; - var textFound = this._collection.any(function(entry) { - return entry[0] == marker; - }.bind(this)); - this._controls.editor.update(''); - var option; - this._collection.each(function(entry, index) { - option = document.createElement('option'); - option.value = entry[0]; - option.selected = textFound ? entry[0] == marker : 0 == index; - option.appendChild(document.createTextNode(entry[1])); - this._controls.editor.appendChild(option); - }.bind(this)); - this._controls.editor.disabled = false; - Field.scrollFreeActivate(this._controls.editor); - } -}); - -//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** -//**** This only exists for a while, in order to let **** -//**** users adapt to the new API. Read up on the new **** -//**** API and convert your code to it ASAP! **** - -Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { - if (!options) return; - function fallback(name, expr) { - if (name in options || expr === undefined) return; - options[name] = expr; - }; - fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : - options.cancelLink == options.cancelButton == false ? false : undefined))); - fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : - options.okLink == options.okButton == false ? false : undefined))); - fallback('highlightColor', options.highlightcolor); - fallback('highlightEndColor', options.highlightendcolor); -}; - -Object.extend(Ajax.InPlaceEditor, { - DefaultOptions: { - ajaxOptions: { }, - autoRows: 3, // Use when multi-line w/ rows == 1 - cancelControl: 'link', // 'link'|'button'|false - cancelText: 'cancel', - clickToEditText: 'Click to edit', - externalControl: null, // id|elt - externalControlOnly: false, - fieldPostCreation: 'activate', // 'activate'|'focus'|false - formClassName: 'inplaceeditor-form', - formId: null, // id|elt - highlightColor: '#ffff99', - highlightEndColor: '#ffffff', - hoverClassName: '', - htmlResponse: true, - loadingClassName: 'inplaceeditor-loading', - loadingText: 'Loading...', - okControl: 'button', // 'link'|'button'|false - okText: 'ok', - paramName: 'value', - rows: 1, // If 1 and multi-line, uses autoRows - savingClassName: 'inplaceeditor-saving', - savingText: 'Saving...', - size: 0, - stripLoadedTextTags: false, - submitOnBlur: false, - textAfterControls: '', - textBeforeControls: '', - textBetweenControls: '' - }, - DefaultCallbacks: { - callback: function(form) { - return Form.serialize(form); - }, - onComplete: function(transport, element) { - // For backward compatibility, this one is bound to the IPE, and passes - // the element directly. It was too often customized, so we don't break it. - new Effect.Highlight(element, { - startcolor: this.options.highlightColor, keepBackgroundImage: true }); - }, - onEnterEditMode: null, - onEnterHover: function(ipe) { - ipe.element.style.backgroundColor = ipe.options.highlightColor; - if (ipe._effect) - ipe._effect.cancel(); - }, - onFailure: function(transport, ipe) { - alert('Error communication with the server: ' + transport.responseText.stripTags()); - }, - onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. - onLeaveEditMode: null, - onLeaveHover: function(ipe) { - ipe._effect = new Effect.Highlight(ipe.element, { - startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, - restorecolor: ipe._originalBackground, keepBackgroundImage: true - }); - } - }, - Listeners: { - click: 'enterEditMode', - keydown: 'checkForEscapeOrReturn', - mouseover: 'enterHover', - mouseout: 'leaveHover' - } -}); - -Ajax.InPlaceCollectionEditor.DefaultOptions = { - loadingCollectionText: 'Loading options...' -}; - -// Delayed observer, like Form.Element.Observer, -// but waits for delay after last key input -// Ideal for live-search fields - -Form.Element.DelayedObserver = Class.create({ - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } -}); \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/public/javascripts/dragdrop.js b/railties/lib/rails/generators/rails/app/templates/public/javascripts/dragdrop.js deleted file mode 100644 index 15c6dbca68..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/public/javascripts/dragdrop.js +++ /dev/null @@ -1,974 +0,0 @@ -// 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/ - -if(Object.isUndefined(Effect)) - throw("dragdrop.js requires including script.aculo.us' effects.js library"); - -var Droppables = { - drops: [], - - remove: function(element) { - this.drops = this.drops.reject(function(d) { return d.element==$(element) }); - }, - - add: function(element) { - element = $(element); - var options = Object.extend({ - greedy: true, - hoverclass: null, - tree: false - }, arguments[1] || { }); - - // cache containers - if(options.containment) { - options._containers = []; - var containment = options.containment; - if(Object.isArray(containment)) { - containment.each( function(c) { options._containers.push($(c)) }); - } else { - options._containers.push($(containment)); - } - } - - if(options.accept) options.accept = [options.accept].flatten(); - - Element.makePositioned(element); // fix IE - options.element = element; - - this.drops.push(options); - }, - - findDeepestChild: function(drops) { - deepest = drops[0]; - - for (i = 1; i < drops.length; ++i) - if (Element.isParent(drops[i].element, deepest.element)) - deepest = drops[i]; - - return deepest; - }, - - isContained: function(element, drop) { - var containmentNode; - if(drop.tree) { - containmentNode = element.treeNode; - } else { - containmentNode = element.parentNode; - } - return drop._containers.detect(function(c) { return containmentNode == c }); - }, - - isAffected: function(point, element, drop) { - return ( - (drop.element!=element) && - ((!drop._containers) || - this.isContained(element, drop)) && - ((!drop.accept) || - (Element.classNames(element).detect( - function(v) { return drop.accept.include(v) } ) )) && - Position.within(drop.element, point[0], point[1]) ); - }, - - deactivate: function(drop) { - if(drop.hoverclass) - Element.removeClassName(drop.element, drop.hoverclass); - this.last_active = null; - }, - - activate: function(drop) { - if(drop.hoverclass) - Element.addClassName(drop.element, drop.hoverclass); - this.last_active = drop; - }, - - show: function(point, element) { - if(!this.drops.length) return; - var drop, affected = []; - - this.drops.each( function(drop) { - if(Droppables.isAffected(point, element, drop)) - affected.push(drop); - }); - - if(affected.length>0) - drop = Droppables.findDeepestChild(affected); - - if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); - if (drop) { - Position.within(drop.element, point[0], point[1]); - if(drop.onHover) - drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); - - if (drop != this.last_active) Droppables.activate(drop); - } - }, - - fire: function(event, element) { - if(!this.last_active) return; - Position.prepare(); - - if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) - if (this.last_active.onDrop) { - this.last_active.onDrop(element, this.last_active.element, event); - return true; - } - }, - - reset: function() { - if(this.last_active) - this.deactivate(this.last_active); - } -}; - -var Draggables = { - drags: [], - observers: [], - - register: function(draggable) { - if(this.drags.length == 0) { - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.updateDrag.bindAsEventListener(this); - this.eventKeypress = this.keyPress.bindAsEventListener(this); - - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - Event.observe(document, "keypress", this.eventKeypress); - } - this.drags.push(draggable); - }, - - unregister: function(draggable) { - this.drags = this.drags.reject(function(d) { return d==draggable }); - if(this.drags.length == 0) { - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - Event.stopObserving(document, "keypress", this.eventKeypress); - } - }, - - activate: function(draggable) { - if(draggable.options.delay) { - this._timeout = setTimeout(function() { - Draggables._timeout = null; - window.focus(); - Draggables.activeDraggable = draggable; - }.bind(this), draggable.options.delay); - } else { - window.focus(); // allows keypress events if window isn't currently focused, fails for Safari - this.activeDraggable = draggable; - } - }, - - deactivate: function() { - this.activeDraggable = null; - }, - - updateDrag: function(event) { - if(!this.activeDraggable) return; - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - // Mozilla-based browsers fire successive mousemove events with - // the same coordinates, prevent needless redrawing (moz bug?) - if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; - this._lastPointer = pointer; - - this.activeDraggable.updateDrag(event, pointer); - }, - - endDrag: function(event) { - if(this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } - if(!this.activeDraggable) return; - this._lastPointer = null; - this.activeDraggable.endDrag(event); - this.activeDraggable = null; - }, - - keyPress: function(event) { - if(this.activeDraggable) - this.activeDraggable.keyPress(event); - }, - - addObserver: function(observer) { - this.observers.push(observer); - this._cacheObserverCallbacks(); - }, - - removeObserver: function(element) { // element instead of observer fixes mem leaks - this.observers = this.observers.reject( function(o) { return o.element==element }); - this._cacheObserverCallbacks(); - }, - - notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' - if(this[eventName+'Count'] > 0) - this.observers.each( function(o) { - if(o[eventName]) o[eventName](eventName, draggable, event); - }); - if(draggable.options[eventName]) draggable.options[eventName](draggable, event); - }, - - _cacheObserverCallbacks: function() { - ['onStart','onEnd','onDrag'].each( function(eventName) { - Draggables[eventName+'Count'] = Draggables.observers.select( - function(o) { return o[eventName]; } - ).length; - }); - } -}; - -/*--------------------------------------------------------------------------*/ - -var Draggable = Class.create({ - initialize: function(element) { - var defaults = { - handle: false, - reverteffect: function(element, top_offset, left_offset) { - var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; - new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, - queue: {scope:'_draggable', position:'end'} - }); - }, - endeffect: function(element) { - var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; - new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, - queue: {scope:'_draggable', position:'end'}, - afterFinish: function(){ - Draggable._dragging[element] = false - } - }); - }, - zindex: 1000, - revert: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } - delay: 0 - }; - - if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) - Object.extend(defaults, { - starteffect: function(element) { - element._opacity = Element.getOpacity(element); - Draggable._dragging[element] = true; - new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); - } - }); - - var options = Object.extend(defaults, arguments[1] || { }); - - this.element = $(element); - - if(options.handle && Object.isString(options.handle)) - this.handle = this.element.down('.'+options.handle, 0); - - if(!this.handle) this.handle = $(options.handle); - if(!this.handle) this.handle = this.element; - - if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { - options.scroll = $(options.scroll); - this._isScrollChild = Element.childOf(this.element, options.scroll); - } - - Element.makePositioned(this.element); // fix IE - - this.options = options; - this.dragging = false; - - this.eventMouseDown = this.initDrag.bindAsEventListener(this); - Event.observe(this.handle, "mousedown", this.eventMouseDown); - - Draggables.register(this); - }, - - destroy: function() { - Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); - Draggables.unregister(this); - }, - - currentDelta: function() { - return([ - parseInt(Element.getStyle(this.element,'left') || '0'), - parseInt(Element.getStyle(this.element,'top') || '0')]); - }, - - initDrag: function(event) { - if(!Object.isUndefined(Draggable._dragging[this.element]) && - Draggable._dragging[this.element]) return; - if(Event.isLeftClick(event)) { - // abort on form elements, fixes a Firefox issue - var src = Event.element(event); - if((tag_name = src.tagName.toUpperCase()) && ( - tag_name=='INPUT' || - tag_name=='SELECT' || - tag_name=='OPTION' || - tag_name=='BUTTON' || - tag_name=='TEXTAREA')) return; - - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = this.element.cumulativeOffset(); - this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); - - Draggables.activate(this); - Event.stop(event); - } - }, - - startDrag: function(event) { - this.dragging = true; - if(!this.delta) - this.delta = this.currentDelta(); - - if(this.options.zindex) { - this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); - this.element.style.zIndex = this.options.zindex; - } - - if(this.options.ghosting) { - this._clone = this.element.cloneNode(true); - this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); - if (!this._originallyAbsolute) - Position.absolutize(this.element); - this.element.parentNode.insertBefore(this._clone, this.element); - } - - if(this.options.scroll) { - if (this.options.scroll == window) { - var where = this._getWindowScroll(this.options.scroll); - this.originalScrollLeft = where.left; - this.originalScrollTop = where.top; - } else { - this.originalScrollLeft = this.options.scroll.scrollLeft; - this.originalScrollTop = this.options.scroll.scrollTop; - } - } - - Draggables.notify('onStart', this, event); - - if(this.options.starteffect) this.options.starteffect(this.element); - }, - - updateDrag: function(event, pointer) { - if(!this.dragging) this.startDrag(event); - - if(!this.options.quiet){ - Position.prepare(); - Droppables.show(pointer, this.element); - } - - Draggables.notify('onDrag', this, event); - - this.draw(pointer); - if(this.options.change) this.options.change(this); - - if(this.options.scroll) { - this.stopScrolling(); - - var p; - if (this.options.scroll == window) { - with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } - } else { - p = Position.page(this.options.scroll); - p[0] += this.options.scroll.scrollLeft + Position.deltaX; - p[1] += this.options.scroll.scrollTop + Position.deltaY; - p.push(p[0]+this.options.scroll.offsetWidth); - p.push(p[1]+this.options.scroll.offsetHeight); - } - var speed = [0,0]; - if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); - if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); - if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); - if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); - this.startScrolling(speed); - } - - // fix AppleWebKit rendering - if(Prototype.Browser.WebKit) window.scrollBy(0,0); - - Event.stop(event); - }, - - finishDrag: function(event, success) { - this.dragging = false; - - if(this.options.quiet){ - Position.prepare(); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - Droppables.show(pointer, this.element); - } - - if(this.options.ghosting) { - if (!this._originallyAbsolute) - Position.relativize(this.element); - delete this._originallyAbsolute; - Element.remove(this._clone); - this._clone = null; - } - - var dropped = false; - if(success) { - dropped = Droppables.fire(event, this.element); - if (!dropped) dropped = false; - } - if(dropped && this.options.onDropped) this.options.onDropped(this.element); - Draggables.notify('onEnd', this, event); - - var revert = this.options.revert; - if(revert && Object.isFunction(revert)) revert = revert(this.element); - - var d = this.currentDelta(); - if(revert && this.options.reverteffect) { - if (dropped == 0 || revert != 'failure') - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); - } else { - this.delta = d; - } - - if(this.options.zindex) - this.element.style.zIndex = this.originalZ; - - if(this.options.endeffect) - this.options.endeffect(this.element); - - Draggables.deactivate(this); - Droppables.reset(); - }, - - keyPress: function(event) { - if(event.keyCode!=Event.KEY_ESC) return; - this.finishDrag(event, false); - Event.stop(event); - }, - - endDrag: function(event) { - if(!this.dragging) return; - this.stopScrolling(); - this.finishDrag(event, true); - Event.stop(event); - }, - - draw: function(point) { - 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; - } - - var d = this.currentDelta(); - pos[0] -= d[0]; pos[1] -= d[1]; - - if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { - pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; - pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; - } - - var p = [0,1].map(function(i){ - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - if(this.options.snap) { - if(Object.isFunction(this.options.snap)) { - p = this.options.snap(p[0],p[1],this); - } else { - if(Object.isArray(this.options.snap)) { - p = p.map( function(v, i) { - return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); - } else { - p = p.map( function(v) { - return (v/this.options.snap).round()*this.options.snap }.bind(this)); - } - }} - - var style = this.element.style; - if((!this.options.constraint) || (this.options.constraint=='horizontal')) - style.left = p[0] + "px"; - if((!this.options.constraint) || (this.options.constraint=='vertical')) - style.top = p[1] + "px"; - - if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering - }, - - stopScrolling: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - Draggables._lastScrollPointer = null; - } - }, - - startScrolling: function(speed) { - if(!(speed[0] || speed[1])) return; - this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; - this.lastScrolled = new Date(); - this.scrollInterval = setInterval(this.scroll.bind(this), 10); - }, - - scroll: function() { - var current = new Date(); - var delta = current - this.lastScrolled; - this.lastScrolled = current; - if(this.options.scroll == window) { - with (this._getWindowScroll(this.options.scroll)) { - if (this.scrollSpeed[0] || this.scrollSpeed[1]) { - var d = delta / 1000; - this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); - } - } - } else { - this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; - this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; - } - - Position.prepare(); - Droppables.show(Draggables._lastPointer, this.element); - Draggables.notify('onDrag', this); - if (this._isScrollChild) { - Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); - Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; - Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; - if (Draggables._lastScrollPointer[0] < 0) - Draggables._lastScrollPointer[0] = 0; - if (Draggables._lastScrollPointer[1] < 0) - Draggables._lastScrollPointer[1] = 0; - this.draw(Draggables._lastScrollPointer); - } - - if(this.options.change) this.options.change(this); - }, - - _getWindowScroll: function(w) { - var T, L, W, H; - with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { - T = documentElement.scrollTop; - L = documentElement.scrollLeft; - } else if (w.document.body) { - T = body.scrollTop; - L = body.scrollLeft; - } - if (w.innerWidth) { - W = w.innerWidth; - H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { - W = documentElement.clientWidth; - H = documentElement.clientHeight; - } else { - W = body.offsetWidth; - H = body.offsetHeight; - } - } - return { top: T, left: L, width: W, height: H }; - } -}); - -Draggable._dragging = { }; - -/*--------------------------------------------------------------------------*/ - -var SortableObserver = Class.create({ - initialize: function(element, observer) { - this.element = $(element); - this.observer = observer; - this.lastValue = Sortable.serialize(this.element); - }, - - onStart: function() { - this.lastValue = Sortable.serialize(this.element); - }, - - onEnd: function() { - Sortable.unmark(); - if(this.lastValue != Sortable.serialize(this.element)) - this.observer(this.element) - } -}); - -var Sortable = { - SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, - - sortables: { }, - - _findRootElement: function(element) { - while (element.tagName.toUpperCase() != "BODY") { - if(element.id && Sortable.sortables[element.id]) return element; - element = element.parentNode; - } - }, - - options: function(element) { - element = Sortable._findRootElement($(element)); - if(!element) return; - return Sortable.sortables[element.id]; - }, - - destroy: function(element){ - element = $(element); - var s = Sortable.sortables[element.id]; - - if(s) { - Draggables.removeObserver(s.element); - s.droppables.each(function(d){ Droppables.remove(d) }); - s.draggables.invoke('destroy'); - - delete Sortable.sortables[s.element.id]; - } - }, - - create: function(element) { - element = $(element); - var options = Object.extend({ - element: element, - tag: 'li', // assumes li children, override with tag: 'tagname' - dropOnEmpty: false, - tree: false, - treeTag: 'ul', - overlap: 'vertical', // one of 'vertical', 'horizontal' - constraint: 'vertical', // one of 'vertical', 'horizontal', false - containment: element, // also takes array of elements (or id's); or false - handle: false, // or a CSS class - only: false, - delay: 0, - hoverclass: null, - ghosting: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - format: this.SERIALIZE_RULE, - - // these take arrays of elements or ids and can be - // used for better initialization performance - elements: false, - handles: false, - - onChange: Prototype.emptyFunction, - onUpdate: Prototype.emptyFunction - }, arguments[1] || { }); - - // clear any old sortable with same element - this.destroy(element); - - // build options for the draggables - var options_for_draggable = { - revert: true, - quiet: options.quiet, - scroll: options.scroll, - scrollSpeed: options.scrollSpeed, - scrollSensitivity: options.scrollSensitivity, - delay: options.delay, - ghosting: options.ghosting, - constraint: options.constraint, - handle: options.handle }; - - if(options.starteffect) - options_for_draggable.starteffect = options.starteffect; - - if(options.reverteffect) - options_for_draggable.reverteffect = options.reverteffect; - else - if(options.ghosting) options_for_draggable.reverteffect = function(element) { - element.style.top = 0; - element.style.left = 0; - }; - - if(options.endeffect) - options_for_draggable.endeffect = options.endeffect; - - if(options.zindex) - options_for_draggable.zindex = options.zindex; - - // build options for the droppables - var options_for_droppable = { - overlap: options.overlap, - containment: options.containment, - tree: options.tree, - hoverclass: options.hoverclass, - onHover: Sortable.onHover - }; - - var options_for_tree = { - onHover: Sortable.onEmptyHover, - overlap: options.overlap, - containment: options.containment, - hoverclass: options.hoverclass - }; - - // fix for gecko engine - Element.cleanWhitespace(element); - - options.draggables = []; - options.droppables = []; - - // drop on empty handling - if(options.dropOnEmpty || options.tree) { - Droppables.add(element, options_for_tree); - options.droppables.push(element); - } - - (options.elements || this.findElements(element, options) || []).each( function(e,i) { - var handle = options.handles ? $(options.handles[i]) : - (options.handle ? $(e).select('.' + options.handle)[0] : e); - options.draggables.push( - new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); - Droppables.add(e, options_for_droppable); - if(options.tree) e.treeNode = element; - options.droppables.push(e); - }); - - if(options.tree) { - (Sortable.findTreeElements(element, options) || []).each( function(e) { - Droppables.add(e, options_for_tree); - e.treeNode = element; - options.droppables.push(e); - }); - } - - // keep reference - this.sortables[element.identify()] = options; - - // for onupdate - Draggables.addObserver(new SortableObserver(element, options.onUpdate)); - - }, - - // return all suitable-for-sortable elements in a guaranteed order - findElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.tag); - }, - - findTreeElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.treeTag); - }, - - onHover: function(element, dropon, overlap) { - if(Element.isParent(dropon, element)) return; - - if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { - return; - } else if(overlap>0.5) { - Sortable.mark(dropon, 'before'); - if(dropon.previousSibling != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, dropon); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } else { - Sortable.mark(dropon, 'after'); - var nextElement = dropon.nextSibling || null; - if(nextElement != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, nextElement); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } - }, - - onEmptyHover: function(element, dropon, overlap) { - var oldParentNode = element.parentNode; - var droponOptions = Sortable.options(dropon); - - if(!Element.isParent(dropon, element)) { - var index; - - var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); - var child = null; - - if(children) { - var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); - - for (index = 0; index < children.length; index += 1) { - if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { - offset -= Element.offsetSize (children[index], droponOptions.overlap); - } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { - child = index + 1 < children.length ? children[index + 1] : null; - break; - } else { - child = children[index]; - break; - } - } - } - - dropon.insertBefore(element, child); - - Sortable.options(oldParentNode).onChange(element); - droponOptions.onChange(element); - } - }, - - unmark: function() { - if(Sortable._marker) Sortable._marker.hide(); - }, - - mark: function(dropon, position) { - // mark on ghosting only - var sortable = Sortable.options(dropon.parentNode); - if(sortable && !sortable.ghosting) return; - - if(!Sortable._marker) { - Sortable._marker = - ($('dropmarker') || Element.extend(document.createElement('DIV'))). - hide().addClassName('dropmarker').setStyle({position:'absolute'}); - document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); - } - var offsets = dropon.cumulativeOffset(); - Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); - - if(position=='after') - if(sortable.overlap == 'horizontal') - Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); - else - Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); - - Sortable._marker.show(); - }, - - _tree: function(element, options, parent) { - var children = Sortable.findElements(element, options) || []; - - for (var i = 0; i < children.length; ++i) { - var match = children[i].id.match(options.format); - - if (!match) continue; - - var child = { - id: encodeURIComponent(match ? match[1] : null), - element: element, - parent: parent, - children: [], - position: parent.children.length, - container: $(children[i]).down(options.treeTag) - }; - - /* Get the element containing the children and recurse over it */ - if (child.container) - this._tree(child.container, options, child); - - parent.children.push (child); - } - - return parent; - }, - - tree: function(element) { - element = $(element); - var sortableOptions = this.options(element); - var options = Object.extend({ - tag: sortableOptions.tag, - treeTag: sortableOptions.treeTag, - only: sortableOptions.only, - name: element.id, - format: sortableOptions.format - }, arguments[1] || { }); - - var root = { - id: null, - parent: null, - children: [], - container: element, - position: 0 - }; - - return Sortable._tree(element, options, root); - }, - - /* Construct a [i] index for a particular node */ - _constructIndex: function(node) { - var index = ''; - do { - if (node.id) index = '[' + node.position + ']' + index; - } while ((node = node.parent) != null); - return index; - }, - - sequence: function(element) { - element = $(element); - var options = Object.extend(this.options(element), arguments[1] || { }); - - return $(this.findElements(element, options) || []).map( function(item) { - return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; - }); - }, - - setSequence: function(element, new_sequence) { - element = $(element); - var options = Object.extend(this.options(element), arguments[2] || { }); - - var nodeMap = { }; - this.findElements(element, options).each( function(n) { - if (n.id.match(options.format)) - nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; - n.parentNode.removeChild(n); - }); - - new_sequence.each(function(ident) { - var n = nodeMap[ident]; - if (n) { - n[1].appendChild(n[0]); - delete nodeMap[ident]; - } - }); - }, - - serialize: function(element) { - element = $(element); - var options = Object.extend(Sortable.options(element), arguments[1] || { }); - var name = encodeURIComponent( - (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); - - if (options.tree) { - return Sortable.tree(element, arguments[1]).children.map( function (item) { - return [name + Sortable._constructIndex(item) + "[id]=" + - encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); - }).flatten().join('&'); - } else { - return Sortable.sequence(element, arguments[1]).map( function(item) { - return name + "[]=" + encodeURIComponent(item); - }).join('&'); - } - } -}; - -// Returns true if child is contained within element -Element.isParent = function(child, element) { - if (!child.parentNode || child == element) return false; - if (child.parentNode == element) return true; - return Element.isParent(child.parentNode, element); -}; - -Element.findChildren = function(element, only, recursive, tagName) { - if(!element.hasChildNodes()) return null; - tagName = tagName.toUpperCase(); - if(only) only = [only].flatten(); - var elements = []; - $A(element.childNodes).each( function(e) { - if(e.tagName && e.tagName.toUpperCase()==tagName && - (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) - elements.push(e); - if(recursive) { - var grandchildren = Element.findChildren(e, only, recursive, tagName); - if(grandchildren) elements.push(grandchildren); - } - }); - - return (elements.length>0 ? elements.flatten() : []); -}; - -Element.offsetSize = function (element, type) { - return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; -}; \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/public/javascripts/effects.js b/railties/lib/rails/generators/rails/app/templates/public/javascripts/effects.js deleted file mode 100644 index c81e6c7d5f..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/public/javascripts/effects.js +++ /dev/null @@ -1,1123 +0,0 @@ -// 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/) -// Martin Bialasinki -// -// 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/ - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if (this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if (this.slice(0,1) == '#') { - if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if (this.length==7) color = this.toLowerCase(); - } - } - return (color.length==7 ? color : (arguments[0] || this)); -}; - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -}; - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -}; - -Element.setContentZoom = function(element, percent) { - element = $(element); - element.setStyle({fontSize: (percent/100) + 'em'}); - if (Prototype.Browser.WebKit) window.scrollBy(0,0); - return element; -}; - -Element.getInlineOpacity = function(element){ - return $(element).style.opacity || ''; -}; - -Element.forceRerendering = function(element) { - try { - element = $(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -var Effect = { - _elementDoesNotExistError: { - name: 'ElementDoesNotExistError', - message: 'The specified DOM element does not exist, but is required for this effect to operate' - }, - Transitions: { - linear: Prototype.K, - sinoidal: function(pos) { - return (-Math.cos(pos*Math.PI)/2) + .5; - }, - reverse: function(pos) { - return 1-pos; - }, - flicker: function(pos) { - var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; - return pos > 1 ? 1 : pos; - }, - wobble: function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; - }, - pulse: function(pos, pulses) { - return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; - }, - spring: function(pos) { - return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); - }, - none: function(pos) { - return 0; - }, - full: function(pos) { - return 1; - } - }, - DefaultOptions: { - duration: 1.0, // seconds - fps: 100, // 100= assume 66fps max. - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' - }, - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; - - element = $(element); - $A(element.childNodes).each( function(child) { - if (child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - new Element('span', {style: tagifyStyle}).update( - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if (((typeof element == 'object') || - Object.isFunction(element)) && - (element.length)) - elements = element; - else - elements = $(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || { }); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect, options) { - element = $(element); - 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 } - }, options || {})); - } -}; - -Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; - -/* ------------- core effects ------------- */ - -Effect.ScopedQueue = Class.create(Enumerable, { - initialize: function() { - this.effects = []; - this.interval = null; - }, - _each: function(iterator) { - this.effects._each(iterator); - }, - add: function(effect) { - var timestamp = new Date().getTime(); - - var position = Object.isString(effect.options.queue) ? - effect.options.queue : effect.options.queue.position; - - switch(position) { - case 'front': - // move unstarted effects after this effect - this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { - e.startOn += effect.finishOn; - e.finishOn += effect.finishOn; - }); - break; - case 'with-last': - timestamp = this.effects.pluck('startOn').max() || timestamp; - break; - case 'end': - // start effect after last queued effect has finished - timestamp = this.effects.pluck('finishOn').max() || timestamp; - break; - } - - effect.startOn += timestamp; - effect.finishOn += timestamp; - - if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) - this.effects.push(effect); - - if (!this.interval) - this.interval = setInterval(this.loop.bind(this), 15); - }, - remove: function(effect) { - this.effects = this.effects.reject(function(e) { return e==effect }); - if (this.effects.length == 0) { - clearInterval(this.interval); - this.interval = null; - } - }, - loop: function() { - var timePos = new Date().getTime(); - for(var i=0, len=this.effects.length;i= this.startOn) { - if (timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if (this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / this.totalTime, - frame = (pos * this.totalFrames).round(); - if (frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - cancel: function() { - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if (this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - var data = $H(); - for(property in this) - if (!Object.isFunction(this[property])) data.set(property, this[property]); - return '#'; - } -}); - -Effect.Parallel = Class.create(Effect.Base, { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if (effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Tween = Class.create(Effect.Base, { - initialize: function(object, from, to) { - object = Object.isString(object) ? $(object) : object; - var args = $A(arguments), method = args.last(), - options = args.length == 5 ? args[3] : null; - this.method = Object.isFunction(method) ? method.bind(object) : - Object.isFunction(object[method]) ? object[method].bind(object) : - function(value) { object[method] = value }; - this.start(Object.extend({ from: from, to: to }, options || { })); - }, - update: function(position) { - this.method(position); - } -}); - -Effect.Event = Class.create(Effect.Base, { - initialize: function() { - this.start(Object.extend({ duration: 0 }, arguments[0] || { })); - }, - update: Prototype.emptyFunction -}); - -Effect.Opacity = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - // make this work on IE on elements without 'layout' - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || { }); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if (this.options.mode == 'absolute') { - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: (this.options.x * position + this.originalLeft).round() + 'px', - top: (this.options.y * position + this.originalTop).round() + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); -}; - -Effect.Scale = Class.create(Effect.Base, { - initialize: function(element, percent) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or { } with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || { }); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = { }; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%','pt'].each( function(fontSizeType) { - if (fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if (this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if (/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if (!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if (this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = { }; - if (this.options.scaleX) d.width = width.round() + 'px'; - if (this.options.scaleY) d.height = height.round() + 'px'; - if (this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if (this.elementPositioning == 'absolute') { - if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if (this.options.scaleY) d.top = -topd + 'px'; - if (this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if (this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { }; - if (!this.options.keepBackgroundImage) { - this.oldStyle.backgroundImage = this.element.getStyle('background-image'); - this.element.setStyle({backgroundImage: 'none'}); - } - if (!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if (!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = function(element) { - var options = arguments[1] || { }, - scrollOffsets = document.viewport.getScrollOffsets(), - elementOffsets = $(element).cumulativeOffset(); - - if (options.offset) elementOffsets[1] += options.offset; - - return new Effect.Tween(null, - scrollOffsets.top, - elementOffsets[1], - options, - function(p){ scrollTo(scrollOffsets.left, p.round()); } - ); -}; - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if (effect.options.to!=0) return; - effect.element.hide().setStyle({opacity: oldOpacity}); - } - }, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Appear = function(element) { - element = $(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from).show(); - }}, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Puff = function(element) { - element = $(element); - var oldStyle = { - opacity: element.getInlineOpacity(), - position: element.getStyle('position'), - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height - }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - Position.absolutize(effect.effects[0].element); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().setStyle(oldStyle); } - }, arguments[1] || { }) - ); -}; - -Effect.BlindUp = function(element) { - element = $(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }, arguments[1] || { }) - ); -}; - -Effect.BlindDown = function(element) { - element = $(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || { })); -}; - -Effect.SwitchOff = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, Object.extend({ - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); - } - }); - } - }, arguments[1] || { })); -}; - -Effect.DropOut = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); - } - }, arguments[1] || { })); -}; - -Effect.Shake = function(element) { - element = $(element); - var options = Object.extend({ - distance: 20, - duration: 0.5 - }, arguments[1] || {}); - var distance = parseFloat(options.distance); - var split = parseFloat(options.duration) / 10.0; - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { - effect.element.undoPositioned().setStyle(oldStyle); - }}); }}); }}); }}); }}); }}); -}; - -Effect.SlideDown = function(element) { - element = $(element).cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || { }) - ); -}; - -Effect.SlideUp = function(element) { - element = $(element).cleanWhitespace(); - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); - } - }, arguments[1] || { }) - ); -}; - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, { - restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }); -}; - -Effect.Grow = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide().makeClipping().makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); - } - }, options) - ); - } - }); -}; - -Effect.Shrink = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } - }, options) - ); -}; - -Effect.Pulsate = function(element) { - element = $(element); - var options = arguments[1] || { }, - oldOpacity = element.getInlineOpacity(), - transition = options.transition || Effect.Transitions.linear, - reverser = function(pos){ - return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); - }; - - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 2.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -}; - -Effect.Fold = function(element) { - element = $(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - element.makeClipping(); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().setStyle(oldStyle); - } }); - }}, arguments[1] || { })); -}; - -Effect.Morph = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - style: { } - }, arguments[1] || { }); - - if (!Object.isString(options.style)) this.style = $H(options.style); - else { - if (options.style.include(':')) - this.style = options.style.parseStyle(); - else { - this.element.addClassName(options.style); - this.style = $H(this.element.getStyles()); - this.element.removeClassName(options.style); - var css = this.element.getStyles(); - this.style = this.style.reject(function(style) { - return style.value == css[style.key]; - }); - options.afterFinishInternal = function(effect) { - effect.element.addClassName(effect.options.style); - effect.transforms.each(function(transform) { - effect.element.style[transform.style] = ''; - }); - }; - } - } - this.start(options); - }, - - setup: function(){ - function parseColor(color){ - if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; - color = color.parseColor(); - return $R(0,2).map(function(i){ - return parseInt( color.slice(i*2+1,i*2+3), 16 ); - }); - } - this.transforms = this.style.map(function(pair){ - var property = pair[0], value = pair[1], unit = null; - - if (value.parseColor('#zzzzzz') != '#zzzzzz') { - value = value.parseColor(); - unit = 'color'; - } else if (property == 'opacity') { - value = parseFloat(value); - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - } else if (Element.CSS_LENGTH.test(value)) { - var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); - value = parseFloat(components[1]); - unit = (components.length == 3) ? components[2] : null; - } - - var originalValue = this.element.getStyle(property); - return { - style: property.camelize(), - originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), - targetValue: unit=='color' ? parseColor(value) : value, - unit: unit - }; - }.bind(this)).reject(function(transform){ - return ( - (transform.originalValue == transform.targetValue) || - ( - transform.unit != 'color' && - (isNaN(transform.originalValue) || isNaN(transform.targetValue)) - ) - ); - }); - }, - update: function(position) { - var style = { }, transform, i = this.transforms.length; - while(i--) - style[(transform = this.transforms[i]).style] = - transform.unit=='color' ? '#'+ - (Math.round(transform.originalValue[0]+ - (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + - (Math.round(transform.originalValue[1]+ - (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + - (Math.round(transform.originalValue[2]+ - (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : - (transform.originalValue + - (transform.targetValue - transform.originalValue) * position).toFixed(3) + - (transform.unit === null ? '' : transform.unit); - this.element.setStyle(style, true); - } -}); - -Effect.Transform = Class.create({ - initialize: function(tracks){ - this.tracks = []; - this.options = arguments[1] || { }; - this.addTracks(tracks); - }, - addTracks: function(tracks){ - tracks.each(function(track){ - track = $H(track); - var data = track.values().first(); - this.tracks.push($H({ - ids: track.keys().first(), - effect: Effect.Morph, - options: { style: data } - })); - }.bind(this)); - return this; - }, - play: function(){ - return new Effect.Parallel( - this.tracks.map(function(track){ - var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); - var elements = [$(ids) || $$(ids)].flatten(); - return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); - }).flatten(), - this.options - ); - } -}); - -Element.CSS_PROPERTIES = $w( - 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + - 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + - 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + - 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + - 'fontSize fontWeight height left letterSpacing lineHeight ' + - 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ - 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + - 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + - 'right textIndent top width wordSpacing zIndex'); - -Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; - -String.__parseStyleElement = document.createElement('div'); -String.prototype.parseStyle = function(){ - var style, styleRules = $H(); - if (Prototype.Browser.WebKit) - style = new Element('div',{style:this}).style; - else { - String.__parseStyleElement.innerHTML = '
    '; - style = String.__parseStyleElement.childNodes[0].style; - } - - Element.CSS_PROPERTIES.each(function(property){ - if (style[property]) styleRules.set(property, style[property]); - }); - - if (Prototype.Browser.IE && this.include('opacity')) - styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); - - return styleRules; -}; - -if (document.defaultView && document.defaultView.getComputedStyle) { - Element.getStyles = function(element) { - var css = document.defaultView.getComputedStyle($(element), null); - return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { - styles[property] = css[property]; - return styles; - }); - }; -} else { - Element.getStyles = function(element) { - element = $(element); - var css = element.currentStyle, styles; - styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { - results[property] = css[property]; - return results; - }); - if (!styles.opacity) styles.opacity = element.getOpacity(); - return styles; - }; -} - -Effect.Methods = { - morph: function(element, style) { - element = $(element); - new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); - return element; - }, - visualEffect: function(element, effect, options) { - element = $(element); - var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[klass](element, options); - return element; - }, - highlight: function(element, options) { - element = $(element); - new Effect.Highlight(element, options); - return element; - } -}; - -$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ - 'pulsate shake puff squish switchOff dropOut').each( - function(effect) { - Effect.Methods[effect] = function(element, options){ - element = $(element); - Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); - return element; - }; - } -); - -$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( - function(f) { Effect.Methods[f] = Element[f]; } -); - -Element.addMethods(Effect.Methods); \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/app/templates/public/javascripts/jquery.js b/railties/lib/rails/generators/rails/app/templates/public/javascripts/jquery.js deleted file mode 100644 index aa3a4f34fd..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/public/javascripts/jquery.js +++ /dev/null @@ -1,8176 +0,0 @@ -/*! - * jQuery JavaScript Library v1.5 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Mon Jan 31 08:31:29 2011 -0500 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document; -var jQuery = (function() { - -// Define a local copy of jQuery -var jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // A central reference to the root jQuery(document) - rootjQuery, - - // A simple way to check for HTML strings or ID strings - // (both of which we optimize for) - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Check for digits - rdigit = /\d/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Keep a UserAgent string for use with jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // Has the ready events already been bound? - readyBound = false, - - // The deferred used on DOM ready - readyList, - - // Promise methods - promiseMethods = "then done fail isResolved isRejected promise".split( " " ), - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = "body"; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - match = quickExpr.exec( selector ); - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = (context ? context.ownerDocument || context : document); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; - } - - return jQuery.merge( this, selector ); - - // HANDLE: $("#id") - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return (context || rootjQuery).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if (selector.selector !== undefined) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.5", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return slice.call( this, 0 ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = this.constructor(); - - if ( jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - jQuery.merge( ret, elems ); - } - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + (this.selector ? " " : "") + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Attach the listeners - jQuery.bindReady(); - - // Add the callback - readyList.done( fn ); - - return this; - }, - - eq: function( i ) { - return i === -1 ? - this.slice( i ) : - this.slice( i, +i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ), - "slice", slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - window.$ = _$; - - if ( deep ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - // A third-party is pushing the ready event forwards - if ( wait === true ) { - jQuery.readyWait--; - } - - // Make sure that the DOM is not already loaded - if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger( "ready" ).unbind( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyBound ) { - return; - } - - readyBound = true; - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent("onreadystatechange", DOMContentLoaded); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - // A crude way of determining if an object is a window - isWindow: function( obj ) { - return obj && typeof obj === "object" && "setInterval" in obj; - }, - - isNaN: function( obj ) { - return obj == null || !rdigit.test( obj ) || isNaN( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw msg; - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test(data.replace(rvalidescape, "@") - .replace(rvalidtokens, "]") - .replace(rvalidbraces, "")) ) { - - // Try to use the native JSON parser first - return window.JSON && window.JSON.parse ? - window.JSON.parse( data ) : - (new Function("return " + data))(); - - } else { - jQuery.error( "Invalid JSON: " + data ); - } - }, - - // Cross-browser xml parsing - // (xml & tmp used internally) - parseXML: function( data , xml , tmp ) { - - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - - tmp = xml.documentElement; - - if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { - jQuery.error( "Invalid XML: " + data ); - } - - return xml; - }, - - noop: function() {}, - - // Evalulates a script in a global context - globalEval: function( data ) { - if ( data && rnotwhite.test(data) ) { - // Inspired by code by Andrea Giammarchi - // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html - var head = document.getElementsByTagName("head")[0] || document.documentElement, - script = document.createElement("script"); - - script.type = "text/javascript"; - - if ( jQuery.support.scriptEval() ) { - script.appendChild( document.createTextNode( data ) ); - } else { - script.text = data; - } - - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709). - head.insertBefore( script, head.firstChild ); - head.removeChild( script ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || jQuery.isFunction(object); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( var value = object[0]; - i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // The extra typeof function check is to prevent crashes - // in Safari 2 (See: #3039) - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type(array); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array ) { - if ( array.indexOf ) { - return array.indexOf( elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var ret = [], value; - - // Go through the array, translating each of the items to their - // new value (or values). - for ( var i = 0, length = elems.length; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - proxy: function( fn, proxy, thisObject ) { - if ( arguments.length === 2 ) { - if ( typeof proxy === "string" ) { - thisObject = fn; - fn = thisObject[ proxy ]; - proxy = undefined; - - } else if ( proxy && !jQuery.isFunction( proxy ) ) { - thisObject = proxy; - proxy = undefined; - } - } - - if ( !proxy && fn ) { - proxy = function() { - return fn.apply( thisObject || this, arguments ); - }; - } - - // Set the guid of unique handler to the same of original handler, so it can be removed - if ( fn ) { - proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; - } - - // So proxy can be declared as an argument - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can be optionally by executed if its a function - access: function( elems, key, value, exec, fn, pass ) { - var length = elems.length; - - // Setting many attributes - if ( typeof key === "object" ) { - for ( var k in key ) { - jQuery.access( elems, k, key[k], exec, fn, value ); - } - return elems; - } - - // Setting one attribute - if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = !pass && exec && jQuery.isFunction(value); - - for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - - return elems; - } - - // Getting an attribute - return length ? fn( elems[0], key ) : undefined; - }, - - now: function() { - return (new Date()).getTime(); - }, - - // Create a simple deferred (one callbacks list) - _Deferred: function() { - var // callbacks list - callbacks = [], - // stored [ context , args ] - fired, - // to avoid firing when already doing so - firing, - // flag to know if the deferred has been cancelled - cancelled, - // the deferred itself - deferred = { - - // done( f1, f2, ...) - done: function() { - if ( !cancelled ) { - var args = arguments, - i, - length, - elem, - type, - _fired; - if ( fired ) { - _fired = fired; - fired = 0; - } - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - deferred.done.apply( deferred, elem ); - } else if ( type === "function" ) { - callbacks.push( elem ); - } - } - if ( _fired ) { - deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); - } - } - return this; - }, - - // resolve with given context and args - resolveWith: function( context, args ) { - if ( !cancelled && !fired && !firing ) { - firing = 1; - try { - while( callbacks[ 0 ] ) { - callbacks.shift().apply( context, args ); - } - } - finally { - fired = [ context, args ]; - firing = 0; - } - } - return this; - }, - - // resolve with this as context and given arguments - resolve: function() { - deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); - return this; - }, - - // Has this deferred been resolved? - isResolved: function() { - return !!( firing || fired ); - }, - - // Cancel - cancel: function() { - cancelled = 1; - callbacks = []; - return this; - } - }; - - return deferred; - }, - - // Full fledged deferred (two callbacks list) - Deferred: function( func ) { - var deferred = jQuery._Deferred(), - failDeferred = jQuery._Deferred(), - promise; - // Add errorDeferred methods, then and promise - jQuery.extend( deferred, { - then: function( doneCallbacks, failCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ); - return this; - }, - fail: failDeferred.done, - rejectWith: failDeferred.resolveWith, - reject: failDeferred.resolve, - isRejected: failDeferred.isResolved, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj , i /* internal */ ) { - if ( obj == null ) { - if ( promise ) { - return promise; - } - promise = obj = {}; - } - i = promiseMethods.length; - while( i-- ) { - obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ]; - } - return obj; - } - } ); - // Make sure only one callback list will be used - deferred.then( failDeferred.cancel, deferred.cancel ); - // Unexpose cancel - delete deferred.cancel; - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - return deferred; - }, - - // Deferred helper - when: function( object ) { - var args = arguments, - length = args.length, - deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ? - object : - jQuery.Deferred(), - promise = deferred.promise(), - resolveArray; - - if ( length > 1 ) { - resolveArray = new Array( length ); - jQuery.each( args, function( index, element ) { - jQuery.when( element ).then( function( value ) { - resolveArray[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; - if( ! --length ) { - deferred.resolveWith( promise, resolveArray ); - } - }, deferred.reject ); - } ); - } else if ( deferred !== object ) { - deferred.resolve( object ); - } - return promise; - }, - - // Use of jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - sub: function() { - function jQuerySubclass( selector, context ) { - return new jQuerySubclass.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySubclass, this ); - jQuerySubclass.superclass = this; - jQuerySubclass.fn = jQuerySubclass.prototype = this(); - jQuerySubclass.fn.constructor = jQuerySubclass; - jQuerySubclass.subclass = this.subclass; - jQuerySubclass.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { - context = jQuerySubclass(context); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); - }; - jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; - var rootjQuerySubclass = jQuerySubclass(document); - return jQuerySubclass; - }, - - browser: {} -}); - -// Create readyList deferred -readyList = jQuery._Deferred(); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - jQuery.browser[ browserMatch.browser ] = true; - jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use jQuery.browser.webkit instead -if ( jQuery.browser.webkit ) { - jQuery.browser.safari = true; -} - -if ( indexOf ) { - jQuery.inArray = function( elem, array ) { - return indexOf.call( array, elem ); - }; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - jQuery.ready(); -} - -// Expose jQuery to the global object -return (window.jQuery = window.$ = jQuery); - -})(); - - -(function() { - - jQuery.support = {}; - - var div = document.createElement("div"); - - div.style.display = "none"; - div.innerHTML = "
    a"; - - var all = div.getElementsByTagName("*"), - a = div.getElementsByTagName("a")[0], - select = document.createElement("select"), - opt = select.appendChild( document.createElement("option") ); - - // Can't get basic test support - if ( !all || !all.length || !a ) { - return; - } - - jQuery.support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: div.firstChild.nodeType === 3, - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText insted) - style: /red/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: a.getAttribute("href") === "/a", - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.55$/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: div.getElementsByTagName("input")[0].value === "on", - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Will be defined later - deleteExpando: true, - optDisabled: false, - checkClone: false, - _scriptEval: null, - noCloneEvent: true, - boxModel: null, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableHiddenOffsets: true - }; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as diabled) - select.disabled = true; - jQuery.support.optDisabled = !opt.disabled; - - jQuery.support.scriptEval = function() { - if ( jQuery.support._scriptEval === null ) { - var root = document.documentElement, - script = document.createElement("script"), - id = "script" + jQuery.now(); - - script.type = "text/javascript"; - try { - script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); - } catch(e) {} - - root.insertBefore( script, root.firstChild ); - - // Make sure that the execution of code works by injecting a script - // tag with appendChild/createTextNode - // (IE doesn't support this, fails, and uses .text instead) - if ( window[ id ] ) { - jQuery.support._scriptEval = true; - delete window[ id ]; - } else { - jQuery.support._scriptEval = false; - } - - root.removeChild( script ); - // release memory in IE - root = script = id = null; - } - - return jQuery.support._scriptEval; - }; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - - } catch(e) { - jQuery.support.deleteExpando = false; - } - - if ( div.attachEvent && div.fireEvent ) { - div.attachEvent("onclick", function click() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - jQuery.support.noCloneEvent = false; - div.detachEvent("onclick", click); - }); - div.cloneNode(true).fireEvent("onclick"); - } - - div = document.createElement("div"); - div.innerHTML = ""; - - var fragment = document.createDocumentFragment(); - fragment.appendChild( div.firstChild ); - - // WebKit doesn't clone checked state correctly in fragments - jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; - - // Figure out if the W3C box model works as expected - // document.body must exist before we can do this - jQuery(function() { - var div = document.createElement("div"), - body = document.getElementsByTagName("body")[0]; - - // Frameset documents with no body should not run this code - if ( !body ) { - return; - } - - div.style.width = div.style.paddingLeft = "1px"; - body.appendChild( div ); - jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; - - if ( "zoom" in div.style ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.style.display = "inline"; - div.style.zoom = 1; - jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = ""; - div.innerHTML = "
    "; - jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; - } - - div.innerHTML = "
    t
    "; - var tds = div.getElementsByTagName("td"); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; - - tds[0].style.display = ""; - tds[1].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE < 8 fail this test) - jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; - div.innerHTML = ""; - - body.removeChild( div ).style.display = "none"; - div = tds = null; - }); - - // Technique from Juriy Zaytsev - // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ - var eventSupported = function( eventName ) { - var el = document.createElement("div"); - eventName = "on" + eventName; - - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( !el.attachEvent ) { - return true; - } - - var isSupported = (eventName in el); - if ( !isSupported ) { - el.setAttribute(eventName, "return;"); - isSupported = typeof el[eventName] === "function"; - } - el = null; - - return isSupported; - }; - - jQuery.support.submitBubbles = eventSupported("submit"); - jQuery.support.changeBubbles = eventSupported("change"); - - // release memory in IE - div = all = a = null; -})(); - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/; - -jQuery.extend({ - cache: {}, - - // Please use with caution - uuid: 0, - - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - - return !!elem && !jQuery.isEmptyObject(elem); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ jQuery.expando ] = id = ++jQuery.uuid; - } else { - id = jQuery.expando; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" ) { - if ( pvt ) { - cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); - } else { - cache[ id ] = jQuery.extend(cache[ id ], name); - } - } - - thisCache = cache[ id ]; - - // Internal jQuery data is stored in a separate object inside the object's data - // cache in order to avoid key collisions between internal data and user-defined - // data - if ( pvt ) { - if ( !thisCache[ internalKey ] ) { - thisCache[ internalKey ] = {}; - } - - thisCache = thisCache[ internalKey ]; - } - - if ( data !== undefined ) { - thisCache[ name ] = data; - } - - // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should - // not attempt to inspect the internal events object using jQuery.data, as this - // internal data object is undocumented and subject to change. - if ( name === "events" && !thisCache[name] ) { - return thisCache[ internalKey ] && thisCache[ internalKey ].events; - } - - return getByName ? thisCache[ name ] : thisCache; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - - // See jQuery.data for more information - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; - - if ( thisCache ) { - delete thisCache[ name ]; - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !jQuery.isEmptyObject(thisCache) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( pvt ) { - delete cache[ id ][ internalKey ]; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !jQuery.isEmptyObject(cache[ id ]) ) { - return; - } - } - - var internalCache = cache[ id ][ internalKey ]; - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - if ( jQuery.support.deleteExpando || cache != window ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the entire user cache at once because it's faster than - // iterating through each key, but we need to continue to persist internal - // data if it existed - if ( internalCache ) { - cache[ id ] = {}; - cache[ id ][ internalKey ] = internalCache; - - // Otherwise, we need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - } else if ( isNode ) { - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( jQuery.support.deleteExpando ) { - delete elem[ jQuery.expando ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( jQuery.expando ); - } else { - elem[ jQuery.expando ] = null; - } - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - if ( elem.nodeName ) { - var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var data = null; - - if ( typeof key === "undefined" ) { - if ( this.length ) { - data = jQuery.data( this[0] ); - - if ( this[0].nodeType === 1 ) { - var attr = this[0].attributes, name; - for ( var i = 0, l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = name.substr( 5 ); - dataAttr( this[0], name, data[ name ] ); - } - } - } - } - - return data; - - } else if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - var parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - // Try to fetch any internally stored data first - if ( data === undefined && this.length ) { - data = jQuery.data( this[0], key ); - data = dataAttr( this[0], key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - - } else { - return this.each(function() { - var $this = jQuery( this ), - args = [ parts[0], value ]; - - $this.triggerHandler( "setData" + parts[1] + "!", args ); - jQuery.data( this, key, value ); - $this.triggerHandler( "changeData" + parts[1] + "!", args ); - }); - } - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - data = elem.getAttribute( "data-" + key ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - !jQuery.isNaN( data ) ? parseFloat( data ) : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - - - - -jQuery.extend({ - queue: function( elem, type, data ) { - if ( !elem ) { - return; - } - - type = (type || "fx") + "queue"; - var q = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( !data ) { - return q || []; - } - - if ( !q || jQuery.isArray(data) ) { - q = jQuery._data( elem, type, jQuery.makeArray(data) ); - - } else { - q.push( data ); - } - - return q; - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - fn = queue.shift(); - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift("inprogress"); - } - - fn.call(elem, function() { - jQuery.dequeue(elem, type); - }); - } - - if ( !queue.length ) { - jQuery.removeData( elem, type + "queue", true ); - } - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) { - return jQuery.queue( this[0], type ); - } - return this.each(function( i ) { - var queue = jQuery.queue( this, type, data ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; - type = type || "fx"; - - return this.queue( type, function() { - var elem = this; - setTimeout(function() { - jQuery.dequeue( elem, type ); - }, time ); - }); - }, - - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspaces = /\s+/, - rreturn = /\r/g, - rspecialurl = /^(?:href|src|style)$/, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea)?$/i, - rradiocheck = /^(?:radio|checkbox)$/i; - -jQuery.props = { - "for": "htmlFor", - "class": "className", - readonly: "readOnly", - maxlength: "maxLength", - cellspacing: "cellSpacing", - rowspan: "rowSpan", - colspan: "colSpan", - tabindex: "tabIndex", - usemap: "useMap", - frameborder: "frameBorder" -}; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.attr ); - }, - - removeAttr: function( name, fn ) { - return this.each(function(){ - jQuery.attr( this, name, "" ); - if ( this.nodeType === 1 ) { - this.removeAttribute( name ); - } - }); - }, - - addClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.addClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( value && typeof value === "string" ) { - var classNames = (value || "").split( rspaces ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className ) { - elem.className = value; - - } else { - var className = " " + elem.className + " ", - setClass = elem.className; - - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { - setClass += " " + classNames[c]; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.removeClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - var classNames = (value || "").split( rspaces ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - var className = (" " + elem.className + " ").replace(rclass, " "); - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[c] + " ", " "); - } - elem.className = jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this); - self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( rspaces ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " "; - for ( var i = 0, l = this.length; i < l; i++ ) { - if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - if ( !arguments.length ) { - var elem = this[0]; - - if ( elem ) { - if ( jQuery.nodeName( elem, "option" ) ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - - // We need to handle select boxes special - if ( jQuery.nodeName( elem, "select" ) ) { - var index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery(option).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - } - - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { - return elem.getAttribute("value") === null ? "on" : elem.value; - } - - // Everything else, we just grab the value - return (elem.value || "").replace(rreturn, ""); - - } - - return undefined; - } - - var isFunction = jQuery.isFunction(value); - - return this.each(function(i) { - var self = jQuery(this), val = value; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call(this, i, self.val()); - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray(val) ) { - val = jQuery.map(val, function (value) { - return value == null ? "" : value + ""; - }); - } - - if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { - this.checked = jQuery.inArray( self.val(), val ) >= 0; - - } else if ( jQuery.nodeName( this, "select" ) ) { - var values = jQuery.makeArray(val); - - jQuery( "option", this ).each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - this.selectedIndex = -1; - } - - } else { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attr: function( elem, name, value, pass ) { - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { - return undefined; - } - - if ( pass && name in jQuery.attrFn ) { - return jQuery(elem)[name](value); - } - - var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), - // Whether we are setting (or getting) - set = value !== undefined; - - // Try to normalize/fix the name - name = notxml && jQuery.props[ name ] || name; - - // Only do all the following if this is a node (faster for style) - if ( elem.nodeType === 1 ) { - // These attributes require special treatment - var special = rspecialurl.test( name ); - - // Safari mis-reports the default selected property of an option - // Accessing the parent's selectedIndex property fixes it - if ( name === "selected" && !jQuery.support.optSelected ) { - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - - // If applicable, access the attribute via the DOM 0 way - // 'in' checks fail in Blackberry 4.7 #6931 - if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { - if ( set ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } - - if ( value === null ) { - if ( elem.nodeType === 1 ) { - elem.removeAttribute( name ); - } - - } else { - elem[ name ] = value; - } - } - - // browsers index elements by id/name on forms, give priority to attributes. - if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { - return elem.getAttributeNode( name ).nodeValue; - } - - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - if ( name === "tabIndex" ) { - var attributeNode = elem.getAttributeNode( "tabIndex" ); - - return attributeNode && attributeNode.specified ? - attributeNode.value : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - - return elem[ name ]; - } - - if ( !jQuery.support.style && notxml && name === "style" ) { - if ( set ) { - elem.style.cssText = "" + value; - } - - return elem.style.cssText; - } - - if ( set ) { - // convert the value to a string (all browsers do this but IE) see #1070 - elem.setAttribute( name, "" + value ); - } - - // Ensure that missing attributes return undefined - // Blackberry 4.7 returns "" from getAttribute #6938 - if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { - return undefined; - } - - var attr = !jQuery.support.hrefNormalized && notxml && special ? - // Some attributes require a special call on IE - elem.getAttribute( name, 2 ) : - elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return attr === null ? undefined : attr; - } - // Handle everything which isn't a DOM element node - if ( set ) { - elem[ name ] = value; - } - return elem[ name ]; - } -}); - - - - -var rnamespaces = /\.(.*)$/, - rformElems = /^(?:textarea|input|select)$/i, - rperiod = /\./g, - rspace = / /g, - rescape = /[^\w\s.|`]/g, - fcleanup = function( nm ) { - return nm.replace(rescape, "\\$&"); - }, - eventKey = "events"; - -/* - * A number of helper functions used for managing events. - * Many of the ideas behind this code originated from - * Dean Edwards' addEvent library. - */ -jQuery.event = { - - // Bind an event to an element - // Original by Dean Edwards - add: function( elem, types, handler, data ) { - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // For whatever reason, IE has trouble passing the window object - // around, causing it to be cloned in the process - if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { - elem = window; - } - - if ( handler === false ) { - handler = returnFalse; - } else if ( !handler ) { - // Fixes bug #7229. Fix recommended by jdalton - return; - } - - var handleObjIn, handleObj; - - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - } - - // Make sure that the function being executed has a unique ID - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure - var elemData = jQuery._data( elem ); - - // If no elemData is found then we must be trying to bind to one of the - // banned noData elements - if ( !elemData ) { - return; - } - - var events = elemData[ eventKey ], - eventHandle = elemData.handle; - - if ( typeof events === "function" ) { - // On plain objects events is a fn that holds the data - // which prevents this data from being JSON serialized - // the function does not need to be called, it just contains the data - eventHandle = events.handle; - events = events.events; - - } else if ( !events ) { - if ( !elem.nodeType ) { - // On plain objects, create a fn that acts as the holder - // of the values to avoid JSON serialization of event data - elemData[ eventKey ] = elemData = function(){}; - } - - elemData.events = events = {}; - } - - if ( !eventHandle ) { - elemData.handle = eventHandle = function() { - // Handle the second event of a trigger and when - // an event is called after a page has unloaded - return typeof jQuery !== "undefined" && !jQuery.event.triggered ? - jQuery.event.handle.apply( eventHandle.elem, arguments ) : - undefined; - }; - } - - // Add elem as a property of the handle function - // This is to prevent a memory leak with non-native events in IE. - eventHandle.elem = elem; - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = types.split(" "); - - var type, i = 0, namespaces; - - while ( (type = types[ i++ ]) ) { - handleObj = handleObjIn ? - jQuery.extend({}, handleObjIn) : - { handler: handler, data: data }; - - // Namespaced event handlers - if ( type.indexOf(".") > -1 ) { - namespaces = type.split("."); - type = namespaces.shift(); - handleObj.namespace = namespaces.slice(0).sort().join("."); - - } else { - namespaces = []; - handleObj.namespace = ""; - } - - handleObj.type = type; - if ( !handleObj.guid ) { - handleObj.guid = handler.guid; - } - - // Get the current list of functions bound to this event - var handlers = events[ type ], - special = jQuery.event.special[ type ] || {}; - - // Init the event handler queue - if ( !handlers ) { - handlers = events[ type ] = []; - - // Check for a special event handler - // Only use addEventListener/attachEvent if the special - // events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add the function to the element's handler list - handlers.push( handleObj ); - - // Keep track of which events have been used, for global triggering - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, pos ) { - // don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - if ( handler === false ) { - handler = returnFalse; - } - - var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ), - events = elemData && elemData[ eventKey ]; - - if ( !elemData || !events ) { - return; - } - - if ( typeof events === "function" ) { - elemData = events; - events = events.events; - } - - // types is actually an event object here - if ( types && types.type ) { - handler = types.handler; - types = types.type; - } - - // Unbind all events for the element - if ( !types || typeof types === "string" && types.charAt(0) === "." ) { - types = types || ""; - - for ( type in events ) { - jQuery.event.remove( elem, type + types ); - } - - return; - } - - // Handle multiple events separated by a space - // jQuery(...).unbind("mouseover mouseout", fn); - types = types.split(" "); - - while ( (type = types[ i++ ]) ) { - origType = type; - handleObj = null; - all = type.indexOf(".") < 0; - namespaces = []; - - if ( !all ) { - // Namespaced event handlers - namespaces = type.split("."); - type = namespaces.shift(); - - namespace = new RegExp("(^|\\.)" + - jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - eventType = events[ type ]; - - if ( !eventType ) { - continue; - } - - if ( !handler ) { - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( all || namespace.test( handleObj.namespace ) ) { - jQuery.event.remove( elem, origType, handleObj.handler, j ); - eventType.splice( j--, 1 ); - } - } - - continue; - } - - special = jQuery.event.special[ type ] || {}; - - for ( j = pos || 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( handler.guid === handleObj.guid ) { - // remove the given handler for the given type - if ( all || namespace.test( handleObj.namespace ) ) { - if ( pos == null ) { - eventType.splice( j--, 1 ); - } - - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - - if ( pos != null ) { - break; - } - } - } - - // remove generic event handler if no more handlers exist - if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - ret = null; - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - var handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - delete elemData.events; - delete elemData.handle; - - if ( typeof elemData === "function" ) { - jQuery.removeData( elem, eventKey, true ); - - } else if ( jQuery.isEmptyObject( elemData ) ) { - jQuery.removeData( elem, undefined, true ); - } - } - }, - - // bubbling is internal - trigger: function( event, data, elem /*, bubbling */ ) { - // Event object or event type - var type = event.type || event, - bubbling = arguments[3]; - - if ( !bubbling ) { - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - jQuery.extend( jQuery.Event(type), event ) : - // Just the event type (string) - jQuery.Event(type); - - if ( type.indexOf("!") >= 0 ) { - event.type = type = type.slice(0, -1); - event.exclusive = true; - } - - // Handle a global trigger - if ( !elem ) { - // Don't bubble custom events when global (to avoid too much overhead) - event.stopPropagation(); - - // Only trigger if we've ever bound an event for it - if ( jQuery.event.global[ type ] ) { - // XXX This code smells terrible. event.js should not be directly - // inspecting the data cache - jQuery.each( jQuery.cache, function() { - // internalKey variable is just used to make it easier to find - // and potentially change this stuff later; currently it just - // points to jQuery.expando - var internalKey = jQuery.expando, - internalCache = this[ internalKey ]; - if ( internalCache && internalCache.events && internalCache.events[type] ) { - jQuery.event.trigger( event, data, internalCache.handle.elem ); - } - }); - } - } - - // Handle triggering a single element - - // don't do events on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { - return undefined; - } - - // Clean up in case it is reused - event.result = undefined; - event.target = elem; - - // Clone the incoming data, if any - data = jQuery.makeArray( data ); - data.unshift( event ); - } - - event.currentTarget = elem; - - // Trigger the event, it is assumed that "handle" is a function - var handle = elem.nodeType ? - jQuery._data( elem, "handle" ) : - (jQuery._data( elem, eventKey ) || {}).handle; - - if ( handle ) { - handle.apply( elem, data ); - } - - var parent = elem.parentNode || elem.ownerDocument; - - // Trigger an inline bound script - try { - if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { - if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { - event.result = false; - event.preventDefault(); - } - } - - // prevent IE from throwing an error for some elements with some event types, see #3533 - } catch (inlineError) {} - - if ( !event.isPropagationStopped() && parent ) { - jQuery.event.trigger( event, data, parent, true ); - - } else if ( !event.isDefaultPrevented() ) { - var old, - target = event.target, - targetType = type.replace( rnamespaces, "" ), - isClick = jQuery.nodeName( target, "a" ) && targetType === "click", - special = jQuery.event.special[ targetType ] || {}; - - if ( (!special._default || special._default.call( elem, event ) === false) && - !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { - - try { - if ( target[ targetType ] ) { - // Make sure that we don't accidentally re-trigger the onFOO events - old = target[ "on" + targetType ]; - - if ( old ) { - target[ "on" + targetType ] = null; - } - - jQuery.event.triggered = true; - target[ targetType ](); - } - - // prevent IE from throwing an error for some elements with some event types, see #3533 - } catch (triggerError) {} - - if ( old ) { - target[ "on" + targetType ] = old; - } - - jQuery.event.triggered = false; - } - } - }, - - handle: function( event ) { - var all, handlers, namespaces, namespace_re, events, - namespace_sort = [], - args = jQuery.makeArray( arguments ); - - event = args[0] = jQuery.event.fix( event || window.event ); - event.currentTarget = this; - - // Namespaced event handlers - all = event.type.indexOf(".") < 0 && !event.exclusive; - - if ( !all ) { - namespaces = event.type.split("."); - event.type = namespaces.shift(); - namespace_sort = namespaces.slice(0).sort(); - namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.namespace = event.namespace || namespace_sort.join("."); - - events = jQuery._data(this, eventKey); - - if ( typeof events === "function" ) { - events = events.events; - } - - handlers = (events || {})[ event.type ]; - - if ( events && handlers ) { - // Clone the handlers to prevent manipulation - handlers = handlers.slice(0); - - for ( var j = 0, l = handlers.length; j < l; j++ ) { - var handleObj = handlers[ j ]; - - // Filter the functions by class - if ( all || namespace_re.test( handleObj.namespace ) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handleObj.handler; - event.data = handleObj.data; - event.handleObj = handleObj; - - var ret = handleObj.handler.apply( this, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - } - - return event.result; - }, - - props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // store a copy of the original event object - // and "clone" to set read-only properties - var originalEvent = event; - event = jQuery.Event( originalEvent ); - - for ( var i = this.props.length, prop; i; ) { - prop = this.props[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary - if ( !event.target ) { - // Fixes #1925 where srcElement might not be defined either - event.target = event.srcElement || document; - } - - // check if target is a textnode (safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && event.fromElement ) { - event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; - } - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && event.clientX != null ) { - var doc = document.documentElement, - body = document.body; - - event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Add which for key events - if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { - event.which = event.charCode != null ? event.charCode : event.keyCode; - } - - // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) - if ( !event.metaKey && event.ctrlKey ) { - event.metaKey = event.ctrlKey; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && event.button !== undefined ) { - event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); - } - - return event; - }, - - // Deprecated, use jQuery.guid instead - guid: 1E8, - - // Deprecated, use jQuery.proxy instead - proxy: jQuery.proxy, - - special: { - ready: { - // Make sure the ready event is setup - setup: jQuery.bindReady, - teardown: jQuery.noop - }, - - live: { - add: function( handleObj ) { - jQuery.event.add( this, - liveConvert( handleObj.origType, handleObj.selector ), - jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); - }, - - remove: function( handleObj ) { - jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); - } - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - } -}; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -jQuery.Event = function( src ) { - // Allow instantiation without the 'new' keyword - if ( !this.preventDefault ) { - return new jQuery.Event( src ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // timeStamp is buggy for some events on Firefox(#3843) - // So we won't rely on the native value - this.timeStamp = jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Checks if an event happened on an element within another element -// Used in jQuery.event.special.mouseenter and mouseleave handlers -var withinElement = function( event ) { - // Check if mouse(over|out) are still within the same parent element - var parent = event.relatedTarget; - - // Firefox sometimes assigns relatedTarget a XUL element - // which we cannot access the parentNode property of - try { - // Traverse up the tree - while ( parent && parent !== this ) { - parent = parent.parentNode; - } - - if ( parent !== this ) { - // set the correct event type - event.type = event.data; - - // handle event if we actually just moused on to a non sub-element - jQuery.event.handle.apply( this, arguments ); - } - - // assuming we've left the element since we most likely mousedover a xul element - } catch(e) { } -}, - -// In case of event delegation, we only need to rename the event.type, -// liveHandler will take care of the rest. -delegate = function( event ) { - event.type = event.data; - jQuery.event.handle.apply( this, arguments ); -}; - -// Create mouseenter and mouseleave events -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - setup: function( data ) { - jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); - }, - teardown: function( data ) { - jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); - } - }; -}); - -// submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function( data, namespaces ) { - if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) { - jQuery.event.add(this, "click.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { - e.liveFired = undefined; - return trigger( "submit", this, arguments ); - } - }); - - jQuery.event.add(this, "keypress.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { - e.liveFired = undefined; - return trigger( "submit", this, arguments ); - } - }); - - } else { - return false; - } - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialSubmit" ); - } - }; - -} - -// change delegation, happens here so we have bind. -if ( !jQuery.support.changeBubbles ) { - - var changeFilters, - - getVal = function( elem ) { - var type = elem.type, val = elem.value; - - if ( type === "radio" || type === "checkbox" ) { - val = elem.checked; - - } else if ( type === "select-multiple" ) { - val = elem.selectedIndex > -1 ? - jQuery.map( elem.options, function( elem ) { - return elem.selected; - }).join("-") : - ""; - - } else if ( elem.nodeName.toLowerCase() === "select" ) { - val = elem.selectedIndex; - } - - return val; - }, - - testChange = function testChange( e ) { - var elem = e.target, data, val; - - if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { - return; - } - - data = jQuery._data( elem, "_change_data" ); - val = getVal(elem); - - // the current data will be also retrieved by beforeactivate - if ( e.type !== "focusout" || elem.type !== "radio" ) { - jQuery._data( elem, "_change_data", val ); - } - - if ( data === undefined || val === data ) { - return; - } - - if ( data != null || val ) { - e.type = "change"; - e.liveFired = undefined; - return jQuery.event.trigger( e, arguments[1], elem ); - } - }; - - jQuery.event.special.change = { - filters: { - focusout: testChange, - - beforedeactivate: testChange, - - click: function( e ) { - var elem = e.target, type = elem.type; - - if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { - return testChange.call( this, e ); - } - }, - - // Change has to be called before submit - // Keydown will be called before keypress, which is used in submit-event delegation - keydown: function( e ) { - var elem = e.target, type = elem.type; - - if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || - (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || - type === "select-multiple" ) { - return testChange.call( this, e ); - } - }, - - // Beforeactivate happens also before the previous element is blurred - // with this event you can't trigger a change event, but you can store - // information - beforeactivate: function( e ) { - var elem = e.target; - jQuery._data( elem, "_change_data", getVal(elem) ); - } - }, - - setup: function( data, namespaces ) { - if ( this.type === "file" ) { - return false; - } - - for ( var type in changeFilters ) { - jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); - } - - return rformElems.test( this.nodeName ); - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialChange" ); - - return rformElems.test( this.nodeName ); - } - }; - - changeFilters = jQuery.event.special.change.filters; - - // Handle when the input is .focus()'d - changeFilters.focus = changeFilters.beforeactivate; -} - -function trigger( type, elem, args ) { - args[0].type = type; - return jQuery.event.handle.apply( elem, args ); -} - -// Create "bubbling" focus and blur events -if ( document.addEventListener ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - jQuery.event.special[ fix ] = { - setup: function() { - this.addEventListener( orig, handler, true ); - }, - teardown: function() { - this.removeEventListener( orig, handler, true ); - } - }; - - function handler( e ) { - e = jQuery.event.fix( e ); - e.type = fix; - return jQuery.event.handle.call( this, e ); - } - }); -} - -jQuery.each(["bind", "one"], function( i, name ) { - jQuery.fn[ name ] = function( type, data, fn ) { - // Handle object literals - if ( typeof type === "object" ) { - for ( var key in type ) { - this[ name ](key, data, type[key], fn); - } - return this; - } - - if ( jQuery.isFunction( data ) || data === false ) { - fn = data; - data = undefined; - } - - var handler = name === "one" ? jQuery.proxy( fn, function( event ) { - jQuery( this ).unbind( event, handler ); - return fn.apply( this, arguments ); - }) : fn; - - if ( type === "unload" && name !== "one" ) { - this.one( type, data, fn ); - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.add( this[i], type, handler, data ); - } - } - - return this; - }; -}); - -jQuery.fn.extend({ - unbind: function( type, fn ) { - // Handle object literals - if ( typeof type === "object" && !type.preventDefault ) { - for ( var key in type ) { - this.unbind(key, type[key]); - } - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.remove( this[i], type, fn ); - } - } - - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.live( types, data, fn, selector ); - }, - - undelegate: function( selector, types, fn ) { - if ( arguments.length === 0 ) { - return this.unbind( "live" ); - - } else { - return this.die( types, null, fn, selector ); - } - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - - triggerHandler: function( type, data ) { - if ( this[0] ) { - var event = jQuery.Event( type ); - event.preventDefault(); - event.stopPropagation(); - jQuery.event.trigger( event, data, this[0] ); - return event.result; - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - i = 1; - - // link all the functions, so any of them can unbind this click handler - while ( i < args.length ) { - jQuery.proxy( fn, args[ i++ ] ); - } - - return this.click( jQuery.proxy( fn, function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - })); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -var liveMap = { - focus: "focusin", - blur: "focusout", - mouseenter: "mouseover", - mouseleave: "mouseout" -}; - -jQuery.each(["live", "die"], function( i, name ) { - jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { - var type, i = 0, match, namespaces, preType, - selector = origSelector || this.selector, - context = origSelector ? this : jQuery( this.context ); - - if ( typeof types === "object" && !types.preventDefault ) { - for ( var key in types ) { - context[ name ]( key, data, types[key], selector ); - } - - return this; - } - - if ( jQuery.isFunction( data ) ) { - fn = data; - data = undefined; - } - - types = (types || "").split(" "); - - while ( (type = types[ i++ ]) != null ) { - match = rnamespaces.exec( type ); - namespaces = ""; - - if ( match ) { - namespaces = match[0]; - type = type.replace( rnamespaces, "" ); - } - - if ( type === "hover" ) { - types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); - continue; - } - - preType = type; - - if ( type === "focus" || type === "blur" ) { - types.push( liveMap[ type ] + namespaces ); - type = type + namespaces; - - } else { - type = (liveMap[ type ] || type) + namespaces; - } - - if ( name === "live" ) { - // bind live handler - for ( var j = 0, l = context.length; j < l; j++ ) { - jQuery.event.add( context[j], "live." + liveConvert( type, selector ), - { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); - } - - } else { - // unbind live handler - context.unbind( "live." + liveConvert( type, selector ), fn ); - } - } - - return this; - }; -}); - -function liveHandler( event ) { - var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, - elems = [], - selectors = [], - events = jQuery._data( this, eventKey ); - - if ( typeof events === "function" ) { - events = events.events; - } - - // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) - if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { - return; - } - - if ( event.namespace ) { - namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.liveFired = this; - - var live = events.live.slice(0); - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { - selectors.push( handleObj.selector ); - - } else { - live.splice( j--, 1 ); - } - } - - match = jQuery( event.target ).closest( selectors, event.currentTarget ); - - for ( i = 0, l = match.length; i < l; i++ ) { - close = match[i]; - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) { - elem = close.elem; - related = null; - - // Those two events require additional checking - if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { - event.type = handleObj.preType; - related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; - } - - if ( !related || related !== elem ) { - elems.push({ elem: elem, handleObj: handleObj, level: close.level }); - } - } - } - } - - for ( i = 0, l = elems.length; i < l; i++ ) { - match = elems[i]; - - if ( maxLevel && match.level > maxLevel ) { - break; - } - - event.currentTarget = match.elem; - event.data = match.handleObj.data; - event.handleObj = match.handleObj; - - ret = match.handleObj.origHandler.apply( match.elem, arguments ); - - if ( ret === false || event.isPropagationStopped() ) { - maxLevel = match.level; - - if ( ret === false ) { - stop = false; - } - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - - return stop; -} - -function liveConvert( type, selector ) { - return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); -} - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.bind( name, data, fn ) : - this.trigger( name ); - }; - - if ( jQuery.attrFn ) { - jQuery.attrFn[ name ] = true; - } -}); - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var match, - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - var left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace(/\\/g, ""); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - var found, item, - filter = Expr.filter[ type ], - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw "Syntax error, unrecognized expression: " + msg; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !/\W/.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !/\W/.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !/\W/.test(part) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !/\W/.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace(/\\/g, "") + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace(/\\/g, ""); - }, - - TAG: function( match, curLoop ) { - return match[1].toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace(/\\/g, ""); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace(/\\/g, ""); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - elem.parentNode.selectedIndex; - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - return "text" === elem.type; - }, - radio: function( elem ) { - return "radio" === elem.type; - }, - - checkbox: function( elem ) { - return "checkbox" === elem.type; - }, - - file: function( elem ) { - return "file" === elem.type; - }, - password: function( elem ) { - return "password" === elem.type; - }, - - submit: function( elem ) { - return "submit" === elem.type; - }, - - image: function( elem ) { - return "image" === elem.type; - }, - - reset: function( elem ) { - return "reset" === elem.type; - }, - - button: function( elem ) { - return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - var first = match[2], - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // If the nodes are siblings (or identical) we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Utility function for retreiving the text value of an array of DOM nodes -Sizzle.getText = function( elems ) { - var ret = "", elem; - - for ( var i = 0; elems[i]; i++ ) { - elem = elems[i]; - - // Get the text from text nodes and CDATA nodes - if ( elem.nodeType === 3 || elem.nodeType === 4 ) { - ret += elem.nodeValue; - - // Traverse everything else, except comment nodes - } else if ( elem.nodeType !== 8 ) { - ret += Sizzle.getText( elem.childNodes ); - } - } - - return ret; -}; - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

    "; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - context.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - if ( matches ) { - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - return matches.call( node, expr ); - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
    "; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = jQuery.expr.match.POS, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var ret = this.pushStack( "", "find", selector ), - length = 0; - - for ( var i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( var n = length; n < ret.length; n++ ) { - for ( var r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var targets = jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && jQuery.filter( selector, this ).length > 0; - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - if ( jQuery.isArray( selectors ) ) { - var match, selector, - matches = {}, - level = 1; - - if ( cur && selectors.length ) { - for ( i = 0, l = selectors.length; i < l; i++ ) { - selector = selectors[i]; - - if ( !matches[selector] ) { - matches[selector] = jQuery.expr.match.POS.test( selector ) ? - jQuery( selector, context || this.context ) : - selector; - } - } - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( selector in matches ) { - match = matches[selector]; - - if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { - ret.push({ selector: selector, elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - } - - return ret; - } - - var pos = POS.test( selectors ) ? - jQuery( selectors, context || this.context ) : null; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context ) { - break; - } - } - } - } - - ret = ret.length > 1 ? jQuery.unique(ret) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - if ( !elem || typeof elem === "string" ) { - return jQuery.inArray( this[0], - // If it receives a string, the selector is used - // If it receives nothing, the siblings are used - elem ? jQuery( elem ) : this.parent().children() ); - } - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return jQuery.nth( elem, 2, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( elem.parentNode.firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ), - // The variable 'args' was introduced in - // https://github.com/jquery/jquery/commit/52a0238 - // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. - // http://code.google.com/p/v8/issues/detail?id=1050 - args = slice.call(arguments); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, args.join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return (elem === qualifier) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return (jQuery.inArray( elem, qualifier ) >= 0) === keep; - }); -} - - - - -var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /", "" ], - legend: [ 1, "
    ", "
    " ], - thead: [ 1, "", "
    " ], - tr: [ 2, "", "
    " ], - td: [ 3, "", "
    " ], - col: [ 2, "", "
    " ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }; - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and " + - "" - assert_equal expected, stripped_body - end - - test "default application's asset_path" do - @plugin.write "config/routes.rb", <<-RUBY - Bukkits::Engine.routes.draw do - match "/foo" => "foo#index" - end - RUBY - - @plugin.write "app/controllers/foo_controller.rb", <<-RUBY - class FooController < ActionController::Base - def index - render :inline => '<%= image_path("foo.png") %>' - end - end - RUBY - - app_file "config/routes.rb", <<-RUBY - AppTemplate::Application.routes.draw do - mount Bukkits::Engine => "/bukkits" - end - RUBY - - boot_rails - - get("/bukkits/foo") - assert_equal "/bukkits/images/foo.png", last_response.body.strip - end - - test "engine's files are served via ActionDispatch::Static" do - add_to_config "config.serve_static_assets = true" - - @plugin.write "lib/bukkits.rb", <<-RUBY - class Bukkits - class Engine < ::Rails::Engine - engine_name :bukkits - end - end - RUBY - - @plugin.write "public/bukkits.html", "/bukkits/bukkits.html" - app_file "public/app.html", "/app.html" - app_file "public/bukkits/file_from_app.html", "/bukkits/file_from_app.html" - - boot_rails - - get("/app.html") - assert_equal File.read(File.join(app_path, "public/app.html")), last_response.body - - get("/bukkits/bukkits.html") - assert_equal File.read(File.join(@plugin.path, "public/bukkits.html")), last_response.body - - get("/bukkits/file_from_app.html") - assert_equal File.read(File.join(app_path, "public/bukkits/file_from_app.html")), last_response.body - end - - test "an applications files are given priority over an engines files when served via ActionDispatch::Static" do - add_to_config "config.serve_static_assets = true" - - @plugin.write "lib/bukkits.rb", <<-RUBY - class Bukkits - class Engine < ::Rails::Engine - engine_name :bukkits - end - end - RUBY - - app_file "config/routes.rb", <<-RUBY - AppTemplate::Application.routes.draw do - mount Bukkits::Engine => "/bukkits" - end - RUBY - - @plugin.write "public/bukkits.html", "in engine" - - app_file "public/bukkits/bukkits.html", "in app" - - boot_rails - - get('/bukkits/bukkits.html') - - assert_equal 'in app', last_response.body.strip - end - - test "shared engine should include application's helpers and own helpers" do - app_file "config/routes.rb", <<-RUBY - AppTemplate::Application.routes.draw do - match "/foo" => "bukkits/foo#index", :as => "foo" - match "/foo/show" => "bukkits/foo#show" - match "/foo/bar" => "bukkits/foo#bar" - end - RUBY - - app_file "app/helpers/some_helper.rb", <<-RUBY - module SomeHelper - def something - "Something... Something... Something..." - end - end - RUBY - - @plugin.write "app/helpers/bar_helper.rb", <<-RUBY - module BarHelper - def bar - "It's a bar." - end - end - RUBY - - @plugin.write "app/controllers/bukkits/foo_controller.rb", <<-RUBY - class Bukkits::FooController < ActionController::Base - def index - render :inline => "<%= something %>" - end - - def show - render :text => foo_path - end - - def bar - render :inline => "<%= bar %>" - end - end - RUBY - - boot_rails - - get("/foo") - assert_equal "Something... Something... Something...", last_response.body - - get("/foo/show") - assert_equal "/foo", last_response.body - - get("/foo/bar") - assert_equal "It's a bar.", last_response.body - end - test "isolated engine should include only its own routes and helpers" do @plugin.write "lib/bukkits.rb", <<-RUBY module Bukkits @@ -772,71 +584,6 @@ module RailtiesTest assert_equal Bukkits::Engine.instance, Rails::Engine.find(engine_path) end - test "ensure that engine properly sets assets directories" do - add_to_config("config.action_dispatch.show_exceptions = false") - add_to_config("config.serve_static_assets = true") - add_to_config("config.assets.enabled = false") - - @plugin.write "lib/bukkits.rb", <<-RUBY - module Bukkits - class Engine < ::Rails::Engine - isolate_namespace Bukkits - end - end - RUBY - - @plugin.write "public/stylesheets/foo.css", "" - @plugin.write "public/javascripts/foo.js", "" - - @plugin.write "app/views/layouts/bukkits/application.html.erb", <<-RUBY - <%= stylesheet_link_tag :all %> - <%= javascript_include_tag :all %> - <%= yield %> - RUBY - - @plugin.write "app/controllers/bukkits/home_controller.rb", <<-RUBY - module Bukkits - class HomeController < ActionController::Base - def index - render :text => "Good morning!", :layout => "bukkits/application" - end - end - end - RUBY - - @plugin.write "config/routes.rb", <<-RUBY - Bukkits::Engine.routes.draw do - match "/home" => "home#index" - end - RUBY - - app_file "config/routes.rb", <<-RUBY - Rails.application.routes.draw do - mount Bukkits::Engine => "/bukkits" - end - RUBY - - require 'rack/test' - extend Rack::Test::Methods - - boot_rails - - require "#{rails_root}/config/environment" - - assert_equal File.join(@plugin.path, "public"), Bukkits::HomeController.assets_dir - assert_equal File.join(@plugin.path, "public/stylesheets"), Bukkits::HomeController.stylesheets_dir - assert_equal File.join(@plugin.path, "public/javascripts"), Bukkits::HomeController.javascripts_dir - - assert_equal File.join(app_path, "public"), ActionController::Base.assets_dir - assert_equal File.join(app_path, "public/stylesheets"), ActionController::Base.stylesheets_dir - assert_equal File.join(app_path, "public/javascripts"), ActionController::Base.javascripts_dir - - get "/bukkits/home" - - assert_match %r{bukkits/stylesheets/foo.css}, last_response.body - assert_match %r{bukkits/javascripts/foo.js}, last_response.body - end - private def app Rails.application diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb index 46bab2a47b..b2b18938ae 100644 --- a/railties/test/railties/shared_tests.rb +++ b/railties/test/railties/shared_tests.rb @@ -10,44 +10,6 @@ module RailtiesTest @app ||= Rails.application end - def test_install_migrations_and_assets - @plugin.write "public/javascripts/foo.js", "doSomething()" - - @plugin.write "db/migrate/1_create_users.rb", <<-RUBY - class CreateUsers < ActiveRecord::Migration - end - RUBY - - app_file "db/migrate/1_create_sessions.rb", <<-RUBY - class CreateSessions < ActiveRecord::Migration - end - RUBY - - add_to_config "ActiveRecord::Base.timestamped_migrations = false" - - Dir.chdir(app_path) do - `rake bukkits:install` - assert File.exists?("#{app_path}/db/migrate/2_create_users.rb") - assert File.exists?(app_path("public/bukkits/javascripts/foo.js")) - end - end - - def test_copying_public - @plugin.write "public/javascripts/foo.js", "doSomething()" - @plugin.write "public/stylesheets/foo.css", "h1 { font-size: 10000px }" - @plugin.write "public/images/img.png", "" - - Dir.chdir(app_path) do - `rake bukkits:install:public --trace` - - assert File.exists?(app_path("public/bukkits/javascripts/foo.js")) - assert_equal "doSomething()\n", File.read(app_path("public/bukkits/javascripts/foo.js")) - assert File.exists?(app_path("public/bukkits/stylesheets/foo.css")) - assert_equal "h1 { font-size: 10000px }\n", File.read(app_path("public/bukkits/stylesheets/foo.css")) - assert File.exists?(app_path("public/bukkits/images/img.png")) - end - end - def test_serving_sprockets_assets @plugin.write "app/assets/javascripts/engine.js.coffee", "square = (x) -> x * x" -- cgit v1.2.3 From d5ad92ced1786b742c3ecce3cb60d851c7200bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 15 Apr 2011 20:09:39 +0200 Subject: Make static faster as we don't have to serve multiple paths anymore. --- railties/lib/rails/application.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 9bdf18bf79..7af0735c14 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -161,7 +161,7 @@ module Rails end if config.serve_static_assets - middleware.use ::ActionDispatch::Static, "/" => paths["public"].first + middleware.use ::ActionDispatch::Static, paths["public"].first end middleware.use ::Rack::Lock unless config.allow_concurrency -- cgit v1.2.3 From 9982b5af94746263419c88668972b260d33a0770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 15 Apr 2011 21:32:36 +0200 Subject: Fix missing test_helper. --- railties/lib/rails/generators/rails/app/app_generator.rb | 3 ++- .../generators/rails/app/templates/test/test_helper.rb | 15 +++++++++++++++ .../generators/rails/app/templates/test/test_helper.rb.tt | 15 --------------- 3 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 railties/lib/rails/generators/rails/app/templates/test/test_helper.rb delete mode 100644 railties/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt (limited to 'railties') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 93d6c1f827..8d74fe2c94 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -106,7 +106,8 @@ module Rails empty_directory_with_gitkeep "test/integration" empty_directory_with_gitkeep "test/unit" - copy_file "test/performance/browsing_test.rb" + template "test/performance/browsing_test.rb" + template "test/test_helper.rb" end def tmp diff --git a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb new file mode 100644 index 0000000000..a8f7aeac7d --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb @@ -0,0 +1,15 @@ +ENV["RAILS_ENV"] = "test" +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' + +class ActiveSupport::TestCase +<% unless options[:skip_active_record] -%> + # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. + # + # Note: You'll currently still have to declare fixtures explicitly in integration tests + # -- they do not yet inherit this setting + fixtures :all + +<% end -%> + # Add more helper methods to be used by all tests here... +end diff --git a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt deleted file mode 100644 index a8f7aeac7d..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +++ /dev/null @@ -1,15 +0,0 @@ -ENV["RAILS_ENV"] = "test" -require File.expand_path('../../config/environment', __FILE__) -require 'rails/test_help' - -class ActiveSupport::TestCase -<% unless options[:skip_active_record] -%> - # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. - # - # Note: You'll currently still have to declare fixtures explicitly in integration tests - # -- they do not yet inherit this setting - fixtures :all - -<% end -%> - # Add more helper methods to be used by all tests here... -end -- cgit v1.2.3 From 2c54fde54d13038f143bb65c7154b5656606258f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 15 Apr 2011 22:01:06 +0200 Subject: Fix generator tests. --- railties/test/generators/app_generator_test.rb | 43 +++++++++++++------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'railties') diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index dfb7adf459..3ef06c7f25 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -8,6 +8,8 @@ DEFAULT_APP_FILES = %w( Gemfile Rakefile config.ru + app/assets/javascripts + app/assets/stylesheets app/controllers app/helpers app/mailers @@ -22,8 +24,6 @@ DEFAULT_APP_FILES = %w( lib/tasks log public/images - public/javascripts - public/stylesheets script/rails test/fixtures test/functional @@ -31,11 +31,9 @@ DEFAULT_APP_FILES = %w( test/performance test/unit vendor + vendor/assets vendor/plugins - tmp/sessions - tmp/sockets tmp/cache - tmp/pids ) class AppGeneratorTest < Rails::Generators::TestCase @@ -49,8 +47,9 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_application_controller_and_layout_files run_generator - assert_file "app/views/layouts/application.html.erb", /stylesheet_link_tag :all/ - assert_no_file "public/stylesheets/application.css" + assert_file "app/views/layouts/application.html.erb", /stylesheet_link_tag\s+"application"/ + assert_file "app/views/layouts/application.html.erb", /javascript_include_tag\s+"application"/ + assert_file "app/assets/stylesheets/application.css" end def test_invalid_application_name_raises_an_error @@ -149,37 +148,37 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_jquery_and_test_unit_are_added_by_default run_generator assert_file "config/application.rb", /#\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(prototype effects dragdrop controls rails\)/ - assert_file "public/javascripts/application.js" - assert_file "public/javascripts/jquery.js" - assert_file "public/javascripts/rails.js" + assert_file "app/assets/javascripts/application.js" + assert_file "vendor/assets/javascripts/jquery.js" + assert_file "vendor/assets/javascripts/jquery_ujs.js" assert_file "test" end def test_javascript_is_skipped_if_required run_generator [destination_root, "--skip-javascript"] assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(\)/ - assert_file "public/javascripts/application.js" - assert_no_file "public/javascripts/jquery.js" - assert_no_file "public/javascripts/rails.js" + assert_file "app/assets/javascripts/application.js" + assert_no_file "vendor/assets/javascripts/jquery.js" + assert_no_file "vendor/assets/javascripts/jquery_ujs.js" end def test_config_prototype_javascript_library run_generator [destination_root, "-j", "prototype"] assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(prototype effects dragdrop controls rails\)/ - assert_file "public/javascripts/application.js" - assert_file "public/javascripts/prototype.js" - assert_file "public/javascripts/effects.js" - assert_file "public/javascripts/dragdrop.js" - assert_file "public/javascripts/controls.js" - assert_file "public/javascripts/rails.js", /prototype/ + assert_file "app/assets/javascripts/application.js" + assert_file "vendor/assets/javascripts/prototype.js" + assert_file "vendor/assets/javascripts/effects.js" + assert_file "vendor/assets/javascripts/dragdrop.js" + assert_file "vendor/assets/javascripts/controls.js" + assert_file "vendor/assets/javascripts/prototype_ujs.js", /prototype/ end def test_config_jquery_javascript_library run_generator [destination_root, "-j", "jquery"] assert_file "config/application.rb", /#\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(prototype effects dragdrop controls rails\)/ - assert_file "public/javascripts/application.js" - assert_file "public/javascripts/jquery.js" - assert_file "public/javascripts/rails.js", /jQuery/ + assert_file "app/assets/javascripts/application.js" + assert_file "vendor/assets/javascripts/jquery.js" + assert_file "vendor/assets/javascripts/jquery_ujs.js", /jQuery/ end def test_template_from_dir_pwd -- cgit v1.2.3 From 5952d4f86055ed612aba66c66a4dc3092e6d4e42 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 16 Apr 2011 19:59:13 +0200 Subject: Fix plugin new generator to work with new javascript/stylesheets conventions --- .../rails/generators/rails/app/app_generator.rb | 4 +-- .../rails/plugin_new/plugin_new_generator.rb | 31 +++++++++++++------- .../test/generators/plugin_new_generator_test.rb | 34 ++++++++++++---------- 3 files changed, 40 insertions(+), 29 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 8d74fe2c94..4df68d67c7 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -138,7 +138,7 @@ module Rails def vendor_stylesheets empty_directory_with_gitkeep "vendor/assets/stylesheets" end - + def vendor_plugins empty_directory_with_gitkeep "vendor/plugins" end @@ -166,7 +166,7 @@ module Rails if !options[:skip_active_record] && !DATABASES.include?(options[:database]) raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}." end - + if !options[:skip_javascript] && !JAVASCRIPTS.include?(options[:javascript]) raise Error, "Invalid value for --javascript option. Supported for preconfiguration are: #{JAVASCRIPTS.join(", ")}." end diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 3cf8410d1e..e7f4bab9de 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -94,26 +94,35 @@ task :default => :test end def stylesheets - empty_directory_with_gitkeep "public/stylesheets" if options[:mountable] + if options[:mountable] + empty_directory_with_gitkeep "app/stylesheets" + copy_file "#{app_templates_dir}/app/assets/stylesheets/application.css", + "app/assets/stylesheets/application.css" + end end def javascripts return unless options[:mountable] - empty_directory "#{app_templates_dir}/public/javascripts" - - unless options[:skip_javascript] - copy_file "#{app_templates_dir}/public/javascripts/#{options[:javascript]}.js", "public/javascripts/#{options[:javascript]}.js" - copy_file "#{app_templates_dir}/public/javascripts/#{options[:javascript]}_ujs.js", "public/javascripts/rails.js" + if options[:skip_javascript] + empty_directory_with_gitkeep "vendor/assets/javascripts" + else + copy_file "#{app_templates_dir}/app/assets/javascripts/application.js.tt", + "app/assets/javascripts/application.js" + copy_file "#{app_templates_dir}/vendor/assets/javascripts/#{options[:javascript]}.js", + "vendor/assets/javascripts/#{options[:javascript]}.js" + copy_file "#{app_templates_dir}/vendor/assets/javascripts/#{options[:javascript]}_ujs.js", + "vendor/assets/javascripts/#{options[:javascript]}_ujs.js" if options[:javascript] == "prototype" - copy_file "#{app_templates_dir}/public/javascripts/controls.js", "public/javascripts/controls.js" - copy_file "#{app_templates_dir}/public/javascripts/dragdrop.js", "public/javascripts/dragdrop.js" - copy_file "#{app_templates_dir}/public/javascripts/effects.js", "public/javascripts/effects.js" + copy_file "#{app_templates_dir}/vendor/assets/javascripts/controls.js", + "vendor/assets/javascripts/controls.js" + copy_file "#{app_templates_dir}/vendor/assets/javascripts/dragdrop.js", + "vendor/assets/javascripts/dragdrop.js" + copy_file "#{app_templates_dir}/vendor/assets/javascripts/effects.js", + "vendor/assets/javascripts/effects.js" end end - - copy_file "#{app_templates_dir}/public/javascripts/application.js", "public/javascripts/application.js" end def script(force = false) diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 402fd25b14..fd8c30efaf 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -95,32 +95,33 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_skipping_javascripts_without_mountable_option run_generator - assert_no_file "public/javascripts/jquery.js" - assert_no_file "public/javascripts/rails.js" - assert_no_file "public/javascripts/application.js" + assert_no_file "app/assets/javascripts/application.js" + assert_no_file "vendor/assets/javascripts/jquery.js" + assert_no_file "vendor/assets/javascripts/jquery_ujs.js" end def test_javascripts_generation run_generator [destination_root, "--mountable"] - assert_file "public/javascripts/jquery.js" - assert_file "public/javascripts/rails.js" - assert_file "public/javascripts/application.js" + assert_file "app/assets/javascripts/application.js" + assert_file "vendor/assets/javascripts/jquery.js" + assert_file "vendor/assets/javascripts/jquery_ujs.js" end def test_skip_javascripts run_generator [destination_root, "--skip-javascript", "--mountable"] - assert_no_file "public/javascripts/jquery.js" - assert_no_file "public/javascripts/rails.js" + assert_no_file "app/assets/javascripts/application.js" + assert_no_file "vendor/assets/javascripts/jquery.js" + assert_no_file "vendor/assets/javascripts/jquery_ujs.js" end - def test_ensure_that_javascript_option_is_passed_to_app_generator - run_generator [destination_root, "--javascript", "prototype"] - assert_file "test/dummy/public/javascripts/prototype.js" - end - - def test_ensure_that_skip_javascript_option_is_passed_to_app_generator - run_generator [destination_root, "--skip_javascript"] - assert_no_file "test/dummy/public/javascripts/jquery.js" + def test_config_prototype_javascript_library + run_generator [destination_root, "-j", "prototype", "--mountable"] + assert_file "app/assets/javascripts/application.js" + assert_file "vendor/assets/javascripts/prototype.js" + assert_file "vendor/assets/javascripts/effects.js" + assert_file "vendor/assets/javascripts/dragdrop.js" + assert_file "vendor/assets/javascripts/controls.js" + assert_file "vendor/assets/javascripts/prototype_ujs.js", /prototype/ end def test_template_from_dir_pwd @@ -218,3 +219,4 @@ protected silence(:stdout){ generator.send(*args, &block) } end end + -- cgit v1.2.3 From eb75f15a1aaa570fc0eedd1cb5ad0486e0e48450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 17 Apr 2011 10:23:07 +0200 Subject: Generate app/* stubs directories for full plugins to show ththat it is possible to extend them. --- .../rails/plugin_new/plugin_new_generator.rb | 43 ++++++++++++++-------- .../templates/app/models/.empty_directory | 0 .../test/generators/plugin_new_generator_test.rb | 6 +++ 3 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory (limited to 'railties') diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index e7f4bab9de..81563f81d3 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -9,10 +9,15 @@ module Rails end def app - if options[:mountable] + if mountable? directory "app" template "#{app_templates_dir}/app/views/layouts/application.html.erb.tt", "app/views/layouts/#{name}/application.html.erb" + elsif full? + empty_directory_with_gitkeep "app/models" + empty_directory_with_gitkeep "app/controllers" + empty_directory_with_gitkeep "app/views" + empty_directory_with_gitkeep "app/helpers" end end @@ -61,8 +66,12 @@ task :default => :test end end + PASSTHROUGH_OPTIONS = [ + :skip_active_record, :skip_javascript, :database, :javascript, :quiet, :pretend, :force, :skip + ] + def generate_test_dummy(force = false) - opts = (options || {}).slice(:skip_active_record, :skip_javascript, :database, :javascript, :quiet, :pretend, :force, :skip) + opts = (options || {}).slice(*PASSTHROUGH_OPTIONS) opts[:force] = force invoke Rails::Generators::AppGenerator, @@ -94,19 +103,18 @@ task :default => :test end def stylesheets - if options[:mountable] - empty_directory_with_gitkeep "app/stylesheets" + if mountable? copy_file "#{app_templates_dir}/app/assets/stylesheets/application.css", "app/assets/stylesheets/application.css" + elsif full? + empty_directory_with_gitkeep "app/assets/stylesheets" end end def javascripts - return unless options[:mountable] + return if options.skip_javascript? - if options[:skip_javascript] - empty_directory_with_gitkeep "vendor/assets/javascripts" - else + if mountable? copy_file "#{app_templates_dir}/app/assets/javascripts/application.js.tt", "app/assets/javascripts/application.js" copy_file "#{app_templates_dir}/vendor/assets/javascripts/#{options[:javascript]}.js", @@ -122,6 +130,8 @@ task :default => :test copy_file "#{app_templates_dir}/vendor/assets/javascripts/effects.js", "vendor/assets/javascripts/effects.js" end + elsif full? + empty_directory_with_gitkeep "app/assets/javascripts" end end @@ -139,17 +149,17 @@ task :default => :test alias_method :plugin_path, :app_path - class_option :dummy_path, :type => :string, :default => "test/dummy", - :desc => "Create dummy application at given path" + class_option :dummy_path, :type => :string, :default => "test/dummy", + :desc => "Create dummy application at given path" - class_option :full, :type => :boolean, :default => false, - :desc => "Generate rails engine with integration tests" + class_option :full, :type => :boolean, :default => false, + :desc => "Generate rails engine with integration tests" - class_option :mountable, :type => :boolean, :default => false, - :desc => "Generate mountable isolated application" + class_option :mountable, :type => :boolean, :default => false, + :desc => "Generate mountable isolated application" - class_option :skip_gemspec, :type => :boolean, :default => false, - :desc => "Skip gemspec file" + class_option :skip_gemspec, :type => :boolean, :default => false, + :desc => "Skip gemspec file" def initialize(*args) raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank? @@ -209,6 +219,7 @@ task :default => :test public_task :apply_rails_template, :bundle_if_dev_or_edge protected + def app_templates_dir "../../app/templates" end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory b/railties/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory new file mode 100644 index 0000000000..e69de29bb2 diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index fd8c30efaf..d20335ad95 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -145,6 +145,12 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_creating_engine_in_full_mode run_generator [destination_root, "--full"] + assert_file "app/assets/javascripts" + assert_file "app/assets/stylesheets" + assert_file "app/models" + assert_file "app/controllers" + assert_file "app/views" + assert_file "app/helpers" assert_file "config/routes.rb", /Rails.application.routes.draw do/ assert_file "lib/bukkits/engine.rb", /module Bukkits\n class Engine < Rails::Engine\n end\nend/ assert_file "lib/bukkits.rb", /require "bukkits\/engine"/ -- cgit v1.2.3 From 8f75c3abcde4f2ff64e855178027e1bd93976de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 17 Apr 2011 10:51:07 +0200 Subject: Move app initializers to sprockets railtie. --- railties/lib/rails/application.rb | 9 --------- railties/lib/rails/application/finisher.rb | 18 ++---------------- 2 files changed, 2 insertions(+), 25 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 7af0735c14..0c3c7737ea 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -139,15 +139,6 @@ module Rails alias :build_middleware_stack :app - def build_asset_environment - require 'sprockets' - env = Sprockets::Environment.new(root.to_s) - env.static_root = File.join(root.join("public"), config.assets.prefix) - env.paths.concat config.assets.paths - env.logger = Rails.logger - @assets = env - end - def default_middleware_stack ActionDispatch::MiddlewareStack.new.tap do |middleware| if rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index 838e50de6c..bf865ce466 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -33,22 +33,6 @@ module Rails end end - initializer :add_sprockets_route do |app| - assets = config.assets - if assets.enabled - build_asset_environment - app.routes.append do - mount app.assets => assets.prefix - end - end - end - - initializer :index_sprockets_environment do |app| - if config.assets.enabled && config.action_controller.perform_caching - app.assets = app.assets.index - end - end - initializer :build_middleware_stack do build_middleware_stack end @@ -69,6 +53,8 @@ module Rails end # Force routes to be loaded just at the end and add it to to_prepare callbacks + # This needs to be after the finisher hook to ensure routes added in the hook + # are still loaded. initializer :set_routes_reloader do |app| reloader = lambda { app.routes_reloader.execute_if_updated } reloader.call -- cgit v1.2.3 From 3a68aec1a1c6329bfcbf0f87bdc2fbd75cb98feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 17 Apr 2011 11:44:52 +0200 Subject: Make generators more modular, add hooks and improve test suite. --- railties/lib/rails/generators.rb | 9 +++- .../generators/rails/assets/assets_generator.rb | 48 +++++++++--------- .../rails/scaffold/scaffold_generator.rb | 21 +++++++- .../rails/scaffold/templates/scaffold.css | 56 +++++++++++++++++++++ .../rails/scaffold/templates/scaffold.css.scss | 58 ++++++++++++++++++++++ .../lib/rails/generators/rails/stylesheets/USAGE | 5 -- .../rails/stylesheets/stylesheets_generator.rb | 23 --------- .../rails/stylesheets/templates/scaffold.css | 56 --------------------- .../rails/stylesheets/templates/scaffold.css.scss | 58 ---------------------- .../test/generators/scaffold_generator_test.rb | 52 ++++++++++++++++--- .../test/generators/stylesheets_generator_test.rb | 23 --------- 11 files changed, 210 insertions(+), 199 deletions(-) create mode 100644 railties/lib/rails/generators/rails/scaffold/templates/scaffold.css create mode 100644 railties/lib/rails/generators/rails/scaffold/templates/scaffold.css.scss delete mode 100644 railties/lib/rails/generators/rails/stylesheets/USAGE delete mode 100644 railties/lib/rails/generators/rails/stylesheets/stylesheets_generator.rb delete mode 100644 railties/lib/rails/generators/rails/stylesheets/templates/scaffold.css delete mode 100644 railties/lib/rails/generators/rails/stylesheets/templates/scaffold.css.scss delete mode 100644 railties/test/generators/stylesheets_generator_test.rb (limited to 'railties') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index be61b087f9..82171d0832 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -24,9 +24,11 @@ module Rails :rails => { :actions => '-a', :orm => '-o', + :javascript_engine => '-je', :resource_controller => '-c', :scaffold_controller => '-c', :stylesheets => '-y', + :stylesheet_engine => '-se', :template_engine => '-e', :test_framework => '-t' }, @@ -43,15 +45,18 @@ module Rails DEFAULT_OPTIONS = { :rails => { + :assets => true, :force_plural => false, :helper => true, - :assets => true, - :orm => nil, :integration_tool => nil, + :javascripts => true, + :javascript_engine => nil, + :orm => nil, :performance_tool => nil, :resource_controller => :controller, :scaffold_controller => :scaffold_controller, :stylesheets => true, + :stylesheet_engine => nil, :test_framework => nil, :template_engine => :erb }, diff --git a/railties/lib/rails/generators/rails/assets/assets_generator.rb b/railties/lib/rails/generators/rails/assets/assets_generator.rb index 59239d1a03..80beb7abfe 100644 --- a/railties/lib/rails/generators/rails/assets/assets_generator.rb +++ b/railties/lib/rails/generators/rails/assets/assets_generator.rb @@ -1,36 +1,38 @@ module Rails module Generators - # TODO: Add hooks for using other asset pipelines, like Less class AssetsGenerator < NamedBase - def create_asset_files + class_option :javascripts, :type => :boolean, :desc => "Generate javascripts" + class_option :stylesheets, :type => :boolean, :desc => "Generate stylesheets" + + class_option :javascript_engine, :desc => "Engine for javascripts" + class_option :stylesheet_engine, :desc => "Engine for stylesheets" + + def create_javascript_files + return unless options.javascripts? copy_file "javascript.#{javascript_extension}", - File.join('app/assets/javascripts', "#{file_name}.#{javascript_extension}") + File.join('app/assets/javascripts', class_path, "#{asset_name}.#{javascript_extension}") + end + def create_stylesheet_files + return unless options.stylesheets? copy_file "stylesheet.#{stylesheet_extension}", - File.join('app/assets/stylesheets', "#{file_name}.#{stylesheet_extension}") + File.join('app/assets/stylesheets', class_path, "#{asset_name}.#{stylesheet_extension}") end - - private - def javascript_extension - using_coffee? ? "js.coffee" : "js" + + protected + + def asset_name + file_name end - - def using_coffee? - require 'coffee-script' - defined?(CoffeeScript) - rescue LoadError - false + + def javascript_extension + options.javascript_engine.present? ? + "js.#{options.javascript_engine}" : "js" end - + def stylesheet_extension - using_sass? ? "css.scss" : "css" - end - - def using_sass? - require 'sass' - defined?(Sass) - rescue LoadError - false + options.stylesheet_engine.present? ? + "css.#{options.stylesheet_engine}" : "css" end end end diff --git a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb index 779f933785..6eef0dbe5b 100644 --- a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb @@ -6,8 +6,27 @@ module Rails remove_hook_for :resource_controller remove_class_option :actions + class_option :stylesheets, :type => :boolean, :desc => "Generate stylesheets" + class_option :stylesheet_engine, :desc => "Engine for stylesheets" + hook_for :scaffold_controller, :required => true - hook_for :stylesheets + + def copy_stylesheets_file + if behavior == :invoke && options.stylesheets? + template "scaffold.#{stylesheet_extension}", "app/assets/stylesheets/scaffold.#{stylesheet_extension}" + end + end + + hook_for :assets do |assets| + invoke assets, [controller_name] + end + + private + + def stylesheet_extension + options.stylesheet_engine.present? ? + "css.#{options.stylesheet_engine}" : "css" + end end end end diff --git a/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css b/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css new file mode 100644 index 0000000000..1ae7000299 --- /dev/null +++ b/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css @@ -0,0 +1,56 @@ +body { background-color: #fff; color: #333; } + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { color: #000; } +a:visited { color: #666; } +a:hover { color: #fff; background-color:#000; } + +div.field, div.actions { + margin-bottom: 10px; +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; +} + +#error_explanation h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; +} + +#error_explanation ul li { + font-size: 12px; + list-style: square; +} diff --git a/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css.scss b/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css.scss new file mode 100644 index 0000000000..45116b53f6 --- /dev/null +++ b/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css.scss @@ -0,0 +1,58 @@ +body { background-color: #fff; color: #333; } + +body, p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { + color: #000; + &:visited { color: #666; } + &:hover { color: #fff; background-color:#000; } +} + +div.field, div.actions { + margin-bottom: 10px; +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; + + h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; + } + + ul li { + font-size: 12px; + list-style: square; + } +} \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/stylesheets/USAGE b/railties/lib/rails/generators/rails/stylesheets/USAGE deleted file mode 100644 index 59e5495d0b..0000000000 --- a/railties/lib/rails/generators/rails/stylesheets/USAGE +++ /dev/null @@ -1,5 +0,0 @@ -Description: - Copies scaffold stylesheets to public/stylesheets/. - -Examples: - `rails generate stylesheets` diff --git a/railties/lib/rails/generators/rails/stylesheets/stylesheets_generator.rb b/railties/lib/rails/generators/rails/stylesheets/stylesheets_generator.rb deleted file mode 100644 index d06db25292..0000000000 --- a/railties/lib/rails/generators/rails/stylesheets/stylesheets_generator.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Rails - module Generators - class StylesheetsGenerator < Base - def copy_stylesheets_file - if behavior == :invoke - template "scaffold.#{stylesheet_extension}", "app/assets/stylesheets/scaffold.#{stylesheet_extension}" - end - end - - private - def stylesheet_extension - using_sass? ? "css.scss" : "css" - end - - def using_sass? - require 'sass' - defined?(Sass) - rescue LoadError - false - end - end - end -end diff --git a/railties/lib/rails/generators/rails/stylesheets/templates/scaffold.css b/railties/lib/rails/generators/rails/stylesheets/templates/scaffold.css deleted file mode 100644 index 1ae7000299..0000000000 --- a/railties/lib/rails/generators/rails/stylesheets/templates/scaffold.css +++ /dev/null @@ -1,56 +0,0 @@ -body { background-color: #fff; color: #333; } - -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} - -pre { - background-color: #eee; - padding: 10px; - font-size: 11px; -} - -a { color: #000; } -a:visited { color: #666; } -a:hover { color: #fff; background-color:#000; } - -div.field, div.actions { - margin-bottom: 10px; -} - -#notice { - color: green; -} - -.field_with_errors { - padding: 2px; - background-color: red; - display: table; -} - -#error_explanation { - width: 450px; - border: 2px solid red; - padding: 7px; - padding-bottom: 0; - margin-bottom: 20px; - background-color: #f0f0f0; -} - -#error_explanation h2 { - text-align: left; - font-weight: bold; - padding: 5px 5px 5px 15px; - font-size: 12px; - margin: -7px; - margin-bottom: 0px; - background-color: #c00; - color: #fff; -} - -#error_explanation ul li { - font-size: 12px; - list-style: square; -} diff --git a/railties/lib/rails/generators/rails/stylesheets/templates/scaffold.css.scss b/railties/lib/rails/generators/rails/stylesheets/templates/scaffold.css.scss deleted file mode 100644 index 45116b53f6..0000000000 --- a/railties/lib/rails/generators/rails/stylesheets/templates/scaffold.css.scss +++ /dev/null @@ -1,58 +0,0 @@ -body { background-color: #fff; color: #333; } - -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} - -pre { - background-color: #eee; - padding: 10px; - font-size: 11px; -} - -a { - color: #000; - &:visited { color: #666; } - &:hover { color: #fff; background-color:#000; } -} - -div.field, div.actions { - margin-bottom: 10px; -} - -#notice { - color: green; -} - -.field_with_errors { - padding: 2px; - background-color: red; - display: table; -} - -#error_explanation { - width: 450px; - border: 2px solid red; - padding: 7px; - padding-bottom: 0; - margin-bottom: 20px; - background-color: #f0f0f0; - - h2 { - text-align: left; - font-weight: bold; - padding: 5px 5px 5px 15px; - font-size: 12px; - margin: -7px; - margin-bottom: 0px; - background-color: #c00; - color: #fff; - } - - ul li { - font-size: 12px; - list-style: square; - } -} \ No newline at end of file diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index df787f61ba..4b07f8bcbe 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -79,8 +79,10 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_file "app/helpers/product_lines_helper.rb" assert_file "test/unit/helpers/product_lines_helper_test.rb" - # Stylesheets - assert_file "public/stylesheets/scaffold.css" + # Assets + assert_file "app/assets/stylesheets/scaffold.css.scss" + assert_file "app/assets/javascripts/product_lines.js.coffee" + assert_file "app/assets/stylesheets/product_lines.css.scss" end def test_scaffold_on_revoke @@ -110,8 +112,10 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_no_file "app/helpers/product_lines_helper.rb" assert_no_file "test/unit/helpers/product_lines_helper_test.rb" - # Stylesheets (should not be removed) - assert_file "public/stylesheets/scaffold.css" + # Assets + assert_file "app/assets/stylesheets/scaffold.css.scss", /&:visited/ + assert_no_file "app/assets/javascripts/product_lines.js.coffee" + assert_no_file "app/assets/stylesheets/product_lines.css.scss" end def test_scaffold_with_namespace_on_invoke @@ -184,8 +188,10 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_file "app/helpers/admin/roles_helper.rb" assert_file "test/unit/helpers/admin/roles_helper_test.rb" - # Stylesheets - assert_file "public/stylesheets/scaffold.css" + # Assets + assert_file "app/assets/stylesheets/scaffold.css.scss", /&:visited/ + assert_file "app/assets/javascripts/admin/roles.js.coffee" + assert_file "app/assets/stylesheets/admin/roles.css.scss" end def test_scaffold_with_namespace_on_revoke @@ -216,8 +222,10 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_no_file "app/helpers/admin/roles_helper.rb" assert_no_file "test/unit/helpers/admin/roles_helper_test.rb" - # Stylesheets (should not be removed) - assert_file "public/stylesheets/scaffold.css" + # Assets + assert_file "app/assets/stylesheets/scaffold.css.scss" + assert_no_file "app/assets/javascripts/admin/roles.js.coffee" + assert_no_file "app/assets/stylesheets/admin/roles.css.scss" end def test_scaffold_generator_on_revoke_does_not_mutilate_legacy_map_parameter @@ -235,6 +243,34 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_file "config/routes.rb", /\.routes\.draw do\s*\|map\|\s*$/ end + def test_scaffold_generator_no_assets + run_generator [ "posts", "--no-assets" ] + assert_file "app/assets/stylesheets/scaffold.css.scss" + assert_no_file "app/assets/javascripts/posts.js.coffee" + assert_no_file "app/assets/stylesheets/posts.css.scss" + end + + def test_scaffold_generator_no_stylesheets + run_generator [ "posts", "--no-stylesheets" ] + assert_no_file "app/assets/stylesheets/scaffold.css.scss" + assert_file "app/assets/javascripts/posts.js.coffee" + assert_no_file "app/assets/stylesheets/posts.css.scss" + end + + def test_scaffold_generator_no_javascripts + run_generator [ "posts", "--no-javascripts" ] + assert_file "app/assets/stylesheets/scaffold.css.scss" + assert_no_file "app/assets/javascripts/posts.js.coffee" + assert_file "app/assets/stylesheets/posts.css.scss" + end + + def test_scaffold_generator_no_negines + run_generator [ "posts", "--no-javascript-engine", "--no-stylesheet-engine" ] + assert_file "app/assets/stylesheets/scaffold.css" + assert_file "app/assets/javascripts/posts.js" + assert_file "app/assets/stylesheets/posts.css" + end + def test_scaffold_generator_outputs_error_message_on_missing_attribute_type content = capture(:stderr) { run_generator ["post", "title:string", "body"]} assert_match(/Missing type for attribute 'body'/, content) diff --git a/railties/test/generators/stylesheets_generator_test.rb b/railties/test/generators/stylesheets_generator_test.rb deleted file mode 100644 index 4b86cdd1c7..0000000000 --- a/railties/test/generators/stylesheets_generator_test.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'generators/generators_test_helper' -require 'rails/generators/rails/stylesheets/stylesheets_generator' - -class StylesheetsGeneratorTest < Rails::Generators::TestCase - include GeneratorsTestHelper - - def test_copy_scss_stylesheet - self.generator_class.any_instance.stubs(:using_sass?).returns(true) - run_generator - assert_file "app/assets/stylesheets/scaffold.css.scss" - end - - def test_copy_css_stylesheet - run_generator - assert_file "app/assets/stylesheets/scaffold.css" - end - - def test_stylesheets_are_not_deleted_on_revoke - run_generator - run_generator [], :behavior => :revoke - assert_file "app/assets/stylesheets/scaffold.css" - end -end -- cgit v1.2.3 From a9a20357220309e3bc7d06c5eac5619ca34b8c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 17 Apr 2011 11:48:15 +0200 Subject: Fix assets generators. --- railties/lib/rails/generators.rb | 1 + railties/test/generators/assets_generator_test.rb | 26 +++++++++-------------- 2 files changed, 11 insertions(+), 16 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 82171d0832..9be395e989 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -24,6 +24,7 @@ module Rails :rails => { :actions => '-a', :orm => '-o', + :javascripts => '-j', :javascript_engine => '-je', :resource_controller => '-c', :scaffold_controller => '-c', diff --git a/railties/test/generators/assets_generator_test.rb b/railties/test/generators/assets_generator_test.rb index a2a40a28d4..e99f0f092a 100644 --- a/railties/test/generators/assets_generator_test.rb +++ b/railties/test/generators/assets_generator_test.rb @@ -6,27 +6,21 @@ class AssetsGeneratorTest < Rails::Generators::TestCase include GeneratorsTestHelper arguments %w(posts) - def test_vanilla_assets + def test_assets run_generator - assert_file "app/assets/javascripts/posts.js" - assert_file "app/assets/stylesheets/posts.css" + assert_file "app/assets/javascripts/posts.js.coffee" + assert_file "app/assets/stylesheets/posts.css.scss" end def test_skipping_assets - content = run_generator ["posts", "--skip-assets"] - assert_no_file "app/assets/javascripts/posts.js" - assert_no_file "app/assets/stylesheets/posts.css" - end - - def test_coffee_javascript - self.generator_class.any_instance.stubs(:using_coffee?).returns(true) - run_generator - assert_file "app/assets/javascripts/posts.js.coffee" + content = run_generator ["posts", "--no-stylesheets", "--no-javascripts"] + assert_no_file "app/assets/javascripts/posts.js.coffee" + assert_no_file "app/assets/stylesheets/posts.css.scss" end - def test_sass_stylesheet - self.generator_class.any_instance.stubs(:using_sass?).returns(true) - run_generator - assert_file "app/assets/stylesheets/posts.css.scss" + def test_vanilla_assets + run_generator ["posts", "--no-javascript-engine", "--no-stylesheet-engine"] + assert_file "app/assets/javascripts/posts.js" + assert_file "app/assets/stylesheets/posts.css" end end -- cgit v1.2.3