diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/.specification b/vendor/gems/thoughtbot-clearance-0.7.0/.specification new file mode 100644 index 0000000..236e31f --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/.specification @@ -0,0 +1,145 @@ +--- !ruby/object:Gem::Specification +name: thoughtbot-clearance +version: !ruby/object:Gem::Version + version: 0.7.0 +platform: ruby +authors: +- Dan Croak +- Mike Burns +- Jason Morrison +- Joe Ferris +- Eugene Bolshakov +- Nick Quaranto +- Josh Nichols +- Mike Breen +- "Marcel G\xC3\xB6rner" +- Bence Nagy +- Ben Mabey +- Eloy Duran +- Tim Pope +- Mihai Anca +- Mark Cornick +- Shay Arnett +autorequire: +bindir: bin +cert_chain: [] + +date: 2009-08-04 00:00:00 -04:00 +default_executable: +dependencies: [] + +description: Rails authentication with email & password. +email: support@thoughtbot.com +executables: [] + +extensions: [] + +extra_rdoc_files: [] + +files: +- CHANGELOG.textile +- LICENSE +- Rakefile +- README.textile +- TODO.textile +- app/controllers +- app/controllers/clearance +- app/controllers/clearance/confirmations_controller.rb +- app/controllers/clearance/passwords_controller.rb +- app/controllers/clearance/sessions_controller.rb +- app/controllers/clearance/users_controller.rb +- app/models +- app/models/clearance_mailer.rb +- app/views +- app/views/clearance_mailer +- app/views/clearance_mailer/change_password.html.erb +- app/views/clearance_mailer/confirmation.html.erb +- app/views/passwords +- app/views/passwords/edit.html.erb +- app/views/passwords/new.html.erb +- app/views/sessions +- app/views/sessions/new.html.erb +- app/views/users +- app/views/users/_form.html.erb +- app/views/users/new.html.erb +- config/clearance_routes.rb +- generators/clearance +- generators/clearance/clearance_generator.rb +- generators/clearance/lib +- generators/clearance/lib/insert_commands.rb +- generators/clearance/lib/rake_commands.rb +- generators/clearance/templates +- generators/clearance/templates/factories.rb +- generators/clearance/templates/migrations +- generators/clearance/templates/migrations/create_users.rb +- generators/clearance/templates/migrations/update_users.rb +- generators/clearance/templates/README +- generators/clearance/templates/user.rb +- generators/clearance/USAGE +- generators/clearance_features +- generators/clearance_features/clearance_features_generator.rb +- generators/clearance_features/templates +- generators/clearance_features/templates/features +- generators/clearance_features/templates/features/password_reset.feature +- generators/clearance_features/templates/features/sign_in.feature +- generators/clearance_features/templates/features/sign_out.feature +- generators/clearance_features/templates/features/sign_up.feature +- generators/clearance_features/templates/features/step_definitions +- generators/clearance_features/templates/features/step_definitions/clearance_steps.rb +- generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb +- generators/clearance_features/templates/features/support +- generators/clearance_features/templates/features/support/paths.rb +- generators/clearance_features/USAGE +- generators/clearance_views +- generators/clearance_views/clearance_views_generator.rb +- generators/clearance_views/templates +- generators/clearance_views/templates/formtastic +- generators/clearance_views/templates/formtastic/passwords +- generators/clearance_views/templates/formtastic/passwords/edit.html.erb +- generators/clearance_views/templates/formtastic/passwords/new.html.erb +- generators/clearance_views/templates/formtastic/sessions +- generators/clearance_views/templates/formtastic/sessions/new.html.erb +- generators/clearance_views/templates/formtastic/users +- generators/clearance_views/templates/formtastic/users/_inputs.html.erb +- generators/clearance_views/templates/formtastic/users/new.html.erb +- generators/clearance_views/USAGE +- lib/clearance +- lib/clearance/authentication.rb +- lib/clearance/extensions +- lib/clearance/extensions/errors.rb +- lib/clearance/extensions/rescue.rb +- lib/clearance/extensions/routes.rb +- lib/clearance/user.rb +- lib/clearance.rb +- shoulda_macros/clearance.rb +- rails/init.rb +has_rdoc: true +homepage: http://github.com/thoughtbot/clearance +licenses: [] + +post_install_message: +rdoc_options: [] + +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +required_rubygems_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +requirements: [] + +rubyforge_project: +rubygems_version: 1.3.4 +signing_key: +specification_version: 3 +summary: Rails authentication with email & password. +test_files: [] + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/CHANGELOG.textile b/vendor/gems/thoughtbot-clearance-0.7.0/CHANGELOG.textile new file mode 100644 index 0000000..c493128 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/CHANGELOG.textile @@ -0,0 +1,176 @@ +h2. 0.7.0 (08/04/2009) + +* Redirect signed in user who clicks confirmation link again. (Dan Croak) +* Redirect signed out user who clicks confirmation link again. (Dan Croak) +* Added signed_out? convenience method for controllers, helpers, views. (Dan +Croak) +* Added clearance_views generator. By default, creates formtastic views which +pass all tests and features. (Dan Croak) + +h2. 0.6.9 (07/04/2009) + +* Added timestamps to create users migration. (Dan Croak) +* Ready for Ruby 1.9. (Jason Morrison, Nick Quaranto) + +h2. 0.6.8 (06/24/2009) + +* Added defined? checks for various Rails constants such as ActionController +for easier unit testing of Clearance extensions... particularly ActiveRecord +extensions... particularly strong_password. (Dan Croak) + +h2. 0.6.7 (06/13/2009) + +* [#30] Added sign_up, sign_in, sign_out named routes. (Dan Croak) +* [#22] Minimizing Reek smell: Duplication in redirect_back_or. (Dan Croak) +* Deprecated sign_user_in. Told developers to use sign_in instead. (Dan +Croak) +* [#16] flash_success_after_create, flash_notice_after_create, flash_failure_after_create, flash_sucess_after_update, flash_success_after_destroy, etc. (Dan Croak) +* [#17] bug. added #create to forbidden before_filters on confirmations controller. (Dan Croak) +* [#24] should_be_signed_in_as shouldn't look in the session. (Dan Croak) +* README improvements. (Dan Croak) +* Move routes loading to separate file. (Joshua Clayton) + +h2. 0.6.6 (05/18/2009) + +* [#14] replaced class_eval in Clearance::User with modules. This was needed +in a thoughtbot client app so we could write our own validations. (Dan Croak) + +h2. 0.6.5 (05/17/2009) + +* [#6] Make Clearance i18n aware. (Timur Vafin, Marcel Goerner, Eugene Bolshakov, Dan Croak) + +h2. 0.6.4 (05/12/2009) + +* Moved issue tracking to Github from Lighthouse. (Dan Croak) +* [#7] asking higher-level questions of controllers in webrat steps, such as signed_in? instead of what's in the session. same for accessors. (Dan Croak) +* [#11] replacing sign_in_as & sign_out shoulda macros with a stubbing (requires no dependency) approach. this will avoid dealing with the internals of current_user, such as session & cookies. added sign_in macro which signs in an email confirmed user from clearance's factories. (Dan Croak) +* [#13] move private methods on sessions controller into Clearance::Authentication module (Dan Croak) +* [#9] audited flash keys. (Dan Croak) + +h2. 0.6.3 (04/23/2009) + +* Scoping ClearanceMailer properly within controllers so it works in production environments. (Nick Quaranto) + +h2. 0.6.2 (04/22/2009) + +* Insert Clearance::User into User model if it exists. (Nick Quaranto) +* World(NavigationHelpers) Cucumber 3.0 style. (Shay Arnett & Mark Cornick) + +h2. 0.6.1 (04/21/2009) +* Scope operators are necessary to keep Rails happy. Reverting the original +revert so they're back in the library now for constants referenced inside of +the gem. (Nick Quaranto) + +h2. 0.6.0 (04/21/2009) + +* Converted Clearance to a Rails engine. (Dan Croak & Joe Ferris) +* Include Clearance::User in User model in app. (Dan Croak & Joe Ferris) +* Include Clearance::Authentication in ApplicationController. (Dan Croak & Joe Ferris) +* Namespace controllers under Clearance. (Dan Croak & Joe Ferris) +* Routes move to engine, use namespaced controllers but publicly the same. (Dan Croak & Joe Ferris) +* If you want to override a controller, subclass it like SessionsController < +Clearance::SessionsController. This gives you access to usual hooks such as +url_after_create. (Dan Croak & Joe Ferris) +* Controllers, mailer, model, routes all unit tested inside engine. Use +script/generate clearance_features to test integration of Clearance with your +Rails app. No longer including modules in your app's test files. (Dan Croak & Joe Ferris) +* Moved views to engine. (Joe Ferris) +* Converted generated test/factories/clearance.rb to use inheritence for +email_confirmed_user. (Dan Croak) +* Corrected some spelling errors with methods (Nick Quaranto) +* Converted "I should see error messages" to use a regex in the features (Nick +Quaranto) +* Loading clearance routes after rails routes via some monkeypatching (Nick +Quaranto) +* Made the clearance controllers unloadable to stop constant loading errors in +development mode (Nick Quaranto) + +h2. 0.5.6 (4/11/2009) + +* [#57] Step definition changed for "User should see error messages" so +features won't fail for certain validations. (Nick Quaranto) + +h2. 0.5.5 (3/23/2009) + +* Removing duplicate test to get rid of warning. (Nick Quaranto) + +h2. 0.5.4 (3/21/2009) + +* When users fail logging in, redirect them instead of rendering. (Matt +Jankowski) + +h2. 0.5.3 (3/5/2009) + +* Clearance now works with (and requires) Shoulda 2.10.0. (Mark Cornick, Joe +Ferris, Dan Croak) +* Prefer flat over nested contexts in sessions_controller_test. (Joe Ferris, +Dan Croak) + +h2. 0.5.2 (3/2/2009) + +* Fixed last remaining errors in Rails 2.3 tests. Now fully compatible. (Joe +Ferris, Dan Croak) + +h2. 0.5.1 (2/27/2009) + +* [#46] A user with unconfirmed email who resets password now confirms email. +(Marcel Görner) +* Refactored user_from_cookie, user_from_session, User#authenticate to use +more direct return code instead of ugly, harder to read ternary. (Dan Croak) +* Switch order of cookies and sessions to take advantage of Rails 2.3's "Rack-based lazy-loaded sessions":http://is.gd/i23E. (Dan Croak) +* Altered generator to interact with application_controller.rb instead of +application.rb in Rails 2.3 apps. (Dan Croak) +* [#42] Bug fix. Rack-based session change altered how to test remember me +cookie. (Mihai Anca) + +h2. 0.5.0 (2/27/2009) + +* Fixed problem with Cucumber features. (Dan Croak) +* Fixed mising HTTP fluency use case. (Dan Croak) +* Refactored User#update_password to take just parameters it needs. (Dan +Croak) +* Refactored User unit tests to be more readable. (Dan Croak) + +h2. 0.4.9 (2/20/2009) + +* Protect passwords & confirmations actions with forbidden filters. (Dan Croak) +* Return 403 Forbidden status code in those cases. (Tim Pope) +* Test 403 Forbidden status code in Cucumber feature. (Dan Croak, Joe Ferris) +* Raise custom ActionController::Forbidden error internally. (Joe Ferris, Mike Burns, Jason Morrison) +* Test ActionController::Forbidden error is raised in functional test. (Joe Ferris, Mike Burns, Dan Croak) +* [#45] Fixed bug that allowed anyone to edit another user's password (Marcel Görner) +* Required Factory Girl >= 1.2.0. (Dan Croak) + +h2. 0.4.8 (2/16/2009) + +* Added support paths for Cucumber. (Ben Mabey) +* Added documentation for the flash. (Ben Mabey) +* Generators require "test_helper" instead of File.join. for rr compatibility. (Joe Ferris) +* Removed interpolated email address from flash message to make i18n easier. (Bence Nagy) +* Standardized flash messages that refer to email delivery. (Dan Croak) + +h2. 0.4.7 (2/12/2009) + +* Removed Clearance::Test::TestHelper so there is one less setup step. (Dan Croak) +* All test helpers now in shoulda_macros. (Dan Croak) + +h2. 0.4.6 (2/11/2009) + +* Made the modules behave like mixins again. (hat-tip Eloy Duran) +* Created Actions and PrivateMethods modules on controllers for future RDoc reasons. (Dan Croak, Joe Ferris) + +h2. 0.4.5 (2/9/2009) + +* [#43] Removed email downcasing because local-part is case sensitive per RFC5321. (Dan Croak) +* [#42] Removed dependency on Mocha. (Dan Croak) +* Required Shoulda >= 2.9.1. (Dan Croak) +* Added password reset feature to clearance_features generator. (Eugene Bolshakov, Dan Croak) +* Removed unnecessary session[:salt]. (Dan Croak) +* [#41] Only store location for session[:return_to] for GET requests. (Dan Croak) +* Audited "sign up" naming convention. "Register" had slipped in a few places. (Dan Croak) +* Switched to SHA1 encryption. Cypher doesn't matter much for email confirmation, password reset. Better to have shorter hashes in the emails for clients who line break on 72 chars. (Dan Croak) + +h2. 0.4.4 (2/2/2009) + +* Added a generator for Cucumber features. (Joe Ferris, Dan Croak) +* Standarized naming for "Sign up," "Sign in," and "Sign out". (Dan Croak) diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/LICENSE b/vendor/gems/thoughtbot-clearance-0.7.0/LICENSE new file mode 100644 index 0000000..5060183 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2008 thoughtbot, inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/README.textile b/vendor/gems/thoughtbot-clearance-0.7.0/README.textile new file mode 100644 index 0000000..3aa3687 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/README.textile @@ -0,0 +1,123 @@ +h1. Clearance + +Rails authentication with email & password. + +"We have clearance, Clarence.":http://www.youtube.com/v/mNRXJEE3Nz8 + +h2. Wiki + +Most information regarding Clearance is on the "Github Wiki":http://wiki.github.com/thoughtbot/clearance. + +h2. Installation + +Clearance is a Rails engine. It works with versions of Rails greater than 2.3. + +In config/environment.rb: + +
+config.gem "thoughtbot-clearance", 
+  :lib     => 'clearance', 
+  :source  => 'http://gems.github.com', 
+  :version => '0.6.9'
+
+ +Vendor the gem: + +
+rake gems:install
+rake gems:unpack
+
+ +Make sure the development database exists and run the generator: + +@script/generate clearance@ + +A number of files will be created and instructions will be printed. + +You may already have some of these files. Don't worry. You'll be asked if you want to overwrite them. + +Run the migration: + +@rake db:migrate@ + +Define a HOST constant in your environment files. +In config/environments/test.rb and config/environments/development.rb it can be: + +@HOST = "localhost"@ + +In production.rb it must be the actual host your application is deployed to. +The constant is used by mailers to generate URLs in emails. + +In config/environment.rb: + +@DO_NOT_REPLY = "donotreply@example.com"@ + +Define root_url to *something* in your config/routes.rb: + +@map.root :controller => 'home'@ + +h2. Cucumber Features + +As your app evolves, you want to know that authentication still works. Clearance's opinion is that you should test its integration with your app using "Cucumber":http://cukes.info/. + +In config/environments/test.rb: + +
+config.gem 'webrat',
+  :version => '= 0.4.4'
+config.gem 'cucumber',
+  :version => '= 0.3.0'
+config.gem 'thoughtbot-factory_girl',
+  :lib     => 'factory_girl',
+  :source  => "http://gems.github.com", 
+  :version => '1.2.1'
+
+ +Vendor the gems: + +
+rake gems:install RAILS_ENV=test
+rake gems:unpack  RAILS_ENV=test
+
+ +We don't vendor nokogiri due to its native extensions, so install it normally on your machine: + +@sudo gem install nokogiri@ + +Run the Cucumber generator (if you haven't already) and Clearance's feature generator: + +
+script/generate cucumber
+script/generate clearance_features
+
+ +All of the files generated should be new with the exception of the features/support/paths.rb file. If you have not modified your paths.rb then you will be okay to replace it with this one. If you need to keep your paths.rb file then add these locations in your paths.rb manually: + +
+def path_to(page_name)
+  case page_name
+   ...
+  when /the sign up page/i
+   new_user_path
+  when /the sign in page/i
+   new_session_path
+  when /the password reset request page/i
+   new_password_path
+  ...
+end
+
+ +h2. Authors + +Clearance was extracted out of "Hoptoad":http://hoptoadapp.com. We merged the authentication code from two of thoughtbot's clients' Rails apps and have since used it each time we need authentication. The following people have improved the library. Thank you! + +Dan Croak, Mike Burns, Jason Morrison, Joe Ferris, Eugene Bolshakov, Nick Quaranto, Josh Nichols, Mike Breen, Marcel Görner, Bence Nagy, Ben Mabey, Eloy Duran, Tim Pope, Mihai Anca, Mark Cornick, Shay Arnett, Joshua Clayton & Mustafa Ekim. + +h2. Questions? + +Ask the "mailing list":http://groups.google.com/group/thoughtbot-clearance + +h2. Suggestions, Bugs, Refactoring? + +Fork away and create a "Github Issue":http://github.com/thoughtbot/clearance/issues. Please don't send pull requests. + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/Rakefile b/vendor/gems/thoughtbot-clearance-0.7.0/Rakefile new file mode 100644 index 0000000..cacfe35 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/Rakefile @@ -0,0 +1,103 @@ +# encoding: utf-8 + +require 'rake' +require 'rake/testtask' +require 'cucumber/rake/task' + +namespace :test do + Rake::TestTask.new(:basic => ["generator:cleanup", + "generator:clearance", + "generator:clearance_features"]) do |task| + task.libs << "lib" + task.libs << "test" + task.pattern = "test/**/*_test.rb" + task.verbose = false + end + + Rake::TestTask.new(:views => ["generator:clearance_views"]) do |task| + task.libs << "lib" + task.libs << "test" + task.pattern = "test/**/*_test.rb" + task.verbose = false + end + + Cucumber::Rake::Task.new(:features) do |t| + t.cucumber_opts = "--format progress" + t.feature_pattern = "test/rails_root/features/*.feature" + end + + Cucumber::Rake::Task.new(:features_for_views) do |t| + t.cucumber_opts = "--format progress" + t.feature_pattern = "test/rails_root/features/*.feature" + end +end + +generators = %w(clearance clearance_features clearance_views) + +namespace :generator do + desc "Cleans up the test app before running the generator" + task :cleanup do + generators.each do |generator| + FileList["generators/#{generator}/templates/**/*.*"].each do |each| + file = "test/rails_root/#{each.gsub("generators/#{generator}/templates/",'')}" + File.delete(file) if File.exists?(file) + end + end + + FileList["test/rails_root/db/**/*"].each do |each| + FileUtils.rm_rf(each) + end + + FileUtils.rm_rf("test/rails_root/vendor/plugins/clearance") + FileUtils.mkdir_p("test/rails_root/vendor/plugins") + clearance_root = File.expand_path(File.dirname(__FILE__)) + system("ln -s #{clearance_root} test/rails_root/vendor/plugins/clearance") + + FileUtils.rm_rf("test/rails_root/app/views/passwords") + FileUtils.rm_rf("test/rails_root/app/views/sessions") + FileUtils.rm_rf("test/rails_root/app/views/users") + end + + desc "Run the clearance generator" + task :clearance do + system "cd test/rails_root && ./script/generate clearance && rake db:migrate db:test:prepare" + end + + desc "Run the clearance features generator" + task :clearance_features do + system "cd test/rails_root && ./script/generate clearance_features" + end + + desc "Run the clearance views generator" + task :clearance_views do + system "cd test/rails_root && ./script/generate clearance_views" + end +end + +desc "Run the test suite" +task :default => ['test:basic', 'test:features', + 'test:views', 'test:features_for_views'] + +gem_spec = Gem::Specification.new do |gem_spec| + gem_spec.name = "clearance" + gem_spec.version = "0.7.0" + gem_spec.summary = "Rails authentication with email & password." + gem_spec.email = "support@thoughtbot.com" + gem_spec.homepage = "http://github.com/thoughtbot/clearance" + gem_spec.description = "Rails authentication with email & password." + gem_spec.authors = ["Dan Croak", "Mike Burns", "Jason Morrison", + "Joe Ferris", "Eugene Bolshakov", "Nick Quaranto", + "Josh Nichols", "Mike Breen", "Marcel Görner", + "Bence Nagy", "Ben Mabey", "Eloy Duran", + "Tim Pope", "Mihai Anca", "Mark Cornick", + "Shay Arnett"] + gem_spec.files = FileList["[A-Z]*", "{app,config,generators,lib,shoulda_macros,rails}/**/*"] +end + +desc "Generate a gemspec file" +task :gemspec do + File.open("#{gem_spec.name}.gemspec", 'w') do |f| + f.write gem_spec.to_yaml + end +end + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/TODO.textile b/vendor/gems/thoughtbot-clearance-0.7.0/TODO.textile new file mode 100644 index 0000000..9805aed --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/TODO.textile @@ -0,0 +1,6 @@ +h1. To-do + +* Make insertion of Clearance::User into User model automatic from the generator. +* Change generated README to include instruction about running the migration. +* DO_NOT_REPLY, HOST refactoring. + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/confirmations_controller.rb b/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/confirmations_controller.rb new file mode 100644 index 0000000..983e506 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/confirmations_controller.rb @@ -0,0 +1,73 @@ +class Clearance::ConfirmationsController < ApplicationController + unloadable + + before_filter :redirect_signed_in_confirmed_user, :only => [:new, :create] + before_filter :redirect_signed_out_confirmed_user, :only => [:new, :create] + before_filter :forbid_missing_token, :only => [:new, :create] + before_filter :forbid_non_existent_user, :only => [:new, :create] + + filter_parameter_logging :token + + def new + create + end + + def create + @user = ::User.find_by_id_and_token(params[:user_id], params[:token]) + @user.confirm_email! + + sign_in(@user) + flash_success_after_create + redirect_to(url_after_create) + end + + private + + def redirect_signed_in_confirmed_user + user = ::User.find_by_id(params[:user_id]) + if user && user.email_confirmed? && current_user == user + flash_success_after_create + redirect_to(url_after_create) + end + end + + def redirect_signed_out_confirmed_user + user = ::User.find_by_id(params[:user_id]) + if user && user.email_confirmed? && signed_out? + flash_already_confirmed + redirect_to(url_already_confirmed) + end + end + + def forbid_missing_token + if params[:token].blank? + raise ActionController::Forbidden, "missing token" + end + end + + def forbid_non_existent_user + unless ::User.find_by_id_and_token(params[:user_id], params[:token]) + raise ActionController::Forbidden, "non-existent user" + end + end + + def flash_success_after_create + flash[:success] = translate(:confirmed_email, + :scope => [:clearance, :controllers, :confirmations], + :default => "Confirmed email and signed in.") + end + + def flash_already_confirmed + flash[:success] = translate(:already_confirmed_email, + :scope => [:clearance, :controllers, :confirmations], + :default => "Already confirmed email. Please sign in.") + end + + def url_after_create + root_url + end + + def url_already_confirmed + sign_in_url + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/passwords_controller.rb b/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/passwords_controller.rb new file mode 100644 index 0000000..6221ad3 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/passwords_controller.rb @@ -0,0 +1,81 @@ +class Clearance::PasswordsController < ApplicationController + unloadable + + before_filter :forbid_missing_token, :only => [:edit, :update] + before_filter :forbid_non_existent_user, :only => [:edit, :update] + filter_parameter_logging :password, :password_confirmation + + def new + render :template => 'passwords/new' + end + + def create + if user = ::User.find_by_email(params[:password][:email]) + user.forgot_password! + ::ClearanceMailer.deliver_change_password user + flash_notice_after_create + redirect_to(url_after_create) + else + flash_failure_after_create + render :template => 'passwords/new' + end + end + + def edit + @user = ::User.find_by_id_and_token(params[:user_id], params[:token]) + render :template => 'passwords/edit' + end + + def update + @user = ::User.find_by_id_and_token(params[:user_id], params[:token]) + + if @user.update_password(params[:user][:password], + params[:user][:password_confirmation]) + @user.confirm_email! + sign_in(@user) + flash_success_after_update + redirect_to(url_after_update) + else + render :template => 'passwords/edit' + end + end + + private + + def forbid_missing_token + if params[:token].blank? + raise ActionController::Forbidden, "missing token" + end + end + + def forbid_non_existent_user + unless ::User.find_by_id_and_token(params[:user_id], params[:token]) + raise ActionController::Forbidden, "non-existent user" + end + end + + def flash_notice_after_create + flash[:notice] = translate(:deliver_change_password, + :scope => [:clearance, :controllers, :passwords], + :default => "You will receive an email within the next few minutes. " << + "It contains instructions for changing your password.") + end + + def flash_failure_after_create + flash.now[:failure] = translate(:unknown_email, + :scope => [:clearance, :controllers, :passwords], + :default => "Unknown email.") + end + + def url_after_create + new_session_url + end + + def flash_success_after_update + flash[:success] = translate(:signed_in, :default => "Signed in.") + end + + def url_after_update + root_url + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/sessions_controller.rb b/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/sessions_controller.rb new file mode 100644 index 0000000..2ea0440 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/sessions_controller.rb @@ -0,0 +1,67 @@ +class Clearance::SessionsController < ApplicationController + unloadable + + protect_from_forgery :except => :create + filter_parameter_logging :password + + def new + render :template => 'sessions/new' + end + + def create + @user = ::User.authenticate(params[:session][:email], + params[:session][:password]) + if @user.nil? + flash_failure_after_create + render :template => 'sessions/new', :status => :unauthorized + else + if @user.email_confirmed? + sign_in(@user) + remember(@user) if remember? + flash_success_after_create + redirect_back_or(url_after_create) + else + ::ClearanceMailer.deliver_confirmation(@user) + flash_notice_after_create + redirect_to(new_session_url) + end + end + end + + def destroy + forget(current_user) + flash_success_after_destroy + redirect_to(url_after_destroy) + end + + private + + def flash_failure_after_create + flash.now[:failure] = translate(:bad_email_or_password, + :scope => [:clearance, :controllers, :sessions], + :default => "Bad email or password.") + end + + def flash_success_after_create + flash[:success] = translate(:signed_in, :default => "Signed in.") + end + + def flash_notice_after_create + flash[:notice] = translate(:unconfirmed_email, + :scope => [:clearance, :controllers, :sessions], + :default => "User has not confirmed email. " << + "Confirmation email will be resent.") + end + + def url_after_create + root_url + end + + def flash_success_after_destroy + flash[:success] = translate(:signed_out, :default => "Signed out.") + end + + def url_after_destroy + new_session_url + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/users_controller.rb b/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/users_controller.rb new file mode 100644 index 0000000..6b8659e --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/controllers/clearance/users_controller.rb @@ -0,0 +1,35 @@ +class Clearance::UsersController < ApplicationController + unloadable + + before_filter :redirect_to_root, :only => [:new, :create], :if => :signed_in? + filter_parameter_logging :password + + def new + @user = ::User.new(params[:user]) + render :template => 'users/new' + end + + def create + @user = ::User.new params[:user] + if @user.save + ::ClearanceMailer.deliver_confirmation @user + flash_notice_after_create + redirect_to(url_after_create) + else + render :template => 'users/new' + end + end + + private + + def flash_notice_after_create + flash[:notice] = translate(:deliver_confirmation, + :scope => [:clearance, :controllers, :users], + :default => "You will receive an email within the next few minutes. " << + "It contains instructions for confirming your account.") + end + + def url_after_create + new_session_url + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/models/clearance_mailer.rb b/vendor/gems/thoughtbot-clearance-0.7.0/app/models/clearance_mailer.rb new file mode 100644 index 0000000..90f5f16 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/models/clearance_mailer.rb @@ -0,0 +1,23 @@ +class ClearanceMailer < ActionMailer::Base + + default_url_options[:host] = HOST + + def change_password(user) + from DO_NOT_REPLY + recipients user.email + subject I18n.t(:change_password, + :scope => [:clearance, :models, :clearance_mailer], + :default => "Change your password") + body :user => user + end + + def confirmation(user) + from DO_NOT_REPLY + recipients user.email + subject I18n.t(:confirmation, + :scope => [:clearance, :models, :clearance_mailer], + :default => "Account confirmation") + body :user => user + end + +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/views/clearance_mailer/change_password.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/clearance_mailer/change_password.html.erb new file mode 100644 index 0000000..246324d --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/clearance_mailer/change_password.html.erb @@ -0,0 +1,7 @@ +Someone, hopefully you, has requested that we send you a link to change your password. + +Here's the link: + +<%= edit_user_password_url(@user, :token => @user.token, :escape => false) %> + +If you didn't request this, ignore this email. Don't worry. Your password hasn't been changed. diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/views/clearance_mailer/confirmation.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/clearance_mailer/confirmation.html.erb new file mode 100644 index 0000000..83d3de4 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/clearance_mailer/confirmation.html.erb @@ -0,0 +1,2 @@ + +<%= new_user_confirmation_url :user_id => @user, :token => @user.token, :encode => false %> diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/views/passwords/edit.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/passwords/edit.html.erb new file mode 100644 index 0000000..c8637f5 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/passwords/edit.html.erb @@ -0,0 +1,23 @@ +

Change your password

+ +

+ Your password has been reset. Choose a new password below. +

+ +<%= error_messages_for :user %> + +<% form_for(:user, + :url => user_password_path(@user, :token => @user.token), + :html => { :method => :put }) do |form| %> +
+ <%= form.label :password, "Choose password" %> + <%= form.password_field :password %> +
+
+ <%= form.label :password_confirmation, "Confirm password" %> + <%= form.password_field :password_confirmation %> +
+
+ <%= form.submit "Save this password", :disable_with => "Please wait..." %> +
+<% end %> diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/views/passwords/new.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/passwords/new.html.erb new file mode 100644 index 0000000..bd37d6d --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/passwords/new.html.erb @@ -0,0 +1,15 @@ +

Change your password

+ +

+ We will email you a link to change your password. +

+ +<% form_for :password, :url => passwords_path do |form| %> +
+ <%= form.label :email, "Email address" %> + <%= form.text_field :email %> +
+
+ <%= form.submit "Reset password", :disable_with => "Please wait..." %> +
+<% end %> \ No newline at end of file diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/views/sessions/new.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/sessions/new.html.erb new file mode 100644 index 0000000..a1e5607 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/sessions/new.html.erb @@ -0,0 +1,28 @@ +

Sign in

+ +<% form_for :session, :url => session_path do |form| %> +
+ <%= form.label :email %> + <%= form.text_field :email %> +
+
+ <%= form.label :password %> + <%= form.password_field :password %> +
+
+ <%= form.check_box :remember_me %> + <%= form.label :remember_me %> +
+
+ <%= form.submit "Sign in", :disable_with => "Please wait..." %> +
+<% end %> + + \ No newline at end of file diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/views/users/_form.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/users/_form.html.erb new file mode 100644 index 0000000..6a9b8e0 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/users/_form.html.erb @@ -0,0 +1,13 @@ +<%= form.error_messages %> +
+ <%= form.label :email %> + <%= form.text_field :email %> +
+
+ <%= form.label :password %> + <%= form.password_field :password %> +
+
+ <%= form.label :password_confirmation, "Confirm password" %> + <%= form.password_field :password_confirmation %> +
\ No newline at end of file diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/app/views/users/new.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/users/new.html.erb new file mode 100644 index 0000000..de2ebf7 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/app/views/users/new.html.erb @@ -0,0 +1,6 @@ +

Sign up

