aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2010-02-14 19:28:05 +0000
committerPratik Naik <pratiknaik@gmail.com>2010-02-14 19:28:05 +0000
commit6f3c5f67870a625b8be4de6e34e8d0d2f5d2b5e3 (patch)
tree3da8d75101aabe3c1d90d0582505ec1480c9d885 /railties
parent77bf78b3b78a41d4f2f6e733f5c9c00608c0adba (diff)
parenta1b60696e2b13cbe94d748444cc0da37b190fbb8 (diff)
downloadrails-6f3c5f67870a625b8be4de6e34e8d0d2f5d2b5e3.tar.gz
rails-6f3c5f67870a625b8be4de6e34e8d0d2f5d2b5e3.tar.bz2
rails-6f3c5f67870a625b8be4de6e34e8d0d2f5d2b5e3.zip
Merge remote branch 'mainstream/master'
Conflicts: railties/README railties/guides/source/active_support_core_extensions.textile railties/guides/source/getting_started.textile railties/lib/generators/rails/app/templates/README
Diffstat (limited to 'railties')
-rw-r--r--railties/README4
-rw-r--r--railties/Rakefile22
-rw-r--r--railties/guides/source/3_0_release_notes.textile4
-rw-r--r--railties/guides/source/action_mailer_basics.textile6
-rw-r--r--railties/guides/source/activerecord_validations_callbacks.textile2
-rw-r--r--railties/guides/source/command_line.textile58
-rw-r--r--railties/guides/source/debugging_rails_applications.textile12
-rw-r--r--railties/guides/source/generators.textile28
-rw-r--r--railties/guides/source/migrations.textile10
-rw-r--r--railties/guides/source/performance_testing.textile16
-rw-r--r--railties/guides/source/plugins.textile28
-rw-r--r--railties/guides/source/rails_on_rack.textile10
-rw-r--r--railties/guides/source/testing.textile8
-rw-r--r--railties/lib/generators/erb/scaffold/templates/layout.html.erb2
-rw-r--r--railties/lib/generators/rails/app/templates/Gemfile44
-rw-r--r--railties/lib/generators/rails/app/templates/config/application.rb14
-rw-r--r--railties/lib/generators/rails/app/templates/config/boot.rb29
-rw-r--r--railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml31
-rw-r--r--railties/lib/generators/rails/app/templates/public/javascripts/controls.js8
-rw-r--r--railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js13
-rw-r--r--railties/lib/generators/rails/app/templates/public/javascripts/effects.js21
-rw-r--r--railties/lib/generators/rails/app/templates/public/javascripts/prototype.js2592
-rw-r--r--railties/lib/generators/rails/app/templates/public/javascripts/rails.js41
-rw-r--r--railties/lib/generators/rails/app/templates/script/rails1
-rw-r--r--railties/lib/generators/rails/app/templates/test/test_helper.rb2
-rw-r--r--railties/lib/generators/rails/controller/USAGE2
-rw-r--r--railties/lib/generators/rails/generator/USAGE2
-rw-r--r--railties/lib/generators/rails/generator/templates/USAGE.tt2
-rw-r--r--railties/lib/generators/rails/helper/USAGE2
-rw-r--r--railties/lib/generators/rails/integration_test/USAGE2
-rw-r--r--railties/lib/generators/rails/mailer/USAGE2
-rw-r--r--railties/lib/generators/rails/metal/USAGE2
-rw-r--r--railties/lib/generators/rails/migration/USAGE4
-rw-r--r--railties/lib/generators/rails/model/USAGE4
-rw-r--r--railties/lib/generators/rails/observer/USAGE2
-rw-r--r--railties/lib/generators/rails/performance_test/USAGE2
-rw-r--r--railties/lib/generators/rails/plugin/USAGE2
-rw-r--r--railties/lib/generators/rails/resource/USAGE6
-rw-r--r--railties/lib/generators/rails/scaffold/USAGE8
-rw-r--r--railties/lib/generators/rails/scaffold_controller/USAGE2
-rw-r--r--railties/lib/generators/rails/session_migration/USAGE2
-rw-r--r--railties/lib/generators/rails/stylesheets/USAGE2
-rw-r--r--railties/lib/rails/all.rb5
-rw-r--r--railties/lib/rails/backtrace_cleaner.rb11
-rw-r--r--railties/lib/rails/commands.rb14
-rw-r--r--railties/lib/rails/commands/console.rb2
-rw-r--r--railties/lib/rails/commands/destroy.rb4
-rwxr-xr-xrailties/lib/rails/commands/generate.rb4
-rw-r--r--railties/lib/rails/commands/performance/benchmarker.rb4
-rw-r--r--railties/lib/rails/commands/performance/profiler.rb4
-rw-r--r--railties/lib/rails/commands/plugin.rb12
-rw-r--r--railties/lib/rails/commands/runner.rb2
-rw-r--r--railties/lib/rails/commands/server.rb26
-rw-r--r--railties/lib/rails/configuration.rb3
-rw-r--r--railties/lib/rails/deprecation.rb27
-rw-r--r--railties/lib/rails/engine.rb6
-rw-r--r--railties/lib/rails/engine/configuration.rb1
-rw-r--r--railties/lib/rails/generators.rb9
-rw-r--r--railties/lib/rails/generators/actions.rb8
-rw-r--r--railties/lib/rails/generators/base.rb11
-rw-r--r--railties/lib/rails/rack/debugger.rb4
-rw-r--r--railties/lib/rails/tasks/documentation.rake2
-rw-r--r--railties/lib/rails/test_help.rb6
-rw-r--r--railties/lib/rails/test_unit/railtie.rb2
-rw-r--r--railties/lib/rails/version.rb2
-rw-r--r--railties/railties.gemspec7
-rw-r--r--railties/test/application/generators_test.rb15
-rw-r--r--railties/test/application/test_test.rb17
-rw-r--r--railties/test/generators/actions_test.rb28
-rw-r--r--railties/test/generators/app_generator_test.rb12
-rw-r--r--railties/test/generators/generators_test_helper.rb1
-rw-r--r--railties/test/isolation/abstract_unit.rb2
72 files changed, 1966 insertions, 1339 deletions
diff --git a/railties/README b/railties/README
index ffed467872..e4de4a5cb2 100644
--- a/railties/README
+++ b/railties/README
@@ -250,7 +250,7 @@ app/views/layouts
app/helpers
Holds view helpers that should be named like weblogs_helper.rb. These are generated
- for you automatically when using rails generate for controllers. Helpers can be used to
+ for you automatically when using <tt>rails generate</tt> for controllers. Helpers can be used to
wrap functionality for your views into methods.
config
@@ -277,7 +277,7 @@ script
Helper scripts for automation and generation.
test
- Unit and functional tests along with fixtures. When using the rails generate command, template
+ Unit and functional tests along with fixtures. When using the <tt>rails generate</tt> scripts, template
test files will be generated for you and placed in this directory.
vendor
diff --git a/railties/Rakefile b/railties/Rakefile
index ea0b8ef8fb..f32a794544 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -90,11 +90,11 @@ end
# Publishing -------------------------------------------------------
-desc "Publish the rails gem"
-task :pgem => [:gem] do
- require 'rake/contrib/sshpublisher'
- Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
- `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
+desc "Release to gemcutter"
+task :release => :package do
+ require 'rake/gemcutter'
+ Rake::Gemcutter::Tasks.new(spec).define
+ Rake::Task['gem:push'].invoke
end
desc "Publish the guides"
@@ -105,15 +105,3 @@ task :pguides => :generate_guides do
Rake::SshFilePublisher.new("web.rubyonrails.org", "/u/sites/guides.rubyonrails.org/public", "pkg", "guides.gz").upload
`ssh web.rubyonrails.org 'cd /u/sites/guides.rubyonrails.org/public/ && tar -xvzf guides.gz && mv guides/output/* . && rm -rf guides*'`
end
-
-desc "Publish the release files to RubyForge."
-task :release => [ :package ] do
- require 'rake/contrib/rubyforgepublisher'
- require 'rubyforge'
-
- packages = %w( gem ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" }
-
- rubyforge = RubyForge.new
- rubyforge.login
- rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages)
-end
diff --git a/railties/guides/source/3_0_release_notes.textile b/railties/guides/source/3_0_release_notes.textile
index 7e4d6ed067..4bee0f537f 100644
--- a/railties/guides/source/3_0_release_notes.textile
+++ b/railties/guides/source/3_0_release_notes.textile
@@ -50,8 +50,8 @@ h4. script/* replaced by script/rails
The new <tt>script/rails</tt> replaces all the scripts that used to be in the <tt>script</tt> directory. You do not run <tt>script/rails</tt> directly though, the +rails+ command detects it is being invoked in the root of a Rails application and runs the script for you. Intended usage is:
<shell>
-rails console # => ./script/console
-rails g scaffold post title:string # => ./script/generate scaffold post title:string
+rails console # instead of script/console
+rails g scaffold post title:string # instead of script/generate scaffold post title:string
</shell>
Run <tt>rails --help</tt> for a list of all the options.
diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile
index 2405b8f28c..941c2e9771 100644
--- a/railties/guides/source/action_mailer_basics.textile
+++ b/railties/guides/source/action_mailer_basics.textile
@@ -19,7 +19,7 @@ h4. Walkthrough to Generating a Mailer
h5. Create the Mailer
<shell>
-./script/generate mailer UserMailer
+rails generate mailer UserMailer
create app/mailers/user_mailer.rb
invoke erb
create app/views/user_mailer
@@ -111,7 +111,7 @@ Let's see how we would go about wiring it up using an observer.
First off, we need to create a simple +User+ scaffold:
<shell>
-$ script/generate scaffold user name:string email:string login:string
+$ rails generate scaffold user name:string email:string login:string
$ rake db:migrate
</shell>
@@ -333,7 +333,7 @@ Receiving and parsing emails with Action Mailer can be a rather complex endeavou
* Implement a +receive+ method in your mailer.
-* Configure your email server to forward emails from the address(es) you would like your app to receive to +/path/to/app/script/runner 'UserMailer.receive(STDIN.read)'+.
+* Configure your email server to forward emails from the address(es) you would like your app to receive to +/path/to/app/script/rails runner 'UserMailer.receive(STDIN.read)'+.
Once a method called +receive+ is defined in any mailer, Action Mailer will parse the raw incoming email into an email object, decode it, instantiate a new mailer, and pass the email object to the mailer +receive+ instance method. Here's an example:
diff --git a/railties/guides/source/activerecord_validations_callbacks.textile b/railties/guides/source/activerecord_validations_callbacks.textile
index 9d0ee29ff2..dc61021f76 100644
--- a/railties/guides/source/activerecord_validations_callbacks.textile
+++ b/railties/guides/source/activerecord_validations_callbacks.textile
@@ -44,7 +44,7 @@ class Person < ActiveRecord::Base
end
</ruby>
-We can see how it works by looking at some script/console output:
+We can see how it works by looking at some +rails console+ output:
<shell>
>> p = Person.new(:name => "John Doe")
diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile
index 1a571358a1..a84e928731 100644
--- a/railties/guides/source/command_line.textile
+++ b/railties/guides/source/command_line.textile
@@ -58,7 +58,7 @@ Without any prodding of any kind, +server+ will run our new shiny Rails app:
<shell>
$ cd commandsapp
-$ ./script/server
+$ rails server
=> Booting WEBrick...
=> Rails 2.2.0 application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
@@ -76,8 +76,8 @@ h4. +generate+
The +generate+ command uses templates to create a whole lot of things. You can always find out what's available by running +generate+ by itself. Let's do that:
<shell>
-$ ./script/generate
-Usage: ./script/generate generator [options] [args]
+$ rails generate
+Usage: rails generate generator [options] [args]
...
...
@@ -95,17 +95,17 @@ Using generators will save you a large amount of time by writing *boilerplate co
Let's make our own controller with the controller generator. But what command should we use? Let's ask the generator:
-INFO: All Rails console utilities have help text. As with most *NIX utilities, you can try adding +--help+ or +-h+ to the end, for example +./script/server --help+.
+INFO: All Rails console utilities have help text. As with most *NIX utilities, you can try adding +--help+ or +-h+ to the end, for example +rails server --help+.
<shell>
-$ ./script/generate controller
-Usage: ./script/generate controller ControllerName [options]
+$ rails generate controller
+Usage: rails generate controller ControllerName [options]
...
...
Example:
- ./script/generate controller CreditCard open debit credit close
+ rails generate controller CreditCard open debit credit close
Credit card controller with URLs like /credit_card/debit.
Controller: app/controllers/credit_card_controller.rb
@@ -114,7 +114,7 @@ Example:
Test: test/functional/credit_card_controller_test.rb
Modules Example:
- ./script/generate controller 'admin/credit_card' suspend late_fee
+ rails generate controller 'admin/credit_card' suspend late_fee
Credit card admin controller with URLs /admin/credit_card/suspend.
Controller: app/controllers/admin/credit_card_controller.rb
@@ -126,7 +126,7 @@ Modules Example:
Ah, the controller generator is expecting parameters in the form of +generate controller ControllerName action1 action2+. Let's make a +Greetings+ controller with an action of *hello*, which will say something nice to us.
<shell>
-$ ./script/generate controller Greetings hello
+$ rails generate controller Greetings hello
exists app/controllers/
exists app/helpers/
create app/views/greetings
@@ -157,10 +157,10 @@ Then the view, to display our nice message (in +app/views/greetings/hello.html.e
<p><%= @message %></p>
</html>
-Deal. Go check it out in your browser. Fire up your server. Remember? +./script/server+ at the root of your Rails application should do it.
+Deal. Go check it out in your browser. Fire up your server. Remember? +rails server+ at the root of your Rails application should do it.
<shell>
-$ ./script/server
+$ rails server
=> Booting WEBrick...
</shell>
@@ -173,13 +173,13 @@ INFO: With a normal, plain-old Rails application, your URLs will generally follo
"What about data, though?", you ask over a cup of coffee. Rails comes with a generator for data models too. Can you guess its generator name?
<shell>
-$ ./script/generate model
-Usage: ./script/generate model ModelName [field:type, field:type]
+$ rails generate model
+Usage: rails generate model ModelName [field:type, field:type]
...
Examples:
- ./script/generate model account
+ rails generate model account
creates an Account model, test, fixture, and migration:
Model: app/models/account.rb
@@ -187,7 +187,7 @@ Examples:
Fixtures: test/fixtures/accounts.yml
Migration: db/migrate/XXX_add_accounts.rb
- ./script/generate model post title:string body:text published:boolean
+ rails generate model post title:string body:text published:boolean
creates a Post model with a string title, text body, and published flag.
</shell>
@@ -197,7 +197,7 @@ But instead of generating a model directly (which we'll be doing later), let's s
Let's set up a simple resource called "HighScore" that will keep track of our highest score on video games we play.
<shell>
-$ ./script/generate scaffold HighScore game:string score:integer
+$ rails generate scaffold HighScore game:string score:integer
exists app/models/
exists app/controllers/
exists app/helpers/
@@ -244,13 +244,13 @@ $ rake db:migrate
INFO: Let's talk about unit tests. Unit tests are code that tests and makes assertions about code. In unit testing, we take a little part of code, say a method of a model, and test its inputs and outputs. Unit tests are your friend. The sooner you make peace with the fact that your quality of life will drastically increase when you unit test your code, the better. Seriously. We'll make one in a moment.
-Let's see the interface Rails created for us. ./script/server; http://localhost:3000/high_scores
+Let's see the interface Rails created for us. rails server; http://localhost:3000/high_scores
We can create new high scores (55,160 on Space Invaders!)
h4. +console+
-The +console+ command lets you interact with your Rails application from the command line. On the underside, +script/console+ uses IRB, so if you've ever used it, you'll be right at home. This is useful for testing out quick ideas with code and changing data server-side without touching the website.
+The +console+ command lets you interact with your Rails application from the command line. On the underside, +rails console+ uses IRB, so if you've ever used it, you'll be right at home. This is useful for testing out quick ideas with code and changing data server-side without touching the website.
h4. +dbconsole+
@@ -265,7 +265,7 @@ Let's say you're creating a website for a client who wants a small accounting sy
There is such a thing! The plugin we're installing is called "acts_as_paranoid", and it lets models implement a "deleted_at" column that gets set when you call destroy. Later, when calling find, the plugin will tack on a database check to filter out "deleted" things.
<shell>
-$ ./script/plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_paranoid
+$ rails plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_paranoid
+ ./CHANGELOG
+ ./MIT-LICENSE
...
@@ -277,7 +277,7 @@ h4. +runner+
<tt>runner</tt> runs Ruby code in the context of Rails non-interactively. For instance:
<shell>
-$ ./script/runner "Model.long_running_method"
+$ rails runner "Model.long_running_method"
</shell>
h4. +destroy+
@@ -285,7 +285,7 @@ h4. +destroy+
Think of +destroy+ as the opposite of +generate+. It'll figure out what generate did, and undo it. Believe you-me, the creation of this tutorial used this command many times!
<shell>
-$ ./script/generate model Oops
+$ rails generate model Oops
exists app/models/
exists test/unit/
exists test/fixtures/
@@ -294,7 +294,7 @@ $ ./script/generate model Oops
create test/fixtures/oops.yml
exists db/migrate
create db/migrate/20081221040817_create_oops.rb
-$ ./script/destroy model Oops
+$ rails destroy model Oops
notempty db/migrate
notempty db
rm db/migrate/20081221040817_create_oops.rb
@@ -314,7 +314,7 @@ h4. +about+
Check it: Version numbers for Ruby, RubyGems, Rails, the Rails subcomponents, your application's folder, the current Rails environment name, your app's database adapter, and schema version! +about+ is useful when you need to ask for help, check if a security patch might affect you, or when you need some stats for an existing Rails installation.
<shell>
-$ ./script/about
+$ rails about
About your application's environment
Ruby version 1.8.6 (i486-linux)
RubyGems version 1.3.1
@@ -399,7 +399,7 @@ Many people have created a large number different web servers in Ruby, and many
NOTE: For more details on the Rack integration, see "Rails on Rack":rails_on_rack.html.
-To use a different server, just install its gem, then use its name for the first parameter to +script/server+:
+To use a different server, just install its gem, then use its name for the first parameter to +rails server+:
<shell>
$ sudo gem install mongrel
@@ -412,9 +412,9 @@ Successfully installed mongrel-1.1.5
...
...
Installing RDoc documentation for mongrel-1.1.5...
-$ script/server mongrel
-=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
-=> Rails 2.2.0 application starting on http://0.0.0.0:3000
+$ rails server mongrel
+=> Booting Mongrel (use 'rails server webrick' to force WEBrick)
+=> Rails 3.0.0 application starting on http://0.0.0.0:3000
...
</shell>
@@ -481,7 +481,7 @@ I got assigned some args:
Then we'll make sure it got included in the list of available generators:
<shell>
-$ ./script/generate
+$ rails generate
...
...
Installed Generators
@@ -491,7 +491,7 @@ Installed Generators
SWEET! Now let's generate some text, yeah!
<shell>
-$ ./script/generate tutorial_test arg1 arg2 arg3
+$ rails generate tutorial_test arg1 arg2 arg3
exists public
create public/tutorial.txt
</shell>
diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile
index 94411a560e..cd0098d686 100644
--- a/railties/guides/source/debugging_rails_applications.textile
+++ b/railties/guides/source/debugging_rails_applications.textile
@@ -247,9 +247,9 @@ If you see the message in the console or logs:
Make sure you have started your web server with the option +--debugger+:
<shell>
-~/PathTo/rails_project$ script/server --debugger
-=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
-=> Rails 2.2.0 application starting on http://0.0.0.0:3000
+~/PathTo/rails_project$ rails server --debugger
+=> Booting Mongrel (use 'rails server webrick' to force WEBrick)
+=> Rails 3.0.0 application starting on http://0.0.0.0:3000
=> Debugger enabled
...
</shell>
@@ -472,10 +472,10 @@ class Author < ActiveRecord::Base
end
</ruby>
-TIP: You can use ruby-debug while using script/console. Just remember to +require "ruby-debug"+ before calling the +debugger+ method.
+TIP: You can use ruby-debug while using +rails console+. Just remember to +require "ruby-debug"+ before calling the +debugger+ method.
<shell>
-/PathTo/project $ script/console
+/PathTo/project $ rails console
Loading development environment (Rails 2.1.0)
>> require "ruby-debug"
=> []
@@ -636,7 +636,7 @@ require 'bleak_house' if ENV['BLEAK_HOUSE']
Start a server instance with BleakHouse integration:
<shell>
-RAILS_ENV=production BLEAK_HOUSE=1 ruby-bleak-house ./script/server
+RAILS_ENV=production BLEAK_HOUSE=1 ruby-bleak-house rails server
</shell>
Make sure to run a couple hundred requests to get better data samples, then press +CTRL-C+. The server will stop and Bleak House will produce a dumpfile in +/tmp+:
diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile
index fcd91f8956..4387fe3bd5 100644
--- a/railties/guides/source/generators.textile
+++ b/railties/guides/source/generators.textile
@@ -17,18 +17,18 @@ NOTE: This guide is about Rails generators for versions >= 3.0. Rails generators
h3. First contact
-When you create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +script/generate+:
+When you create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +rails generate+:
<shell>
$ rails myapp
$ cd myapp
-$ ruby script/generate
+$ rails generate
</shell>
You will get a list of all generators that comes with Rails. If you need a detailed description, for instance about the helper generator, you can simply do:
<shell>
-$ ruby script/generate helper --help
+$ rails generate helper --help
</shell>
h3. Creating your first generator
@@ -50,13 +50,13 @@ Our new generator is quite simple: it inherits from +Rails::Generators::Base+ an
To invoke our new generator, we just need to do:
<shell>
-$ ruby script/generate initializer
+$ rails generate initializer
</shell>
Before we go on, let's see our brand new generator description:
<shell>
-$ ruby script/generate initializer --help
+$ rails generate initializer --help
</shell>
Rails usually is able to generate good descriptions if a generator is namespaced, as +ActiveRecord::Generators::ModelGenerator+, but not in this particular case. We can solve this problem in two ways. The first one is calling +desc+ inside our generator:
@@ -77,7 +77,7 @@ h3. Creating generators with generators
A faster way to create a generator is using the generator's generator:
<shell>
-$ ruby script/generate generator initializer
+$ rails generate generator initializer
create lib/generators/initializer
create lib/generators/initializer/initializer_generator.rb
create lib/generators/initializer/USAGE
@@ -99,9 +99,9 @@ At first, we can notice that we are inheriting from +Rails::Generators::NamedBas
We can see that by invoking the description of this new generator (don't forget to delete the old generator file):
<shell>
-$ ruby script/generate initializer --help
+$ rails generate initializer --help
Usage:
- script/generate initializer NAME [options]
+ rails generate initializer NAME [options]
</shell>
We can also see in our new generator that it has a class method called +source_root+. This method points to where our generator templates will be placed and by default it points to the created directory under +RAILS_APP/lib/generators/initializer/templates+. In order to understand what a generator template means, let's create a file at +RAILS_APP/lib/generators/initializer/templates/initializer.rb+ with the following content:
@@ -128,7 +128,7 @@ end
And let's execute our generator:
<shell>
-$ ruby script/generate initializer foo
+$ rails generate initializer foo
</shell>
We can see that now a initializer named foo was created at +config/initializers/foo.rb+ with the contents of our template. That means that copy_file copied a file in our source root to the destination path we gave. The method +file_name+ is automatically created when we inherit from +Rails::Generators::NamedBase+.
@@ -166,7 +166,7 @@ end
Before we customize our workflow, let's first see how our scaffold looks like:
<shell>
-$ ruby script/generate scaffold User name:string
+$ rails generate scaffold User name:string
invoke active_record
create db/migrate/20091120125558_create_users.rb
create app/models/user.rb
@@ -212,7 +212,7 @@ If we generate another resource on scaffold, we can notice that neither styleshe
To show that, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator:
<shell>
-$ ruby script/generate generator my_helper
+$ rails generate generator my_helper
</shell>
After that, we can delete both templates directory and the +source_root+ class method from our new generators, because we are not going to need them. So our new generator looks like the following:
@@ -232,7 +232,7 @@ end
We can try out our new generator by creating a helper for users:
<shell>
-$ ruby script/generate my_helper users
+$ rails generate my_helper users
</shell>
And it will generate the following helper file in app/helpers:
@@ -258,7 +258,7 @@ end
And see it in action when invoking generator once again:
<shell>
-$ ruby script/generate scaffold Post body:text
+$ rails generate scaffold Post body:text
[...]
invoke my_helper
create app/helpers/posts_helper.rb
@@ -343,7 +343,7 @@ Rails::Generators.fallbacks[:shoulda] = :test_unit
Now, if create a Comment scaffold, you will see that shoulda generators are being invoked, and at the end, they are just falling back to test unit generators:
<shell>
-$ ruby script/generate scaffold Comment body:text
+$ rails generate scaffold Comment body:text
invoke active_record
create db/migrate/20091120151323_create_comments.rb
create app/models/comment.rb
diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile
index 771c3e2523..558cbb4771 100644
--- a/railties/guides/source/migrations.textile
+++ b/railties/guides/source/migrations.textile
@@ -105,7 +105,7 @@ h4. Creating a Model
The model and scaffold generators will create migrations appropriate for adding a new model. This migration will already contain instructions for creating the relevant table. If you tell Rails what columns you want then statements for adding those will also be created. For example, running
<shell>
-ruby script/generate model Product name:string description:text
+rails generate model Product name:string description:text
</shell>
will create a migration that looks like this
@@ -135,7 +135,7 @@ h4. Creating a Standalone Migration
If you are creating migrations for other purposes (for example to add a column to an existing table) then you can use the migration generator:
<shell>
-ruby script/generate migration AddPartNumberToProducts
+rails generate migration AddPartNumberToProducts
</shell>
This will create an empty but appropriately named migration:
@@ -153,7 +153,7 @@ end
If the migration name is of the form "AddXXXToYYY" or "RemoveXXXFromYYY" and is followed by a list of column names and types then a migration containing the appropriate +add_column+ and +remove_column+ statements will be created.
<shell>
-ruby script/generate migration AddPartNumberToProducts part_number:string
+rails generate migration AddPartNumberToProducts part_number:string
</shell>
will generate
@@ -173,7 +173,7 @@ end
Similarly,
<shell>
-ruby script/generate migration RemovePartNumberFromProducts part_number:string
+rails generate migration RemovePartNumberFromProducts part_number:string
</shell>
generates
@@ -193,7 +193,7 @@ end
You are not limited to one magically generated column, for example
<shell>
-ruby script/generate migration AddDetailsToProducts part_number:string price:decimal
+rails generate migration AddDetailsToProducts part_number:string price:decimal
</shell>
generates
diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile
index f0dc9acbb8..5c760a5966 100644
--- a/railties/guides/source/performance_testing.textile
+++ b/railties/guides/source/performance_testing.textile
@@ -37,7 +37,7 @@ h4. Generating Performance Tests
Rails provides a generator called +performance_test+ for creating new performance tests:
<shell>
-script/generate performance_test homepage
+rails generate performance_test homepage
</shell>
This generates +homepage_test.rb+ in the +test/performance+ directory:
@@ -381,19 +381,19 @@ h4. +benchmarker+
Usage:
<shell>
-$ script/performance/benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ...
+$ rails benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ...
</shell>
Examples:
<shell>
-$ script/performance/benchmarker 10 'Item.all' 'CouchItem.all'
+$ rails benchmarker 10 'Item.all' 'CouchItem.all'
</shell>
If the +[times]+ argument is omitted, supplied methods are run just once:
<shell>
-$ script/performance/benchmarker 'Item.first' 'Item.last'
+$ rails benchmarker 'Item.first' 'Item.last'
</shell>
h4. +profiler+
@@ -403,19 +403,19 @@ h4. +profiler+
Usage:
<shell>
-$ script/performance/profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]
+$ rails profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]
</shell>
Examples:
<shell>
-$ script/performance/profiler 'Item.all'
+$ rails profiler 'Item.all'
</shell>
This will profile +Item.all+ in +RubyProf::WALL_TIME+ measure mode. By default, it prints flat output to the shell.
<shell>
-$ script/performance/profiler 'Item.all' 10 graph
+$ rails profiler 'Item.all' 10 graph
</shell>
This will profile +10.times { Item.all }+ with +RubyProf::WALL_TIME+ measure mode and print graph output to the shell.
@@ -423,7 +423,7 @@ This will profile +10.times { Item.all }+ with +RubyProf::WALL_TIME+ measure mod
If you want to store the output in a file:
<shell>
-$ script/performance/profiler 'Item.all' 10 graph 2> graph.txt
+$ rails profiler 'Item.all' 10 graph 2> graph.txt
</shell>
h3. Helper Methods
diff --git a/railties/guides/source/plugins.textile b/railties/guides/source/plugins.textile
index 06d0d493e4..71e1a7e3d3 100644
--- a/railties/guides/source/plugins.textile
+++ b/railties/guides/source/plugins.textile
@@ -39,9 +39,9 @@ The examples in this guide require that you have a working rails application. T
gem install rails
rails yaffle_guide
cd yaffle_guide
-script/generate scaffold bird name:string
+rails generate scaffold bird name:string
rake db:migrate
-script/server
+rails server
</pre>
Then navigate to http://localhost:3000/birds. Make sure you have a functioning rails app before continuing.
@@ -57,16 +57,16 @@ This creates a plugin in 'vendor/plugins' including an 'init.rb' and 'README' as
Examples:
<pre>
-./script/generate plugin yaffle
-./script/generate plugin yaffle --with-generator
+rails generate plugin yaffle
+rails generate plugin yaffle --with-generator
</pre>
-To get more detailed help on the plugin generator, type +./script/generate plugin+.
+To get more detailed help on the plugin generator, type +rails generate plugin+.
Later on this guide will describe how to work with generators, so go ahead and generate your plugin with the +--with-generator+ option now:
<pre>
-./script/generate plugin yaffle --with-generator
+rails generate plugin yaffle --with-generator
</pre>
You should see the following output:
@@ -334,7 +334,7 @@ end
To test that your method does what it says it does, run the unit tests with +rake+ from your plugin directory. To see this in action, fire up a console and start squawking:
<shell>
-$ ./script/console
+$ rails console
>> "Hello World".to_squawk
=> "squawk! Hello World"
</shell>
@@ -871,7 +871,7 @@ If you plan to distribute your plugin, developers will expect at least a minimum
Rails ships with several built-in generators. You can see all of the generators available to you by typing the following at the command line:
<shell>
-./script/generate
+rails generate
</shell>
You should see something like this:
@@ -882,7 +882,7 @@ Installed Generators
Builtin: controller, integration_test, mailer, migration, model, observer, plugin, resource, scaffold, session_migration
</shell>
-When you run +script/generate yaffle_definition -h+ you should see the contents of your 'vendor/plugins/yaffle/generators/yaffle_definition/USAGE'.
+When you run +rails generate yaffle_definition -h+ you should see the contents of your 'vendor/plugins/yaffle/generators/yaffle_definition/USAGE'.
For this plugin, update the USAGE file could look like this:
@@ -1111,11 +1111,11 @@ end
To see this work, type:
<shell>
-./script/generate yaffle_route
-./script/destroy yaffle_route
+rails generate yaffle_route
+rails destroy yaffle_route
</shell>
-NOTE: If you haven't set up the custom route from above, 'script/destroy' will fail and you'll have to remove it manually.
+NOTE: If you haven't set up the custom route from above, 'rails destroy' will fail and you'll have to remove it manually.
h3. Migrations
@@ -1195,7 +1195,7 @@ h4. Generate Migrations
Generating migrations has several advantages over other methods. Namely, you can allow other developers to more easily customize the migration. The flow looks like this:
- * call your script/generate script and pass in whatever options they need
+ * call your rails generate script and pass in whatever options they need
* examine the generated migration, adding/removing columns or other options as necessary
This example will demonstrate how to use one of the built-in generator methods named 'migration_template' to create a migration file. Extending the rails migration generator requires a somewhat intimate knowledge of the migration generator internals, so it's best to write a test first:
@@ -1289,7 +1289,7 @@ It's courteous to check to see if table names are being pluralized whenever you
To run the generator, type the following at the command line:
<shell>
-./script/generate yaffle_migration bird
+rails generate yaffle_migration bird
</shell>
and you will see a new file:
diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile
index df93580e89..eef44d9ec9 100644
--- a/railties/guides/source/rails_on_rack.textile
+++ b/railties/guides/source/rails_on_rack.textile
@@ -30,11 +30,11 @@ h4. Rails Application's Rack Object
<tt>ActionController::Dispatcher.new</tt> is the primary Rack application object of a Rails application. Any Rack compliant web server should be using +ActionController::Dispatcher.new+ object to serve a Rails application.</p>
-h4. +script/server+
+h4. +rails server+
-<tt>script/server</tt> does the basic job of creating a +Rack::Builder+ object and starting the webserver. This is Rails' equivalent of Rack's +rackup+ script.
+<tt>rails server</tt> does the basic job of creating a +Rack::Builder+ object and starting the webserver. This is Rails' equivalent of Rack's +rackup+ script.
-Here's how +script/server+ creates an instance of +Rack::Builder+
+Here's how +rails server+ creates an instance of +Rack::Builder+
<ruby>
app = Rack::Builder.new {
@@ -54,7 +54,7 @@ Middlewares used in the code above are primarily useful only in the development
h4. +rackup+
-To use +rackup+ instead of Rails' +script/server+, you can put the following inside +config.ru+ of your Rails application's root directory:
+To use +rackup+ instead of Rails' +rails server+, you can put the following inside +config.ru+ of your Rails application's root directory:
<ruby>
# RAILS_ROOT/config.ru
@@ -233,7 +233,7 @@ h4. Generating a Metal Application
Rails provides a generator called +metal+ for creating a new Metal application:
<shell>
-$ script/generate metal poller
+$ rails generate metal poller
</shell>
This generates +poller.rb+ in the +app/metal+ directory:
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index c7b475899f..ac9fb4276e 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -56,7 +56,7 @@ h5. What are Fixtures?
_Fixtures_ is a fancy word for sample data. Fixtures allow you to populate your testing database with predefined data before your tests run. Fixtures are database independent and assume one of two formats: *YAML* or *CSV*. In this guide we will use *YAML* which is the preferred format.
-You'll find fixtures under your +test/fixtures+ directory. When you run +script/generate model+ to create a new model, fixture stubs will be automatically created and placed in this directory.
+You'll find fixtures under your +test/fixtures+ directory. When you run +rails generate model+ to create a new model, fixture stubs will be automatically created and placed in this directory.
h5. YAML
@@ -144,10 +144,10 @@ For this guide we will be using Rails _scaffolding_. It will create the model, a
NOTE: For more information on Rails _scaffolding_, refer to "Getting Started with Rails":getting_started.html
-When you use +script/generate scaffold+, for a resource among other things it creates a test stub in the +test/unit+ folder:
+When you use +rails generate scaffold+, for a resource among other things it creates a test stub in the +test/unit+ folder:
<pre>
-$ script/generate scaffold post title:string body:text
+$ rails generate scaffold post title:string body:text
...
create app/models/post.rb
create test/unit/post_test.rb
@@ -604,7 +604,7 @@ Integration tests are used to test the interaction among any number of controlle
Unlike Unit and Functional tests, integration tests have to be explicitly created under the 'test/integration' folder within your application. Rails provides a generator to create an integration test skeleton for you.
<shell>
-$ script/generate integration_test user_flows
+$ rails generate integration_test user_flows
exists test/integration/
create test/integration/user_flows_test.rb
</shell>
diff --git a/railties/lib/generators/erb/scaffold/templates/layout.html.erb b/railties/lib/generators/erb/scaffold/templates/layout.html.erb
index 7aa049fe80..420d17f33c 100644
--- a/railties/lib/generators/erb/scaffold/templates/layout.html.erb
+++ b/railties/lib/generators/erb/scaffold/templates/layout.html.erb
@@ -3,6 +3,8 @@
<head>
<title><%= controller_class_name %>: <%%= controller.action_name %></title>
<%%= stylesheet_link_tag 'scaffold' %>
+ <%%= javascript_include_tag :defaults %>
+ <%%= csrf_meta_tag %>
</head>
<body>
diff --git a/railties/lib/generators/rails/app/templates/Gemfile b/railties/lib/generators/rails/app/templates/Gemfile
index f51edc4d2f..f4bce8646d 100644
--- a/railties/lib/generators/rails/app/templates/Gemfile
+++ b/railties/lib/generators/rails/app/templates/Gemfile
@@ -1,34 +1,34 @@
-# Edit this Gemfile to bundle your application's dependencies.
source 'http://gemcutter.org'
-<% if !dev_or_edge? %>
-gem "rails", "<%= Rails::VERSION::STRING %>"
-<% end -%>
-
-## Bundle edge rails:
<%- if options.dev? -%>
-path "<%= Rails::Generators::RAILS_DEV_PATH %>", :glob => "{*/,}*.gemspec"
-gem "rails", "<%= Rails::VERSION::STRING %>"
+gem 'rails', :path => '<%= Rails::Generators::RAILS_DEV_PATH %>'
+<%- elsif options.edge? -%>
+gem 'rails', :git => 'git://github.com/rails/rails.git'
<%- else -%>
-<%= "# " unless options.edge? %>gem "rails", :git => "git://github.com/rails/rails.git"
+gem 'rails', '<%= Rails::VERSION::STRING %>'
+
+# Bundle edge Rails instead:
+# gem 'rails', :git => 'git://github.com/rails/rails.git'
<%- end -%>
<% unless options[:skip_activerecord] -%>
-<% if options[:database] == 'sqlite3' -%>
-# ActiveRecord requires a database adapter. By default,
-# Rails has selected sqlite3.
-<% end -%>
-gem "<%= gem_for_database %>"<% if require_for_database %>, :require => "<%= require_for_database %>"<% end %>
+gem '<%= gem_for_database %>'<% if require_for_database %>, :require => '<%= require_for_database %>'<% end %>
<% end -%>
-## Bundle the gems you use:
-# gem "bj"
-# gem "hpricot", "0.6"
-# gem "sqlite3-ruby", :require => "sqlite3"
-# gem "aws-s3", :require => "aws/s3"
+# Use mongrel as the web server
+# gem 'mongrel'
+
+# Deploy with Capistrano
+# gem 'capistrano'
+
+# Bundle the extra gems:
+# gem 'bj'
+# gem 'hpricot', '0.6'
+# gem 'sqlite3-ruby', :require => 'sqlite3'
+# gem 'aws-s3', :require => 'aws/s3'
-## Bundle gems used only in certain environments:
-# gem "rspec", :group => :test
+# Bundle gems for certain environments:
+# gem 'rspec', :group => :test
# group :test do
-# gem "webrat"
+# gem 'webrat'
# end
diff --git a/railties/lib/generators/rails/app/templates/config/application.rb b/railties/lib/generators/rails/app/templates/config/application.rb
index 78a355d2f4..7c555c2542 100644
--- a/railties/lib/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/generators/rails/app/templates/config/application.rb
@@ -1,5 +1,19 @@
require File.expand_path('../boot', __FILE__)
+<% unless options[:skip_activerecord] -%>
+require 'rails/all'
+<% else -%>
+# Pick the frameworks you want:
+# require "active_record/railtie"
+require "action_controller/railtie"
+require "action_mailer/railtie"
+require "active_resource/railtie"
+require "rails/test_unit/railtie"
+<% end -%>
+
+# Auto-require default libraries and those for the current Rails environment.
+Bundler.require :default, Rails.env
+
module <%= app_const_base %>
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
diff --git a/railties/lib/generators/rails/app/templates/config/boot.rb b/railties/lib/generators/rails/app/templates/config/boot.rb
index 03396113e8..29c9d506e5 100644
--- a/railties/lib/generators/rails/app/templates/config/boot.rb
+++ b/railties/lib/generators/rails/app/templates/config/boot.rb
@@ -15,32 +15,3 @@ rescue LoadError
#
# require 'rubygems'
end
-
-# Auto-require all bundled libraries.
-Bundler.require
-
-<% unless options[:skip_activerecord] -%>
-require 'rails/all'
-
-# To pick the frameworks you want, remove 'require "rails/all"'
-# and list the framework railties that you want:
-#
-# require "active_support/railtie"
-# require "active_model/railtie"
-# require "active_record/railtie"
-# require "action_controller/railtie"
-# require "action_view/railtie"
-# require "action_mailer/railtie"
-# require "active_resource/railtie"
-# require "rails/test_unit/railtie"
-<% else -%>
-# Pick the frameworks you want:
-# require "active_model/railtie"
-# require "active_record/railtie"
-require "active_support/railtie"
-require "action_controller/railtie"
-require "action_view/railtie"
-require "action_mailer/railtie"
-require "active_resource/railtie"
-require "rails/test_unit/railtie"
-<% end -%>
diff --git a/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml
index 2cecb5c879..2784a949fb 100644
--- a/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml
+++ b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml
@@ -4,23 +4,32 @@
# http://rubyforge.org/projects/rubyibm/
#
# To install the ibm_db gem:
+#
# On Linux:
-# Source the db2profile file and set the necessary environment variables:
+# . /home/db2inst1/sqllib/db2profile
+# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include
+# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib32
+# gem install ibm_db
#
+# On Mac OS X 10.5:
# . /home/db2inst1/sqllib/db2profile
-# export IBM_DB_DIR=/opt/ibm/db2/V9.1
-# export IBM_DB_LIB=/opt/ibm/db2/V9.1/lib32
+# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include
+# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib32
+# export ARCHFLAGS="-arch i386"
+# gem install ibm_db
#
-# Then issue the command: gem install ibm_db
+# On Mac OS X 10.6:
+# . /home/db2inst1/sqllib/db2profile
+# export IBM_DB_INCLUDE=/opt/ibm/db2/V9.7/include
+# export IBM_DB_LIB=/opt/ibm/db2/V9.7/lib64
+# export ARCHFLAGS="-arch x86_64"
+# gem install ibm_db
#
# On Windows:
-# Issue the command: gem install ibm_db
-# If prompted, select the mswin32 option
-#
-# For more details on the installation refer to http://rubyforge.org/docman/view.php/2361/7682/IBM_DB_GEM.pdf
+# Issue the command: gem install ibm_db
#
-# For more details on the connection parameters below refer to:
-# http://rubyibm.rubyforge.org/docs/adapter/0.9.0/rdoc/classes/ActiveRecord/ConnectionAdapters/IBM_DBAdapter.html
+# For more details on the installation and the connection parameters below,
+# please refer to the latest documents at http://rubyforge.org/docman/?group_id=2361
development:
adapter: ibm_db
@@ -52,7 +61,7 @@ production:
adapter: ibm_db
username: db2inst1
password:
- database: <%= app_name[0,4] %>_prd
+ database: <%= app_name[0,8] %>
#schema: db2inst1
#host: localhost
#port: 50000
diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/controls.js b/railties/lib/generators/rails/app/templates/public/javascripts/controls.js
index ca29aefdd1..7392fb664c 100644
--- a/railties/lib/generators/rails/app/templates/public/javascripts/controls.js
+++ b/railties/lib/generators/rails/app/templates/public/javascripts/controls.js
@@ -1,6 +1,8 @@
-// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
-// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
+// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009
+
+// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2009 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js b/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js
index 07229f986f..15c6dbca68 100644
--- a/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js
+++ b/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js
@@ -1,5 +1,6 @@
-// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+// script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009
+
+// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
@@ -311,7 +312,7 @@ var Draggable = Class.create({
tag_name=='TEXTAREA')) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
- var pos = Position.cumulativeOffset(this.element);
+ var pos = this.element.cumulativeOffset();
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
Draggables.activate(this);
@@ -454,7 +455,7 @@ var Draggable = Class.create({
},
draw: function(point) {
- var pos = Position.cumulativeOffset(this.element);
+ var pos = this.element.cumulativeOffset();
if(this.options.ghosting) {
var r = Position.realOffset(this.element);
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
@@ -730,7 +731,7 @@ var Sortable = {
}
// keep reference
- this.sortables[element.id] = options;
+ this.sortables[element.identify()] = options;
// for onupdate
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
@@ -825,7 +826,7 @@ var Sortable = {
hide().addClassName('dropmarker').setStyle({position:'absolute'});
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
}
- var offsets = Position.cumulativeOffset(dropon);
+ var offsets = dropon.cumulativeOffset();
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
if(position=='after')
diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/effects.js b/railties/lib/generators/rails/app/templates/public/javascripts/effects.js
index 5a639d2dea..066ee5909c 100644
--- a/railties/lib/generators/rails/app/templates/public/javascripts/effects.js
+++ b/railties/lib/generators/rails/app/templates/public/javascripts/effects.js
@@ -1,4 +1,6 @@
-// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009
+
+// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
@@ -145,14 +147,13 @@ var Effect = {
'blind': ['BlindDown','BlindUp'],
'appear': ['Appear','Fade']
},
- toggle: function(element, effect) {
+ toggle: function(element, effect, options) {
element = $(element);
- effect = (effect || 'appear').toLowerCase();
- var options = Object.extend({
+ effect = (effect || 'appear').toLowerCase();
+
+ return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
- }, arguments[2] || { });
- Effect[element.visible() ?
- Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+ }, options || {}));
}
};
@@ -228,12 +229,6 @@ Effect.Queue = Effect.Queues.get('global');
Effect.Base = Class.create({
position: null,
start: function(options) {
- function codeForEvent(options,eventName){
- return (
- (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
- (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
- );
- }
if (options && options.transition === false) options.transition = Effect.Transitions.linear;
this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
this.currentFrame = 0;
diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js
index dfe8ab4e13..9fe6e1243b 100644
--- a/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js
+++ b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js
@@ -1,5 +1,5 @@
-/* Prototype JavaScript framework, version 1.6.0.3
- * (c) 2005-2008 Sam Stephenson
+/* Prototype JavaScript framework, version 1.6.1
+ * (c) 2005-2009 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
@@ -7,26 +7,43 @@
*--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.6.0.3',
-
- Browser: {
- IE: !!(window.attachEvent &&
- navigator.userAgent.indexOf('Opera') === -1),
- Opera: navigator.userAgent.indexOf('Opera') > -1,
- WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
- Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
- navigator.userAgent.indexOf('KHTML') === -1,
- MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
- },
+ Version: '1.6.1',
+
+ Browser: (function(){
+ var ua = navigator.userAgent;
+ var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
+ return {
+ IE: !!window.attachEvent && !isOpera,
+ Opera: isOpera,
+ WebKit: ua.indexOf('AppleWebKit/') > -1,
+ Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
+ MobileSafari: /Apple.*Mobile.*Safari/.test(ua)
+ }
+ })(),
BrowserFeatures: {
XPath: !!document.evaluate,
SelectorsAPI: !!document.querySelector,
- ElementExtensions: !!window.HTMLElement,
- SpecificElementExtensions:
- document.createElement('div')['__proto__'] &&
- document.createElement('div')['__proto__'] !==
- document.createElement('form')['__proto__']
+ ElementExtensions: (function() {
+ var constructor = window.Element || window.HTMLElement;
+ return !!(constructor && constructor.prototype);
+ })(),
+ SpecificElementExtensions: (function() {
+ if (typeof window.HTMLDivElement !== 'undefined')
+ return true;
+
+ var div = document.createElement('div');
+ var form = document.createElement('form');
+ var isSupported = false;
+
+ if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
+ isSupported = true;
+ }
+
+ div = form = null;
+
+ return isSupported;
+ })()
},
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
@@ -40,9 +57,30 @@ if (Prototype.Browser.MobileSafari)
Prototype.BrowserFeatures.SpecificElementExtensions = false;
+var Abstract = { };
+
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
/* Based on Alex Arnell's inheritance implementation. */
-var Class = {
- create: function() {
+
+var Class = (function() {
+ function subclass() {};
+ function create() {
var parent = null, properties = $A(arguments);
if (Object.isFunction(properties[0]))
parent = properties.shift();
@@ -56,7 +94,6 @@ var Class = {
klass.subclasses = [];
if (parent) {
- var subclass = function() { };
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
@@ -69,18 +106,19 @@ var Class = {
klass.prototype.initialize = Prototype.emptyFunction;
klass.prototype.constructor = klass;
-
return klass;
}
-};
-Class.Methods = {
- addMethods: function(source) {
+ function addMethods(source) {
var ancestor = this.superclass && this.superclass.prototype;
var properties = Object.keys(source);
- if (!Object.keys({ toString: true }).length)
- properties.push("toString", "valueOf");
+ if (!Object.keys({ toString: true }).length) {
+ if (source.toString != Object.prototype.toString)
+ properties.push("toString");
+ if (source.valueOf != Object.prototype.valueOf)
+ properties.push("valueOf");
+ }
for (var i = 0, length = properties.length; i < length; i++) {
var property = properties[i], value = source[property];
@@ -88,7 +126,7 @@ Class.Methods = {
value.argumentNames().first() == "$super") {
var method = value;
value = (function(m) {
- return function() { return ancestor[m].apply(this, arguments) };
+ return function() { return ancestor[m].apply(this, arguments); };
})(property).wrap(method);
value.valueOf = method.valueOf.bind(method);
@@ -99,29 +137,36 @@ Class.Methods = {
return this;
}
-};
-var Abstract = { };
+ return {
+ create: create,
+ Methods: {
+ addMethods: addMethods
+ }
+ };
+})();
+(function() {
-Object.extend = function(destination, source) {
- for (var property in source)
- destination[property] = source[property];
- return destination;
-};
+ var _toString = Object.prototype.toString;
-Object.extend(Object, {
- inspect: function(object) {
+ function extend(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+ }
+
+ function inspect(object) {
try {
- if (Object.isUndefined(object)) return 'undefined';
+ if (isUndefined(object)) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
- },
+ }
- toJSON: function(object) {
+ function toJSON(object) {
var type = typeof object;
switch (type) {
case 'undefined':
@@ -132,131 +177,180 @@ Object.extend(Object, {
if (object === null) return 'null';
if (object.toJSON) return object.toJSON();
- if (Object.isElement(object)) return;
+ if (isElement(object)) return;
var results = [];
for (var property in object) {
- var value = Object.toJSON(object[property]);
- if (!Object.isUndefined(value))
+ var value = toJSON(object[property]);
+ if (!isUndefined(value))
results.push(property.toJSON() + ': ' + value);
}
return '{' + results.join(', ') + '}';
- },
+ }
- toQueryString: function(object) {
+ function toQueryString(object) {
return $H(object).toQueryString();
- },
+ }
- toHTML: function(object) {
+ function toHTML(object) {
return object && object.toHTML ? object.toHTML() : String.interpret(object);
- },
+ }
- keys: function(object) {
- var keys = [];
+ function keys(object) {
+ var results = [];
for (var property in object)
- keys.push(property);
- return keys;
- },
+ results.push(property);
+ return results;
+ }
- values: function(object) {
- var values = [];
+ function values(object) {
+ var results = [];
for (var property in object)
- values.push(object[property]);
- return values;
- },
+ results.push(object[property]);
+ return results;
+ }
- clone: function(object) {
- return Object.extend({ }, object);
- },
+ function clone(object) {
+ return extend({ }, object);
+ }
- isElement: function(object) {
+ function isElement(object) {
return !!(object && object.nodeType == 1);
- },
+ }
+
+ function isArray(object) {
+ return _toString.call(object) == "[object Array]";
+ }
- isArray: function(object) {
- return object != null && typeof object == "object" &&
- 'splice' in object && 'join' in object;
- },
- isHash: function(object) {
+ function isHash(object) {
return object instanceof Hash;
- },
+ }
- isFunction: function(object) {
- return typeof object == "function";
- },
+ function isFunction(object) {
+ return typeof object === "function";
+ }
- isString: function(object) {
- return typeof object == "string";
- },
+ function isString(object) {
+ return _toString.call(object) == "[object String]";
+ }
- isNumber: function(object) {
- return typeof object == "number";
- },
+ function isNumber(object) {
+ return _toString.call(object) == "[object Number]";
+ }
- isUndefined: function(object) {
- return typeof object == "undefined";
+ function isUndefined(object) {
+ return typeof object === "undefined";
}
-});
-Object.extend(Function.prototype, {
- argumentNames: function() {
- var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
+ extend(Object, {
+ extend: extend,
+ inspect: inspect,
+ toJSON: toJSON,
+ toQueryString: toQueryString,
+ toHTML: toHTML,
+ keys: keys,
+ values: values,
+ clone: clone,
+ isElement: isElement,
+ isArray: isArray,
+ isHash: isHash,
+ isFunction: isFunction,
+ isString: isString,
+ isNumber: isNumber,
+ isUndefined: isUndefined
+ });
+})();
+Object.extend(Function.prototype, (function() {
+ var slice = Array.prototype.slice;
+
+ function update(array, args) {
+ var arrayLength = array.length, length = args.length;
+ while (length--) array[arrayLength + length] = args[length];
+ return array;
+ }
+
+ function merge(array, args) {
+ array = slice.call(array, 0);
+ return update(array, args);
+ }
+
+ function argumentNames() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
+ .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
.replace(/\s+/g, '').split(',');
return names.length == 1 && !names[0] ? [] : names;
- },
+ }
- bind: function() {
+ function bind(context) {
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
- var __method = this, args = $A(arguments), object = args.shift();
+ var __method = this, args = slice.call(arguments, 1);
return function() {
- return __method.apply(object, args.concat($A(arguments)));
+ var a = merge(args, arguments);
+ return __method.apply(context, a);
}
- },
+ }
- bindAsEventListener: function() {
- var __method = this, args = $A(arguments), object = args.shift();
+ function bindAsEventListener(context) {
+ var __method = this, args = slice.call(arguments, 1);
return function(event) {
- return __method.apply(object, [event || window.event].concat(args));
+ var a = update([event || window.event], args);
+ return __method.apply(context, a);
}
- },
+ }
- curry: function() {
+ function curry() {
if (!arguments.length) return this;
- var __method = this, args = $A(arguments);
+ var __method = this, args = slice.call(arguments, 0);
return function() {
- return __method.apply(this, args.concat($A(arguments)));
+ var a = merge(args, arguments);
+ return __method.apply(this, a);
}
- },
+ }
- delay: function() {
- var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ function delay(timeout) {
+ var __method = this, args = slice.call(arguments, 1);
+ timeout = timeout * 1000
return window.setTimeout(function() {
return __method.apply(__method, args);
}, timeout);
- },
+ }
- defer: function() {
- var args = [0.01].concat($A(arguments));
+ function defer() {
+ var args = update([0.01], arguments);
return this.delay.apply(this, args);
- },
+ }
- wrap: function(wrapper) {
+ function wrap(wrapper) {
var __method = this;
return function() {
- return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ var a = update([__method.bind(this)], arguments);
+ return wrapper.apply(this, a);
}
- },
+ }
- methodize: function() {
+ function methodize() {
if (this._methodized) return this._methodized;
var __method = this;
return this._methodized = function() {
- return __method.apply(null, [this].concat($A(arguments)));
+ var a = update([this], arguments);
+ return __method.apply(null, a);
};
}
-});
+
+ return {
+ argumentNames: argumentNames,
+ bind: bind,
+ bindAsEventListener: bindAsEventListener,
+ curry: curry,
+ delay: delay,
+ defer: defer,
+ wrap: wrap,
+ methodize: methodize
+ }
+})());
+
Date.prototype.toJSON = function() {
return '"' + this.getUTCFullYear() + '-' +
@@ -267,30 +361,12 @@ Date.prototype.toJSON = function() {
this.getUTCSeconds().toPaddedString(2) + 'Z"';
};
-var Try = {
- these: function() {
- var returnValue;
-
- for (var i = 0, length = arguments.length; i < length; i++) {
- var lambda = arguments[i];
- try {
- returnValue = lambda();
- break;
- } catch (e) { }
- }
-
- return returnValue;
- }
-};
RegExp.prototype.match = RegExp.prototype.test;
RegExp.escape = function(str) {
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
-
-/*--------------------------------------------------------------------------*/
-
var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
@@ -319,8 +395,10 @@ var PeriodicalExecuter = Class.create({
try {
this.currentlyExecuting = true;
this.execute();
- } finally {
this.currentlyExecuting = false;
+ } catch(e) {
+ this.currentlyExecuting = false;
+ throw e;
}
}
}
@@ -339,10 +417,25 @@ Object.extend(String, {
}
});
-Object.extend(String.prototype, {
- gsub: function(pattern, replacement) {
+Object.extend(String.prototype, (function() {
+
+ function prepareReplacement(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+ }
+
+ function gsub(pattern, replacement) {
var result = '', source = this, match;
- replacement = arguments.callee.prepareReplacement(replacement);
+ replacement = prepareReplacement(replacement);
+
+ if (Object.isString(pattern))
+ pattern = RegExp.escape(pattern);
+
+ if (!(pattern.length || pattern.source)) {
+ replacement = replacement('');
+ return replacement + source.split('').join(replacement) + replacement;
+ }
while (source.length > 0) {
if (match = source.match(pattern)) {
@@ -354,69 +447,64 @@ Object.extend(String.prototype, {
}
}
return result;
- },
+ }
- sub: function(pattern, replacement, count) {
- replacement = this.gsub.prepareReplacement(replacement);
+ function sub(pattern, replacement, count) {
+ replacement = prepareReplacement(replacement);
count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
return replacement(match);
});
- },
+ }
- scan: function(pattern, iterator) {
+ function scan(pattern, iterator) {
this.gsub(pattern, iterator);
return String(this);
- },
+ }
- truncate: function(length, truncation) {
+ function truncate(length, truncation) {
length = length || 30;
truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
this.slice(0, length - truncation.length) + truncation : String(this);
- },
+ }
- strip: function() {
+ function strip() {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
- },
+ }
- stripTags: function() {
- return this.replace(/<\/?[^>]+>/gi, '');
- },
+ function stripTags() {
+ return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
+ }
- stripScripts: function() {
+ function stripScripts() {
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
- },
+ }
- extractScripts: function() {
+ function extractScripts() {
var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
return (this.match(matchAll) || []).map(function(scriptTag) {
return (scriptTag.match(matchOne) || ['', ''])[1];
});
- },
+ }
- evalScripts: function() {
+ function evalScripts() {
return this.extractScripts().map(function(script) { return eval(script) });
- },
+ }
- escapeHTML: function() {
- var self = arguments.callee;
- self.text.data = this;
- return self.div.innerHTML;
- },
+ function escapeHTML() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ }
+
+ function unescapeHTML() {
+ return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
+ }
- unescapeHTML: function() {
- var div = new Element('div');
- div.innerHTML = this.stripTags();
- return div.childNodes[0] ? (div.childNodes.length > 1 ?
- $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
- div.childNodes[0].nodeValue) : '';
- },
- toQueryParams: function(separator) {
+ function toQueryParams(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return { };
@@ -434,22 +522,22 @@ Object.extend(String.prototype, {
}
return hash;
});
- },
+ }
- toArray: function() {
+ function toArray() {
return this.split('');
- },
+ }
- succ: function() {
+ function succ() {
return this.slice(0, this.length - 1) +
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
- },
+ }
- times: function(count) {
+ function times(count) {
return count < 1 ? '' : new Array(count + 1).join(this);
- },
+ }
- camelize: function() {
+ function camelize() {
var parts = this.split('-'), len = parts.length;
if (len == 1) return parts[0];
@@ -461,101 +549,117 @@ Object.extend(String.prototype, {
camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
return camelized;
- },
+ }
- capitalize: function() {
+ function capitalize() {
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
- },
+ }
- underscore: function() {
- return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
- },
+ function underscore() {
+ return this.replace(/::/g, '/')
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
+ .replace(/([a-z\d])([A-Z])/g, '$1_$2')
+ .replace(/-/g, '_')
+ .toLowerCase();
+ }
- dasherize: function() {
- return this.gsub(/_/,'-');
- },
+ function dasherize() {
+ return this.replace(/_/g, '-');
+ }
- inspect: function(useDoubleQuotes) {
- var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
- var character = String.specialChar[match[0]];
- return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ function inspect(useDoubleQuotes) {
+ var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
+ if (character in String.specialChar) {
+ return String.specialChar[character];
+ }
+ return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
});
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
return "'" + escapedString.replace(/'/g, '\\\'') + "'";
- },
+ }
- toJSON: function() {
+ function toJSON() {
return this.inspect(true);
- },
+ }
- unfilterJSON: function(filter) {
- return this.sub(filter || Prototype.JSONFilter, '#{1}');
- },
+ function unfilterJSON(filter) {
+ return this.replace(filter || Prototype.JSONFilter, '$1');
+ }
- isJSON: function() {
+ function isJSON() {
var str = this;
if (str.blank()) return false;
str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
- },
+ }
- evalJSON: function(sanitize) {
+ function evalJSON(sanitize) {
var json = this.unfilterJSON();
try {
if (!sanitize || json.isJSON()) return eval('(' + json + ')');
} catch (e) { }
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
- },
+ }
- include: function(pattern) {
+ function include(pattern) {
return this.indexOf(pattern) > -1;
- },
+ }
- startsWith: function(pattern) {
+ function startsWith(pattern) {
return this.indexOf(pattern) === 0;
- },
+ }
- endsWith: function(pattern) {
+ function endsWith(pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
- },
+ }
- empty: function() {
+ function empty() {
return this == '';
- },
+ }
- blank: function() {
+ function blank() {
return /^\s*$/.test(this);
- },
-
- interpolate: function(object, pattern) {
- return new Template(this, pattern).evaluate(object);
}
-});
-if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
- escapeHTML: function() {
- return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
- },
- unescapeHTML: function() {
- return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ function interpolate(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
}
-});
-
-String.prototype.gsub.prepareReplacement = function(replacement) {
- if (Object.isFunction(replacement)) return replacement;
- var template = new Template(replacement);
- return function(match) { return template.evaluate(match) };
-};
-
-String.prototype.parseQuery = String.prototype.toQueryParams;
-
-Object.extend(String.prototype.escapeHTML, {
- div: document.createElement('div'),
- text: document.createTextNode('')
-});
-String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
+ return {
+ gsub: gsub,
+ sub: sub,
+ scan: scan,
+ truncate: truncate,
+ strip: String.prototype.trim ? String.prototype.trim : strip,
+ stripTags: stripTags,
+ stripScripts: stripScripts,
+ extractScripts: extractScripts,
+ evalScripts: evalScripts,
+ escapeHTML: escapeHTML,
+ unescapeHTML: unescapeHTML,
+ toQueryParams: toQueryParams,
+ parseQuery: toQueryParams,
+ toArray: toArray,
+ succ: succ,
+ times: times,
+ camelize: camelize,
+ capitalize: capitalize,
+ underscore: underscore,
+ dasherize: dasherize,
+ inspect: inspect,
+ toJSON: toJSON,
+ unfilterJSON: unfilterJSON,
+ isJSON: isJSON,
+ evalJSON: evalJSON,
+ include: include,
+ startsWith: startsWith,
+ endsWith: endsWith,
+ empty: empty,
+ blank: blank,
+ interpolate: interpolate
+ };
+})());
var Template = Class.create({
initialize: function(template, pattern) {
@@ -564,11 +668,11 @@ var Template = Class.create({
},
evaluate: function(object) {
- if (Object.isFunction(object.toTemplateReplacements))
+ if (object && Object.isFunction(object.toTemplateReplacements))
object = object.toTemplateReplacements();
return this.template.gsub(this.pattern, function(match) {
- if (object == null) return '';
+ if (object == null) return (match[1] + '');
var before = match[1] || '';
if (before == '\\') return match[2];
@@ -579,7 +683,7 @@ var Template = Class.create({
if (match == null) return before;
while (match != null) {
- var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
ctx = ctx[comp];
if (null == ctx || '' == match[3]) break;
expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
@@ -594,8 +698,8 @@ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
var $break = { };
-var Enumerable = {
- each: function(iterator, context) {
+var Enumerable = (function() {
+ function each(iterator, context) {
var index = 0;
try {
this._each(function(value) {
@@ -605,17 +709,17 @@ var Enumerable = {
if (e != $break) throw e;
}
return this;
- },
+ }
- eachSlice: function(number, iterator, context) {
+ function eachSlice(number, iterator, context) {
var index = -number, slices = [], array = this.toArray();
if (number < 1) return array;
while ((index += number) < array.length)
slices.push(array.slice(index, index+number));
return slices.collect(iterator, context);
- },
+ }
- all: function(iterator, context) {
+ function all(iterator, context) {
iterator = iterator || Prototype.K;
var result = true;
this.each(function(value, index) {
@@ -623,9 +727,9 @@ var Enumerable = {
if (!result) throw $break;
});
return result;
- },
+ }
- any: function(iterator, context) {
+ function any(iterator, context) {
iterator = iterator || Prototype.K;
var result = false;
this.each(function(value, index) {
@@ -633,18 +737,18 @@ var Enumerable = {
throw $break;
});
return result;
- },
+ }
- collect: function(iterator, context) {
+ function collect(iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
this.each(function(value, index) {
results.push(iterator.call(context, value, index));
});
return results;
- },
+ }
- detect: function(iterator, context) {
+ function detect(iterator, context) {
var result;
this.each(function(value, index) {
if (iterator.call(context, value, index)) {
@@ -653,32 +757,32 @@ var Enumerable = {
}
});
return result;
- },
+ }
- findAll: function(iterator, context) {
+ function findAll(iterator, context) {
var results = [];
this.each(function(value, index) {
if (iterator.call(context, value, index))
results.push(value);
});
return results;
- },
+ }
- grep: function(filter, iterator, context) {
+ function grep(filter, iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
if (Object.isString(filter))
- filter = new RegExp(filter);
+ filter = new RegExp(RegExp.escape(filter));
this.each(function(value, index) {
if (filter.match(value))
results.push(iterator.call(context, value, index));
});
return results;
- },
+ }
- include: function(object) {
+ function include(object) {
if (Object.isFunction(this.indexOf))
if (this.indexOf(object) != -1) return true;
@@ -690,31 +794,31 @@ var Enumerable = {
}
});
return found;
- },
+ }
- inGroupsOf: function(number, fillWith) {
+ function inGroupsOf(number, fillWith) {
fillWith = Object.isUndefined(fillWith) ? null : fillWith;
return this.eachSlice(number, function(slice) {
while(slice.length < number) slice.push(fillWith);
return slice;
});
- },
+ }
- inject: function(memo, iterator, context) {
+ function inject(memo, iterator, context) {
this.each(function(value, index) {
memo = iterator.call(context, memo, value, index);
});
return memo;
- },
+ }
- invoke: function(method) {
+ function invoke(method) {
var args = $A(arguments).slice(1);
return this.map(function(value) {
return value[method].apply(value, args);
});
- },
+ }
- max: function(iterator, context) {
+ function max(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
@@ -723,9 +827,9 @@ var Enumerable = {
result = value;
});
return result;
- },
+ }
- min: function(iterator, context) {
+ function min(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
@@ -734,9 +838,9 @@ var Enumerable = {
result = value;
});
return result;
- },
+ }
- partition: function(iterator, context) {
+ function partition(iterator, context) {
iterator = iterator || Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
@@ -744,26 +848,26 @@ var Enumerable = {
trues : falses).push(value);
});
return [trues, falses];
- },
+ }
- pluck: function(property) {
+ function pluck(property) {
var results = [];
this.each(function(value) {
results.push(value[property]);
});
return results;
- },
+ }
- reject: function(iterator, context) {
+ function reject(iterator, context) {
var results = [];
this.each(function(value, index) {
if (!iterator.call(context, value, index))
results.push(value);
});
return results;
- },
+ }
- sortBy: function(iterator, context) {
+ function sortBy(iterator, context) {
return this.map(function(value, index) {
return {
value: value,
@@ -773,13 +877,13 @@ var Enumerable = {
var a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
}).pluck('value');
- },
+ }
- toArray: function() {
+ function toArray() {
return this.map();
- },
+ }
- zip: function() {
+ function zip() {
var iterator = Prototype.K, args = $A(arguments);
if (Object.isFunction(args.last()))
iterator = args.pop();
@@ -788,130 +892,152 @@ var Enumerable = {
return this.map(function(value, index) {
return iterator(collections.pluck(index));
});
- },
+ }
- size: function() {
+ function size() {
return this.toArray().length;
- },
+ }
- inspect: function() {
+ function inspect() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
-};
-Object.extend(Enumerable, {
- map: Enumerable.collect,
- find: Enumerable.detect,
- select: Enumerable.findAll,
- filter: Enumerable.findAll,
- member: Enumerable.include,
- entries: Enumerable.toArray,
- every: Enumerable.all,
- some: Enumerable.any
-});
+
+
+
+
+
+
+
+
+ return {
+ each: each,
+ eachSlice: eachSlice,
+ all: all,
+ every: all,
+ any: any,
+ some: any,
+ collect: collect,
+ map: collect,
+ detect: detect,
+ findAll: findAll,
+ select: findAll,
+ filter: findAll,
+ grep: grep,
+ include: include,
+ member: include,
+ inGroupsOf: inGroupsOf,
+ inject: inject,
+ invoke: invoke,
+ max: max,
+ min: min,
+ partition: partition,
+ pluck: pluck,
+ reject: reject,
+ sortBy: sortBy,
+ toArray: toArray,
+ entries: toArray,
+ zip: zip,
+ size: size,
+ inspect: inspect,
+ find: detect
+ };
+})();
function $A(iterable) {
if (!iterable) return [];
- if (iterable.toArray) return iterable.toArray();
+ if ('toArray' in Object(iterable)) return iterable.toArray();
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
-if (Prototype.Browser.WebKit) {
- $A = function(iterable) {
- if (!iterable) return [];
- // In Safari, only use the `toArray` method if it's not a NodeList.
- // A NodeList is a function, has an function `item` property, and a numeric
- // `length` property. Adapted from Google Doctype.
- if (!(typeof iterable === 'function' && typeof iterable.length ===
- 'number' && typeof iterable.item === 'function') && iterable.toArray)
- return iterable.toArray();
- var length = iterable.length || 0, results = new Array(length);
- while (length--) results[length] = iterable[length];
- return results;
- };
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
}
Array.from = $A;
-Object.extend(Array.prototype, Enumerable);
-if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+(function() {
+ var arrayProto = Array.prototype,
+ slice = arrayProto.slice,
+ _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
-Object.extend(Array.prototype, {
- _each: function(iterator) {
+ function each(iterator) {
for (var i = 0, length = this.length; i < length; i++)
iterator(this[i]);
- },
+ }
+ if (!_each) _each = each;
- clear: function() {
+ function clear() {
this.length = 0;
return this;
- },
+ }
- first: function() {
+ function first() {
return this[0];
- },
+ }
- last: function() {
+ function last() {
return this[this.length - 1];
- },
+ }
- compact: function() {
+ function compact() {
return this.select(function(value) {
return value != null;
});
- },
+ }
- flatten: function() {
+ function flatten() {
return this.inject([], function(array, value) {
- return array.concat(Object.isArray(value) ?
- value.flatten() : [value]);
+ if (Object.isArray(value))
+ return array.concat(value.flatten());
+ array.push(value);
+ return array;
});
- },
+ }
- without: function() {
- var values = $A(arguments);
+ function without() {
+ var values = slice.call(arguments, 0);
return this.select(function(value) {
return !values.include(value);
});
- },
+ }
- reverse: function(inline) {
+ function reverse(inline) {
return (inline !== false ? this : this.toArray())._reverse();
- },
-
- reduce: function() {
- return this.length > 1 ? this : this[0];
- },
+ }
- uniq: function(sorted) {
+ function uniq(sorted) {
return this.inject([], function(array, value, index) {
if (0 == index || (sorted ? array.last() != value : !array.include(value)))
array.push(value);
return array;
});
- },
+ }
- intersect: function(array) {
+ function intersect(array) {
return this.uniq().findAll(function(item) {
return array.detect(function(value) { return item === value });
});
- },
+ }
- clone: function() {
- return [].concat(this);
- },
- size: function() {
+ function clone() {
+ return slice.call(this, 0);
+ }
+
+ function size() {
return this.length;
- },
+ }
- inspect: function() {
+ function inspect() {
return '[' + this.map(Object.inspect).join(', ') + ']';
- },
+ }
- toJSON: function() {
+ function toJSON() {
var results = [];
this.each(function(object) {
var value = Object.toJSON(object);
@@ -919,205 +1045,270 @@ Object.extend(Array.prototype, {
});
return '[' + results.join(', ') + ']';
}
-});
-// use native browser JS 1.6 implementation if available
-if (Object.isFunction(Array.prototype.forEach))
- Array.prototype._each = Array.prototype.forEach;
-
-if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
- i || (i = 0);
- var length = this.length;
- if (i < 0) i = length + i;
- for (; i < length; i++)
- if (this[i] === item) return i;
- return -1;
-};
-
-if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
- i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
- var n = this.slice(0, i).reverse().indexOf(item);
- return (n < 0) ? n : i - n - 1;
-};
-
-Array.prototype.toArray = Array.prototype.clone;
+ function indexOf(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+ }
-function $w(string) {
- if (!Object.isString(string)) return [];
- string = string.strip();
- return string ? string.split(/\s+/) : [];
-}
+ function lastIndexOf(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+ }
-if (Prototype.Browser.Opera){
- Array.prototype.concat = function() {
- var array = [];
- for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ function concat() {
+ var array = slice.call(this, 0), item;
for (var i = 0, length = arguments.length; i < length; i++) {
- if (Object.isArray(arguments[i])) {
- for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
- array.push(arguments[i][j]);
+ item = arguments[i];
+ if (Object.isArray(item) && !('callee' in item)) {
+ for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
+ array.push(item[j]);
} else {
- array.push(arguments[i]);
+ array.push(item);
}
}
return array;
- };
-}
-Object.extend(Number.prototype, {
- toColorPart: function() {
- return this.toPaddedString(2, 16);
- },
-
- succ: function() {
- return this + 1;
- },
+ }
- times: function(iterator, context) {
- $R(0, this, true).each(iterator, context);
- return this;
- },
+ Object.extend(arrayProto, Enumerable);
+
+ if (!arrayProto._reverse)
+ arrayProto._reverse = arrayProto.reverse;
+
+ Object.extend(arrayProto, {
+ _each: _each,
+ clear: clear,
+ first: first,
+ last: last,
+ compact: compact,
+ flatten: flatten,
+ without: without,
+ reverse: reverse,
+ uniq: uniq,
+ intersect: intersect,
+ clone: clone,
+ toArray: clone,
+ size: size,
+ inspect: inspect,
+ toJSON: toJSON
+ });
- toPaddedString: function(length, radix) {
- var string = this.toString(radix || 10);
- return '0'.times(length - string.length) + string;
- },
+ var CONCAT_ARGUMENTS_BUGGY = (function() {
+ return [].concat(arguments)[0][0] !== 1;
+ })(1,2)
- toJSON: function() {
- return isFinite(this) ? this.toString() : 'null';
- }
-});
+ if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
-$w('abs round ceil floor').each(function(method){
- Number.prototype[method] = Math[method].methodize();
-});
+ if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
+ if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
+})();
function $H(object) {
return new Hash(object);
};
var Hash = Class.create(Enumerable, (function() {
+ function initialize(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ }
+
+ function _each(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ }
+
+ function set(key, value) {
+ return this._object[key] = value;
+ }
+
+ function get(key) {
+ if (this._object[key] !== Object.prototype[key])
+ return this._object[key];
+ }
+
+ function unset(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ }
+
+ function toObject() {
+ return Object.clone(this._object);
+ }
+
+ function keys() {
+ return this.pluck('key');
+ }
+
+ function values() {
+ return this.pluck('value');
+ }
+
+ function index(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ }
+
+ function merge(object) {
+ return this.clone().update(object);
+ }
+
+ function update(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ }
function toQueryPair(key, value) {
if (Object.isUndefined(value)) return key;
return key + '=' + encodeURIComponent(String.interpret(value));
}
- return {
- initialize: function(object) {
- this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
- },
+ function toQueryString() {
+ return this.inject([], function(results, pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
- _each: function(iterator) {
- for (var key in this._object) {
- var value = this._object[key], pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
- }
- },
-
- set: function(key, value) {
- return this._object[key] = value;
- },
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return results.concat(values.map(toQueryPair.curry(key)));
+ } else results.push(toQueryPair(key, values));
+ return results;
+ }).join('&');
+ }
- get: function(key) {
- // simulating poorly supported hasOwnProperty
- if (this._object[key] !== Object.prototype[key])
- return this._object[key];
- },
+ function inspect() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ }
- unset: function(key) {
- var value = this._object[key];
- delete this._object[key];
- return value;
- },
+ function toJSON() {
+ return Object.toJSON(this.toObject());
+ }
- toObject: function() {
- return Object.clone(this._object);
- },
+ function clone() {
+ return new Hash(this);
+ }
- keys: function() {
- return this.pluck('key');
- },
+ return {
+ initialize: initialize,
+ _each: _each,
+ set: set,
+ get: get,
+ unset: unset,
+ toObject: toObject,
+ toTemplateReplacements: toObject,
+ keys: keys,
+ values: values,
+ index: index,
+ merge: merge,
+ update: update,
+ toQueryString: toQueryString,
+ inspect: inspect,
+ toJSON: toJSON,
+ clone: clone
+ };
+})());
- values: function() {
- return this.pluck('value');
- },
+Hash.from = $H;
+Object.extend(Number.prototype, (function() {
+ function toColorPart() {
+ return this.toPaddedString(2, 16);
+ }
- index: function(value) {
- var match = this.detect(function(pair) {
- return pair.value === value;
- });
- return match && match.key;
- },
+ function succ() {
+ return this + 1;
+ }
- merge: function(object) {
- return this.clone().update(object);
- },
+ function times(iterator, context) {
+ $R(0, this, true).each(iterator, context);
+ return this;
+ }
- update: function(object) {
- return new Hash(object).inject(this, function(result, pair) {
- result.set(pair.key, pair.value);
- return result;
- });
- },
+ function toPaddedString(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ }
- toQueryString: function() {
- return this.inject([], function(results, pair) {
- var key = encodeURIComponent(pair.key), values = pair.value;
+ function toJSON() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
- if (values && typeof values == 'object') {
- if (Object.isArray(values))
- return results.concat(values.map(toQueryPair.curry(key)));
- } else results.push(toQueryPair(key, values));
- return results;
- }).join('&');
- },
+ function abs() {
+ return Math.abs(this);
+ }
- inspect: function() {
- return '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
- },
+ function round() {
+ return Math.round(this);
+ }
- toJSON: function() {
- return Object.toJSON(this.toObject());
- },
+ function ceil() {
+ return Math.ceil(this);
+ }
- clone: function() {
- return new Hash(this);
- }
+ function floor() {
+ return Math.floor(this);
}
+
+ return {
+ toColorPart: toColorPart,
+ succ: succ,
+ times: times,
+ toPaddedString: toPaddedString,
+ toJSON: toJSON,
+ abs: abs,
+ round: round,
+ ceil: ceil,
+ floor: floor
+ };
})());
-Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
-Hash.from = $H;
-var ObjectRange = Class.create(Enumerable, {
- initialize: function(start, end, exclusive) {
+function $R(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+}
+
+var ObjectRange = Class.create(Enumerable, (function() {
+ function initialize(start, end, exclusive) {
this.start = start;
this.end = end;
this.exclusive = exclusive;
- },
+ }
- _each: function(iterator) {
+ function _each(iterator) {
var value = this.start;
while (this.include(value)) {
iterator(value);
value = value.succ();
}
- },
+ }
- include: function(value) {
+ function include(value) {
if (value < this.start)
return false;
if (this.exclusive)
return value < this.end;
return value <= this.end;
}
-});
-var $R = function(start, end, exclusive) {
- return new ObjectRange(start, end, exclusive);
-};
+ return {
+ initialize: initialize,
+ _each: _each,
+ include: include
+ };
+})());
+
+
var Ajax = {
getTransport: function() {
@@ -1164,7 +1355,6 @@ Ajax.Responders.register({
onCreate: function() { Ajax.activeRequestCount++ },
onComplete: function() { Ajax.activeRequestCount-- }
});
-
Ajax.Base = Class.create({
initialize: function(options) {
this.options = {
@@ -1186,7 +1376,6 @@ Ajax.Base = Class.create({
this.options.parameters = this.options.parameters.toObject();
}
});
-
Ajax.Request = Class.create(Ajax.Base, {
_complete: false,
@@ -1202,7 +1391,6 @@ Ajax.Request = Class.create(Ajax.Base, {
var params = Object.clone(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
- // simulate other verbs over post
params['_method'] = this.method;
this.method = 'post';
}
@@ -1210,7 +1398,6 @@ Ajax.Request = Class.create(Ajax.Base, {
this.parameters = params;
if (params = Object.toQueryString(params)) {
- // when GET, append parameters to URL
if (this.method == 'get')
this.url += (this.url.include('?') ? '&' : '?') + params;
else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
@@ -1269,7 +1456,6 @@ Ajax.Request = Class.create(Ajax.Base, {
headers['Connection'] = 'close';
}
- // user-defined headers
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
@@ -1323,7 +1509,6 @@ Ajax.Request = Class.create(Ajax.Base, {
}
if (state == 'Complete') {
- // avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = Prototype.emptyFunction;
}
},
@@ -1340,7 +1525,7 @@ Ajax.Request = Class.create(Ajax.Base, {
getHeader: function(name) {
try {
return this.transport.getResponseHeader(name) || null;
- } catch (e) { return null }
+ } catch (e) { return null; }
},
evalResponse: function() {
@@ -1360,6 +1545,13 @@ Ajax.Request = Class.create(Ajax.Base, {
Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+
+
+
+
+
+
Ajax.Response = Class.create({
initialize: function(request){
this.request = request;
@@ -1381,6 +1573,7 @@ Ajax.Response = Class.create({
},
status: 0,
+
statusText: '',
getStatus: Ajax.Request.prototype.getStatus,
@@ -1510,6 +1703,9 @@ Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
+
+
+
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
@@ -1537,7 +1733,6 @@ if (Prototype.BrowserFeatures.XPath) {
if (!window.Node) var Node = { };
if (!Node.ELEMENT_NODE) {
- // DOM level 2 ECMAScript Language Binding
Object.extend(Node, {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
@@ -1554,13 +1749,30 @@ if (!Node.ELEMENT_NODE) {
});
}
-(function() {
- var element = this.Element;
- this.Element = function(tagName, attributes) {
+
+(function(global) {
+
+ var SETATTRIBUTE_IGNORES_NAME = (function(){
+ var elForm = document.createElement("form");
+ var elInput = document.createElement("input");
+ var root = document.documentElement;
+ elInput.setAttribute("name", "test");
+ elForm.appendChild(elInput);
+ root.appendChild(elForm);
+ var isBuggy = elForm.elements
+ ? (typeof elForm.elements.test == "undefined")
+ : null;
+ root.removeChild(elForm);
+ elForm = elInput = null;
+ return isBuggy;
+ })();
+
+ var element = global.Element;
+ global.Element = function(tagName, attributes) {
attributes = attributes || { };
tagName = tagName.toLowerCase();
var cache = Element.cache;
- if (Prototype.Browser.IE && attributes.name) {
+ if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {
tagName = '<' + tagName + ' name="' + attributes.name + '">';
delete attributes.name;
return Element.writeAttribute(document.createElement(tagName), attributes);
@@ -1568,11 +1780,12 @@ if (!Node.ELEMENT_NODE) {
if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
};
- Object.extend(this.Element, element || { });
- if (element) this.Element.prototype = element.prototype;
-}).call(window);
+ Object.extend(global.Element, element || { });
+ if (element) global.Element.prototype = element.prototype;
+})(this);
Element.cache = { };
+Element.idCounter = 1;
Element.Methods = {
visible: function(element) {
@@ -1585,6 +1798,7 @@ Element.Methods = {
return element;
},
+
hide: function(element) {
element = $(element);
element.style.display = 'none';
@@ -1603,15 +1817,89 @@ Element.Methods = {
return element;
},
- update: function(element, content) {
- element = $(element);
- if (content && content.toElement) content = content.toElement();
- if (Object.isElement(content)) return element.update().insert(content);
- content = Object.toHTML(content);
- element.innerHTML = content.stripScripts();
- content.evalScripts.bind(content).defer();
- return element;
- },
+ update: (function(){
+
+ var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
+ var el = document.createElement("select"),
+ isBuggy = true;
+ el.innerHTML = "<option value=\"test\">test</option>";
+ if (el.options && el.options[0]) {
+ isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
+ }
+ el = null;
+ return isBuggy;
+ })();
+
+ var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
+ try {
+ var el = document.createElement("table");
+ if (el && el.tBodies) {
+ el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
+ var isBuggy = typeof el.tBodies[0] == "undefined";
+ el = null;
+ return isBuggy;
+ }
+ } catch (e) {
+ return true;
+ }
+ })();
+
+ var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
+ var s = document.createElement("script"),
+ isBuggy = false;
+ try {
+ s.appendChild(document.createTextNode(""));
+ isBuggy = !s.firstChild ||
+ s.firstChild && s.firstChild.nodeType !== 3;
+ } catch (e) {
+ isBuggy = true;
+ }
+ s = null;
+ return isBuggy;
+ })();
+
+ function update(element, content) {
+ element = $(element);
+
+ if (content && content.toElement)
+ content = content.toElement();
+
+ if (Object.isElement(content))
+ return element.update().insert(content);
+
+ content = Object.toHTML(content);
+
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
+ element.text = content;
+ return element;
+ }
+
+ if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
+ if (tagName in Element._insertionTranslations.tags) {
+ while (element.firstChild) {
+ element.removeChild(element.firstChild);
+ }
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) {
+ element.appendChild(node)
+ });
+ }
+ else {
+ element.innerHTML = content.stripScripts();
+ }
+ }
+ else {
+ element.innerHTML = content.stripScripts();
+ }
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ }
+
+ return update;
+ })(),
replace: function(element, content) {
element = $(element);
@@ -1696,11 +1984,11 @@ Element.Methods = {
},
ancestors: function(element) {
- return $(element).recursivelyCollect('parentNode');
+ return Element.recursivelyCollect(element, 'parentNode');
},
descendants: function(element) {
- return $(element).select("*");
+ return Element.select(element, "*");
},
firstDescendant: function(element) {
@@ -1717,16 +2005,17 @@ Element.Methods = {
},
previousSiblings: function(element) {
- return $(element).recursivelyCollect('previousSibling');
+ return Element.recursivelyCollect(element, 'previousSibling');
},
nextSiblings: function(element) {
- return $(element).recursivelyCollect('nextSibling');
+ return Element.recursivelyCollect(element, 'nextSibling');
},
siblings: function(element) {
element = $(element);
- return element.previousSiblings().reverse().concat(element.nextSiblings());
+ return Element.previousSiblings(element).reverse()
+ .concat(Element.nextSiblings(element));
},
match: function(element, selector) {
@@ -1738,22 +2027,22 @@ Element.Methods = {
up: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return $(element.parentNode);
- var ancestors = element.ancestors();
+ var ancestors = Element.ancestors(element);
return Object.isNumber(expression) ? ancestors[expression] :
Selector.findElement(ancestors, expression, index);
},
down: function(element, expression, index) {
element = $(element);
- if (arguments.length == 1) return element.firstDescendant();
- return Object.isNumber(expression) ? element.descendants()[expression] :
+ if (arguments.length == 1) return Element.firstDescendant(element);
+ return Object.isNumber(expression) ? Element.descendants(element)[expression] :
Element.select(element, expression)[index || 0];
},
previous: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
- var previousSiblings = element.previousSiblings();
+ var previousSiblings = Element.previousSiblings(element);
return Object.isNumber(expression) ? previousSiblings[expression] :
Selector.findElement(previousSiblings, expression, index);
},
@@ -1761,27 +2050,28 @@ Element.Methods = {
next: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
- var nextSiblings = element.nextSiblings();
+ var nextSiblings = Element.nextSiblings(element);
return Object.isNumber(expression) ? nextSiblings[expression] :
Selector.findElement(nextSiblings, expression, index);
},
- select: function() {
- var args = $A(arguments), element = $(args.shift());
+
+ select: function(element) {
+ var args = Array.prototype.slice.call(arguments, 1);
return Selector.findChildElements(element, args);
},
- adjacent: function() {
- var args = $A(arguments), element = $(args.shift());
+ adjacent: function(element) {
+ var args = Array.prototype.slice.call(arguments, 1);
return Selector.findChildElements(element.parentNode, args).without(element);
},
identify: function(element) {
element = $(element);
- var id = element.readAttribute('id'), self = arguments.callee;
+ var id = Element.readAttribute(element, 'id');
if (id) return id;
- do { id = 'anonymous_element_' + self.counter++ } while ($(id));
- element.writeAttribute('id', id);
+ do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
+ Element.writeAttribute(element, 'id', id);
return id;
},
@@ -1820,11 +2110,11 @@ Element.Methods = {
},
getHeight: function(element) {
- return $(element).getDimensions().height;
+ return Element.getDimensions(element).height;
},
getWidth: function(element) {
- return $(element).getDimensions().width;
+ return Element.getDimensions(element).width;
},
classNames: function(element) {
@@ -1840,7 +2130,7 @@ Element.Methods = {
addClassName: function(element, className) {
if (!(element = $(element))) return;
- if (!element.hasClassName(className))
+ if (!Element.hasClassName(element, className))
element.className += (element.className ? ' ' : '') + className;
return element;
},
@@ -1854,11 +2144,10 @@ Element.Methods = {
toggleClassName: function(element, className) {
if (!(element = $(element))) return;
- return element[element.hasClassName(className) ?
- 'removeClassName' : 'addClassName'](className);
+ return Element[Element.hasClassName(element, className) ?
+ 'removeClassName' : 'addClassName'](element, className);
},
- // removes whitespace-only text node children
cleanWhitespace: function(element) {
element = $(element);
var node = element.firstChild;
@@ -1892,7 +2181,7 @@ Element.Methods = {
scrollTo: function(element) {
element = $(element);
- var pos = element.cumulativeOffset();
+ var pos = Element.cumulativeOffset(element);
window.scrollTo(pos[0], pos[1]);
return element;
},
@@ -1940,18 +2229,17 @@ Element.Methods = {
getDimensions: function(element) {
element = $(element);
- var display = element.getStyle('display');
+ var display = Element.getStyle(element, 'display');
if (display != 'none' && display != null) // Safari bug
return {width: element.offsetWidth, height: element.offsetHeight};
- // All *Width and *Height properties give 0 on elements with display none,
- // so enable the element temporarily
var els = element.style;
var originalVisibility = els.visibility;
var originalPosition = els.position;
var originalDisplay = els.display;
els.visibility = 'hidden';
- els.position = 'absolute';
+ if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
+ els.position = 'absolute';
els.display = 'block';
var originalWidth = element.clientWidth;
var originalHeight = element.clientHeight;
@@ -1967,8 +2255,6 @@ Element.Methods = {
if (pos == 'static' || !pos) {
element._madePositioned = true;
element.style.position = 'relative';
- // Opera returns the offset relative to the positioning context, when an
- // element is position relative but top and left have not been defined
if (Prototype.Browser.Opera) {
element.style.top = 0;
element.style.left = 0;
@@ -2034,10 +2320,9 @@ Element.Methods = {
absolutize: function(element) {
element = $(element);
- if (element.getStyle('position') == 'absolute') return element;
- // Position.prepare(); // To be done manually by Scripty when it needs it.
+ if (Element.getStyle(element, 'position') == 'absolute') return element;
- var offsets = element.positionedOffset();
+ var offsets = Element.positionedOffset(element);
var top = offsets[1];
var left = offsets[0];
var width = element.clientWidth;
@@ -2058,8 +2343,7 @@ Element.Methods = {
relativize: function(element) {
element = $(element);
- if (element.getStyle('position') == 'relative') return element;
- // Position.prepare(); // To be done manually by Scripty when it needs it.
+ if (Element.getStyle(element, 'position') == 'relative') return element;
element.style.position = 'relative';
var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
@@ -2101,7 +2385,6 @@ Element.Methods = {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
- // Safari fix
if (element.offsetParent == document.body &&
Element.getStyle(element, 'position') == 'absolute') break;
@@ -2128,28 +2411,22 @@ Element.Methods = {
offsetLeft: 0
}, arguments[2] || { });
- // find page position of source
source = $(source);
- var p = source.viewportOffset();
+ var p = Element.viewportOffset(source);
- // find coordinate system to use
element = $(element);
var delta = [0, 0];
var parent = null;
- // delta [0,0] will do fine with position: fixed elements,
- // position:absolute needs offsetParent deltas
if (Element.getStyle(element, 'position') == 'absolute') {
- parent = element.getOffsetParent();
- delta = parent.viewportOffset();
+ parent = Element.getOffsetParent(element);
+ delta = Element.viewportOffset(parent);
}
- // correct by body offsets (fixes Safari)
if (parent == document.body) {
delta[0] -= document.body.offsetLeft;
delta[1] -= document.body.offsetTop;
}
- // set position
if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
if (options.setWidth) element.style.width = source.offsetWidth + 'px';
@@ -2158,10 +2435,9 @@ Element.Methods = {
}
};
-Element.Methods.identify.counter = 1;
-
Object.extend(Element.Methods, {
getElementsBySelector: Element.Methods.select,
+
childElements: Element.Methods.immediateDescendants
});
@@ -2182,11 +2458,8 @@ if (Prototype.Browser.Opera) {
case 'left': case 'top': case 'right': case 'bottom':
if (proceed(element, 'position') === 'static') return null;
case 'height': case 'width':
- // returns '0px' for hidden elements; we want it to return null
if (!Element.visible(element)) return null;
- // returns the border-box dimensions rather than the content-box
- // dimensions, so we subtract padding and borders from the value
var dim = parseInt(proceed(element, style), 10);
if (dim !== element['offset' + style.capitalize()])
@@ -2219,12 +2492,9 @@ if (Prototype.Browser.Opera) {
}
else if (Prototype.Browser.IE) {
- // IE doesn't report offsets correctly for static elements, so we change them
- // to "relative" to get the values, then change them back.
Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
function(proceed, element) {
element = $(element);
- // IE throws an error if element is not in document
try { element.offsetParent }
catch(e) { return $(document.body) }
var position = element.getStyle('position');
@@ -2244,8 +2514,6 @@ else if (Prototype.Browser.IE) {
catch(e) { return Element._returnOffset(0,0) }
var position = element.getStyle('position');
if (position !== 'static') return proceed(element);
- // Trigger hasLayout on the offset parent so that IE6 reports
- // accurate offsetTop and offsetLeft values for position: fixed.
var offsetParent = element.getOffsetParent();
if (offsetParent && offsetParent.getStyle('position') === 'fixed')
offsetParent.setStyle({ zoom: 1 });
@@ -2306,36 +2574,92 @@ else if (Prototype.Browser.IE) {
return element;
};
- Element._attributeTranslations = {
- read: {
- names: {
- 'class': 'className',
- 'for': 'htmlFor'
- },
- values: {
- _getAttr: function(element, attribute) {
- return element.getAttribute(attribute, 2);
- },
- _getAttrNode: function(element, attribute) {
- var node = element.getAttributeNode(attribute);
- return node ? node.value : "";
- },
- _getEv: function(element, attribute) {
- attribute = element.getAttribute(attribute);
- return attribute ? attribute.toString().slice(23, -2) : null;
- },
- _flag: function(element, attribute) {
- return $(element).hasAttribute(attribute) ? attribute : null;
- },
- style: function(element) {
- return element.style.cssText.toLowerCase();
+ Element._attributeTranslations = (function(){
+
+ var classProp = 'className';
+ var forProp = 'for';
+
+ var el = document.createElement('div');
+
+ el.setAttribute(classProp, 'x');
+
+ if (el.className !== 'x') {
+ el.setAttribute('class', 'x');
+ if (el.className === 'x') {
+ classProp = 'class';
+ }
+ }
+ el = null;
+
+ el = document.createElement('label');
+ el.setAttribute(forProp, 'x');
+ if (el.htmlFor !== 'x') {
+ el.setAttribute('htmlFor', 'x');
+ if (el.htmlFor === 'x') {
+ forProp = 'htmlFor';
+ }
+ }
+ el = null;
+
+ return {
+ read: {
+ names: {
+ 'class': classProp,
+ 'className': classProp,
+ 'for': forProp,
+ 'htmlFor': forProp
},
- title: function(element) {
- return element.title;
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute);
+ },
+ _getAttr2: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: (function(){
+
+ var el = document.createElement('div');
+ el.onclick = Prototype.emptyFunction;
+ var value = el.getAttribute('onclick');
+ var f;
+
+ if (String(value).indexOf('{') > -1) {
+ f = function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ if (!attribute) return null;
+ attribute = attribute.toString();
+ attribute = attribute.split('{')[1];
+ attribute = attribute.split('}')[0];
+ return attribute.strip();
+ };
+ }
+ else if (value === '') {
+ f = function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ if (!attribute) return null;
+ return attribute.strip();
+ };
+ }
+ el = null;
+ return f;
+ })(),
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
}
}
}
- };
+ })();
Element._attributeTranslations.write = {
names: Object.extend({
@@ -2363,8 +2687,8 @@ else if (Prototype.Browser.IE) {
(function(v) {
Object.extend(v, {
- href: v._getAttr,
- src: v._getAttr,
+ href: v._getAttr2,
+ src: v._getAttr2,
type: v._getAttr,
action: v._getAttrNode,
disabled: v._flag,
@@ -2391,6 +2715,26 @@ else if (Prototype.Browser.IE) {
onchange: v._getEv
});
})(Element._attributeTranslations.read.values);
+
+ if (Prototype.BrowserFeatures.ElementExtensions) {
+ (function() {
+ function _descendants(element) {
+ var nodes = element.getElementsByTagName('*'), results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName !== "!") // Filter out comment nodes.
+ results.push(node);
+ return results;
+ }
+
+ Element.Methods.down = function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? _descendants(element)[expression] :
+ Element.select(element, expression)[index || 0];
+ }
+ })();
+ }
+
}
else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
@@ -2420,9 +2764,6 @@ else if (Prototype.Browser.WebKit) {
return element;
};
- // Safari returns margins on body which is incorrect if the child is absolutely
- // positioned. For performance reasons, redefine Element#cumulativeOffset for
- // KHTML/WebKit only.
Element.Methods.cumulativeOffset = function(element) {
var valueT = 0, valueL = 0;
do {
@@ -2438,30 +2779,7 @@ else if (Prototype.Browser.WebKit) {
};
}
-if (Prototype.Browser.IE || Prototype.Browser.Opera) {
- // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
- Element.Methods.update = function(element, content) {
- element = $(element);
-
- if (content && content.toElement) content = content.toElement();
- if (Object.isElement(content)) return element.update().insert(content);
-
- content = Object.toHTML(content);
- var tagName = element.tagName.toUpperCase();
-
- if (tagName in Element._insertionTranslations.tags) {
- $A(element.childNodes).each(function(node) { element.removeChild(node) });
- Element._getContentFromAnonymousElement(tagName, content.stripScripts())
- .each(function(node) { element.appendChild(node) });
- }
- else element.innerHTML = content.stripScripts();
-
- content.evalScripts.bind(content).defer();
- return element;
- };
-}
-
-if ('outerHTML' in document.createElement('div')) {
+if ('outerHTML' in document.documentElement) {
Element.Methods.replace = function(element, content) {
element = $(element);
@@ -2529,12 +2847,13 @@ Element._insertionTranslations = {
};
(function() {
- Object.extend(this.tags, {
- THEAD: this.tags.TBODY,
- TFOOT: this.tags.TBODY,
- TH: this.tags.TD
+ var tags = Element._insertionTranslations.tags;
+ Object.extend(tags, {
+ THEAD: tags.TBODY,
+ TFOOT: tags.TBODY,
+ TH: tags.TD
});
-}).call(Element._insertionTranslations);
+})();
Element.Methods.Simulated = {
hasAttribute: function(element, attribute) {
@@ -2548,41 +2867,81 @@ Element.Methods.ByTag = { };
Object.extend(Element, Element.Methods);
-if (!Prototype.BrowserFeatures.ElementExtensions &&
- document.createElement('div')['__proto__']) {
- window.HTMLElement = { };
- window.HTMLElement.prototype = document.createElement('div')['__proto__'];
- Prototype.BrowserFeatures.ElementExtensions = true;
-}
+(function(div) {
+
+ if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = div['__proto__'];
+ Prototype.BrowserFeatures.ElementExtensions = true;
+ }
+
+ div = null;
+
+})(document.createElement('div'))
Element.extend = (function() {
- if (Prototype.BrowserFeatures.SpecificElementExtensions)
+
+ function checkDeficiency(tagName) {
+ if (typeof window.Element != 'undefined') {
+ var proto = window.Element.prototype;
+ if (proto) {
+ var id = '_' + (Math.random()+'').slice(2);
+ var el = document.createElement(tagName);
+ proto[id] = 'x';
+ var isBuggy = (el[id] !== 'x');
+ delete proto[id];
+ el = null;
+ return isBuggy;
+ }
+ }
+ return false;
+ }
+
+ function extendElementWith(element, methods) {
+ for (var property in methods) {
+ var value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+ }
+
+ var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
+
+ if (Prototype.BrowserFeatures.SpecificElementExtensions) {
+ if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
+ return function(element) {
+ if (element && typeof element._extendedByPrototype == 'undefined') {
+ var t = element.tagName;
+ if (t && (/^(?:object|applet|embed)$/i.test(t))) {
+ extendElementWith(element, Element.Methods);
+ extendElementWith(element, Element.Methods.Simulated);
+ extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
+ }
+ }
+ return element;
+ }
+ }
return Prototype.K;
+ }
var Methods = { }, ByTag = Element.Methods.ByTag;
var extend = Object.extend(function(element) {
- if (!element || element._extendedByPrototype ||
+ if (!element || typeof element._extendedByPrototype != 'undefined' ||
element.nodeType != 1 || element == window) return element;
var methods = Object.clone(Methods),
- tagName = element.tagName.toUpperCase(), property, value;
+ tagName = element.tagName.toUpperCase();
- // extend methods for specific tags
if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
- for (property in methods) {
- value = methods[property];
- if (Object.isFunction(value) && !(property in element))
- element[property] = value.methodize();
- }
+ extendElementWith(element, methods);
element._extendedByPrototype = Prototype.emptyFunction;
return element;
}, {
refresh: function() {
- // extend methods for all tags (Safari doesn't need this)
if (!Prototype.BrowserFeatures.ElementExtensions) {
Object.extend(Methods, Element.Methods);
Object.extend(Methods, Element.Methods.Simulated);
@@ -2661,14 +3020,18 @@ Element.addMethods = function(methods) {
klass = 'HTML' + tagName.capitalize() + 'Element';
if (window[klass]) return window[klass];
- window[klass] = { };
- window[klass].prototype = document.createElement(tagName)['__proto__'];
- return window[klass];
+ var element = document.createElement(tagName);
+ var proto = element['__proto__'] || element.constructor.prototype;
+ element = null;
+ return proto;
}
+ var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
+ Element.prototype;
+
if (F.ElementExtensions) {
- copy(Element.Methods, HTMLElement.prototype);
- copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ copy(Element.Methods, elementPrototype);
+ copy(Element.Methods.Simulated, elementPrototype, true);
}
if (F.SpecificElementExtensions) {
@@ -2686,38 +3049,109 @@ Element.addMethods = function(methods) {
Element.cache = { };
};
-document.viewport = {
- getDimensions: function() {
- var dimensions = { }, B = Prototype.Browser;
- $w('width height').each(function(d) {
- var D = d.capitalize();
- if (B.WebKit && !document.evaluate) {
- // Safari <3.0 needs self.innerWidth/Height
- dimensions[d] = self['inner' + D];
- } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
- // Opera <9.5 needs document.body.clientWidth/Height
- dimensions[d] = document.body['client' + D]
- } else {
- dimensions[d] = document.documentElement['client' + D];
- }
- });
- return dimensions;
- },
- getWidth: function() {
- return this.getDimensions().width;
- },
+document.viewport = {
- getHeight: function() {
- return this.getDimensions().height;
+ getDimensions: function() {
+ return { width: this.getWidth(), height: this.getHeight() };
},
getScrollOffsets: function() {
return Element._returnOffset(
window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
- window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
};
+
+(function(viewport) {
+ var B = Prototype.Browser, doc = document, element, property = {};
+
+ function getRootElement() {
+ if (B.WebKit && !doc.evaluate)
+ return document;
+
+ if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
+ return document.body;
+
+ return document.documentElement;
+ }
+
+ function define(D) {
+ if (!element) element = getRootElement();
+
+ property[D] = 'client' + D;
+
+ viewport['get' + D] = function() { return element[property[D]] };
+ return viewport['get' + D]();
+ }
+
+ viewport.getWidth = define.curry('Width');
+
+ viewport.getHeight = define.curry('Height');
+})(document.viewport);
+
+
+Element.Storage = {
+ UID: 1
+};
+
+Element.addMethods({
+ getStorage: function(element) {
+ if (!(element = $(element))) return;
+
+ var uid;
+ if (element === window) {
+ uid = 0;
+ } else {
+ if (typeof element._prototypeUID === "undefined")
+ element._prototypeUID = [Element.Storage.UID++];
+ uid = element._prototypeUID[0];
+ }
+
+ if (!Element.Storage[uid])
+ Element.Storage[uid] = $H();
+
+ return Element.Storage[uid];
+ },
+
+ store: function(element, key, value) {
+ if (!(element = $(element))) return;
+
+ if (arguments.length === 2) {
+ Element.getStorage(element).update(key);
+ } else {
+ Element.getStorage(element).set(key, value);
+ }
+
+ return element;
+ },
+
+ retrieve: function(element, key, defaultValue) {
+ if (!(element = $(element))) return;
+ var hash = Element.getStorage(element), value = hash.get(key);
+
+ if (Object.isUndefined(value)) {
+ hash.set(key, defaultValue);
+ value = defaultValue;
+ }
+
+ return value;
+ },
+
+ clone: function(element, deep) {
+ if (!(element = $(element))) return;
+ var clone = element.cloneNode(deep);
+ clone._prototypeUID = void 0;
+ if (deep) {
+ var descendants = Element.select(clone, '*'),
+ i = descendants.length;
+ while (i--) {
+ descendants[i]._prototypeUID = void 0;
+ }
+ }
+ return Element.extend(clone);
+ }
+});
/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
* part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
* license. Please see http://www.yui-ext.com/ for more information. */
@@ -2738,31 +3172,52 @@ var Selector = Class.create({
},
- shouldUseXPath: function() {
- if (!Prototype.BrowserFeatures.XPath) return false;
+ shouldUseXPath: (function() {
- var e = this.expression;
+ var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
+ var isBuggy = false;
+ if (document.evaluate && window.XPathResult) {
+ var el = document.createElement('div');
+ el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';
- // Safari 3 chokes on :*-of-type and :empty
- if (Prototype.Browser.WebKit &&
- (e.include("-of-type") || e.include(":empty")))
- return false;
+ var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
+ "//*[local-name()='li' or local-name()='LI']";
- // XPath can't do namespaced attributes, nor can it read
- // the "checked" property from DOM nodes
- if ((/(\[[\w-]*?:|:checked)/).test(e))
- return false;
+ var result = document.evaluate(xpath, el, null,
+ XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
- return true;
- },
+ isBuggy = (result.snapshotLength !== 2);
+ el = null;
+ }
+ return isBuggy;
+ })();
+
+ return function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ if ((/(\[[\w-]*?:|:checked)/).test(e))
+ return false;
+
+ if (IS_DESCENDANT_SELECTOR_BUGGY) return false;
+
+ return true;
+ }
+
+ })(),
shouldUseSelectorsAPI: function() {
if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
+ if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;
+
if (!Selector._div) Selector._div = new Element('div');
- // Make sure the browser treats the selector as valid. Test on an
- // isolated element to minimize cost of this check.
try {
Selector._div.querySelector(this.expression);
} catch(e) {
@@ -2774,7 +3229,7 @@ var Selector = Class.create({
compileMatcher: function() {
var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
- c = Selector.criteria, le, p, m;
+ c = Selector.criteria, le, p, m, len = ps.length, name;
if (Selector._cache[e]) {
this.matcher = Selector._cache[e];
@@ -2786,11 +3241,12 @@ var Selector = Class.create({
while (e && le != e && (/\S/).test(e)) {
le = e;
- for (var i in ps) {
- p = ps[i];
+ for (var i = 0; i<len; i++) {
+ p = ps[i].re;
+ name = ps[i].name;
if (m = e.match(p)) {
- this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
- new Template(c[i]).evaluate(m));
+ this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :
+ new Template(c[name]).evaluate(m));
e = e.replace(m[0], '');
break;
}
@@ -2804,7 +3260,7 @@ var Selector = Class.create({
compileXPathMatcher: function() {
var e = this.expression, ps = Selector.patterns,
- x = Selector.xpath, le, m;
+ x = Selector.xpath, le, m, len = ps.length, name;
if (Selector._cache[e]) {
this.xpath = Selector._cache[e]; return;
@@ -2813,10 +3269,11 @@ var Selector = Class.create({
this.matcher = ['.//*'];
while (e && le != e && (/\S/).test(e)) {
le = e;
- for (var i in ps) {
- if (m = e.match(ps[i])) {
- this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
- new Template(x[i]).evaluate(m));
+ for (var i = 0; i<len; i++) {
+ name = ps[i].name;
+ if (m = e.match(ps[i].re)) {
+ this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :
+ new Template(x[name]).evaluate(m));
e = e.replace(m[0], '');
break;
}
@@ -2833,11 +3290,9 @@ var Selector = Class.create({
switch (this.mode) {
case 'selectorsAPI':
- // querySelectorAll queries document-wide, then filters to descendants
- // of the context element. That's not what we want.
- // Add an explicit context to the selector if necessary.
if (root !== document) {
var oldId = root.id, id = $(root).identify();
+ id = id.replace(/([\.:])/g, "\\$1");
e = "#" + id + " " + e;
}
@@ -2856,21 +3311,18 @@ var Selector = Class.create({
this.tokens = [];
var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
- var le, p, m;
+ var le, p, m, len = ps.length, name;
while (e && le !== e && (/\S/).test(e)) {
le = e;
- for (var i in ps) {
- p = ps[i];
+ for (var i = 0; i<len; i++) {
+ p = ps[i].re;
+ name = ps[i].name;
if (m = e.match(p)) {
- // use the Selector.assertions methods unless the selector
- // is too complex.
- if (as[i]) {
- this.tokens.push([i, Object.clone(m)]);
+ if (as[name]) {
+ this.tokens.push([name, Object.clone(m)]);
e = e.replace(m[0], '');
} else {
- // reluctantly do a document-wide search
- // and look for a match in the array
return this.findElements(document).include(element);
}
}
@@ -2897,6 +3349,21 @@ var Selector = Class.create({
}
});
+if (Prototype.BrowserFeatures.SelectorsAPI &&
+ document.compatMode === 'BackCompat') {
+ Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){
+ var div = document.createElement('div'),
+ span = document.createElement('span');
+
+ div.id = "prototype_test_id";
+ span.className = 'Test';
+ div.appendChild(span);
+ var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);
+ div = span = null;
+ return isIgnored;
+ })();
+}
+
Object.extend(Selector, {
_cache: { },
@@ -2946,14 +3413,15 @@ Object.extend(Selector, {
'enabled': "[not(@disabled) and (@type!='hidden')]",
'not': function(m) {
var e = m[6], p = Selector.patterns,
- x = Selector.xpath, le, v;
+ x = Selector.xpath, le, v, len = p.length, name;
var exclusion = [];
while (e && le != e && (/\S/).test(e)) {
le = e;
- for (var i in p) {
- if (m = e.match(p[i])) {
- v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ for (var i = 0; i<len; i++) {
+ name = p[i].name
+ if (m = e.match(p[i].re)) {
+ v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m);
exclusion.push("(" + v.substring(1, v.length - 1) + ")");
e = e.replace(m[0], '');
break;
@@ -3021,25 +3489,20 @@ Object.extend(Selector, {
laterSibling: 'c = "laterSibling";'
},
- patterns: {
- // combinators must be listed first
- // (and descendant needs to be last combinator)
- laterSibling: /^\s*~\s*/,
- child: /^\s*>\s*/,
- adjacent: /^\s*\+\s*/,
- descendant: /^\s/,
+ patterns: [
+ { name: 'laterSibling', re: /^\s*~\s*/ },
+ { name: 'child', re: /^\s*>\s*/ },
+ { name: 'adjacent', re: /^\s*\+\s*/ },
+ { name: 'descendant', re: /^\s/ },
- // selectors follow
- tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
- id: /^#([\w\-\*]+)(\b|$)/,
- className: /^\.([\w\-\*]+)(\b|$)/,
- pseudo:
-/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
- attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
- attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
- },
+ { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ },
+ { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ },
+ { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ },
+ { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ },
+ { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ },
+ { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }
+ ],
- // for Selector.match and Element#match
assertions: {
tagName: function(element, matches) {
return matches[1].toUpperCase() == element.tagName.toUpperCase();
@@ -3064,15 +3527,12 @@ Object.extend(Selector, {
},
handlers: {
- // UTILITY FUNCTIONS
- // joins two collections
concat: function(a, b) {
for (var i = 0, node; node = b[i]; i++)
a.push(node);
return a;
},
- // marks an array of nodes for counting
mark: function(nodes) {
var _true = Prototype.emptyFunction;
for (var i = 0, node; node = nodes[i]; i++)
@@ -3080,15 +3540,32 @@ Object.extend(Selector, {
return nodes;
},
- unmark: function(nodes) {
- for (var i = 0, node; node = nodes[i]; i++)
- node._countedByPrototype = undefined;
- return nodes;
- },
+ unmark: (function(){
+
+ var PROPERTIES_ATTRIBUTES_MAP = (function(){
+ var el = document.createElement('div'),
+ isBuggy = false,
+ propName = '_countedByPrototype',
+ value = 'x'
+ el[propName] = value;
+ isBuggy = (el.getAttribute(propName) === value);
+ el = null;
+ return isBuggy;
+ })();
+
+ return PROPERTIES_ATTRIBUTES_MAP ?
+ function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ } :
+ function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = void 0;
+ return nodes;
+ }
+ })(),
- // mark each child node with its position (for nth calls)
- // "ofType" flag indicates whether we're indexing for nth-of-type
- // rather than nth-child
index: function(parentNode, reverse, ofType) {
parentNode._countedByPrototype = Prototype.emptyFunction;
if (reverse) {
@@ -3102,19 +3579,17 @@ Object.extend(Selector, {
}
},
- // filters out duplicates and extends all nodes
unique: function(nodes) {
if (nodes.length == 0) return nodes;
var results = [], n;
for (var i = 0, l = nodes.length; i < l; i++)
- if (!(n = nodes[i])._countedByPrototype) {
+ if (typeof (n = nodes[i])._countedByPrototype == 'undefined') {
n._countedByPrototype = Prototype.emptyFunction;
results.push(Element.extend(n));
}
return Selector.handlers.unmark(results);
},
- // COMBINATOR FUNCTIONS
descendant: function(nodes) {
var h = Selector.handlers;
for (var i = 0, results = [], node; node = nodes[i]; i++)
@@ -3158,13 +3633,11 @@ Object.extend(Selector, {
return null;
},
- // TOKEN FUNCTIONS
tagName: function(nodes, root, tagName, combinator) {
var uTagName = tagName.toUpperCase();
var results = [], h = Selector.handlers;
if (nodes) {
if (combinator) {
- // fastlane for ordinary descendant combinators
if (combinator == "descendant") {
for (var i = 0, node; node = nodes[i]; i++)
h.concat(results, node.getElementsByTagName(tagName));
@@ -3180,8 +3653,19 @@ Object.extend(Selector, {
id: function(nodes, root, id, combinator) {
var targetNode = $(id), h = Selector.handlers;
- if (!targetNode) return [];
- if (!nodes && root == document) return [targetNode];
+
+ if (root == document) {
+ if (!targetNode) return [];
+ if (!nodes) return [targetNode];
+ } else {
+ if (!root.sourceIndex || root.sourceIndex < 1) {
+ var nodes = root.getElementsByTagName('*');
+ for (var j = 0, node; node = nodes[j]; j++) {
+ if (node.id === id) return [node];
+ }
+ }
+ }
+
if (nodes) {
if (combinator) {
if (combinator == 'child') {
@@ -3293,7 +3777,6 @@ Object.extend(Selector, {
return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
},
- // handles the an+b logic
getIndices: function(a, b, total) {
if (a == 0) return b > 0 ? [b] : [];
return $R(1, total).inject([], function(memo, i) {
@@ -3302,7 +3785,6 @@ Object.extend(Selector, {
});
},
- // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
nth: function(nodes, formula, root, reverse, ofType) {
if (nodes.length == 0) return [];
if (formula == 'even') formula = '2n+0';
@@ -3336,7 +3818,6 @@ Object.extend(Selector, {
'empty': function(nodes, value, root) {
for (var i = 0, results = [], node; node = nodes[i]; i++) {
- // IE treats comments as element nodes
if (node.tagName == '!' || node.firstChild) continue;
results.push(node);
}
@@ -3379,8 +3860,6 @@ Object.extend(Selector, {
'^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
'$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
'*=': function(nv, v) { return nv == v || nv && nv.include(v); },
- '$=': function(nv, v) { return nv.endsWith(v); },
- '*=': function(nv, v) { return nv.include(v); },
'~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
'|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
'-').include('-' + (v || "").toUpperCase() + '-'); }
@@ -3423,19 +3902,10 @@ Object.extend(Selector, {
if (Prototype.Browser.IE) {
Object.extend(Selector.handlers, {
- // IE returns comment nodes on getElementsByTagName("*").
- // Filter them out.
concat: function(a, b) {
for (var i = 0, node; node = b[i]; i++)
if (node.tagName !== "!") a.push(node);
return a;
- },
-
- // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
- unmark: function(nodes) {
- for (var i = 0, node; node = nodes[i]; i++)
- node.removeAttribute('_countedByPrototype');
- return nodes;
}
});
}
@@ -3443,9 +3913,11 @@ if (Prototype.Browser.IE) {
function $$() {
return Selector.findChildElements(document, $A(arguments));
}
+
var Form = {
reset: function(form) {
- $(form).reset();
+ form = $(form);
+ form.reset();
return form;
},
@@ -3460,7 +3932,6 @@ var Form = {
if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
submit !== false && (!submit || key == submit) && (submitted = true)))) {
if (key in result) {
- // a key is already present; construct an array of values
if (!Object.isArray(result[key])) result[key] = [result[key]];
result[key].push(value);
}
@@ -3480,13 +3951,18 @@ Form.Methods = {
},
getElements: function(form) {
- return $A($(form).getElementsByTagName('*')).inject([],
- function(elements, child) {
- if (Form.Element.Serializers[child.tagName.toLowerCase()])
- elements.push(Element.extend(child));
- return elements;
- }
- );
+ var elements = $(form).getElementsByTagName('*'),
+ element,
+ arr = [ ],
+ serializers = Form.Element.Serializers;
+ for (var i = 0; element = elements[i]; i++) {
+ arr.push(element);
+ }
+ return arr.inject([], function(elements, child) {
+ if (serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ })
},
getInputs: function(form, typeName, name) {
@@ -3526,7 +4002,7 @@ Form.Methods = {
}).sortBy(function(element) { return element.tabIndex }).first();
return firstByIndex ? firstByIndex : elements.find(function(element) {
- return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ return /^(?:input|select|textarea)$/i.test(element.tagName);
});
},
@@ -3557,6 +4033,7 @@ Form.Methods = {
/*--------------------------------------------------------------------------*/
+
Form.Element = {
focus: function(element) {
$(element).focus();
@@ -3570,6 +4047,7 @@ Form.Element = {
};
Form.Element.Methods = {
+
serialize: function(element) {
element = $(element);
if (!element.disabled && element.name) {
@@ -3610,7 +4088,7 @@ Form.Element.Methods = {
try {
element.focus();
if (element.select && (element.tagName.toLowerCase() != 'input' ||
- !['button', 'reset', 'submit'].include(element.type)))
+ !(/^(?:button|reset|submit)$/i.test(element.type))))
element.select();
} catch (e) { }
return element;
@@ -3632,6 +4110,7 @@ Form.Element.Methods = {
/*--------------------------------------------------------------------------*/
var Field = Form.Element;
+
var $F = Form.Element.Methods.getValue;
/*--------------------------------------------------------------------------*/
@@ -3694,13 +4173,13 @@ Form.Element.Serializers = {
},
optionValue: function(opt) {
- // extend element because hasAttribute may not be native
return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
}
};
/*--------------------------------------------------------------------------*/
+
Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
initialize: function($super, element, frequency, callback) {
$super(callback, frequency);
@@ -3782,354 +4261,441 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
return Form.serialize(this.element);
}
});
-if (!window.Event) var Event = { };
-
-Object.extend(Event, {
- KEY_BACKSPACE: 8,
- KEY_TAB: 9,
- KEY_RETURN: 13,
- KEY_ESC: 27,
- KEY_LEFT: 37,
- KEY_UP: 38,
- KEY_RIGHT: 39,
- KEY_DOWN: 40,
- KEY_DELETE: 46,
- KEY_HOME: 36,
- KEY_END: 35,
- KEY_PAGEUP: 33,
- KEY_PAGEDOWN: 34,
- KEY_INSERT: 45,
-
- cache: { },
-
- relatedTarget: function(event) {
- var element;
- switch(event.type) {
- case 'mouseover': element = event.fromElement; break;
- case 'mouseout': element = event.toElement; break;
- default: return null;
- }
- return Element.extend(element);
- }
-});
+(function() {
+
+ var Event = {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: {}
+ };
-Event.Methods = (function() {
- var isButton;
+ var docEl = document.documentElement;
+ var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
+ && 'onmouseleave' in docEl;
+ var _isButton;
if (Prototype.Browser.IE) {
var buttonMap = { 0: 1, 1: 4, 2: 2 };
- isButton = function(event, code) {
- return event.button == buttonMap[code];
+ _isButton = function(event, code) {
+ return event.button === buttonMap[code];
};
-
} else if (Prototype.Browser.WebKit) {
- isButton = function(event, code) {
+ _isButton = function(event, code) {
switch (code) {
case 0: return event.which == 1 && !event.metaKey;
case 1: return event.which == 1 && event.metaKey;
default: return false;
}
};
-
} else {
- isButton = function(event, code) {
+ _isButton = function(event, code) {
return event.which ? (event.which === code + 1) : (event.button === code);
};
}
- return {
- isLeftClick: function(event) { return isButton(event, 0) },
- isMiddleClick: function(event) { return isButton(event, 1) },
- isRightClick: function(event) { return isButton(event, 2) },
-
- element: function(event) {
- event = Event.extend(event);
-
- var node = event.target,
- type = event.type,
- currentTarget = event.currentTarget;
-
- if (currentTarget && currentTarget.tagName) {
- // Firefox screws up the "click" event when moving between radio buttons
- // via arrow keys. It also screws up the "load" and "error" events on images,
- // reporting the document as the target instead of the original image.
- if (type === 'load' || type === 'error' ||
- (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
- && currentTarget.type === 'radio'))
- node = currentTarget;
- }
- if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
- return Element.extend(node);
- },
+ function isLeftClick(event) { return _isButton(event, 0) }
- findElement: function(event, expression) {
- var element = Event.element(event);
- if (!expression) return element;
- var elements = [element].concat(element.ancestors());
- return Selector.findElement(elements, expression, 0);
- },
+ function isMiddleClick(event) { return _isButton(event, 1) }
- pointer: function(event) {
- var docElement = document.documentElement,
- body = document.body || { scrollLeft: 0, scrollTop: 0 };
- return {
- x: event.pageX || (event.clientX +
- (docElement.scrollLeft || body.scrollLeft) -
- (docElement.clientLeft || 0)),
- y: event.pageY || (event.clientY +
- (docElement.scrollTop || body.scrollTop) -
- (docElement.clientTop || 0))
- };
- },
+ function isRightClick(event) { return _isButton(event, 2) }
+
+ function element(event) {
+ event = Event.extend(event);
- pointerX: function(event) { return Event.pointer(event).x },
- pointerY: function(event) { return Event.pointer(event).y },
+ var node = event.target, type = event.type,
+ currentTarget = event.currentTarget;
- stop: function(event) {
- Event.extend(event);
- event.preventDefault();
- event.stopPropagation();
- event.stopped = true;
+ if (currentTarget && currentTarget.tagName) {
+ if (type === 'load' || type === 'error' ||
+ (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
+ && currentTarget.type === 'radio'))
+ node = currentTarget;
}
+
+ if (node.nodeType == Node.TEXT_NODE)
+ node = node.parentNode;
+
+ return Element.extend(node);
+ }
+
+ function findElement(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ }
+
+ function pointer(event) {
+ return { x: pointerX(event), y: pointerY(event) };
+ }
+
+ function pointerX(event) {
+ var docElement = document.documentElement,
+ body = document.body || { scrollLeft: 0 };
+
+ return event.pageX || (event.clientX +
+ (docElement.scrollLeft || body.scrollLeft) -
+ (docElement.clientLeft || 0));
+ }
+
+ function pointerY(event) {
+ var docElement = document.documentElement,
+ body = document.body || { scrollTop: 0 };
+
+ return event.pageY || (event.clientY +
+ (docElement.scrollTop || body.scrollTop) -
+ (docElement.clientTop || 0));
+ }
+
+
+ function stop(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+
+ event.stopped = true;
+ }
+
+ Event.Methods = {
+ isLeftClick: isLeftClick,
+ isMiddleClick: isMiddleClick,
+ isRightClick: isRightClick,
+
+ element: element,
+ findElement: findElement,
+
+ pointer: pointer,
+ pointerX: pointerX,
+ pointerY: pointerY,
+
+ stop: stop
};
-})();
-Event.extend = (function() {
+
var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
m[name] = Event.Methods[name].methodize();
return m;
});
if (Prototype.Browser.IE) {
+ function _relatedTarget(event) {
+ var element;
+ switch (event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+
Object.extend(methods, {
stopPropagation: function() { this.cancelBubble = true },
preventDefault: function() { this.returnValue = false },
- inspect: function() { return "[object Event]" }
+ inspect: function() { return '[object Event]' }
});
- return function(event) {
+ Event.extend = function(event, element) {
if (!event) return false;
if (event._extendedByPrototype) return event;
event._extendedByPrototype = Prototype.emptyFunction;
var pointer = Event.pointer(event);
+
Object.extend(event, {
- target: event.srcElement,
- relatedTarget: Event.relatedTarget(event),
+ target: event.srcElement || element,
+ relatedTarget: _relatedTarget(event),
pageX: pointer.x,
pageY: pointer.y
});
+
return Object.extend(event, methods);
};
-
} else {
- Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
+ Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
Object.extend(Event.prototype, methods);
- return Prototype.K;
+ Event.extend = Prototype.K;
}
-})();
-
-Object.extend(Event, (function() {
- var cache = Event.cache;
- function getEventID(element) {
- if (element._prototypeEventID) return element._prototypeEventID[0];
- arguments.callee.id = arguments.callee.id || 1;
- return element._prototypeEventID = [++arguments.callee.id];
- }
+ function _createResponder(element, eventName, handler) {
+ var registry = Element.retrieve(element, 'prototype_event_registry');
- function getDOMEventName(eventName) {
- if (eventName && eventName.include(':')) return "dataavailable";
- return eventName;
- }
+ if (Object.isUndefined(registry)) {
+ CACHE.push(element);
+ registry = Element.retrieve(element, 'prototype_event_registry', $H());
+ }
- function getCacheForID(id) {
- return cache[id] = cache[id] || { };
- }
+ var respondersForEvent = registry.get(eventName);
+ if (Object.isUndefined(respondersForEvent)) {
+ respondersForEvent = [];
+ registry.set(eventName, respondersForEvent);
+ }
- function getWrappersForEventName(id, eventName) {
- var c = getCacheForID(id);
- return c[eventName] = c[eventName] || [];
- }
+ if (respondersForEvent.pluck('handler').include(handler)) return false;
- function createWrapper(element, eventName, handler) {
- var id = getEventID(element);
- var c = getWrappersForEventName(id, eventName);
- if (c.pluck("handler").include(handler)) return false;
+ var responder;
+ if (eventName.include(":")) {
+ responder = function(event) {
+ if (Object.isUndefined(event.eventName))
+ return false;
- var wrapper = function(event) {
- if (!Event || !Event.extend ||
- (event.eventName && event.eventName != eventName))
+ if (event.eventName !== eventName)
return false;
- Event.extend(event);
- handler.call(element, event);
- };
+ Event.extend(event, element);
+ handler.call(element, event);
+ };
+ } else {
+ if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
+ (eventName === "mouseenter" || eventName === "mouseleave")) {
+ if (eventName === "mouseenter" || eventName === "mouseleave") {
+ responder = function(event) {
+ Event.extend(event, element);
+
+ var parent = event.relatedTarget;
+ while (parent && parent !== element) {
+ try { parent = parent.parentNode; }
+ catch(e) { parent = element; }
+ }
- wrapper.handler = handler;
- c.push(wrapper);
- return wrapper;
- }
+ if (parent === element) return;
- function findWrapper(id, eventName, handler) {
- var c = getWrappersForEventName(id, eventName);
- return c.find(function(wrapper) { return wrapper.handler == handler });
- }
+ handler.call(element, event);
+ };
+ }
+ } else {
+ responder = function(event) {
+ Event.extend(event, element);
+ handler.call(element, event);
+ };
+ }
+ }
- function destroyWrapper(id, eventName, handler) {
- var c = getCacheForID(id);
- if (!c[eventName]) return false;
- c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ responder.handler = handler;
+ respondersForEvent.push(responder);
+ return responder;
}
- function destroyCache() {
- for (var id in cache)
- for (var eventName in cache[id])
- cache[id][eventName] = null;
+ function _destroyCache() {
+ for (var i = 0, length = CACHE.length; i < length; i++) {
+ Event.stopObserving(CACHE[i]);
+ CACHE[i] = null;
+ }
}
+ var CACHE = [];
- // Internet Explorer needs to remove event handlers on page unload
- // in order to avoid memory leaks.
- if (window.attachEvent) {
- window.attachEvent("onunload", destroyCache);
- }
+ if (Prototype.Browser.IE)
+ window.attachEvent('onunload', _destroyCache);
- // Safari has a dummy event handler on page unload so that it won't
- // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
- // object when page is returned to via the back button using its bfcache.
- if (Prototype.Browser.WebKit) {
+ if (Prototype.Browser.WebKit)
window.addEventListener('unload', Prototype.emptyFunction, false);
+
+
+ var _getDOMEventName = Prototype.K;
+
+ if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
+ _getDOMEventName = function(eventName) {
+ var translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
+ return eventName in translations ? translations[eventName] : eventName;
+ };
}
- return {
- observe: function(element, eventName, handler) {
- element = $(element);
- var name = getDOMEventName(eventName);
+ function observe(element, eventName, handler) {
+ element = $(element);
- var wrapper = createWrapper(element, eventName, handler);
- if (!wrapper) return element;
+ var responder = _createResponder(element, eventName, handler);
- if (element.addEventListener) {
- element.addEventListener(name, wrapper, false);
- } else {
- element.attachEvent("on" + name, wrapper);
+ if (!responder) return element;
+
+ if (eventName.include(':')) {
+ if (element.addEventListener)
+ element.addEventListener("dataavailable", responder, false);
+ else {
+ element.attachEvent("ondataavailable", responder);
+ element.attachEvent("onfilterchange", responder);
}
+ } else {
+ var actualEventName = _getDOMEventName(eventName);
- return element;
- },
+ if (element.addEventListener)
+ element.addEventListener(actualEventName, responder, false);
+ else
+ element.attachEvent("on" + actualEventName, responder);
+ }
- stopObserving: function(element, eventName, handler) {
- element = $(element);
- var id = getEventID(element), name = getDOMEventName(eventName);
+ return element;
+ }
- if (!handler && eventName) {
- getWrappersForEventName(id, eventName).each(function(wrapper) {
- element.stopObserving(eventName, wrapper.handler);
- });
- return element;
+ function stopObserving(element, eventName, handler) {
+ element = $(element);
- } else if (!eventName) {
- Object.keys(getCacheForID(id)).each(function(eventName) {
- element.stopObserving(eventName);
- });
- return element;
- }
+ var registry = Element.retrieve(element, 'prototype_event_registry');
- var wrapper = findWrapper(id, eventName, handler);
- if (!wrapper) return element;
+ if (Object.isUndefined(registry)) return element;
- if (element.removeEventListener) {
- element.removeEventListener(name, wrapper, false);
- } else {
- element.detachEvent("on" + name, wrapper);
- }
+ if (eventName && !handler) {
+ var responders = registry.get(eventName);
- destroyWrapper(id, eventName, handler);
+ if (Object.isUndefined(responders)) return element;
+ responders.each( function(r) {
+ Element.stopObserving(element, eventName, r.handler);
+ });
return element;
- },
+ } else if (!eventName) {
+ registry.each( function(pair) {
+ var eventName = pair.key, responders = pair.value;
- fire: function(element, eventName, memo) {
- element = $(element);
- if (element == document && document.createEvent && !element.dispatchEvent)
- element = document.documentElement;
+ responders.each( function(r) {
+ Element.stopObserving(element, eventName, r.handler);
+ });
+ });
+ return element;
+ }
- var event;
- if (document.createEvent) {
- event = document.createEvent("HTMLEvents");
- event.initEvent("dataavailable", true, true);
- } else {
- event = document.createEventObject();
- event.eventType = "ondataavailable";
- }
+ var responders = registry.get(eventName);
- event.eventName = eventName;
- event.memo = memo || { };
+ if (!responders) return;
- if (document.createEvent) {
- element.dispatchEvent(event);
- } else {
- element.fireEvent(event.eventType, event);
+ var responder = responders.find( function(r) { return r.handler === handler; });
+ if (!responder) return element;
+
+ var actualEventName = _getDOMEventName(eventName);
+
+ if (eventName.include(':')) {
+ if (element.removeEventListener)
+ element.removeEventListener("dataavailable", responder, false);
+ else {
+ element.detachEvent("ondataavailable", responder);
+ element.detachEvent("onfilterchange", responder);
}
+ } else {
+ if (element.removeEventListener)
+ element.removeEventListener(actualEventName, responder, false);
+ else
+ element.detachEvent('on' + actualEventName, responder);
+ }
- return Event.extend(event);
+ registry.set(eventName, responders.without(responder));
+
+ return element;
+ }
+
+ function fire(element, eventName, memo, bubble) {
+ element = $(element);
+
+ if (Object.isUndefined(bubble))
+ bubble = true;
+
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent('HTMLEvents');
+ event.initEvent('dataavailable', true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
}
- };
-})());
-Object.extend(Event, Event.Methods);
+ event.eventName = eventName;
+ event.memo = memo || { };
-Element.addMethods({
- fire: Event.fire,
- observe: Event.observe,
- stopObserving: Event.stopObserving
-});
+ if (document.createEvent)
+ element.dispatchEvent(event);
+ else
+ element.fireEvent(event.eventType, event);
-Object.extend(document, {
- fire: Element.Methods.fire.methodize(),
- observe: Element.Methods.observe.methodize(),
- stopObserving: Element.Methods.stopObserving.methodize(),
- loaded: false
-});
+ return Event.extend(event);
+ }
+
+
+ Object.extend(Event, Event.Methods);
+
+ Object.extend(Event, {
+ fire: fire,
+ observe: observe,
+ stopObserving: stopObserving
+ });
+
+ Element.addMethods({
+ fire: fire,
+
+ observe: observe,
+
+ stopObserving: stopObserving
+ });
+
+ Object.extend(document, {
+ fire: fire.methodize(),
+
+ observe: observe.methodize(),
+
+ stopObserving: stopObserving.methodize(),
+
+ loaded: false
+ });
+
+ if (window.Event) Object.extend(window.Event, Event);
+ else window.Event = Event;
+})();
(function() {
/* Support for the DOMContentLoaded event is based on work by Dan Webb,
- Matthias Miller, Dean Edwards and John Resig. */
+ Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
var timer;
function fireContentLoadedEvent() {
if (document.loaded) return;
- if (timer) window.clearInterval(timer);
- document.fire("dom:loaded");
+ if (timer) window.clearTimeout(timer);
document.loaded = true;
+ document.fire('dom:loaded');
}
- if (document.addEventListener) {
- if (Prototype.Browser.WebKit) {
- timer = window.setInterval(function() {
- if (/loaded|complete/.test(document.readyState))
- fireContentLoadedEvent();
- }, 0);
-
- Event.observe(window, "load", fireContentLoadedEvent);
+ function checkReadyState() {
+ if (document.readyState === 'complete') {
+ document.stopObserving('readystatechange', checkReadyState);
+ fireContentLoadedEvent();
+ }
+ }
- } else {
- document.addEventListener("DOMContentLoaded",
- fireContentLoadedEvent, false);
+ function pollDoScroll() {
+ try { document.documentElement.doScroll('left'); }
+ catch(e) {
+ timer = pollDoScroll.defer();
+ return;
}
+ fireContentLoadedEvent();
+ }
+ if (document.addEventListener) {
+ document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
} else {
- document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
- $("__onDOMContentLoaded").onreadystatechange = function() {
- if (this.readyState == "complete") {
- this.onreadystatechange = null;
- fireContentLoadedEvent();
- }
- };
+ document.observe('readystatechange', checkReadyState);
+ if (window == top)
+ timer = pollDoScroll.defer();
}
+
+ Event.observe(window, 'load', fireContentLoadedEvent);
})();
+
+Element.addMethods();
+
/*------------------------------- DEPRECATED -------------------------------*/
Hash.toQueryString = Object.toQueryString;
@@ -4158,16 +4724,9 @@ var Insertion = {
var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
-// This should be moved to script.aculo.us; notice the deprecated methods
-// further below, that map to the newer Element methods.
var Position = {
- // set to true if needed, warning: firefox performance problems
- // NOT neeeded for page scrolling, only if draggable contained in
- // scrollable elements
includeScrollOffsets: false,
- // must be called before calling withinIncludingScrolloffset, every time the
- // page is scrolled
prepare: function() {
this.deltaX = window.pageXOffset
|| document.documentElement.scrollLeft
@@ -4179,7 +4738,6 @@ var Position = {
|| 0;
},
- // caches x/y coordinate pair to use with overlap
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
@@ -4206,7 +4764,6 @@ var Position = {
this.xcomp < this.offset[0] + element.offsetWidth);
},
- // within must be called directly before
overlap: function(mode, element) {
if (!mode) return 0;
if (mode == 'vertical')
@@ -4217,7 +4774,6 @@ var Position = {
element.offsetWidth;
},
- // Deprecation layer -- use newer Element methods now (1.5.2).
cumulativeOffset: Element.Methods.cumulativeOffset,
@@ -4316,5 +4872,3 @@ Element.ClassNames.prototype = {
Object.extend(Element.ClassNames.prototype, Enumerable);
/*--------------------------------------------------------------------------*/
-
-Element.addMethods(); \ No newline at end of file
diff --git a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js
index 2a0a05d25f..f7ddba390a 100644
--- a/railties/lib/generators/rails/app/templates/public/javascripts/rails.js
+++ b/railties/lib/generators/rails/app/templates/public/javascripts/rails.js
@@ -1,4 +1,11 @@
document.observe("dom:loaded", function() {
+ var authToken = $$('meta[name=csrf-token]').first().readAttribute('content'),
+ authParam = $$('meta[name=csrf-param]').first().readAttribute('content'),
+ formTemplate = '<form method="#{method}" action="#{action}">\
+ #{realmethod}<input name="#{param}" value="#{token}" type="hidden">\
+ </form>',
+ realmethodTemplate = '<input name="_method" value="#{method}" type="hidden">';
+
function handleRemote(element) {
var method, url, params;
@@ -34,20 +41,46 @@ document.observe("dom:loaded", function() {
}
$(document.body).observe("click", function(event) {
+ var message = event.element().readAttribute('data-confirm');
+ if (message && !confirm(message)) {
+ event.stop();
+ return false;
+ }
+
var element = event.findElement("a[data-remote=true]");
if (element) {
handleRemote(element);
event.stop();
}
- });
- $(document.body).observe("ajax:before", function(event) {
- var message = event.element().readAttribute('data-confirm');
- if (message && !confirm(message)) event.stop();
+ var element = event.findElement("a[data-method]");
+ if (element && element.readAttribute('data-remote') != 'true') {
+ var method = element.readAttribute('data-method'),
+ piggyback = method.toLowerCase() != 'post',
+ formHTML = formTemplate.interpolate({
+ method: 'POST',
+ realmethod: piggyback ? realmethodTemplate.interpolate({ method: method }) : '',
+ action: element.readAttribute('href'),
+ token: authToken,
+ param: authParam
+ });
+
+ var form = new Element('div').update(formHTML).down().hide();
+ this.insert({ bottom: form });
+
+ form.submit();
+ event.stop();
+ }
});
// TODO: I don't think submit bubbles in IE
$(document.body).observe("submit", function(event) {
+ var message = event.element().readAttribute('data-confirm');
+ if (message && !confirm(message)) {
+ event.stop();
+ return false;
+ }
+
var inputs = event.element().select("input[type=submit][data-disable-with]");
inputs.each(function(input) {
input.disabled = true;
diff --git a/railties/lib/generators/rails/app/templates/script/rails b/railties/lib/generators/rails/app/templates/script/rails
index 2fcf6d09b5..b01d1ee183 100644
--- a/railties/lib/generators/rails/app/templates/script/rails
+++ b/railties/lib/generators/rails/app/templates/script/rails
@@ -3,7 +3,6 @@
ENV_PATH = File.expand_path('../../config/environment', __FILE__)
BOOT_PATH = File.expand_path('../../config/boot', __FILE__)
APP_PATH = File.expand_path('../../config/application', __FILE__)
-ROOT_PATH = File.expand_path('../..', __FILE__)
require BOOT_PATH
require 'rails/commands'
diff --git a/railties/lib/generators/rails/app/templates/test/test_helper.rb b/railties/lib/generators/rails/app/templates/test/test_helper.rb
index 45b551fc7d..8bf1192ffe 100644
--- a/railties/lib/generators/rails/app/templates/test/test_helper.rb
+++ b/railties/lib/generators/rails/app/templates/test/test_helper.rb
@@ -1,5 +1,5 @@
ENV["RAILS_ENV"] = "test"
-require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
+require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
diff --git a/railties/lib/generators/rails/controller/USAGE b/railties/lib/generators/rails/controller/USAGE
index 6ed4b2edfc..70618a3906 100644
--- a/railties/lib/generators/rails/controller/USAGE
+++ b/railties/lib/generators/rails/controller/USAGE
@@ -9,7 +9,7 @@ Description:
template engine and test framework generators.
Example:
- `./script/generate controller CreditCard open debit credit close`
+ `rails generate controller CreditCard open debit credit close`
Credit card controller with URLs like /credit_card/debit.
Controller: app/controllers/credit_card_controller.rb
diff --git a/railties/lib/generators/rails/generator/USAGE b/railties/lib/generators/rails/generator/USAGE
index ca7d3f62d0..d8c3f7f634 100644
--- a/railties/lib/generators/rails/generator/USAGE
+++ b/railties/lib/generators/rails/generator/USAGE
@@ -3,7 +3,7 @@ Description:
CamelCased or under_scored, as an argument.
Example:
- `./script/generate generator Awesome`
+ `rails generate generator Awesome`
creates a standard awesome generator:
lib/generators/awesome/
diff --git a/railties/lib/generators/rails/generator/templates/USAGE.tt b/railties/lib/generators/rails/generator/templates/USAGE.tt
index ea9f4f12cc..1bb8df840d 100644
--- a/railties/lib/generators/rails/generator/templates/USAGE.tt
+++ b/railties/lib/generators/rails/generator/templates/USAGE.tt
@@ -2,7 +2,7 @@ Description:
Explain the generator
Example:
- ./script/generate <%= file_name %> Thing
+ rails generate <%= file_name %> Thing
This will create:
what/will/it/create
diff --git a/railties/lib/generators/rails/helper/USAGE b/railties/lib/generators/rails/helper/USAGE
index 531c9b390a..c0ddb0f606 100644
--- a/railties/lib/generators/rails/helper/USAGE
+++ b/railties/lib/generators/rails/helper/USAGE
@@ -9,7 +9,7 @@ Description:
test framework.
Example:
- `./script/generate helper CreditCard`
+ `rails generate helper CreditCard`
Credit card helper.
Helper: app/helpers/credit_card_helper.rb
diff --git a/railties/lib/generators/rails/integration_test/USAGE b/railties/lib/generators/rails/integration_test/USAGE
index b76c35a702..57ee3543e6 100644
--- a/railties/lib/generators/rails/integration_test/USAGE
+++ b/railties/lib/generators/rails/integration_test/USAGE
@@ -6,5 +6,5 @@ Description:
TestUnit.
Example:
- `./script/generate integration_test GeneralStories` creates a GeneralStories
+ `rails generate integration_test GeneralStories` creates a GeneralStories
integration test in test/integration/general_stories_test.rb
diff --git a/railties/lib/generators/rails/mailer/USAGE b/railties/lib/generators/rails/mailer/USAGE
index beae79fbf4..a08d459739 100644
--- a/railties/lib/generators/rails/mailer/USAGE
+++ b/railties/lib/generators/rails/mailer/USAGE
@@ -6,7 +6,7 @@ Description:
engine and test framework generators.
Example:
- `./script/generate mailer Notifications signup forgot_password invoice`
+ `rails generate mailer Notifications signup forgot_password invoice`
creates a Notifications mailer class, views, test, and fixtures:
Mailer: app/mailers/notifications.rb
diff --git a/railties/lib/generators/rails/metal/USAGE b/railties/lib/generators/rails/metal/USAGE
index 123ec6c03f..c88325a444 100644
--- a/railties/lib/generators/rails/metal/USAGE
+++ b/railties/lib/generators/rails/metal/USAGE
@@ -2,7 +2,7 @@ Description:
Cast some metal!
Examples:
- `./script/generate metal poller`
+ `rails generate metal poller`
This will create:
Metal: app/metal/poller.rb
diff --git a/railties/lib/generators/rails/migration/USAGE b/railties/lib/generators/rails/migration/USAGE
index d91127aac3..d21c81b760 100644
--- a/railties/lib/generators/rails/migration/USAGE
+++ b/railties/lib/generators/rails/migration/USAGE
@@ -8,12 +8,12 @@ Description:
column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
Example:
- `./script/generate migration AddSslFlag`
+ `rails generate migration AddSslFlag`
If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
db/migrate/20080514090912_add_ssl_flag.rb
- `./script/generate migration AddTitleBodyToPost title:string body:text published:boolean`
+ `rails generate migration AddTitleBodyToPost title:string body:text published:boolean`
This will create the AddTitleBodyToPost in db/migrate/20080514090912_add_title_body_to_post.rb with
this in the Up migration:
diff --git a/railties/lib/generators/rails/model/USAGE b/railties/lib/generators/rails/model/USAGE
index b056d5df8b..d97e9ac103 100644
--- a/railties/lib/generators/rails/model/USAGE
+++ b/railties/lib/generators/rails/model/USAGE
@@ -16,7 +16,7 @@ Description:
created model. This allows you create Single Table Inheritance models.
Examples:
- `./script/generate model account`
+ `rails generate model account`
For ActiveRecord and TestUnit it creates:
@@ -25,6 +25,6 @@ Examples:
Fixtures: test/fixtures/accounts.yml
Migration: db/migrate/XXX_add_accounts.rb
- `./script/generate model post title:string body:text published:boolean`
+ `rails generate model post title:string body:text published:boolean`
Creates a Post model with a string title, text body, and published flag.
diff --git a/railties/lib/generators/rails/observer/USAGE b/railties/lib/generators/rails/observer/USAGE
index 9a20f55a89..d8f32a6a48 100644
--- a/railties/lib/generators/rails/observer/USAGE
+++ b/railties/lib/generators/rails/observer/USAGE
@@ -5,7 +5,7 @@ Description:
This generator only invokes your ORM and test framework generators.
Example:
- `./script/generate observer Account`
+ `rails generate observer Account`
For ActiveRecord and TestUnit it creates:
Observer: app/models/account_observer.rb
diff --git a/railties/lib/generators/rails/performance_test/USAGE b/railties/lib/generators/rails/performance_test/USAGE
index ee82578cdb..9dc799559c 100644
--- a/railties/lib/generators/rails/performance_test/USAGE
+++ b/railties/lib/generators/rails/performance_test/USAGE
@@ -6,5 +6,5 @@ Description:
TestUnit.
Example:
- `./script/generate performance_test GeneralStories` creates a GeneralStories
+ `rails generate performance_test GeneralStories` creates a GeneralStories
performance test in test/performance/general_stories_test.rb
diff --git a/railties/lib/generators/rails/plugin/USAGE b/railties/lib/generators/rails/plugin/USAGE
index 8a17fa4dec..00a429c585 100644
--- a/railties/lib/generators/rails/plugin/USAGE
+++ b/railties/lib/generators/rails/plugin/USAGE
@@ -3,7 +3,7 @@ Description:
CamelCased or under_scored, as an argument.
Example:
- `./script/generate plugin BrowserFilters`
+ `rails generate plugin BrowserFilters`
creates a standard browser_filters plugin:
vendor/plugins/browser_filters/README
diff --git a/railties/lib/generators/rails/resource/USAGE b/railties/lib/generators/rails/resource/USAGE
index 936619b0db..e359cd574f 100644
--- a/railties/lib/generators/rails/resource/USAGE
+++ b/railties/lib/generators/rails/resource/USAGE
@@ -18,6 +18,6 @@ Description:
views or add any methods to the generated controller.
Examples:
- `./script/generate resource post` # no attributes
- `./script/generate resource post title:string body:text published:boolean`
- `./script/generate resource purchase order_id:integer amount:decimal`
+ `rails generate resource post` # no attributes
+ `rails generate resource post title:string body:text published:boolean`
+ `rails generate resource purchase order_id:integer amount:decimal`
diff --git a/railties/lib/generators/rails/scaffold/USAGE b/railties/lib/generators/rails/scaffold/USAGE
index 530ccdaf0a..be1d113ed8 100644
--- a/railties/lib/generators/rails/scaffold/USAGE
+++ b/railties/lib/generators/rails/scaffold/USAGE
@@ -21,9 +21,9 @@ Description:
declaration in config/routes.rb.
If you want to remove all the generated files, run
- 'script/destroy scaffold ModelName'.
+ 'rails destroy scaffold ModelName'.
Examples:
- `./script/generate scaffold post`
- `./script/generate scaffold post title:string body:text published:boolean`
- `./script/generate scaffold purchase order_id:integer amount:decimal`
+ `rails generate scaffold post`
+ `rails generate scaffold post title:string body:text published:boolean`
+ `rails generate scaffold purchase order_id:integer amount:decimal`
diff --git a/railties/lib/generators/rails/scaffold_controller/USAGE b/railties/lib/generators/rails/scaffold_controller/USAGE
index d60a3c3680..673f69bc81 100644
--- a/railties/lib/generators/rails/scaffold_controller/USAGE
+++ b/railties/lib/generators/rails/scaffold_controller/USAGE
@@ -11,7 +11,7 @@ Description:
template engine and test framework generators.
Example:
- `./script/generate scaffold_controller CreditCard`
+ `rails generate scaffold_controller CreditCard`
Credit card controller with URLs like /credit_card/debit.
Controller: app/controllers/credit_cards_controller.rb
diff --git a/railties/lib/generators/rails/session_migration/USAGE b/railties/lib/generators/rails/session_migration/USAGE
index e106f6ecc8..564d1ffd78 100644
--- a/railties/lib/generators/rails/session_migration/USAGE
+++ b/railties/lib/generators/rails/session_migration/USAGE
@@ -5,4 +5,4 @@ Description:
Before invoking this generator, be sure that your ORM supports session stores.
Example:
- `./script/generate session_migration CreateSessionTable`
+ `rails generate session_migration CreateSessionTable`
diff --git a/railties/lib/generators/rails/stylesheets/USAGE b/railties/lib/generators/rails/stylesheets/USAGE
index d6a81e51d0..59e5495d0b 100644
--- a/railties/lib/generators/rails/stylesheets/USAGE
+++ b/railties/lib/generators/rails/stylesheets/USAGE
@@ -2,4 +2,4 @@ Description:
Copies scaffold stylesheets to public/stylesheets/.
Examples:
- `./script/generate stylesheets`
+ `rails generate stylesheets`
diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb
index 1a0b4a8d73..82775b7e3b 100644
--- a/railties/lib/rails/all.rb
+++ b/railties/lib/rails/all.rb
@@ -1,11 +1,8 @@
require "rails"
%w(
- active_support
- active_model
active_record
action_controller
- action_view
action_mailer
active_resource
rails/test_unit
@@ -14,4 +11,4 @@ require "rails"
require "#{framework}/railtie"
rescue LoadError
end
-end \ No newline at end of file
+end
diff --git a/railties/lib/rails/backtrace_cleaner.rb b/railties/lib/rails/backtrace_cleaner.rb
index 40198306f9..14eccd5a6a 100644
--- a/railties/lib/rails/backtrace_cleaner.rb
+++ b/railties/lib/rails/backtrace_cleaner.rb
@@ -12,7 +12,6 @@ module Rails
add_filter { |line| line.sub('./', '/') } # for tests
add_gem_filters
- add_bundler_filters
add_silencer { |line| !APP_DIRS.any? { |dir| line =~ /^#{dir}/ } }
end
@@ -27,16 +26,6 @@ module Rails
}
end
end
-
- def add_bundler_filters
- return unless defined? Bundler
- add_filter { |line|
- line.sub(%r{vendor/gems/[^/]+/[^/]+/gems/([^/]+)-([0-9.]+)/(.*)}, '\1 (\2) \3')
- }
- add_filter { |line|
- line.sub(%r{vendor/gems/[^/]+/[^/]+/dirs/([^/]+)/(.*)}, '\1 \2')
- }
- end
end
# For installing the BacktraceCleaner in the test/unit
diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb
index 4240038673..6972e25b29 100644
--- a/railties/lib/rails/commands.rb
+++ b/railties/lib/rails/commands.rb
@@ -34,8 +34,12 @@ when 'c', 'console'
Rails::Console.start(Rails::Application)
when 's', 'server'
require 'rails/commands/server'
- Dir.chdir(ROOT_PATH)
- Rails::Server.start
+ # Initialize the server first, so environment options are set
+ server = Rails::Server.new
+ require APP_PATH
+
+ Dir.chdir(Rails::Application.root)
+ server.start
when 'db', 'dbconsole'
require 'rails/commands/dbconsole'
require APP_PATH
@@ -57,11 +61,7 @@ when 'plugin'
require 'rails/commands/plugin'
when 'runner'
require 'rails/commands/runner'
- require ENV_PATH
-
-when '--version', '-v'
- puts "Rails #{Rails::VERSION::STRING}"
when '--help', '-h'
puts HELP_TEXT
when '--version', '-v'
@@ -70,4 +70,4 @@ when '--version', '-v'
else
puts "Error: Command not recognized"
puts HELP_TEXT
-end \ No newline at end of file
+end
diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb
index a984eff6e2..50df6ba405 100644
--- a/railties/lib/rails/commands/console.rb
+++ b/railties/lib/rails/commands/console.rb
@@ -19,7 +19,7 @@ module Rails
opt.banner = "Usage: console [environment] [options]"
opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
- opt.on('--irb') { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/console` instead' }
+ opt.on('--irb', "DEPRECATED: Invoke `/your/choice/of/ruby script/rails console` instead") { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/rails console` instead' }
opt.parse!(ARGV)
end
diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb
index 92a06ebdd8..9023c61bf2 100644
--- a/railties/lib/rails/commands/destroy.rb
+++ b/railties/lib/rails/commands/destroy.rb
@@ -1,7 +1,7 @@
require 'rails/generators'
-if ARGV.size == 0
- Rails::Generators.help
+if [nil, "-h", "--help"].include?(ARGV.first)
+ Rails::Generators.help 'destroy'
exit
end
diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb
index 5e45d8ab46..7d05a30de8 100755
--- a/railties/lib/rails/commands/generate.rb
+++ b/railties/lib/rails/commands/generate.rb
@@ -1,7 +1,7 @@
require 'rails/generators'
-if ARGV.size == 0
- Rails::Generators.help
+if [nil, "-h", "--help"].include?(ARGV.first)
+ Rails::Generators.help 'generate'
exit
end
diff --git a/railties/lib/rails/commands/performance/benchmarker.rb b/railties/lib/rails/commands/performance/benchmarker.rb
index ad84d94dbf..0432261802 100644
--- a/railties/lib/rails/commands/performance/benchmarker.rb
+++ b/railties/lib/rails/commands/performance/benchmarker.rb
@@ -1,5 +1,5 @@
-if ARGV.empty?
- puts "Usage: benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ..."
+if [nil, "-h", "--help"].include?(ARGV.first)
+ puts "Usage: rails benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ..."
exit 1
end
diff --git a/railties/lib/rails/commands/performance/profiler.rb b/railties/lib/rails/commands/performance/profiler.rb
index 50ae411166..6d9717b5cd 100644
--- a/railties/lib/rails/commands/performance/profiler.rb
+++ b/railties/lib/rails/commands/performance/profiler.rb
@@ -1,5 +1,5 @@
-if ARGV.empty?
- $stderr.puts "Usage: profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]"
+if [nil, "-h", "--help"].include?(ARGV.first)
+ $stderr.puts "Usage: rails profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]"
exit(1)
end
diff --git a/railties/lib/rails/commands/plugin.rb b/railties/lib/rails/commands/plugin.rb
index af12df1425..8bcd92a33b 100644
--- a/railties/lib/rails/commands/plugin.rb
+++ b/railties/lib/rails/commands/plugin.rb
@@ -2,7 +2,7 @@
#
# Installing plugins:
#
-# $ ./script/plugin install continuous_builder asset_timestamping
+# $ rails plugin install continuous_builder asset_timestamping
#
# Specifying revisions:
#
@@ -319,13 +319,13 @@ module Commands
o.separator ""
o.separator "EXAMPLES"
o.separator " Install a plugin:"
- o.separator " #{@script_name} install continuous_builder\n"
+ o.separator " #{@script_name} plugin install continuous_builder\n"
o.separator " Install a plugin from a subversion URL:"
- o.separator " #{@script_name} install http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder\n"
+ o.separator " #{@script_name} plugin install http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder\n"
o.separator " Install a plugin from a git URL:"
- o.separator " #{@script_name} install git://github.com/SomeGuy/my_awesome_plugin.git\n"
+ o.separator " #{@script_name} plugin install git://github.com/SomeGuy/my_awesome_plugin.git\n"
o.separator " Install a plugin and add a svn:externals entry to vendor/plugins"
- o.separator " #{@script_name} install -x continuous_builder\n"
+ o.separator " #{@script_name} plugin install -x continuous_builder\n"
end
end
@@ -381,7 +381,7 @@ module Commands
"Exports the plugin, allowing you to check it into your local repository. Does not enable updates, or add an svn:externals entry.") { |v| @method = :export }
o.on( "-q", "--quiet",
"Suppresses the output from installation.",
- "Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true }
+ "Ignored if -v is passed (rails plugin -v install ...)") { |v| @options[:quiet] = true }
o.on( "-r REVISION", "--revision REVISION",
"Checks out the given revision from subversion or git.",
"Ignored if subversion/git is not used.") { |v| @options[:revision] = v }
diff --git a/railties/lib/rails/commands/runner.rb b/railties/lib/rails/commands/runner.rb
index 606e04483f..1570b9ab0d 100644
--- a/railties/lib/rails/commands/runner.rb
+++ b/railties/lib/rails/commands/runner.rb
@@ -35,6 +35,8 @@ ARGV.delete(code_or_file)
ENV["RAILS_ENV"] = options[:environment]
+require ENV_PATH
+
begin
if code_or_file.nil?
$stderr.puts "Run '#{$0} -h' for help."
diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
index b21ae2a17b..c57660c0d1 100644
--- a/railties/lib/rails/commands/server.rb
+++ b/railties/lib/rails/commands/server.rb
@@ -6,20 +6,21 @@ module Rails
class Server < ::Rack::Server
class Options
def parse!(args)
- options = {}
- args = args.dup
+ args, options = args.dup, {}
+
opt_parser = OptionParser.new do |opts|
+ opts.banner = "Usage: rails server [options]"
opts.on("-p", "--port=port", Integer,
- "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v }
+ "Runs Rails on the specified port.", "Default: 3000") { |v| options[:Port] = v }
opts.on("-b", "--binding=ip", String,
- "Binds Rails to the specified ip.", "Default: #{options[:Host]}") { |v| options[:Host] = v }
+ "Binds Rails to the specified ip.", "Default: 0.0.0.0") { |v| options[:Host] = v }
opts.on("-c", "--config=file", String,
"Use custom rackup configuration file") { |v| options[:config] = v }
opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:daemonize] = true }
opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { options[:debugger] = true }
opts.on("-e", "--environment=name", String,
"Specifies the environment to run this server under (test/development/production).",
- "Default: #{options[:environment]}") { |v| options[:environment] = v }
+ "Default: development") { |v| options[:environment] = v }
opts.separator ""
@@ -33,13 +34,20 @@ module Rails
end
end
+ def initialize(*)
+ super
+ set_environment
+ end
+
def opt_parser
Options.new
end
- def start
- ENV["RAILS_ENV"] = options[:environment]
+ def set_environment
+ ENV["RAILS_ENV"] ||= options[:environment]
+ end
+ def start
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
puts "=> Rails #{Rails.version} application starting in #{Rails.env} on http://#{options[:Host]}:#{options[:Port]}"
puts "=> Call with -d to detach" unless options[:daemonize]
@@ -48,7 +56,9 @@ module Rails
super
ensure
- puts 'Exiting' unless options[:daemonize]
+ # The '-h' option calls exit before @options is set.
+ # If we call 'options' with it unset, we get double help banners.
+ puts 'Exiting' unless @options && options[:daemonize]
end
def middleware
diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb
index 80b72252f1..910b26f886 100644
--- a/railties/lib/rails/configuration.rb
+++ b/railties/lib/rails/configuration.rb
@@ -91,12 +91,13 @@ module Rails
# Generators configuration which uses method missing to wrap it in a nifty DSL.
# It also allows you to set generators fallbacks and aliases.
class Generators #:nodoc:
- attr_accessor :aliases, :options, :fallbacks, :colorize_logging
+ attr_accessor :aliases, :options, :templates, :fallbacks, :colorize_logging
def initialize
@aliases = Hash.new { |h,k| h[k] = {} }
@options = Hash.new { |h,k| h[k] = {} }
@fallbacks = {}
+ @templates = []
@colorize_logging = true
end
diff --git a/railties/lib/rails/deprecation.rb b/railties/lib/rails/deprecation.rb
index f28da5a6b0..1eb6d804b6 100644
--- a/railties/lib/rails/deprecation.rb
+++ b/railties/lib/rails/deprecation.rb
@@ -2,6 +2,9 @@ require "active_support/string_inquirer"
require "active_support/deprecation"
RAILS_ROOT = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do
+ cattr_accessor :warned
+ self.warned = false
+
def target
Rails.root
end
@@ -11,12 +14,17 @@ RAILS_ROOT = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do
end
def warn(callstack, called, args)
- msg = "RAILS_ROOT is deprecated! Use Rails.root instead"
- ActiveSupport::Deprecation.warn(msg, callstack)
+ unless warned
+ ActiveSupport::Deprecation.warn("RAILS_ROOT is deprecated! Use Rails.root instead", callstack)
+ self.warned = true
+ end
end
end).new
RAILS_ENV = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do
+ cattr_accessor :warned
+ self.warned = false
+
def target
Rails.env
end
@@ -26,12 +34,17 @@ RAILS_ENV = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do
end
def warn(callstack, called, args)
- msg = "RAILS_ENV is deprecated! Use Rails.env instead"
- ActiveSupport::Deprecation.warn(msg, callstack)
+ unless warned
+ ActiveSupport::Deprecation.warn("RAILS_ENV is deprecated! Use Rails.env instead", callstack)
+ self.warned = true
+ end
end
end).new
RAILS_DEFAULT_LOGGER = (Class.new(ActiveSupport::Deprecation::DeprecationProxy) do
+ cattr_accessor :warned
+ self.warned = false
+
def target
Rails.logger
end
@@ -41,7 +54,9 @@ RAILS_DEFAULT_LOGGER = (Class.new(ActiveSupport::Deprecation::DeprecationProxy)
end
def warn(callstack, called, args)
- msg = "RAILS_DEFAULT_LOGGER is deprecated! Use Rails.logger instead"
- ActiveSupport::Deprecation.warn(msg, callstack)
+ unless warned
+ ActiveSupport::Deprecation.warn("RAILS_DEFAULT_LOGGER is deprecated! Use Rails.logger instead", callstack)
+ self.warned = true
+ end
end
end).new
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 2b9c4add4f..226d1aaa88 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -99,7 +99,7 @@ module Rails
unless abstract_railtie?(base)
base.called_from = begin
call_stack = caller.map { |p| p.split(':').first }
- File.dirname(call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] })
+ File.dirname(call_stack.detect { |p| p !~ %r[railties[\w\-]*/lib/rails|rack[\w\-]*/lib/rack] })
end
end
@@ -185,6 +185,10 @@ module Rails
app.metal_loader.paths.unshift(*paths.app.metals.to_a)
end
+ initializer :add_generator_templates do |app|
+ config.generators.templates.unshift(*paths.lib.templates.to_a)
+ end
+
initializer :load_application_initializers do
paths.config.initializers.to_a.sort.each do |initializer|
load(initializer)
diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb
index 7d6de91430..93b882f874 100644
--- a/railties/lib/rails/engine/configuration.rb
+++ b/railties/lib/rails/engine/configuration.rb
@@ -21,6 +21,7 @@ module Rails
paths.app.views "app/views"
paths.lib "lib", :load_path => true
paths.lib.tasks "lib/tasks", :glob => "**/*.rake"
+ paths.lib.templates "lib/templates"
paths.config "config"
paths.config.initializers "config/initializers", :glob => "**/*.rb"
paths.config.locales "config/locales", :glob => "*.{rb,yml}"
diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb
index 5d95f2fa52..c01018aab2 100644
--- a/railties/lib/rails/generators.rb
+++ b/railties/lib/rails/generators.rb
@@ -66,6 +66,11 @@ module Rails
aliases.deep_merge! config.aliases
options.deep_merge! config.options
fallbacks.merge! config.fallbacks
+ templates_path.concat config.templates
+ end
+
+ def self.templates_path
+ @templates_path ||= []
end
def self.aliases #:nodoc:
@@ -161,7 +166,7 @@ module Rails
end
# Show help message with available generators.
- def self.help
+ def self.help(command = 'generate')
lookup!
namespaces = subclasses.map{ |k| k.namespace }
@@ -173,7 +178,7 @@ module Rails
groups[base] << namespace
end
- puts "Usage: rails generate GENERATOR [args] [options]"
+ puts "Usage: rails #{command} GENERATOR [args] [options]"
puts
puts "General options:"
puts " -h, [--help] # Print generators options and usage"
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index f95b15acce..d41da773c6 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -32,7 +32,7 @@ module Rails
options[:git] = "-b #{options[:branch]} #{options[:git]}" if options[:branch]
options[:svn] = "-r #{options[:revision]} #{options[:svn]}" if options[:revision]
in_root do
- run_ruby_script "script/plugin install #{options[:svn] || options[:git]}", :verbose => false
+ run_ruby_script "script/rails plugin install #{options[:svn] || options[:git]}", :verbose => false
end
else
log "! no git or svn provided for #{name}. Skipping..."
@@ -69,7 +69,7 @@ module Rails
# otherwise use name (version).
parts, message = [ name.inspect ], name
if version ||= options.delete(:version)
- parts << version
+ parts << version.inspect
message << " (#{version})"
end
message = options[:git] if options[:git]
@@ -81,7 +81,7 @@ module Rails
end
in_root do
- append_file "Gemfile", "gem #{parts.join(", ")}", :verbose => false
+ append_file "Gemfile", "gem #{parts.join(", ")}\n", :verbose => false
end
end
@@ -226,7 +226,7 @@ module Rails
log :generate, what
argument = args.map {|arg| arg.to_s }.flatten.join(" ")
- in_root { run_ruby_script("script/generate #{what} #{argument}", :verbose => false) }
+ in_root { run_ruby_script("script/rails generate #{what} #{argument}", :verbose => false) }
end
# Runs the supplied rake task
diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb
index dfa0d573c9..9624c35c0b 100644
--- a/railties/lib/rails/generators/base.rb
+++ b/railties/lib/rails/generators/base.rb
@@ -62,7 +62,7 @@ module Rails
#
# For example, if the user invoke the controller generator as:
#
- # ruby script/generate controller Account --test-framework=test_unit
+ # rails generate controller Account --test-framework=test_unit
#
# The controller generator will then try to invoke the following generators:
#
@@ -117,11 +117,11 @@ module Rails
# All hooks come with switches for user interface. If the user don't want
# to use any test framework, he can do:
#
- # ruby script/generate controller Account --skip-test-framework
+ # rails generate controller Account --skip-test-framework
#
# Or similarly:
#
- # ruby script/generate controller Account --no-test-framework
+ # rails generate controller Account --no-test-framework
#
# ==== Boolean hooks
#
@@ -133,7 +133,7 @@ module Rails
#
# Then, if you want, webrat to be invoked, just supply:
#
- # ruby script/generate controller Account --webrat
+ # rails generate controller Account --webrat
#
# The hooks lookup is similar as above:
#
@@ -213,8 +213,7 @@ module Rails
if base.name && base.name !~ /Base$/
Rails::Generators.subclasses << base
- if defined?(Rails.root) && Rails.root
- path = File.expand_path(File.join(Rails.root, 'lib', 'templates'))
+ Rails::Generators.templates_path.each do |path|
if base.name.include?('::')
base.source_paths << File.join(path, base.base_name, base.generator_name)
else
diff --git a/railties/lib/rails/rack/debugger.rb b/railties/lib/rails/rack/debugger.rb
index 0a7b405553..06e23db5f1 100644
--- a/railties/lib/rails/rack/debugger.rb
+++ b/railties/lib/rails/rack/debugger.rb
@@ -1,10 +1,12 @@
+require 'active_support/core_ext/kernel/requires'
+
module Rails
module Rack
class Debugger
def initialize(app)
@app = app
- ARGV.clear # clear ARGV so that script/server options aren't passed to IRB
+ ARGV.clear # clear ARGV so that rails server options aren't passed to IRB
require_library_or_gem 'ruby-debug'
::Debugger.start
diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake
index 7095046f21..f7cc6ff4be 100644
--- a/railties/lib/rails/tasks/documentation.rake
+++ b/railties/lib/rails/tasks/documentation.rake
@@ -14,7 +14,7 @@ namespace :doc do
desc 'Generate documentation for the Rails framework. Specify path with PATH="/path/to/rails"'
Rake::RDocTask.new("rails") { |rdoc|
path = ENV['RAILS_PATH'] || 'vendor/gems/gems'
- version = '-3.0.0.beta' unless ENV['RAILS_PATH']
+ version = '-3.0.0.beta1' unless ENV['RAILS_PATH']
rdoc.rdoc_dir = 'doc/api'
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
rdoc.title = "Rails Framework Documentation"
diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb
index 350d0b3961..f9aa018cab 100644
--- a/railties/lib/rails/test_help.rb
+++ b/railties/lib/rails/test_help.rb
@@ -5,6 +5,12 @@ exit("Abort testing: Your Rails environment is not running in test mode!") unles
require 'test/unit'
require 'active_support/core_ext/kernel/requires'
+# TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit
+if defined?(Test::Unit::Util::BacktraceFilter) && ENV['BACKTRACE'].nil?
+ require 'rails/backtrace_cleaner'
+ Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit }
+end
+
if defined?(ActiveRecord)
class ActiveSupport::TestCase
include ActiveRecord::TestFixtures
diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb
index 21b9dbc074..d99325a6d8 100644
--- a/railties/lib/rails/test_unit/railtie.rb
+++ b/railties/lib/rails/test_unit/railtie.rb
@@ -14,4 +14,4 @@ module Rails
load "rails/test_unit/testing.rake"
end
end
-end \ No newline at end of file
+end
diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb
index c327d4545a..d0c7cb45db 100644
--- a/railties/lib/rails/version.rb
+++ b/railties/lib/rails/version.rb
@@ -2,7 +2,7 @@ module Rails
module VERSION #:nodoc:
MAJOR = 3
MINOR = 0
- TINY = "0.beta"
+ TINY = "0.beta1"
STRING = [MAJOR, MINOR, TINY].join('.')
end
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index e91bd0e1b5..65d2dde89f 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -1,9 +1,10 @@
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = 'railties'
- s.version = '3.0.0.beta'
+ s.version = '3.0.0.beta1'
s.summary = 'Controls boot-up, rake tasks and generators for the Rails framework.'
s.description = 'Controls boot-up, rake tasks and generators for the Rails framework.'
+ s.required_ruby_version = '>= 1.8.7'
s.author = 'David Heinemeier Hansson'
s.email = 'david@loudthinking.com'
@@ -21,6 +22,6 @@ Gem::Specification.new do |s|
s.add_dependency('rake', '>= 0.8.3')
s.add_dependency('thor', '~> 0.13')
- s.add_dependency('activesupport', '= 3.0.0.beta')
- s.add_dependency('actionpack', '= 3.0.0.beta')
+ s.add_dependency('activesupport', '= 3.0.0.beta1')
+ s.add_dependency('actionpack', '= 3.0.0.beta1')
end
diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb
index 25fa100275..712c8bef36 100644
--- a/railties/test/application/generators_test.rb
+++ b/railties/test/application/generators_test.rb
@@ -52,30 +52,23 @@ module ApplicationTests
end
end
- test "generators set rails fallbacks" do
- with_config do |c|
- c.generators.fallbacks[:shoulda] = :test_unit
- expected = { :shoulda => :test_unit }
- assert_equal expected, c.generators.fallbacks
- end
- end
-
- test "generators aliases, options and fallbacks on initialization" do
+ test "generators aliases, options, templates and fallbacks on initialization" do
add_to_config <<-RUBY
config.generators.rails :aliases => { :test_framework => "-w" }
config.generators.orm :datamapper
config.generators.test_framework :rspec
config.generators.fallbacks[:shoulda] = :test_unit
+ config.generators.templates << "some/where"
RUBY
# Initialize the application
require "#{app_path}/config/environment"
require "rails/generators"
- Rails::Generators.configure!
assert_equal :rspec, Rails::Generators.options[:rails][:test_framework]
assert_equal "-w", Rails::Generators.aliases[:rails][:test_framework]
- assert_equal :test_unit, Rails::Generators.fallbacks[:shoulda]
+ assert_equal Hash[:shoulda => :test_unit], Rails::Generators.fallbacks
+ assert_equal ["#{app_path}/lib/templates", "some/where"], Rails::Generators.templates_path
end
test "generators no color on initialization" do
diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb
index 37175783d8..de316a6fd0 100644
--- a/railties/test/application/test_test.rb
+++ b/railties/test/application/test_test.rb
@@ -23,6 +23,23 @@ module ApplicationTests
run_test 'unit/foo_test.rb'
end
+ # Run just in Ruby < 1.9
+ if defined?(Test::Unit::Util::BacktraceFilter)
+ test "adds backtrace cleaner" do
+ app_file 'test/unit/backtrace_test.rb', <<-RUBY
+ require 'test_helper'
+
+ class FooTest < ActiveSupport::TestCase
+ def test_truth
+ assert Test::Unit::Util::BacktraceFilter.ancestors.include?(Rails::BacktraceFilterForTestUnit)
+ end
+ end
+ RUBY
+
+ run_test 'unit/backtrace_test.rb'
+ end
+ end
+
test "integration test" do
controller 'posts', <<-RUBY
class PostsController < ActionController::Base
diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb
index cb1fa96e0d..5929db6318 100644
--- a/railties/test/generators/actions_test.rb
+++ b/railties/test/generators/actions_test.rb
@@ -36,22 +36,22 @@ class ActionsTest < Rails::Generators::TestCase
end
def test_plugin_with_git_option_should_run_plugin_install
- generator.expects(:run_ruby_script).once.with("script/plugin install #{@git_plugin_uri}", :verbose => false)
+ generator.expects(:run_ruby_script).once.with("script/rails plugin install #{@git_plugin_uri}", :verbose => false)
action :plugin, 'restful-authentication', :git => @git_plugin_uri
end
def test_plugin_with_svn_option_should_run_plugin_install
- generator.expects(:run_ruby_script).once.with("script/plugin install #{@svn_plugin_uri}", :verbose => false)
+ generator.expects(:run_ruby_script).once.with("script/rails plugin install #{@svn_plugin_uri}", :verbose => false)
action :plugin, 'restful-authentication', :svn => @svn_plugin_uri
end
def test_plugin_with_git_option_and_branch_should_run_plugin_install
- generator.expects(:run_ruby_script).once.with("script/plugin install -b stable #{@git_plugin_uri}", :verbose => false)
+ generator.expects(:run_ruby_script).once.with("script/rails plugin install -b stable #{@git_plugin_uri}", :verbose => false)
action :plugin, 'restful-authentication', :git => @git_plugin_uri, :branch => 'stable'
end
def test_plugin_with_svn_option_and_revision_should_run_plugin_install
- generator.expects(:run_ruby_script).once.with("script/plugin install -r 1234 #{@svn_plugin_uri}", :verbose => false)
+ generator.expects(:run_ruby_script).once.with("script/rails plugin install -r 1234 #{@svn_plugin_uri}", :verbose => false)
action :plugin, 'restful-authentication', :svn => @svn_plugin_uri, :revision => 1234
end
@@ -103,6 +103,24 @@ class ActionsTest < Rails::Generators::TestCase
assert_file 'Gemfile', /gem "rspec", :only => \["development", "test"\]/
end
+ def test_gem_with_version_should_include_version_in_gemfile
+ run_generator
+
+ action :gem, 'rspec', '>=2.0.0.a5'
+
+ assert_file 'Gemfile', /gem "rspec", ">=2.0.0.a5"/
+ end
+
+ def test_gem_should_insert_on_separate_lines
+ run_generator
+
+ action :gem, 'rspec'
+ action :gem, 'rspec-rails'
+
+ assert_file 'Gemfile', /gem "rspec"$/
+ assert_file 'Gemfile', /gem "rspec-rails"$/
+ end
+
def test_environment_should_include_data_in_environment_initializer_block
run_generator
load_paths = 'config.load_paths += %w["#{Rails.root}/app/extras"]'
@@ -155,7 +173,7 @@ class ActionsTest < Rails::Generators::TestCase
end
def test_generate_should_run_script_generate_with_argument_and_options
- generator.expects(:run_ruby_script).once.with('script/generate model MyModel', :verbose => false)
+ generator.expects(:run_ruby_script).once.with('script/rails generate model MyModel', :verbose => false)
action :generate, 'model', 'MyModel'
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 76579adb26..0a746b200f 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -74,13 +74,13 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_config_database_is_added_by_default
run_generator
assert_file "config/database.yml", /sqlite3/
- assert_file "Gemfile", /^gem "sqlite3-ruby", :require => "sqlite3"$/
+ assert_file "Gemfile", /^gem\s+["']sqlite3-ruby["'],\s+:require\s+=>\s+["']sqlite3["']$/
end
def test_config_another_database
run_generator([destination_root, "-d", "mysql"])
assert_file "config/database.yml", /mysql/
- assert_file "Gemfile", /^gem "mysql"$/
+ assert_file "Gemfile", /^gem\s+["']mysql["']$/
end
def test_config_database_is_not_added_if_skip_activerecord_is_given
@@ -90,7 +90,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_activerecord_is_removed_from_frameworks_if_skip_activerecord_is_given
run_generator [destination_root, "--skip-activerecord"]
- assert_file "config/boot.rb", /# require "active_record\/railtie"/
+ assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
end
def test_prototype_and_test_unit_are_added_by_default
@@ -158,15 +158,13 @@ class AppGeneratorTest < Rails::Generators::TestCase
generator([destination_root], :dev => true).expects(:run).with("bundle install")
silence(:stdout){ generator.invoke }
rails_path = File.expand_path('../../..', Rails.root)
- dev_gem = %(path #{rails_path.inspect}, :glob => "{*/,}*.gemspec")
- assert_file 'Gemfile', /^#{Regexp.escape(dev_gem)}$/
+ assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/
end
def test_edge_option
generator([destination_root], :edge => true).expects(:run).with("bundle install")
silence(:stdout){ generator.invoke }
- edge_gem = %(gem "rails", :git => "git://github.com/rails/rails.git")
- assert_file 'Gemfile', /^#{Regexp.escape(edge_gem)}$/
+ assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$/
end
protected
diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb
index 3cd16a69f9..32be99b144 100644
--- a/railties/test/generators/generators_test_helper.rb
+++ b/railties/test/generators/generators_test_helper.rb
@@ -6,6 +6,7 @@ module Rails
end
end
Rails.application.config.root = Rails.root
+Rails.application.config.generators.templates = [File.join(Rails.root, "lib", "templates")]
require 'rails/generators'
require 'rails/generators/test_case'
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index dcadf3f485..364dbd8e55 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -154,7 +154,7 @@ module TestHelpers
def script(script)
Dir.chdir(app_path) do
- `#{Gem.ruby} #{app_path}/script/#{script}`
+ `#{Gem.ruby} #{app_path}/script/rails #{script}`
end
end