rails 1.2.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rails might be problematic. Click here for more details.
- data/CHANGELOG +491 -12
- data/MIT-LICENSE +1 -1
- data/README +17 -25
- data/Rakefile +41 -18
- data/bin/about +1 -1
- data/bin/console +1 -1
- data/bin/destroy +1 -1
- data/bin/generate +1 -1
- data/bin/performance/request +3 -0
- data/bin/plugin +1 -1
- data/bin/runner +1 -1
- data/bin/server +1 -1
- data/builtin/rails_info/rails/info.rb +2 -2
- data/configs/apache.conf +1 -1
- data/configs/databases/mysql.yml +9 -3
- data/configs/databases/postgresql.yml +16 -12
- data/configs/initializers/inflections.rb +10 -0
- data/configs/initializers/mime_types.rb +5 -0
- data/configs/routes.rb +23 -11
- data/doc/README_FOR_APP +1 -1
- data/environments/boot.rb +95 -26
- data/environments/development.rb +2 -5
- data/environments/environment.rb +24 -25
- data/environments/test.rb +4 -1
- data/helpers/application.rb +5 -2
- data/helpers/test_helper.rb +10 -0
- data/html/422.html +30 -0
- data/html/500.html +1 -1
- data/html/index.html +2 -2
- data/html/javascripts/controls.js +484 -354
- data/html/javascripts/dragdrop.js +88 -58
- data/html/javascripts/effects.js +396 -364
- data/html/javascripts/prototype.js +2817 -1107
- data/html/robots.txt +5 -1
- data/lib/commands/console.rb +12 -5
- data/lib/commands/performance/request.rb +6 -0
- data/lib/commands/plugin.rb +15 -10
- data/lib/commands/process/spawner.rb +14 -4
- data/lib/commands/servers/base.rb +12 -0
- data/lib/commands/servers/mongrel.rb +5 -1
- data/lib/commands/servers/webrick.rb +14 -7
- data/lib/console_app.rb +5 -2
- data/lib/console_with_helpers.rb +5 -2
- data/lib/dispatcher.rb +3 -151
- data/lib/fcgi_handler.rb +79 -81
- data/lib/initializer.rb +125 -169
- data/lib/rails/plugin.rb +84 -0
- data/lib/rails/plugin/loader.rb +150 -0
- data/lib/rails/plugin/locator.rb +78 -0
- data/lib/rails/version.rb +3 -3
- data/lib/rails_generator/base.rb +11 -9
- data/lib/rails_generator/commands.rb +20 -10
- data/lib/rails_generator/generators/applications/app/USAGE +0 -7
- data/lib/rails_generator/generators/applications/app/app_generator.rb +25 -6
- data/lib/rails_generator/generators/components/controller/USAGE +11 -12
- data/lib/rails_generator/generators/components/controller/controller_generator.rb +2 -2
- data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +1 -11
- data/lib/rails_generator/generators/components/controller/templates/{view.rhtml → view.html.erb} +0 -0
- data/lib/rails_generator/generators/components/integration_test/USAGE +5 -11
- data/lib/rails_generator/generators/components/mailer/USAGE +8 -10
- data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +3 -3
- data/lib/rails_generator/generators/components/mailer/templates/fixture.erb +3 -0
- data/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml +0 -3
- data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +8 -24
- data/lib/rails_generator/generators/components/mailer/templates/view.erb +3 -0
- data/lib/rails_generator/generators/components/mailer/templates/view.rhtml +0 -3
- data/lib/rails_generator/generators/components/migration/USAGE +23 -8
- data/lib/rails_generator/generators/components/migration/migration_generator.rb +15 -2
- data/lib/rails_generator/generators/components/migration/templates/migration.rb +6 -2
- data/lib/rails_generator/generators/components/model/USAGE +15 -14
- data/lib/rails_generator/generators/components/model/model_generator.rb +10 -3
- data/lib/rails_generator/generators/components/model/templates/fixtures.yml +11 -3
- data/lib/rails_generator/generators/components/model/templates/migration.rb +4 -1
- data/lib/rails_generator/generators/components/model/templates/unit_test.rb +1 -3
- data/lib/rails_generator/generators/components/observer/USAGE +5 -7
- data/lib/rails_generator/generators/components/observer/templates/unit_test.rb +0 -2
- data/lib/rails_generator/generators/components/plugin/USAGE +8 -18
- data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +1 -0
- data/lib/rails_generator/generators/components/plugin/templates/MIT-LICENSE +20 -0
- data/lib/rails_generator/generators/components/plugin/templates/README +10 -1
- data/lib/rails_generator/generators/components/plugin/templates/USAGE +1 -1
- data/lib/rails_generator/generators/components/plugin/templates/init.rb +1 -1
- data/lib/rails_generator/generators/components/plugin/templates/plugin.rb +1 -1
- data/lib/rails_generator/generators/components/plugin/templates/tasks.rake +1 -1
- data/lib/rails_generator/generators/components/resource/USAGE +23 -0
- data/lib/rails_generator/generators/components/resource/resource_generator.rb +13 -15
- data/lib/rails_generator/generators/components/resource/templates/controller.rb +1 -1
- data/lib/rails_generator/generators/components/resource/templates/functional_test.rb +2 -14
- data/lib/rails_generator/generators/components/scaffold/USAGE +24 -31
- data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +45 -146
- data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +64 -37
- data/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb +23 -80
- data/lib/rails_generator/generators/components/scaffold/templates/{layout.rhtml → layout.html.erb} +0 -0
- data/lib/rails_generator/generators/components/scaffold/templates/style.css +1 -1
- data/lib/rails_generator/generators/components/{scaffold_resource/templates/view_edit.rhtml → scaffold/templates/view_edit.html.erb} +4 -4
- data/lib/rails_generator/generators/components/{scaffold_resource/templates/view_index.rhtml → scaffold/templates/view_index.html.erb} +4 -4
- data/lib/rails_generator/generators/components/{scaffold_resource/templates/view_new.rhtml → scaffold/templates/view_new.html.erb} +3 -3
- data/lib/rails_generator/generators/components/{scaffold_resource/templates/view_show.rhtml → scaffold/templates/view_show.html.erb} +1 -1
- data/lib/rails_generator/generators/components/session_migration/USAGE +6 -11
- data/lib/rails_generator/generators/components/session_migration/templates/migration.rb +3 -3
- data/lib/rails_generator/lookup.rb +45 -10
- data/lib/rails_generator/scripts.rb +6 -3
- data/lib/rails_generator/scripts/destroy.rb +23 -0
- data/lib/rails_generator/secret_key_generator.rb +160 -0
- data/lib/rails_generator/spec.rb +1 -1
- data/lib/source_annotation_extractor.rb +62 -0
- data/lib/tasks/annotations.rake +23 -0
- data/lib/tasks/databases.rake +249 -83
- data/lib/tasks/documentation.rake +11 -13
- data/lib/tasks/framework.rake +1 -1
- data/lib/tasks/rails.rb +1 -1
- data/lib/tasks/testing.rake +5 -7
- data/lib/test_help.rb +4 -3
- data/lib/webrick_server.rb +3 -4
- metadata +31 -49
- data/bin/breakpointer +0 -3
- data/lib/binding_of_caller.rb +0 -85
- data/lib/breakpoint.rb +0 -553
- data/lib/breakpoint_client.rb +0 -196
- data/lib/commands/breakpointer.rb +0 -1
- data/lib/rails_generator/generators/components/resource/templates/USAGE +0 -18
- data/lib/rails_generator/generators/components/resource/templates/fixtures.yml +0 -11
- data/lib/rails_generator/generators/components/resource/templates/migration.rb +0 -13
- data/lib/rails_generator/generators/components/resource/templates/model.rb +0 -2
- data/lib/rails_generator/generators/components/resource/templates/unit_test.rb +0 -10
- data/lib/rails_generator/generators/components/scaffold/templates/form.rhtml +0 -3
- data/lib/rails_generator/generators/components/scaffold/templates/form_scaffolding.rhtml +0 -1
- data/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml +0 -9
- data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +0 -27
- data/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml +0 -8
- data/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml +0 -8
- data/lib/rails_generator/generators/components/scaffold_resource/USAGE +0 -29
- data/lib/rails_generator/generators/components/scaffold_resource/scaffold_resource_generator.rb +0 -93
- data/lib/rails_generator/generators/components/scaffold_resource/templates/controller.rb +0 -79
- data/lib/rails_generator/generators/components/scaffold_resource/templates/fixtures.yml +0 -11
- data/lib/rails_generator/generators/components/scaffold_resource/templates/functional_test.rb +0 -57
- data/lib/rails_generator/generators/components/scaffold_resource/templates/helper.rb +0 -2
- data/lib/rails_generator/generators/components/scaffold_resource/templates/layout.rhtml +0 -17
- data/lib/rails_generator/generators/components/scaffold_resource/templates/migration.rb +0 -13
- data/lib/rails_generator/generators/components/scaffold_resource/templates/model.rb +0 -2
- data/lib/rails_generator/generators/components/scaffold_resource/templates/style.css +0 -74
- data/lib/rails_generator/generators/components/scaffold_resource/templates/unit_test.rb +0 -10
- data/lib/rails_generator/generators/components/web_service/USAGE +0 -28
- data/lib/rails_generator/generators/components/web_service/templates/api_definition.rb +0 -5
- data/lib/rails_generator/generators/components/web_service/templates/controller.rb +0 -8
- data/lib/rails_generator/generators/components/web_service/templates/functional_test.rb +0 -19
- data/lib/rails_generator/generators/components/web_service/web_service_generator.rb +0 -29
- data/lib/tasks/pre_namespace_aliases.rake +0 -53
data/doc/README_FOR_APP
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
Use this README file to introduce your application and point to useful places in the API for learning more.
|
2
|
-
Run "rake
|
2
|
+
Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
|
data/environments/boot.rb
CHANGED
@@ -1,39 +1,108 @@
|
|
1
|
-
# Don't change this file
|
1
|
+
# Don't change this file!
|
2
|
+
# Configure your app in config/environment.rb and config/environments/*.rb
|
2
3
|
|
3
4
|
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
module Rails
|
7
|
+
class << self
|
8
|
+
def boot!
|
9
|
+
unless booted?
|
10
|
+
preinitialize
|
11
|
+
pick_boot.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def booted?
|
16
|
+
defined? Rails::Initializer
|
17
|
+
end
|
18
|
+
|
19
|
+
def pick_boot
|
20
|
+
(vendor_rails? ? VendorBoot : GemBoot).new
|
21
|
+
end
|
22
|
+
|
23
|
+
def vendor_rails?
|
24
|
+
File.exist?("#{RAILS_ROOT}/vendor/rails")
|
25
|
+
end
|
26
|
+
|
27
|
+
def preinitialize
|
28
|
+
load(preinitializer_path) if File.exists?(preinitializer_path)
|
29
|
+
end
|
10
30
|
|
11
|
-
|
12
|
-
|
13
|
-
|
31
|
+
def preinitializer_path
|
32
|
+
"#{RAILS_ROOT}/config/preinitializer.rb"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Boot
|
37
|
+
def run
|
38
|
+
load_initializer
|
39
|
+
Rails::Initializer.run(:set_load_path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class VendorBoot < Boot
|
44
|
+
def load_initializer
|
45
|
+
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class GemBoot < Boot
|
50
|
+
def load_initializer
|
51
|
+
self.class.load_rubygems
|
52
|
+
load_rails_gem
|
53
|
+
require 'initializer'
|
54
|
+
end
|
55
|
+
|
56
|
+
def load_rails_gem
|
57
|
+
if version = self.class.gem_version
|
58
|
+
gem 'rails', version
|
14
59
|
else
|
15
|
-
|
16
|
-
$1
|
60
|
+
gem 'rails'
|
17
61
|
end
|
62
|
+
rescue Gem::LoadError => load_error
|
63
|
+
$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.)
|
64
|
+
exit 1
|
65
|
+
end
|
18
66
|
|
19
|
-
|
20
|
-
|
67
|
+
class << self
|
68
|
+
def rubygems_version
|
69
|
+
Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
|
70
|
+
end
|
21
71
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
72
|
+
def gem_version
|
73
|
+
if defined? RAILS_GEM_VERSION
|
74
|
+
RAILS_GEM_VERSION
|
75
|
+
elsif ENV.include?('RAILS_GEM_VERSION')
|
76
|
+
ENV['RAILS_GEM_VERSION']
|
77
|
+
else
|
78
|
+
parse_gem_version(read_environment_rb)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def load_rubygems
|
83
|
+
require 'rubygems'
|
84
|
+
|
85
|
+
unless rubygems_version >= '0.9.4'
|
86
|
+
$stderr.puts %(Rails requires RubyGems >= 0.9.4 (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
87
|
+
exit 1
|
88
|
+
end
|
89
|
+
|
90
|
+
rescue LoadError
|
91
|
+
$stderr.puts %(Rails requires RubyGems >= 0.9.4. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
30
92
|
exit 1
|
31
93
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
94
|
+
|
95
|
+
def parse_gem_version(text)
|
96
|
+
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*'([!~<>=]*\s*[\d.]+)'/
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
def read_environment_rb
|
101
|
+
File.read("#{RAILS_ROOT}/config/environment.rb")
|
102
|
+
end
|
35
103
|
end
|
36
104
|
end
|
37
|
-
|
38
|
-
Rails::Initializer.run(:set_load_path)
|
39
105
|
end
|
106
|
+
|
107
|
+
# All that for this:
|
108
|
+
Rails.boot!
|
data/environments/development.rb
CHANGED
@@ -8,14 +8,11 @@ config.cache_classes = false
|
|
8
8
|
# Log error messages when you accidentally call methods on nil.
|
9
9
|
config.whiny_nils = true
|
10
10
|
|
11
|
-
# Enable the breakpoint server that script/breakpointer connects to
|
12
|
-
config.breakpoint_server = true
|
13
|
-
|
14
11
|
# Show full error reports and disable caching
|
15
12
|
config.action_controller.consider_all_requests_local = true
|
13
|
+
config.action_view.debug_rjs = true
|
16
14
|
config.action_controller.perform_caching = false
|
17
15
|
config.action_view.cache_template_extensions = false
|
18
|
-
config.action_view.debug_rjs = true
|
19
16
|
|
20
17
|
# Don't care if the mailer can't send
|
21
|
-
config.action_mailer.raise_delivery_errors = false
|
18
|
+
config.action_mailer.raise_delivery_errors = false
|
data/environments/environment.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Be sure to restart your
|
1
|
+
# Be sure to restart your server when you modify this file
|
2
2
|
|
3
3
|
# Uncomment below to force Rails into production mode when
|
4
4
|
# you don't control web/app server and can't set it the proper way
|
@@ -11,13 +11,19 @@
|
|
11
11
|
require File.join(File.dirname(__FILE__), 'boot')
|
12
12
|
|
13
13
|
Rails::Initializer.run do |config|
|
14
|
-
# Settings in config/environments/* take precedence over those specified here
|
14
|
+
# Settings in config/environments/* take precedence over those specified here.
|
15
|
+
# Application configuration should go into files in config/initializers
|
16
|
+
# -- all .rb files in that directory are automatically loaded.
|
17
|
+
# See Rails::Configuration for more options.
|
15
18
|
|
16
|
-
# Skip frameworks you're not going to use (only works if using vendor/rails)
|
17
|
-
#
|
19
|
+
# Skip frameworks you're not going to use (only works if using vendor/rails).
|
20
|
+
# To use Rails without a database, you must remove the Active Record framework
|
21
|
+
# config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
|
18
22
|
|
19
|
-
# Only load the plugins named here,
|
20
|
-
#
|
23
|
+
# Only load the plugins named here, in the order given. By default, all plugins
|
24
|
+
# in vendor/plugins are loaded in alphabetical order.
|
25
|
+
# :all can be used as a placeholder for all plugins not explicitly named
|
26
|
+
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
|
21
27
|
|
22
28
|
# Add additional load paths for your own custom dirs
|
23
29
|
# config.load_paths += %W( #{RAILS_ROOT}/extras )
|
@@ -26,7 +32,17 @@ Rails::Initializer.run do |config|
|
|
26
32
|
# (by default production uses :info, the others :debug)
|
27
33
|
# config.log_level = :debug
|
28
34
|
|
29
|
-
#
|
35
|
+
# Your secret key for verifying cookie session data integrity.
|
36
|
+
# If you change this key, all old sessions will become invalid!
|
37
|
+
# Make sure the secret is at least 30 characters and all random,
|
38
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
39
|
+
config.action_controller.session = {
|
40
|
+
:session_key => '_<%= app_name %>_session',
|
41
|
+
:secret => '<%= app_secret %>'
|
42
|
+
}
|
43
|
+
|
44
|
+
# Use the database for sessions instead of the cookie-based default,
|
45
|
+
# which shouldn't be used to store highly confidential information
|
30
46
|
# (create the session table with 'rake db:sessions:create')
|
31
47
|
# config.action_controller.session_store = :active_record_store
|
32
48
|
|
@@ -40,21 +56,4 @@ Rails::Initializer.run do |config|
|
|
40
56
|
|
41
57
|
# Make Active Record use UTC-base instead of local time
|
42
58
|
# config.active_record.default_timezone = :utc
|
43
|
-
|
44
|
-
# Add new inflection rules using the following format
|
45
|
-
# (all these examples are active by default):
|
46
|
-
# Inflector.inflections do |inflect|
|
47
|
-
# inflect.plural /^(ox)$/i, '\1en'
|
48
|
-
# inflect.singular /^(ox)en/i, '\1'
|
49
|
-
# inflect.irregular 'person', 'people'
|
50
|
-
# inflect.uncountable %w( fish sheep )
|
51
|
-
# end
|
52
|
-
|
53
|
-
# See Rails::Configuration for more options
|
54
|
-
end
|
55
|
-
|
56
|
-
# Add new mime types for use in respond_to blocks:
|
57
|
-
# Mime::Type.register "text/richtext", :rtf
|
58
|
-
# Mime::Type.register "application/x-mobile", :mobile
|
59
|
-
|
60
|
-
# Include your application configuration below
|
59
|
+
end
|
data/environments/test.rb
CHANGED
@@ -13,7 +13,10 @@ config.whiny_nils = true
|
|
13
13
|
config.action_controller.consider_all_requests_local = true
|
14
14
|
config.action_controller.perform_caching = false
|
15
15
|
|
16
|
+
# Disable request forgery protection in test environment
|
17
|
+
config.action_controller.allow_forgery_protection = false
|
18
|
+
|
16
19
|
# Tell ActionMailer not to deliver emails to the real world.
|
17
20
|
# The :test delivery method accumulates sent emails in the
|
18
21
|
# ActionMailer::Base.deliveries array.
|
19
|
-
config.action_mailer.delivery_method = :test
|
22
|
+
config.action_mailer.delivery_method = :test
|
data/helpers/application.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
# Likewise, all the methods added will be available for all controllers.
|
3
3
|
|
4
4
|
class ApplicationController < ActionController::Base
|
5
|
-
|
6
|
-
|
5
|
+
helper :all # include all helpers, all the time
|
6
|
+
|
7
|
+
# See ActionController::RequestForgeryProtection for details
|
8
|
+
# Uncomment the :secret if you're not using the cookie session store
|
9
|
+
protect_from_forgery # :secret => '<%= app_secret %>'
|
7
10
|
end
|
data/helpers/test_helper.rb
CHANGED
@@ -15,6 +15,10 @@ class Test::Unit::TestCase
|
|
15
15
|
# in MySQL. Turn off transactional fixtures in this case; however, if you
|
16
16
|
# don't care one way or the other, switching from MyISAM to InnoDB tables
|
17
17
|
# is recommended.
|
18
|
+
#
|
19
|
+
# The only drawback to using transactional fixtures is when you actually
|
20
|
+
# need to test transactions. Since your test is bracketed by a transaction,
|
21
|
+
# any transactions started in your code will be automatically rolled back.
|
18
22
|
self.use_transactional_fixtures = true
|
19
23
|
|
20
24
|
# Instantiated fixtures are slow, but give you @david where otherwise you
|
@@ -24,5 +28,11 @@ class Test::Unit::TestCase
|
|
24
28
|
# then set this back to true.
|
25
29
|
self.use_instantiated_fixtures = false
|
26
30
|
|
31
|
+
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
32
|
+
#
|
33
|
+
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
34
|
+
# -- they do not yet inherit this setting
|
35
|
+
fixtures :all
|
36
|
+
|
27
37
|
# Add more helper methods to be used by all tests here...
|
28
38
|
end
|
data/html/422.html
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
|
6
|
+
<head>
|
7
|
+
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
8
|
+
<title>The change you wanted was rejected (422)</title>
|
9
|
+
<style type="text/css">
|
10
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
11
|
+
div.dialog {
|
12
|
+
width: 25em;
|
13
|
+
padding: 0 4em;
|
14
|
+
margin: 4em auto 0 auto;
|
15
|
+
border: 1px solid #ccc;
|
16
|
+
border-right-color: #999;
|
17
|
+
border-bottom-color: #999;
|
18
|
+
}
|
19
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
20
|
+
</style>
|
21
|
+
</head>
|
22
|
+
|
23
|
+
<body>
|
24
|
+
<!-- This file lives in public/422.html -->
|
25
|
+
<div class="dialog">
|
26
|
+
<h1>The change you wanted was rejected.</h1>
|
27
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
28
|
+
</div>
|
29
|
+
</body>
|
30
|
+
</html>
|
data/html/500.html
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
<head>
|
7
7
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
8
|
-
<title>We're sorry, but something went wrong</title>
|
8
|
+
<title>We're sorry, but something went wrong (500)</title>
|
9
9
|
<style type="text/css">
|
10
10
|
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
11
11
|
div.dialog {
|
data/html/index.html
CHANGED
@@ -240,7 +240,7 @@
|
|
240
240
|
<div id="content">
|
241
241
|
<div id="header">
|
242
242
|
<h1>Welcome aboard</h1>
|
243
|
-
<h2>You’re riding
|
243
|
+
<h2>You’re riding Ruby on Rails!</h2>
|
244
244
|
</div>
|
245
245
|
|
246
246
|
<div id="about">
|
@@ -265,7 +265,7 @@
|
|
265
265
|
|
266
266
|
<li>
|
267
267
|
<h2>Set up a default route and remove or rename this file</h2>
|
268
|
-
<p>Routes are
|
268
|
+
<p>Routes are set up in config/routes.rb.</p>
|
269
269
|
</li>
|
270
270
|
</ol>
|
271
271
|
</div>
|
@@ -1,6 +1,6 @@
|
|
1
|
-
// Copyright (c) 2005
|
2
|
-
// (c) 2005
|
3
|
-
// (c) 2005
|
1
|
+
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
2
|
+
// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
|
3
|
+
// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
|
4
4
|
// Contributors:
|
5
5
|
// Richard Livsey
|
6
6
|
// Rahul Bhargava
|
@@ -37,22 +37,23 @@
|
|
37
37
|
if(typeof Effect == 'undefined')
|
38
38
|
throw("controls.js requires including script.aculo.us' effects.js library");
|
39
39
|
|
40
|
-
var Autocompleter = {}
|
41
|
-
Autocompleter.Base =
|
42
|
-
Autocompleter.Base.prototype = {
|
40
|
+
var Autocompleter = { }
|
41
|
+
Autocompleter.Base = Class.create({
|
43
42
|
baseInitialize: function(element, update, options) {
|
44
|
-
|
43
|
+
element = $(element)
|
44
|
+
this.element = element;
|
45
45
|
this.update = $(update);
|
46
46
|
this.hasFocus = false;
|
47
47
|
this.changed = false;
|
48
48
|
this.active = false;
|
49
49
|
this.index = 0;
|
50
50
|
this.entryCount = 0;
|
51
|
+
this.oldElementValue = this.element.value;
|
51
52
|
|
52
53
|
if(this.setOptions)
|
53
54
|
this.setOptions(options);
|
54
55
|
else
|
55
|
-
this.options = options || {};
|
56
|
+
this.options = options || { };
|
56
57
|
|
57
58
|
this.options.paramName = this.options.paramName || this.element.name;
|
58
59
|
this.options.tokens = this.options.tokens || [];
|
@@ -74,6 +75,9 @@ Autocompleter.Base.prototype = {
|
|
74
75
|
|
75
76
|
if(typeof(this.options.tokens) == 'string')
|
76
77
|
this.options.tokens = new Array(this.options.tokens);
|
78
|
+
// Force carriage returns as token delimiters anyway
|
79
|
+
if (!this.options.tokens.include('\n'))
|
80
|
+
this.options.tokens.push('\n');
|
77
81
|
|
78
82
|
this.observer = null;
|
79
83
|
|
@@ -81,15 +85,14 @@ Autocompleter.Base.prototype = {
|
|
81
85
|
|
82
86
|
Element.hide(this.update);
|
83
87
|
|
84
|
-
Event.observe(this.element,
|
85
|
-
Event.observe(this.element,
|
88
|
+
Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
|
89
|
+
Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
|
86
90
|
},
|
87
91
|
|
88
92
|
show: function() {
|
89
93
|
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
|
90
94
|
if(!this.iefix &&
|
91
|
-
(
|
92
|
-
(navigator.userAgent.indexOf('Opera')<0) &&
|
95
|
+
(Prototype.Browser.IE) &&
|
93
96
|
(Element.getStyle(this.update, 'position')=='absolute')) {
|
94
97
|
new Insertion.After(this.update,
|
95
98
|
'<iframe id="' + this.update.id + '_iefix" '+
|
@@ -139,17 +142,17 @@ Autocompleter.Base.prototype = {
|
|
139
142
|
case Event.KEY_UP:
|
140
143
|
this.markPrevious();
|
141
144
|
this.render();
|
142
|
-
|
145
|
+
Event.stop(event);
|
143
146
|
return;
|
144
147
|
case Event.KEY_DOWN:
|
145
148
|
this.markNext();
|
146
149
|
this.render();
|
147
|
-
|
150
|
+
Event.stop(event);
|
148
151
|
return;
|
149
152
|
}
|
150
153
|
else
|
151
154
|
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
|
152
|
-
(
|
155
|
+
(Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
|
153
156
|
|
154
157
|
this.changed = true;
|
155
158
|
this.hasFocus = true;
|
@@ -195,7 +198,6 @@ Autocompleter.Base.prototype = {
|
|
195
198
|
this.index==i ?
|
196
199
|
Element.addClassName(this.getEntry(i),"selected") :
|
197
200
|
Element.removeClassName(this.getEntry(i),"selected");
|
198
|
-
|
199
201
|
if(this.hasFocus) {
|
200
202
|
this.show();
|
201
203
|
this.active = true;
|
@@ -238,21 +240,22 @@ Autocompleter.Base.prototype = {
|
|
238
240
|
}
|
239
241
|
var value = '';
|
240
242
|
if (this.options.select) {
|
241
|
-
var nodes =
|
243
|
+
var nodes = $(selectedElement).select('.' + this.options.select) || [];
|
242
244
|
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
|
243
245
|
} else
|
244
246
|
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
|
245
247
|
|
246
|
-
var
|
247
|
-
if (
|
248
|
-
var newValue = this.element.value.substr(0,
|
249
|
-
var whitespace = this.element.value.substr(
|
248
|
+
var bounds = this.getTokenBounds();
|
249
|
+
if (bounds[0] != -1) {
|
250
|
+
var newValue = this.element.value.substr(0, bounds[0]);
|
251
|
+
var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
|
250
252
|
if (whitespace)
|
251
253
|
newValue += whitespace[0];
|
252
|
-
this.element.value = newValue + value;
|
254
|
+
this.element.value = newValue + value + this.element.value.substr(bounds[1]);
|
253
255
|
} else {
|
254
256
|
this.element.value = value;
|
255
257
|
}
|
258
|
+
this.oldElementValue = this.element.value;
|
256
259
|
this.element.focus();
|
257
260
|
|
258
261
|
if (this.options.afterUpdateElement)
|
@@ -296,39 +299,48 @@ Autocompleter.Base.prototype = {
|
|
296
299
|
|
297
300
|
onObserverEvent: function() {
|
298
301
|
this.changed = false;
|
302
|
+
this.tokenBounds = null;
|
299
303
|
if(this.getToken().length>=this.options.minChars) {
|
300
|
-
this.startIndicator();
|
301
304
|
this.getUpdatedChoices();
|
302
305
|
} else {
|
303
306
|
this.active = false;
|
304
307
|
this.hide();
|
305
308
|
}
|
309
|
+
this.oldElementValue = this.element.value;
|
306
310
|
},
|
307
311
|
|
308
312
|
getToken: function() {
|
309
|
-
var
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
var
|
320
|
-
|
321
|
-
for (var
|
322
|
-
|
323
|
-
if (
|
324
|
-
|
313
|
+
var bounds = this.getTokenBounds();
|
314
|
+
return this.element.value.substring(bounds[0], bounds[1]).strip();
|
315
|
+
},
|
316
|
+
|
317
|
+
getTokenBounds: function() {
|
318
|
+
if (null != this.tokenBounds) return this.tokenBounds;
|
319
|
+
var value = this.element.value;
|
320
|
+
if (value.strip().empty()) return [-1, 0];
|
321
|
+
var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
|
322
|
+
var offset = (diff == this.oldElementValue.length ? 1 : 0);
|
323
|
+
var prevTokenPos = -1, nextTokenPos = value.length;
|
324
|
+
var tp;
|
325
|
+
for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
|
326
|
+
tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
|
327
|
+
if (tp > prevTokenPos) prevTokenPos = tp;
|
328
|
+
tp = value.indexOf(this.options.tokens[index], diff + offset);
|
329
|
+
if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
|
325
330
|
}
|
326
|
-
return
|
331
|
+
return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
|
327
332
|
}
|
328
|
-
}
|
333
|
+
});
|
334
|
+
|
335
|
+
Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
|
336
|
+
var boundary = Math.min(newS.length, oldS.length);
|
337
|
+
for (var index = 0; index < boundary; ++index)
|
338
|
+
if (newS[index] != oldS[index])
|
339
|
+
return index;
|
340
|
+
return boundary;
|
341
|
+
};
|
329
342
|
|
330
|
-
Ajax.Autocompleter = Class.create(
|
331
|
-
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
|
343
|
+
Ajax.Autocompleter = Class.create(Autocompleter.Base, {
|
332
344
|
initialize: function(element, update, url, options) {
|
333
345
|
this.baseInitialize(element, update, options);
|
334
346
|
this.options.asynchronous = true;
|
@@ -338,7 +350,9 @@ Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.pro
|
|
338
350
|
},
|
339
351
|
|
340
352
|
getUpdatedChoices: function() {
|
341
|
-
|
353
|
+
this.startIndicator();
|
354
|
+
|
355
|
+
var entry = encodeURIComponent(this.options.paramName) + '=' +
|
342
356
|
encodeURIComponent(this.getToken());
|
343
357
|
|
344
358
|
this.options.parameters = this.options.callback ?
|
@@ -346,14 +360,13 @@ Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.pro
|
|
346
360
|
|
347
361
|
if(this.options.defaultParams)
|
348
362
|
this.options.parameters += '&' + this.options.defaultParams;
|
349
|
-
|
363
|
+
|
350
364
|
new Ajax.Request(this.url, this.options);
|
351
365
|
},
|
352
366
|
|
353
367
|
onComplete: function(request) {
|
354
368
|
this.updateChoices(request.responseText);
|
355
369
|
}
|
356
|
-
|
357
370
|
});
|
358
371
|
|
359
372
|
// The local array autocompleter. Used when you'd prefer to
|
@@ -391,8 +404,7 @@ Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.pro
|
|
391
404
|
// In that case, the other options above will not apply unless
|
392
405
|
// you support them.
|
393
406
|
|
394
|
-
Autocompleter.Local = Class.create(
|
395
|
-
Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
|
407
|
+
Autocompleter.Local = Class.create(Autocompleter.Base, {
|
396
408
|
initialize: function(element, update, array, options) {
|
397
409
|
this.baseInitialize(element, update, options);
|
398
410
|
this.options.array = array;
|
@@ -448,13 +460,12 @@ Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
|
|
448
460
|
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
|
449
461
|
return "<ul>" + ret.join('') + "</ul>";
|
450
462
|
}
|
451
|
-
}, options || {});
|
463
|
+
}, options || { });
|
452
464
|
}
|
453
465
|
});
|
454
466
|
|
455
|
-
// AJAX in-place editor
|
456
|
-
//
|
457
|
-
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
|
467
|
+
// AJAX in-place editor and collection editor
|
468
|
+
// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
|
458
469
|
|
459
470
|
// Use this if you notice weird scrolling problems on some browsers,
|
460
471
|
// the DOM might be a bit confused when this gets called so do this
|
@@ -465,353 +476,472 @@ Field.scrollFreeActivate = function(field) {
|
|
465
476
|
}, 1);
|
466
477
|
}
|
467
478
|
|
468
|
-
Ajax.InPlaceEditor = Class.create(
|
469
|
-
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
|
470
|
-
Ajax.InPlaceEditor.prototype = {
|
479
|
+
Ajax.InPlaceEditor = Class.create({
|
471
480
|
initialize: function(element, url, options) {
|
472
481
|
this.url = url;
|
473
|
-
this.element = $(element);
|
474
|
-
|
475
|
-
this.
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
clickToEditText: "Click to edit",
|
483
|
-
okText: "ok",
|
484
|
-
rows: 1,
|
485
|
-
onComplete: function(transport, element) {
|
486
|
-
new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
|
487
|
-
},
|
488
|
-
onFailure: function(transport) {
|
489
|
-
alert("Error communicating with the server: " + transport.responseText.stripTags());
|
490
|
-
},
|
491
|
-
callback: function(form) {
|
492
|
-
return Form.serialize(form);
|
493
|
-
},
|
494
|
-
handleLineBreaks: true,
|
495
|
-
loadingText: 'Loading...',
|
496
|
-
savingClassName: 'inplaceeditor-saving',
|
497
|
-
loadingClassName: 'inplaceeditor-loading',
|
498
|
-
formClassName: 'inplaceeditor-form',
|
499
|
-
highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
|
500
|
-
highlightendcolor: "#FFFFFF",
|
501
|
-
externalControl: null,
|
502
|
-
submitOnBlur: false,
|
503
|
-
ajaxOptions: {},
|
504
|
-
evalScripts: false
|
505
|
-
}, options || {});
|
506
|
-
|
507
|
-
if(!this.options.formId && this.element.id) {
|
508
|
-
this.options.formId = this.element.id + "-inplaceeditor";
|
509
|
-
if ($(this.options.formId)) {
|
510
|
-
// there's already a form with that name, don't specify an id
|
511
|
-
this.options.formId = null;
|
512
|
-
}
|
482
|
+
this.element = element = $(element);
|
483
|
+
this.prepareOptions();
|
484
|
+
this._controls = { };
|
485
|
+
arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
|
486
|
+
Object.extend(this.options, options || { });
|
487
|
+
if (!this.options.formId && this.element.id) {
|
488
|
+
this.options.formId = this.element.id + '-inplaceeditor';
|
489
|
+
if ($(this.options.formId))
|
490
|
+
this.options.formId = '';
|
513
491
|
}
|
514
|
-
|
515
|
-
if (this.options.externalControl) {
|
492
|
+
if (this.options.externalControl)
|
516
493
|
this.options.externalControl = $(this.options.externalControl);
|
517
|
-
|
518
|
-
|
519
|
-
this.
|
520
|
-
if (!this.originalBackground) {
|
521
|
-
this.originalBackground = "transparent";
|
522
|
-
}
|
523
|
-
|
494
|
+
if (!this.options.externalControl)
|
495
|
+
this.options.externalControlOnly = false;
|
496
|
+
this._originalBackground = this.element.getStyle('background-color') || 'transparent';
|
524
497
|
this.element.title = this.options.clickToEditText;
|
525
|
-
|
526
|
-
this.
|
527
|
-
this.
|
528
|
-
this.
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
498
|
+
this._boundCancelHandler = this.handleFormCancellation.bind(this);
|
499
|
+
this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
|
500
|
+
this._boundFailureHandler = this.handleAJAXFailure.bind(this);
|
501
|
+
this._boundSubmitHandler = this.handleFormSubmission.bind(this);
|
502
|
+
this._boundWrapperHandler = this.wrapUp.bind(this);
|
503
|
+
this.registerListeners();
|
504
|
+
},
|
505
|
+
checkForEscapeOrReturn: function(e) {
|
506
|
+
if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
|
507
|
+
if (Event.KEY_ESC == e.keyCode)
|
508
|
+
this.handleFormCancellation(e);
|
509
|
+
else if (Event.KEY_RETURN == e.keyCode)
|
510
|
+
this.handleFormSubmission(e);
|
511
|
+
},
|
512
|
+
createControl: function(mode, handler, extraClasses) {
|
513
|
+
var control = this.options[mode + 'Control'];
|
514
|
+
var text = this.options[mode + 'Text'];
|
515
|
+
if ('button' == control) {
|
516
|
+
var btn = document.createElement('input');
|
517
|
+
btn.type = 'submit';
|
518
|
+
btn.value = text;
|
519
|
+
btn.className = 'editor_' + mode + '_button';
|
520
|
+
if ('cancel' == mode)
|
521
|
+
btn.onclick = this._boundCancelHandler;
|
522
|
+
this._form.appendChild(btn);
|
523
|
+
this._controls[mode] = btn;
|
524
|
+
} else if ('link' == control) {
|
525
|
+
var link = document.createElement('a');
|
526
|
+
link.href = '#';
|
527
|
+
link.appendChild(document.createTextNode(text));
|
528
|
+
link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
|
529
|
+
link.className = 'editor_' + mode + '_link';
|
530
|
+
if (extraClasses)
|
531
|
+
link.className += ' ' + extraClasses;
|
532
|
+
this._form.appendChild(link);
|
533
|
+
this._controls[mode] = link;
|
536
534
|
}
|
537
535
|
},
|
538
|
-
enterEditMode: function(evt) {
|
539
|
-
if (this.saving) return;
|
540
|
-
if (this.editing) return;
|
541
|
-
this.editing = true;
|
542
|
-
this.onEnterEditMode();
|
543
|
-
if (this.options.externalControl) {
|
544
|
-
Element.hide(this.options.externalControl);
|
545
|
-
}
|
546
|
-
Element.hide(this.element);
|
547
|
-
this.createForm();
|
548
|
-
this.element.parentNode.insertBefore(this.form, this.element);
|
549
|
-
if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);
|
550
|
-
// stop the event to avoid a page refresh in Safari
|
551
|
-
if (evt) {
|
552
|
-
Event.stop(evt);
|
553
|
-
}
|
554
|
-
return false;
|
555
|
-
},
|
556
|
-
createForm: function() {
|
557
|
-
this.form = document.createElement("form");
|
558
|
-
this.form.id = this.options.formId;
|
559
|
-
Element.addClassName(this.form, this.options.formClassName)
|
560
|
-
this.form.onsubmit = this.onSubmit.bind(this);
|
561
|
-
|
562
|
-
this.createEditField();
|
563
|
-
|
564
|
-
if (this.options.textarea) {
|
565
|
-
var br = document.createElement("br");
|
566
|
-
this.form.appendChild(br);
|
567
|
-
}
|
568
|
-
|
569
|
-
if (this.options.okButton) {
|
570
|
-
okButton = document.createElement("input");
|
571
|
-
okButton.type = "submit";
|
572
|
-
okButton.value = this.options.okText;
|
573
|
-
okButton.className = 'editor_ok_button';
|
574
|
-
this.form.appendChild(okButton);
|
575
|
-
}
|
576
|
-
|
577
|
-
if (this.options.cancelLink) {
|
578
|
-
cancelLink = document.createElement("a");
|
579
|
-
cancelLink.href = "#";
|
580
|
-
cancelLink.appendChild(document.createTextNode(this.options.cancelText));
|
581
|
-
cancelLink.onclick = this.onclickCancel.bind(this);
|
582
|
-
cancelLink.className = 'editor_cancel';
|
583
|
-
this.form.appendChild(cancelLink);
|
584
|
-
}
|
585
|
-
},
|
586
|
-
hasHTMLLineBreaks: function(string) {
|
587
|
-
if (!this.options.handleLineBreaks) return false;
|
588
|
-
return string.match(/<br/i) || string.match(/<p>/i);
|
589
|
-
},
|
590
|
-
convertHTMLLineBreaks: function(string) {
|
591
|
-
return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
|
592
|
-
},
|
593
536
|
createEditField: function() {
|
594
|
-
var text;
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
}
|
600
|
-
|
601
|
-
var obj = this;
|
602
|
-
|
603
|
-
if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
|
604
|
-
this.options.textarea = false;
|
605
|
-
var textField = document.createElement("input");
|
606
|
-
textField.obj = this;
|
607
|
-
textField.type = "text";
|
608
|
-
textField.name = this.options.paramName;
|
609
|
-
textField.value = text;
|
610
|
-
textField.style.backgroundColor = this.options.highlightcolor;
|
611
|
-
textField.className = 'editor_field';
|
537
|
+
var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
|
538
|
+
var fld;
|
539
|
+
if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
|
540
|
+
fld = document.createElement('input');
|
541
|
+
fld.type = 'text';
|
612
542
|
var size = this.options.size || this.options.cols || 0;
|
613
|
-
if (
|
614
|
-
if (this.options.submitOnBlur)
|
615
|
-
textField.onblur = this.onSubmit.bind(this);
|
616
|
-
this.editField = textField;
|
543
|
+
if (0 < size) fld.size = size;
|
617
544
|
} else {
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
textArea.name = this.options.paramName;
|
622
|
-
textArea.value = this.convertHTMLLineBreaks(text);
|
623
|
-
textArea.rows = this.options.rows;
|
624
|
-
textArea.cols = this.options.cols || 40;
|
625
|
-
textArea.className = 'editor_field';
|
626
|
-
if (this.options.submitOnBlur)
|
627
|
-
textArea.onblur = this.onSubmit.bind(this);
|
628
|
-
this.editField = textArea;
|
545
|
+
fld = document.createElement('textarea');
|
546
|
+
fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
|
547
|
+
fld.cols = this.options.cols || 40;
|
629
548
|
}
|
630
|
-
|
631
|
-
|
549
|
+
fld.name = this.options.paramName;
|
550
|
+
fld.value = text; // No HTML breaks conversion anymore
|
551
|
+
fld.className = 'editor_field';
|
552
|
+
if (this.options.submitOnBlur)
|
553
|
+
fld.onblur = this._boundSubmitHandler;
|
554
|
+
this._controls.editor = fld;
|
555
|
+
if (this.options.loadTextURL)
|
632
556
|
this.loadExternalText();
|
633
|
-
|
634
|
-
|
557
|
+
this._form.appendChild(this._controls.editor);
|
558
|
+
},
|
559
|
+
createForm: function() {
|
560
|
+
var ipe = this;
|
561
|
+
function addText(mode, condition) {
|
562
|
+
var text = ipe.options['text' + mode + 'Controls'];
|
563
|
+
if (!text || condition === false) return;
|
564
|
+
ipe._form.appendChild(document.createTextNode(text));
|
565
|
+
};
|
566
|
+
this._form = $(document.createElement('form'));
|
567
|
+
this._form.id = this.options.formId;
|
568
|
+
this._form.addClassName(this.options.formClassName);
|
569
|
+
this._form.onsubmit = this._boundSubmitHandler;
|
570
|
+
this.createEditField();
|
571
|
+
if ('textarea' == this._controls.editor.tagName.toLowerCase())
|
572
|
+
this._form.appendChild(document.createElement('br'));
|
573
|
+
if (this.options.onFormCustomization)
|
574
|
+
this.options.onFormCustomization(this, this._form);
|
575
|
+
addText('Before', this.options.okControl || this.options.cancelControl);
|
576
|
+
this.createControl('ok', this._boundSubmitHandler);
|
577
|
+
addText('Between', this.options.okControl && this.options.cancelControl);
|
578
|
+
this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
|
579
|
+
addText('After', this.options.okControl || this.options.cancelControl);
|
580
|
+
},
|
581
|
+
destroy: function() {
|
582
|
+
if (this._oldInnerHTML)
|
583
|
+
this.element.innerHTML = this._oldInnerHTML;
|
584
|
+
this.leaveEditMode();
|
585
|
+
this.unregisterListeners();
|
586
|
+
},
|
587
|
+
enterEditMode: function(e) {
|
588
|
+
if (this._saving || this._editing) return;
|
589
|
+
this._editing = true;
|
590
|
+
this.triggerCallback('onEnterEditMode');
|
591
|
+
if (this.options.externalControl)
|
592
|
+
this.options.externalControl.hide();
|
593
|
+
this.element.hide();
|
594
|
+
this.createForm();
|
595
|
+
this.element.parentNode.insertBefore(this._form, this.element);
|
596
|
+
if (!this.options.loadTextURL)
|
597
|
+
this.postProcessEditField();
|
598
|
+
if (e) Event.stop(e);
|
599
|
+
},
|
600
|
+
enterHover: function(e) {
|
601
|
+
if (this.options.hoverClassName)
|
602
|
+
this.element.addClassName(this.options.hoverClassName);
|
603
|
+
if (this._saving) return;
|
604
|
+
this.triggerCallback('onEnterHover');
|
635
605
|
},
|
636
606
|
getText: function() {
|
637
607
|
return this.element.innerHTML;
|
638
608
|
},
|
639
|
-
|
640
|
-
|
641
|
-
this.
|
642
|
-
|
643
|
-
this.
|
644
|
-
Object.extend({
|
645
|
-
asynchronous: true,
|
646
|
-
onComplete: this.onLoadedExternalText.bind(this)
|
647
|
-
}, this.options.ajaxOptions)
|
648
|
-
);
|
649
|
-
},
|
650
|
-
onLoadedExternalText: function(transport) {
|
651
|
-
Element.removeClassName(this.form, this.options.loadingClassName);
|
652
|
-
this.editField.disabled = false;
|
653
|
-
this.editField.value = transport.responseText.stripTags();
|
654
|
-
Field.scrollFreeActivate(this.editField);
|
655
|
-
},
|
656
|
-
onclickCancel: function() {
|
657
|
-
this.onComplete();
|
658
|
-
this.leaveEditMode();
|
659
|
-
return false;
|
660
|
-
},
|
661
|
-
onFailure: function(transport) {
|
662
|
-
this.options.onFailure(transport);
|
663
|
-
if (this.oldInnerHTML) {
|
664
|
-
this.element.innerHTML = this.oldInnerHTML;
|
665
|
-
this.oldInnerHTML = null;
|
609
|
+
handleAJAXFailure: function(transport) {
|
610
|
+
this.triggerCallback('onFailure', transport);
|
611
|
+
if (this._oldInnerHTML) {
|
612
|
+
this.element.innerHTML = this._oldInnerHTML;
|
613
|
+
this._oldInnerHTML = null;
|
666
614
|
}
|
667
|
-
return false;
|
668
615
|
},
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
this.
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
this.
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
}, this.options.ajaxOptions));
|
698
|
-
}
|
699
|
-
// stop the event to avoid a page refresh in Safari
|
700
|
-
if (arguments.length > 1) {
|
701
|
-
Event.stop(arguments[0]);
|
616
|
+
handleFormCancellation: function(e) {
|
617
|
+
this.wrapUp();
|
618
|
+
if (e) Event.stop(e);
|
619
|
+
},
|
620
|
+
handleFormSubmission: function(e) {
|
621
|
+
var form = this._form;
|
622
|
+
var value = $F(this._controls.editor);
|
623
|
+
this.prepareSubmission();
|
624
|
+
var params = this.options.callback(form, value) || '';
|
625
|
+
if (Object.isString(params))
|
626
|
+
params = params.toQueryParams();
|
627
|
+
params.editorId = this.element.id;
|
628
|
+
if (this.options.htmlResponse) {
|
629
|
+
var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
|
630
|
+
Object.extend(options, {
|
631
|
+
parameters: params,
|
632
|
+
onComplete: this._boundWrapperHandler,
|
633
|
+
onFailure: this._boundFailureHandler
|
634
|
+
});
|
635
|
+
new Ajax.Updater({ success: this.element }, this.url, options);
|
636
|
+
} else {
|
637
|
+
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
|
638
|
+
Object.extend(options, {
|
639
|
+
parameters: params,
|
640
|
+
onComplete: this._boundWrapperHandler,
|
641
|
+
onFailure: this._boundFailureHandler
|
642
|
+
});
|
643
|
+
new Ajax.Request(this.url, options);
|
702
644
|
}
|
703
|
-
|
645
|
+
if (e) Event.stop(e);
|
646
|
+
},
|
647
|
+
leaveEditMode: function() {
|
648
|
+
this.element.removeClassName(this.options.savingClassName);
|
649
|
+
this.removeForm();
|
650
|
+
this.leaveHover();
|
651
|
+
this.element.style.backgroundColor = this._originalBackground;
|
652
|
+
this.element.show();
|
653
|
+
if (this.options.externalControl)
|
654
|
+
this.options.externalControl.show();
|
655
|
+
this._saving = false;
|
656
|
+
this._editing = false;
|
657
|
+
this._oldInnerHTML = null;
|
658
|
+
this.triggerCallback('onLeaveEditMode');
|
659
|
+
},
|
660
|
+
leaveHover: function(e) {
|
661
|
+
if (this.options.hoverClassName)
|
662
|
+
this.element.removeClassName(this.options.hoverClassName);
|
663
|
+
if (this._saving) return;
|
664
|
+
this.triggerCallback('onLeaveHover');
|
704
665
|
},
|
705
|
-
|
706
|
-
this.
|
666
|
+
loadExternalText: function() {
|
667
|
+
this._form.addClassName(this.options.loadingClassName);
|
668
|
+
this._controls.editor.disabled = true;
|
669
|
+
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
|
670
|
+
Object.extend(options, {
|
671
|
+
parameters: 'editorId=' + encodeURIComponent(this.element.id),
|
672
|
+
onComplete: Prototype.emptyFunction,
|
673
|
+
onSuccess: function(transport) {
|
674
|
+
this._form.removeClassName(this.options.loadingClassName);
|
675
|
+
var text = transport.responseText;
|
676
|
+
if (this.options.stripLoadedTextTags)
|
677
|
+
text = text.stripTags();
|
678
|
+
this._controls.editor.value = text;
|
679
|
+
this._controls.editor.disabled = false;
|
680
|
+
this.postProcessEditField();
|
681
|
+
}.bind(this),
|
682
|
+
onFailure: this._boundFailureHandler
|
683
|
+
});
|
684
|
+
new Ajax.Request(this.options.loadTextURL, options);
|
685
|
+
},
|
686
|
+
postProcessEditField: function() {
|
687
|
+
var fpc = this.options.fieldPostCreation;
|
688
|
+
if (fpc)
|
689
|
+
$(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
|
690
|
+
},
|
691
|
+
prepareOptions: function() {
|
692
|
+
this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
|
693
|
+
Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
|
694
|
+
[this._extraDefaultOptions].flatten().compact().each(function(defs) {
|
695
|
+
Object.extend(this.options, defs);
|
696
|
+
}.bind(this));
|
697
|
+
},
|
698
|
+
prepareSubmission: function() {
|
699
|
+
this._saving = true;
|
707
700
|
this.removeForm();
|
708
701
|
this.leaveHover();
|
709
702
|
this.showSaving();
|
710
703
|
},
|
704
|
+
registerListeners: function() {
|
705
|
+
this._listeners = { };
|
706
|
+
var listener;
|
707
|
+
$H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
|
708
|
+
listener = this[pair.value].bind(this);
|
709
|
+
this._listeners[pair.key] = listener;
|
710
|
+
if (!this.options.externalControlOnly)
|
711
|
+
this.element.observe(pair.key, listener);
|
712
|
+
if (this.options.externalControl)
|
713
|
+
this.options.externalControl.observe(pair.key, listener);
|
714
|
+
}.bind(this));
|
715
|
+
},
|
716
|
+
removeForm: function() {
|
717
|
+
if (!this._form) return;
|
718
|
+
this._form.remove();
|
719
|
+
this._form = null;
|
720
|
+
this._controls = { };
|
721
|
+
},
|
711
722
|
showSaving: function() {
|
712
|
-
this.
|
723
|
+
this._oldInnerHTML = this.element.innerHTML;
|
713
724
|
this.element.innerHTML = this.options.savingText;
|
714
|
-
|
715
|
-
this.element.style.backgroundColor = this.
|
716
|
-
|
725
|
+
this.element.addClassName(this.options.savingClassName);
|
726
|
+
this.element.style.backgroundColor = this._originalBackground;
|
727
|
+
this.element.show();
|
717
728
|
},
|
718
|
-
|
719
|
-
if(this.
|
720
|
-
|
721
|
-
this.form = null;
|
729
|
+
triggerCallback: function(cbName, arg) {
|
730
|
+
if ('function' == typeof this.options[cbName]) {
|
731
|
+
this.options[cbName](this, arg);
|
722
732
|
}
|
723
733
|
},
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
this.
|
729
|
-
|
730
|
-
|
734
|
+
unregisterListeners: function() {
|
735
|
+
$H(this._listeners).each(function(pair) {
|
736
|
+
if (!this.options.externalControlOnly)
|
737
|
+
this.element.stopObserving(pair.key, pair.value);
|
738
|
+
if (this.options.externalControl)
|
739
|
+
this.options.externalControl.stopObserving(pair.key, pair.value);
|
740
|
+
}.bind(this));
|
731
741
|
},
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
+
wrapUp: function(transport) {
|
743
|
+
this.leaveEditMode();
|
744
|
+
// Can't use triggerCallback due to backward compatibility: requires
|
745
|
+
// binding + direct element
|
746
|
+
this._boundComplete(transport, this.element);
|
747
|
+
}
|
748
|
+
});
|
749
|
+
|
750
|
+
Object.extend(Ajax.InPlaceEditor.prototype, {
|
751
|
+
dispose: Ajax.InPlaceEditor.prototype.destroy
|
752
|
+
});
|
753
|
+
|
754
|
+
Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
|
755
|
+
initialize: function($super, element, url, options) {
|
756
|
+
this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
|
757
|
+
$super(element, url, options);
|
758
|
+
},
|
759
|
+
|
760
|
+
createEditField: function() {
|
761
|
+
var list = document.createElement('select');
|
762
|
+
list.name = this.options.paramName;
|
763
|
+
list.size = 1;
|
764
|
+
this._controls.editor = list;
|
765
|
+
this._collection = this.options.collection || [];
|
766
|
+
if (this.options.loadCollectionURL)
|
767
|
+
this.loadCollection();
|
768
|
+
else
|
769
|
+
this.checkForExternalText();
|
770
|
+
this._form.appendChild(this._controls.editor);
|
771
|
+
},
|
772
|
+
|
773
|
+
loadCollection: function() {
|
774
|
+
this._form.addClassName(this.options.loadingClassName);
|
775
|
+
this.showLoadingText(this.options.loadingCollectionText);
|
776
|
+
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
|
777
|
+
Object.extend(options, {
|
778
|
+
parameters: 'editorId=' + encodeURIComponent(this.element.id),
|
779
|
+
onComplete: Prototype.emptyFunction,
|
780
|
+
onSuccess: function(transport) {
|
781
|
+
var js = transport.responseText.strip();
|
782
|
+
if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
|
783
|
+
throw 'Server returned an invalid collection representation.';
|
784
|
+
this._collection = eval(js);
|
785
|
+
this.checkForExternalText();
|
786
|
+
}.bind(this),
|
787
|
+
onFailure: this.onFailure
|
742
788
|
});
|
789
|
+
new Ajax.Request(this.options.loadCollectionURL, options);
|
743
790
|
},
|
744
|
-
|
745
|
-
|
746
|
-
this.
|
747
|
-
this.
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
791
|
+
|
792
|
+
showLoadingText: function(text) {
|
793
|
+
this._controls.editor.disabled = true;
|
794
|
+
var tempOption = this._controls.editor.firstChild;
|
795
|
+
if (!tempOption) {
|
796
|
+
tempOption = document.createElement('option');
|
797
|
+
tempOption.value = '';
|
798
|
+
this._controls.editor.appendChild(tempOption);
|
799
|
+
tempOption.selected = true;
|
752
800
|
}
|
753
|
-
|
754
|
-
this.saving = false;
|
755
|
-
this.oldInnerHTML = null;
|
756
|
-
this.onLeaveEditMode();
|
801
|
+
tempOption.update((text || '').stripScripts().stripTags());
|
757
802
|
},
|
758
|
-
|
759
|
-
|
760
|
-
this.
|
803
|
+
|
804
|
+
checkForExternalText: function() {
|
805
|
+
this._text = this.getText();
|
806
|
+
if (this.options.loadTextURL)
|
807
|
+
this.loadExternalText();
|
808
|
+
else
|
809
|
+
this.buildOptionList();
|
761
810
|
},
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
811
|
+
|
812
|
+
loadExternalText: function() {
|
813
|
+
this.showLoadingText(this.options.loadingText);
|
814
|
+
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
|
815
|
+
Object.extend(options, {
|
816
|
+
parameters: 'editorId=' + encodeURIComponent(this.element.id),
|
817
|
+
onComplete: Prototype.emptyFunction,
|
818
|
+
onSuccess: function(transport) {
|
819
|
+
this._text = transport.responseText.strip();
|
820
|
+
this.buildOptionList();
|
821
|
+
}.bind(this),
|
822
|
+
onFailure: this.onFailure
|
823
|
+
});
|
824
|
+
new Ajax.Request(this.options.loadTextURL, options);
|
825
|
+
},
|
826
|
+
|
827
|
+
buildOptionList: function() {
|
828
|
+
this._form.removeClassName(this.options.loadingClassName);
|
829
|
+
this._collection = this._collection.map(function(entry) {
|
830
|
+
return 2 === entry.length ? entry : [entry, entry].flatten();
|
831
|
+
});
|
832
|
+
var marker = ('value' in this.options) ? this.options.value : this._text;
|
833
|
+
var textFound = this._collection.any(function(entry) {
|
834
|
+
return entry[0] == marker;
|
835
|
+
}.bind(this));
|
836
|
+
this._controls.editor.update('');
|
837
|
+
var option;
|
838
|
+
this._collection.each(function(entry, index) {
|
839
|
+
option = document.createElement('option');
|
840
|
+
option.value = entry[0];
|
841
|
+
option.selected = textFound ? entry[0] == marker : 0 == index;
|
842
|
+
option.appendChild(document.createTextNode(entry[1]));
|
843
|
+
this._controls.editor.appendChild(option);
|
844
|
+
}.bind(this));
|
845
|
+
this._controls.editor.disabled = false;
|
846
|
+
Field.scrollFreeActivate(this._controls.editor);
|
777
847
|
}
|
778
|
-
};
|
848
|
+
});
|
779
849
|
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
}
|
850
|
+
//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
|
851
|
+
//**** This only exists for a while, in order to let ****
|
852
|
+
//**** users adapt to the new API. Read up on the new ****
|
853
|
+
//**** API and convert your code to it ASAP! ****
|
854
|
+
|
855
|
+
Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
|
856
|
+
if (!options) return;
|
857
|
+
function fallback(name, expr) {
|
858
|
+
if (name in options || expr === undefined) return;
|
859
|
+
options[name] = expr;
|
860
|
+
};
|
861
|
+
fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
|
862
|
+
options.cancelLink == options.cancelButton == false ? false : undefined)));
|
863
|
+
fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
|
864
|
+
options.okLink == options.okButton == false ? false : undefined)));
|
865
|
+
fallback('highlightColor', options.highlightcolor);
|
866
|
+
fallback('highlightEndColor', options.highlightendcolor);
|
867
|
+
};
|
799
868
|
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
869
|
+
Object.extend(Ajax.InPlaceEditor, {
|
870
|
+
DefaultOptions: {
|
871
|
+
ajaxOptions: { },
|
872
|
+
autoRows: 3, // Use when multi-line w/ rows == 1
|
873
|
+
cancelControl: 'link', // 'link'|'button'|false
|
874
|
+
cancelText: 'cancel',
|
875
|
+
clickToEditText: 'Click to edit',
|
876
|
+
externalControl: null, // id|elt
|
877
|
+
externalControlOnly: false,
|
878
|
+
fieldPostCreation: 'activate', // 'activate'|'focus'|false
|
879
|
+
formClassName: 'inplaceeditor-form',
|
880
|
+
formId: null, // id|elt
|
881
|
+
highlightColor: '#ffff99',
|
882
|
+
highlightEndColor: '#ffffff',
|
883
|
+
hoverClassName: '',
|
884
|
+
htmlResponse: true,
|
885
|
+
loadingClassName: 'inplaceeditor-loading',
|
886
|
+
loadingText: 'Loading...',
|
887
|
+
okControl: 'button', // 'link'|'button'|false
|
888
|
+
okText: 'ok',
|
889
|
+
paramName: 'value',
|
890
|
+
rows: 1, // If 1 and multi-line, uses autoRows
|
891
|
+
savingClassName: 'inplaceeditor-saving',
|
892
|
+
savingText: 'Saving...',
|
893
|
+
size: 0,
|
894
|
+
stripLoadedTextTags: false,
|
895
|
+
submitOnBlur: false,
|
896
|
+
textAfterControls: '',
|
897
|
+
textBeforeControls: '',
|
898
|
+
textBetweenControls: ''
|
899
|
+
},
|
900
|
+
DefaultCallbacks: {
|
901
|
+
callback: function(form) {
|
902
|
+
return Form.serialize(form);
|
903
|
+
},
|
904
|
+
onComplete: function(transport, element) {
|
905
|
+
// For backward compatibility, this one is bound to the IPE, and passes
|
906
|
+
// the element directly. It was too often customized, so we don't break it.
|
907
|
+
new Effect.Highlight(element, {
|
908
|
+
startcolor: this.options.highlightColor, keepBackgroundImage: true });
|
909
|
+
},
|
910
|
+
onEnterEditMode: null,
|
911
|
+
onEnterHover: function(ipe) {
|
912
|
+
ipe.element.style.backgroundColor = ipe.options.highlightColor;
|
913
|
+
if (ipe._effect)
|
914
|
+
ipe._effect.cancel();
|
915
|
+
},
|
916
|
+
onFailure: function(transport, ipe) {
|
917
|
+
alert('Error communication with the server: ' + transport.responseText.stripTags());
|
918
|
+
},
|
919
|
+
onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
|
920
|
+
onLeaveEditMode: null,
|
921
|
+
onLeaveHover: function(ipe) {
|
922
|
+
ipe._effect = new Effect.Highlight(ipe.element, {
|
923
|
+
startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
|
924
|
+
restorecolor: ipe._originalBackground, keepBackgroundImage: true
|
925
|
+
});
|
805
926
|
}
|
927
|
+
},
|
928
|
+
Listeners: {
|
929
|
+
click: 'enterEditMode',
|
930
|
+
keydown: 'checkForEscapeOrReturn',
|
931
|
+
mouseover: 'enterHover',
|
932
|
+
mouseout: 'leaveHover'
|
806
933
|
}
|
807
934
|
});
|
808
935
|
|
936
|
+
Ajax.InPlaceCollectionEditor.DefaultOptions = {
|
937
|
+
loadingCollectionText: 'Loading options...'
|
938
|
+
};
|
939
|
+
|
809
940
|
// Delayed observer, like Form.Element.Observer,
|
810
941
|
// but waits for delay after last key input
|
811
942
|
// Ideal for live-search fields
|
812
943
|
|
813
|
-
Form.Element.DelayedObserver = Class.create(
|
814
|
-
Form.Element.DelayedObserver.prototype = {
|
944
|
+
Form.Element.DelayedObserver = Class.create({
|
815
945
|
initialize: function(element, delay, callback) {
|
816
946
|
this.delay = delay || 0.5;
|
817
947
|
this.element = $(element);
|
@@ -830,4 +960,4 @@ Form.Element.DelayedObserver.prototype = {
|
|
830
960
|
this.timer = null;
|
831
961
|
this.callback(this.element, $F(this.element));
|
832
962
|
}
|
833
|
-
};
|
963
|
+
});
|