+ +<% form_for @user do |form| %> + <%= render :partial => '/users/form', :object => form %> + <%= form.submit 'Sign up', :disable_with => 'Please wait...' %> +<% end %> diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/config/clearance_routes.rb b/vendor/gems/thoughtbot-clearance-0.7.0/config/clearance_routes.rb new file mode 100644 index 0000000..caeb5cc --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/config/clearance_routes.rb @@ -0,0 +1,30 @@ +ActionController::Routing::Routes.draw do |map| + map.resources :passwords, + :controller => 'clearance/passwords', + :only => [:new, :create] + + map.resource :session, + :controller => 'clearance/sessions', + :only => [:new, :create, :destroy] + + map.resources :users, :controller => 'clearance/users' do |users| + users.resource :password, + :controller => 'clearance/passwords', + :only => [:create, :edit, :update] + + users.resource :confirmation, + :controller => 'clearance/confirmations', + :only => [:new, :create] + end + + map.sign_up 'sign_up', + :controller => 'clearance/users', + :action => 'new' + map.sign_in 'sign_in', + :controller => 'clearance/sessions', + :action => 'new' + map.sign_out 'sign_out', + :controller => 'clearance/sessions', + :action => 'destroy', + :method => :delete +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/USAGE b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/USAGE new file mode 100644 index 0000000..3d9cabe --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/USAGE @@ -0,0 +1 @@ +script/generate clearance \ No newline at end of file diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/clearance_generator.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/clearance_generator.rb new file mode 100644 index 0000000..d3704b7 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/clearance_generator.rb @@ -0,0 +1,41 @@ +require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb") +require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb") +require 'factory_girl' + +class ClearanceGenerator < Rails::Generator::Base + + def manifest + record do |m| + m.insert_into "app/controllers/application_controller.rb", + "include Clearance::Authentication" + + user_model = "app/models/user.rb" + if File.exists?(user_model) + m.insert_into user_model, "include Clearance::User" + else + m.directory File.join("app", "models") + m.file "user.rb", user_model + end + + m.directory File.join("test", "factories") + m.file "factories.rb", "test/factories/clearance.rb" + + m.migration_template "migrations/#{migration_name}.rb", + 'db/migrate', + :migration_file_name => "clearance_#{migration_name}" + + m.readme "README" + end + end + + private + + def migration_name + if ActiveRecord::Base.connection.table_exists?(:users) + 'update_users' + else + 'create_users' + end + end + +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/lib/insert_commands.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/lib/insert_commands.rb new file mode 100644 index 0000000..cc76c56 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/lib/insert_commands.rb @@ -0,0 +1,33 @@ +# Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master + +Rails::Generator::Commands::Base.class_eval do + def file_contains?(relative_destination, line) + File.read(destination_path(relative_destination)).include?(line) + end +end + +Rails::Generator::Commands::Create.class_eval do + def insert_into(file, line) + logger.insert "#{line} into #{file}" + unless options[:pretend] || file_contains?(file, line) + gsub_file file, /^(class|module) .+$/ do |match| + "#{match}\n #{line}" + end + end + end +end + +Rails::Generator::Commands::Destroy.class_eval do + def insert_into(file, line) + logger.remove "#{line} from #{file}" + unless options[:pretend] + gsub_file file, "\n #{line}", '' + end + end +end + +Rails::Generator::Commands::List.class_eval do + def insert_into(file, line) + logger.insert "#{line} into #{file}" + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/lib/rake_commands.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/lib/rake_commands.rb new file mode 100644 index 0000000..a9fd417 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/lib/rake_commands.rb @@ -0,0 +1,22 @@ +Rails::Generator::Commands::Create.class_eval do + def rake_db_migrate + logger.rake "db:migrate" + unless system("rake db:migrate") + logger.rake "db:migrate failed. Rolling back" + command(:destroy).invoke! + end + end +end + +Rails::Generator::Commands::Destroy.class_eval do + def rake_db_migrate + logger.rake "db:rollback" + system "rake db:rollback" + end +end + +Rails::Generator::Commands::List.class_eval do + def rake_db_migrate + logger.rake "db:migrate" + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/README b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/README new file mode 100644 index 0000000..17850c8 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/README @@ -0,0 +1,22 @@ + +******************************************************************************* + +Ok, enough fancy automatic stuff. Time for some old school monkey copy-pasting. + +1. Define a HOST constant in your environments files. +In config/environments/test.rb and config/environments/development.rb it can be: + + HOST = "localhost" + +In production.rb it must be the actual host your application is deployed to. +The constant is used by mailers to generate URLs in emails. + +2. In config/environment.rb: + + DO_NOT_REPLY = "donotreply@example.com" + +3. Define root_url to *something* in your config/routes.rb: + + map.root :controller => 'home' + +******************************************************************************* diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/factories.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/factories.rb new file mode 100644 index 0000000..9bdd13a --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/factories.rb @@ -0,0 +1,13 @@ +Factory.sequence :email do |n| + "user#{n}@example.com" +end + +Factory.define :user do |user| + user.email { Factory.next :email } + user.password { "password" } + user.password_confirmation { "password" } +end + +Factory.define :email_confirmed_user, :parent => :user do |user| + user.email_confirmed { true } +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/migrations/create_users.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/migrations/create_users.rb new file mode 100644 index 0000000..22e921a --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/migrations/create_users.rb @@ -0,0 +1,21 @@ +class ClearanceCreateUsers < ActiveRecord::Migration + def self.up + create_table(:users) do |t| + t.string :email + t.string :encrypted_password, :limit => 128 + t.string :salt, :limit => 128 + t.string :token, :limit => 128 + t.datetime :token_expires_at + t.boolean :email_confirmed, :default => false, :null => false + t.timestamps + end + + add_index :users, [:id, :token] + add_index :users, :email + add_index :users, :token + end + + def self.down + drop_table :users + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/migrations/update_users.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/migrations/update_users.rb new file mode 100644 index 0000000..4a329fa --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/migrations/update_users.rb @@ -0,0 +1,41 @@ +class ClearanceUpdateUsers < ActiveRecord::Migration + def self.up +<% + existing_columns = ActiveRecord::Base.connection.columns(:users).collect { |each| each.name } + columns = [ + [:email, 't.string :email'], + [:encrypted_password, 't.string :encrypted_password, :limit => 128'], + [:salt, 't.string :salt, :limit => 128'], + [:token, 't.string :token, :limit => 128'], + [:token_expires_at, 't.datetime :token_expires_at'], + [:email_confirmed, 't.boolean :email_confirmed, :default => false, :null => false'] + ].delete_if {|c| existing_columns.include?(c.first.to_s)} +-%> + change_table(:users) do |t| +<% columns.each do |c| -%> + <%= c.last %> +<% end -%> + end + +<% + existing_indexes = ActiveRecord::Base.connection.indexes(:users) + index_names = existing_indexes.collect { |each| each.name } + new_indexes = [ + [:index_users_on_id_and_token, 'add_index :users, [:id, :token]'], + [:index_users_on_email, 'add_index :users, :email'], + [:index_users_on_token, 'add_index :users, :token'] + ].delete_if { |each| index_names.include?(each.first.to_s) } +-%> +<% new_indexes.each do |each| -%> + <%= each.last %> +<% end -%> + end + + def self.down + change_table(:users) do |t| +<% unless columns.empty? -%> + t.remove <%= columns.collect { |each| ":#{each.first}" }.join(',') %> +<% end -%> + end + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/user.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/user.rb new file mode 100644 index 0000000..6d077a1 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance/templates/user.rb @@ -0,0 +1,3 @@ +class User < ActiveRecord::Base + include Clearance::User +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/USAGE b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/USAGE new file mode 100644 index 0000000..3758c0b --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/USAGE @@ -0,0 +1 @@ +script/generate clearance_features diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/clearance_features_generator.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/clearance_features_generator.rb new file mode 100644 index 0000000..477afd8 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/clearance_features_generator.rb @@ -0,0 +1,20 @@ +class ClearanceFeaturesGenerator < Rails::Generator::Base + + def manifest + record do |m| + m.directory File.join("features", "step_definitions") + m.directory File.join("features", "support") + + ["features/step_definitions/clearance_steps.rb", + "features/step_definitions/factory_girl_steps.rb", + "features/support/paths.rb", + "features/sign_in.feature", + "features/sign_out.feature", + "features/sign_up.feature", + "features/password_reset.feature"].each do |file| + m.file file, file + end + end + end + +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/password_reset.feature b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/password_reset.feature new file mode 100644 index 0000000..51b77f7 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/password_reset.feature @@ -0,0 +1,33 @@ +Feature: Password reset + In order to sign in even if user forgot their password + A user + Should be able to reset it + + Scenario: User is not signed up + Given no user exists with an email of "email@person.com" + When I request password reset link to be sent to "email@person.com" + Then I should see "Unknown email" + + Scenario: User is signed up and requests password reset + Given I signed up with "email@person.com/password" + When I request password reset link to be sent to "email@person.com" + Then I should see "instructions for changing your password" + And a password reset message should be sent to "email@person.com" + + Scenario: User is signed up updated his password and types wrong confirmation + Given I signed up with "email@person.com/password" + When I follow the password reset link sent to "email@person.com" + And I update my password with "newpassword/wrongconfirmation" + Then I should see error messages + And I should be signed out + + Scenario: User is signed up and updates his password + Given I signed up with "email@person.com/password" + When I follow the password reset link sent to "email@person.com" + And I update my password with "newpassword/newpassword" + Then I should be signed in + When I sign out + Then I should be signed out + And I sign in as "email@person.com/newpassword" + Then I should be signed in + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_in.feature b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_in.feature new file mode 100644 index 0000000..4b44c39 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_in.feature @@ -0,0 +1,42 @@ +Feature: Sign in + In order to get access to protected sections of the site + A user + Should be able to sign in + + Scenario: User is not signed up + Given no user exists with an email of "email@person.com" + When I go to the sign in page + And I sign in as "email@person.com/password" + Then I should see "Bad email or password" + And I should be signed out + + Scenario: User is not confirmed + Given I signed up with "email@person.com/password" + When I go to the sign in page + And I sign in as "email@person.com/password" + Then I should see "User has not confirmed email" + And I should be signed out + + Scenario: User enters wrong password + Given I am signed up and confirmed as "email@person.com/password" + When I go to the sign in page + And I sign in as "email@person.com/wrongpassword" + Then I should see "Bad email or password" + And I should be signed out + + Scenario: User signs in successfully + Given I am signed up and confirmed as "email@person.com/password" + When I go to the sign in page + And I sign in as "email@person.com/password" + Then I should see "Signed in" + And I should be signed in + + Scenario: User signs in and checks "remember me" + Given I am signed up and confirmed as "email@person.com/password" + When I go to the sign in page + And I sign in with "remember me" as "email@person.com/password" + Then I should see "Signed in" + And I should be signed in + When I return next time + Then I should be signed in + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_out.feature b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_out.feature new file mode 100644 index 0000000..2107226 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_out.feature @@ -0,0 +1,23 @@ +Feature: Sign out + To protect my account from unauthorized access + A signed in user + Should be able to sign out + + Scenario: User signs out + Given I am signed up and confirmed as "email@person.com/password" + When I sign in as "email@person.com/password" + Then I should be signed in + And I sign out + Then I should see "Signed out" + And I should be signed out + + Scenario: User who was remembered signs out + Given I am signed up and confirmed as "email@person.com/password" + When I sign in with "remember me" as "email@person.com/password" + Then I should be signed in + And I sign out + Then I should see "Signed out" + And I should be signed out + When I return next time + Then I should be signed out + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_up.feature b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_up.feature new file mode 100644 index 0000000..4bb565d --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/sign_up.feature @@ -0,0 +1,45 @@ +Feature: Sign up + In order to get access to protected sections of the site + A user + Should be able to sign up + + Scenario: User signs up with invalid data + When I go to the sign up page + And I fill in "Email" with "invalidemail" + And I fill in "Password" with "password" + And I fill in "Confirm password" with "" + And I press "Sign Up" + Then I should see error messages + + Scenario: User signs up with valid data + When I go to the sign up page + And I fill in "Email" with "email@person.com" + And I fill in "Password" with "password" + And I fill in "Confirm password" with "password" + And I press "Sign Up" + Then I should see "instructions for confirming" + And a confirmation message should be sent to "email@person.com" + + Scenario: User confirms his account + Given I signed up with "email@person.com/password" + When I follow the confirmation link sent to "email@person.com" + Then I should see "Confirmed email and signed in" + And I should be signed in + + Scenario: Signed in user clicks confirmation link again + Given I signed up with "email@person.com/password" + When I follow the confirmation link sent to "email@person.com" + Then I should be signed in + When I follow the confirmation link sent to "email@person.com" + Then I should see "Confirmed email and signed in" + And I should be signed in + + Scenario: Signed out user clicks confirmation link again + Given I signed up with "email@person.com/password" + When I follow the confirmation link sent to "email@person.com" + Then I should be signed in + When I sign out + And I follow the confirmation link sent to "email@person.com" + Then I should see "Already confirmed email. Please sign in." + And I should be signed out + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb new file mode 100644 index 0000000..52ac7f4 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb @@ -0,0 +1,110 @@ +# General + +Then /^I should see error messages$/ do + assert_match /error(s)? prohibited/m, response.body +end + +# Database + +Given /^no user exists with an email of "(.*)"$/ do |email| + assert_nil User.find_by_email(email) +end + +Given /^I signed up with "(.*)\/(.*)"$/ do |email, password| + user = Factory :user, + :email => email, + :password => password, + :password_confirmation => password +end + +Given /^I am signed up and confirmed as "(.*)\/(.*)"$/ do |email, password| + user = Factory :email_confirmed_user, + :email => email, + :password => password, + :password_confirmation => password +end + +# Session + +Then /^I should be signed in$/ do + assert controller.signed_in? +end + +Then /^I should be signed out$/ do + assert ! controller.signed_in? +end + +When /^session is cleared$/ do + request.reset_session + controller.instance_variable_set(:@_current_user, nil) +end + +# Emails + +Then /^a confirmation message should be sent to "(.*)"$/ do |email| + user = User.find_by_email(email) + sent = ActionMailer::Base.deliveries.first + assert_equal [user.email], sent.to + assert_match /confirm/i, sent.subject + assert !user.token.blank? + assert_match /#{user.token}/, sent.body +end + +When /^I follow the confirmation link sent to "(.*)"$/ do |email| + user = User.find_by_email(email) + visit new_user_confirmation_path(:user_id => user, :token => user.token) +end + +Then /^a password reset message should be sent to "(.*)"$/ do |email| + user = User.find_by_email(email) + sent = ActionMailer::Base.deliveries.first + assert_equal [user.email], sent.to + assert_match /password/i, sent.subject + assert !user.token.blank? + assert_match /#{user.token}/, sent.body +end + +When /^I follow the password reset link sent to "(.*)"$/ do |email| + user = User.find_by_email(email) + visit edit_user_password_path(:user_id => user, :token => user.token) +end + +When /^I try to change the password of "(.*)" without token$/ do |email| + user = User.find_by_email(email) + visit edit_user_password_path(:user_id => user) +end + +Then /^I should be forbidden$/ do + assert_response :forbidden +end + +# Actions + +When /^I sign in( with "remember me")? as "(.*)\/(.*)"$/ do |remember, email, password| + When %{I go to the sign in page} + And %{I fill in "Email" with "#{email}"} + And %{I fill in "Password" with "#{password}"} + And %{I check "Remember me"} if remember + And %{I press "Sign In"} +end + +When /^I sign out$/ do + visit '/session', :delete +end + +When /^I request password reset link to be sent to "(.*)"$/ do |email| + When %{I go to the password reset request page} + And %{I fill in "Email address" with "#{email}"} + And %{I press "Reset password"} +end + +When /^I update my password with "(.*)\/(.*)"$/ do |password, confirmation| + And %{I fill in "Choose password" with "#{password}"} + And %{I fill in "Confirm password" with "#{confirmation}"} + And %{I press "Save this password"} +end + +When /^I return next time$/ do + When %{session is cleared} + And %{I go to the homepage} +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb new file mode 100644 index 0000000..6337f66 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb @@ -0,0 +1,5 @@ +Factory.factories.each do |name, factory| + Given /^an? #{name} exists with an? (.*) of "([^"]*)"$/ do |attr, value| + Factory(name, attr.gsub(' ', '_') => value) + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/support/paths.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/support/paths.rb new file mode 100644 index 0000000..62ba3d5 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_features/templates/features/support/paths.rb @@ -0,0 +1,22 @@ +module NavigationHelpers + def path_to(page_name) + case page_name + + when /the homepage/i + root_path + when /the sign up page/i + new_user_path + when /the sign in page/i + new_session_path + when /the password reset request page/i + new_password_path + + # Add more page name => path mappings here + + else + raise "Can't find mapping from \"#{page_name}\" to a path." + end + end +end + +World(NavigationHelpers) diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/USAGE b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/USAGE new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/USAGE diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/clearance_views_generator.rb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/clearance_views_generator.rb new file mode 100644 index 0000000..6075ed8 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/clearance_views_generator.rb @@ -0,0 +1,27 @@ +class ClearanceViewsGenerator < Rails::Generator::Base + + def manifest + record do |m| + strategy = "formtastic" + template_strategy = "erb" + + m.directory File.join("app", "views", "users") + m.file "#{strategy}/users/new.html.#{template_strategy}", + "app/views/users/new.html.#{template_strategy}" + m.file "#{strategy}/users/_inputs.html.#{template_strategy}", + "app/views/users/_inputs.html.#{template_strategy}" + + m.directory File.join("app", "views", "sessions") + m.file "#{strategy}/sessions/new.html.#{template_strategy}", + "app/views/sessions/new.html.#{template_strategy}" + + m.directory File.join("app", "views", "passwords") + m.file "#{strategy}/passwords/new.html.#{template_strategy}", + "app/views/passwords/new.html.#{template_strategy}" + m.file "#{strategy}/passwords/edit.html.#{template_strategy}", + "app/views/passwords/edit.html.#{template_strategy}" + end + end + +end + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/passwords/edit.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/passwords/edit.html.erb new file mode 100644 index 0000000..9cb7112 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/passwords/edit.html.erb @@ -0,0 +1,21 @@ +

Change your password

+ +

+ Your password has been reset. Choose a new password below. +

+ +<% semantic_form_for(:user, + :url => user_password_path(@user, :token => @user.token), + :html => { :method => :put }) do |form| %> + <%= form.error_messages %> + <% form.inputs do -%> + <%= form.input :password, :as => :password, + :label => "Choose password" %> + <%= form.input :password_confirmation, :as => :password, + :label => "Confirm password" %> + <% end -%> + <% form.buttons do -%> + <%= form.commit_button "Save this password" %> + <% end -%> +<% end %> + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/passwords/new.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/passwords/new.html.erb new file mode 100644 index 0000000..4ac1269 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/passwords/new.html.erb @@ -0,0 +1,15 @@ +

Reset your password

+ +

+ We will email you a link to reset your password. +

+ +<% semantic_form_for :password, :url => passwords_path do |form| -%> + <% form.inputs do -%> + <%= form.input :email, :label => "Email address" %> + <% end -%> + <% form.buttons do -%> + <%= form.commit_button "Reset password" %> + <% end -%> +<% end -%> + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/sessions/new.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/sessions/new.html.erb new file mode 100644 index 0000000..ad86f71 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/sessions/new.html.erb @@ -0,0 +1,22 @@ +

Sign in

+ +<% semantic_form_for :session, :url => session_path do |form| %> + <% form.inputs do %> + <%= form.input :email %> + <%= form.input :password, :as => :password %> + <%= form.input :remember_me, :as => :boolean, :required => false %> + <% end %> + <% form.buttons do %> + <%= form.commit_button "Sign in" %> + <% end %> +<% end %> + + + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/users/_inputs.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/users/_inputs.html.erb new file mode 100644 index 0000000..aff7908 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/users/_inputs.html.erb @@ -0,0 +1,6 @@ +<% form.inputs do %> + <%= form.input :email %> + <%= form.input :password %> + <%= form.input :password_confirmation, :label => "Confirm password" %> +<% end %> + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/users/new.html.erb b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/users/new.html.erb new file mode 100644 index 0000000..be7f1dc --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/generators/clearance_views/templates/formtastic/users/new.html.erb @@ -0,0 +1,10 @@ +

Sign up

+ +<% semantic_form_for @user do |form| %> + <%= form.error_messages %> + <%= render :partial => "/users/inputs", :locals => { :form => form } %> + <% form.buttons do %> + <%= form.commit_button "Sign up" %> + <% end %> +<% end %> + diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance.rb b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance.rb new file mode 100644 index 0000000..260c4d6 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance.rb @@ -0,0 +1,6 @@ +require 'clearance/extensions/errors' +require 'clearance/extensions/rescue' +require 'clearance/extensions/routes' + +require 'clearance/authentication' +require 'clearance/user' diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/authentication.rb b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/authentication.rb new file mode 100644 index 0000000..303ffd6 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/authentication.rb @@ -0,0 +1,102 @@ +module Clearance + module Authentication + + def self.included(controller) + controller.send(:include, InstanceMethods) + + controller.class_eval do + helper_method :current_user, :signed_in?, :signed_out? + hide_action :current_user, :signed_in?, :signed_out? + end + end + + module InstanceMethods + def current_user + @_current_user ||= (user_from_cookie || user_from_session) + end + + def signed_in? + ! current_user.nil? + end + + def signed_out? + current_user.nil? + end + + protected + + def authenticate + deny_access unless signed_in? + end + + def user_from_session + if session[:user_id] + return nil unless user = ::User.find_by_id(session[:user_id]) + return user if user.email_confirmed? + end + end + + def user_from_cookie + if token = cookies[:remember_token] + return nil unless user = ::User.find_by_token(token) + return user if user.remember? + end + end + + def sign_user_in(user) + warn "[DEPRECATION] sign_user_in: unnecessary. use sign_in(user) instead." + sign_in(user) + end + + def sign_in(user) + if user + session[:user_id] = user.id + end + end + + def remember? + params[:session] && params[:session][:remember_me] == "1" + end + + def remember(user) + user.remember_me! + cookies[:remember_token] = { :value => user.token, + :expires => user.token_expires_at } + end + + def forget(user) + user.forget_me! if user + cookies.delete(:remember_token) + reset_session + end + + def redirect_back_or(default) + redirect_to(return_to || default) + clear_return_to + end + + def return_to + session[:return_to] || params[:return_to] + end + + def clear_return_to + session[:return_to] = nil + end + + def redirect_to_root + redirect_to(root_url) + end + + def store_location + session[:return_to] = request.request_uri if request.get? + end + + def deny_access(flash_message = nil, opts = {}) + store_location + flash[:failure] = flash_message if flash_message + redirect_to(new_session_url) + end + end + + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/errors.rb b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/errors.rb new file mode 100644 index 0000000..d6b19bf --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/errors.rb @@ -0,0 +1,6 @@ +if defined?(ActionController) + module ActionController + class Forbidden < StandardError + end + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/rescue.rb b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/rescue.rb new file mode 100644 index 0000000..7afe4ad --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/rescue.rb @@ -0,0 +1,3 @@ +if defined?(ActionController::Base) + ActionController::Base.rescue_responses.update('ActionController::Forbidden' => :forbidden) +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/routes.rb b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/routes.rb new file mode 100644 index 0000000..1a6c43b --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/extensions/routes.rb @@ -0,0 +1,14 @@ +if defined?(ActionController::Routing::RouteSet) + class ActionController::Routing::RouteSet + def load_routes_with_clearance! + lib_path = File.dirname(__FILE__) + clearance_routes = File.join(lib_path, *%w[.. .. .. config clearance_routes.rb]) + unless configuration_files.include?(clearance_routes) + add_configuration_file(clearance_routes) + end + load_routes_without_clearance! + end + + alias_method_chain :load_routes!, :clearance + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/user.rb b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/user.rb new file mode 100644 index 0000000..f6206e9 --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/lib/clearance/user.rb @@ -0,0 +1,143 @@ +require 'digest/sha1' + +module Clearance + module User + + def self.included(model) + model.extend(ClassMethods) + + model.send(:include, InstanceMethods) + model.send(:include, AttrAccessible) + model.send(:include, AttrAccessor) + model.send(:include, Validations) + model.send(:include, Callbacks) + end + + module AttrAccessible + def self.included(model) + model.class_eval do + attr_accessible :email, :password, :password_confirmation + end + end + end + + module AttrAccessor + def self.included(model) + model.class_eval do + attr_accessor :password, :password_confirmation + end + end + end + + module Validations + def self.included(model) + model.class_eval do + validates_presence_of :email + validates_uniqueness_of :email, :case_sensitive => false + validates_format_of :email, :with => %r{.+@.+\..+} + + validates_presence_of :password, :if => :password_required? + validates_confirmation_of :password, :if => :password_required? + end + end + end + + module Callbacks + def self.included(model) + model.class_eval do + before_save :initialize_salt, :encrypt_password, :initialize_token + end + end + end + + module InstanceMethods + def authenticated?(password) + encrypted_password == encrypt(password) + end + + def encrypt(string) + generate_hash("--#{salt}--#{string}--") + end + + def remember? + token_expires_at && Time.now.utc < token_expires_at + end + + def remember_me! + remember_me_until! 2.weeks.from_now.utc + end + + def forget_me! + clear_token + save(false) + end + + def confirm_email! + self.email_confirmed = true + self.token = nil + save(false) + end + + def forgot_password! + generate_token + save(false) + end + + def update_password(new_password, new_password_confirmation) + self.password = new_password + self.password_confirmation = new_password_confirmation + clear_token if valid? + save + end + + protected + + def generate_hash(string) + Digest::SHA1.hexdigest(string) + end + + def initialize_salt + if new_record? + self.salt = generate_hash("--#{Time.now.utc.to_s}--#{password}--") + end + end + + def encrypt_password + return if password.blank? + self.encrypted_password = encrypt(password) + end + + def generate_token + self.token = encrypt("--#{Time.now.utc.to_s}--#{password}--") + self.token_expires_at = nil + end + + def clear_token + self.token = nil + self.token_expires_at = nil + end + + def initialize_token + generate_token if new_record? + end + + def password_required? + encrypted_password.blank? || !password.blank? + end + + def remember_me_until!(time) + self.token_expires_at = time + self.token = encrypt("--#{token_expires_at}--#{password}--") + save(false) + end + end + + module ClassMethods + def authenticate(email, password) + return nil unless user = find_by_email(email) + return user if user.authenticated?(password) + end + end + + end +end diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/rails/init.rb b/vendor/gems/thoughtbot-clearance-0.7.0/rails/init.rb new file mode 100644 index 0000000..5ed1d1b --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/rails/init.rb @@ -0,0 +1 @@ +require 'clearance' \ No newline at end of file diff --git a/vendor/gems/thoughtbot-clearance-0.7.0/shoulda_macros/clearance.rb b/vendor/gems/thoughtbot-clearance-0.7.0/shoulda_macros/clearance.rb new file mode 100644 index 0000000..10bc99c --- /dev/null +++ b/vendor/gems/thoughtbot-clearance-0.7.0/shoulda_macros/clearance.rb @@ -0,0 +1,268 @@ +module Clearance + module Shoulda + + # STATE OF AUTHENTICATION + + def should_be_signed_in_as(&block) + should "be signed in as #{block.bind(self).call}" do + user = block.bind(self).call + assert_not_nil user, + "please pass a User. try: should_be_signed_in_as { @user }" + assert_equal user, @controller.send(:current_user), + "#{user.inspect} is not the current_user, " << + "which is #{@controller.send(:current_user).inspect}" + end + end + + def should_be_signed_in_and_email_confirmed_as(&block) + warn "[DEPRECATION] should_be_signed_in_and_email_confirmed_as: questionable usefulness" + should_be_signed_in_as &block + + should "have confirmed email" do + user = block.bind(self).call + + assert_not_nil user + assert_equal user, assigns(:user) + assert assigns(:user).email_confirmed? + end + end + + def should_not_be_signed_in + should "not be signed in" do + assert_nil session[:user_id] + end + end + + def should_deny_access_on(http_method, action, opts = {}) + warn "[DEPRECATION] should_deny_access_on: use a setup & should_deny_access(:flash => ?)" + flash_message = opts.delete(:flash) + context "on #{http_method} to #{action}" do + setup do + send(http_method, action, opts) + end + + should_deny_access(:flash => flash_message) + end + end + + def should_deny_access(opts = {}) + if opts[:flash] + should_set_the_flash_to opts[:flash] + else + should_not_set_the_flash + end + + should_redirect_to('new_session_url') { new_session_url } + end + + # HTTP FLUENCY + + def should_forbid(description, &block) + should "forbid #{description}" do + assert_raises ActionController::Forbidden do + instance_eval(&block) + end + end + end + + # CONTEXTS + + def signed_in_user_context(&blk) + warn "[DEPRECATION] signed_in_user_context: creates a Mystery Guest, causes Obscure Test" + context "A signed in user" do + setup do + @user = Factory(:user) + @user.confirm_email! + sign_in_as @user + end + merge_block(&blk) + end + end + + def public_context(&blk) + warn "[DEPRECATION] public_context: common case is no-op. call sign_out otherwise" + context "The public" do + setup { sign_out } + merge_block(&blk) + end + end + + # CREATING USERS + + def should_create_user_successfully + warn "[DEPRECATION] should_create_user_successfully: not meant to be public, no longer used internally" + should_assign_to :user + should_change 'User.count', :by => 1 + + should "send the confirmation email" do + assert_sent_email do |email| + email.subject =~ /account confirmation/i + end + end + + should_set_the_flash_to /confirm/i + should_redirect_to_url_after_create + end + + # RENDERING + + def should_render_nothing + should "render nothing" do + assert @response.body.blank? + end + end + + # REDIRECTS + + def should_redirect_to_url_after_create + should_redirect_to("the post-create url") do + @controller.send(:url_after_create) + end + end + + def should_redirect_to_url_after_update + should_redirect_to("the post-update url") do + @controller.send(:url_after_update) + end + end + + def should_redirect_to_url_after_destroy + should_redirect_to("the post-destroy url") do + @controller.send(:url_after_destroy) + end + end + + def should_redirect_to_url_already_confirmed + should_redirect_to("the already confirmed url") do + @controller.send(:url_already_confirmed) + end + end + + # VALIDATIONS + + def should_validate_confirmation_of(attribute, opts = {}) + warn "[DEPRECATION] should_validate_confirmation_of: not meant to be public, no longer used internally" + raise ArgumentError if opts[:factory].nil? + + context "on save" do + should_validate_confirmation_is_not_blank opts[:factory], attribute + should_validate_confirmation_is_not_bad opts[:factory], attribute + end + end + + def should_validate_confirmation_is_not_blank(factory, attribute, opts = {}) + warn "[DEPRECATION] should_validate_confirmation_is_not_blank: not meant to be public, no longer used internally" + should "validate #{attribute}_confirmation is not blank" do + model = Factory.build(factory, blank_confirmation_options(attribute)) + model.save + assert_confirmation_error(model, attribute, + "#{attribute}_confirmation cannot be blank") + end + end + + def should_validate_confirmation_is_not_bad(factory, attribute, opts = {}) + warn "[DEPRECATION] should_validate_confirmation_is_not_bad: not meant to be public, no longer used internally" + should "validate #{attribute}_confirmation is different than #{attribute}" do + model = Factory.build(factory, bad_confirmation_options(attribute)) + model.save + assert_confirmation_error(model, attribute, + "#{attribute}_confirmation cannot be different than #{attribute}") + end + end + + # FORMS + + def should_display_a_password_update_form + warn "[DEPRECATION] should_display_a_password_update_form: not meant to be public, no longer used internally" + should "have a form for the user's token, password, and password confirm" do + update_path = ERB::Util.h( + user_password_path(@user, :token => @user.token) + ) + + assert_select 'form[action=?]', update_path do + assert_select 'input[name=_method][value=?]', 'put' + assert_select 'input[name=?]', 'user[password]' + assert_select 'input[name=?]', 'user[password_confirmation]' + end + end + end + + def should_display_a_sign_up_form + warn "[DEPRECATION] should_display_a_sign_up_form: not meant to be public, no longer used internally" + should "display a form to sign up" do + assert_select "form[action=#{users_path}][method=post]", + true, "There must be a form to sign up" do + assert_select "input[type=text][name=?]", + "user[email]", true, "There must be an email field" + assert_select "input[type=password][name=?]", + "user[password]", true, "There must be a password field" + assert_select "input[type=password][name=?]", + "user[password_confirmation]", true, "There must be a password confirmation field" + assert_select "input[type=submit]", true, + "There must be a submit button" + end + end + end + + def should_display_a_sign_in_form + warn "[DEPRECATION] should_display_a_sign_in_form: not meant to be public, no longer used internally" + should 'display a "sign in" form' do + assert_select "form[action=#{session_path}][method=post]", + true, "There must be a form to sign in" do + assert_select "input[type=text][name=?]", + "session[email]", true, "There must be an email field" + assert_select "input[type=password][name=?]", + "session[password]", true, "There must be a password field" + assert_select "input[type=checkbox][name=?]", + "session[remember_me]", true, "There must be a 'remember me' check box" + assert_select "input[type=submit]", true, + "There must be a submit button" + end + end + end + end +end + +module Clearance + module Shoulda + module Helpers + def sign_in_as(user) + @controller.class_eval { attr_accessor :current_user } + @controller.current_user = user + return user + end + + def sign_in + sign_in_as Factory(:email_confirmed_user) + end + + def sign_out + @controller.class_eval { attr_accessor :current_user } + @controller.current_user = nil + end + + def blank_confirmation_options(attribute) + warn "[DEPRECATION] blank_confirmation_options: not meant to be public, no longer used internally" + opts = { attribute => attribute.to_s } + opts.merge("#{attribute}_confirmation".to_sym => "") + end + + def bad_confirmation_options(attribute) + warn "[DEPRECATION] bad_confirmation_options: not meant to be public, no longer used internally" + opts = { attribute => attribute.to_s } + opts.merge("#{attribute}_confirmation".to_sym => "not_#{attribute}") + end + + def assert_confirmation_error(model, attribute, message = "confirmation error") + warn "[DEPRECATION] assert_confirmation_error: not meant to be public, no longer used internally" + assert model.errors.on(attribute).include?("doesn't match confirmation"), + message + end + end + end +end + +class Test::Unit::TestCase + include Clearance::Shoulda::Helpers +end +Test::Unit::TestCase.extend(Clearance::Shoulda) diff --git a/vendor/plugins/clearance/CHANGELOG.textile b/vendor/plugins/clearance/CHANGELOG.textile deleted file mode 100644 index 3c27788..0000000 --- a/vendor/plugins/clearance/CHANGELOG.textile +++ /dev/null @@ -1,167 +0,0 @@ -h2. 0.6.9 (07/04/2009) - -* Added timestamps to create users migration. (Dan Croak) -* Ready for Ruby 1.9. (Jason Morrison, Nick Quaranto) - -h2. 0.6.8 (06/24/2009) - -* Added defined? checks for various Rails constants such as ActionController -for easier unit testing of Clearance extensions... particularly ActiveRecord -extensions... particularly strong_password. (Dan Croak) - -h2. 0.6.7 (06/13/2009) - -* [#30] Added sign_up, sign_in, sign_out named routes. (Dan Croak) -* [#22] Minimizing Reek smell: Duplication in redirect_back_or. (Dan Croak) -* Deprecated sign_user_in. Told developers to use sign_in instead. (Dan -Croak) -* [#16] flash_success_after_create, flash_notice_after_create, flash_failure_after_create, flash_sucess_after_update, flash_success_after_destroy, etc. (Dan Croak) -* [#17] bug. added #create to forbidden before_filters on confirmations controller. (Dan Croak) -* [#24] should_be_signed_in_as shouldn't look in the session. (Dan Croak) -* README improvements. (Dan Croak) -* Move routes loading to separate file. (Joshua Clayton) - -h2. 0.6.6 (05/18/2009) - -* [#14] replaced class_eval in Clearance::User with modules. This was needed -in a thoughtbot client app so we could write our own validations. (Dan Croak) - -h2. 0.6.5 (05/17/2009) - -* [#6] Make Clearance i18n aware. (Timur Vafin, Marcel Goerner, Eugene Bolshakov, Dan Croak) - -h2. 0.6.4 (05/12/2009) - -* Moved issue tracking to Github from Lighthouse. (Dan Croak) -* [#7] asking higher-level questions of controllers in webrat steps, such as signed_in? instead of what's in the session. same for accessors. (Dan Croak) -* [#11] replacing sign_in_as & sign_out shoulda macros with a stubbing (requires no dependency) approach. this will avoid dealing with the internals of current_user, such as session & cookies. added sign_in macro which signs in an email confirmed user from clearance's factories. (Dan Croak) -* [#13] move private methods on sessions controller into Clearance::Authentication module (Dan Croak) -* [#9] audited flash keys. (Dan Croak) - -h2. 0.6.3 (04/23/2009) - -* Scoping ClearanceMailer properly within controllers so it works in production environments. (Nick Quaranto) - -h2. 0.6.2 (04/22/2009) - -* Insert Clearance::User into User model if it exists. (Nick Quaranto) -* World(NavigationHelpers) Cucumber 3.0 style. (Shay Arnett & Mark Cornick) - -h2. 0.6.1 (04/21/2009) -* Scope operators are necessary to keep Rails happy. Reverting the original -revert so they're back in the library now for constants referenced inside of -the gem. (Nick Quaranto) - -h2. 0.6.0 (04/21/2009) - -* Converted Clearance to a Rails engine. (Dan Croak & Joe Ferris) -* Include Clearance::User in User model in app. (Dan Croak & Joe Ferris) -* Include Clearance::Authentication in ApplicationController. (Dan Croak & Joe Ferris) -* Namespace controllers under Clearance. (Dan Croak & Joe Ferris) -* Routes move to engine, use namespaced controllers but publicly the same. (Dan Croak & Joe Ferris) -* If you want to override a controller, subclass it like SessionsController < -Clearance::SessionsController. This gives you access to usual hooks such as -url_after_create. (Dan Croak & Joe Ferris) -* Controllers, mailer, model, routes all unit tested inside engine. Use -script/generate clearance_features to test integration of Clearance with your -Rails app. No longer including modules in your app's test files. (Dan Croak & Joe Ferris) -* Moved views to engine. (Joe Ferris) -* Converted generated test/factories/clearance.rb to use inheritence for -email_confirmed_user. (Dan Croak) -* Corrected some spelling errors with methods (Nick Quaranto) -* Converted "I should see error messages" to use a regex in the features (Nick -Quaranto) -* Loading clearance routes after rails routes via some monkeypatching (Nick -Quaranto) -* Made the clearance controllers unloadable to stop constant loading errors in -development mode (Nick Quaranto) - -h2. 0.5.6 (4/11/2009) - -* [#57] Step definition changed for "User should see error messages" so -features won't fail for certain validations. (Nick Quaranto) - -h2. 0.5.5 (3/23/2009) - -* Removing duplicate test to get rid of warning. (Nick Quaranto) - -h2. 0.5.4 (3/21/2009) - -* When users fail logging in, redirect them instead of rendering. (Matt -Jankowski) - -h2. 0.5.3 (3/5/2009) - -* Clearance now works with (and requires) Shoulda 2.10.0. (Mark Cornick, Joe -Ferris, Dan Croak) -* Prefer flat over nested contexts in sessions_controller_test. (Joe Ferris, -Dan Croak) - -h2. 0.5.2 (3/2/2009) - -* Fixed last remaining errors in Rails 2.3 tests. Now fully compatible. (Joe -Ferris, Dan Croak) - -h2. 0.5.1 (2/27/2009) - -* [#46] A user with unconfirmed email who resets password now confirms email. -(Marcel Görner) -* Refactored user_from_cookie, user_from_session, User#authenticate to use -more direct return code instead of ugly, harder to read ternary. (Dan Croak) -* Switch order of cookies and sessions to take advantage of Rails 2.3's "Rack-based lazy-loaded sessions":http://is.gd/i23E. (Dan Croak) -* Altered generator to interact with application_controller.rb instead of -application.rb in Rails 2.3 apps. (Dan Croak) -* [#42] Bug fix. Rack-based session change altered how to test remember me -cookie. (Mihai Anca) - -h2. 0.5.0 (2/27/2009) - -* Fixed problem with Cucumber features. (Dan Croak) -* Fixed mising HTTP fluency use case. (Dan Croak) -* Refactored User#update_password to take just parameters it needs. (Dan -Croak) -* Refactored User unit tests to be more readable. (Dan Croak) - -h2. 0.4.9 (2/20/2009) - -* Protect passwords & confirmations actions with forbidden filters. (Dan Croak) -* Return 403 Forbidden status code in those cases. (Tim Pope) -* Test 403 Forbidden status code in Cucumber feature. (Dan Croak, Joe Ferris) -* Raise custom ActionController::Forbidden error internally. (Joe Ferris, Mike Burns, Jason Morrison) -* Test ActionController::Forbidden error is raised in functional test. (Joe Ferris, Mike Burns, Dan Croak) -* [#45] Fixed bug that allowed anyone to edit another user's password (Marcel Görner) -* Required Factory Girl >= 1.2.0. (Dan Croak) - -h2. 0.4.8 (2/16/2009) - -* Added support paths for Cucumber. (Ben Mabey) -* Added documentation for the flash. (Ben Mabey) -* Generators require "test_helper" instead of File.join. for rr compatibility. (Joe Ferris) -* Removed interpolated email address from flash message to make i18n easier. (Bence Nagy) -* Standardized flash messages that refer to email delivery. (Dan Croak) - -h2. 0.4.7 (2/12/2009) - -* Removed Clearance::Test::TestHelper so there is one less setup step. (Dan Croak) -* All test helpers now in shoulda_macros. (Dan Croak) - -h2. 0.4.6 (2/11/2009) - -* Made the modules behave like mixins again. (hat-tip Eloy Duran) -* Created Actions and PrivateMethods modules on controllers for future RDoc reasons. (Dan Croak, Joe Ferris) - -h2. 0.4.5 (2/9/2009) - -* [#43] Removed email downcasing because local-part is case sensitive per RFC5321. (Dan Croak) -* [#42] Removed dependency on Mocha. (Dan Croak) -* Required Shoulda >= 2.9.1. (Dan Croak) -* Added password reset feature to clearance_features generator. (Eugene Bolshakov, Dan Croak) -* Removed unnecessary session[:salt]. (Dan Croak) -* [#41] Only store location for session[:return_to] for GET requests. (Dan Croak) -* Audited "sign up" naming convention. "Register" had slipped in a few places. (Dan Croak) -* Switched to SHA1 encryption. Cypher doesn't matter much for email confirmation, password reset. Better to have shorter hashes in the emails for clients who line break on 72 chars. (Dan Croak) - -h2. 0.4.4 (2/2/2009) - -* Added a generator for Cucumber features. (Joe Ferris, Dan Croak) -* Standarized naming for "Sign up," "Sign in," and "Sign out". (Dan Croak) diff --git a/vendor/plugins/clearance/LICENSE b/vendor/plugins/clearance/LICENSE deleted file mode 100644 index 5060183..0000000 --- a/vendor/plugins/clearance/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2008 thoughtbot, inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/plugins/clearance/README.textile b/vendor/plugins/clearance/README.textile deleted file mode 100644 index 3aa3687..0000000 --- a/vendor/plugins/clearance/README.textile +++ /dev/null @@ -1,123 +0,0 @@ -h1. Clearance - -Rails authentication with email & password. - -"We have clearance, Clarence.":http://www.youtube.com/v/mNRXJEE3Nz8 - -h2. Wiki - -Most information regarding Clearance is on the "Github Wiki":http://wiki.github.com/thoughtbot/clearance. - -h2. Installation - -Clearance is a Rails engine. It works with versions of Rails greater than 2.3. - -In config/environment.rb: - -
-config.gem "thoughtbot-clearance", 
-  :lib     => 'clearance', 
-  :source  => 'http://gems.github.com', 
-  :version => '0.6.9'
-
- -Vendor the gem: - -
-rake gems:install
-rake gems:unpack
-
- -Make sure the development database exists and run the generator: - -@script/generate clearance@ - -A number of files will be created and instructions will be printed. - -You may already have some of these files. Don't worry. You'll be asked if you want to overwrite them. - -Run the migration: - -@rake db:migrate@ - -Define a HOST constant in your environment files. -In config/environments/test.rb and config/environments/development.rb it can be: - -@HOST = "localhost"@ - -In production.rb it must be the actual host your application is deployed to. -The constant is used by mailers to generate URLs in emails. - -In config/environment.rb: - -@DO_NOT_REPLY = "donotreply@example.com"@ - -Define root_url to *something* in your config/routes.rb: - -@map.root :controller => 'home'@ - -h2. Cucumber Features - -As your app evolves, you want to know that authentication still works. Clearance's opinion is that you should test its integration with your app using "Cucumber":http://cukes.info/. - -In config/environments/test.rb: - -
-config.gem 'webrat',
-  :version => '= 0.4.4'
-config.gem 'cucumber',
-  :version => '= 0.3.0'
-config.gem 'thoughtbot-factory_girl',
-  :lib     => 'factory_girl',
-  :source  => "http://gems.github.com", 
-  :version => '1.2.1'
-
- -Vendor the gems: - -
-rake gems:install RAILS_ENV=test
-rake gems:unpack  RAILS_ENV=test
-
- -We don't vendor nokogiri due to its native extensions, so install it normally on your machine: - -@sudo gem install nokogiri@ - -Run the Cucumber generator (if you haven't already) and Clearance's feature generator: - -
-script/generate cucumber
-script/generate clearance_features
-
- -All of the files generated should be new with the exception of the features/support/paths.rb file. If you have not modified your paths.rb then you will be okay to replace it with this one. If you need to keep your paths.rb file then add these locations in your paths.rb manually: - -
-def path_to(page_name)
-  case page_name
-   ...
-  when /the sign up page/i
-   new_user_path
-  when /the sign in page/i
-   new_session_path
-  when /the password reset request page/i
-   new_password_path
-  ...
-end
-
- -h2. Authors - -Clearance was extracted out of "Hoptoad":http://hoptoadapp.com. We merged the authentication code from two of thoughtbot's clients' Rails apps and have since used it each time we need authentication. The following people have improved the library. Thank you! - -Dan Croak, Mike Burns, Jason Morrison, Joe Ferris, Eugene Bolshakov, Nick Quaranto, Josh Nichols, Mike Breen, Marcel Görner, Bence Nagy, Ben Mabey, Eloy Duran, Tim Pope, Mihai Anca, Mark Cornick, Shay Arnett, Joshua Clayton & Mustafa Ekim. - -h2. Questions? - -Ask the "mailing list":http://groups.google.com/group/thoughtbot-clearance - -h2. Suggestions, Bugs, Refactoring? - -Fork away and create a "Github Issue":http://github.com/thoughtbot/clearance/issues. Please don't send pull requests. - diff --git a/vendor/plugins/clearance/Rakefile b/vendor/plugins/clearance/Rakefile deleted file mode 100644 index b5fd366..0000000 --- a/vendor/plugins/clearance/Rakefile +++ /dev/null @@ -1,76 +0,0 @@ -# encoding: utf-8 - -require 'rake' -require 'rake/testtask' -require 'cucumber/rake/task' - -namespace :test do - Rake::TestTask.new(:all => ["generator:cleanup", - "generator:generate"]) do |task| - task.libs << "lib" - task.libs << "test" - task.pattern = "test/**/*_test.rb" - task.verbose = false - end - - Cucumber::Rake::Task.new(:features) do |t| - t.cucumber_opts = "--format progress" - t.feature_pattern = "test/rails_root/features/*.feature" - end -end - -generators = %w(clearance clearance_features) - -namespace :generator do - desc "Cleans up the test app before running the generator" - task :cleanup do - generators.each do |generator| - FileList["generators/#{generator}/templates/**/*.*"].each do |each| - file = "test/rails_root/#{each.gsub("generators/#{generator}/templates/",'')}" - File.delete(file) if File.exists?(file) - end - end - - FileList["test/rails_root/db/**/*"].each do |each| - FileUtils.rm_rf(each) - end - FileUtils.rm_rf("test/rails_root/vendor/plugins/clearance") - FileUtils.mkdir_p("test/rails_root/vendor/plugins") - clearance_root = File.expand_path(File.dirname(__FILE__)) - system("ln -s #{clearance_root} test/rails_root/vendor/plugins/clearance") - end - - desc "Run the generator on the tests" - task :generate do - generators.each do |generator| - system "cd test/rails_root && ./script/generate #{generator} && rake db:migrate db:test:prepare" - end - end -end - -desc "Run the test suite" -task :default => ['test:all', 'test:features'] - -gem_spec = Gem::Specification.new do |gem_spec| - gem_spec.name = "clearance" - gem_spec.version = "0.6.9" - gem_spec.summary = "Rails authentication with email & password." - gem_spec.email = "support@thoughtbot.com" - gem_spec.homepage = "http://github.com/thoughtbot/clearance" - gem_spec.description = "Rails authentication with email & password." - gem_spec.authors = ["Dan Croak", "Mike Burns", "Jason Morrison", - "Joe Ferris", "Eugene Bolshakov", "Nick Quaranto", - "Josh Nichols", "Mike Breen", "Marcel Görner", - "Bence Nagy", "Ben Mabey", "Eloy Duran", - "Tim Pope", "Mihai Anca", "Mark Cornick", - "Shay Arnett"] - gem_spec.files = FileList["[A-Z]*", "{app,config,generators,lib,shoulda_macros,rails}/**/*"] -end - -desc "Generate a gemspec file" -task :gemspec do - File.open("#{gem_spec.name}.gemspec", 'w') do |f| - f.write gem_spec.to_yaml - end -end - diff --git a/vendor/plugins/clearance/TODO.textile b/vendor/plugins/clearance/TODO.textile deleted file mode 100644 index 9805aed..0000000 --- a/vendor/plugins/clearance/TODO.textile +++ /dev/null @@ -1,6 +0,0 @@ -h1. To-do - -* Make insertion of Clearance::User into User model automatic from the generator. -* Change generated README to include instruction about running the migration. -* DO_NOT_REPLY, HOST refactoring. - diff --git a/vendor/plugins/clearance/app/controllers/clearance/confirmations_controller.rb b/vendor/plugins/clearance/app/controllers/clearance/confirmations_controller.rb deleted file mode 100644 index 9f1e125..0000000 --- a/vendor/plugins/clearance/app/controllers/clearance/confirmations_controller.rb +++ /dev/null @@ -1,52 +0,0 @@ -class Clearance::ConfirmationsController < ApplicationController - unloadable - - before_filter :forbid_confirmed_user, :only => [:new, :create] - before_filter :forbid_missing_token, :only => [:new, :create] - before_filter :forbid_non_existent_user, :only => [:new, :create] - filter_parameter_logging :token - - def new - create - end - - def create - @user = ::User.find_by_id_and_token(params[:user_id], params[:token]) - @user.confirm_email! - - sign_in(@user) - flash_success_after_create - redirect_to(url_after_create) - end - - private - - def forbid_confirmed_user - user = ::User.find_by_id(params[:user_id]) - if user && user.email_confirmed? - raise ActionController::Forbidden, "confirmed user" - end - end - - def forbid_missing_token - if params[:token].blank? - raise ActionController::Forbidden, "missing token" - end - end - - def forbid_non_existent_user - unless ::User.find_by_id_and_token(params[:user_id], params[:token]) - raise ActionController::Forbidden, "non-existent user" - end - end - - def flash_success_after_create - flash[:success] = translate(:confirmed_email, - :scope => [:clearance, :controllers, :confirmations], - :default => "Confirmed email and signed in.") - end - - def url_after_create - root_url - end -end diff --git a/vendor/plugins/clearance/app/controllers/clearance/passwords_controller.rb b/vendor/plugins/clearance/app/controllers/clearance/passwords_controller.rb deleted file mode 100644 index 6221ad3..0000000 --- a/vendor/plugins/clearance/app/controllers/clearance/passwords_controller.rb +++ /dev/null @@ -1,81 +0,0 @@ -class Clearance::PasswordsController < ApplicationController - unloadable - - before_filter :forbid_missing_token, :only => [:edit, :update] - before_filter :forbid_non_existent_user, :only => [:edit, :update] - filter_parameter_logging :password, :password_confirmation - - def new - render :template => 'passwords/new' - end - - def create - if user = ::User.find_by_email(params[:password][:email]) - user.forgot_password! - ::ClearanceMailer.deliver_change_password user - flash_notice_after_create - redirect_to(url_after_create) - else - flash_failure_after_create - render :template => 'passwords/new' - end - end - - def edit - @user = ::User.find_by_id_and_token(params[:user_id], params[:token]) - render :template => 'passwords/edit' - end - - def update - @user = ::User.find_by_id_and_token(params[:user_id], params[:token]) - - if @user.update_password(params[:user][:password], - params[:user][:password_confirmation]) - @user.confirm_email! - sign_in(@user) - flash_success_after_update - redirect_to(url_after_update) - else - render :template => 'passwords/edit' - end - end - - private - - def forbid_missing_token - if params[:token].blank? - raise ActionController::Forbidden, "missing token" - end - end - - def forbid_non_existent_user - unless ::User.find_by_id_and_token(params[:user_id], params[:token]) - raise ActionController::Forbidden, "non-existent user" - end - end - - def flash_notice_after_create - flash[:notice] = translate(:deliver_change_password, - :scope => [:clearance, :controllers, :passwords], - :default => "You will receive an email within the next few minutes. " << - "It contains instructions for changing your password.") - end - - def flash_failure_after_create - flash.now[:failure] = translate(:unknown_email, - :scope => [:clearance, :controllers, :passwords], - :default => "Unknown email.") - end - - def url_after_create - new_session_url - end - - def flash_success_after_update - flash[:success] = translate(:signed_in, :default => "Signed in.") - end - - def url_after_update - root_url - end -end diff --git a/vendor/plugins/clearance/app/controllers/clearance/sessions_controller.rb b/vendor/plugins/clearance/app/controllers/clearance/sessions_controller.rb deleted file mode 100644 index 2ea0440..0000000 --- a/vendor/plugins/clearance/app/controllers/clearance/sessions_controller.rb +++ /dev/null @@ -1,67 +0,0 @@ -class Clearance::SessionsController < ApplicationController - unloadable - - protect_from_forgery :except => :create - filter_parameter_logging :password - - def new - render :template => 'sessions/new' - end - - def create - @user = ::User.authenticate(params[:session][:email], - params[:session][:password]) - if @user.nil? - flash_failure_after_create - render :template => 'sessions/new', :status => :unauthorized - else - if @user.email_confirmed? - sign_in(@user) - remember(@user) if remember? - flash_success_after_create - redirect_back_or(url_after_create) - else - ::ClearanceMailer.deliver_confirmation(@user) - flash_notice_after_create - redirect_to(new_session_url) - end - end - end - - def destroy - forget(current_user) - flash_success_after_destroy - redirect_to(url_after_destroy) - end - - private - - def flash_failure_after_create - flash.now[:failure] = translate(:bad_email_or_password, - :scope => [:clearance, :controllers, :sessions], - :default => "Bad email or password.") - end - - def flash_success_after_create - flash[:success] = translate(:signed_in, :default => "Signed in.") - end - - def flash_notice_after_create - flash[:notice] = translate(:unconfirmed_email, - :scope => [:clearance, :controllers, :sessions], - :default => "User has not confirmed email. " << - "Confirmation email will be resent.") - end - - def url_after_create - root_url - end - - def flash_success_after_destroy - flash[:success] = translate(:signed_out, :default => "Signed out.") - end - - def url_after_destroy - new_session_url - end -end diff --git a/vendor/plugins/clearance/app/controllers/clearance/users_controller.rb b/vendor/plugins/clearance/app/controllers/clearance/users_controller.rb deleted file mode 100644 index 6b8659e..0000000 --- a/vendor/plugins/clearance/app/controllers/clearance/users_controller.rb +++ /dev/null @@ -1,35 +0,0 @@ -class Clearance::UsersController < ApplicationController - unloadable - - before_filter :redirect_to_root, :only => [:new, :create], :if => :signed_in? - filter_parameter_logging :password - - def new - @user = ::User.new(params[:user]) - render :template => 'users/new' - end - - def create - @user = ::User.new params[:user] - if @user.save - ::ClearanceMailer.deliver_confirmation @user - flash_notice_after_create - redirect_to(url_after_create) - else - render :template => 'users/new' - end - end - - private - - def flash_notice_after_create - flash[:notice] = translate(:deliver_confirmation, - :scope => [:clearance, :controllers, :users], - :default => "You will receive an email within the next few minutes. " << - "It contains instructions for confirming your account.") - end - - def url_after_create - new_session_url - end -end diff --git a/vendor/plugins/clearance/app/models/clearance_mailer.rb b/vendor/plugins/clearance/app/models/clearance_mailer.rb deleted file mode 100644 index 90f5f16..0000000 --- a/vendor/plugins/clearance/app/models/clearance_mailer.rb +++ /dev/null @@ -1,23 +0,0 @@ -class ClearanceMailer < ActionMailer::Base - - default_url_options[:host] = HOST - - def change_password(user) - from DO_NOT_REPLY - recipients user.email - subject I18n.t(:change_password, - :scope => [:clearance, :models, :clearance_mailer], - :default => "Change your password") - body :user => user - end - - def confirmation(user) - from DO_NOT_REPLY - recipients user.email - subject I18n.t(:confirmation, - :scope => [:clearance, :models, :clearance_mailer], - :default => "Account confirmation") - body :user => user - end - -end diff --git a/vendor/plugins/clearance/app/views/clearance_mailer/change_password.html.erb b/vendor/plugins/clearance/app/views/clearance_mailer/change_password.html.erb deleted file mode 100644 index 246324d..0000000 --- a/vendor/plugins/clearance/app/views/clearance_mailer/change_password.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -Someone, hopefully you, has requested that we send you a link to change your password. - -Here's the link: - -<%= edit_user_password_url(@user, :token => @user.token, :escape => false) %> - -If you didn't request this, ignore this email. Don't worry. Your password hasn't been changed. diff --git a/vendor/plugins/clearance/app/views/clearance_mailer/confirmation.html.erb b/vendor/plugins/clearance/app/views/clearance_mailer/confirmation.html.erb deleted file mode 100644 index 83d3de4..0000000 --- a/vendor/plugins/clearance/app/views/clearance_mailer/confirmation.html.erb +++ /dev/null @@ -1,2 +0,0 @@ - -<%= new_user_confirmation_url :user_id => @user, :token => @user.token, :encode => false %> diff --git a/vendor/plugins/clearance/app/views/passwords/edit.html.erb b/vendor/plugins/clearance/app/views/passwords/edit.html.erb deleted file mode 100644 index c8637f5..0000000 --- a/vendor/plugins/clearance/app/views/passwords/edit.html.erb +++ /dev/null @@ -1,23 +0,0 @@ -

Change your password

- -

- Your password has been reset. Choose a new password below. -

- -<%= error_messages_for :user %> - -<% form_for(:user, - :url => user_password_path(@user, :token => @user.token), - :html => { :method => :put }) do |form| %> -
- <%= form.label :password, "Choose password" %> - <%= form.password_field :password %> -
-
- <%= form.label :password_confirmation, "Confirm password" %> - <%= form.password_field :password_confirmation %> -
-
- <%= form.submit "Save this password", :disable_with => "Please wait..." %> -
-<% end %> diff --git a/vendor/plugins/clearance/app/views/passwords/new.html.erb b/vendor/plugins/clearance/app/views/passwords/new.html.erb deleted file mode 100644 index bd37d6d..0000000 --- a/vendor/plugins/clearance/app/views/passwords/new.html.erb +++ /dev/null @@ -1,15 +0,0 @@ -

Change your password

- -

- We will email you a link to change your password. -

- -<% form_for :password, :url => passwords_path do |form| %> -
- <%= form.label :email, "Email address" %> - <%= form.text_field :email %> -
-
- <%= form.submit "Reset password", :disable_with => "Please wait..." %> -
-<% end %> \ No newline at end of file diff --git a/vendor/plugins/clearance/app/views/sessions/new.html.erb b/vendor/plugins/clearance/app/views/sessions/new.html.erb deleted file mode 100644 index a1e5607..0000000 --- a/vendor/plugins/clearance/app/views/sessions/new.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -

Sign in

- -<% form_for :session, :url => session_path do |form| %> -
- <%= form.label :email %> - <%= form.text_field :email %> -
-
- <%= form.label :password %> - <%= form.password_field :password %> -
-
- <%= form.check_box :remember_me %> - <%= form.label :remember_me %> -
-
- <%= form.submit "Sign in", :disable_with => "Please wait..." %> -
-<% end %> - - \ No newline at end of file diff --git a/vendor/plugins/clearance/app/views/users/_form.html.erb b/vendor/plugins/clearance/app/views/users/_form.html.erb deleted file mode 100644 index 6a9b8e0..0000000 --- a/vendor/plugins/clearance/app/views/users/_form.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -<%= form.error_messages %> -
- <%= form.label :email %> - <%= form.text_field :email %> -
-
- <%= form.label :password %> - <%= form.password_field :password %> -
-
- <%= form.label :password_confirmation, "Confirm password" %> - <%= form.password_field :password_confirmation %> -
\ No newline at end of file diff --git a/vendor/plugins/clearance/app/views/users/new.html.erb b/vendor/plugins/clearance/app/views/users/new.html.erb deleted file mode 100644 index de2ebf7..0000000 --- a/vendor/plugins/clearance/app/views/users/new.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -

Sign up

- -<% form_for @user do |form| %> - <%= render :partial => '/users/form', :object => form %> - <%= form.submit 'Sign up', :disable_with => 'Please wait...' %> -<% end %> diff --git a/vendor/plugins/clearance/clearance.gemspec b/vendor/plugins/clearance/clearance.gemspec deleted file mode 100644 index e00b453..0000000 --- a/vendor/plugins/clearance/clearance.gemspec +++ /dev/null @@ -1,132 +0,0 @@ ---- !ruby/object:Gem::Specification -name: clearance -version: !ruby/object:Gem::Version - version: 0.6.9 -platform: ruby -authors: -- Dan Croak -- Mike Burns -- Jason Morrison -- Joe Ferris -- Eugene Bolshakov -- Nick Quaranto -- Josh Nichols -- Mike Breen -- "Marcel G\xC3\xB6rner" -- Bence Nagy -- Ben Mabey -- Eloy Duran -- Tim Pope -- Mihai Anca -- Mark Cornick -- Shay Arnett -autorequire: -bindir: bin -cert_chain: [] - -date: 2009-07-04 00:00:00 -04:00 -default_executable: -dependencies: [] - -description: Rails authentication with email & password. -email: support@thoughtbot.com -executables: [] - -extensions: [] - -extra_rdoc_files: [] - -files: -- CHANGELOG.textile -- LICENSE -- Rakefile -- README.textile -- TODO.textile -- app/controllers -- app/controllers/clearance -- app/controllers/clearance/confirmations_controller.rb -- app/controllers/clearance/passwords_controller.rb -- app/controllers/clearance/sessions_controller.rb -- app/controllers/clearance/users_controller.rb -- app/models -- app/models/clearance_mailer.rb -- app/views -- app/views/clearance_mailer -- app/views/clearance_mailer/change_password.html.erb -- app/views/clearance_mailer/confirmation.html.erb -- app/views/passwords -- app/views/passwords/edit.html.erb -- app/views/passwords/new.html.erb -- app/views/sessions -- app/views/sessions/new.html.erb -- app/views/users -- app/views/users/_form.html.erb -- app/views/users/new.html.erb -- config/clearance_routes.rb -- generators/clearance -- generators/clearance/clearance_generator.rb -- generators/clearance/lib -- generators/clearance/lib/insert_commands.rb -- generators/clearance/lib/rake_commands.rb -- generators/clearance/templates -- generators/clearance/templates/factories.rb -- generators/clearance/templates/migrations -- generators/clearance/templates/migrations/create_users.rb -- generators/clearance/templates/migrations/update_users.rb -- generators/clearance/templates/README -- generators/clearance/templates/user.rb -- generators/clearance/USAGE -- generators/clearance_features -- generators/clearance_features/clearance_features_generator.rb -- generators/clearance_features/templates -- generators/clearance_features/templates/features -- generators/clearance_features/templates/features/password_reset.feature -- generators/clearance_features/templates/features/sign_in.feature -- generators/clearance_features/templates/features/sign_out.feature -- generators/clearance_features/templates/features/sign_up.feature -- generators/clearance_features/templates/features/step_definitions -- generators/clearance_features/templates/features/step_definitions/clearance_steps.rb -- generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb -- generators/clearance_features/templates/features/support -- generators/clearance_features/templates/features/support/paths.rb -- generators/clearance_features/USAGE -- lib/clearance -- lib/clearance/authentication.rb -- lib/clearance/extensions -- lib/clearance/extensions/errors.rb -- lib/clearance/extensions/rescue.rb -- lib/clearance/extensions/routes.rb -- lib/clearance/user.rb -- lib/clearance.rb -- shoulda_macros/clearance.rb -- rails/init.rb -has_rdoc: true -homepage: http://github.com/thoughtbot/clearance -licenses: [] - -post_install_message: -rdoc_options: [] - -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -required_rubygems_version: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: "0" - version: -requirements: [] - -rubyforge_project: -rubygems_version: 1.3.4 -signing_key: -specification_version: 3 -summary: Rails authentication with email & password. -test_files: [] - diff --git a/vendor/plugins/clearance/config/clearance_routes.rb b/vendor/plugins/clearance/config/clearance_routes.rb deleted file mode 100644 index caeb5cc..0000000 --- a/vendor/plugins/clearance/config/clearance_routes.rb +++ /dev/null @@ -1,30 +0,0 @@ -ActionController::Routing::Routes.draw do |map| - map.resources :passwords, - :controller => 'clearance/passwords', - :only => [:new, :create] - - map.resource :session, - :controller => 'clearance/sessions', - :only => [:new, :create, :destroy] - - map.resources :users, :controller => 'clearance/users' do |users| - users.resource :password, - :controller => 'clearance/passwords', - :only => [:create, :edit, :update] - - users.resource :confirmation, - :controller => 'clearance/confirmations', - :only => [:new, :create] - end - - map.sign_up 'sign_up', - :controller => 'clearance/users', - :action => 'new' - map.sign_in 'sign_in', - :controller => 'clearance/sessions', - :action => 'new' - map.sign_out 'sign_out', - :controller => 'clearance/sessions', - :action => 'destroy', - :method => :delete -end diff --git a/vendor/plugins/clearance/generators/clearance/USAGE b/vendor/plugins/clearance/generators/clearance/USAGE deleted file mode 100644 index 3d9cabe..0000000 --- a/vendor/plugins/clearance/generators/clearance/USAGE +++ /dev/null @@ -1 +0,0 @@ -script/generate clearance \ No newline at end of file diff --git a/vendor/plugins/clearance/generators/clearance/clearance_generator.rb b/vendor/plugins/clearance/generators/clearance/clearance_generator.rb deleted file mode 100644 index d3704b7..0000000 --- a/vendor/plugins/clearance/generators/clearance/clearance_generator.rb +++ /dev/null @@ -1,41 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb") -require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb") -require 'factory_girl' - -class ClearanceGenerator < Rails::Generator::Base - - def manifest - record do |m| - m.insert_into "app/controllers/application_controller.rb", - "include Clearance::Authentication" - - user_model = "app/models/user.rb" - if File.exists?(user_model) - m.insert_into user_model, "include Clearance::User" - else - m.directory File.join("app", "models") - m.file "user.rb", user_model - end - - m.directory File.join("test", "factories") - m.file "factories.rb", "test/factories/clearance.rb" - - m.migration_template "migrations/#{migration_name}.rb", - 'db/migrate', - :migration_file_name => "clearance_#{migration_name}" - - m.readme "README" - end - end - - private - - def migration_name - if ActiveRecord::Base.connection.table_exists?(:users) - 'update_users' - else - 'create_users' - end - end - -end diff --git a/vendor/plugins/clearance/generators/clearance/lib/insert_commands.rb b/vendor/plugins/clearance/generators/clearance/lib/insert_commands.rb deleted file mode 100644 index cc76c56..0000000 --- a/vendor/plugins/clearance/generators/clearance/lib/insert_commands.rb +++ /dev/null @@ -1,33 +0,0 @@ -# Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master - -Rails::Generator::Commands::Base.class_eval do - def file_contains?(relative_destination, line) - File.read(destination_path(relative_destination)).include?(line) - end -end - -Rails::Generator::Commands::Create.class_eval do - def insert_into(file, line) - logger.insert "#{line} into #{file}" - unless options[:pretend] || file_contains?(file, line) - gsub_file file, /^(class|module) .+$/ do |match| - "#{match}\n #{line}" - end - end - end -end - -Rails::Generator::Commands::Destroy.class_eval do - def insert_into(file, line) - logger.remove "#{line} from #{file}" - unless options[:pretend] - gsub_file file, "\n #{line}", '' - end - end -end - -Rails::Generator::Commands::List.class_eval do - def insert_into(file, line) - logger.insert "#{line} into #{file}" - end -end diff --git a/vendor/plugins/clearance/generators/clearance/lib/rake_commands.rb b/vendor/plugins/clearance/generators/clearance/lib/rake_commands.rb deleted file mode 100644 index a9fd417..0000000 --- a/vendor/plugins/clearance/generators/clearance/lib/rake_commands.rb +++ /dev/null @@ -1,22 +0,0 @@ -Rails::Generator::Commands::Create.class_eval do - def rake_db_migrate - logger.rake "db:migrate" - unless system("rake db:migrate") - logger.rake "db:migrate failed. Rolling back" - command(:destroy).invoke! - end - end -end - -Rails::Generator::Commands::Destroy.class_eval do - def rake_db_migrate - logger.rake "db:rollback" - system "rake db:rollback" - end -end - -Rails::Generator::Commands::List.class_eval do - def rake_db_migrate - logger.rake "db:migrate" - end -end diff --git a/vendor/plugins/clearance/generators/clearance/templates/README b/vendor/plugins/clearance/generators/clearance/templates/README deleted file mode 100644 index 17850c8..0000000 --- a/vendor/plugins/clearance/generators/clearance/templates/README +++ /dev/null @@ -1,22 +0,0 @@ - -******************************************************************************* - -Ok, enough fancy automatic stuff. Time for some old school monkey copy-pasting. - -1. Define a HOST constant in your environments files. -In config/environments/test.rb and config/environments/development.rb it can be: - - HOST = "localhost" - -In production.rb it must be the actual host your application is deployed to. -The constant is used by mailers to generate URLs in emails. - -2. In config/environment.rb: - - DO_NOT_REPLY = "donotreply@example.com" - -3. Define root_url to *something* in your config/routes.rb: - - map.root :controller => 'home' - -******************************************************************************* diff --git a/vendor/plugins/clearance/generators/clearance/templates/factories.rb b/vendor/plugins/clearance/generators/clearance/templates/factories.rb deleted file mode 100644 index 9bdd13a..0000000 --- a/vendor/plugins/clearance/generators/clearance/templates/factories.rb +++ /dev/null @@ -1,13 +0,0 @@ -Factory.sequence :email do |n| - "user#{n}@example.com" -end - -Factory.define :user do |user| - user.email { Factory.next :email } - user.password { "password" } - user.password_confirmation { "password" } -end - -Factory.define :email_confirmed_user, :parent => :user do |user| - user.email_confirmed { true } -end diff --git a/vendor/plugins/clearance/generators/clearance/templates/migrations/create_users.rb b/vendor/plugins/clearance/generators/clearance/templates/migrations/create_users.rb deleted file mode 100644 index 22e921a..0000000 --- a/vendor/plugins/clearance/generators/clearance/templates/migrations/create_users.rb +++ /dev/null @@ -1,21 +0,0 @@ -class ClearanceCreateUsers < ActiveRecord::Migration - def self.up - create_table(:users) do |t| - t.string :email - t.string :encrypted_password, :limit => 128 - t.string :salt, :limit => 128 - t.string :token, :limit => 128 - t.datetime :token_expires_at - t.boolean :email_confirmed, :default => false, :null => false - t.timestamps - end - - add_index :users, [:id, :token] - add_index :users, :email - add_index :users, :token - end - - def self.down - drop_table :users - end -end diff --git a/vendor/plugins/clearance/generators/clearance/templates/migrations/update_users.rb b/vendor/plugins/clearance/generators/clearance/templates/migrations/update_users.rb deleted file mode 100644 index 4a329fa..0000000 --- a/vendor/plugins/clearance/generators/clearance/templates/migrations/update_users.rb +++ /dev/null @@ -1,41 +0,0 @@ -class ClearanceUpdateUsers < ActiveRecord::Migration - def self.up -<% - existing_columns = ActiveRecord::Base.connection.columns(:users).collect { |each| each.name } - columns = [ - [:email, 't.string :email'], - [:encrypted_password, 't.string :encrypted_password, :limit => 128'], - [:salt, 't.string :salt, :limit => 128'], - [:token, 't.string :token, :limit => 128'], - [:token_expires_at, 't.datetime :token_expires_at'], - [:email_confirmed, 't.boolean :email_confirmed, :default => false, :null => false'] - ].delete_if {|c| existing_columns.include?(c.first.to_s)} --%> - change_table(:users) do |t| -<% columns.each do |c| -%> - <%= c.last %> -<% end -%> - end - -<% - existing_indexes = ActiveRecord::Base.connection.indexes(:users) - index_names = existing_indexes.collect { |each| each.name } - new_indexes = [ - [:index_users_on_id_and_token, 'add_index :users, [:id, :token]'], - [:index_users_on_email, 'add_index :users, :email'], - [:index_users_on_token, 'add_index :users, :token'] - ].delete_if { |each| index_names.include?(each.first.to_s) } --%> -<% new_indexes.each do |each| -%> - <%= each.last %> -<% end -%> - end - - def self.down - change_table(:users) do |t| -<% unless columns.empty? -%> - t.remove <%= columns.collect { |each| ":#{each.first}" }.join(',') %> -<% end -%> - end - end -end diff --git a/vendor/plugins/clearance/generators/clearance/templates/user.rb b/vendor/plugins/clearance/generators/clearance/templates/user.rb deleted file mode 100644 index 6d077a1..0000000 --- a/vendor/plugins/clearance/generators/clearance/templates/user.rb +++ /dev/null @@ -1,3 +0,0 @@ -class User < ActiveRecord::Base - include Clearance::User -end diff --git a/vendor/plugins/clearance/generators/clearance_features/USAGE b/vendor/plugins/clearance/generators/clearance_features/USAGE deleted file mode 100644 index 3758c0b..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/USAGE +++ /dev/null @@ -1 +0,0 @@ -script/generate clearance_features diff --git a/vendor/plugins/clearance/generators/clearance_features/clearance_features_generator.rb b/vendor/plugins/clearance/generators/clearance_features/clearance_features_generator.rb deleted file mode 100644 index f2b43ea..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/clearance_features_generator.rb +++ /dev/null @@ -1,20 +0,0 @@ -class ClearanceFeaturesGenerator < Rails::Generator::Base - - def manifest - record do |m| - m.directory File.join("features", "step_definitions") - m.directory File.join("features", "support") - - ["features/step_definitions/clearance_steps.rb", - "features/step_definitions/factory_girl_steps.rb", - "features/support/paths.rb", - "features/sign_in.feature", - "features/sign_out.feature", - "features/sign_up.feature", - "features/password_reset.feature"].each do |file| - m.file file, file - end - end - end - -end diff --git a/vendor/plugins/clearance/generators/clearance_features/templates/features/password_reset.feature b/vendor/plugins/clearance/generators/clearance_features/templates/features/password_reset.feature deleted file mode 100644 index 51b77f7..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/templates/features/password_reset.feature +++ /dev/null @@ -1,33 +0,0 @@ -Feature: Password reset - In order to sign in even if user forgot their password - A user - Should be able to reset it - - Scenario: User is not signed up - Given no user exists with an email of "email@person.com" - When I request password reset link to be sent to "email@person.com" - Then I should see "Unknown email" - - Scenario: User is signed up and requests password reset - Given I signed up with "email@person.com/password" - When I request password reset link to be sent to "email@person.com" - Then I should see "instructions for changing your password" - And a password reset message should be sent to "email@person.com" - - Scenario: User is signed up updated his password and types wrong confirmation - Given I signed up with "email@person.com/password" - When I follow the password reset link sent to "email@person.com" - And I update my password with "newpassword/wrongconfirmation" - Then I should see error messages - And I should be signed out - - Scenario: User is signed up and updates his password - Given I signed up with "email@person.com/password" - When I follow the password reset link sent to "email@person.com" - And I update my password with "newpassword/newpassword" - Then I should be signed in - When I sign out - Then I should be signed out - And I sign in as "email@person.com/newpassword" - Then I should be signed in - diff --git a/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_in.feature b/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_in.feature deleted file mode 100644 index 4b44c39..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_in.feature +++ /dev/null @@ -1,42 +0,0 @@ -Feature: Sign in - In order to get access to protected sections of the site - A user - Should be able to sign in - - Scenario: User is not signed up - Given no user exists with an email of "email@person.com" - When I go to the sign in page - And I sign in as "email@person.com/password" - Then I should see "Bad email or password" - And I should be signed out - - Scenario: User is not confirmed - Given I signed up with "email@person.com/password" - When I go to the sign in page - And I sign in as "email@person.com/password" - Then I should see "User has not confirmed email" - And I should be signed out - - Scenario: User enters wrong password - Given I am signed up and confirmed as "email@person.com/password" - When I go to the sign in page - And I sign in as "email@person.com/wrongpassword" - Then I should see "Bad email or password" - And I should be signed out - - Scenario: User signs in successfully - Given I am signed up and confirmed as "email@person.com/password" - When I go to the sign in page - And I sign in as "email@person.com/password" - Then I should see "Signed in" - And I should be signed in - - Scenario: User signs in and checks "remember me" - Given I am signed up and confirmed as "email@person.com/password" - When I go to the sign in page - And I sign in with "remember me" as "email@person.com/password" - Then I should see "Signed in" - And I should be signed in - When I return next time - Then I should be signed in - diff --git a/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_out.feature b/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_out.feature deleted file mode 100644 index 2107226..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_out.feature +++ /dev/null @@ -1,23 +0,0 @@ -Feature: Sign out - To protect my account from unauthorized access - A signed in user - Should be able to sign out - - Scenario: User signs out - Given I am signed up and confirmed as "email@person.com/password" - When I sign in as "email@person.com/password" - Then I should be signed in - And I sign out - Then I should see "Signed out" - And I should be signed out - - Scenario: User who was remembered signs out - Given I am signed up and confirmed as "email@person.com/password" - When I sign in with "remember me" as "email@person.com/password" - Then I should be signed in - And I sign out - Then I should see "Signed out" - And I should be signed out - When I return next time - Then I should be signed out - diff --git a/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_up.feature b/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_up.feature deleted file mode 100644 index 27492d9..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/templates/features/sign_up.feature +++ /dev/null @@ -1,28 +0,0 @@ -Feature: Sign up - In order to get access to protected sections of the site - A user - Should be able to sign up - - Scenario: User signs up with invalid data - When I go to the sign up page - And I fill in "Email" with "invalidemail" - And I fill in "Password" with "password" - And I fill in "Confirm password" with "" - And I press "Sign Up" - Then I should see error messages - - Scenario: User signs up with valid data - When I go to the sign up page - And I fill in "Email" with "email@person.com" - And I fill in "Password" with "password" - And I fill in "Confirm password" with "password" - And I press "Sign Up" - Then I should see "instructions for confirming" - And a confirmation message should be sent to "email@person.com" - - Scenario: User confirms his account - Given I signed up with "email@person.com/password" - When I follow the confirmation link sent to "email@person.com" - Then I should see "Confirmed email and signed in" - And I should be signed in - diff --git a/vendor/plugins/clearance/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb b/vendor/plugins/clearance/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb deleted file mode 100644 index 52ac7f4..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb +++ /dev/null @@ -1,110 +0,0 @@ -# General - -Then /^I should see error messages$/ do - assert_match /error(s)? prohibited/m, response.body -end - -# Database - -Given /^no user exists with an email of "(.*)"$/ do |email| - assert_nil User.find_by_email(email) -end - -Given /^I signed up with "(.*)\/(.*)"$/ do |email, password| - user = Factory :user, - :email => email, - :password => password, - :password_confirmation => password -end - -Given /^I am signed up and confirmed as "(.*)\/(.*)"$/ do |email, password| - user = Factory :email_confirmed_user, - :email => email, - :password => password, - :password_confirmation => password -end - -# Session - -Then /^I should be signed in$/ do - assert controller.signed_in? -end - -Then /^I should be signed out$/ do - assert ! controller.signed_in? -end - -When /^session is cleared$/ do - request.reset_session - controller.instance_variable_set(:@_current_user, nil) -end - -# Emails - -Then /^a confirmation message should be sent to "(.*)"$/ do |email| - user = User.find_by_email(email) - sent = ActionMailer::Base.deliveries.first - assert_equal [user.email], sent.to - assert_match /confirm/i, sent.subject - assert !user.token.blank? - assert_match /#{user.token}/, sent.body -end - -When /^I follow the confirmation link sent to "(.*)"$/ do |email| - user = User.find_by_email(email) - visit new_user_confirmation_path(:user_id => user, :token => user.token) -end - -Then /^a password reset message should be sent to "(.*)"$/ do |email| - user = User.find_by_email(email) - sent = ActionMailer::Base.deliveries.first - assert_equal [user.email], sent.to - assert_match /password/i, sent.subject - assert !user.token.blank? - assert_match /#{user.token}/, sent.body -end - -When /^I follow the password reset link sent to "(.*)"$/ do |email| - user = User.find_by_email(email) - visit edit_user_password_path(:user_id => user, :token => user.token) -end - -When /^I try to change the password of "(.*)" without token$/ do |email| - user = User.find_by_email(email) - visit edit_user_password_path(:user_id => user) -end - -Then /^I should be forbidden$/ do - assert_response :forbidden -end - -# Actions - -When /^I sign in( with "remember me")? as "(.*)\/(.*)"$/ do |remember, email, password| - When %{I go to the sign in page} - And %{I fill in "Email" with "#{email}"} - And %{I fill in "Password" with "#{password}"} - And %{I check "Remember me"} if remember - And %{I press "Sign In"} -end - -When /^I sign out$/ do - visit '/session', :delete -end - -When /^I request password reset link to be sent to "(.*)"$/ do |email| - When %{I go to the password reset request page} - And %{I fill in "Email address" with "#{email}"} - And %{I press "Reset password"} -end - -When /^I update my password with "(.*)\/(.*)"$/ do |password, confirmation| - And %{I fill in "Choose password" with "#{password}"} - And %{I fill in "Confirm password" with "#{confirmation}"} - And %{I press "Save this password"} -end - -When /^I return next time$/ do - When %{session is cleared} - And %{I go to the homepage} -end diff --git a/vendor/plugins/clearance/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb b/vendor/plugins/clearance/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb deleted file mode 100644 index 6337f66..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb +++ /dev/null @@ -1,5 +0,0 @@ -Factory.factories.each do |name, factory| - Given /^an? #{name} exists with an? (.*) of "([^"]*)"$/ do |attr, value| - Factory(name, attr.gsub(' ', '_') => value) - end -end diff --git a/vendor/plugins/clearance/generators/clearance_features/templates/features/support/paths.rb b/vendor/plugins/clearance/generators/clearance_features/templates/features/support/paths.rb deleted file mode 100644 index 62ba3d5..0000000 --- a/vendor/plugins/clearance/generators/clearance_features/templates/features/support/paths.rb +++ /dev/null @@ -1,22 +0,0 @@ -module NavigationHelpers - def path_to(page_name) - case page_name - - when /the homepage/i - root_path - when /the sign up page/i - new_user_path - when /the sign in page/i - new_session_path - when /the password reset request page/i - new_password_path - - # Add more page name => path mappings here - - else - raise "Can't find mapping from \"#{page_name}\" to a path." - end - end -end - -World(NavigationHelpers) diff --git a/vendor/plugins/clearance/lib/clearance.rb b/vendor/plugins/clearance/lib/clearance.rb deleted file mode 100644 index 260c4d6..0000000 --- a/vendor/plugins/clearance/lib/clearance.rb +++ /dev/null @@ -1,6 +0,0 @@ -require 'clearance/extensions/errors' -require 'clearance/extensions/rescue' -require 'clearance/extensions/routes' - -require 'clearance/authentication' -require 'clearance/user' diff --git a/vendor/plugins/clearance/lib/clearance/authentication.rb b/vendor/plugins/clearance/lib/clearance/authentication.rb deleted file mode 100644 index 48143f2..0000000 --- a/vendor/plugins/clearance/lib/clearance/authentication.rb +++ /dev/null @@ -1,100 +0,0 @@ -module Clearance - module Authentication - - def self.included(controller) - controller.send(:include, InstanceMethods) - - controller.class_eval do - helper_method :current_user - helper_method :signed_in? - - hide_action :current_user, :signed_in? - end - end - - module InstanceMethods - def current_user - @_current_user ||= (user_from_cookie || user_from_session) - end - - def signed_in? - ! current_user.nil? - end - - protected - - def authenticate - deny_access unless signed_in? - end - - def user_from_session - if session[:user_id] - return nil unless user = ::User.find_by_id(session[:user_id]) - return user if user.email_confirmed? - end - end - - def user_from_cookie - if token = cookies[:remember_token] - return nil unless user = ::User.find_by_token(token) - return user if user.remember? - end - end - - def sign_user_in(user) - warn "[DEPRECATION] sign_user_in: unnecessary. use sign_in(user) instead." - sign_in(user) - end - - def sign_in(user) - if user - session[:user_id] = user.id - end - end - - def remember? - params[:session] && params[:session][:remember_me] == "1" - end - - def remember(user) - user.remember_me! - cookies[:remember_token] = { :value => user.token, - :expires => user.token_expires_at } - end - - def forget(user) - user.forget_me! if user - cookies.delete(:remember_token) - reset_session - end - - def redirect_back_or(default) - redirect_to(return_to || default) - clear_return_to - end - - def return_to - session[:return_to] || params[:return_to] - end - - def clear_return_to - session[:return_to] = nil - end - - def redirect_to_root - redirect_to(root_url) - end - - def store_location - session[:return_to] = request.request_uri if request.get? - end - - def deny_access(flash_message = nil, opts = {}) - store_location - flash[:failure] = flash_message if flash_message - redirect_to(new_session_url) - end - end - - end -end diff --git a/vendor/plugins/clearance/lib/clearance/extensions/errors.rb b/vendor/plugins/clearance/lib/clearance/extensions/errors.rb deleted file mode 100644 index d6b19bf..0000000 --- a/vendor/plugins/clearance/lib/clearance/extensions/errors.rb +++ /dev/null @@ -1,6 +0,0 @@ -if defined?(ActionController) - module ActionController - class Forbidden < StandardError - end - end -end diff --git a/vendor/plugins/clearance/lib/clearance/extensions/rescue.rb b/vendor/plugins/clearance/lib/clearance/extensions/rescue.rb deleted file mode 100644 index 7afe4ad..0000000 --- a/vendor/plugins/clearance/lib/clearance/extensions/rescue.rb +++ /dev/null @@ -1,3 +0,0 @@ -if defined?(ActionController::Base) - ActionController::Base.rescue_responses.update('ActionController::Forbidden' => :forbidden) -end diff --git a/vendor/plugins/clearance/lib/clearance/extensions/routes.rb b/vendor/plugins/clearance/lib/clearance/extensions/routes.rb deleted file mode 100644 index 1a6c43b..0000000 --- a/vendor/plugins/clearance/lib/clearance/extensions/routes.rb +++ /dev/null @@ -1,14 +0,0 @@ -if defined?(ActionController::Routing::RouteSet) - class ActionController::Routing::RouteSet - def load_routes_with_clearance! - lib_path = File.dirname(__FILE__) - clearance_routes = File.join(lib_path, *%w[.. .. .. config clearance_routes.rb]) - unless configuration_files.include?(clearance_routes) - add_configuration_file(clearance_routes) - end - load_routes_without_clearance! - end - - alias_method_chain :load_routes!, :clearance - end -end diff --git a/vendor/plugins/clearance/lib/clearance/user.rb b/vendor/plugins/clearance/lib/clearance/user.rb deleted file mode 100644 index f6206e9..0000000 --- a/vendor/plugins/clearance/lib/clearance/user.rb +++ /dev/null @@ -1,143 +0,0 @@ -require 'digest/sha1' - -module Clearance - module User - - def self.included(model) - model.extend(ClassMethods) - - model.send(:include, InstanceMethods) - model.send(:include, AttrAccessible) - model.send(:include, AttrAccessor) - model.send(:include, Validations) - model.send(:include, Callbacks) - end - - module AttrAccessible - def self.included(model) - model.class_eval do - attr_accessible :email, :password, :password_confirmation - end - end - end - - module AttrAccessor - def self.included(model) - model.class_eval do - attr_accessor :password, :password_confirmation - end - end - end - - module Validations - def self.included(model) - model.class_eval do - validates_presence_of :email - validates_uniqueness_of :email, :case_sensitive => false - validates_format_of :email, :with => %r{.+@.+\..+} - - validates_presence_of :password, :if => :password_required? - validates_confirmation_of :password, :if => :password_required? - end - end - end - - module Callbacks - def self.included(model) - model.class_eval do - before_save :initialize_salt, :encrypt_password, :initialize_token - end - end - end - - module InstanceMethods - def authenticated?(password) - encrypted_password == encrypt(password) - end - - def encrypt(string) - generate_hash("--#{salt}--#{string}--") - end - - def remember? - token_expires_at && Time.now.utc < token_expires_at - end - - def remember_me! - remember_me_until! 2.weeks.from_now.utc - end - - def forget_me! - clear_token - save(false) - end - - def confirm_email! - self.email_confirmed = true - self.token = nil - save(false) - end - - def forgot_password! - generate_token - save(false) - end - - def update_password(new_password, new_password_confirmation) - self.password = new_password - self.password_confirmation = new_password_confirmation - clear_token if valid? - save - end - - protected - - def generate_hash(string) - Digest::SHA1.hexdigest(string) - end - - def initialize_salt - if new_record? - self.salt = generate_hash("--#{Time.now.utc.to_s}--#{password}--") - end - end - - def encrypt_password - return if password.blank? - self.encrypted_password = encrypt(password) - end - - def generate_token - self.token = encrypt("--#{Time.now.utc.to_s}--#{password}--") - self.token_expires_at = nil - end - - def clear_token - self.token = nil - self.token_expires_at = nil - end - - def initialize_token - generate_token if new_record? - end - - def password_required? - encrypted_password.blank? || !password.blank? - end - - def remember_me_until!(time) - self.token_expires_at = time - self.token = encrypt("--#{token_expires_at}--#{password}--") - save(false) - end - end - - module ClassMethods - def authenticate(email, password) - return nil unless user = find_by_email(email) - return user if user.authenticated?(password) - end - end - - end -end diff --git a/vendor/plugins/clearance/rails/init.rb b/vendor/plugins/clearance/rails/init.rb deleted file mode 100644 index 5ed1d1b..0000000 --- a/vendor/plugins/clearance/rails/init.rb +++ /dev/null @@ -1 +0,0 @@ -require 'clearance' \ No newline at end of file diff --git a/vendor/plugins/clearance/shoulda_macros/clearance.rb b/vendor/plugins/clearance/shoulda_macros/clearance.rb deleted file mode 100644 index cc44b7d..0000000 --- a/vendor/plugins/clearance/shoulda_macros/clearance.rb +++ /dev/null @@ -1,262 +0,0 @@ -module Clearance - module Shoulda - - # STATE OF AUTHENTICATION - - def should_be_signed_in_as(&block) - should "be signed in as #{block.bind(self).call}" do - user = block.bind(self).call - assert_not_nil user, - "please pass a User. try: should_be_signed_in_as { @user }" - assert_equal user, @controller.send(:current_user), - "#{user.inspect} is not the current_user, " << - "which is #{@controller.send(:current_user).inspect}" - end - end - - def should_be_signed_in_and_email_confirmed_as(&block) - warn "[DEPRECATION] should_be_signed_in_and_email_confirmed_as: questionable usefulness" - should_be_signed_in_as &block - - should "have confirmed email" do - user = block.bind(self).call - - assert_not_nil user - assert_equal user, assigns(:user) - assert assigns(:user).email_confirmed? - end - end - - def should_not_be_signed_in - should "not be signed in" do - assert_nil session[:user_id] - end - end - - def should_deny_access_on(http_method, action, opts = {}) - warn "[DEPRECATION] should_deny_access_on: use a setup & should_deny_access(:flash => ?)" - flash_message = opts.delete(:flash) - context "on #{http_method} to #{action}" do - setup do - send(http_method, action, opts) - end - - should_deny_access(:flash => flash_message) - end - end - - def should_deny_access(opts = {}) - if opts[:flash] - should_set_the_flash_to opts[:flash] - else - should_not_set_the_flash - end - - should_redirect_to('new_session_url') { new_session_url } - end - - # HTTP FLUENCY - - def should_forbid(description, &block) - should "forbid #{description}" do - assert_raises ActionController::Forbidden do - instance_eval(&block) - end - end - end - - # CONTEXTS - - def signed_in_user_context(&blk) - warn "[DEPRECATION] signed_in_user_context: creates a Mystery Guest, causes Obscure Test" - context "A signed in user" do - setup do - @user = Factory(:user) - @user.confirm_email! - sign_in_as @user - end - merge_block(&blk) - end - end - - def public_context(&blk) - warn "[DEPRECATION] public_context: common case is no-op. call sign_out otherwise" - context "The public" do - setup { sign_out } - merge_block(&blk) - end - end - - # CREATING USERS - - def should_create_user_successfully - warn "[DEPRECATION] should_create_user_successfully: not meant to be public, no longer used internally" - should_assign_to :user - should_change 'User.count', :by => 1 - - should "send the confirmation email" do - assert_sent_email do |email| - email.subject =~ /account confirmation/i - end - end - - should_set_the_flash_to /confirm/i - should_redirect_to_url_after_create - end - - # RENDERING - - def should_render_nothing - should "render nothing" do - assert @response.body.blank? - end - end - - # REDIRECTS - - def should_redirect_to_url_after_create - should_redirect_to("the post-create url") do - @controller.send(:url_after_create) - end - end - - def should_redirect_to_url_after_update - should_redirect_to("the post-update url") do - @controller.send(:url_after_update) - end - end - - def should_redirect_to_url_after_destroy - should_redirect_to("the post-destroy url") do - @controller.send(:url_after_destroy) - end - end - - # VALIDATIONS - - def should_validate_confirmation_of(attribute, opts = {}) - warn "[DEPRECATION] should_validate_confirmation_of: not meant to be public, no longer used internally" - raise ArgumentError if opts[:factory].nil? - - context "on save" do - should_validate_confirmation_is_not_blank opts[:factory], attribute - should_validate_confirmation_is_not_bad opts[:factory], attribute - end - end - - def should_validate_confirmation_is_not_blank(factory, attribute, opts = {}) - warn "[DEPRECATION] should_validate_confirmation_is_not_blank: not meant to be public, no longer used internally" - should "validate #{attribute}_confirmation is not blank" do - model = Factory.build(factory, blank_confirmation_options(attribute)) - model.save - assert_confirmation_error(model, attribute, - "#{attribute}_confirmation cannot be blank") - end - end - - def should_validate_confirmation_is_not_bad(factory, attribute, opts = {}) - warn "[DEPRECATION] should_validate_confirmation_is_not_bad: not meant to be public, no longer used internally" - should "validate #{attribute}_confirmation is different than #{attribute}" do - model = Factory.build(factory, bad_confirmation_options(attribute)) - model.save - assert_confirmation_error(model, attribute, - "#{attribute}_confirmation cannot be different than #{attribute}") - end - end - - # FORMS - - def should_display_a_password_update_form - warn "[DEPRECATION] should_display_a_password_update_form: not meant to be public, no longer used internally" - should "have a form for the user's token, password, and password confirm" do - update_path = ERB::Util.h( - user_password_path(@user, :token => @user.token) - ) - - assert_select 'form[action=?]', update_path do - assert_select 'input[name=_method][value=?]', 'put' - assert_select 'input[name=?]', 'user[password]' - assert_select 'input[name=?]', 'user[password_confirmation]' - end - end - end - - def should_display_a_sign_up_form - warn "[DEPRECATION] should_display_a_sign_up_form: not meant to be public, no longer used internally" - should "display a form to sign up" do - assert_select "form[action=#{users_path}][method=post]", - true, "There must be a form to sign up" do - assert_select "input[type=text][name=?]", - "user[email]", true, "There must be an email field" - assert_select "input[type=password][name=?]", - "user[password]", true, "There must be a password field" - assert_select "input[type=password][name=?]", - "user[password_confirmation]", true, "There must be a password confirmation field" - assert_select "input[type=submit]", true, - "There must be a submit button" - end - end - end - - def should_display_a_sign_in_form - warn "[DEPRECATION] should_display_a_sign_in_form: not meant to be public, no longer used internally" - should 'display a "sign in" form' do - assert_select "form[action=#{session_path}][method=post]", - true, "There must be a form to sign in" do - assert_select "input[type=text][name=?]", - "session[email]", true, "There must be an email field" - assert_select "input[type=password][name=?]", - "session[password]", true, "There must be a password field" - assert_select "input[type=checkbox][name=?]", - "session[remember_me]", true, "There must be a 'remember me' check box" - assert_select "input[type=submit]", true, - "There must be a submit button" - end - end - end - end -end - -module Clearance - module Shoulda - module Helpers - def sign_in_as(user) - @controller.class_eval { attr_accessor :current_user } - @controller.current_user = user - return user - end - - def sign_in - sign_in_as Factory(:email_confirmed_user) - end - - def sign_out - @controller.class_eval { attr_accessor :current_user } - @controller.current_user = nil - end - - def blank_confirmation_options(attribute) - warn "[DEPRECATION] blank_confirmation_options: not meant to be public, no longer used internally" - opts = { attribute => attribute.to_s } - opts.merge("#{attribute}_confirmation".to_sym => "") - end - - def bad_confirmation_options(attribute) - warn "[DEPRECATION] bad_confirmation_options: not meant to be public, no longer used internally" - opts = { attribute => attribute.to_s } - opts.merge("#{attribute}_confirmation".to_sym => "not_#{attribute}") - end - - def assert_confirmation_error(model, attribute, message = "confirmation error") - warn "[DEPRECATION] assert_confirmation_error: not meant to be public, no longer used internally" - assert model.errors.on(attribute).include?("doesn't match confirmation"), - message - end - end - end -end - -class Test::Unit::TestCase - include Clearance::Shoulda::Helpers -end -Test::Unit::TestCase.extend(Clearance::Shoulda) diff --git a/vendor/plugins/clearance/test/controllers/confirmations_controller_test.rb b/vendor/plugins/clearance/test/controllers/confirmations_controller_test.rb deleted file mode 100644 index d412707..0000000 --- a/vendor/plugins/clearance/test/controllers/confirmations_controller_test.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'test_helper' - -class ConfirmationsControllerTest < ActionController::TestCase - - tests Clearance::ConfirmationsController - - should_filter_params :token - - context "a user whose email has not been confirmed" do - setup { @user = Factory(:user) } - - should "have a token" do - assert_not_nil @user.token - assert_not_equal "", @user.token - end - - context "on GET to #new with correct id and token" do - setup do - get :new, :user_id => @user.to_param, :token => @user.token - end - - should_set_the_flash_to /confirmed email/i - should_set_the_flash_to /signed in/i - should_be_signed_in_and_email_confirmed_as { @user } - should_redirect_to_url_after_create - end - - context "with an incorrect token" do - setup do - @bad_token = "bad token" - assert_not_equal @bad_token, @user.token - end - - should_forbid "on GET to #new with incorrect token" do - get :new, :user_id => @user.to_param, :token => @bad_token - end - end - - should_forbid "on GET to #new with blank token" do - get :new, :user_id => @user.to_param, :token => "" - end - - should_forbid "on GET to #new with no token" do - get :new, :user_id => @user.to_param - end - end - - context "a user with email confirmed" do - setup { @user = Factory(:email_confirmed_user) } - - should_forbid "on GET to #new with correct id" do - get :new, :user_id => @user.to_param - end - end - - context "no users" do - setup { assert_equal 0, ::User.count } - - should_forbid "on GET to #new with nonexistent id and token" do - get :new, :user_id => '123', :token => '123' - end - end - -end diff --git a/vendor/plugins/clearance/test/controllers/passwords_controller_test.rb b/vendor/plugins/clearance/test/controllers/passwords_controller_test.rb deleted file mode 100644 index e42f981..0000000 --- a/vendor/plugins/clearance/test/controllers/passwords_controller_test.rb +++ /dev/null @@ -1,175 +0,0 @@ -require 'test_helper' - -class PasswordsControllerTest < ActionController::TestCase - - tests Clearance::PasswordsController - - should_route :get, '/users/1/password/edit', - :controller => 'clearance/passwords', :action => 'edit', :user_id => '1' - - context "a signed up user" do - setup do - @user = Factory(:user) - end - - context "on GET to #new" do - setup { get :new, :user_id => @user.to_param } - - should_respond_with :success - should_render_template "new" - end - - context "on POST to #create" do - context "with correct email address" do - setup do - ActionMailer::Base.deliveries.clear - post :create, :password => { :email => @user.email } - end - - should "generate a token for the change your password email" do - assert_not_nil @user.reload.token - end - - should "send the change your password email" do - assert_sent_email do |email| - email.subject =~ /change your password/i - end - end - - should_set_the_flash_to /password/i - should_redirect_to_url_after_create - end - - context "with incorrect email address" do - setup do - email = "user1@example.com" - assert ! ::User.exists?(['email = ?', email]) - ActionMailer::Base.deliveries.clear - assert_equal @user.token, @user.reload.token - - post :create, :password => { :email => email } - end - - should "not generate a token for the change your password email" do - assert_equal @user.token, @user.reload.token - end - - should "not send a password reminder email" do - assert ActionMailer::Base.deliveries.empty? - end - - should "set the failure flash to Unknown email" do - assert_match /unknown email/i, flash.now[:failure] - end - - should_render_template :new - end - end - end - - context "a signed up user and forgotten password" do - setup do - @user = Factory(:user) - @user.forgot_password! - end - - context "on GET to #edit with correct id and token" do - setup do - get :edit, :user_id => @user.to_param, :token => @user.token - end - - should "find the user" do - assert_equal @user, assigns(:user) - end - - should_respond_with :success - should_render_template "edit" - should_display_a_password_update_form - end - - should_forbid "on GET to #edit with correct id but blank token" do - get :edit, :user_id => @user.to_param, :token => "" - end - - should_forbid "on GET to #edit with correct id but no token" do - get :edit, :user_id => @user.to_param - end - - context "on PUT to #update with matching password and password confirmation" do - setup do - new_password = "new_password" - @encrypted_new_password = @user.encrypt(new_password) - assert_not_equal @encrypted_new_password, @user.encrypted_password - - put(:update, - :user_id => @user, - :token => @user.token, - :user => { - :password => new_password, - :password_confirmation => new_password - }) - @user.reload - end - - should "update password" do - assert_equal @encrypted_new_password, @user.encrypted_password - end - - should "clear token" do - assert_nil @user.token - end - - should_be_signed_in_as { @user } - should_set_the_flash_to(/signed in/i) - should_redirect_to_url_after_update - end - - context "on PUT to #update with password but blank password confirmation" do - setup do - new_password = "new_password" - @encrypted_new_password = @user.encrypt(new_password) - - put(:update, - :user_id => @user.to_param, - :token => @user.token, - :user => { - :password => new_password, - :password_confirmation => '' - }) - @user.reload - end - - should "not update password" do - assert_not_equal @encrypted_new_password, @user.encrypted_password - end - - should "not clear token" do - assert_not_nil @user.token - end - - should_not_be_signed_in - should_not_set_the_flash - should_respond_with :success - should_render_template :edit - - should_display_a_password_update_form - end - - should_forbid "on PUT to #update with id but no token" do - put :update, :user_id => @user.to_param, :token => "" - end - end - - context "given two users and user one signs in" do - setup do - @user_one = Factory(:user) - @user_two = Factory(:user) - sign_in_as @user_one - end - - should_forbid "when user one tries to change user two's password on GET with no token" do - get :edit, :user_id => @user_two.to_param - end - end - -end diff --git a/vendor/plugins/clearance/test/controllers/sessions_controller_test.rb b/vendor/plugins/clearance/test/controllers/sessions_controller_test.rb deleted file mode 100644 index 6a1cccb..0000000 --- a/vendor/plugins/clearance/test/controllers/sessions_controller_test.rb +++ /dev/null @@ -1,178 +0,0 @@ -require 'test_helper' - -class SessionsControllerTest < ActionController::TestCase - - tests Clearance::SessionsController - - should_filter_params :password - - context "on GET to /sessions/new" do - setup { get :new } - - should_respond_with :success - should_render_template :new - should_not_set_the_flash - should_display_a_sign_in_form - end - - context "on POST to #create with unconfirmed credentials" do - setup do - @user = Factory(:user) - ActionMailer::Base.deliveries.clear - post :create, :session => { - :email => @user.email, - :password => @user.password } - end - - should_deny_access(:flash => /User has not confirmed email. Confirmation email will be resent./i) - - should "send the confirmation email" do - assert_not_nil email = ActionMailer::Base.deliveries[0] - assert_match /account confirmation/i, email.subject - end - end - - context "on POST to #create with good credentials" do - setup do - @user = Factory(:email_confirmed_user) - post :create, :session => { - :email => @user.email, - :password => @user.password } - end - - should_set_the_flash_to /signed in/i - should_redirect_to_url_after_create - should_be_signed_in_as { @user } - end - - context "on POST to #create with good credentials and remember me" do - setup do - @user = Factory(:email_confirmed_user) - post :create, :session => { - :email => @user.email, - :password => @user.password, - :remember_me => '1' } - end - - should_set_the_flash_to /signed in/i - should_redirect_to_url_after_create - should_be_signed_in_as { @user } - - should 'set the cookie' do - assert ! cookies['remember_token'].empty? - end - - should 'set the token in users table' do - assert_not_nil @user.reload.token - assert_not_nil @user.reload.token_expires_at - end - end - - context "on POST to #create with good credentials and a session return url" do - setup do - @user = Factory(:email_confirmed_user) - @return_url = '/url_in_the_session' - @request.session[:return_to] = @return_url - post :create, :session => { - :email => @user.email, - :password => @user.password } - end - - should_redirect_to("the return URL") { @return_url } - end - - context "on POST to #create with good credentials and a request return url" do - setup do - @user = Factory(:email_confirmed_user) - @return_url = '/url_in_the_request' - post :create, :session => { - :email => @user.email, - :password => @user.password }, - :return_to => @return_url - end - - should_redirect_to("the return URL") { @return_url } - end - - context "on POST to #create with good credentials and a session return url and request return url" do - setup do - @user = Factory(:email_confirmed_user) - @return_url = '/url_in_the_session' - @request.session[:return_to] = @return_url - post :create, :session => { - :email => @user.email, - :password => @user.password }, - :return_to => '/url_in_the_request' - end - - should_redirect_to("the return URL") { @return_url } - end - - context "on POST to #create with bad credentials" do - setup do - post :create, :session => { - :email => 'bad.email@example.com', - :password => "bad value" } - end - - should_set_the_flash_to /bad/i - should_respond_with :unauthorized - should_render_template :new - should_not_be_signed_in - end - - context "on POST to #create with bad credentials and remember me" do - setup do - post :create, :session => { - :email => 'bad.email@example.com', - :password => "bad value", - :remember_me => '1' } - end - - should_set_the_flash_to /bad/i - should_respond_with :unauthorized - should_render_template :new - should_not_be_signed_in - - should 'not create the cookie' do - assert_nil cookies['remember_token'] - end - end - - context "on DELETE to #destroy given a signed out user" do - setup do - sign_out - delete :destroy - end - should_set_the_flash_to(/signed out/i) - should_redirect_to_url_after_destroy - end - - context "on DELETE to #destroy without a cookie" do - setup do - sign_in - delete :destroy - end - should_set_the_flash_to(/signed out/i) - should_redirect_to_url_after_destroy - end - - context "on DELETE to #destroy with a cookie" do - setup do - @user = Factory(:email_confirmed_user) - cookies['remember_token'] = CGI::Cookie.new('token', 'value') - sign_in_as @user - delete :destroy - end - - should "delete the cookie token" do - assert_nil cookies['remember_token'] - end - - should "delete the database token" do - assert_nil @user.reload.token - assert_nil @user.reload.token_expires_at - end - end - -end diff --git a/vendor/plugins/clearance/test/controllers/users_controller_test.rb b/vendor/plugins/clearance/test/controllers/users_controller_test.rb deleted file mode 100644 index c9e9057..0000000 --- a/vendor/plugins/clearance/test/controllers/users_controller_test.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'test_helper' - -class UsersControllerTest < ActionController::TestCase - - tests Clearance::UsersController - - should_filter_params :password - - context "when signed out" do - setup { sign_out } - - context "on GET to #new" do - setup { get :new } - - should_respond_with :success - should_render_template :new - should_not_set_the_flash - - should_display_a_sign_up_form - end - - context "on GET to #new with email" do - setup do - @email = "a@example.com" - get :new, :user => { :email => @email } - end - - should "set assigned user's email" do - assert_equal @email, assigns(:user).email - end - end - - context "on POST to #create with valid attributes" do - setup do - user_attributes = Factory.attributes_for(:user) - post :create, :user => user_attributes - end - - should_create_user_successfully - end - end - - signed_in_user_context do - context "GET to new" do - setup { get :new } - should_redirect_to("the home page") { root_url } - end - - context "POST to create" do - setup { post :create, :user => {} } - should_redirect_to("the home page") { root_url } - end - end - -end diff --git a/vendor/plugins/clearance/test/models/clearance_mailer_test.rb b/vendor/plugins/clearance/test/models/clearance_mailer_test.rb deleted file mode 100644 index c7295d5..0000000 --- a/vendor/plugins/clearance/test/models/clearance_mailer_test.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'test_helper' - -class ClearanceMailerTest < ActiveSupport::TestCase - - context "A change password email" do - setup do - @user = Factory(:user) - @email = ClearanceMailer.create_change_password @user - end - - should "be from DO_NOT_REPLY" do - assert_match /#{@email.from[0]}/i, DO_NOT_REPLY - end - - should "be sent to user" do - assert_match /#{@user.email}/i, @email.to.first - end - - should "contain a link to edit the user's password" do - host = ActionMailer::Base.default_url_options[:host] - regexp = %r{http://#{host}/users/#{@user.id}/password/edit\?token=#{@user.token}} - assert_match regexp, @email.body - end - - should "set its subject" do - assert_match /Change your password/, @email.subject - end - end - - context "A confirmation email" do - setup do - @user = Factory(:user) - @email = ClearanceMailer.create_confirmation @user - end - - should "be from DO_NOT_REPLY" do - assert_match /#{@email.from[0]}/i, DO_NOT_REPLY - end - - should "be sent to user" do - assert_match /#{@user.email}/i, @email.to.first - end - - should "set its subject" do - assert_match /Account confirmation/, @email.subject - end - - should "contain a link to confirm the user's account" do - host = ActionMailer::Base.default_url_options[:host] - regexp = %r{http://#{host}/users/#{@user.id}/confirmation/new\?token=#{@user.token}} - assert_match regexp, @email.body - end - end - -end diff --git a/vendor/plugins/clearance/test/models/user_test.rb b/vendor/plugins/clearance/test/models/user_test.rb deleted file mode 100644 index 4266409..0000000 --- a/vendor/plugins/clearance/test/models/user_test.rb +++ /dev/null @@ -1,233 +0,0 @@ -require 'test_helper' - -class UserTest < ActiveSupport::TestCase - - should_not_allow_mass_assignment_of :email_confirmed, - :salt, :encrypted_password, - :token, :token_expires_at - - # signing up - - context "When signing up" do - should_validate_presence_of :email, :password - should_allow_values_for :email, "foo@example.com" - should_not_allow_values_for :email, "foo" - should_not_allow_values_for :email, "example.com" - - should "require password confirmation on create" do - user = Factory.build(:user, :password => 'blah', - :password_confirmation => 'boogidy') - assert ! user.save - assert user.errors.on(:password) - end - - should "require non blank password confirmation on create" do - user = Factory.build(:user, :password => 'blah', - :password_confirmation => '') - assert ! user.save - assert user.errors.on(:password) - end - - should "initialize salt" do - assert_not_nil Factory(:user).salt - end - - should "initialize token without expiry date" do - assert_not_nil Factory(:user).token - assert_nil Factory(:user).token_expires_at - end - - context "encrypt password" do - setup do - @salt = "salt" - @user = Factory.build(:user, :salt => @salt) - def @user.initialize_salt; end - @user.save! - @password = @user.password - - @user.encrypt(@password) - @expected = Digest::SHA1.hexdigest("--#{@salt}--#{@password}--") - end - - should "create an encrypted password using SHA1 encryption" do - assert_equal @expected, @user.encrypted_password - end - end - - should "store email in exact case" do - user = Factory(:user, :email => "John.Doe@example.com") - assert_equal "John.Doe@example.com", user.email - end - end - - context "When multiple users have signed up" do - setup { @user = Factory(:user) } - should_validate_uniqueness_of :email - end - - # confirming email - - context "A user without email confirmation" do - setup do - @user = Factory(:user) - assert ! @user.email_confirmed? - end - - context "after #confirm_email!" do - setup do - assert @user.confirm_email! - @user.reload - end - - should "have confirmed their email" do - assert @user.email_confirmed? - end - - should "reset token" do - assert_nil @user.token - end - end - end - - # authenticating - - context "A user" do - setup do - @user = Factory(:user) - @password = @user.password - end - - should "authenticate with good credentials" do - assert ::User.authenticate(@user.email, @password) - assert @user.authenticated?(@password) - end - - should "not authenticate with bad credentials" do - assert ! ::User.authenticate(@user.email, 'bad_password') - assert ! @user.authenticated?('bad_password') - end - end - - # remember me - - context "When authenticating with remember_me!" do - setup do - @user = Factory(:email_confirmed_user) - @token = @user.token - assert_nil @user.token_expires_at - @user.remember_me! - end - - should "set the remember token and expiration date" do - assert_not_equal @token, @user.token - assert_not_nil @user.token_expires_at - end - - should "remember user when token expires in the future" do - @user.update_attribute :token_expires_at, - 2.weeks.from_now.utc - assert @user.remember? - end - - should "not remember user when token has already expired" do - @user.update_attribute :token_expires_at, - 2.weeks.ago.utc - assert ! @user.remember? - end - - should "not remember user when token expiry date is not set" do - @user.update_attribute :token_expires_at, nil - assert ! @user.remember? - end - - # logging out - - context "forget_me!" do - setup { @user.forget_me! } - - should "unset the remember token and expiration date" do - assert_nil @user.token - assert_nil @user.token_expires_at - end - - should "not remember user" do - assert ! @user.remember? - end - end - end - - # updating password - - context "An email confirmed user" do - setup do - @user = Factory(:email_confirmed_user) - @old_encrypted_password = @user.encrypted_password - end - - context "who updates password with confirmation" do - setup do - @user.update_password("new_password", "new_password") - end - - should "change encrypted password" do - assert_not_equal @user.encrypted_password, - @old_encrypted_password - end - end - end - - # recovering forgotten password - - context "An email confirmed user" do - setup do - @user = Factory(:email_confirmed_user) - @old_encrypted_password = @user.encrypted_password - @user.confirm_email! - end - - context "who requests password reminder" do - setup do - assert_nil @user.token - @user.forgot_password! - end - - should "generate token" do - assert_not_nil @user.token - end - - context "and then updates password" do - context 'with confirmation' do - setup do - @user.update_password("new_password", "new_password") - end - - should "change encrypted password" do - assert_not_equal @user.encrypted_password, - @old_encrypted_password - end - - should "clear token" do - assert_nil @user.token - end - end - - context 'without confirmation' do - setup do - @user.update_password("new_password", "") - end - - should "not change encrypted password" do - assert_equal @user.encrypted_password, - @old_encrypted_password - end - - should "not clear token" do - assert_not_nil @user.token - end - end - end - end - - end - -end diff --git a/vendor/plugins/clearance/test/rails_root/.gitignore b/vendor/plugins/clearance/test/rails_root/.gitignore deleted file mode 100644 index 5964c47..0000000 --- a/vendor/plugins/clearance/test/rails_root/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -log/* -tmp/**/* -db/schema.rb -db/*.sqlite3 -public/system -*.DS_Store -coverage/* -*.swp \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/.rake_tasks b/vendor/plugins/clearance/test/rails_root/.rake_tasks deleted file mode 100644 index 63bec09..0000000 --- a/vendor/plugins/clearance/test/rails_root/.rake_tasks +++ /dev/null @@ -1,103 +0,0 @@ -db:abort_if_pending_migrations -db:bootstrap -db:bootstrap:load -db:charset -db:collation -db:create -db:create:all -db:drop -db:drop:all -db:fixtures:identify -db:fixtures:load -db:migrate -db:migrate:down -db:migrate:redo -db:migrate:reset -db:migrate:up -db:reset -db:rollback -db:schema:dump -db:schema:load -db:sessions:clear -db:sessions:create -db:structure:dump -db:test:clone -db:test:clone_structure -db:test:prepare -db:test:purge -db:version -deploy -doc:app -doc:clobber_app -doc:clobber_plugins -doc:clobber_rails -doc:plugins -doc:rails -doc:reapp -doc:rerails -gems -gems:build -gems:install -gems:unpack -gems:unpack:dependencies -git:branch:production -git:diff:production -git:diff:staging -git:pull:template -git:push:production -git:push:staging -log:clear -notes -notes:fixme -notes:optimize -notes:todo -rails:freeze:edge -rails:freeze:gems -rails:unfreeze -rails:update -rails:update:configs -rails:update:javascripts -rails:update:scripts -remote:cleanup -remote:cold_deploy -remote:deploy -remote:deploy_with_migrations -remote:diff_from_last_deploy -remote:disable_web -remote:enable_web -remote:exec -remote:invoke -remote:migrate -remote:restart -remote:rollback -remote:rollback_code -remote:setup -remote:shell -remote:show_tasks -remote:spinner -remote:symlink -remote:update -remote:update_code -remote:update_current -rollback -routes -secret -shoulda:from_yaml -shoulda:list -stats -test -test:functionals -test:integration -test:plugins -test:recent -test:uncommitted -test:units -time:zones:all -time:zones:local -time:zones:us -tmp:cache:clear -tmp:clear -tmp:create -tmp:pids:clear -tmp:sessions:clear -tmp:sockets:clear diff --git a/vendor/plugins/clearance/test/rails_root/Capfile b/vendor/plugins/clearance/test/rails_root/Capfile deleted file mode 100644 index c36d48d..0000000 --- a/vendor/plugins/clearance/test/rails_root/Capfile +++ /dev/null @@ -1,3 +0,0 @@ -load 'deploy' if respond_to?(:namespace) # cap2 differentiator -Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) } -load 'config/deploy' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/Rakefile b/vendor/plugins/clearance/test/rails_root/Rakefile deleted file mode 100644 index 3bb0e85..0000000 --- a/vendor/plugins/clearance/test/rails_root/Rakefile +++ /dev/null @@ -1,10 +0,0 @@ -# Add your own tasks in files placed in lib/tasks ending in .rake, -# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. - -require(File.join(File.dirname(__FILE__), 'config', 'boot')) - -require 'rake' -require 'rake/testtask' -require 'rake/rdoctask' - -require 'tasks/rails' diff --git a/vendor/plugins/clearance/test/rails_root/app/controllers/accounts_controller.rb b/vendor/plugins/clearance/test/rails_root/app/controllers/accounts_controller.rb deleted file mode 100644 index a54e1ad..0000000 --- a/vendor/plugins/clearance/test/rails_root/app/controllers/accounts_controller.rb +++ /dev/null @@ -1,10 +0,0 @@ -class AccountsController < ApplicationController - before_filter :authenticate - - def edit - end - - def create - redirect_to edit_account_path - end -end diff --git a/vendor/plugins/clearance/test/rails_root/app/controllers/application_controller.rb b/vendor/plugins/clearance/test/rails_root/app/controllers/application_controller.rb deleted file mode 100644 index 8312eee..0000000 --- a/vendor/plugins/clearance/test/rails_root/app/controllers/application_controller.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ApplicationController < ActionController::Base - helper :all - protect_from_forgery - include Clearance::Authentication -end diff --git a/vendor/plugins/clearance/test/rails_root/app/helpers/application_helper.rb b/vendor/plugins/clearance/test/rails_root/app/helpers/application_helper.rb deleted file mode 100644 index 7ad714a..0000000 --- a/vendor/plugins/clearance/test/rails_root/app/helpers/application_helper.rb +++ /dev/null @@ -1,5 +0,0 @@ -module ApplicationHelper - def body_class - "#{controller.controller_name} #{controller.controller_name}-#{controller.action_name}" - end -end diff --git a/vendor/plugins/clearance/test/rails_root/app/helpers/confirmations_helper.rb b/vendor/plugins/clearance/test/rails_root/app/helpers/confirmations_helper.rb deleted file mode 100644 index e475aa1..0000000 --- a/vendor/plugins/clearance/test/rails_root/app/helpers/confirmations_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module ConfirmationsHelper -end diff --git a/vendor/plugins/clearance/test/rails_root/app/helpers/passwords_helper.rb b/vendor/plugins/clearance/test/rails_root/app/helpers/passwords_helper.rb deleted file mode 100644 index 8797917..0000000 --- a/vendor/plugins/clearance/test/rails_root/app/helpers/passwords_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module PasswordsHelper -end diff --git a/vendor/plugins/clearance/test/rails_root/app/models/.keep b/vendor/plugins/clearance/test/rails_root/app/models/.keep deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/app/models/.keep +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/app/views/accounts/edit.html.erb b/vendor/plugins/clearance/test/rails_root/app/views/accounts/edit.html.erb deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/app/views/accounts/edit.html.erb +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/app/views/layouts/application.html.erb b/vendor/plugins/clearance/test/rails_root/app/views/layouts/application.html.erb deleted file mode 100644 index 56a61f6..0000000 --- a/vendor/plugins/clearance/test/rails_root/app/views/layouts/application.html.erb +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Clearance - <%= stylesheet_link_tag 'screen', :media => 'all' %> - <%= javascript_include_tag :defaults %> - - -
- <% flash.each do |key, value| -%> -
<%=h value %>
- <% end %> -
- <%= yield %> - - diff --git a/vendor/plugins/clearance/test/rails_root/config/boot.rb b/vendor/plugins/clearance/test/rails_root/config/boot.rb deleted file mode 100644 index 0ad0f78..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/boot.rb +++ /dev/null @@ -1,110 +0,0 @@ -# Don't change this file! -# Configure your app in config/environment.rb and config/environments/*.rb - -RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) - -module Rails - class << self - def boot! - unless booted? - preinitialize - pick_boot.run - end - end - - def booted? - defined? Rails::Initializer - end - - def pick_boot - (vendor_rails? ? VendorBoot : GemBoot).new - end - - def vendor_rails? - File.exist?("#{RAILS_ROOT}/vendor/rails") - end - - def preinitialize - load(preinitializer_path) if File.exist?(preinitializer_path) - end - - def preinitializer_path - "#{RAILS_ROOT}/config/preinitializer.rb" - end - end - - class Boot - def run - load_initializer - Rails::Initializer.run(:set_load_path) - end - end - - class VendorBoot < Boot - def load_initializer - require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" - Rails::Initializer.run(:install_gem_spec_stubs) - Rails::GemDependency.add_frozen_gem_path - end - end - - class GemBoot < Boot - def load_initializer - self.class.load_rubygems - load_rails_gem - require 'initializer' - end - - def load_rails_gem - if version = self.class.gem_version - gem 'rails', version - else - gem 'rails' - end - rescue Gem::LoadError => load_error - $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.) - exit 1 - end - - class << self - def rubygems_version - Gem::RubyGemsVersion rescue nil - end - - def gem_version - if defined? RAILS_GEM_VERSION - RAILS_GEM_VERSION - elsif ENV.include?('RAILS_GEM_VERSION') - ENV['RAILS_GEM_VERSION'] - else - parse_gem_version(read_environment_rb) - end - end - - def load_rubygems - require 'rubygems' - min_version = '1.3.1' - unless rubygems_version >= min_version - $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.) - exit 1 - end - - rescue LoadError - $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org) - exit 1 - end - - def parse_gem_version(text) - $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ - end - - private - def read_environment_rb - File.read("#{RAILS_ROOT}/config/environment.rb") - end - end - end -end - -# All that for this: -Rails.boot! diff --git a/vendor/plugins/clearance/test/rails_root/config/database.yml b/vendor/plugins/clearance/test/rails_root/config/database.yml deleted file mode 100644 index 55bd1c6..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/database.yml +++ /dev/null @@ -1,14 +0,0 @@ -development: - adapter: sqlite3 - database: db/development.sqlite3 - timeout: 5000 - -test: - adapter: sqlite3 - database: db/test.sqlite3 - timeout: 5000 - -production: - adapter: sqlite3 - database: db/production.sqlite3 - timeout: 5000 diff --git a/vendor/plugins/clearance/test/rails_root/config/environment.rb b/vendor/plugins/clearance/test/rails_root/config/environment.rb deleted file mode 100644 index 2215092..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/environment.rb +++ /dev/null @@ -1,13 +0,0 @@ -require File.join(File.dirname(__FILE__), 'boot') -require 'digest/md5' - -Rails::Initializer.run do |config| - config.load_paths += Dir.glob(File.join(RAILS_ROOT, 'vendor', 'gems', '*', 'lib')) - config.time_zone = 'Eastern Time (US & Canada)' - config.action_controller.session = { - :session_key => "_clearance_session", - :secret => ['clearance', 'random', 'words', 'here'].map {|k| Digest::MD5.hexdigest(k) }.join - } -end - -DO_NOT_REPLY = "donotreply@example.com" diff --git a/vendor/plugins/clearance/test/rails_root/config/environments/development.rb b/vendor/plugins/clearance/test/rails_root/config/environments/development.rb deleted file mode 100644 index 4013d5b..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/environments/development.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# In the development environment your application's code is reloaded on -# every request. This slows down response time but is perfect for development -# since you don't have to restart the webserver when you make code changes. -config.cache_classes = false - -# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true - -# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_controller.perform_caching = false -config.action_view.debug_rjs = true - -# Don't care if the mailer can't send -config.action_mailer.raise_delivery_errors = false - -HOST = "localhost" diff --git a/vendor/plugins/clearance/test/rails_root/config/environments/production.rb b/vendor/plugins/clearance/test/rails_root/config/environments/production.rb deleted file mode 100644 index 5a0b99e..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/environments/production.rb +++ /dev/null @@ -1 +0,0 @@ -HOST = "http://example.com" diff --git a/vendor/plugins/clearance/test/rails_root/config/environments/test.rb b/vendor/plugins/clearance/test/rails_root/config/environments/test.rb deleted file mode 100644 index fbe8599..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/environments/test.rb +++ /dev/null @@ -1,33 +0,0 @@ -# Settings specified here will take precedence over those in config/environment.rb - -# The test environment is used exclusively to run your application's -# test suite. You never need to work with it otherwise. Remember that -# your test database is "scratch space" for the test suite and is wiped -# and recreated between test runs. Don't rely on the data there! -config.cache_classes = true - -# Log error messages when you accidentally call methods on nil. -config.whiny_nils = true - -# Show full error reports and disable caching -config.action_controller.consider_all_requests_local = true -config.action_controller.perform_caching = false - -# Disable request forgery protection in test environment -config.action_controller.allow_forgery_protection = false - -# Tell ActionMailer not to deliver emails to the real world. -# The :test delivery method accumulates sent emails in the -# ActionMailer::Base.deliveries array. -config.action_mailer.delivery_method = :test - -HOST = "localhost" - -config.gem 'thoughtbot-shoulda', - :lib => 'shoulda', - :source => "http://gems.github.com", - :version => '>= 2.9.1' -config.gem 'thoughtbot-factory_girl', - :lib => 'factory_girl', - :source => "http://gems.github.com", - :version => '>= 1.2.0' diff --git a/vendor/plugins/clearance/test/rails_root/config/initializers/clearance.rb b/vendor/plugins/clearance/test/rails_root/config/initializers/clearance.rb deleted file mode 100644 index 601e97c..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/initializers/clearance.rb +++ /dev/null @@ -1,8 +0,0 @@ -# This simulates loading the clearance gem, but without relying on -# vendor/gems - -clearance_path = File.join(File.dirname(__FILE__), *%w(.. .. .. ..)) -clearance_lib_path = File.join(clearance_path, "lib") - -$LOAD_PATH.unshift(clearance_lib_path) -load File.join(clearance_path, 'rails', 'init.rb') diff --git a/vendor/plugins/clearance/test/rails_root/config/initializers/inflections.rb b/vendor/plugins/clearance/test/rails_root/config/initializers/inflections.rb deleted file mode 100644 index 09158b8..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/initializers/inflections.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new inflection rules using the following format -# (all these examples are active by default): -# Inflector.inflections do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' -# inflect.uncountable %w( fish sheep ) -# end diff --git a/vendor/plugins/clearance/test/rails_root/config/initializers/mime_types.rb b/vendor/plugins/clearance/test/rails_root/config/initializers/mime_types.rb deleted file mode 100644 index 72aca7e..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/initializers/mime_types.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new mime types for use in respond_to blocks: -# Mime::Type.register "text/richtext", :rtf -# Mime::Type.register_alias "text/html", :iphone diff --git a/vendor/plugins/clearance/test/rails_root/config/initializers/requires.rb b/vendor/plugins/clearance/test/rails_root/config/initializers/requires.rb deleted file mode 100644 index 5acec2b..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/initializers/requires.rb +++ /dev/null @@ -1,13 +0,0 @@ -Dir[File.join(RAILS_ROOT, 'lib', 'extensions', '*.rb')].each do |f| - require f -end - -Dir[File.join(RAILS_ROOT, 'lib', '*.rb')].each do |f| - require f -end - -# Rails 2 doesn't like mocks - -Dir[File.join(RAILS_ROOT, 'test', 'mocks', RAILS_ENV, '*.rb')].each do |f| - require f -end diff --git a/vendor/plugins/clearance/test/rails_root/config/initializers/time_formats.rb b/vendor/plugins/clearance/test/rails_root/config/initializers/time_formats.rb deleted file mode 100644 index 99cc335..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/initializers/time_formats.rb +++ /dev/null @@ -1,4 +0,0 @@ -# Example time formats -{ :short_date => "%x", :long_date => "%a, %b %d, %Y" }.each do |k, v| - ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.update(k => v) -end diff --git a/vendor/plugins/clearance/test/rails_root/config/locales/en.yml b/vendor/plugins/clearance/test/rails_root/config/locales/en.yml deleted file mode 100644 index fb5e204..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/locales/en.yml +++ /dev/null @@ -1,19 +0,0 @@ -en: - clearance: - models: - clearance_mailer: - change_password: Change your password - confirmation: Account confirmation - controllers: - confirmations: - confirmed_email: Confirmed email and signed in. - passwords: - deliver_change_password: You will receive an email within the next few minutes. It contains instructions for changing your password. - unknown_email: Unknown email. - sessions: - bad_email_or_password: Bad email or password. - unconfirmed_email: User has not confirmed email. Confirmation email will be resent. - users: - deliver_confirmation: You will receive an email within the next few minutes. It contains instructions for confirming your account. - signed_in: Signed in. - signed_out: Signed out. diff --git a/vendor/plugins/clearance/test/rails_root/config/routes.rb b/vendor/plugins/clearance/test/rails_root/config/routes.rb deleted file mode 100644 index ca45194..0000000 --- a/vendor/plugins/clearance/test/rails_root/config/routes.rb +++ /dev/null @@ -1,5 +0,0 @@ -ActionController::Routing::Routes.draw do |map| - map.resource :account - - map.root :controller => 'accounts', :action => 'edit' -end diff --git a/vendor/plugins/clearance/test/rails_root/db/.keep b/vendor/plugins/clearance/test/rails_root/db/.keep deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/db/.keep +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/doc/README_FOR_APP b/vendor/plugins/clearance/test/rails_root/doc/README_FOR_APP deleted file mode 100644 index ac6c149..0000000 --- a/vendor/plugins/clearance/test/rails_root/doc/README_FOR_APP +++ /dev/null @@ -1,2 +0,0 @@ -Use this README file to introduce your application and point to useful places in the API for learning more. -Run "rake appdoc" to generate API documentation for your models and controllers. \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/doc/README_FOR_TEMPLATE b/vendor/plugins/clearance/test/rails_root/doc/README_FOR_TEMPLATE deleted file mode 100644 index e890e2c..0000000 --- a/vendor/plugins/clearance/test/rails_root/doc/README_FOR_TEMPLATE +++ /dev/null @@ -1,15 +0,0 @@ -This is the Thoughtbot Rails Template. To create a new project, checkout this -repository and run: - - ./script/create_project.rb projectname - -This will create a project in ../projectname. You should then follow the -instructions on Github to upload that project there. This script creates an -entirely new git repository, and is not meant to be used against an existing -repo. - -When making a change to a project that was created via this template, consider -whether it's a change that should be made across all projects. If so, then -make the change in this template, and pull it into your project via: - - git pull git@github.com:thoughtbot/rails-template.git master \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/features/step_definitions/webrat_steps.rb b/vendor/plugins/clearance/test/rails_root/features/step_definitions/webrat_steps.rb deleted file mode 100644 index 30841f9..0000000 --- a/vendor/plugins/clearance/test/rails_root/features/step_definitions/webrat_steps.rb +++ /dev/null @@ -1,99 +0,0 @@ -require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths")) - -# Commonly used webrat steps -# http://github.com/brynary/webrat - -When /^I go to (.+)$/ do |page_name| - visit path_to(page_name) -end - -When /^I press "(.*)"$/ do |button| - click_button(button) -end - -When /^I follow "(.*)"$/ do |link| - click_link(link) -end - -When /^I fill in "(.*)" with "(.*)"$/ do |field, value| - fill_in(field, :with => value) -end - -When /^I select "(.*)" from "(.*)"$/ do |value, field| - select(value, :from => field) -end - -# Use this step in conjunction with Rail's datetime_select helper. For example: -# When I select "December 25, 2008 10:00" as the date and time -When /^I select "(.*)" as the date and time$/ do |time| - select_datetime(time) -end - -# Use this step when using multiple datetime_select helpers on a page or -# you want to specify which datetime to select. Given the following view: -# <%= f.label :preferred %>
-# <%= f.datetime_select :preferred %> -# <%= f.label :alternative %>
-# <%= f.datetime_select :alternative %> -# The following steps would fill out the form: -# When I select "November 23, 2004 11:20" as the "Preferred" data and time -# And I select "November 25, 2004 10:30" as the "Alternative" data and time -When /^I select "(.*)" as the "(.*)" date and time$/ do |datetime, datetime_label| - select_datetime(datetime, :from => datetime_label) -end - -# Use this step in conjuction with Rail's time_select helper. For example: -# When I select "2:20PM" as the time -# Note: Rail's default time helper provides 24-hour time-- not 12 hour time. Webrat -# will convert the 2:20PM to 14:20 and then select it. -When /^I select "(.*)" as the time$/ do |time| - select_time(time) -end - -# Use this step when using multiple time_select helpers on a page or you want to -# specify the name of the time on the form. For example: -# When I select "7:30AM" as the "Gym" time -When /^I select "(.*)" as the "(.*)" time$/ do |time, time_label| - select_time(time, :from => time_label) -end - -# Use this step in conjuction with Rail's date_select helper. For example: -# When I select "February 20, 1981" as the date -When /^I select "(.*)" as the date$/ do |date| - select_date(date) -end - -# Use this step when using multiple date_select helpers on one page or -# you want to specify the name of the date on the form. For example: -# When I select "April 26, 1982" as the "Date of Birth" date -When /^I select "(.*)" as the "(.*)" date$/ do |date, date_label| - select_date(date, :from => date_label) -end - -When /^I check "(.*)"$/ do |field| - check(field) -end - -When /^I uncheck "(.*)"$/ do |field| - uncheck(field) -end - -When /^I choose "(.*)"$/ do |field| - choose(field) -end - -When /^I attach the file at "(.*)" to "(.*)" $/ do |path, field| - attach_file(field, path) -end - -Then /^I should see "(.*)"$/ do |text| - assert_match /#{text}/m, response.body -end - -Then /^I should not see "(.*)"$/ do |text| - assert_match /#{text}/m, response.body -end - -Then /^the "(.*)" checkbox should be checked$/ do |label| - field_labeled(label).should be_checked -end diff --git a/vendor/plugins/clearance/test/rails_root/features/support/env.rb b/vendor/plugins/clearance/test/rails_root/features/support/env.rb deleted file mode 100644 index 52bceb8..0000000 --- a/vendor/plugins/clearance/test/rails_root/features/support/env.rb +++ /dev/null @@ -1,14 +0,0 @@ -# Sets up the Rails environment for Cucumber -ENV["RAILS_ENV"] = "test" -require File.expand_path(File.dirname(__FILE__) + '/../../config/environment') -require 'factory_girl' -require 'cucumber/rails/world' -require 'cucumber/formatter/unicode' # Comment out this line if you don't want Cucumber Unicode support -Cucumber::Rails.use_transactional_fixtures -Cucumber::Rails.bypass_rescue - -require 'webrat' - -Webrat.configure do |config| - config.mode = :rails -end diff --git a/vendor/plugins/clearance/test/rails_root/public/.htaccess b/vendor/plugins/clearance/test/rails_root/public/.htaccess deleted file mode 100644 index d3c9983..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/.htaccess +++ /dev/null @@ -1,40 +0,0 @@ -# General Apache options -AddHandler fastcgi-script .fcgi -AddHandler cgi-script .cgi -Options +FollowSymLinks +ExecCGI - -# If you don't want Rails to look in certain directories, -# use the following rewrite rules so that Apache won't rewrite certain requests -# -# Example: -# RewriteCond %{REQUEST_URI} ^/notrails.* -# RewriteRule .* - [L] - -# Redirect all requests not available on the filesystem to Rails -# By default the cgi dispatcher is used which is very slow -# -# For better performance replace the dispatcher with the fastcgi one -# -# Example: -# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L] -RewriteEngine On - -# If your Rails application is accessed via an Alias directive, -# then you MUST also set the RewriteBase in this htaccess file. -# -# Example: -# Alias /myrailsapp /path/to/myrailsapp/public -# RewriteBase /myrailsapp - -RewriteRule ^$ index.html [QSA] -RewriteRule ^([^.]+)$ $1.html [QSA] -RewriteCond %{REQUEST_FILENAME} !-f -RewriteRule ^(.*)$ dispatch.cgi [QSA,L] - -# In case Rails experiences terminal errors -# Instead of displaying this message you can supply a file here which will be rendered instead -# -# Example: -# ErrorDocument 500 /500.html - -ErrorDocument 500 "

Application error

Rails application failed to start properly" \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/public/404.html b/vendor/plugins/clearance/test/rails_root/public/404.html deleted file mode 100644 index eff660b..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/404.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - The page you were looking for doesn't exist (404) - - - - - -
-

The page you were looking for doesn't exist.

-

You may have mistyped the address or the page may have moved.

-
- - \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/public/422.html b/vendor/plugins/clearance/test/rails_root/public/422.html deleted file mode 100644 index b54e4a3..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/422.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - The change you wanted was rejected (422) - - - - - -
-

The change you wanted was rejected.

-

Maybe you tried to change something you didn't have access to.

-
- - \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/public/500.html b/vendor/plugins/clearance/test/rails_root/public/500.html deleted file mode 100644 index f0aee0e..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/500.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - We're sorry, but something went wrong - - - - - -
-

We're sorry, but something went wrong.

-

We've been notified about this issue and we'll take a look at it shortly.

-
- - \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/public/dispatch.rb b/vendor/plugins/clearance/test/rails_root/public/dispatch.rb deleted file mode 100755 index a76782a..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/dispatch.rb +++ /dev/null @@ -1,10 +0,0 @@ -#!/opt/local/bin/ruby - -require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) - -# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: -# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired -require "dispatcher" - -ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) -Dispatcher.dispatch \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/public/favicon.ico b/vendor/plugins/clearance/test/rails_root/public/favicon.ico deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/favicon.ico +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/public/images/rails.png b/vendor/plugins/clearance/test/rails_root/public/images/rails.png deleted file mode 100644 index b8441f1..0000000 Binary files a/vendor/plugins/clearance/test/rails_root/public/images/rails.png and /dev/null differ diff --git a/vendor/plugins/clearance/test/rails_root/public/javascripts/application.js b/vendor/plugins/clearance/test/rails_root/public/javascripts/application.js deleted file mode 100644 index fe45776..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/javascripts/application.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place your application-specific JavaScript functions and classes here -// This file is automatically included by javascript_include_tag :defaults diff --git a/vendor/plugins/clearance/test/rails_root/public/javascripts/builder.js b/vendor/plugins/clearance/test/rails_root/public/javascripts/builder.js deleted file mode 100644 index 5b4ce87..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/javascripts/builder.js +++ /dev/null @@ -1,136 +0,0 @@ -// script.aculo.us builder.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007 - -// Copyright (c) 2005-2007 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/ - -var Builder = { - NODEMAP: { - AREA: 'map', - CAPTION: 'table', - COL: 'table', - COLGROUP: 'table', - LEGEND: 'fieldset', - OPTGROUP: 'select', - OPTION: 'select', - PARAM: 'object', - TBODY: 'table', - TD: 'table', - TFOOT: 'table', - TH: 'table', - THEAD: 'table', - TR: 'table' - }, - // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, - // due to a Firefox bug - node: function(elementName) { - elementName = elementName.toUpperCase(); - - // try innerHTML approach - var parentTag = this.NODEMAP[elementName] || 'div'; - var parentElement = document.createElement(parentTag); - try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 - parentElement.innerHTML = "<" + elementName + ">"; - } catch(e) {} - var element = parentElement.firstChild || null; - - // see if browser added wrapping tags - if(element && (element.tagName.toUpperCase() != elementName)) - element = element.getElementsByTagName(elementName)[0]; - - // fallback to createElement approach - if(!element) element = document.createElement(elementName); - - // abort if nothing could be created - if(!element) return; - - // attributes (or text) - if(arguments[1]) - if(this._isStringOrNumber(arguments[1]) || - (arguments[1] instanceof Array) || - arguments[1].tagName) { - this._children(element, arguments[1]); - } else { - var attrs = this._attributes(arguments[1]); - if(attrs.length) { - try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 - parentElement.innerHTML = "<" +elementName + " " + - attrs + ">"; - } catch(e) {} - element = parentElement.firstChild || null; - // workaround firefox 1.0.X bug - if(!element) { - element = document.createElement(elementName); - for(attr in arguments[1]) - element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; - } - if(element.tagName.toUpperCase() != elementName) - element = parentElement.getElementsByTagName(elementName)[0]; - } - } - - // text, or array of children - if(arguments[2]) - this._children(element, arguments[2]); - - return element; - }, - _text: function(text) { - return document.createTextNode(text); - }, - - ATTR_MAP: { - 'className': 'class', - 'htmlFor': 'for' - }, - - _attributes: function(attributes) { - var attrs = []; - for(attribute in attributes) - attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + - '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); - return attrs.join(" "); - }, - _children: function(element, children) { - if(children.tagName) { - element.appendChild(children); - return; - } - if(typeof children=='object') { // array can hold nodes and text - children.flatten().each( function(e) { - if(typeof e=='object') - element.appendChild(e) - else - if(Builder._isStringOrNumber(e)) - element.appendChild(Builder._text(e)); - }); - } else - if(Builder._isStringOrNumber(children)) - element.appendChild(Builder._text(children)); - }, - _isStringOrNumber: function(param) { - return(typeof param=='string' || typeof param=='number'); - }, - build: function(html) { - var element = this.node('div'); - $(element).update(html.strip()); - return element.down(); - }, - dump: function(scope) { - if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope - - var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + - "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + - "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+ - "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+ - "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ - "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); - - tags.each( function(tag){ - scope[tag] = function() { - return Builder.node.apply(Builder, [tag].concat($A(arguments))); - } - }); - } -} diff --git a/vendor/plugins/clearance/test/rails_root/public/javascripts/controls.js b/vendor/plugins/clearance/test/rails_root/public/javascripts/controls.js deleted file mode 100644 index 5aaf0bb..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/javascripts/controls.js +++ /dev/null @@ -1,963 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) -// Contributors: -// Richard Livsey -// Rahul Bhargava -// Rob Wills -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// Autocompleter.Base handles all the autocompletion functionality -// that's independent of the data source for autocompletion. This -// includes drawing the autocompletion menu, observing keyboard -// and mouse events, and similar. -// -// Specific autocompleters need to provide, at the very least, -// a getUpdatedChoices function that will be invoked every time -// the text inside the monitored textbox changes. This method -// should get the text for which to provide autocompletion by -// invoking this.getToken(), NOT by directly accessing -// this.element.value. This is to allow incremental tokenized -// autocompletion. Specific auto-completion logic (AJAX, etc) -// belongs in getUpdatedChoices. -// -// Tokenized incremental autocompletion is enabled automatically -// when an autocompleter is instantiated with the 'tokens' option -// in the options parameter, e.g.: -// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); -// will incrementally autocomplete with a comma as the token. -// Additionally, ',' in the above example can be replaced with -// a token array, e.g. { tokens: [',', '\n'] } which -// enables autocompletion on multiple tokens. This is most -// useful when one of the tokens is \n (a newline), as it -// allows smart autocompletion after linebreaks. - -if(typeof Effect == 'undefined') - throw("controls.js requires including script.aculo.us' effects.js library"); - -var Autocompleter = { } -Autocompleter.Base = Class.create({ - baseInitialize: function(element, update, options) { - element = $(element) - this.element = element; - this.update = $(update); - this.hasFocus = false; - this.changed = false; - this.active = false; - this.index = 0; - this.entryCount = 0; - this.oldElementValue = this.element.value; - - if(this.setOptions) - this.setOptions(options); - else - this.options = options || { }; - - this.options.paramName = this.options.paramName || this.element.name; - this.options.tokens = this.options.tokens || []; - this.options.frequency = this.options.frequency || 0.4; - this.options.minChars = this.options.minChars || 1; - this.options.onShow = this.options.onShow || - function(element, update){ - if(!update.style.position || update.style.position=='absolute') { - update.style.position = 'absolute'; - Position.clone(element, update, { - setHeight: false, - offsetTop: element.offsetHeight - }); - } - Effect.Appear(update,{duration:0.15}); - }; - this.options.onHide = this.options.onHide || - function(element, update){ new Effect.Fade(update,{duration:0.15}) }; - - if(typeof(this.options.tokens) == 'string') - this.options.tokens = new Array(this.options.tokens); - // Force carriage returns as token delimiters anyway - if (!this.options.tokens.include('\n')) - this.options.tokens.push('\n'); - - this.observer = null; - - this.element.setAttribute('autocomplete','off'); - - Element.hide(this.update); - - Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); - }, - - show: function() { - if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); - if(!this.iefix && - (Prototype.Browser.IE) && - (Element.getStyle(this.update, 'position')=='absolute')) { - new Insertion.After(this.update, - ''); - this.iefix = $(this.update.id+'_iefix'); - } - if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); - }, - - fixIEOverlapping: function() { - Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); - this.iefix.style.zIndex = 1; - this.update.style.zIndex = 2; - Element.show(this.iefix); - }, - - hide: function() { - this.stopIndicator(); - if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); - if(this.iefix) Element.hide(this.iefix); - }, - - startIndicator: function() { - if(this.options.indicator) Element.show(this.options.indicator); - }, - - stopIndicator: function() { - if(this.options.indicator) Element.hide(this.options.indicator); - }, - - onKeyPress: function(event) { - if(this.active) - switch(event.keyCode) { - case Event.KEY_TAB: - case Event.KEY_RETURN: - this.selectEntry(); - Event.stop(event); - case Event.KEY_ESC: - this.hide(); - this.active = false; - Event.stop(event); - return; - case Event.KEY_LEFT: - case Event.KEY_RIGHT: - return; - case Event.KEY_UP: - this.markPrevious(); - this.render(); - Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - Event.stop(event); - return; - } - else - if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; - - this.changed = true; - this.hasFocus = true; - - if(this.observer) clearTimeout(this.observer); - this.observer = - setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) - { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index-- - else this.index = this.entryCount-1; - this.getEntry(this.index).scrollIntoView(true); - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++ - else this.index = 0; - this.getEntry(this.index).scrollIntoView(false); - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = $(selectedElement).select('.' + this.options.select) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var bounds = this.getTokenBounds(); - if (bounds[0] != -1) { - var newValue = this.element.value.substr(0, bounds[0]); - var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value + this.element.value.substr(bounds[1]); - } else { - this.element.value = value; - } - this.oldElementValue = this.element.value; - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.down()); - - if(this.update.firstChild && this.update.down().childNodes) { - this.entryCount = - this.update.down().childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { - this.entryCount = 0; - } - - this.stopIndicator(); - this.index = 0; - - if(this.entryCount==1 && this.options.autoSelect) { - this.selectEntry(); - this.hide(); - } else { - this.render(); - } - } - }, - - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - this.tokenBounds = null; - if(this.getToken().length>=this.options.minChars) { - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - this.oldElementValue = this.element.value; - }, - - getToken: function() { - var bounds = this.getTokenBounds(); - return this.element.value.substring(bounds[0], bounds[1]).strip(); - }, - - getTokenBounds: function() { - if (null != this.tokenBounds) return this.tokenBounds; - var value = this.element.value; - if (value.strip().empty()) return [-1, 0]; - var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); - var offset = (diff == this.oldElementValue.length ? 1 : 0); - var prevTokenPos = -1, nextTokenPos = value.length; - var tp; - for (var index = 0, l = this.options.tokens.length; index < l; ++index) { - tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); - if (tp > prevTokenPos) prevTokenPos = tp; - tp = value.indexOf(this.options.tokens[index], diff + offset); - if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; - } - return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); - } -}); - -Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { - var boundary = Math.min(newS.length, oldS.length); - for (var index = 0; index < boundary; ++index) - if (newS[index] != oldS[index]) - return index; - return boundary; -}; - -Ajax.Autocompleter = Class.create(Autocompleter.Base, { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - this.startIndicator(); - - var entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } -}); - -// The local array autocompleter. Used when you'd prefer to -// inject an array of autocompletion options into the page, rather -// than sending out Ajax queries, which can be quite slow sometimes. -// -// The constructor takes four parameters. The first two are, as usual, -// the id of the monitored textbox, and id of the autocompletion menu. -// The third is the array you want to autocomplete from, and the fourth -// is the options block. -// -// Extra local autocompletion options: -// - choices - How many autocompletion choices to offer -// -// - partialSearch - If false, the autocompleter will match entered -// text only at the beginning of strings in the -// autocomplete array. Defaults to true, which will -// match text at the beginning of any *word* in the -// strings in the autocomplete array. If you want to -// search anywhere in the string, additionally set -// the option fullSearch to true (default: off). -// -// - fullSsearch - Search anywhere in autocomplete array strings. -// -// - partialChars - How many characters to enter before triggering -// a partial match (unlike minChars, which defines -// how many characters are required to do any match -// at all). Defaults to 2. -// -// - ignoreCase - Whether to ignore case when autocompleting. -// Defaults to true. -// -// It's possible to pass in a custom function as the 'selector' -// option, if you prefer to write your own autocompletion logic. -// In that case, the other options above will not apply unless -// you support them. - -Autocompleter.Local = Class.create(Autocompleter.Base, { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("
  • " + elem.substr(0, entry.length) + "" + - elem.substr(entry.length) + "
  • "); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("
  • " + elem.substr(0, foundPos) + "" + - elem.substr(foundPos, entry.length) + "" + elem.substr( - foundPos + entry.length) + "
  • "); - break; - } - } - - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) - return ""; - } - }, options || { }); - } -}); - -// AJAX in-place editor and collection editor -// Full rewrite by Christophe Porteneuve (April 2007). - -// Use this if you notice weird scrolling problems on some browsers, -// the DOM might be a bit confused when this gets called so do this -// waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); -} - -Ajax.InPlaceEditor = Class.create({ - initialize: function(element, url, options) { - this.url = url; - this.element = element = $(element); - this.prepareOptions(); - this._controls = { }; - arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! - Object.extend(this.options, options || { }); - if (!this.options.formId && this.element.id) { - this.options.formId = this.element.id + '-inplaceeditor'; - if ($(this.options.formId)) - this.options.formId = ''; - } - if (this.options.externalControl) - this.options.externalControl = $(this.options.externalControl); - if (!this.options.externalControl) - this.options.externalControlOnly = false; - this._originalBackground = this.element.getStyle('background-color') || 'transparent'; - this.element.title = this.options.clickToEditText; - this._boundCancelHandler = this.handleFormCancellation.bind(this); - this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); - this._boundFailureHandler = this.handleAJAXFailure.bind(this); - this._boundSubmitHandler = this.handleFormSubmission.bind(this); - this._boundWrapperHandler = this.wrapUp.bind(this); - this.registerListeners(); - }, - checkForEscapeOrReturn: function(e) { - if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; - if (Event.KEY_ESC == e.keyCode) - this.handleFormCancellation(e); - else if (Event.KEY_RETURN == e.keyCode) - this.handleFormSubmission(e); - }, - createControl: function(mode, handler, extraClasses) { - var control = this.options[mode + 'Control']; - var text = this.options[mode + 'Text']; - if ('button' == control) { - var btn = document.createElement('input'); - btn.type = 'submit'; - btn.value = text; - btn.className = 'editor_' + mode + '_button'; - if ('cancel' == mode) - btn.onclick = this._boundCancelHandler; - this._form.appendChild(btn); - this._controls[mode] = btn; - } else if ('link' == control) { - var link = document.createElement('a'); - link.href = '#'; - link.appendChild(document.createTextNode(text)); - link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; - link.className = 'editor_' + mode + '_link'; - if (extraClasses) - link.className += ' ' + extraClasses; - this._form.appendChild(link); - this._controls[mode] = link; - } - }, - createEditField: function() { - var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); - var fld; - if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { - fld = document.createElement('input'); - fld.type = 'text'; - var size = this.options.size || this.options.cols || 0; - if (0 < size) fld.size = size; - } else { - fld = document.createElement('textarea'); - fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); - fld.cols = this.options.cols || 40; - } - fld.name = this.options.paramName; - fld.value = text; // No HTML breaks conversion anymore - fld.className = 'editor_field'; - if (this.options.submitOnBlur) - fld.onblur = this._boundSubmitHandler; - this._controls.editor = fld; - if (this.options.loadTextURL) - this.loadExternalText(); - this._form.appendChild(this._controls.editor); - }, - createForm: function() { - var ipe = this; - function addText(mode, condition) { - var text = ipe.options['text' + mode + 'Controls']; - if (!text || condition === false) return; - ipe._form.appendChild(document.createTextNode(text)); - }; - this._form = $(document.createElement('form')); - this._form.id = this.options.formId; - this._form.addClassName(this.options.formClassName); - this._form.onsubmit = this._boundSubmitHandler; - this.createEditField(); - if ('textarea' == this._controls.editor.tagName.toLowerCase()) - this._form.appendChild(document.createElement('br')); - if (this.options.onFormCustomization) - this.options.onFormCustomization(this, this._form); - addText('Before', this.options.okControl || this.options.cancelControl); - this.createControl('ok', this._boundSubmitHandler); - addText('Between', this.options.okControl && this.options.cancelControl); - this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); - addText('After', this.options.okControl || this.options.cancelControl); - }, - destroy: function() { - if (this._oldInnerHTML) - this.element.innerHTML = this._oldInnerHTML; - this.leaveEditMode(); - this.unregisterListeners(); - }, - enterEditMode: function(e) { - if (this._saving || this._editing) return; - this._editing = true; - this.triggerCallback('onEnterEditMode'); - if (this.options.externalControl) - this.options.externalControl.hide(); - this.element.hide(); - this.createForm(); - this.element.parentNode.insertBefore(this._form, this.element); - if (!this.options.loadTextURL) - this.postProcessEditField(); - if (e) Event.stop(e); - }, - enterHover: function(e) { - if (this.options.hoverClassName) - this.element.addClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onEnterHover'); - }, - getText: function() { - return this.element.innerHTML; - }, - handleAJAXFailure: function(transport) { - this.triggerCallback('onFailure', transport); - if (this._oldInnerHTML) { - this.element.innerHTML = this._oldInnerHTML; - this._oldInnerHTML = null; - } - }, - handleFormCancellation: function(e) { - this.wrapUp(); - if (e) Event.stop(e); - }, - handleFormSubmission: function(e) { - var form = this._form; - var value = $F(this._controls.editor); - this.prepareSubmission(); - var params = this.options.callback(form, value) || ''; - if (Object.isString(params)) - params = params.toQueryParams(); - params.editorId = this.element.id; - if (this.options.htmlResponse) { - var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Updater({ success: this.element }, this.url, options); - } else { - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.url, options); - } - if (e) Event.stop(e); - }, - leaveEditMode: function() { - this.element.removeClassName(this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - if (this.options.externalControl) - this.options.externalControl.show(); - this._saving = false; - this._editing = false; - this._oldInnerHTML = null; - this.triggerCallback('onLeaveEditMode'); - }, - leaveHover: function(e) { - if (this.options.hoverClassName) - this.element.removeClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onLeaveHover'); - }, - loadExternalText: function() { - this._form.addClassName(this.options.loadingClassName); - this._controls.editor.disabled = true; - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._form.removeClassName(this.options.loadingClassName); - var text = transport.responseText; - if (this.options.stripLoadedTextTags) - text = text.stripTags(); - this._controls.editor.value = text; - this._controls.editor.disabled = false; - this.postProcessEditField(); - }.bind(this), - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - postProcessEditField: function() { - var fpc = this.options.fieldPostCreation; - if (fpc) - $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); - }, - prepareOptions: function() { - this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); - Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); - [this._extraDefaultOptions].flatten().compact().each(function(defs) { - Object.extend(this.options, defs); - }.bind(this)); - }, - prepareSubmission: function() { - this._saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - registerListeners: function() { - this._listeners = { }; - var listener; - $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { - listener = this[pair.value].bind(this); - this._listeners[pair.key] = listener; - if (!this.options.externalControlOnly) - this.element.observe(pair.key, listener); - if (this.options.externalControl) - this.options.externalControl.observe(pair.key, listener); - }.bind(this)); - }, - removeForm: function() { - if (!this._form) return; - this._form.remove(); - this._form = null; - this._controls = { }; - }, - showSaving: function() { - this._oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - this.element.addClassName(this.options.savingClassName); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - }, - triggerCallback: function(cbName, arg) { - if ('function' == typeof this.options[cbName]) { - this.options[cbName](this, arg); - } - }, - unregisterListeners: function() { - $H(this._listeners).each(function(pair) { - if (!this.options.externalControlOnly) - this.element.stopObserving(pair.key, pair.value); - if (this.options.externalControl) - this.options.externalControl.stopObserving(pair.key, pair.value); - }.bind(this)); - }, - wrapUp: function(transport) { - this.leaveEditMode(); - // Can't use triggerCallback due to backward compatibility: requires - // binding + direct element - this._boundComplete(transport, this.element); - } -}); - -Object.extend(Ajax.InPlaceEditor.prototype, { - dispose: Ajax.InPlaceEditor.prototype.destroy -}); - -Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { - initialize: function($super, element, url, options) { - this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; - $super(element, url, options); - }, - - createEditField: function() { - var list = document.createElement('select'); - list.name = this.options.paramName; - list.size = 1; - this._controls.editor = list; - this._collection = this.options.collection || []; - if (this.options.loadCollectionURL) - this.loadCollection(); - else - this.checkForExternalText(); - this._form.appendChild(this._controls.editor); - }, - - loadCollection: function() { - this._form.addClassName(this.options.loadingClassName); - this.showLoadingText(this.options.loadingCollectionText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - var js = transport.responseText.strip(); - if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check - throw 'Server returned an invalid collection representation.'; - this._collection = eval(js); - this.checkForExternalText(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadCollectionURL, options); - }, - - showLoadingText: function(text) { - this._controls.editor.disabled = true; - var tempOption = this._controls.editor.firstChild; - if (!tempOption) { - tempOption = document.createElement('option'); - tempOption.value = ''; - this._controls.editor.appendChild(tempOption); - tempOption.selected = true; - } - tempOption.update((text || '').stripScripts().stripTags()); - }, - - checkForExternalText: function() { - this._text = this.getText(); - if (this.options.loadTextURL) - this.loadExternalText(); - else - this.buildOptionList(); - }, - - loadExternalText: function() { - this.showLoadingText(this.options.loadingText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._text = transport.responseText.strip(); - this.buildOptionList(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - - buildOptionList: function() { - this._form.removeClassName(this.options.loadingClassName); - this._collection = this._collection.map(function(entry) { - return 2 === entry.length ? entry : [entry, entry].flatten(); - }); - var marker = ('value' in this.options) ? this.options.value : this._text; - var textFound = this._collection.any(function(entry) { - return entry[0] == marker; - }.bind(this)); - this._controls.editor.update(''); - var option; - this._collection.each(function(entry, index) { - option = document.createElement('option'); - option.value = entry[0]; - option.selected = textFound ? entry[0] == marker : 0 == index; - option.appendChild(document.createTextNode(entry[1])); - this._controls.editor.appendChild(option); - }.bind(this)); - this._controls.editor.disabled = false; - Field.scrollFreeActivate(this._controls.editor); - } -}); - -//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** -//**** This only exists for a while, in order to let **** -//**** users adapt to the new API. Read up on the new **** -//**** API and convert your code to it ASAP! **** - -Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { - if (!options) return; - function fallback(name, expr) { - if (name in options || expr === undefined) return; - options[name] = expr; - }; - fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : - options.cancelLink == options.cancelButton == false ? false : undefined))); - fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : - options.okLink == options.okButton == false ? false : undefined))); - fallback('highlightColor', options.highlightcolor); - fallback('highlightEndColor', options.highlightendcolor); -}; - -Object.extend(Ajax.InPlaceEditor, { - DefaultOptions: { - ajaxOptions: { }, - autoRows: 3, // Use when multi-line w/ rows == 1 - cancelControl: 'link', // 'link'|'button'|false - cancelText: 'cancel', - clickToEditText: 'Click to edit', - externalControl: null, // id|elt - externalControlOnly: false, - fieldPostCreation: 'activate', // 'activate'|'focus'|false - formClassName: 'inplaceeditor-form', - formId: null, // id|elt - highlightColor: '#ffff99', - highlightEndColor: '#ffffff', - hoverClassName: '', - htmlResponse: true, - loadingClassName: 'inplaceeditor-loading', - loadingText: 'Loading...', - okControl: 'button', // 'link'|'button'|false - okText: 'ok', - paramName: 'value', - rows: 1, // If 1 and multi-line, uses autoRows - savingClassName: 'inplaceeditor-saving', - savingText: 'Saving...', - size: 0, - stripLoadedTextTags: false, - submitOnBlur: false, - textAfterControls: '', - textBeforeControls: '', - textBetweenControls: '' - }, - DefaultCallbacks: { - callback: function(form) { - return Form.serialize(form); - }, - onComplete: function(transport, element) { - // For backward compatibility, this one is bound to the IPE, and passes - // the element directly. It was too often customized, so we don't break it. - new Effect.Highlight(element, { - startcolor: this.options.highlightColor, keepBackgroundImage: true }); - }, - onEnterEditMode: null, - onEnterHover: function(ipe) { - ipe.element.style.backgroundColor = ipe.options.highlightColor; - if (ipe._effect) - ipe._effect.cancel(); - }, - onFailure: function(transport, ipe) { - alert('Error communication with the server: ' + transport.responseText.stripTags()); - }, - onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. - onLeaveEditMode: null, - onLeaveHover: function(ipe) { - ipe._effect = new Effect.Highlight(ipe.element, { - startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, - restorecolor: ipe._originalBackground, keepBackgroundImage: true - }); - } - }, - Listeners: { - click: 'enterEditMode', - keydown: 'checkForEscapeOrReturn', - mouseover: 'enterHover', - mouseout: 'leaveHover' - } -}); - -Ajax.InPlaceCollectionEditor.DefaultOptions = { - loadingCollectionText: 'Loading options...' -}; - -// Delayed observer, like Form.Element.Observer, -// but waits for delay after last key input -// Ideal for live-search fields - -Form.Element.DelayedObserver = Class.create({ - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } -}); diff --git a/vendor/plugins/clearance/test/rails_root/public/javascripts/dragdrop.js b/vendor/plugins/clearance/test/rails_root/public/javascripts/dragdrop.js deleted file mode 100644 index bf5cfea..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/javascripts/dragdrop.js +++ /dev/null @@ -1,972 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -if(Object.isUndefined(Effect)) - throw("dragdrop.js requires including script.aculo.us' effects.js library"); - -var Droppables = { - drops: [], - - remove: function(element) { - this.drops = this.drops.reject(function(d) { return d.element==$(element) }); - }, - - add: function(element) { - element = $(element); - var options = Object.extend({ - greedy: true, - hoverclass: null, - tree: false - }, arguments[1] || { }); - - // cache containers - if(options.containment) { - options._containers = []; - var containment = options.containment; - if(Object.isArray(containment)) { - containment.each( function(c) { options._containers.push($(c)) }); - } else { - options._containers.push($(containment)); - } - } - - if(options.accept) options.accept = [options.accept].flatten(); - - Element.makePositioned(element); // fix IE - options.element = element; - - this.drops.push(options); - }, - - findDeepestChild: function(drops) { - deepest = drops[0]; - - for (i = 1; i < drops.length; ++i) - if (Element.isParent(drops[i].element, deepest.element)) - deepest = drops[i]; - - return deepest; - }, - - isContained: function(element, drop) { - var containmentNode; - if(drop.tree) { - containmentNode = element.treeNode; - } else { - containmentNode = element.parentNode; - } - return drop._containers.detect(function(c) { return containmentNode == c }); - }, - - isAffected: function(point, element, drop) { - return ( - (drop.element!=element) && - ((!drop._containers) || - this.isContained(element, drop)) && - ((!drop.accept) || - (Element.classNames(element).detect( - function(v) { return drop.accept.include(v) } ) )) && - Position.within(drop.element, point[0], point[1]) ); - }, - - deactivate: function(drop) { - if(drop.hoverclass) - Element.removeClassName(drop.element, drop.hoverclass); - this.last_active = null; - }, - - activate: function(drop) { - if(drop.hoverclass) - Element.addClassName(drop.element, drop.hoverclass); - this.last_active = drop; - }, - - show: function(point, element) { - if(!this.drops.length) return; - var drop, affected = []; - - this.drops.each( function(drop) { - if(Droppables.isAffected(point, element, drop)) - affected.push(drop); - }); - - if(affected.length>0) - drop = Droppables.findDeepestChild(affected); - - if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); - if (drop) { - Position.within(drop.element, point[0], point[1]); - if(drop.onHover) - drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); - - if (drop != this.last_active) Droppables.activate(drop); - } - }, - - fire: function(event, element) { - if(!this.last_active) return; - Position.prepare(); - - if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) - if (this.last_active.onDrop) { - this.last_active.onDrop(element, this.last_active.element, event); - return true; - } - }, - - reset: function() { - if(this.last_active) - this.deactivate(this.last_active); - } -} - -var Draggables = { - drags: [], - observers: [], - - register: function(draggable) { - if(this.drags.length == 0) { - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.updateDrag.bindAsEventListener(this); - this.eventKeypress = this.keyPress.bindAsEventListener(this); - - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - Event.observe(document, "keypress", this.eventKeypress); - } - this.drags.push(draggable); - }, - - unregister: function(draggable) { - this.drags = this.drags.reject(function(d) { return d==draggable }); - if(this.drags.length == 0) { - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - Event.stopObserving(document, "keypress", this.eventKeypress); - } - }, - - activate: function(draggable) { - if(draggable.options.delay) { - this._timeout = setTimeout(function() { - Draggables._timeout = null; - window.focus(); - Draggables.activeDraggable = draggable; - }.bind(this), draggable.options.delay); - } else { - window.focus(); // allows keypress events if window isn't currently focused, fails for Safari - this.activeDraggable = draggable; - } - }, - - deactivate: function() { - this.activeDraggable = null; - }, - - updateDrag: function(event) { - if(!this.activeDraggable) return; - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - // Mozilla-based browsers fire successive mousemove events with - // the same coordinates, prevent needless redrawing (moz bug?) - if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; - this._lastPointer = pointer; - - this.activeDraggable.updateDrag(event, pointer); - }, - - endDrag: function(event) { - if(this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } - if(!this.activeDraggable) return; - this._lastPointer = null; - this.activeDraggable.endDrag(event); - this.activeDraggable = null; - }, - - keyPress: function(event) { - if(this.activeDraggable) - this.activeDraggable.keyPress(event); - }, - - addObserver: function(observer) { - this.observers.push(observer); - this._cacheObserverCallbacks(); - }, - - removeObserver: function(element) { // element instead of observer fixes mem leaks - this.observers = this.observers.reject( function(o) { return o.element==element }); - this._cacheObserverCallbacks(); - }, - - notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' - if(this[eventName+'Count'] > 0) - this.observers.each( function(o) { - if(o[eventName]) o[eventName](eventName, draggable, event); - }); - if(draggable.options[eventName]) draggable.options[eventName](draggable, event); - }, - - _cacheObserverCallbacks: function() { - ['onStart','onEnd','onDrag'].each( function(eventName) { - Draggables[eventName+'Count'] = Draggables.observers.select( - function(o) { return o[eventName]; } - ).length; - }); - } -} - -/*--------------------------------------------------------------------------*/ - -var Draggable = Class.create({ - initialize: function(element) { - var defaults = { - handle: false, - reverteffect: function(element, top_offset, left_offset) { - var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; - new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, - queue: {scope:'_draggable', position:'end'} - }); - }, - endeffect: function(element) { - var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; - new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, - queue: {scope:'_draggable', position:'end'}, - afterFinish: function(){ - Draggable._dragging[element] = false - } - }); - }, - zindex: 1000, - revert: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } - delay: 0 - }; - - if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) - Object.extend(defaults, { - starteffect: function(element) { - element._opacity = Element.getOpacity(element); - Draggable._dragging[element] = true; - new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); - } - }); - - var options = Object.extend(defaults, arguments[1] || { }); - - this.element = $(element); - - if(options.handle && Object.isString(options.handle)) - this.handle = this.element.down('.'+options.handle, 0); - - if(!this.handle) this.handle = $(options.handle); - if(!this.handle) this.handle = this.element; - - if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { - options.scroll = $(options.scroll); - this._isScrollChild = Element.childOf(this.element, options.scroll); - } - - Element.makePositioned(this.element); // fix IE - - this.options = options; - this.dragging = false; - - this.eventMouseDown = this.initDrag.bindAsEventListener(this); - Event.observe(this.handle, "mousedown", this.eventMouseDown); - - Draggables.register(this); - }, - - destroy: function() { - Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); - Draggables.unregister(this); - }, - - currentDelta: function() { - return([ - parseInt(Element.getStyle(this.element,'left') || '0'), - parseInt(Element.getStyle(this.element,'top') || '0')]); - }, - - initDrag: function(event) { - if(!Object.isUndefined(Draggable._dragging[this.element]) && - Draggable._dragging[this.element]) return; - if(Event.isLeftClick(event)) { - // abort on form elements, fixes a Firefox issue - var src = Event.element(event); - if((tag_name = src.tagName.toUpperCase()) && ( - tag_name=='INPUT' || - tag_name=='SELECT' || - tag_name=='OPTION' || - tag_name=='BUTTON' || - tag_name=='TEXTAREA')) return; - - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = Position.cumulativeOffset(this.element); - this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); - - Draggables.activate(this); - Event.stop(event); - } - }, - - startDrag: function(event) { - this.dragging = true; - if(!this.delta) - this.delta = this.currentDelta(); - - if(this.options.zindex) { - this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); - this.element.style.zIndex = this.options.zindex; - } - - if(this.options.ghosting) { - this._clone = this.element.cloneNode(true); - this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); - if (!this.element._originallyAbsolute) - Position.absolutize(this.element); - this.element.parentNode.insertBefore(this._clone, this.element); - } - - if(this.options.scroll) { - if (this.options.scroll == window) { - var where = this._getWindowScroll(this.options.scroll); - this.originalScrollLeft = where.left; - this.originalScrollTop = where.top; - } else { - this.originalScrollLeft = this.options.scroll.scrollLeft; - this.originalScrollTop = this.options.scroll.scrollTop; - } - } - - Draggables.notify('onStart', this, event); - - if(this.options.starteffect) this.options.starteffect(this.element); - }, - - updateDrag: function(event, pointer) { - if(!this.dragging) this.startDrag(event); - - if(!this.options.quiet){ - Position.prepare(); - Droppables.show(pointer, this.element); - } - - Draggables.notify('onDrag', this, event); - - this.draw(pointer); - if(this.options.change) this.options.change(this); - - if(this.options.scroll) { - this.stopScrolling(); - - var p; - if (this.options.scroll == window) { - with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } - } else { - p = Position.page(this.options.scroll); - p[0] += this.options.scroll.scrollLeft + Position.deltaX; - p[1] += this.options.scroll.scrollTop + Position.deltaY; - p.push(p[0]+this.options.scroll.offsetWidth); - p.push(p[1]+this.options.scroll.offsetHeight); - } - var speed = [0,0]; - if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); - if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); - if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); - if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); - this.startScrolling(speed); - } - - // fix AppleWebKit rendering - if(Prototype.Browser.WebKit) window.scrollBy(0,0); - - Event.stop(event); - }, - - finishDrag: function(event, success) { - this.dragging = false; - - if(this.options.quiet){ - Position.prepare(); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - Droppables.show(pointer, this.element); - } - - if(this.options.ghosting) { - if (!this.element._originallyAbsolute) - Position.relativize(this.element); - delete this.element._originallyAbsolute; - Element.remove(this._clone); - this._clone = null; - } - - var dropped = false; - if(success) { - dropped = Droppables.fire(event, this.element); - if (!dropped) dropped = false; - } - if(dropped && this.options.onDropped) this.options.onDropped(this.element); - Draggables.notify('onEnd', this, event); - - var revert = this.options.revert; - if(revert && Object.isFunction(revert)) revert = revert(this.element); - - var d = this.currentDelta(); - if(revert && this.options.reverteffect) { - if (dropped == 0 || revert != 'failure') - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); - } else { - this.delta = d; - } - - if(this.options.zindex) - this.element.style.zIndex = this.originalZ; - - if(this.options.endeffect) - this.options.endeffect(this.element); - - Draggables.deactivate(this); - Droppables.reset(); - }, - - keyPress: function(event) { - if(event.keyCode!=Event.KEY_ESC) return; - this.finishDrag(event, false); - Event.stop(event); - }, - - endDrag: function(event) { - if(!this.dragging) return; - this.stopScrolling(); - this.finishDrag(event, true); - Event.stop(event); - }, - - draw: function(point) { - var pos = Position.cumulativeOffset(this.element); - if(this.options.ghosting) { - var r = Position.realOffset(this.element); - pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; - } - - var d = this.currentDelta(); - pos[0] -= d[0]; pos[1] -= d[1]; - - if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { - pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; - pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; - } - - var p = [0,1].map(function(i){ - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - if(this.options.snap) { - if(Object.isFunction(this.options.snap)) { - p = this.options.snap(p[0],p[1],this); - } else { - if(Object.isArray(this.options.snap)) { - p = p.map( function(v, i) { - return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)) - } else { - p = p.map( function(v) { - return (v/this.options.snap).round()*this.options.snap }.bind(this)) - } - }} - - var style = this.element.style; - if((!this.options.constraint) || (this.options.constraint=='horizontal')) - style.left = p[0] + "px"; - if((!this.options.constraint) || (this.options.constraint=='vertical')) - style.top = p[1] + "px"; - - if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering - }, - - stopScrolling: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - Draggables._lastScrollPointer = null; - } - }, - - startScrolling: function(speed) { - if(!(speed[0] || speed[1])) return; - this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; - this.lastScrolled = new Date(); - this.scrollInterval = setInterval(this.scroll.bind(this), 10); - }, - - scroll: function() { - var current = new Date(); - var delta = current - this.lastScrolled; - this.lastScrolled = current; - if(this.options.scroll == window) { - with (this._getWindowScroll(this.options.scroll)) { - if (this.scrollSpeed[0] || this.scrollSpeed[1]) { - var d = delta / 1000; - this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); - } - } - } else { - this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; - this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; - } - - Position.prepare(); - Droppables.show(Draggables._lastPointer, this.element); - Draggables.notify('onDrag', this); - if (this._isScrollChild) { - Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); - Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; - Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; - if (Draggables._lastScrollPointer[0] < 0) - Draggables._lastScrollPointer[0] = 0; - if (Draggables._lastScrollPointer[1] < 0) - Draggables._lastScrollPointer[1] = 0; - this.draw(Draggables._lastScrollPointer); - } - - if(this.options.change) this.options.change(this); - }, - - _getWindowScroll: function(w) { - var T, L, W, H; - with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { - T = documentElement.scrollTop; - L = documentElement.scrollLeft; - } else if (w.document.body) { - T = body.scrollTop; - L = body.scrollLeft; - } - if (w.innerWidth) { - W = w.innerWidth; - H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { - W = documentElement.clientWidth; - H = documentElement.clientHeight; - } else { - W = body.offsetWidth; - H = body.offsetHeight - } - } - return { top: T, left: L, width: W, height: H }; - } -}); - -Draggable._dragging = { }; - -/*--------------------------------------------------------------------------*/ - -var SortableObserver = Class.create({ - initialize: function(element, observer) { - this.element = $(element); - this.observer = observer; - this.lastValue = Sortable.serialize(this.element); - }, - - onStart: function() { - this.lastValue = Sortable.serialize(this.element); - }, - - onEnd: function() { - Sortable.unmark(); - if(this.lastValue != Sortable.serialize(this.element)) - this.observer(this.element) - } -}); - -var Sortable = { - SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, - - sortables: { }, - - _findRootElement: function(element) { - while (element.tagName.toUpperCase() != "BODY") { - if(element.id && Sortable.sortables[element.id]) return element; - element = element.parentNode; - } - }, - - options: function(element) { - element = Sortable._findRootElement($(element)); - if(!element) return; - return Sortable.sortables[element.id]; - }, - - destroy: function(element){ - var s = Sortable.options(element); - - if(s) { - Draggables.removeObserver(s.element); - s.droppables.each(function(d){ Droppables.remove(d) }); - s.draggables.invoke('destroy'); - - delete Sortable.sortables[s.element.id]; - } - }, - - create: function(element) { - element = $(element); - var options = Object.extend({ - element: element, - tag: 'li', // assumes li children, override with tag: 'tagname' - dropOnEmpty: false, - tree: false, - treeTag: 'ul', - overlap: 'vertical', // one of 'vertical', 'horizontal' - constraint: 'vertical', // one of 'vertical', 'horizontal', false - containment: element, // also takes array of elements (or id's); or false - handle: false, // or a CSS class - only: false, - delay: 0, - hoverclass: null, - ghosting: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - format: this.SERIALIZE_RULE, - - // these take arrays of elements or ids and can be - // used for better initialization performance - elements: false, - handles: false, - - onChange: Prototype.emptyFunction, - onUpdate: Prototype.emptyFunction - }, arguments[1] || { }); - - // clear any old sortable with same element - this.destroy(element); - - // build options for the draggables - var options_for_draggable = { - revert: true, - quiet: options.quiet, - scroll: options.scroll, - scrollSpeed: options.scrollSpeed, - scrollSensitivity: options.scrollSensitivity, - delay: options.delay, - ghosting: options.ghosting, - constraint: options.constraint, - handle: options.handle }; - - if(options.starteffect) - options_for_draggable.starteffect = options.starteffect; - - if(options.reverteffect) - options_for_draggable.reverteffect = options.reverteffect; - else - if(options.ghosting) options_for_draggable.reverteffect = function(element) { - element.style.top = 0; - element.style.left = 0; - }; - - if(options.endeffect) - options_for_draggable.endeffect = options.endeffect; - - if(options.zindex) - options_for_draggable.zindex = options.zindex; - - // build options for the droppables - var options_for_droppable = { - overlap: options.overlap, - containment: options.containment, - tree: options.tree, - hoverclass: options.hoverclass, - onHover: Sortable.onHover - } - - var options_for_tree = { - onHover: Sortable.onEmptyHover, - overlap: options.overlap, - containment: options.containment, - hoverclass: options.hoverclass - } - - // fix for gecko engine - Element.cleanWhitespace(element); - - options.draggables = []; - options.droppables = []; - - // drop on empty handling - if(options.dropOnEmpty || options.tree) { - Droppables.add(element, options_for_tree); - options.droppables.push(element); - } - - (options.elements || this.findElements(element, options) || []).each( function(e,i) { - var handle = options.handles ? $(options.handles[i]) : - (options.handle ? $(e).select('.' + options.handle)[0] : e); - options.draggables.push( - new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); - Droppables.add(e, options_for_droppable); - if(options.tree) e.treeNode = element; - options.droppables.push(e); - }); - - if(options.tree) { - (Sortable.findTreeElements(element, options) || []).each( function(e) { - Droppables.add(e, options_for_tree); - e.treeNode = element; - options.droppables.push(e); - }); - } - - // keep reference - this.sortables[element.id] = options; - - // for onupdate - Draggables.addObserver(new SortableObserver(element, options.onUpdate)); - - }, - - // return all suitable-for-sortable elements in a guaranteed order - findElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.tag); - }, - - findTreeElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.treeTag); - }, - - onHover: function(element, dropon, overlap) { - if(Element.isParent(dropon, element)) return; - - if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { - return; - } else if(overlap>0.5) { - Sortable.mark(dropon, 'before'); - if(dropon.previousSibling != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, dropon); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } else { - Sortable.mark(dropon, 'after'); - var nextElement = dropon.nextSibling || null; - if(nextElement != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, nextElement); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } - }, - - onEmptyHover: function(element, dropon, overlap) { - var oldParentNode = element.parentNode; - var droponOptions = Sortable.options(dropon); - - if(!Element.isParent(dropon, element)) { - var index; - - var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); - var child = null; - - if(children) { - var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); - - for (index = 0; index < children.length; index += 1) { - if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { - offset -= Element.offsetSize (children[index], droponOptions.overlap); - } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { - child = index + 1 < children.length ? children[index + 1] : null; - break; - } else { - child = children[index]; - break; - } - } - } - - dropon.insertBefore(element, child); - - Sortable.options(oldParentNode).onChange(element); - droponOptions.onChange(element); - } - }, - - unmark: function() { - if(Sortable._marker) Sortable._marker.hide(); - }, - - mark: function(dropon, position) { - // mark on ghosting only - var sortable = Sortable.options(dropon.parentNode); - if(sortable && !sortable.ghosting) return; - - if(!Sortable._marker) { - Sortable._marker = - ($('dropmarker') || Element.extend(document.createElement('DIV'))). - hide().addClassName('dropmarker').setStyle({position:'absolute'}); - document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); - } - var offsets = Position.cumulativeOffset(dropon); - Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); - - if(position=='after') - if(sortable.overlap == 'horizontal') - Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); - else - Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); - - Sortable._marker.show(); - }, - - _tree: function(element, options, parent) { - var children = Sortable.findElements(element, options) || []; - - for (var i = 0; i < children.length; ++i) { - var match = children[i].id.match(options.format); - - if (!match) continue; - - var child = { - id: encodeURIComponent(match ? match[1] : null), - element: element, - parent: parent, - children: [], - position: parent.children.length, - container: $(children[i]).down(options.treeTag) - } - - /* Get the element containing the children and recurse over it */ - if (child.container) - this._tree(child.container, options, child) - - parent.children.push (child); - } - - return parent; - }, - - tree: function(element) { - element = $(element); - var sortableOptions = this.options(element); - var options = Object.extend({ - tag: sortableOptions.tag, - treeTag: sortableOptions.treeTag, - only: sortableOptions.only, - name: element.id, - format: sortableOptions.format - }, arguments[1] || { }); - - var root = { - id: null, - parent: null, - children: [], - container: element, - position: 0 - } - - return Sortable._tree(element, options, root); - }, - - /* Construct a [i] index for a particular node */ - _constructIndex: function(node) { - var index = ''; - do { - if (node.id) index = '[' + node.position + ']' + index; - } while ((node = node.parent) != null); - return index; - }, - - sequence: function(element) { - element = $(element); - var options = Object.extend(this.options(element), arguments[1] || { }); - - return $(this.findElements(element, options) || []).map( function(item) { - return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; - }); - }, - - setSequence: function(element, new_sequence) { - element = $(element); - var options = Object.extend(this.options(element), arguments[2] || { }); - - var nodeMap = { }; - this.findElements(element, options).each( function(n) { - if (n.id.match(options.format)) - nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; - n.parentNode.removeChild(n); - }); - - new_sequence.each(function(ident) { - var n = nodeMap[ident]; - if (n) { - n[1].appendChild(n[0]); - delete nodeMap[ident]; - } - }); - }, - - serialize: function(element) { - element = $(element); - var options = Object.extend(Sortable.options(element), arguments[1] || { }); - var name = encodeURIComponent( - (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); - - if (options.tree) { - return Sortable.tree(element, arguments[1]).children.map( function (item) { - return [name + Sortable._constructIndex(item) + "[id]=" + - encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); - }).flatten().join('&'); - } else { - return Sortable.sequence(element, arguments[1]).map( function(item) { - return name + "[]=" + encodeURIComponent(item); - }).join('&'); - } - } -} - -// Returns true if child is contained within element -Element.isParent = function(child, element) { - if (!child.parentNode || child == element) return false; - if (child.parentNode == element) return true; - return Element.isParent(child.parentNode, element); -} - -Element.findChildren = function(element, only, recursive, tagName) { - if(!element.hasChildNodes()) return null; - tagName = tagName.toUpperCase(); - if(only) only = [only].flatten(); - var elements = []; - $A(element.childNodes).each( function(e) { - if(e.tagName && e.tagName.toUpperCase()==tagName && - (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) - elements.push(e); - if(recursive) { - var grandchildren = Element.findChildren(e, only, recursive, tagName); - if(grandchildren) elements.push(grandchildren); - } - }); - - return (elements.length>0 ? elements.flatten() : []); -} - -Element.offsetSize = function (element, type) { - return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; -} diff --git a/vendor/plugins/clearance/test/rails_root/public/javascripts/effects.js b/vendor/plugins/clearance/test/rails_root/public/javascripts/effects.js deleted file mode 100644 index f030b5d..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/javascripts/effects.js +++ /dev/null @@ -1,1120 +0,0 @@ -// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// Contributors: -// Justin Palmer (http://encytemedia.com/) -// Mark Pilgrim (http://diveintomark.org/) -// Martin Bialasinki -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if (this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if (this.slice(0,1) == '#') { - if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if (this.length==7) color = this.toLowerCase(); - } - } - return (color.length==7 ? color : (arguments[0] || this)); -}; - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -}; - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -}; - -Element.setContentZoom = function(element, percent) { - element = $(element); - element.setStyle({fontSize: (percent/100) + 'em'}); - if (Prototype.Browser.WebKit) window.scrollBy(0,0); - return element; -}; - -Element.getInlineOpacity = function(element){ - return $(element).style.opacity || ''; -}; - -Element.forceRerendering = function(element) { - try { - element = $(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -var Effect = { - _elementDoesNotExistError: { - name: 'ElementDoesNotExistError', - message: 'The specified DOM element does not exist, but is required for this effect to operate' - }, - Transitions: { - linear: Prototype.K, - sinoidal: function(pos) { - return (-Math.cos(pos*Math.PI)/2) + 0.5; - }, - reverse: function(pos) { - return 1-pos; - }, - flicker: function(pos) { - var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; - return pos > 1 ? 1 : pos; - }, - wobble: function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; - }, - pulse: function(pos, pulses) { - pulses = pulses || 5; - return ( - ((pos % (1/pulses)) * pulses).round() == 0 ? - ((pos * pulses * 2) - (pos * pulses * 2).floor()) : - 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) - ); - }, - spring: function(pos) { - return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); - }, - none: function(pos) { - return 0; - }, - full: function(pos) { - return 1; - } - }, - DefaultOptions: { - duration: 1.0, // seconds - fps: 100, // 100= assume 66fps max. - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' - }, - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; - - element = $(element); - $A(element.childNodes).each( function(child) { - if (child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - new Element('span', {style: tagifyStyle}).update( - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if (((typeof element == 'object') || - Object.isFunction(element)) && - (element.length)) - elements = element; - else - elements = $(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || { }); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect) { - element = $(element); - effect = (effect || 'appear').toLowerCase(); - var options = 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); - } -}; - -Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; - -/* ------------- core effects ------------- */ - -Effect.ScopedQueue = Class.create(Enumerable, { - initialize: function() { - this.effects = []; - this.interval = null; - }, - _each: function(iterator) { - this.effects._each(iterator); - }, - add: function(effect) { - var timestamp = new Date().getTime(); - - var position = Object.isString(effect.options.queue) ? - effect.options.queue : effect.options.queue.position; - - switch(position) { - case 'front': - // move unstarted effects after this effect - this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { - e.startOn += effect.finishOn; - e.finishOn += effect.finishOn; - }); - break; - case 'with-last': - timestamp = this.effects.pluck('startOn').max() || timestamp; - break; - case 'end': - // start effect after last queued effect has finished - timestamp = this.effects.pluck('finishOn').max() || timestamp; - break; - } - - effect.startOn += timestamp; - effect.finishOn += timestamp; - - if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) - this.effects.push(effect); - - if (!this.interval) - this.interval = setInterval(this.loop.bind(this), 15); - }, - remove: function(effect) { - this.effects = this.effects.reject(function(e) { return e==effect }); - if (this.effects.length == 0) { - clearInterval(this.interval); - this.interval = null; - } - }, - loop: function() { - var timePos = new Date().getTime(); - for(var i=0, len=this.effects.length;i= this.startOn) { - if (timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if (this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / this.totalTime, - frame = (pos * this.totalFrames).round(); - if (frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - cancel: function() { - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if (this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - var data = $H(); - for(property in this) - if (!Object.isFunction(this[property])) data.set(property, this[property]); - return '#'; - } -}); - -Effect.Parallel = Class.create(Effect.Base, { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if (effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Tween = Class.create(Effect.Base, { - initialize: function(object, from, to) { - object = Object.isString(object) ? $(object) : object; - var args = $A(arguments), method = args.last(), - options = args.length == 5 ? args[3] : null; - this.method = Object.isFunction(method) ? method.bind(object) : - Object.isFunction(object[method]) ? object[method].bind(object) : - function(value) { object[method] = value }; - this.start(Object.extend({ from: from, to: to }, options || { })); - }, - update: function(position) { - this.method(position); - } -}); - -Effect.Event = Class.create(Effect.Base, { - initialize: function() { - this.start(Object.extend({ duration: 0 }, arguments[0] || { })); - }, - update: Prototype.emptyFunction -}); - -Effect.Opacity = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - // make this work on IE on elements without 'layout' - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || { }); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if (this.options.mode == 'absolute') { - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: (this.options.x * position + this.originalLeft).round() + 'px', - top: (this.options.y * position + this.originalTop).round() + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); -}; - -Effect.Scale = Class.create(Effect.Base, { - initialize: function(element, percent) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or { } with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || { }); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = { }; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%','pt'].each( function(fontSizeType) { - if (fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if (this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if (/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if (!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if (this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = { }; - if (this.options.scaleX) d.width = width.round() + 'px'; - if (this.options.scaleY) d.height = height.round() + 'px'; - if (this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if (this.elementPositioning == 'absolute') { - if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if (this.options.scaleY) d.top = -topd + 'px'; - if (this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if (this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { }; - if (!this.options.keepBackgroundImage) { - this.oldStyle.backgroundImage = this.element.getStyle('background-image'); - this.element.setStyle({backgroundImage: 'none'}); - } - if (!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if (!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = function(element) { - var options = arguments[1] || { }, - scrollOffsets = document.viewport.getScrollOffsets(), - elementOffsets = $(element).cumulativeOffset(), - max = (window.height || document.body.scrollHeight) - document.viewport.getHeight(); - - if (options.offset) elementOffsets[1] += options.offset; - - return new Effect.Tween(null, - scrollOffsets.top, - elementOffsets[1] > max ? max : elementOffsets[1], - options, - function(p){ scrollTo(scrollOffsets.left, p.round()) } - ); -}; - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if (effect.options.to!=0) return; - effect.element.hide().setStyle({opacity: oldOpacity}); - } - }, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Appear = function(element) { - element = $(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from).show(); - }}, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Puff = function(element) { - element = $(element); - var oldStyle = { - opacity: element.getInlineOpacity(), - position: element.getStyle('position'), - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height - }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - Position.absolutize(effect.effects[0].element) - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().setStyle(oldStyle); } - }, arguments[1] || { }) - ); -}; - -Effect.BlindUp = function(element) { - element = $(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }, arguments[1] || { }) - ); -}; - -Effect.BlindDown = function(element) { - element = $(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || { })); -}; - -Effect.SwitchOff = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, Object.extend({ - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); - } - }) - } - }, arguments[1] || { })); -}; - -Effect.DropOut = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); - } - }, arguments[1] || { })); -}; - -Effect.Shake = function(element) { - element = $(element); - var options = Object.extend({ - distance: 20, - duration: 0.5 - }, arguments[1] || {}); - var distance = parseFloat(options.distance); - var split = parseFloat(options.duration) / 10.0; - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { - effect.element.undoPositioned().setStyle(oldStyle); - }}) }}) }}) }}) }}) }}); -}; - -Effect.SlideDown = function(element) { - element = $(element).cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || { }) - ); -}; - -Effect.SlideUp = function(element) { - element = $(element).cleanWhitespace(); - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); - } - }, arguments[1] || { }) - ); -}; - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, { - restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }); -}; - -Effect.Grow = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide().makeClipping().makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); - } - }, options) - ) - } - }); -}; - -Effect.Shrink = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } - }, options) - ); -}; - -Effect.Pulsate = function(element) { - element = $(element); - var options = arguments[1] || { }; - var oldOpacity = element.getInlineOpacity(); - var transition = options.transition || Effect.Transitions.sinoidal; - var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; - reverser.bind(transition); - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 2.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -}; - -Effect.Fold = function(element) { - element = $(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - element.makeClipping(); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().setStyle(oldStyle); - } }); - }}, arguments[1] || { })); -}; - -Effect.Morph = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - style: { } - }, arguments[1] || { }); - - if (!Object.isString(options.style)) this.style = $H(options.style); - else { - if (options.style.include(':')) - this.style = options.style.parseStyle(); - else { - this.element.addClassName(options.style); - this.style = $H(this.element.getStyles()); - this.element.removeClassName(options.style); - var css = this.element.getStyles(); - this.style = this.style.reject(function(style) { - return style.value == css[style.key]; - }); - options.afterFinishInternal = function(effect) { - effect.element.addClassName(effect.options.style); - effect.transforms.each(function(transform) { - effect.element.style[transform.style] = ''; - }); - } - } - } - this.start(options); - }, - - setup: function(){ - function parseColor(color){ - if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; - color = color.parseColor(); - return $R(0,2).map(function(i){ - return parseInt( color.slice(i*2+1,i*2+3), 16 ) - }); - } - this.transforms = this.style.map(function(pair){ - var property = pair[0], value = pair[1], unit = null; - - if (value.parseColor('#zzzzzz') != '#zzzzzz') { - value = value.parseColor(); - unit = 'color'; - } else if (property == 'opacity') { - value = parseFloat(value); - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - } else if (Element.CSS_LENGTH.test(value)) { - var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); - value = parseFloat(components[1]); - unit = (components.length == 3) ? components[2] : null; - } - - var originalValue = this.element.getStyle(property); - return { - style: property.camelize(), - originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), - targetValue: unit=='color' ? parseColor(value) : value, - unit: unit - }; - }.bind(this)).reject(function(transform){ - return ( - (transform.originalValue == transform.targetValue) || - ( - transform.unit != 'color' && - (isNaN(transform.originalValue) || isNaN(transform.targetValue)) - ) - ) - }); - }, - update: function(position) { - var style = { }, transform, i = this.transforms.length; - while(i--) - style[(transform = this.transforms[i]).style] = - transform.unit=='color' ? '#'+ - (Math.round(transform.originalValue[0]+ - (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + - (Math.round(transform.originalValue[1]+ - (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + - (Math.round(transform.originalValue[2]+ - (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : - (transform.originalValue + - (transform.targetValue - transform.originalValue) * position).toFixed(3) + - (transform.unit === null ? '' : transform.unit); - this.element.setStyle(style, true); - } -}); - -Effect.Transform = Class.create({ - initialize: function(tracks){ - this.tracks = []; - this.options = arguments[1] || { }; - this.addTracks(tracks); - }, - addTracks: function(tracks){ - tracks.each(function(track){ - track = $H(track); - var data = track.values().first(); - this.tracks.push($H({ - ids: track.keys().first(), - effect: Effect.Morph, - options: { style: data } - })); - }.bind(this)); - return this; - }, - play: function(){ - return new Effect.Parallel( - this.tracks.map(function(track){ - var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); - var elements = [$(ids) || $$(ids)].flatten(); - return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); - }).flatten(), - this.options - ); - } -}); - -Element.CSS_PROPERTIES = $w( - 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + - 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + - 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + - 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + - 'fontSize fontWeight height left letterSpacing lineHeight ' + - 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ - 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + - 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + - 'right textIndent top width wordSpacing zIndex'); - -Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; - -String.__parseStyleElement = document.createElement('div'); -String.prototype.parseStyle = function(){ - var style, styleRules = $H(); - if (Prototype.Browser.WebKit) - style = new Element('div',{style:this}).style; - else { - String.__parseStyleElement.innerHTML = '
    '; - style = String.__parseStyleElement.childNodes[0].style; - } - - Element.CSS_PROPERTIES.each(function(property){ - if (style[property]) styleRules.set(property, style[property]); - }); - - if (Prototype.Browser.IE && this.include('opacity')) - styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); - - return styleRules; -}; - -if (document.defaultView && document.defaultView.getComputedStyle) { - Element.getStyles = function(element) { - var css = document.defaultView.getComputedStyle($(element), null); - return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { - styles[property] = css[property]; - return styles; - }); - }; -} else { - Element.getStyles = function(element) { - element = $(element); - var css = element.currentStyle, styles; - styles = Element.CSS_PROPERTIES.inject({ }, function(hash, property) { - hash.set(property, css[property]); - return hash; - }); - if (!styles.opacity) styles.set('opacity', element.getOpacity()); - return styles; - }; -}; - -Effect.Methods = { - morph: function(element, style) { - element = $(element); - new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); - return element; - }, - visualEffect: function(element, effect, options) { - element = $(element) - var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[klass](element, options); - return element; - }, - highlight: function(element, options) { - element = $(element); - new Effect.Highlight(element, options); - return element; - } -}; - -$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ - 'pulsate shake puff squish switchOff dropOut').each( - function(effect) { - Effect.Methods[effect] = function(element, options){ - element = $(element); - Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); - return element; - } - } -); - -$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( - function(f) { Effect.Methods[f] = Element[f]; } -); - -Element.addMethods(Effect.Methods); diff --git a/vendor/plugins/clearance/test/rails_root/public/javascripts/prototype.js b/vendor/plugins/clearance/test/rails_root/public/javascripts/prototype.js deleted file mode 100644 index 546f9fe..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/javascripts/prototype.js +++ /dev/null @@ -1,4225 +0,0 @@ -/* Prototype JavaScript framework, version 1.6.0.1 - * (c) 2005-2007 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/ - * - *--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.6.0.1', - - Browser: { - IE: !!(window.attachEvent && !window.opera), - Opera: !!window.opera, - WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, - Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, - MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) - }, - - BrowserFeatures: { - XPath: !!document.evaluate, - ElementExtensions: !!window.HTMLElement, - SpecificElementExtensions: - document.createElement('div').__proto__ && - document.createElement('div').__proto__ !== - document.createElement('form').__proto__ - }, - - ScriptFragment: ']*>([\\S\\s]*?)<\/script>', - JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, - - emptyFunction: function() { }, - K: function(x) { return x } -}; - -if (Prototype.Browser.MobileSafari) - Prototype.BrowserFeatures.SpecificElementExtensions = false; - - -/* Based on Alex Arnell's inheritance implementation. */ -var Class = { - create: function() { - var parent = null, properties = $A(arguments); - if (Object.isFunction(properties[0])) - parent = properties.shift(); - - function klass() { - this.initialize.apply(this, arguments); - } - - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - var subclass = function() { }; - subclass.prototype = parent.prototype; - klass.prototype = new subclass; - parent.subclasses.push(klass); - } - - for (var i = 0; i < properties.length; i++) - klass.addMethods(properties[i]); - - if (!klass.prototype.initialize) - klass.prototype.initialize = Prototype.emptyFunction; - - klass.prototype.constructor = klass; - - return klass; - } -}; - -Class.Methods = { - addMethods: function(source) { - var ancestor = this.superclass && this.superclass.prototype; - var properties = Object.keys(source); - - if (!Object.keys({ toString: true }).length) - properties.push("toString", "valueOf"); - - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i], value = source[property]; - if (ancestor && Object.isFunction(value) && - value.argumentNames().first() == "$super") { - var method = value, value = Object.extend((function(m) { - return function() { return ancestor[m].apply(this, arguments) }; - })(property).wrap(method), { - valueOf: function() { return method }, - toString: function() { return method.toString() } - }); - } - this.prototype[property] = value; - } - - return this; - } -}; - -var Abstract = { }; - -Object.extend = function(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; -}; - -Object.extend(Object, { - inspect: function(object) { - try { - if (Object.isUndefined(object)) return 'undefined'; - if (object === null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } - }, - - toJSON: function(object) { - var type = typeof object; - switch (type) { - case 'undefined': - case 'function': - case 'unknown': return; - case 'boolean': return object.toString(); - } - - if (object === null) return 'null'; - if (object.toJSON) return object.toJSON(); - if (Object.isElement(object)) return; - - var results = []; - for (var property in object) { - var value = Object.toJSON(object[property]); - if (!Object.isUndefined(value)) - results.push(property.toJSON() + ': ' + value); - } - - return '{' + results.join(', ') + '}'; - }, - - toQueryString: function(object) { - return $H(object).toQueryString(); - }, - - toHTML: function(object) { - return object && object.toHTML ? object.toHTML() : String.interpret(object); - }, - - keys: function(object) { - var keys = []; - for (var property in object) - keys.push(property); - return keys; - }, - - values: function(object) { - var values = []; - for (var property in object) - values.push(object[property]); - return values; - }, - - clone: function(object) { - return Object.extend({ }, object); - }, - - isElement: function(object) { - return object && object.nodeType == 1; - }, - - isArray: function(object) { - return object && object.constructor === Array; - }, - - isHash: function(object) { - return object instanceof Hash; - }, - - isFunction: function(object) { - return typeof object == "function"; - }, - - isString: function(object) { - return typeof object == "string"; - }, - - isNumber: function(object) { - return typeof object == "number"; - }, - - isUndefined: function(object) { - return typeof object == "undefined"; - } -}); - -Object.extend(Function.prototype, { - argumentNames: function() { - var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); - return names.length == 1 && !names[0] ? [] : names; - }, - - bind: function() { - if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } - }, - - bindAsEventListener: function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function(event) { - return __method.apply(object, [event || window.event].concat(args)); - } - }, - - curry: function() { - if (!arguments.length) return this; - var __method = this, args = $A(arguments); - return function() { - return __method.apply(this, args.concat($A(arguments))); - } - }, - - delay: function() { - var __method = this, args = $A(arguments), timeout = args.shift() * 1000; - return window.setTimeout(function() { - return __method.apply(__method, args); - }, timeout); - }, - - wrap: function(wrapper) { - var __method = this; - return function() { - return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); - } - }, - - methodize: function() { - if (this._methodized) return this._methodized; - var __method = this; - return this._methodized = function() { - return __method.apply(null, [this].concat($A(arguments))); - }; - } -}); - -Function.prototype.defer = Function.prototype.delay.curry(0.01); - -Date.prototype.toJSON = function() { - return '"' + this.getUTCFullYear() + '-' + - (this.getUTCMonth() + 1).toPaddedString(2) + '-' + - this.getUTCDate().toPaddedString(2) + 'T' + - this.getUTCHours().toPaddedString(2) + ':' + - this.getUTCMinutes().toPaddedString(2) + ':' + - 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; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - execute: function() { - this.callback(this); - }, - - stop: function() { - if (!this.timer) return; - clearInterval(this.timer); - this.timer = null; - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.execute(); - } finally { - this.currentlyExecuting = false; - } - } - } -}); -Object.extend(String, { - interpret: function(value) { - return value == null ? '' : String(value); - }, - specialChar: { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '\\': '\\\\' - } -}); - -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { - var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += String.interpret(replacement(match)); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - }, - - sub: function(pattern, replacement, count) { - replacement = this.gsub.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) { - this.gsub(pattern, iterator); - return String(this); - }, - - truncate: function(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() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, - - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - 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() { - return this.extractScripts().map(function(script) { return eval(script) }); - }, - - escapeHTML: function() { - var self = arguments.callee; - self.text.data = this; - return self.div.innerHTML; - }, - - 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) { - var match = this.strip().match(/([^?#]*)(#.*)?$/); - if (!match) return { }; - - return match[1].split(separator || '&').inject({ }, function(hash, pair) { - if ((pair = pair.split('='))[0]) { - var key = decodeURIComponent(pair.shift()); - var value = pair.length > 1 ? pair.join('=') : pair[0]; - if (value != undefined) value = decodeURIComponent(value); - - if (key in hash) { - if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; - hash[key].push(value); - } - else hash[key] = value; - } - return hash; - }); - }, - - toArray: function() { - return this.split(''); - }, - - succ: function() { - return this.slice(0, this.length - 1) + - String.fromCharCode(this.charCodeAt(this.length - 1) + 1); - }, - - times: function(count) { - return count < 1 ? '' : new Array(count + 1).join(this); - }, - - camelize: function() { - var parts = this.split('-'), len = parts.length; - if (len == 1) return parts[0]; - - var camelized = this.charAt(0) == '-' - ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) - : parts[0]; - - for (var i = 1; i < len; i++) - camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); - - return camelized; - }, - - capitalize: function() { - 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(); - }, - - dasherize: function() { - return this.gsub(/_/,'-'); - }, - - 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); - }); - if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; - return "'" + escapedString.replace(/'/g, '\\\'') + "'"; - }, - - toJSON: function() { - return this.inspect(true); - }, - - unfilterJSON: function(filter) { - return this.sub(filter || Prototype.JSONFilter, '#{1}'); - }, - - isJSON: function() { - 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) { - 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) { - return this.indexOf(pattern) > -1; - }, - - startsWith: function(pattern) { - return this.indexOf(pattern) === 0; - }, - - endsWith: function(pattern) { - var d = this.length - pattern.length; - return d >= 0 && this.lastIndexOf(pattern) === d; - }, - - empty: function() { - return this == ''; - }, - - blank: function() { - return /^\s*$/.test(this); - }, - - interpolate: function(object, pattern) { - return new Template(this, pattern).evaluate(object); - } -}); - -if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { - escapeHTML: function() { - return this.replace(/&/g,'&').replace(//g,'>'); - }, - unescapeHTML: function() { - return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); - } -}); - -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('') -}); - -with (String.prototype.escapeHTML) div.appendChild(text); - -var Template = Class.create({ - initialize: function(template, pattern) { - this.template = template.toString(); - this.pattern = pattern || Template.Pattern; - }, - - evaluate: function(object) { - if (Object.isFunction(object.toTemplateReplacements)) - object = object.toTemplateReplacements(); - - return this.template.gsub(this.pattern, function(match) { - if (object == null) return ''; - - var before = match[1] || ''; - if (before == '\\') return match[2]; - - var ctx = object, expr = match[3]; - var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; - match = pattern.exec(expr); - if (match == null) return before; - - while (match != null) { - var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; - ctx = ctx[comp]; - if (null == ctx || '' == match[3]) break; - expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); - match = pattern.exec(expr); - } - - return before + String.interpret(ctx); - }.bind(this)); - } -}); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; - -var $break = { }; - -var Enumerable = { - each: function(iterator, context) { - var index = 0; - iterator = iterator.bind(context); - try { - this._each(function(value) { - iterator(value, index++); - }); - } catch (e) { - if (e != $break) throw e; - } - return this; - }, - - eachSlice: function(number, iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var index = -number, slices = [], array = this.toArray(); - while ((index += number) < array.length) - slices.push(array.slice(index, index+number)); - return slices.collect(iterator, context); - }, - - all: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result = true; - this.each(function(value, index) { - result = result && !!iterator(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result = false; - this.each(function(value, index) { - if (result = !!iterator(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function(iterator, context) { - iterator = iterator.bind(context); - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator, context) { - iterator = iterator.bind(context); - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(filter, iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var results = []; - - if (Object.isString(filter)) - filter = new RegExp(filter); - - this.each(function(value, index) { - if (filter.match(value)) - results.push(iterator(value, index)); - }); - return results; - }, - - include: function(object) { - if (Object.isFunction(this.indexOf)) - if (this.indexOf(object) != -1) return true; - - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inGroupsOf: function(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) { - iterator = iterator.bind(context); - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.map(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result; - this.each(function(value, index) { - value = iterator(value, index); - if (result == null || value >= result) - result = value; - }); - return result; - }, - - min: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result; - this.each(function(value, index) { - value = iterator(value, index); - if (result == null || value < result) - result = value; - }); - return result; - }, - - partition: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var trues = [], falses = []; - this.each(function(value, index) { - (iterator(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator, context) { - iterator = iterator.bind(context); - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator, context) { - iterator = iterator.bind(context); - return this.map(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.map(); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (Object.isFunction(args.last())) - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - return iterator(collections.pluck(index)); - }); - }, - - size: function() { - return this.toArray().length; - }, - - inspect: function() { - return '#'; - } -}; - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - filter: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray, - every: Enumerable.all, - some: Enumerable.any -}); -function $A(iterable) { - if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); - var length = iterable.length, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; -} - -if (Prototype.Browser.WebKit) { - function $A(iterable) { - if (!iterable) return []; - if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && - iterable.toArray) return iterable.toArray(); - var length = iterable.length, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; - } -} - -Array.from = $A; - -Object.extend(Array.prototype, Enumerable); - -if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0, length = this.length; i < length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(Object.isArray(value) ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - reduce: function() { - return this.length > 1 ? this : this[0]; - }, - - uniq: function(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) { - return this.uniq().findAll(function(item) { - return array.detect(function(value) { return item === value }); - }); - }, - - clone: function() { - return [].concat(this); - }, - - size: function() { - return this.length; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - }, - - toJSON: function() { - var results = []; - this.each(function(object) { - var value = Object.toJSON(object); - if (!Object.isUndefined(value)) results.push(value); - }); - 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 $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} - -if (Prototype.Browser.Opera){ - Array.prototype.concat = function() { - var array = []; - for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); - 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]); - } else { - array.push(arguments[i]); - } - } - return array; - }; -} -Object.extend(Number.prototype, { - toColorPart: function() { - return this.toPaddedString(2, 16); - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - }, - - toPaddedString: function(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - }, - - toJSON: function() { - return isFinite(this) ? this.toString() : 'null'; - } -}); - -$w('abs round ceil floor').each(function(method){ - Number.prototype[method] = Math[method].methodize(); -}); -function $H(object) { - return new Hash(object); -}; - -var Hash = Class.create(Enumerable, (function() { - - function toQueryPair(key, value) { - if (Object.isUndefined(value)) return key; - return key + '=' + encodeURIComponent(String.interpret(value)); - } - - return { - initialize: function(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - }, - - _each: function(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - set: function(key, value) { - return this._object[key] = value; - }, - - get: function(key) { - return this._object[key]; - }, - - unset: function(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - }, - - toObject: function() { - return Object.clone(this._object); - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - index: function(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - }, - - merge: function(object) { - return this.clone().update(object); - }, - - update: function(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return values.map(toQueryPair.curry(key)).join('&'); - } - return toQueryPair(key, values); - }).join('&'); - }, - - inspect: function() { - return '#'; - }, - - toJSON: function() { - return Object.toJSON(this.toObject()); - }, - - clone: function() { - return new Hash(this); - } - } -})()); - -Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; -Hash.from = $H; -var ObjectRange = Class.create(Enumerable, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - while (this.include(value)) { - iterator(value); - value = value.succ(); - } - }, - - include: function(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); -}; - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new XMLHttpRequest()}, - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')} - ) || false; - }, - - activeRequestCount: 0 -}; - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responder) { - if (!this.include(responder)) - this.responders.push(responder); - }, - - unregister: function(responder) { - this.responders = this.responders.without(responder); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (Object.isFunction(responder[callback])) { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) { } - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { Ajax.activeRequestCount++ }, - onComplete: function() { Ajax.activeRequestCount-- } -}); - -Ajax.Base = Class.create({ - initialize: function(options) { - this.options = { - method: 'post', - asynchronous: true, - contentType: 'application/x-www-form-urlencoded', - encoding: 'UTF-8', - parameters: '', - evalJSON: true, - evalJS: true - }; - Object.extend(this.options, options || { }); - - this.options.method = this.options.method.toLowerCase(); - - if (Object.isString(this.options.parameters)) - this.options.parameters = this.options.parameters.toQueryParams(); - else if (Object.isHash(this.options.parameters)) - this.options.parameters = this.options.parameters.toObject(); - } -}); - -Ajax.Request = Class.create(Ajax.Base, { - _complete: false, - - initialize: function($super, url, options) { - $super(options); - this.transport = Ajax.getTransport(); - this.request(url); - }, - - request: function(url) { - this.url = url; - this.method = this.options.method; - 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'; - } - - 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)) - params += '&_='; - } - - try { - var response = new Ajax.Response(this); - if (this.options.onCreate) this.options.onCreate(response); - Ajax.Responders.dispatch('onCreate', this, response); - - this.transport.open(this.method.toUpperCase(), this.url, - this.options.asynchronous); - - if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); - - this.transport.onreadystatechange = this.onStateChange.bind(this); - this.setRequestHeaders(); - - this.body = this.method == 'post' ? (this.options.postBody || params) : null; - this.transport.send(this.body); - - /* Force Firefox to handle ready state 4 for synchronous requests */ - if (!this.options.asynchronous && this.transport.overrideMimeType) - this.onStateChange(); - - } - catch (e) { - this.dispatchException(e); - } - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState > 1 && !((readyState == 4) && this._complete)) - this.respondToReadyState(this.transport.readyState); - }, - - setRequestHeaders: function() { - var headers = { - 'X-Requested-With': 'XMLHttpRequest', - 'X-Prototype-Version': Prototype.Version, - 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' - }; - - if (this.method == 'post') { - headers['Content-type'] = this.options.contentType + - (this.options.encoding ? '; charset=' + this.options.encoding : ''); - - /* Force "Connection: close" for older Mozilla browsers to work - * around a bug where XMLHttpRequest sends an incorrect - * Content-length header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType && - (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) - headers['Connection'] = 'close'; - } - - // user-defined headers - if (typeof this.options.requestHeaders == 'object') { - var extras = this.options.requestHeaders; - - if (Object.isFunction(extras.push)) - for (var i = 0, length = extras.length; i < length; i += 2) - headers[extras[i]] = extras[i+1]; - else - $H(extras).each(function(pair) { headers[pair.key] = pair.value }); - } - - for (var name in headers) - this.transport.setRequestHeader(name, headers[name]); - }, - - success: function() { - var status = this.getStatus(); - return !status || (status >= 200 && status < 300); - }, - - getStatus: function() { - try { - return this.transport.status || 0; - } catch (e) { return 0 } - }, - - respondToReadyState: function(readyState) { - var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); - - if (state == 'Complete') { - try { - this._complete = true; - (this.options['on' + response.status] - || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - var contentType = response.getHeader('Content-type'); - if (this.options.evalJS == 'force' - || (this.options.evalJS && contentType - && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) - this.evalResponse(); - } - - try { - (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); - Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - if (state == 'Complete') { - // avoid memory leak in MSIE: clean up - this.transport.onreadystatechange = Prototype.emptyFunction; - } - }, - - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name); - } catch (e) { return null } - }, - - evalResponse: function() { - try { - return eval((this.transport.responseText || '').unfilterJSON()); - } catch (e) { - this.dispatchException(e); - } - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Response = Class.create({ - initialize: function(request){ - this.request = request; - var transport = this.transport = request.transport, - readyState = this.readyState = transport.readyState; - - if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { - this.status = this.getStatus(); - this.statusText = this.getStatusText(); - this.responseText = String.interpret(transport.responseText); - this.headerJSON = this._getHeaderJSON(); - } - - if(readyState == 4) { - var xml = transport.responseXML; - this.responseXML = Object.isUndefined(xml) ? null : xml; - this.responseJSON = this._getResponseJSON(); - } - }, - - status: 0, - statusText: '', - - getStatus: Ajax.Request.prototype.getStatus, - - getStatusText: function() { - try { - return this.transport.statusText || ''; - } catch (e) { return '' } - }, - - getHeader: Ajax.Request.prototype.getHeader, - - getAllHeaders: function() { - try { - return this.getAllResponseHeaders(); - } catch (e) { return null } - }, - - getResponseHeader: function(name) { - return this.transport.getResponseHeader(name); - }, - - getAllResponseHeaders: function() { - return this.transport.getAllResponseHeaders(); - }, - - _getHeaderJSON: function() { - var json = this.getHeader('X-JSON'); - if (!json) return null; - json = decodeURIComponent(escape(json)); - try { - return json.evalJSON(this.request.options.sanitizeJSON); - } catch (e) { - this.request.dispatchException(e); - } - }, - - _getResponseJSON: function() { - var options = this.request.options; - if (!options.evalJSON || (options.evalJSON != 'force' && - !(this.getHeader('Content-type') || '').include('application/json')) || - this.responseText.blank()) - return null; - try { - return this.responseText.evalJSON(options.sanitizeJSON); - } catch (e) { - this.request.dispatchException(e); - } - } -}); - -Ajax.Updater = Class.create(Ajax.Request, { - initialize: function($super, container, url, options) { - this.container = { - success: (container.success || container), - failure: (container.failure || (container.success ? null : container)) - }; - - options = Object.clone(options); - var onComplete = options.onComplete; - options.onComplete = (function(response, json) { - this.updateContent(response.responseText); - if (Object.isFunction(onComplete)) onComplete(response, json); - }).bind(this); - - $super(url, options); - }, - - updateContent: function(responseText) { - var receiver = this.container[this.success() ? 'success' : 'failure'], - options = this.options; - - if (!options.evalScripts) responseText = responseText.stripScripts(); - - if (receiver = $(receiver)) { - if (options.insertion) { - if (Object.isString(options.insertion)) { - var insertion = { }; insertion[options.insertion] = responseText; - receiver.insert(insertion); - } - else options.insertion(receiver, responseText); - } - else receiver.update(responseText); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { - initialize: function($super, container, url, options) { - $super(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = { }; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.options.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(response) { - if (this.options.decay) { - this.decay = (response.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = response.responseText; - } - this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); - }, - - onTimerEvent: function() { - 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++) - elements.push($(arguments[i])); - return elements; - } - if (Object.isString(element)) - element = document.getElementById(element); - return Element.extend(element); -} - -if (Prototype.BrowserFeatures.XPath) { - document._getElementsByXPath = function(expression, parentElement) { - var results = []; - var query = document.evaluate(expression, $(parentElement) || document, - null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - for (var i = 0, length = query.snapshotLength; i < length; i++) - results.push(Element.extend(query.snapshotItem(i))); - return results; - }; -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Node) var Node = { }; - -if (!Node.ELEMENT_NODE) { - // DOM level 2 ECMAScript Language Binding - Object.extend(Node, { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE: 12 - }); -} - -(function() { - var element = this.Element; - this.Element = function(tagName, attributes) { - attributes = attributes || { }; - tagName = tagName.toLowerCase(); - var cache = Element.cache; - if (Prototype.Browser.IE && attributes.name) { - tagName = '<' + tagName + ' name="' + attributes.name + '">'; - delete attributes.name; - return Element.writeAttribute(document.createElement(tagName), attributes); - } - if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); - return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); - }; - Object.extend(this.Element, element || { }); -}).call(window); - -Element.cache = { }; - -Element.Methods = { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function(element) { - element = $(element); - Element[Element.visible(element) ? 'hide' : 'show'](element); - return element; - }, - - hide: function(element) { - $(element).style.display = 'none'; - return element; - }, - - show: function(element) { - $(element).style.display = ''; - return element; - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - 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; - }, - - replace: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - else if (!Object.isElement(content)) { - content = Object.toHTML(content); - var range = element.ownerDocument.createRange(); - range.selectNode(element); - content.evalScripts.bind(content).defer(); - content = range.createContextualFragment(content.stripScripts()); - } - element.parentNode.replaceChild(content, element); - return element; - }, - - insert: function(element, insertions) { - element = $(element); - - if (Object.isString(insertions) || Object.isNumber(insertions) || - Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = {bottom:insertions}; - - var content, t, range; - - for (position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - t = Element._insertionTranslations[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - t.insert(element, content); - continue; - } - - content = Object.toHTML(content); - - range = element.ownerDocument.createRange(); - t.initializeRange(element, range); - t.insert(element, range.createContextualFragment(content.stripScripts())); - - content.evalScripts.bind(content).defer(); - } - - return element; - }, - - wrap: function(element, wrapper, attributes) { - element = $(element); - if (Object.isElement(wrapper)) - $(wrapper).writeAttribute(attributes || { }); - else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); - else wrapper = new Element('div', wrapper); - if (element.parentNode) - element.parentNode.replaceChild(wrapper, element); - wrapper.appendChild(element); - return wrapper; - }, - - inspect: function(element) { - element = $(element); - var result = '<' + element.tagName.toLowerCase(); - $H({'id': 'id', 'className': 'class'}).each(function(pair) { - var property = pair.first(), attribute = pair.last(); - var value = (element[property] || '').toString(); - if (value) result += ' ' + attribute + '=' + value.inspect(true); - }); - return result + '>'; - }, - - recursivelyCollect: function(element, property) { - element = $(element); - var elements = []; - while (element = element[property]) - if (element.nodeType == 1) - elements.push(Element.extend(element)); - return elements; - }, - - ancestors: function(element) { - return $(element).recursivelyCollect('parentNode'); - }, - - descendants: function(element) { - return $(element).getElementsBySelector("*"); - }, - - firstDescendant: function(element) { - element = $(element).firstChild; - while (element && element.nodeType != 1) element = element.nextSibling; - return $(element); - }, - - immediateDescendants: function(element) { - if (!(element = $(element).firstChild)) return []; - while (element && element.nodeType != 1) element = element.nextSibling; - if (element) return [element].concat($(element).nextSiblings()); - return []; - }, - - previousSiblings: function(element) { - return $(element).recursivelyCollect('previousSibling'); - }, - - nextSiblings: function(element) { - return $(element).recursivelyCollect('nextSibling'); - }, - - siblings: function(element) { - element = $(element); - return element.previousSiblings().reverse().concat(element.nextSiblings()); - }, - - match: function(element, selector) { - if (Object.isString(selector)) - selector = new Selector(selector); - return selector.match($(element)); - }, - - up: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(element.parentNode); - var ancestors = element.ancestors(); - return expression ? Selector.findElement(ancestors, expression, index) : - ancestors[index || 0]; - }, - - down: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - var descendants = element.descendants(); - return expression ? Selector.findElement(descendants, expression, index) : - descendants[index || 0]; - }, - - previous: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); - var previousSiblings = element.previousSiblings(); - return expression ? Selector.findElement(previousSiblings, expression, index) : - previousSiblings[index || 0]; - }, - - next: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); - var nextSiblings = element.nextSiblings(); - return expression ? Selector.findElement(nextSiblings, expression, index) : - nextSiblings[index || 0]; - }, - - select: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element, args); - }, - - adjacent: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element.parentNode, args).without(element); - }, - - identify: function(element) { - element = $(element); - var id = element.readAttribute('id'), self = arguments.callee; - if (id) return id; - do { id = 'anonymous_element_' + self.counter++ } while ($(id)); - element.writeAttribute('id', id); - return id; - }, - - readAttribute: function(element, name) { - element = $(element); - if (Prototype.Browser.IE) { - var t = Element._attributeTranslations.read; - if (t.values[name]) return t.values[name](element, name); - if (t.names[name]) name = t.names[name]; - if (name.include(':')) { - return (!element.attributes || !element.attributes[name]) ? null : - element.attributes[name].value; - } - } - return element.getAttribute(name); - }, - - writeAttribute: function(element, name, value) { - element = $(element); - var attributes = { }, t = Element._attributeTranslations.write; - - if (typeof name == 'object') attributes = name; - else attributes[name] = Object.isUndefined(value) ? true : value; - - for (var attr in attributes) { - name = t.names[attr] || attr; - value = attributes[attr]; - if (t.values[attr]) name = t.values[attr](element, value); - if (value === false || value === null) - element.removeAttribute(name); - else if (value === true) - element.setAttribute(name, name); - else element.setAttribute(name, value); - } - return element; - }, - - getHeight: function(element) { - return $(element).getDimensions().height; - }, - - getWidth: function(element) { - return $(element).getDimensions().width; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - var elementClassName = element.className; - return (elementClassName.length > 0 && (elementClassName == className || - new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - if (!element.hasClassName(className)) - element.className += (element.className ? ' ' : '') + className; - return element; - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - element.className = element.className.replace( - new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); - return element; - }, - - toggleClassName: function(element, className) { - if (!(element = $(element))) return; - return element[element.hasClassName(className) ? - 'removeClassName' : 'addClassName'](className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - var node = element.firstChild; - while (node) { - var nextNode = node.nextSibling; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - element.removeChild(node); - node = nextNode; - } - return element; - }, - - empty: function(element) { - return $(element).innerHTML.blank(); - }, - - descendantOf: function(element, ancestor) { - element = $(element), ancestor = $(ancestor); - var originalAncestor = ancestor; - - if (element.compareDocumentPosition) - return (element.compareDocumentPosition(ancestor) & 8) === 8; - - if (element.sourceIndex && !Prototype.Browser.Opera) { - var e = element.sourceIndex, a = ancestor.sourceIndex, - nextAncestor = ancestor.nextSibling; - if (!nextAncestor) { - do { ancestor = ancestor.parentNode; } - while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); - } - if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex); - } - - while (element = element.parentNode) - if (element == originalAncestor) return true; - return false; - }, - - scrollTo: function(element) { - element = $(element); - var pos = element.cumulativeOffset(); - window.scrollTo(pos[0], pos[1]); - return element; - }, - - getStyle: function(element, style) { - element = $(element); - style = style == 'float' ? 'cssFloat' : style.camelize(); - var value = element.style[style]; - if (!value) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css[style] : null; - } - if (style == 'opacity') return value ? parseFloat(value) : 1.0; - return value == 'auto' ? null : value; - }, - - getOpacity: function(element) { - return $(element).getStyle('opacity'); - }, - - setStyle: function(element, styles) { - element = $(element); - var elementStyle = element.style, match; - if (Object.isString(styles)) { - element.style.cssText += ';' + styles; - return styles.include('opacity') ? - element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; - } - for (var property in styles) - if (property == 'opacity') element.setOpacity(styles[property]); - else - elementStyle[(property == 'float' || property == 'cssFloat') ? - (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : - property] = styles[property]; - - return element; - }, - - setOpacity: function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - return element; - }, - - getDimensions: function(element) { - element = $(element); - var display = $(element).getStyle('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'; - els.display = 'block'; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = originalDisplay; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - 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 (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - return element; - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - return element; - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return element; - element._overflow = Element.getStyle(element, 'overflow') || 'auto'; - if (element._overflow !== 'hidden') - element.style.overflow = 'hidden'; - return element; - }, - - undoClipping: function(element) { - element = $(element); - if (!element._overflow) return element; - element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; - element._overflow = null; - return element; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - if (element.tagName == 'BODY') break; - var p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; - } - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - absolutize: function(element) { - element = $(element); - if (element.getStyle('position') == 'absolute') return; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - var offsets = element.positionedOffset(); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.width = width + 'px'; - element.style.height = height + 'px'; - return element; - }, - - relativize: function(element) { - element = $(element); - if (element.getStyle('position') == 'relative') return; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - return element; - }, - - cumulativeScrollOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - getOffsetParent: function(element) { - if (element.offsetParent) return $(element.offsetParent); - if (element == document.body) return $(element); - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return $(element); - - return $(document.body); - }, - - viewportOffset: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent == document.body && - Element.getStyle(element, 'position') == 'absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - if (!Prototype.Browser.Opera || element.tagName == 'BODY') { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } - } while (element = element.parentNode); - - return Element._returnOffset(valueL, valueT); - }, - - clonePosition: function(element, source) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || { }); - - // find page position of source - source = $(source); - var p = source.viewportOffset(); - - // 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(); - } - - // 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'; - if (options.setHeight) element.style.height = source.offsetHeight + 'px'; - return element; - } -}; - -Element.Methods.identify.counter = 1; - -Object.extend(Element.Methods, { - getElementsBySelector: Element.Methods.select, - childElements: Element.Methods.immediateDescendants -}); - -Element._attributeTranslations = { - write: { - names: { - className: 'class', - htmlFor: 'for' - }, - values: { } - } -}; - - -if (!document.createRange || Prototype.Browser.Opera) { - Element.Methods.insert = function(element, insertions) { - element = $(element); - - if (Object.isString(insertions) || Object.isNumber(insertions) || - Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = { bottom: insertions }; - - var t = Element._insertionTranslations, content, position, pos, tagName; - - for (position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - pos = t[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - pos.insert(element, content); - continue; - } - - content = Object.toHTML(content); - tagName = ((position == 'before' || position == 'after') - ? element.parentNode : element).tagName.toUpperCase(); - - if (t.tags[tagName]) { - var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - if (position == 'top' || position == 'after') fragments.reverse(); - fragments.each(pos.insert.curry(element)); - } - else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); - - content.evalScripts.bind(content).defer(); - } - - return element; - }; -} - -if (Prototype.Browser.Opera) { - Element.Methods.getStyle = Element.Methods.getStyle.wrap( - function(proceed, element, style) { - switch (style) { - 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()]) - return dim + 'px'; - - var properties; - if (style === 'height') { - properties = ['border-top-width', 'padding-top', - 'padding-bottom', 'border-bottom-width']; - } - else { - properties = ['border-left-width', 'padding-left', - 'padding-right', 'border-right-width']; - } - return properties.inject(dim, function(memo, property) { - var val = proceed(element, property); - return val === null ? memo : memo - parseInt(val, 10); - }) + 'px'; - default: return proceed(element, style); - } - } - ); - - Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( - function(proceed, element, attribute) { - if (attribute === 'title') return element.title; - return proceed(element, attribute); - } - ); -} - -else if (Prototype.Browser.IE) { - $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { - Element.Methods[method] = Element.Methods[method].wrap( - function(proceed, element) { - element = $(element); - var position = element.getStyle('position'); - if (position != 'static') return proceed(element); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - }); - - Element.Methods.getStyle = function(element, style) { - element = $(element); - style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); - var value = element.style[style]; - if (!value && element.currentStyle) value = element.currentStyle[style]; - - if (style == 'opacity') { - if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) - if (value[1]) return parseFloat(value[1]) / 100; - return 1.0; - } - - if (value == 'auto') { - if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) - return element['offset' + style.capitalize()] + 'px'; - return null; - } - return value; - }; - - Element.Methods.setOpacity = function(element, value) { - function stripAlpha(filter){ - return filter.replace(/alpha\([^\)]*\)/gi,''); - } - element = $(element); - var currentStyle = element.currentStyle; - if ((currentStyle && !currentStyle.hasLayout) || - (!currentStyle && element.style.zoom == 'normal')) - element.style.zoom = 1; - - var filter = element.getStyle('filter'), style = element.style; - if (value == 1 || value === '') { - (filter = stripAlpha(filter)) ? - style.filter = filter : style.removeAttribute('filter'); - return element; - } else if (value < 0.00001) value = 0; - style.filter = stripAlpha(filter) + - 'alpha(opacity=' + (value * 100) + ')'; - 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(); - }, - title: function(element) { - return element.title; - } - } - } - }; - - Element._attributeTranslations.write = { - names: Object.clone(Element._attributeTranslations.read.names), - values: { - checked: function(element, value) { - element.checked = !!value; - }, - - style: function(element, value) { - element.style.cssText = value ? value : ''; - } - } - }; - - Element._attributeTranslations.has = {}; - - $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + - 'encType maxLength readOnly longDesc').each(function(attr) { - Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; - Element._attributeTranslations.has[attr.toLowerCase()] = attr; - }); - - (function(v) { - Object.extend(v, { - href: v._getAttr, - src: v._getAttr, - type: v._getAttr, - action: v._getAttrNode, - disabled: v._flag, - checked: v._flag, - readonly: v._flag, - multiple: v._flag, - onload: v._getEv, - onunload: v._getEv, - onclick: v._getEv, - ondblclick: v._getEv, - onmousedown: v._getEv, - onmouseup: v._getEv, - onmouseover: v._getEv, - onmousemove: v._getEv, - onmouseout: v._getEv, - onfocus: v._getEv, - onblur: v._getEv, - onkeypress: v._getEv, - onkeydown: v._getEv, - onkeyup: v._getEv, - onsubmit: v._getEv, - onreset: v._getEv, - onselect: v._getEv, - onchange: v._getEv - }); - })(Element._attributeTranslations.read.values); -} - -else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1) ? 0.999999 : - (value === '') ? '' : (value < 0.00001) ? 0 : value; - return element; - }; -} - -else if (Prototype.Browser.WebKit) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - - if (value == 1) - if(element.tagName == 'IMG' && element.width) { - element.width++; element.width--; - } else try { - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch (e) { } - - 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 { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return Element._returnOffset(valueL, valueT); - }; -} - -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 (document.createElement('div').outerHTML) { - Element.Methods.replace = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - element.parentNode.replaceChild(content, element); - return element; - } - - content = Object.toHTML(content); - var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); - - if (Element._insertionTranslations.tags[tagName]) { - var nextSibling = element.next(); - var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - parent.removeChild(element); - if (nextSibling) - fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); - else - fragments.each(function(node) { parent.appendChild(node) }); - } - else element.outerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -Element._returnOffset = function(l, t) { - var result = [l, t]; - result.left = l; - result.top = t; - return result; -}; - -Element._getContentFromAnonymousElement = function(tagName, html) { - var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; - div.innerHTML = t[0] + html + t[1]; - t[2].times(function() { div = div.firstChild }); - return $A(div.childNodes); -}; - -Element._insertionTranslations = { - before: { - adjacency: 'beforeBegin', - insert: function(element, node) { - element.parentNode.insertBefore(node, element); - }, - initializeRange: function(element, range) { - range.setStartBefore(element); - } - }, - top: { - adjacency: 'afterBegin', - insert: function(element, node) { - element.insertBefore(node, element.firstChild); - }, - initializeRange: function(element, range) { - range.selectNodeContents(element); - range.collapse(true); - } - }, - bottom: { - adjacency: 'beforeEnd', - insert: function(element, node) { - element.appendChild(node); - } - }, - after: { - adjacency: 'afterEnd', - insert: function(element, node) { - element.parentNode.insertBefore(node, element.nextSibling); - }, - initializeRange: function(element, range) { - range.setStartAfter(element); - } - }, - tags: { - TABLE: ['', '
    ', 1], - TBODY: ['', '
    ', 2], - TR: ['', '
    ', 3], - TD: ['
    ', '
    ', 4], - SELECT: ['', 1] - } -}; - -(function() { - this.bottom.initializeRange = this.top.initializeRange; - Object.extend(this.tags, { - THEAD: this.tags.TBODY, - TFOOT: this.tags.TBODY, - TH: this.tags.TD - }); -}).call(Element._insertionTranslations); - -Element.Methods.Simulated = { - hasAttribute: function(element, attribute) { - attribute = Element._attributeTranslations.has[attribute] || attribute; - var node = $(element).getAttributeNode(attribute); - return node && node.specified; - } -}; - -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; -} - -Element.extend = (function() { - if (Prototype.BrowserFeatures.SpecificElementExtensions) - return Prototype.K; - - var Methods = { }, ByTag = Element.Methods.ByTag; - - var extend = Object.extend(function(element) { - if (!element || element._extendedByPrototype || - element.nodeType != 1 || element == window) return element; - - var methods = Object.clone(Methods), - tagName = element.tagName, property, value; - - // 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(); - } - - 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); - } - } - }); - - extend.refresh(); - return extend; -})(); - -Element.hasAttribute = function(element, attribute) { - if (element.hasAttribute) return element.hasAttribute(attribute); - return Element.Methods.Simulated.hasAttribute(element, attribute); -}; - -Element.addMethods = function(methods) { - var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; - - if (!methods) { - Object.extend(Form, Form.Methods); - Object.extend(Form.Element, Form.Element.Methods); - Object.extend(Element.Methods.ByTag, { - "FORM": Object.clone(Form.Methods), - "INPUT": Object.clone(Form.Element.Methods), - "SELECT": Object.clone(Form.Element.Methods), - "TEXTAREA": Object.clone(Form.Element.Methods) - }); - } - - if (arguments.length == 2) { - var tagName = methods; - methods = arguments[1]; - } - - if (!tagName) Object.extend(Element.Methods, methods || { }); - else { - if (Object.isArray(tagName)) tagName.each(extend); - else extend(tagName); - } - - function extend(tagName) { - tagName = tagName.toUpperCase(); - if (!Element.Methods.ByTag[tagName]) - Element.Methods.ByTag[tagName] = { }; - Object.extend(Element.Methods.ByTag[tagName], methods); - } - - function copy(methods, destination, onlyIfAbsent) { - onlyIfAbsent = onlyIfAbsent || false; - for (var property in methods) { - var value = methods[property]; - if (!Object.isFunction(value)) continue; - if (!onlyIfAbsent || !(property in destination)) - destination[property] = value.methodize(); - } - } - - function findDOMClass(tagName) { - var klass; - var trans = { - "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", - "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", - "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", - "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", - "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": - "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": - "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": - "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": - "FrameSet", "IFRAME": "IFrame" - }; - if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName.capitalize() + 'Element'; - if (window[klass]) return window[klass]; - - window[klass] = { }; - window[klass].prototype = document.createElement(tagName).__proto__; - return window[klass]; - } - - if (F.ElementExtensions) { - copy(Element.Methods, HTMLElement.prototype); - copy(Element.Methods.Simulated, HTMLElement.prototype, true); - } - - if (F.SpecificElementExtensions) { - for (var tag in Element.Methods.ByTag) { - var klass = findDOMClass(tag); - if (Object.isUndefined(klass)) continue; - copy(T[tag], klass.prototype); - } - } - - Object.extend(Element, Element.Methods); - delete Element.ByTag; - - if (Element.extend.refresh) Element.extend.refresh(); - Element.cache = { }; -}; - -document.viewport = { - getDimensions: function() { - var dimensions = { }; - var B = Prototype.Browser; - $w('width height').each(function(d) { - var D = d.capitalize(); - dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] : - (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D]; - }); - return dimensions; - }, - - getWidth: function() { - return this.getDimensions().width; - }, - - getHeight: function() { - return this.getDimensions().height; - }, - - getScrollOffsets: function() { - return Element._returnOffset( - window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, - window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); - } -}; -/* 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. */ - -var Selector = Class.create({ - initialize: function(expression) { - this.expression = expression.strip(); - this.compileMatcher(); - }, - - shouldUseXPath: function() { - if (!Prototype.BrowserFeatures.XPath) return false; - - var e = this.expression; - - // Safari 3 chokes on :*-of-type and :empty - if (Prototype.Browser.WebKit && - (e.include("-of-type") || e.include(":empty"))) - return false; - - // XPath can't do namespaced attributes, nor can it read - // the "checked" property from DOM nodes - if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) - return false; - - return true; - }, - - compileMatcher: function() { - if (this.shouldUseXPath()) - return this.compileXPathMatcher(); - - var e = this.expression, ps = Selector.patterns, h = Selector.handlers, - c = Selector.criteria, le, p, m; - - if (Selector._cache[e]) { - this.matcher = Selector._cache[e]; - return; - } - - this.matcher = ["this.matcher = function(root) {", - "var r = root, h = Selector.handlers, c = false, n;"]; - - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : - new Template(c[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.matcher.push("return h.unique(n);\n}"); - eval(this.matcher.join('\n')); - Selector._cache[this.expression] = this.matcher; - }, - - compileXPathMatcher: function() { - var e = this.expression, ps = Selector.patterns, - x = Selector.xpath, le, m; - - if (Selector._cache[e]) { - this.xpath = Selector._cache[e]; return; - } - - 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)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.xpath = this.matcher.join(''); - Selector._cache[this.expression] = this.xpath; - }, - - findElements: function(root) { - root = root || document; - if (this.xpath) return document._getElementsByXPath(this.xpath, root); - return this.matcher(root); - }, - - match: function(element) { - this.tokens = []; - - var e = this.expression, ps = Selector.patterns, as = Selector.assertions; - var le, p, m; - - while (e && le !== e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - 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)]); - 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); - } - } - } - } - - var match = true, name, matches; - for (var i = 0, token; token = this.tokens[i]; i++) { - name = token[0], matches = token[1]; - if (!Selector.assertions[name](element, matches)) { - match = false; break; - } - } - - return match; - }, - - toString: function() { - return this.expression; - }, - - inspect: function() { - return "#"; - } -}); - -Object.extend(Selector, { - _cache: { }, - - xpath: { - descendant: "//*", - child: "/*", - adjacent: "/following-sibling::*[1]", - laterSibling: '/following-sibling::*', - tagName: function(m) { - if (m[1] == '*') return ''; - return "[local-name()='" + m[1].toLowerCase() + - "' or local-name()='" + m[1].toUpperCase() + "']"; - }, - className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", - id: "[@id='#{1}']", - attrPresence: function(m) { - m[1] = m[1].toLowerCase(); - return new Template("[@#{1}]").evaluate(m); - }, - attr: function(m) { - m[1] = m[1].toLowerCase(); - m[3] = m[5] || m[6]; - return new Template(Selector.xpath.operators[m[2]]).evaluate(m); - }, - pseudo: function(m) { - var h = Selector.xpath.pseudos[m[1]]; - if (!h) return ''; - if (Object.isFunction(h)) return h(m); - return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); - }, - operators: { - '=': "[@#{1}='#{3}']", - '!=': "[@#{1}!='#{3}']", - '^=': "[starts-with(@#{1}, '#{3}')]", - '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", - '*=': "[contains(@#{1}, '#{3}')]", - '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", - '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" - }, - pseudos: { - 'first-child': '[not(preceding-sibling::*)]', - 'last-child': '[not(following-sibling::*)]', - 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', - 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", - 'checked': "[@checked]", - 'disabled': "[@disabled]", - 'enabled': "[not(@disabled)]", - 'not': function(m) { - var e = m[6], p = Selector.patterns, - x = Selector.xpath, le, v; - - 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); - exclusion.push("(" + v.substring(1, v.length - 1) + ")"); - e = e.replace(m[0], ''); - break; - } - } - } - return "[not(" + exclusion.join(" and ") + ")]"; - }, - 'nth-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); - }, - 'nth-last-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); - }, - 'nth-of-type': function(m) { - return Selector.xpath.pseudos.nth("position() ", m); - }, - 'nth-last-of-type': function(m) { - return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); - }, - 'first-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); - }, - 'last-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); - }, - 'only-of-type': function(m) { - var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); - }, - nth: function(fragment, m) { - var mm, formula = m[6], predicate; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - if (mm = formula.match(/^(\d+)$/)) // digit only - return '[' + fragment + "= " + mm[1] + ']'; - if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (mm[1] == "-") mm[1] = -1; - var a = mm[1] ? Number(mm[1]) : 1; - var b = mm[2] ? Number(mm[2]) : 0; - predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + - "((#{fragment} - #{b}) div #{a} >= 0)]"; - return new Template(predicate).evaluate({ - fragment: fragment, a: a, b: b }); - } - } - } - }, - - criteria: { - tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', - className: 'n = h.className(n, r, "#{1}", c); c = false;', - id: 'n = h.id(n, r, "#{1}", c); c = false;', - attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', - attr: function(m) { - m[3] = (m[5] || m[6]); - return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); - }, - pseudo: function(m) { - if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); - return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); - }, - descendant: 'c = "descendant";', - child: 'c = "child";', - adjacent: 'c = "adjacent";', - 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/, - - // 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]+)\]/, - attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ - }, - - // for Selector.match and Element#match - assertions: { - tagName: function(element, matches) { - return matches[1].toUpperCase() == element.tagName.toUpperCase(); - }, - - className: function(element, matches) { - return Element.hasClassName(element, matches[1]); - }, - - id: function(element, matches) { - return element.id === matches[1]; - }, - - attrPresence: function(element, matches) { - return Element.hasAttribute(element, matches[1]); - }, - - attr: function(element, matches) { - var nodeValue = Element.readAttribute(element, matches[1]); - return Selector.operators[matches[2]](nodeValue, matches[3]); - } - }, - - 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) { - for (var i = 0, node; node = nodes[i]; i++) - node._counted = true; - return nodes; - }, - - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._counted = undefined; - 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._counted = true; - if (reverse) { - for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { - var node = nodes[i]; - if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; - } - } else { - for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) - if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; - } - }, - - // 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])._counted) { - n._counted = true; - 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++) - h.concat(results, node.getElementsByTagName('*')); - return results; - }, - - child: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) { - for (var j = 0, child; child = node.childNodes[j]; j++) - if (child.nodeType == 1 && child.tagName != '!') results.push(child); - } - return results; - }, - - adjacent: function(nodes) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - var next = this.nextElementSibling(node); - if (next) results.push(next); - } - return results; - }, - - laterSibling: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, Element.nextSiblings(node)); - return results; - }, - - nextElementSibling: function(node) { - while (node = node.nextSibling) - if (node.nodeType == 1) return node; - return null; - }, - - previousElementSibling: function(node) { - while (node = node.previousSibling) - if (node.nodeType == 1) return node; - return null; - }, - - // TOKEN FUNCTIONS - tagName: function(nodes, root, tagName, combinator) { - tagName = 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)); - return results; - } else nodes = this[combinator](nodes); - if (tagName == "*") return nodes; - } - for (var i = 0, node; node = nodes[i]; i++) - if (node.tagName.toUpperCase() == tagName) results.push(node); - return results; - } else return root.getElementsByTagName(tagName); - }, - - id: function(nodes, root, id, combinator) { - var targetNode = $(id), h = Selector.handlers; - if (!targetNode) return []; - if (!nodes && root == document) return [targetNode]; - if (nodes) { - if (combinator) { - if (combinator == 'child') { - for (var i = 0, node; node = nodes[i]; i++) - if (targetNode.parentNode == node) return [targetNode]; - } else if (combinator == 'descendant') { - for (var i = 0, node; node = nodes[i]; i++) - if (Element.descendantOf(targetNode, node)) return [targetNode]; - } else if (combinator == 'adjacent') { - for (var i = 0, node; node = nodes[i]; i++) - if (Selector.handlers.previousElementSibling(targetNode) == node) - return [targetNode]; - } else nodes = h[combinator](nodes); - } - for (var i = 0, node; node = nodes[i]; i++) - if (node == targetNode) return [targetNode]; - return []; - } - return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; - }, - - className: function(nodes, root, className, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - return Selector.handlers.byClassName(nodes, root, className); - }, - - byClassName: function(nodes, root, className) { - if (!nodes) nodes = Selector.handlers.descendant([root]); - var needle = ' ' + className + ' '; - for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { - nodeClassName = node.className; - if (nodeClassName.length == 0) continue; - if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) - results.push(node); - } - return results; - }, - - attrPresence: function(nodes, root, attr) { - if (!nodes) nodes = root.getElementsByTagName("*"); - var results = []; - for (var i = 0, node; node = nodes[i]; i++) - if (Element.hasAttribute(node, attr)) results.push(node); - return results; - }, - - attr: function(nodes, root, attr, value, operator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - var handler = Selector.operators[operator], results = []; - for (var i = 0, node; node = nodes[i]; i++) { - var nodeValue = Element.readAttribute(node, attr); - if (nodeValue === null) continue; - if (handler(nodeValue, value)) results.push(node); - } - return results; - }, - - pseudo: function(nodes, name, value, root, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - if (!nodes) nodes = root.getElementsByTagName("*"); - return Selector.pseudos[name](nodes, value, root); - } - }, - - pseudos: { - 'first-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.previousElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'last-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.nextElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'only-child': function(nodes, value, root) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) - results.push(node); - return results; - }, - 'nth-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root); - }, - 'nth-last-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true); - }, - 'nth-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, false, true); - }, - 'nth-last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true, true); - }, - 'first-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, false, true); - }, - 'last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, true, true); - }, - 'only-of-type': function(nodes, formula, root) { - var p = Selector.pseudos; - 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) { - if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); - return memo; - }); - }, - - // 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'; - if (formula == 'odd') formula = '2n+1'; - var h = Selector.handlers, results = [], indexed = [], m; - h.mark(nodes); - for (var i = 0, node; node = nodes[i]; i++) { - if (!node.parentNode._counted) { - h.index(node.parentNode, reverse, ofType); - indexed.push(node.parentNode); - } - } - if (formula.match(/^\d+$/)) { // just a number - formula = Number(formula); - for (var i = 0, node; node = nodes[i]; i++) - if (node.nodeIndex == formula) results.push(node); - } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (m[1] == "-") m[1] = -1; - var a = m[1] ? Number(m[1]) : 1; - var b = m[2] ? Number(m[2]) : 0; - var indices = Selector.pseudos.getIndices(a, b, nodes.length); - for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { - for (var j = 0; j < l; j++) - if (node.nodeIndex == indices[j]) results.push(node); - } - } - h.unmark(nodes); - h.unmark(indexed); - return results; - }, - - '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 && !node.innerHTML.match(/^\s*$/))) continue; - results.push(node); - } - return results; - }, - - 'not': function(nodes, selector, root) { - var h = Selector.handlers, selectorType, m; - var exclusions = new Selector(selector).findElements(root); - h.mark(exclusions); - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node._counted) results.push(node); - h.unmark(exclusions); - return results; - }, - - 'enabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node.disabled) results.push(node); - return results; - }, - - 'disabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.disabled) results.push(node); - return results; - }, - - 'checked': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.checked) results.push(node); - return results; - } - }, - - operators: { - '=': function(nv, v) { return nv == v; }, - '!=': function(nv, v) { return nv != v; }, - '^=': function(nv, v) { return nv.startsWith(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() + '-'); } - }, - - matchElements: function(elements, expression) { - var matches = new Selector(expression).findElements(), h = Selector.handlers; - h.mark(matches); - for (var i = 0, results = [], element; element = elements[i]; i++) - if (element._counted) results.push(element); - h.unmark(matches); - return results; - }, - - findElement: function(elements, expression, index) { - if (Object.isNumber(expression)) { - index = expression; expression = false; - } - return Selector.matchElements(elements, expression || '*')[index || 0]; - }, - - findChildElements: function(element, expressions) { - var exprs = expressions.join(','); - expressions = []; - exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { - expressions.push(m[1].strip()); - }); - var results = [], h = Selector.handlers; - for (var i = 0, l = expressions.length, selector; i < l; i++) { - selector = new Selector(expressions[i].strip()); - h.concat(results, selector.findElements(element)); - } - return (l > 1) ? h.unique(results) : results; - } -}); - -if (Prototype.Browser.IE) { - // IE returns comment nodes on getElementsByTagName("*"). - // Filter them out. - Selector.handlers.concat = function(a, b) { - for (var i = 0, node; node = b[i]; i++) - if (node.tagName !== "!") a.push(node); - return a; - }; -} - -function $$() { - return Selector.findChildElements(document, $A(arguments)); -} -var Form = { - reset: function(form) { - $(form).reset(); - return form; - }, - - serializeElements: function(elements, options) { - if (typeof options != 'object') options = { hash: !!options }; - else if (Object.isUndefined(options.hash)) options.hash = true; - var key, value, submitted = false, submit = options.submit; - - var data = elements.inject({ }, function(result, element) { - if (!element.disabled && element.name) { - key = element.name; value = $(element).getValue(); - if (value != null && (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); - } - else result[key] = value; - } - } - return result; - }); - - return options.hash ? data : Object.toQueryString(data); - } -}; - -Form.Methods = { - serialize: function(form, options) { - return Form.serializeElements(Form.getElements(form), options); - }, - - 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; - } - ); - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) return $A(inputs).map(Element.extend); - - for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || (name && input.name != name)) - continue; - matchingInputs.push(Element.extend(input)); - } - - return matchingInputs; - }, - - disable: function(form) { - form = $(form); - Form.getElements(form).invoke('disable'); - return form; - }, - - enable: function(form) { - form = $(form); - Form.getElements(form).invoke('enable'); - return form; - }, - - findFirstElement: function(form) { - var elements = $(form).getElements().findAll(function(element) { - return 'hidden' != element.type && !element.disabled; - }); - var firstByIndex = elements.findAll(function(element) { - return element.hasAttribute('tabIndex') && element.tabIndex >= 0; - }).sortBy(function(element) { return element.tabIndex }).first(); - - return firstByIndex ? firstByIndex : elements.find(function(element) { - return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - form = $(form); - form.findFirstElement().activate(); - return form; - }, - - request: function(form, options) { - form = $(form), options = Object.clone(options || { }); - - var params = options.parameters, action = form.readAttribute('action') || ''; - if (action.blank()) action = window.location.href; - options.parameters = form.serialize(true); - - if (params) { - if (Object.isString(params)) params = params.toQueryParams(); - Object.extend(options.parameters, params); - } - - if (form.hasAttribute('method') && !options.method) - options.method = form.method; - - return new Ajax.Request(action, options); - } -}; - -/*--------------------------------------------------------------------------*/ - -Form.Element = { - focus: function(element) { - $(element).focus(); - return element; - }, - - select: function(element) { - $(element).select(); - return element; - } -}; - -Form.Element.Methods = { - serialize: function(element) { - element = $(element); - if (!element.disabled && element.name) { - var value = element.getValue(); - if (value != undefined) { - var pair = { }; - pair[element.name] = value; - return Object.toQueryString(pair); - } - } - return ''; - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - return Form.Element.Serializers[method](element); - }, - - setValue: function(element, value) { - element = $(element); - var method = element.tagName.toLowerCase(); - Form.Element.Serializers[method](element, value); - return element; - }, - - clear: function(element) { - $(element).value = ''; - return element; - }, - - present: function(element) { - return $(element).value != ''; - }, - - activate: function(element) { - element = $(element); - try { - element.focus(); - if (element.select && (element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type))) - element.select(); - } catch (e) { } - return element; - }, - - disable: function(element) { - element = $(element); - element.blur(); - element.disabled = true; - return element; - }, - - enable: function(element) { - element = $(element); - element.disabled = false; - return element; - } -}; - -/*--------------------------------------------------------------------------*/ - -var Field = Form.Element; -var $F = Form.Element.Methods.getValue; - -/*--------------------------------------------------------------------------*/ - -Form.Element.Serializers = { - input: function(element, value) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element, value); - default: - return Form.Element.Serializers.textarea(element, value); - } - }, - - inputSelector: function(element, value) { - if (Object.isUndefined(value)) return element.checked ? element.value : null; - else element.checked = !!value; - }, - - textarea: function(element, value) { - if (Object.isUndefined(value)) return element.value; - else element.value = value; - }, - - select: function(element, index) { - if (Object.isUndefined(index)) - return this[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - else { - var opt, value, single = !Object.isArray(index); - for (var i = 0, length = element.length; i < length; i++) { - opt = element.options[i]; - value = this.optionValue(opt); - if (single) { - if (value == index) { - opt.selected = true; - return; - } - } - else opt.selected = index.include(value); - } - } - }, - - selectOne: function(element) { - var index = element.selectedIndex; - return index >= 0 ? this.optionValue(element.options[index]) : null; - }, - - selectMany: function(element) { - var values, length = element.length; - if (!length) return null; - - for (var i = 0, values = []; i < length; i++) { - var opt = element.options[i]; - if (opt.selected) values.push(this.optionValue(opt)); - } - return values; - }, - - 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); - this.element = $(element); - this.lastValue = this.getValue(); - }, - - execute: function() { - var value = this.getValue(); - if (Object.isString(this.lastValue) && Object.isString(value) ? - this.lastValue != value : String(this.lastValue) != String(value)) { - this.callback(this.element, value); - this.lastValue = value; - } - } -}); - -Form.Element.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = Class.create({ - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - Form.getElements(this.element).each(this.registerCallback, this); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - default: - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -}); - -Form.Element.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - 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); - } -}); - -Event.Methods = (function() { - var isButton; - - if (Prototype.Browser.IE) { - var buttonMap = { 0: 1, 1: 4, 2: 2 }; - isButton = function(event, code) { - return event.button == buttonMap[code]; - }; - - } else if (Prototype.Browser.WebKit) { - 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) { - 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) { - var node = Event.extend(event).target; - return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); - }, - - 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); - }, - - pointer: function(event) { - return { - x: event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)), - y: event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)) - }; - }, - - pointerX: function(event) { return Event.pointer(event).x }, - pointerY: function(event) { return Event.pointer(event).y }, - - stop: function(event) { - Event.extend(event); - event.preventDefault(); - event.stopPropagation(); - event.stopped = true; - } - }; -})(); - -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) { - Object.extend(methods, { - stopPropagation: function() { this.cancelBubble = true }, - preventDefault: function() { this.returnValue = false }, - inspect: function() { return "[object Event]" } - }); - - return function(event) { - 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), - pageX: pointer.x, - pageY: pointer.y - }); - return Object.extend(event, methods); - }; - - } else { - Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; - Object.extend(Event.prototype, methods); - return Prototype.K; - } -})(); - -Object.extend(Event, (function() { - var cache = Event.cache; - - function getEventID(element) { - if (element._eventID) return element._eventID; - arguments.callee.id = arguments.callee.id || 1; - return element._eventID = ++arguments.callee.id; - } - - function getDOMEventName(eventName) { - if (eventName && eventName.include(':')) return "dataavailable"; - return eventName; - } - - function getCacheForID(id) { - return cache[id] = cache[id] || { }; - } - - function getWrappersForEventName(id, eventName) { - var c = getCacheForID(id); - return c[eventName] = c[eventName] || []; - } - - function createWrapper(element, eventName, handler) { - var id = getEventID(element); - var c = getWrappersForEventName(id, eventName); - if (c.pluck("handler").include(handler)) return false; - - var wrapper = function(event) { - if (!Event || !Event.extend || - (event.eventName && event.eventName != eventName)) - return false; - - Event.extend(event); - handler.call(element, event) - }; - - wrapper.handler = handler; - c.push(wrapper); - return wrapper; - } - - function findWrapper(id, eventName, handler) { - var c = getWrappersForEventName(id, eventName); - return c.find(function(wrapper) { return wrapper.handler == handler }); - } - - function destroyWrapper(id, eventName, handler) { - var c = getCacheForID(id); - if (!c[eventName]) return false; - c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); - } - - function destroyCache() { - for (var id in cache) - for (var eventName in cache[id]) - cache[id][eventName] = null; - } - - if (window.attachEvent) { - window.attachEvent("onunload", destroyCache); - } - - return { - observe: function(element, eventName, handler) { - element = $(element); - var name = getDOMEventName(eventName); - - var wrapper = createWrapper(element, eventName, handler); - if (!wrapper) return element; - - if (element.addEventListener) { - element.addEventListener(name, wrapper, false); - } else { - element.attachEvent("on" + name, wrapper); - } - - return element; - }, - - stopObserving: function(element, eventName, handler) { - element = $(element); - var id = getEventID(element), name = getDOMEventName(eventName); - - if (!handler && eventName) { - getWrappersForEventName(id, eventName).each(function(wrapper) { - element.stopObserving(eventName, wrapper.handler); - }); - return element; - - } else if (!eventName) { - Object.keys(getCacheForID(id)).each(function(eventName) { - element.stopObserving(eventName); - }); - return element; - } - - var wrapper = findWrapper(id, eventName, handler); - if (!wrapper) return element; - - if (element.removeEventListener) { - element.removeEventListener(name, wrapper, false); - } else { - element.detachEvent("on" + name, wrapper); - } - - destroyWrapper(id, eventName, handler); - - return element; - }, - - fire: function(element, eventName, memo) { - element = $(element); - if (element == document && document.createEvent && !element.dispatchEvent) - element = document.documentElement; - - if (document.createEvent) { - var event = document.createEvent("HTMLEvents"); - event.initEvent("dataavailable", true, true); - } else { - var event = document.createEventObject(); - event.eventType = "ondataavailable"; - } - - event.eventName = eventName; - event.memo = memo || { }; - - if (document.createEvent) { - element.dispatchEvent(event); - } else { - element.fireEvent(event.eventType, event); - } - - return Event.extend(event); - } - }; -})()); - -Object.extend(Event, Event.Methods); - -Element.addMethods({ - fire: Event.fire, - observe: Event.observe, - stopObserving: Event.stopObserving -}); - -Object.extend(document, { - fire: Element.Methods.fire.methodize(), - observe: Element.Methods.observe.methodize(), - stopObserving: Element.Methods.stopObserving.methodize() -}); - -(function() { - /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards and John Resig. */ - - var timer, fired = false; - - function fireContentLoadedEvent() { - if (fired) return; - if (timer) window.clearInterval(timer); - document.fire("dom:loaded"); - fired = true; - } - - if (document.addEventListener) { - if (Prototype.Browser.WebKit) { - timer = window.setInterval(function() { - if (/loaded|complete/.test(document.readyState)) - fireContentLoadedEvent(); - }, 0); - - Event.observe(window, "load", fireContentLoadedEvent); - - } else { - document.addEventListener("DOMContentLoaded", - fireContentLoadedEvent, false); - } - - } else { - document.write("'); - }, - REQUIRED_PROTOTYPE: '1.5.1', - load: function() { - function convertVersionString(versionString){ - var r = versionString.split('.'); - return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]); - } - - if((typeof Prototype=='undefined') || - (typeof Element == 'undefined') || - (typeof Element.Methods=='undefined') || - (convertVersionString(Prototype.Version) < - convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE))) - throw("script.aculo.us requires the Prototype JavaScript framework >= " + - Scriptaculous.REQUIRED_PROTOTYPE); - - $A(document.getElementsByTagName("script")).findAll( function(s) { - return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/)) - }).each( function(s) { - var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,''); - var includes = s.src.match(/\?.*load=([a-z,]*)/); - (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each( - function(include) { Scriptaculous.require(path+include+'.js') }); - }); - } -} - -Scriptaculous.load(); \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/public/javascripts/slider.js b/vendor/plugins/clearance/test/rails_root/public/javascripts/slider.js deleted file mode 100644 index c1a84eb..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/javascripts/slider.js +++ /dev/null @@ -1,277 +0,0 @@ -// script.aculo.us slider.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007 - -// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -if(!Control) var Control = {}; -Control.Slider = Class.create(); - -// options: -// axis: 'vertical', or 'horizontal' (default) -// -// callbacks: -// onChange(value) -// onSlide(value) -Control.Slider.prototype = { - initialize: function(handle, track, options) { - var slider = this; - - if(handle instanceof Array) { - this.handles = handle.collect( function(e) { return $(e) }); - } else { - this.handles = [$(handle)]; - } - - this.track = $(track); - this.options = options || {}; - - this.axis = this.options.axis || 'horizontal'; - this.increment = this.options.increment || 1; - this.step = parseInt(this.options.step || '1'); - this.range = this.options.range || $R(0,1); - - this.value = 0; // assure backwards compat - this.values = this.handles.map( function() { return 0 }); - this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false; - this.options.startSpan = $(this.options.startSpan || null); - this.options.endSpan = $(this.options.endSpan || null); - - this.restricted = this.options.restricted || false; - - this.maximum = this.options.maximum || this.range.end; - this.minimum = this.options.minimum || this.range.start; - - // Will be used to align the handle onto the track, if necessary - this.alignX = parseInt(this.options.alignX || '0'); - this.alignY = parseInt(this.options.alignY || '0'); - - this.trackLength = this.maximumOffset() - this.minimumOffset(); - - this.handleLength = this.isVertical() ? - (this.handles[0].offsetHeight != 0 ? - this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : - (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : - this.handles[0].style.width.replace(/px$/,"")); - - this.active = false; - this.dragging = false; - this.disabled = false; - - if(this.options.disabled) this.setDisabled(); - - // Allowed values array - this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false; - if(this.allowedValues) { - this.minimum = this.allowedValues.min(); - this.maximum = this.allowedValues.max(); - } - - this.eventMouseDown = this.startDrag.bindAsEventListener(this); - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.update.bindAsEventListener(this); - - // Initialize handles in reverse (make sure first handle is active) - this.handles.each( function(h,i) { - i = slider.handles.length-1-i; - slider.setValue(parseFloat( - (slider.options.sliderValue instanceof Array ? - slider.options.sliderValue[i] : slider.options.sliderValue) || - slider.range.start), i); - Element.makePositioned(h); // fix IE - Event.observe(h, "mousedown", slider.eventMouseDown); - }); - - Event.observe(this.track, "mousedown", this.eventMouseDown); - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - - this.initialized = true; - }, - dispose: function() { - var slider = this; - Event.stopObserving(this.track, "mousedown", this.eventMouseDown); - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - this.handles.each( function(h) { - Event.stopObserving(h, "mousedown", slider.eventMouseDown); - }); - }, - setDisabled: function(){ - this.disabled = true; - }, - setEnabled: function(){ - this.disabled = false; - }, - getNearestValue: function(value){ - if(this.allowedValues){ - if(value >= this.allowedValues.max()) return(this.allowedValues.max()); - if(value <= this.allowedValues.min()) return(this.allowedValues.min()); - - var offset = Math.abs(this.allowedValues[0] - value); - var newValue = this.allowedValues[0]; - this.allowedValues.each( function(v) { - var currentOffset = Math.abs(v - value); - if(currentOffset <= offset){ - newValue = v; - offset = currentOffset; - } - }); - return newValue; - } - if(value > this.range.end) return this.range.end; - if(value < this.range.start) return this.range.start; - return value; - }, - setValue: function(sliderValue, handleIdx){ - if(!this.active) { - this.activeHandleIdx = handleIdx || 0; - this.activeHandle = this.handles[this.activeHandleIdx]; - this.updateStyles(); - } - handleIdx = handleIdx || this.activeHandleIdx || 0; - if(this.initialized && this.restricted) { - if((handleIdx>0) && (sliderValuethis.values[handleIdx+1])) - sliderValue = this.values[handleIdx+1]; - } - sliderValue = this.getNearestValue(sliderValue); - this.values[handleIdx] = sliderValue; - this.value = this.values[0]; // assure backwards compat - - this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = - this.translateToPx(sliderValue); - - this.drawSpans(); - if(!this.dragging || !this.event) this.updateFinished(); - }, - setValueBy: function(delta, handleIdx) { - this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, - handleIdx || this.activeHandleIdx || 0); - }, - translateToPx: function(value) { - return Math.round( - ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * - (value - this.range.start)) + "px"; - }, - translateToValue: function(offset) { - return ((offset/(this.trackLength-this.handleLength) * - (this.range.end-this.range.start)) + this.range.start); - }, - getRange: function(range) { - var v = this.values.sortBy(Prototype.K); - range = range || 0; - return $R(v[range],v[range+1]); - }, - minimumOffset: function(){ - return(this.isVertical() ? this.alignY : this.alignX); - }, - maximumOffset: function(){ - return(this.isVertical() ? - (this.track.offsetHeight != 0 ? this.track.offsetHeight : - this.track.style.height.replace(/px$/,"")) - this.alignY : - (this.track.offsetWidth != 0 ? this.track.offsetWidth : - this.track.style.width.replace(/px$/,"")) - this.alignY); - }, - isVertical: function(){ - return (this.axis == 'vertical'); - }, - drawSpans: function() { - var slider = this; - if(this.spans) - $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) }); - if(this.options.startSpan) - this.setSpan(this.options.startSpan, - $R(0, this.values.length>1 ? this.getRange(0).min() : this.value )); - if(this.options.endSpan) - this.setSpan(this.options.endSpan, - $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum)); - }, - setSpan: function(span, range) { - if(this.isVertical()) { - span.style.top = this.translateToPx(range.start); - span.style.height = this.translateToPx(range.end - range.start + this.range.start); - } else { - span.style.left = this.translateToPx(range.start); - span.style.width = this.translateToPx(range.end - range.start + this.range.start); - } - }, - updateStyles: function() { - this.handles.each( function(h){ Element.removeClassName(h, 'selected') }); - Element.addClassName(this.activeHandle, 'selected'); - }, - startDrag: function(event) { - if(Event.isLeftClick(event)) { - if(!this.disabled){ - this.active = true; - - var handle = Event.element(event); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var track = handle; - if(track==this.track) { - var offsets = Position.cumulativeOffset(this.track); - this.event = event; - this.setValue(this.translateToValue( - (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2) - )); - var offsets = Position.cumulativeOffset(this.activeHandle); - this.offsetX = (pointer[0] - offsets[0]); - this.offsetY = (pointer[1] - offsets[1]); - } else { - // find the handle (prevents issues with Safari) - while((this.handles.indexOf(handle) == -1) && handle.parentNode) - handle = handle.parentNode; - - if(this.handles.indexOf(handle)!=-1) { - this.activeHandle = handle; - this.activeHandleIdx = this.handles.indexOf(this.activeHandle); - this.updateStyles(); - - var offsets = Position.cumulativeOffset(this.activeHandle); - this.offsetX = (pointer[0] - offsets[0]); - this.offsetY = (pointer[1] - offsets[1]); - } - } - } - Event.stop(event); - } - }, - update: function(event) { - if(this.active) { - if(!this.dragging) this.dragging = true; - this.draw(event); - if(Prototype.Browser.WebKit) window.scrollBy(0,0); - Event.stop(event); - } - }, - draw: function(event) { - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var offsets = Position.cumulativeOffset(this.track); - pointer[0] -= this.offsetX + offsets[0]; - pointer[1] -= this.offsetY + offsets[1]; - this.event = event; - this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] )); - if(this.initialized && this.options.onSlide) - this.options.onSlide(this.values.length>1 ? this.values : this.value, this); - }, - endDrag: function(event) { - if(this.active && this.dragging) { - this.finishDrag(event, true); - Event.stop(event); - } - this.active = false; - this.dragging = false; - }, - finishDrag: function(event, success) { - this.active = false; - this.dragging = false; - this.updateFinished(); - }, - updateFinished: function() { - if(this.initialized && this.options.onChange) - this.options.onChange(this.values.length>1 ? this.values : this.value, this); - this.event = null; - } -} \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/public/javascripts/sound.js b/vendor/plugins/clearance/test/rails_root/public/javascripts/sound.js deleted file mode 100644 index 164c79a..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/javascripts/sound.js +++ /dev/null @@ -1,60 +0,0 @@ -// script.aculo.us sound.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007 - -// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// -// Based on code created by Jules Gravinese (http://www.webveteran.com/) -// -// 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/ - -Sound = { - tracks: {}, - _enabled: true, - template: - new Template(''), - enable: function(){ - Sound._enabled = true; - }, - disable: function(){ - Sound._enabled = false; - }, - play: function(url){ - if(!Sound._enabled) return; - var options = Object.extend({ - track: 'global', url: url, replace: false - }, arguments[1] || {}); - - if(options.replace && this.tracks[options.track]) { - $R(0, this.tracks[options.track].id).each(function(id){ - var sound = $('sound_'+options.track+'_'+id); - sound.Stop && sound.Stop(); - sound.remove(); - }) - this.tracks[options.track] = null; - } - - if(!this.tracks[options.track]) - this.tracks[options.track] = { id: 0 } - else - this.tracks[options.track].id++; - - options.id = this.tracks[options.track].id; - if (Prototype.Browser.IE) { - var sound = document.createElement('bgsound'); - sound.setAttribute('id','sound_'+options.track+'_'+options.id); - sound.setAttribute('src',options.url); - sound.setAttribute('loop','1'); - sound.setAttribute('autostart','true'); - $$('body')[0].appendChild(sound); - } - else - new Insertion.Bottom($$('body')[0], Sound.template.evaluate(options)); - } -}; - -if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){ - if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 })) - Sound.template = new Template('') - else - Sound.play = function(){} -} diff --git a/vendor/plugins/clearance/test/rails_root/public/robots.txt b/vendor/plugins/clearance/test/rails_root/public/robots.txt deleted file mode 100644 index 4ab9e89..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/robots.txt +++ /dev/null @@ -1 +0,0 @@ -# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/public/stylesheets/.keep b/vendor/plugins/clearance/test/rails_root/public/stylesheets/.keep deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/public/stylesheets/.keep +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/script/about b/vendor/plugins/clearance/test/rails_root/script/about deleted file mode 100755 index 7b07d46..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/about +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/about' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/script/breakpointer b/vendor/plugins/clearance/test/rails_root/script/breakpointer deleted file mode 100755 index 64af76e..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/breakpointer +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/breakpointer' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/script/console b/vendor/plugins/clearance/test/rails_root/script/console deleted file mode 100755 index 42f28f7..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/console +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/console' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/script/create_project.rb b/vendor/plugins/clearance/test/rails_root/script/create_project.rb deleted file mode 100755 index 5effe81..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/create_project.rb +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env ruby -require 'rubygems' -require 'activesupport' -require 'pathname' - -project_name = ARGV[0] -fail("Usage: #{File.basename(__FILE__)} new_project_name") unless project_name -fail("Project name must only contain [a-z0-9_]") unless project_name =~ /^[a-z0-9_]+$/ - -base_directory = Pathname.new(File.join(File.dirname(__FILE__), '..', '..')).realpath -project_directory = base_directory + project_name -fail("Project directory (#{project_directory}) already exists") if project_directory.exist? - -template_url = "git@github.com:thoughtbot/rails-template.git" -changeme = "CHANGEME" - -def run(cmd) - puts "Running '#{cmd}'" - out = `#{cmd}` - if $? != 0 - fail "Command #{cmd} failed: #$?\n#{out}" - end - out -end - -def search_and_replace(file, search, replace) - if File.file?(file) - contents = File.read(file) - if contents[search] - puts "Replacing #{search} with #{replace} in #{file}" - contents.gsub!(search, replace) - File.open(file, "w") { |f| f << contents } - end - end -end - -run("mkdir #{project_directory}") -Dir.chdir(project_directory) or fail("Couldn't change to #{project_directory}") -run("git init") -run("git remote add template #{template_url}") -run("git pull template master") - -Dir.glob("#{project_directory}/**/*").each do |file| - search_and_replace(file, changeme, project_name) -end - -run("git commit -a -m 'Initial commit'") - -puts -puts "Now login to github and add a new project named '#{project_name.humanize.titleize}'" - - diff --git a/vendor/plugins/clearance/test/rails_root/script/cucumber b/vendor/plugins/clearance/test/rails_root/script/cucumber deleted file mode 100755 index 15f8585..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/cucumber +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env ruby -begin - load File.expand_path(File.dirname(__FILE__) + "/../vendor/plugins/cucumber/bin/cucumber") -rescue LoadError - require "rubygems" - load File.join(Gem.bindir, "cucumber") -end \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/script/dbconsole b/vendor/plugins/clearance/test/rails_root/script/dbconsole deleted file mode 100755 index caa60ce..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/dbconsole +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/dbconsole' diff --git a/vendor/plugins/clearance/test/rails_root/script/destroy b/vendor/plugins/clearance/test/rails_root/script/destroy deleted file mode 100755 index fa0e6fc..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/destroy +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/destroy' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/script/generate b/vendor/plugins/clearance/test/rails_root/script/generate deleted file mode 100755 index ef976e0..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/generate +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/generate' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/script/performance/benchmarker b/vendor/plugins/clearance/test/rails_root/script/performance/benchmarker deleted file mode 100755 index c842d35..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/performance/benchmarker +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/performance/benchmarker' diff --git a/vendor/plugins/clearance/test/rails_root/script/performance/profiler b/vendor/plugins/clearance/test/rails_root/script/performance/profiler deleted file mode 100755 index d855ac8..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/performance/profiler +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/performance/profiler' diff --git a/vendor/plugins/clearance/test/rails_root/script/performance/request b/vendor/plugins/clearance/test/rails_root/script/performance/request deleted file mode 100755 index ae3f38c..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/performance/request +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/performance/request' diff --git a/vendor/plugins/clearance/test/rails_root/script/plugin b/vendor/plugins/clearance/test/rails_root/script/plugin deleted file mode 100755 index 26ca64c..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/plugin +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/plugin' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/script/process/inspector b/vendor/plugins/clearance/test/rails_root/script/process/inspector deleted file mode 100755 index bf25ad8..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/process/inspector +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/process/inspector' diff --git a/vendor/plugins/clearance/test/rails_root/script/process/reaper b/vendor/plugins/clearance/test/rails_root/script/process/reaper deleted file mode 100755 index c77f045..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/process/reaper +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/process/reaper' diff --git a/vendor/plugins/clearance/test/rails_root/script/process/spawner b/vendor/plugins/clearance/test/rails_root/script/process/spawner deleted file mode 100755 index 7118f39..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/process/spawner +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../../config/boot' -require 'commands/process/spawner' diff --git a/vendor/plugins/clearance/test/rails_root/script/runner b/vendor/plugins/clearance/test/rails_root/script/runner deleted file mode 100755 index ccc30f9..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/runner +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/runner' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/script/server b/vendor/plugins/clearance/test/rails_root/script/server deleted file mode 100755 index dfabcb8..0000000 --- a/vendor/plugins/clearance/test/rails_root/script/server +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../config/boot' -require 'commands/server' \ No newline at end of file diff --git a/vendor/plugins/clearance/test/rails_root/test/functional/.keep b/vendor/plugins/clearance/test/rails_root/test/functional/.keep deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/test/functional/.keep +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/test/functional/accounts_controller_test.rb b/vendor/plugins/clearance/test/rails_root/test/functional/accounts_controller_test.rb deleted file mode 100644 index 4e7b5c0..0000000 --- a/vendor/plugins/clearance/test/rails_root/test/functional/accounts_controller_test.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'test_helper' - -class AccountsControllerTest < ActionController::TestCase - - context "when signed out" do - setup { sign_out } - should_deny_access_on :get, :edit - should_deny_access_on :put, :update - end - - context "on POST to create" do - setup do - post :create - end - - should_deny_access - - should "not store location" do - assert session[:return_to].nil? - end - end - -end diff --git a/vendor/plugins/clearance/test/rails_root/test/integration/.keep b/vendor/plugins/clearance/test/rails_root/test/integration/.keep deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/test/integration/.keep +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/test/mocks/development/.keep b/vendor/plugins/clearance/test/rails_root/test/mocks/development/.keep deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/test/mocks/development/.keep +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/test/mocks/test/.keep b/vendor/plugins/clearance/test/rails_root/test/mocks/test/.keep deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/test/mocks/test/.keep +++ /dev/null diff --git a/vendor/plugins/clearance/test/rails_root/test/unit/.keep b/vendor/plugins/clearance/test/rails_root/test/unit/.keep deleted file mode 100644 index e69de29..0000000 --- a/vendor/plugins/clearance/test/rails_root/test/unit/.keep +++ /dev/null diff --git a/vendor/plugins/clearance/test/test_helper.rb b/vendor/plugins/clearance/test/test_helper.rb deleted file mode 100644 index eb26409..0000000 --- a/vendor/plugins/clearance/test/test_helper.rb +++ /dev/null @@ -1,22 +0,0 @@ -ENV["RAILS_ENV"] = "test" -require File.expand_path(File.dirname(__FILE__) + - "/rails_root/config/environment") -require 'test_help' - -$: << File.expand_path(File.dirname(__FILE__) + '/..') -require 'clearance' - -gem 'thoughtbot-factory_girl' - -require 'factory_girl' -begin - require 'redgreen' -rescue LoadError -end - -require File.join(File.dirname(__FILE__), '..', 'shoulda_macros', 'clearance') - -class ActiveSupport::TestCase - self.use_transactional_fixtures = true - self.use_instantiated_fixtures = false -end -- libgit2 0.21.2