railties 3.0.0.beta → 3.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. data/CHANGELOG +15 -1
  2. data/README +9 -9
  3. data/bin/rails +28 -9
  4. data/guides/images/challenge.png +0 -0
  5. data/guides/images/edge_badge.png +0 -0
  6. data/guides/images/posts_index.png +0 -0
  7. data/guides/images/rails_welcome.png +0 -0
  8. data/guides/rails_guides.rb +9 -22
  9. data/guides/rails_guides/generator.rb +79 -50
  10. data/guides/rails_guides/textile_extensions.rb +3 -3
  11. data/guides/source/2_2_release_notes.textile +1 -1
  12. data/guides/source/2_3_release_notes.textile +1 -1
  13. data/guides/source/3_0_release_notes.textile +46 -38
  14. data/guides/source/action_controller_overview.textile +2 -2
  15. data/guides/source/action_mailer_basics.textile +4 -4
  16. data/guides/source/action_view_overview.textile +2 -2
  17. data/guides/source/active_record_querying.textile +73 -95
  18. data/guides/source/active_support_core_extensions.textile +993 -85
  19. data/guides/source/activerecord_validations_callbacks.textile +3 -3
  20. data/guides/source/caching_with_rails.textile +1 -1
  21. data/guides/source/command_line.textile +90 -88
  22. data/guides/source/configuring.textile +10 -10
  23. data/guides/source/contribute.textile +2 -2
  24. data/guides/source/contributing_to_rails.textile +14 -7
  25. data/guides/source/credits.textile.erb +8 -0
  26. data/guides/source/debugging_rails_applications.textile +6 -6
  27. data/guides/source/form_helpers.textile +1 -1
  28. data/guides/source/generators.textile +14 -14
  29. data/guides/source/getting_started.textile +634 -500
  30. data/guides/source/index.textile.erb +16 -1
  31. data/guides/source/layout.html.erb +7 -1
  32. data/guides/source/layouts_and_rendering.textile +299 -71
  33. data/guides/source/migrations.textile +5 -5
  34. data/guides/source/performance_testing.textile +8 -8
  35. data/guides/source/plugins.textile +26 -24
  36. data/guides/source/rails_on_rack.textile +5 -5
  37. data/guides/source/routing.textile +119 -117
  38. data/guides/source/security.textile +1 -1
  39. data/guides/source/testing.textile +4 -4
  40. data/lib/rails.rb +4 -1
  41. data/lib/rails/application.rb +44 -7
  42. data/lib/rails/application/bootstrap.rb +2 -14
  43. data/lib/rails/application/configuration.rb +69 -5
  44. data/lib/rails/application/finisher.rb +2 -3
  45. data/lib/rails/application/metal_loader.rb +1 -1
  46. data/lib/rails/application/routes_reloader.rb +1 -1
  47. data/lib/rails/backtrace_cleaner.rb +0 -11
  48. data/lib/rails/commands.rb +7 -6
  49. data/lib/rails/commands/application.rb +1 -1
  50. data/lib/rails/commands/console.rb +1 -1
  51. data/lib/rails/commands/dbconsole.rb +12 -0
  52. data/lib/rails/commands/destroy.rb +2 -2
  53. data/lib/rails/commands/generate.rb +2 -2
  54. data/lib/rails/commands/performance/benchmarker.rb +2 -2
  55. data/lib/rails/commands/performance/profiler.rb +2 -2
  56. data/lib/rails/commands/plugin.rb +6 -6
  57. data/lib/rails/commands/runner.rb +2 -0
  58. data/lib/rails/commands/server.rb +23 -8
  59. data/lib/rails/configuration.rb +2 -84
  60. data/lib/rails/console/app.rb +4 -3
  61. data/lib/rails/console/helpers.rb +3 -1
  62. data/lib/rails/engine.rb +107 -12
  63. data/lib/rails/engine/configuration.rb +8 -2
  64. data/lib/rails/generators.rb +22 -7
  65. data/lib/rails/generators/actions.rb +16 -6
  66. data/lib/rails/generators/base.rb +15 -8
  67. data/lib/rails/generators/erb.rb +21 -0
  68. data/lib/{generators → rails/generators}/erb/controller/controller_generator.rb +4 -5
  69. data/lib/{generators → rails/generators}/erb/controller/templates/view.html.erb +0 -0
  70. data/lib/rails/generators/erb/mailer/mailer_generator.rb +13 -0
  71. data/lib/{generators → rails/generators}/erb/mailer/templates/view.text.erb +0 -0
  72. data/lib/{generators → rails/generators}/erb/scaffold/scaffold_generator.rb +14 -26
  73. data/lib/{generators → rails/generators}/erb/scaffold/templates/_form.html.erb +1 -1
  74. data/lib/{generators → rails/generators}/erb/scaffold/templates/edit.html.erb +0 -0
  75. data/lib/{generators → rails/generators}/erb/scaffold/templates/index.html.erb +1 -1
  76. data/lib/{generators → rails/generators}/erb/scaffold/templates/layout.html.erb +1 -0
  77. data/lib/{generators → rails/generators}/erb/scaffold/templates/new.html.erb +0 -0
  78. data/lib/{generators → rails/generators}/erb/scaffold/templates/show.html.erb +0 -0
  79. data/lib/rails/generators/named_base.rb +4 -0
  80. data/lib/{generators → rails/generators}/rails/app/USAGE +0 -0
  81. data/lib/{generators → rails/generators}/rails/app/app_generator.rb +21 -7
  82. data/lib/rails/generators/rails/app/templates/Gemfile +34 -0
  83. data/lib/{generators → rails/generators}/rails/app/templates/README +9 -8
  84. data/lib/{generators → rails/generators}/rails/app/templates/Rakefile +0 -0
  85. data/lib/{generators → rails/generators}/rails/app/templates/app/controllers/application_controller.rb +0 -0
  86. data/lib/{generators → rails/generators}/rails/app/templates/app/helpers/application_helper.rb +0 -0
  87. data/lib/{generators → rails/generators}/rails/app/templates/app/models/.empty_directory +0 -0
  88. data/lib/{generators → rails/generators}/rails/app/templates/app/views/layouts/.empty_directory +0 -0
  89. data/lib/{generators → rails/generators}/rails/app/templates/config.ru +0 -0
  90. data/lib/{generators → rails/generators}/rails/app/templates/config/application.rb +4 -3
  91. data/lib/rails/generators/rails/app/templates/config/boot.rb +14 -0
  92. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/frontbase.yml +0 -0
  93. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/ibm_db.yml +0 -0
  94. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/mysql.yml +0 -0
  95. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/oracle.yml +0 -0
  96. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/postgresql.yml +0 -0
  97. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/sqlite3.yml +0 -0
  98. data/lib/{generators → rails/generators}/rails/app/templates/config/environment.rb +0 -0
  99. data/lib/{generators → rails/generators}/rails/app/templates/config/environments/development.rb.tt +0 -0
  100. data/lib/{generators → rails/generators}/rails/app/templates/config/environments/production.rb.tt +9 -0
  101. data/lib/{generators → rails/generators}/rails/app/templates/config/environments/test.rb.tt +0 -0
  102. data/lib/{generators → rails/generators}/rails/app/templates/config/initializers/backtrace_silencers.rb +0 -0
  103. data/lib/{generators → rails/generators}/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt +1 -1
  104. data/lib/{generators → rails/generators}/rails/app/templates/config/initializers/inflections.rb +0 -0
  105. data/lib/{generators → rails/generators}/rails/app/templates/config/initializers/mime_types.rb +0 -0
  106. data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +10 -0
  107. data/lib/{generators → rails/generators}/rails/app/templates/config/locales/en.yml +0 -0
  108. data/lib/{generators → rails/generators}/rails/app/templates/config/routes.rb +0 -0
  109. data/lib/{generators → rails/generators}/rails/app/templates/db/seeds.rb +0 -0
  110. data/lib/{generators → rails/generators}/rails/app/templates/doc/README_FOR_APP +0 -0
  111. data/lib/{generators → rails/generators}/rails/app/templates/gitignore +0 -0
  112. data/lib/{generators → rails/generators}/rails/app/templates/public/404.html +0 -0
  113. data/lib/{generators → rails/generators}/rails/app/templates/public/422.html +0 -0
  114. data/lib/{generators → rails/generators}/rails/app/templates/public/500.html +0 -0
  115. data/lib/{generators → rails/generators}/rails/app/templates/public/favicon.ico +0 -0
  116. data/lib/{generators → rails/generators}/rails/app/templates/public/images/rails.png +0 -0
  117. data/lib/{generators → rails/generators}/rails/app/templates/public/index.html +17 -17
  118. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/application.js +0 -0
  119. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/controls.js +5 -3
  120. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/dragdrop.js +7 -6
  121. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/effects.js +8 -13
  122. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/prototype.js +1573 -1019
  123. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/rails.js +1 -2
  124. data/lib/{generators → rails/generators}/rails/app/templates/public/robots.txt +0 -0
  125. data/lib/{generators → rails/generators}/rails/app/templates/public/stylesheets/.empty_directory +0 -0
  126. data/lib/{generators → rails/generators}/rails/app/templates/script/rails +0 -1
  127. data/lib/{generators → rails/generators}/rails/app/templates/test/fixtures/.empty_directory +0 -0
  128. data/lib/{generators → rails/generators}/rails/app/templates/test/functional/.empty_directory +0 -0
  129. data/lib/{generators → rails/generators}/rails/app/templates/test/integration/.empty_directory +0 -0
  130. data/lib/{generators → rails/generators}/rails/app/templates/test/performance/browsing_test.rb +1 -1
  131. data/lib/{generators → rails/generators}/rails/app/templates/test/test_helper.rb +1 -1
  132. data/lib/{generators → rails/generators}/rails/app/templates/test/unit/.empty_directory +0 -0
  133. data/lib/{generators → rails/generators}/rails/controller/USAGE +1 -1
  134. data/lib/{generators → rails/generators}/rails/controller/controller_generator.rb +6 -0
  135. data/lib/{generators → rails/generators}/rails/controller/templates/controller.rb +0 -0
  136. data/lib/{generators → rails/generators}/rails/generator/USAGE +1 -1
  137. data/lib/{generators → rails/generators}/rails/generator/generator_generator.rb +0 -0
  138. data/lib/{generators → rails/generators}/rails/generator/templates/%file_name%_generator.rb.tt +0 -0
  139. data/lib/{generators → rails/generators}/rails/generator/templates/USAGE.tt +1 -1
  140. data/lib/{generators → rails/generators}/rails/generator/templates/templates/.empty_directory +0 -0
  141. data/lib/{generators → rails/generators}/rails/helper/USAGE +1 -1
  142. data/lib/{generators → rails/generators}/rails/helper/helper_generator.rb +0 -0
  143. data/lib/{generators → rails/generators}/rails/helper/templates/helper.rb +0 -0
  144. data/lib/{generators → rails/generators}/rails/integration_test/USAGE +1 -1
  145. data/lib/{generators → rails/generators}/rails/integration_test/integration_test_generator.rb +0 -0
  146. data/lib/{generators → rails/generators}/rails/mailer/USAGE +1 -1
  147. data/lib/{generators → rails/generators}/rails/mailer/mailer_generator.rb +0 -0
  148. data/lib/{generators → rails/generators}/rails/mailer/templates/mailer.rb +0 -0
  149. data/lib/{generators → rails/generators}/rails/metal/USAGE +1 -1
  150. data/lib/{generators → rails/generators}/rails/metal/metal_generator.rb +0 -0
  151. data/lib/{generators → rails/generators}/rails/metal/templates/metal.rb +0 -0
  152. data/lib/{generators → rails/generators}/rails/migration/USAGE +2 -2
  153. data/lib/{generators → rails/generators}/rails/migration/migration_generator.rb +0 -0
  154. data/lib/{generators → rails/generators}/rails/model/USAGE +2 -2
  155. data/lib/{generators → rails/generators}/rails/model/model_generator.rb +0 -0
  156. data/lib/{generators → rails/generators}/rails/observer/USAGE +1 -1
  157. data/lib/{generators → rails/generators}/rails/observer/observer_generator.rb +0 -0
  158. data/lib/{generators → rails/generators}/rails/performance_test/USAGE +1 -1
  159. data/lib/{generators → rails/generators}/rails/performance_test/performance_test_generator.rb +0 -0
  160. data/lib/{generators → rails/generators}/rails/plugin/USAGE +1 -1
  161. data/lib/{generators → rails/generators}/rails/plugin/plugin_generator.rb +1 -1
  162. data/lib/{generators → rails/generators}/rails/plugin/templates/MIT-LICENSE.tt +0 -0
  163. data/lib/{generators → rails/generators}/rails/plugin/templates/README.tt +0 -0
  164. data/lib/rails/generators/rails/plugin/templates/Rakefile.tt +23 -0
  165. data/lib/{generators → rails/generators}/rails/plugin/templates/init.rb +0 -0
  166. data/lib/{generators → rails/generators}/rails/plugin/templates/install.rb +0 -0
  167. data/lib/{generators → rails/generators}/rails/plugin/templates/lib/%file_name%.rb.tt +0 -0
  168. data/lib/{generators → rails/generators}/rails/plugin/templates/lib/tasks/%file_name%_tasks.rake.tt +0 -0
  169. data/lib/{generators → rails/generators}/rails/plugin/templates/uninstall.rb +0 -0
  170. data/lib/{generators → rails/generators}/rails/resource/USAGE +3 -3
  171. data/lib/{generators → rails/generators}/rails/resource/resource_generator.rb +3 -1
  172. data/lib/{generators → rails/generators}/rails/scaffold/USAGE +4 -4
  173. data/lib/{generators → rails/generators}/rails/scaffold/scaffold_generator.rb +1 -1
  174. data/lib/{generators → rails/generators}/rails/scaffold_controller/USAGE +1 -1
  175. data/lib/{generators → rails/generators}/rails/scaffold_controller/scaffold_controller_generator.rb +0 -0
  176. data/lib/{generators → rails/generators}/rails/scaffold_controller/templates/controller.rb +2 -2
  177. data/lib/{generators → rails/generators}/rails/session_migration/USAGE +1 -1
  178. data/lib/{generators → rails/generators}/rails/session_migration/session_migration_generator.rb +0 -0
  179. data/lib/{generators → rails/generators}/rails/stylesheets/USAGE +1 -1
  180. data/lib/{generators → rails/generators}/rails/stylesheets/stylesheets_generator.rb +0 -0
  181. data/lib/{generators → rails/generators}/rails/stylesheets/templates/scaffold.css +4 -0
  182. data/lib/{generators → rails/generators}/test_unit.rb +0 -0
  183. data/lib/{generators → rails/generators}/test_unit/controller/controller_generator.rb +2 -1
  184. data/lib/rails/generators/test_unit/controller/templates/functional_test.rb +18 -0
  185. data/lib/{generators → rails/generators}/test_unit/helper/helper_generator.rb +1 -1
  186. data/lib/{generators → rails/generators}/test_unit/helper/templates/helper_test.rb +0 -0
  187. data/lib/{generators → rails/generators}/test_unit/integration/integration_generator.rb +1 -1
  188. data/lib/{generators → rails/generators}/test_unit/integration/templates/integration_test.rb +0 -0
  189. data/lib/{generators → rails/generators}/test_unit/mailer/mailer_generator.rb +1 -8
  190. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb +20 -0
  191. data/lib/{generators → rails/generators}/test_unit/model/model_generator.rb +1 -1
  192. data/lib/{generators → rails/generators}/test_unit/model/templates/fixtures.yml +0 -0
  193. data/lib/{generators → rails/generators}/test_unit/model/templates/unit_test.rb +0 -0
  194. data/lib/{generators → rails/generators}/test_unit/observer/observer_generator.rb +1 -1
  195. data/lib/{generators → rails/generators}/test_unit/observer/templates/unit_test.rb +0 -0
  196. data/lib/{generators → rails/generators}/test_unit/performance/performance_generator.rb +1 -1
  197. data/lib/{generators → rails/generators}/test_unit/performance/templates/performance_test.rb +0 -0
  198. data/lib/{generators → rails/generators}/test_unit/plugin/plugin_generator.rb +1 -1
  199. data/lib/{generators → rails/generators}/test_unit/plugin/templates/%file_name%_test.rb.tt +0 -0
  200. data/lib/{generators → rails/generators}/test_unit/plugin/templates/test_helper.rb +0 -0
  201. data/lib/{generators → rails/generators}/test_unit/scaffold/scaffold_generator.rb +1 -1
  202. data/lib/{generators → rails/generators}/test_unit/scaffold/templates/functional_test.rb +9 -5
  203. data/{builtin/rails_info → lib}/rails/info.rb +0 -0
  204. data/{builtin/rails_info → lib}/rails/info_controller.rb +0 -0
  205. data/{builtin/routes.rb → lib/rails/info_routes.rb} +2 -2
  206. data/lib/rails/{subscriber.rb → log_subscriber.rb} +27 -27
  207. data/lib/rails/{subscriber → log_subscriber}/test_helper.rb +15 -16
  208. data/lib/rails/plugin.rb +31 -8
  209. data/lib/rails/rack/debugger.rb +3 -1
  210. data/lib/rails/rack/logger.rb +4 -4
  211. data/lib/rails/railtie.rb +179 -16
  212. data/lib/rails/railtie/configuration.rb +56 -1
  213. data/lib/rails/tasks/documentation.rake +38 -20
  214. data/lib/rails/tasks/framework.rake +16 -9
  215. data/lib/rails/tasks/misc.rake +3 -5
  216. data/lib/rails/tasks/routes.rake +2 -2
  217. data/lib/rails/test_help.rb +21 -1
  218. data/lib/rails/test_unit/railtie.rb +1 -3
  219. data/lib/rails/version.rb +3 -2
  220. metadata +199 -171
  221. data/builtin/rails_info/rails/info_helper.rb +0 -2
  222. data/lib/generators/erb.rb +0 -8
  223. data/lib/generators/erb/mailer/mailer_generator.rb +0 -20
  224. data/lib/generators/rails/app/templates/Gemfile +0 -34
  225. data/lib/generators/rails/app/templates/config/boot.rb +0 -17
  226. data/lib/generators/rails/app/templates/config/initializers/session_store.rb.tt +0 -15
  227. data/lib/generators/rails/model_subclass/model_subclass_generator.rb +0 -12
  228. data/lib/generators/rails/plugin/templates/Rakefile.tt +0 -10
  229. data/lib/generators/test_unit/controller/templates/functional_test.rb +0 -8
  230. data/lib/generators/test_unit/mailer/templates/fixture +0 -3
  231. data/lib/generators/test_unit/mailer/templates/functional_test.rb +0 -22
  232. data/lib/rails/railties_path.rb +0 -1
@@ -11,8 +11,9 @@ require "active_resource/railtie"
11
11
  require "rails/test_unit/railtie"
12
12
  <% end -%>
13
13
 
14
- # Auto-require default libraries and those for the current Rails environment.
15
- Bundler.require :default, Rails.env
14
+ # If you have a Gemfile, require the gems listed there, including any gems
15
+ # you've limited to :test, :development, or :production.
16
+ Bundler.require(:default, Rails.env) if defined?(Bundler)
16
17
 
17
18
  module <%= app_const_base %>
18
19
  class Application < Rails::Application
@@ -35,7 +36,7 @@ module <%= app_const_base %>
35
36
  # config.time_zone = 'Central Time (US & Canada)'
36
37
 
37
38
  # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
38
- # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
39
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
39
40
  # config.i18n.default_locale = :de
40
41
 
41
42
  # Configure generators values. Many other options are available, be sure to check the documentation.
@@ -0,0 +1,14 @@
1
+ # Use locked gems if present.
2
+ begin
3
+ require File.expand_path('../../.bundle/environment', __FILE__)
4
+
5
+ rescue LoadError
6
+ # Otherwise, use RubyGems.
7
+ require 'rubygems'
8
+
9
+ # And set up the gems listed in the Gemfile.
10
+ if File.exist?(File.expand_path('../../Gemfile', __FILE__))
11
+ require 'bundler'
12
+ Bundler.setup
13
+ end
14
+ end
@@ -9,6 +9,15 @@
9
9
  config.consider_all_requests_local = false
10
10
  config.action_controller.perform_caching = true
11
11
 
12
+ # Specifies the header that your server uses for sending files
13
+ config.action_dispatch.x_sendfile_header = "X-Sendfile"
14
+
15
+ # For nginx:
16
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
17
+
18
+ # If you have no front-end server that supports something like X-Sendfile,
19
+ # just comment this out and Rails will serve the files
20
+
12
21
  # See everything in the log (default is :info)
13
22
  # config.log_level = :debug
14
23
 
@@ -4,4 +4,4 @@
4
4
  # If you change this key, all old signed cookies will become invalid!
5
5
  # Make sure the secret is at least 30 characters and all random,
6
6
  # no regular words or you'll be exposed to dictionary attacks.
7
- ActionController::Base.cookie_verifier_secret = '<%= app_secret %>'
7
+ Rails.application.config.cookie_secret = '<%= app_secret %>'
@@ -0,0 +1,10 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ Rails.application.config.session_store :cookie_store, {
4
+ :key => '_<%= app_name %>_session',
5
+ }
6
+
7
+ # Use the database for sessions instead of the cookie-based default,
8
+ # which shouldn't be used to store highly confidential information
9
+ # (create the session table with "rake db:sessions:create")
10
+ # Rails.application.config.session_store :active_record_store
@@ -181,27 +181,27 @@
181
181
  }
182
182
 
183
183
  </style>
184
- <script type="text/javascript" src="javascripts/prototype.js"></script>
185
- <script type="text/javascript" src="javascripts/effects.js"></script>
186
184
  <script type="text/javascript">
187
185
  function about() {
188
- if (Element.empty('about-content')) {
189
- new Ajax.Updater('about-content', 'rails/info/properties', {
190
- method: 'get',
191
- onFailure: function() {Element.classNames('about-content').add('failure')},
192
- onComplete: function() {new Effect.BlindDown('about-content', {duration: 0.25})}
193
- });
194
- } else {
195
- new Effect[Element.visible('about-content') ?
196
- 'BlindUp' : 'BlindDown']('about-content', {duration: 0.25});
197
- }
186
+ info = document.getElementById('about-content');
187
+ if (window.XMLHttpRequest)
188
+ { xhr = new XMLHttpRequest(); }
189
+ else
190
+ { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
191
+ xhr.open("GET","rails/info/properties",false);
192
+ xhr.send("");
193
+ info.innerHTML = xhr.responseText;
194
+ info.style.display = 'block'
195
+ }
196
+
197
+ function prepend() {
198
+ search = document.getElementById('search-text');
199
+ text = search.value;
200
+ search.value = 'site:rubyonrails.org ' + text;
198
201
  }
199
202
 
200
203
  window.onload = function() {
201
- $('search-text').value = '';
202
- $('search').onsubmit = function() {
203
- $('search-text').value = 'site:rubyonrails.org ' + $F('search-text');
204
- }
204
+ document.getElementById('search-text').value = '';
205
205
  }
206
206
  </script>
207
207
  </head>
@@ -210,7 +210,7 @@
210
210
  <div id="sidebar">
211
211
  <ul id="sidebar-items">
212
212
  <li>
213
- <form id="search" action="http://www.google.com/search" method="get">
213
+ <form id="search" action="http://www.google.com/search" method="get" onSubmit="prepend();">
214
214
  <input type="hidden" name="hl" value="en" />
215
215
  <input type="text" id="search-text" name="q" value="site:rubyonrails.org " />
216
216
  <input type="submit" value="Search" /> the Rails site
@@ -1,6 +1,8 @@
1
- // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
- // (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
3
- // (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
1
+ // script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009
2
+
3
+ // Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ // (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
5
+ // (c) 2005-2009 Jon Tirsen (http://www.tirsen.com)
4
6
  // Contributors:
5
7
  // Richard Livsey
6
8
  // Rahul Bhargava
@@ -1,5 +1,6 @@
1
- // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
- // (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
1
+ // script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009
2
+
3
+ // Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
3
4
  //
4
5
  // script.aculo.us is freely distributable under the terms of an MIT-style license.
5
6
  // For details, see the script.aculo.us web site: http://script.aculo.us/
@@ -311,7 +312,7 @@ var Draggable = Class.create({
311
312
  tag_name=='TEXTAREA')) return;
312
313
 
313
314
  var pointer = [Event.pointerX(event), Event.pointerY(event)];
314
- var pos = Position.cumulativeOffset(this.element);
315
+ var pos = this.element.cumulativeOffset();
315
316
  this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
316
317
 
317
318
  Draggables.activate(this);
@@ -454,7 +455,7 @@ var Draggable = Class.create({
454
455
  },
455
456
 
456
457
  draw: function(point) {
457
- var pos = Position.cumulativeOffset(this.element);
458
+ var pos = this.element.cumulativeOffset();
458
459
  if(this.options.ghosting) {
459
460
  var r = Position.realOffset(this.element);
460
461
  pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
@@ -730,7 +731,7 @@ var Sortable = {
730
731
  }
731
732
 
732
733
  // keep reference
733
- this.sortables[element.id] = options;
734
+ this.sortables[element.identify()] = options;
734
735
 
735
736
  // for onupdate
736
737
  Draggables.addObserver(new SortableObserver(element, options.onUpdate));
@@ -825,7 +826,7 @@ var Sortable = {
825
826
  hide().addClassName('dropmarker').setStyle({position:'absolute'});
826
827
  document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
827
828
  }
828
- var offsets = Position.cumulativeOffset(dropon);
829
+ var offsets = dropon.cumulativeOffset();
829
830
  Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
830
831
 
831
832
  if(position=='after')
@@ -1,4 +1,6 @@
1
- // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
1
+ // script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009
2
+
3
+ // Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
4
  // Contributors:
3
5
  // Justin Palmer (http://encytemedia.com/)
4
6
  // Mark Pilgrim (http://diveintomark.org/)
@@ -145,14 +147,13 @@ var Effect = {
145
147
  'blind': ['BlindDown','BlindUp'],
146
148
  'appear': ['Appear','Fade']
147
149
  },
148
- toggle: function(element, effect) {
150
+ toggle: function(element, effect, options) {
149
151
  element = $(element);
150
- effect = (effect || 'appear').toLowerCase();
151
- var options = Object.extend({
152
+ effect = (effect || 'appear').toLowerCase();
153
+
154
+ return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({
152
155
  queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
153
- }, arguments[2] || { });
154
- Effect[element.visible() ?
155
- Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
156
+ }, options || {}));
156
157
  }
157
158
  };
158
159
 
@@ -228,12 +229,6 @@ Effect.Queue = Effect.Queues.get('global');
228
229
  Effect.Base = Class.create({
229
230
  position: null,
230
231
  start: function(options) {
231
- function codeForEvent(options,eventName){
232
- return (
233
- (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
234
- (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
235
- );
236
- }
237
232
  if (options && options.transition === false) options.transition = Effect.Transitions.linear;
238
233
  this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
239
234
  this.currentFrame = 0;
@@ -1,5 +1,5 @@
1
- /* Prototype JavaScript framework, version 1.6.0.3
2
- * (c) 2005-2008 Sam Stephenson
1
+ /* Prototype JavaScript framework, version 1.6.1
2
+ * (c) 2005-2009 Sam Stephenson
3
3
  *
4
4
  * Prototype is freely distributable under the terms of an MIT-style license.
5
5
  * For details, see the Prototype web site: http://www.prototypejs.org/
@@ -7,26 +7,43 @@
7
7
  *--------------------------------------------------------------------------*/
8
8
 
9
9
  var Prototype = {
10
- Version: '1.6.0.3',
11
-
12
- Browser: {
13
- IE: !!(window.attachEvent &&
14
- navigator.userAgent.indexOf('Opera') === -1),
15
- Opera: navigator.userAgent.indexOf('Opera') > -1,
16
- WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
17
- Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
18
- navigator.userAgent.indexOf('KHTML') === -1,
19
- MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
20
- },
10
+ Version: '1.6.1',
11
+
12
+ Browser: (function(){
13
+ var ua = navigator.userAgent;
14
+ var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
15
+ return {
16
+ IE: !!window.attachEvent && !isOpera,
17
+ Opera: isOpera,
18
+ WebKit: ua.indexOf('AppleWebKit/') > -1,
19
+ Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
20
+ MobileSafari: /Apple.*Mobile.*Safari/.test(ua)
21
+ }
22
+ })(),
21
23
 
22
24
  BrowserFeatures: {
23
25
  XPath: !!document.evaluate,
24
26
  SelectorsAPI: !!document.querySelector,
25
- ElementExtensions: !!window.HTMLElement,
26
- SpecificElementExtensions:
27
- document.createElement('div')['__proto__'] &&
28
- document.createElement('div')['__proto__'] !==
29
- document.createElement('form')['__proto__']
27
+ ElementExtensions: (function() {
28
+ var constructor = window.Element || window.HTMLElement;
29
+ return !!(constructor && constructor.prototype);
30
+ })(),
31
+ SpecificElementExtensions: (function() {
32
+ if (typeof window.HTMLDivElement !== 'undefined')
33
+ return true;
34
+
35
+ var div = document.createElement('div');
36
+ var form = document.createElement('form');
37
+ var isSupported = false;
38
+
39
+ if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
40
+ isSupported = true;
41
+ }
42
+
43
+ div = form = null;
44
+
45
+ return isSupported;
46
+ })()
30
47
  },
31
48
 
32
49
  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
@@ -40,9 +57,30 @@ if (Prototype.Browser.MobileSafari)
40
57
  Prototype.BrowserFeatures.SpecificElementExtensions = false;
41
58
 
42
59
 
60
+ var Abstract = { };
61
+
62
+
63
+ var Try = {
64
+ these: function() {
65
+ var returnValue;
66
+
67
+ for (var i = 0, length = arguments.length; i < length; i++) {
68
+ var lambda = arguments[i];
69
+ try {
70
+ returnValue = lambda();
71
+ break;
72
+ } catch (e) { }
73
+ }
74
+
75
+ return returnValue;
76
+ }
77
+ };
78
+
43
79
  /* Based on Alex Arnell's inheritance implementation. */
44
- var Class = {
45
- create: function() {
80
+
81
+ var Class = (function() {
82
+ function subclass() {};
83
+ function create() {
46
84
  var parent = null, properties = $A(arguments);
47
85
  if (Object.isFunction(properties[0]))
48
86
  parent = properties.shift();
@@ -56,7 +94,6 @@ var Class = {
56
94
  klass.subclasses = [];
57
95
 
58
96
  if (parent) {
59
- var subclass = function() { };
60
97
  subclass.prototype = parent.prototype;
61
98
  klass.prototype = new subclass;
62
99
  parent.subclasses.push(klass);
@@ -69,18 +106,19 @@ var Class = {
69
106
  klass.prototype.initialize = Prototype.emptyFunction;
70
107
 
71
108
  klass.prototype.constructor = klass;
72
-
73
109
  return klass;
74
110
  }
75
- };
76
111
 
77
- Class.Methods = {
78
- addMethods: function(source) {
112
+ function addMethods(source) {
79
113
  var ancestor = this.superclass && this.superclass.prototype;
80
114
  var properties = Object.keys(source);
81
115
 
82
- if (!Object.keys({ toString: true }).length)
83
- properties.push("toString", "valueOf");
116
+ if (!Object.keys({ toString: true }).length) {
117
+ if (source.toString != Object.prototype.toString)
118
+ properties.push("toString");
119
+ if (source.valueOf != Object.prototype.valueOf)
120
+ properties.push("valueOf");
121
+ }
84
122
 
85
123
  for (var i = 0, length = properties.length; i < length; i++) {
86
124
  var property = properties[i], value = source[property];
@@ -88,7 +126,7 @@ Class.Methods = {
88
126
  value.argumentNames().first() == "$super") {
89
127
  var method = value;
90
128
  value = (function(m) {
91
- return function() { return ancestor[m].apply(this, arguments) };
129
+ return function() { return ancestor[m].apply(this, arguments); };
92
130
  })(property).wrap(method);
93
131
 
94
132
  value.valueOf = method.valueOf.bind(method);
@@ -99,29 +137,36 @@ Class.Methods = {
99
137
 
100
138
  return this;
101
139
  }
102
- };
103
140
 
104
- var Abstract = { };
141
+ return {
142
+ create: create,
143
+ Methods: {
144
+ addMethods: addMethods
145
+ }
146
+ };
147
+ })();
148
+ (function() {
105
149
 
106
- Object.extend = function(destination, source) {
107
- for (var property in source)
108
- destination[property] = source[property];
109
- return destination;
110
- };
150
+ var _toString = Object.prototype.toString;
151
+
152
+ function extend(destination, source) {
153
+ for (var property in source)
154
+ destination[property] = source[property];
155
+ return destination;
156
+ }
111
157
 
112
- Object.extend(Object, {
113
- inspect: function(object) {
158
+ function inspect(object) {
114
159
  try {
115
- if (Object.isUndefined(object)) return 'undefined';
160
+ if (isUndefined(object)) return 'undefined';
116
161
  if (object === null) return 'null';
117
162
  return object.inspect ? object.inspect() : String(object);
118
163
  } catch (e) {
119
164
  if (e instanceof RangeError) return '...';
120
165
  throw e;
121
166
  }
122
- },
167
+ }
123
168
 
124
- toJSON: function(object) {
169
+ function toJSON(object) {
125
170
  var type = typeof object;
126
171
  switch (type) {
127
172
  case 'undefined':
@@ -132,131 +177,180 @@ Object.extend(Object, {
132
177
 
133
178
  if (object === null) return 'null';
134
179
  if (object.toJSON) return object.toJSON();
135
- if (Object.isElement(object)) return;
180
+ if (isElement(object)) return;
136
181
 
137
182
  var results = [];
138
183
  for (var property in object) {
139
- var value = Object.toJSON(object[property]);
140
- if (!Object.isUndefined(value))
184
+ var value = toJSON(object[property]);
185
+ if (!isUndefined(value))
141
186
  results.push(property.toJSON() + ': ' + value);
142
187
  }
143
188
 
144
189
  return '{' + results.join(', ') + '}';
145
- },
190
+ }
146
191
 
147
- toQueryString: function(object) {
192
+ function toQueryString(object) {
148
193
  return $H(object).toQueryString();
149
- },
194
+ }
150
195
 
151
- toHTML: function(object) {
196
+ function toHTML(object) {
152
197
  return object && object.toHTML ? object.toHTML() : String.interpret(object);
153
- },
198
+ }
154
199
 
155
- keys: function(object) {
156
- var keys = [];
200
+ function keys(object) {
201
+ var results = [];
157
202
  for (var property in object)
158
- keys.push(property);
159
- return keys;
160
- },
203
+ results.push(property);
204
+ return results;
205
+ }
161
206
 
162
- values: function(object) {
163
- var values = [];
207
+ function values(object) {
208
+ var results = [];
164
209
  for (var property in object)
165
- values.push(object[property]);
166
- return values;
167
- },
210
+ results.push(object[property]);
211
+ return results;
212
+ }
168
213
 
169
- clone: function(object) {
170
- return Object.extend({ }, object);
171
- },
214
+ function clone(object) {
215
+ return extend({ }, object);
216
+ }
172
217
 
173
- isElement: function(object) {
218
+ function isElement(object) {
174
219
  return !!(object && object.nodeType == 1);
175
- },
220
+ }
221
+
222
+ function isArray(object) {
223
+ return _toString.call(object) == "[object Array]";
224
+ }
176
225
 
177
- isArray: function(object) {
178
- return object != null && typeof object == "object" &&
179
- 'splice' in object && 'join' in object;
180
- },
181
226
 
182
- isHash: function(object) {
227
+ function isHash(object) {
183
228
  return object instanceof Hash;
184
- },
229
+ }
185
230
 
186
- isFunction: function(object) {
187
- return typeof object == "function";
188
- },
231
+ function isFunction(object) {
232
+ return typeof object === "function";
233
+ }
189
234
 
190
- isString: function(object) {
191
- return typeof object == "string";
192
- },
235
+ function isString(object) {
236
+ return _toString.call(object) == "[object String]";
237
+ }
193
238
 
194
- isNumber: function(object) {
195
- return typeof object == "number";
196
- },
239
+ function isNumber(object) {
240
+ return _toString.call(object) == "[object Number]";
241
+ }
197
242
 
198
- isUndefined: function(object) {
199
- return typeof object == "undefined";
243
+ function isUndefined(object) {
244
+ return typeof object === "undefined";
245
+ }
246
+
247
+ extend(Object, {
248
+ extend: extend,
249
+ inspect: inspect,
250
+ toJSON: toJSON,
251
+ toQueryString: toQueryString,
252
+ toHTML: toHTML,
253
+ keys: keys,
254
+ values: values,
255
+ clone: clone,
256
+ isElement: isElement,
257
+ isArray: isArray,
258
+ isHash: isHash,
259
+ isFunction: isFunction,
260
+ isString: isString,
261
+ isNumber: isNumber,
262
+ isUndefined: isUndefined
263
+ });
264
+ })();
265
+ Object.extend(Function.prototype, (function() {
266
+ var slice = Array.prototype.slice;
267
+
268
+ function update(array, args) {
269
+ var arrayLength = array.length, length = args.length;
270
+ while (length--) array[arrayLength + length] = args[length];
271
+ return array;
272
+ }
273
+
274
+ function merge(array, args) {
275
+ array = slice.call(array, 0);
276
+ return update(array, args);
200
277
  }
201
- });
202
278
 
203
- Object.extend(Function.prototype, {
204
- argumentNames: function() {
205
- var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
279
+ function argumentNames() {
280
+ var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
281
+ .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
206
282
  .replace(/\s+/g, '').split(',');
207
283
  return names.length == 1 && !names[0] ? [] : names;
208
- },
284
+ }
209
285
 
210
- bind: function() {
286
+ function bind(context) {
211
287
  if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
212
- var __method = this, args = $A(arguments), object = args.shift();
288
+ var __method = this, args = slice.call(arguments, 1);
213
289
  return function() {
214
- return __method.apply(object, args.concat($A(arguments)));
290
+ var a = merge(args, arguments);
291
+ return __method.apply(context, a);
215
292
  }
216
- },
293
+ }
217
294
 
218
- bindAsEventListener: function() {
219
- var __method = this, args = $A(arguments), object = args.shift();
295
+ function bindAsEventListener(context) {
296
+ var __method = this, args = slice.call(arguments, 1);
220
297
  return function(event) {
221
- return __method.apply(object, [event || window.event].concat(args));
298
+ var a = update([event || window.event], args);
299
+ return __method.apply(context, a);
222
300
  }
223
- },
301
+ }
224
302
 
225
- curry: function() {
303
+ function curry() {
226
304
  if (!arguments.length) return this;
227
- var __method = this, args = $A(arguments);
305
+ var __method = this, args = slice.call(arguments, 0);
228
306
  return function() {
229
- return __method.apply(this, args.concat($A(arguments)));
307
+ var a = merge(args, arguments);
308
+ return __method.apply(this, a);
230
309
  }
231
- },
310
+ }
232
311
 
233
- delay: function() {
234
- var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
312
+ function delay(timeout) {
313
+ var __method = this, args = slice.call(arguments, 1);
314
+ timeout = timeout * 1000
235
315
  return window.setTimeout(function() {
236
316
  return __method.apply(__method, args);
237
317
  }, timeout);
238
- },
318
+ }
239
319
 
240
- defer: function() {
241
- var args = [0.01].concat($A(arguments));
320
+ function defer() {
321
+ var args = update([0.01], arguments);
242
322
  return this.delay.apply(this, args);
243
- },
323
+ }
244
324
 
245
- wrap: function(wrapper) {
325
+ function wrap(wrapper) {
246
326
  var __method = this;
247
327
  return function() {
248
- return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
328
+ var a = update([__method.bind(this)], arguments);
329
+ return wrapper.apply(this, a);
249
330
  }
250
- },
331
+ }
251
332
 
252
- methodize: function() {
333
+ function methodize() {
253
334
  if (this._methodized) return this._methodized;
254
335
  var __method = this;
255
336
  return this._methodized = function() {
256
- return __method.apply(null, [this].concat($A(arguments)));
337
+ var a = update([this], arguments);
338
+ return __method.apply(null, a);
257
339
  };
258
340
  }
259
- });
341
+
342
+ return {
343
+ argumentNames: argumentNames,
344
+ bind: bind,
345
+ bindAsEventListener: bindAsEventListener,
346
+ curry: curry,
347
+ delay: delay,
348
+ defer: defer,
349
+ wrap: wrap,
350
+ methodize: methodize
351
+ }
352
+ })());
353
+
260
354
 
261
355
  Date.prototype.toJSON = function() {
262
356
  return '"' + this.getUTCFullYear() + '-' +
@@ -267,30 +361,12 @@ Date.prototype.toJSON = function() {
267
361
  this.getUTCSeconds().toPaddedString(2) + 'Z"';
268
362
  };
269
363
 
270
- var Try = {
271
- these: function() {
272
- var returnValue;
273
-
274
- for (var i = 0, length = arguments.length; i < length; i++) {
275
- var lambda = arguments[i];
276
- try {
277
- returnValue = lambda();
278
- break;
279
- } catch (e) { }
280
- }
281
-
282
- return returnValue;
283
- }
284
- };
285
364
 
286
365
  RegExp.prototype.match = RegExp.prototype.test;
287
366
 
288
367
  RegExp.escape = function(str) {
289
368
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
290
369
  };
291
-
292
- /*--------------------------------------------------------------------------*/
293
-
294
370
  var PeriodicalExecuter = Class.create({
295
371
  initialize: function(callback, frequency) {
296
372
  this.callback = callback;
@@ -319,8 +395,10 @@ var PeriodicalExecuter = Class.create({
319
395
  try {
320
396
  this.currentlyExecuting = true;
321
397
  this.execute();
322
- } finally {
323
398
  this.currentlyExecuting = false;
399
+ } catch(e) {
400
+ this.currentlyExecuting = false;
401
+ throw e;
324
402
  }
325
403
  }
326
404
  }
@@ -339,10 +417,25 @@ Object.extend(String, {
339
417
  }
340
418
  });
341
419
 
342
- Object.extend(String.prototype, {
343
- gsub: function(pattern, replacement) {
420
+ Object.extend(String.prototype, (function() {
421
+
422
+ function prepareReplacement(replacement) {
423
+ if (Object.isFunction(replacement)) return replacement;
424
+ var template = new Template(replacement);
425
+ return function(match) { return template.evaluate(match) };
426
+ }
427
+
428
+ function gsub(pattern, replacement) {
344
429
  var result = '', source = this, match;
345
- replacement = arguments.callee.prepareReplacement(replacement);
430
+ replacement = prepareReplacement(replacement);
431
+
432
+ if (Object.isString(pattern))
433
+ pattern = RegExp.escape(pattern);
434
+
435
+ if (!(pattern.length || pattern.source)) {
436
+ replacement = replacement('');
437
+ return replacement + source.split('').join(replacement) + replacement;
438
+ }
346
439
 
347
440
  while (source.length > 0) {
348
441
  if (match = source.match(pattern)) {
@@ -354,69 +447,64 @@ Object.extend(String.prototype, {
354
447
  }
355
448
  }
356
449
  return result;
357
- },
450
+ }
358
451
 
359
- sub: function(pattern, replacement, count) {
360
- replacement = this.gsub.prepareReplacement(replacement);
452
+ function sub(pattern, replacement, count) {
453
+ replacement = prepareReplacement(replacement);
361
454
  count = Object.isUndefined(count) ? 1 : count;
362
455
 
363
456
  return this.gsub(pattern, function(match) {
364
457
  if (--count < 0) return match[0];
365
458
  return replacement(match);
366
459
  });
367
- },
460
+ }
368
461
 
369
- scan: function(pattern, iterator) {
462
+ function scan(pattern, iterator) {
370
463
  this.gsub(pattern, iterator);
371
464
  return String(this);
372
- },
465
+ }
373
466
 
374
- truncate: function(length, truncation) {
467
+ function truncate(length, truncation) {
375
468
  length = length || 30;
376
469
  truncation = Object.isUndefined(truncation) ? '...' : truncation;
377
470
  return this.length > length ?
378
471
  this.slice(0, length - truncation.length) + truncation : String(this);
379
- },
472
+ }
380
473
 
381
- strip: function() {
474
+ function strip() {
382
475
  return this.replace(/^\s+/, '').replace(/\s+$/, '');
383
- },
476
+ }
384
477
 
385
- stripTags: function() {
386
- return this.replace(/<\/?[^>]+>/gi, '');
387
- },
478
+ function stripTags() {
479
+ return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
480
+ }
388
481
 
389
- stripScripts: function() {
482
+ function stripScripts() {
390
483
  return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
391
- },
484
+ }
392
485
 
393
- extractScripts: function() {
486
+ function extractScripts() {
394
487
  var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
395
488
  var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
396
489
  return (this.match(matchAll) || []).map(function(scriptTag) {
397
490
  return (scriptTag.match(matchOne) || ['', ''])[1];
398
491
  });
399
- },
492
+ }
400
493
 
401
- evalScripts: function() {
494
+ function evalScripts() {
402
495
  return this.extractScripts().map(function(script) { return eval(script) });
403
- },
496
+ }
404
497
 
405
- escapeHTML: function() {
406
- var self = arguments.callee;
407
- self.text.data = this;
408
- return self.div.innerHTML;
409
- },
498
+ function escapeHTML() {
499
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
500
+ }
501
+
502
+ function unescapeHTML() {
503
+ return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
504
+ }
410
505
 
411
- unescapeHTML: function() {
412
- var div = new Element('div');
413
- div.innerHTML = this.stripTags();
414
- return div.childNodes[0] ? (div.childNodes.length > 1 ?
415
- $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
416
- div.childNodes[0].nodeValue) : '';
417
- },
418
506
 
419
- toQueryParams: function(separator) {
507
+ function toQueryParams(separator) {
420
508
  var match = this.strip().match(/([^?#]*)(#.*)?$/);
421
509
  if (!match) return { };
422
510
 
@@ -434,22 +522,22 @@ Object.extend(String.prototype, {
434
522
  }
435
523
  return hash;
436
524
  });
437
- },
525
+ }
438
526
 
439
- toArray: function() {
527
+ function toArray() {
440
528
  return this.split('');
441
- },
529
+ }
442
530
 
443
- succ: function() {
531
+ function succ() {
444
532
  return this.slice(0, this.length - 1) +
445
533
  String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
446
- },
534
+ }
447
535
 
448
- times: function(count) {
536
+ function times(count) {
449
537
  return count < 1 ? '' : new Array(count + 1).join(this);
450
- },
538
+ }
451
539
 
452
- camelize: function() {
540
+ function camelize() {
453
541
  var parts = this.split('-'), len = parts.length;
454
542
  if (len == 1) return parts[0];
455
543
 
@@ -461,101 +549,117 @@ Object.extend(String.prototype, {
461
549
  camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
462
550
 
463
551
  return camelized;
464
- },
552
+ }
465
553
 
466
- capitalize: function() {
554
+ function capitalize() {
467
555
  return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
468
- },
556
+ }
469
557
 
470
- underscore: function() {
471
- return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
472
- },
558
+ function underscore() {
559
+ return this.replace(/::/g, '/')
560
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
561
+ .replace(/([a-z\d])([A-Z])/g, '$1_$2')
562
+ .replace(/-/g, '_')
563
+ .toLowerCase();
564
+ }
473
565
 
474
- dasherize: function() {
475
- return this.gsub(/_/,'-');
476
- },
566
+ function dasherize() {
567
+ return this.replace(/_/g, '-');
568
+ }
477
569
 
478
- inspect: function(useDoubleQuotes) {
479
- var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
480
- var character = String.specialChar[match[0]];
481
- return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
570
+ function inspect(useDoubleQuotes) {
571
+ var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
572
+ if (character in String.specialChar) {
573
+ return String.specialChar[character];
574
+ }
575
+ return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
482
576
  });
483
577
  if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
484
578
  return "'" + escapedString.replace(/'/g, '\\\'') + "'";
485
- },
579
+ }
486
580
 
487
- toJSON: function() {
581
+ function toJSON() {
488
582
  return this.inspect(true);
489
- },
583
+ }
490
584
 
491
- unfilterJSON: function(filter) {
492
- return this.sub(filter || Prototype.JSONFilter, '#{1}');
493
- },
585
+ function unfilterJSON(filter) {
586
+ return this.replace(filter || Prototype.JSONFilter, '$1');
587
+ }
494
588
 
495
- isJSON: function() {
589
+ function isJSON() {
496
590
  var str = this;
497
591
  if (str.blank()) return false;
498
592
  str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
499
593
  return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
500
- },
594
+ }
501
595
 
502
- evalJSON: function(sanitize) {
596
+ function evalJSON(sanitize) {
503
597
  var json = this.unfilterJSON();
504
598
  try {
505
599
  if (!sanitize || json.isJSON()) return eval('(' + json + ')');
506
600
  } catch (e) { }
507
601
  throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
508
- },
602
+ }
509
603
 
510
- include: function(pattern) {
604
+ function include(pattern) {
511
605
  return this.indexOf(pattern) > -1;
512
- },
606
+ }
513
607
 
514
- startsWith: function(pattern) {
608
+ function startsWith(pattern) {
515
609
  return this.indexOf(pattern) === 0;
516
- },
610
+ }
517
611
 
518
- endsWith: function(pattern) {
612
+ function endsWith(pattern) {
519
613
  var d = this.length - pattern.length;
520
614
  return d >= 0 && this.lastIndexOf(pattern) === d;
521
- },
615
+ }
522
616
 
523
- empty: function() {
617
+ function empty() {
524
618
  return this == '';
525
- },
619
+ }
526
620
 
527
- blank: function() {
621
+ function blank() {
528
622
  return /^\s*$/.test(this);
529
- },
530
-
531
- interpolate: function(object, pattern) {
532
- return new Template(this, pattern).evaluate(object);
533
623
  }
534
- });
535
624
 
536
- if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
537
- escapeHTML: function() {
538
- return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
539
- },
540
- unescapeHTML: function() {
541
- return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
625
+ function interpolate(object, pattern) {
626
+ return new Template(this, pattern).evaluate(object);
542
627
  }
543
- });
544
628
 
545
- String.prototype.gsub.prepareReplacement = function(replacement) {
546
- if (Object.isFunction(replacement)) return replacement;
547
- var template = new Template(replacement);
548
- return function(match) { return template.evaluate(match) };
549
- };
550
-
551
- String.prototype.parseQuery = String.prototype.toQueryParams;
552
-
553
- Object.extend(String.prototype.escapeHTML, {
554
- div: document.createElement('div'),
555
- text: document.createTextNode('')
556
- });
557
-
558
- String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
629
+ return {
630
+ gsub: gsub,
631
+ sub: sub,
632
+ scan: scan,
633
+ truncate: truncate,
634
+ strip: String.prototype.trim ? String.prototype.trim : strip,
635
+ stripTags: stripTags,
636
+ stripScripts: stripScripts,
637
+ extractScripts: extractScripts,
638
+ evalScripts: evalScripts,
639
+ escapeHTML: escapeHTML,
640
+ unescapeHTML: unescapeHTML,
641
+ toQueryParams: toQueryParams,
642
+ parseQuery: toQueryParams,
643
+ toArray: toArray,
644
+ succ: succ,
645
+ times: times,
646
+ camelize: camelize,
647
+ capitalize: capitalize,
648
+ underscore: underscore,
649
+ dasherize: dasherize,
650
+ inspect: inspect,
651
+ toJSON: toJSON,
652
+ unfilterJSON: unfilterJSON,
653
+ isJSON: isJSON,
654
+ evalJSON: evalJSON,
655
+ include: include,
656
+ startsWith: startsWith,
657
+ endsWith: endsWith,
658
+ empty: empty,
659
+ blank: blank,
660
+ interpolate: interpolate
661
+ };
662
+ })());
559
663
 
560
664
  var Template = Class.create({
561
665
  initialize: function(template, pattern) {
@@ -564,11 +668,11 @@ var Template = Class.create({
564
668
  },
565
669
 
566
670
  evaluate: function(object) {
567
- if (Object.isFunction(object.toTemplateReplacements))
671
+ if (object && Object.isFunction(object.toTemplateReplacements))
568
672
  object = object.toTemplateReplacements();
569
673
 
570
674
  return this.template.gsub(this.pattern, function(match) {
571
- if (object == null) return '';
675
+ if (object == null) return (match[1] + '');
572
676
 
573
677
  var before = match[1] || '';
574
678
  if (before == '\\') return match[2];
@@ -579,7 +683,7 @@ var Template = Class.create({
579
683
  if (match == null) return before;
580
684
 
581
685
  while (match != null) {
582
- var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
686
+ var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
583
687
  ctx = ctx[comp];
584
688
  if (null == ctx || '' == match[3]) break;
585
689
  expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
@@ -594,8 +698,8 @@ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
594
698
 
595
699
  var $break = { };
596
700
 
597
- var Enumerable = {
598
- each: function(iterator, context) {
701
+ var Enumerable = (function() {
702
+ function each(iterator, context) {
599
703
  var index = 0;
600
704
  try {
601
705
  this._each(function(value) {
@@ -605,17 +709,17 @@ var Enumerable = {
605
709
  if (e != $break) throw e;
606
710
  }
607
711
  return this;
608
- },
712
+ }
609
713
 
610
- eachSlice: function(number, iterator, context) {
714
+ function eachSlice(number, iterator, context) {
611
715
  var index = -number, slices = [], array = this.toArray();
612
716
  if (number < 1) return array;
613
717
  while ((index += number) < array.length)
614
718
  slices.push(array.slice(index, index+number));
615
719
  return slices.collect(iterator, context);
616
- },
720
+ }
617
721
 
618
- all: function(iterator, context) {
722
+ function all(iterator, context) {
619
723
  iterator = iterator || Prototype.K;
620
724
  var result = true;
621
725
  this.each(function(value, index) {
@@ -623,9 +727,9 @@ var Enumerable = {
623
727
  if (!result) throw $break;
624
728
  });
625
729
  return result;
626
- },
730
+ }
627
731
 
628
- any: function(iterator, context) {
732
+ function any(iterator, context) {
629
733
  iterator = iterator || Prototype.K;
630
734
  var result = false;
631
735
  this.each(function(value, index) {
@@ -633,18 +737,18 @@ var Enumerable = {
633
737
  throw $break;
634
738
  });
635
739
  return result;
636
- },
740
+ }
637
741
 
638
- collect: function(iterator, context) {
742
+ function collect(iterator, context) {
639
743
  iterator = iterator || Prototype.K;
640
744
  var results = [];
641
745
  this.each(function(value, index) {
642
746
  results.push(iterator.call(context, value, index));
643
747
  });
644
748
  return results;
645
- },
749
+ }
646
750
 
647
- detect: function(iterator, context) {
751
+ function detect(iterator, context) {
648
752
  var result;
649
753
  this.each(function(value, index) {
650
754
  if (iterator.call(context, value, index)) {
@@ -653,32 +757,32 @@ var Enumerable = {
653
757
  }
654
758
  });
655
759
  return result;
656
- },
760
+ }
657
761
 
658
- findAll: function(iterator, context) {
762
+ function findAll(iterator, context) {
659
763
  var results = [];
660
764
  this.each(function(value, index) {
661
765
  if (iterator.call(context, value, index))
662
766
  results.push(value);
663
767
  });
664
768
  return results;
665
- },
769
+ }
666
770
 
667
- grep: function(filter, iterator, context) {
771
+ function grep(filter, iterator, context) {
668
772
  iterator = iterator || Prototype.K;
669
773
  var results = [];
670
774
 
671
775
  if (Object.isString(filter))
672
- filter = new RegExp(filter);
776
+ filter = new RegExp(RegExp.escape(filter));
673
777
 
674
778
  this.each(function(value, index) {
675
779
  if (filter.match(value))
676
780
  results.push(iterator.call(context, value, index));
677
781
  });
678
782
  return results;
679
- },
783
+ }
680
784
 
681
- include: function(object) {
785
+ function include(object) {
682
786
  if (Object.isFunction(this.indexOf))
683
787
  if (this.indexOf(object) != -1) return true;
684
788
 
@@ -690,31 +794,31 @@ var Enumerable = {
690
794
  }
691
795
  });
692
796
  return found;
693
- },
797
+ }
694
798
 
695
- inGroupsOf: function(number, fillWith) {
799
+ function inGroupsOf(number, fillWith) {
696
800
  fillWith = Object.isUndefined(fillWith) ? null : fillWith;
697
801
  return this.eachSlice(number, function(slice) {
698
802
  while(slice.length < number) slice.push(fillWith);
699
803
  return slice;
700
804
  });
701
- },
805
+ }
702
806
 
703
- inject: function(memo, iterator, context) {
807
+ function inject(memo, iterator, context) {
704
808
  this.each(function(value, index) {
705
809
  memo = iterator.call(context, memo, value, index);
706
810
  });
707
811
  return memo;
708
- },
812
+ }
709
813
 
710
- invoke: function(method) {
814
+ function invoke(method) {
711
815
  var args = $A(arguments).slice(1);
712
816
  return this.map(function(value) {
713
817
  return value[method].apply(value, args);
714
818
  });
715
- },
819
+ }
716
820
 
717
- max: function(iterator, context) {
821
+ function max(iterator, context) {
718
822
  iterator = iterator || Prototype.K;
719
823
  var result;
720
824
  this.each(function(value, index) {
@@ -723,9 +827,9 @@ var Enumerable = {
723
827
  result = value;
724
828
  });
725
829
  return result;
726
- },
830
+ }
727
831
 
728
- min: function(iterator, context) {
832
+ function min(iterator, context) {
729
833
  iterator = iterator || Prototype.K;
730
834
  var result;
731
835
  this.each(function(value, index) {
@@ -734,9 +838,9 @@ var Enumerable = {
734
838
  result = value;
735
839
  });
736
840
  return result;
737
- },
841
+ }
738
842
 
739
- partition: function(iterator, context) {
843
+ function partition(iterator, context) {
740
844
  iterator = iterator || Prototype.K;
741
845
  var trues = [], falses = [];
742
846
  this.each(function(value, index) {
@@ -744,26 +848,26 @@ var Enumerable = {
744
848
  trues : falses).push(value);
745
849
  });
746
850
  return [trues, falses];
747
- },
851
+ }
748
852
 
749
- pluck: function(property) {
853
+ function pluck(property) {
750
854
  var results = [];
751
855
  this.each(function(value) {
752
856
  results.push(value[property]);
753
857
  });
754
858
  return results;
755
- },
859
+ }
756
860
 
757
- reject: function(iterator, context) {
861
+ function reject(iterator, context) {
758
862
  var results = [];
759
863
  this.each(function(value, index) {
760
864
  if (!iterator.call(context, value, index))
761
865
  results.push(value);
762
866
  });
763
867
  return results;
764
- },
868
+ }
765
869
 
766
- sortBy: function(iterator, context) {
870
+ function sortBy(iterator, context) {
767
871
  return this.map(function(value, index) {
768
872
  return {
769
873
  value: value,
@@ -773,13 +877,13 @@ var Enumerable = {
773
877
  var a = left.criteria, b = right.criteria;
774
878
  return a < b ? -1 : a > b ? 1 : 0;
775
879
  }).pluck('value');
776
- },
880
+ }
777
881
 
778
- toArray: function() {
882
+ function toArray() {
779
883
  return this.map();
780
- },
884
+ }
781
885
 
782
- zip: function() {
886
+ function zip() {
783
887
  var iterator = Prototype.K, args = $A(arguments);
784
888
  if (Object.isFunction(args.last()))
785
889
  iterator = args.pop();
@@ -788,130 +892,152 @@ var Enumerable = {
788
892
  return this.map(function(value, index) {
789
893
  return iterator(collections.pluck(index));
790
894
  });
791
- },
895
+ }
792
896
 
793
- size: function() {
897
+ function size() {
794
898
  return this.toArray().length;
795
- },
899
+ }
796
900
 
797
- inspect: function() {
901
+ function inspect() {
798
902
  return '#<Enumerable:' + this.toArray().inspect() + '>';
799
903
  }
800
- };
801
904
 
802
- Object.extend(Enumerable, {
803
- map: Enumerable.collect,
804
- find: Enumerable.detect,
805
- select: Enumerable.findAll,
806
- filter: Enumerable.findAll,
807
- member: Enumerable.include,
808
- entries: Enumerable.toArray,
809
- every: Enumerable.all,
810
- some: Enumerable.any
811
- });
905
+
906
+
907
+
908
+
909
+
910
+
911
+
912
+
913
+ return {
914
+ each: each,
915
+ eachSlice: eachSlice,
916
+ all: all,
917
+ every: all,
918
+ any: any,
919
+ some: any,
920
+ collect: collect,
921
+ map: collect,
922
+ detect: detect,
923
+ findAll: findAll,
924
+ select: findAll,
925
+ filter: findAll,
926
+ grep: grep,
927
+ include: include,
928
+ member: include,
929
+ inGroupsOf: inGroupsOf,
930
+ inject: inject,
931
+ invoke: invoke,
932
+ max: max,
933
+ min: min,
934
+ partition: partition,
935
+ pluck: pluck,
936
+ reject: reject,
937
+ sortBy: sortBy,
938
+ toArray: toArray,
939
+ entries: toArray,
940
+ zip: zip,
941
+ size: size,
942
+ inspect: inspect,
943
+ find: detect
944
+ };
945
+ })();
812
946
  function $A(iterable) {
813
947
  if (!iterable) return [];
814
- if (iterable.toArray) return iterable.toArray();
948
+ if ('toArray' in Object(iterable)) return iterable.toArray();
815
949
  var length = iterable.length || 0, results = new Array(length);
816
950
  while (length--) results[length] = iterable[length];
817
951
  return results;
818
952
  }
819
953
 
820
- if (Prototype.Browser.WebKit) {
821
- $A = function(iterable) {
822
- if (!iterable) return [];
823
- // In Safari, only use the `toArray` method if it's not a NodeList.
824
- // A NodeList is a function, has an function `item` property, and a numeric
825
- // `length` property. Adapted from Google Doctype.
826
- if (!(typeof iterable === 'function' && typeof iterable.length ===
827
- 'number' && typeof iterable.item === 'function') && iterable.toArray)
828
- return iterable.toArray();
829
- var length = iterable.length || 0, results = new Array(length);
830
- while (length--) results[length] = iterable[length];
831
- return results;
832
- };
954
+ function $w(string) {
955
+ if (!Object.isString(string)) return [];
956
+ string = string.strip();
957
+ return string ? string.split(/\s+/) : [];
833
958
  }
834
959
 
835
960
  Array.from = $A;
836
961
 
837
- Object.extend(Array.prototype, Enumerable);
838
962
 
839
- if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
963
+ (function() {
964
+ var arrayProto = Array.prototype,
965
+ slice = arrayProto.slice,
966
+ _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
840
967
 
841
- Object.extend(Array.prototype, {
842
- _each: function(iterator) {
968
+ function each(iterator) {
843
969
  for (var i = 0, length = this.length; i < length; i++)
844
970
  iterator(this[i]);
845
- },
971
+ }
972
+ if (!_each) _each = each;
846
973
 
847
- clear: function() {
974
+ function clear() {
848
975
  this.length = 0;
849
976
  return this;
850
- },
977
+ }
851
978
 
852
- first: function() {
979
+ function first() {
853
980
  return this[0];
854
- },
981
+ }
855
982
 
856
- last: function() {
983
+ function last() {
857
984
  return this[this.length - 1];
858
- },
985
+ }
859
986
 
860
- compact: function() {
987
+ function compact() {
861
988
  return this.select(function(value) {
862
989
  return value != null;
863
990
  });
864
- },
991
+ }
865
992
 
866
- flatten: function() {
993
+ function flatten() {
867
994
  return this.inject([], function(array, value) {
868
- return array.concat(Object.isArray(value) ?
869
- value.flatten() : [value]);
995
+ if (Object.isArray(value))
996
+ return array.concat(value.flatten());
997
+ array.push(value);
998
+ return array;
870
999
  });
871
- },
1000
+ }
872
1001
 
873
- without: function() {
874
- var values = $A(arguments);
1002
+ function without() {
1003
+ var values = slice.call(arguments, 0);
875
1004
  return this.select(function(value) {
876
1005
  return !values.include(value);
877
1006
  });
878
- },
1007
+ }
879
1008
 
880
- reverse: function(inline) {
1009
+ function reverse(inline) {
881
1010
  return (inline !== false ? this : this.toArray())._reverse();
882
- },
883
-
884
- reduce: function() {
885
- return this.length > 1 ? this : this[0];
886
- },
1011
+ }
887
1012
 
888
- uniq: function(sorted) {
1013
+ function uniq(sorted) {
889
1014
  return this.inject([], function(array, value, index) {
890
1015
  if (0 == index || (sorted ? array.last() != value : !array.include(value)))
891
1016
  array.push(value);
892
1017
  return array;
893
1018
  });
894
- },
1019
+ }
895
1020
 
896
- intersect: function(array) {
1021
+ function intersect(array) {
897
1022
  return this.uniq().findAll(function(item) {
898
1023
  return array.detect(function(value) { return item === value });
899
1024
  });
900
- },
1025
+ }
901
1026
 
902
- clone: function() {
903
- return [].concat(this);
904
- },
905
1027
 
906
- size: function() {
1028
+ function clone() {
1029
+ return slice.call(this, 0);
1030
+ }
1031
+
1032
+ function size() {
907
1033
  return this.length;
908
- },
1034
+ }
909
1035
 
910
- inspect: function() {
1036
+ function inspect() {
911
1037
  return '[' + this.map(Object.inspect).join(', ') + ']';
912
- },
1038
+ }
913
1039
 
914
- toJSON: function() {
1040
+ function toJSON() {
915
1041
  var results = [];
916
1042
  this.each(function(object) {
917
1043
  var value = Object.toJSON(object);
@@ -919,205 +1045,270 @@ Object.extend(Array.prototype, {
919
1045
  });
920
1046
  return '[' + results.join(', ') + ']';
921
1047
  }
922
- });
923
-
924
- // use native browser JS 1.6 implementation if available
925
- if (Object.isFunction(Array.prototype.forEach))
926
- Array.prototype._each = Array.prototype.forEach;
927
-
928
- if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
929
- i || (i = 0);
930
- var length = this.length;
931
- if (i < 0) i = length + i;
932
- for (; i < length; i++)
933
- if (this[i] === item) return i;
934
- return -1;
935
- };
936
-
937
- if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
938
- i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
939
- var n = this.slice(0, i).reverse().indexOf(item);
940
- return (n < 0) ? n : i - n - 1;
941
- };
942
1048
 
943
- Array.prototype.toArray = Array.prototype.clone;
1049
+ function indexOf(item, i) {
1050
+ i || (i = 0);
1051
+ var length = this.length;
1052
+ if (i < 0) i = length + i;
1053
+ for (; i < length; i++)
1054
+ if (this[i] === item) return i;
1055
+ return -1;
1056
+ }
944
1057
 
945
- function $w(string) {
946
- if (!Object.isString(string)) return [];
947
- string = string.strip();
948
- return string ? string.split(/\s+/) : [];
949
- }
1058
+ function lastIndexOf(item, i) {
1059
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
1060
+ var n = this.slice(0, i).reverse().indexOf(item);
1061
+ return (n < 0) ? n : i - n - 1;
1062
+ }
950
1063
 
951
- if (Prototype.Browser.Opera){
952
- Array.prototype.concat = function() {
953
- var array = [];
954
- for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
1064
+ function concat() {
1065
+ var array = slice.call(this, 0), item;
955
1066
  for (var i = 0, length = arguments.length; i < length; i++) {
956
- if (Object.isArray(arguments[i])) {
957
- for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
958
- array.push(arguments[i][j]);
1067
+ item = arguments[i];
1068
+ if (Object.isArray(item) && !('callee' in item)) {
1069
+ for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
1070
+ array.push(item[j]);
959
1071
  } else {
960
- array.push(arguments[i]);
1072
+ array.push(item);
961
1073
  }
962
1074
  }
963
1075
  return array;
964
- };
965
- }
966
- Object.extend(Number.prototype, {
967
- toColorPart: function() {
968
- return this.toPaddedString(2, 16);
969
- },
970
-
971
- succ: function() {
972
- return this + 1;
973
- },
1076
+ }
974
1077
 
975
- times: function(iterator, context) {
976
- $R(0, this, true).each(iterator, context);
977
- return this;
978
- },
1078
+ Object.extend(arrayProto, Enumerable);
1079
+
1080
+ if (!arrayProto._reverse)
1081
+ arrayProto._reverse = arrayProto.reverse;
1082
+
1083
+ Object.extend(arrayProto, {
1084
+ _each: _each,
1085
+ clear: clear,
1086
+ first: first,
1087
+ last: last,
1088
+ compact: compact,
1089
+ flatten: flatten,
1090
+ without: without,
1091
+ reverse: reverse,
1092
+ uniq: uniq,
1093
+ intersect: intersect,
1094
+ clone: clone,
1095
+ toArray: clone,
1096
+ size: size,
1097
+ inspect: inspect,
1098
+ toJSON: toJSON
1099
+ });
979
1100
 
980
- toPaddedString: function(length, radix) {
981
- var string = this.toString(radix || 10);
982
- return '0'.times(length - string.length) + string;
983
- },
1101
+ var CONCAT_ARGUMENTS_BUGGY = (function() {
1102
+ return [].concat(arguments)[0][0] !== 1;
1103
+ })(1,2)
984
1104
 
985
- toJSON: function() {
986
- return isFinite(this) ? this.toString() : 'null';
987
- }
988
- });
1105
+ if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
989
1106
 
990
- $w('abs round ceil floor').each(function(method){
991
- Number.prototype[method] = Math[method].methodize();
992
- });
1107
+ if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
1108
+ if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
1109
+ })();
993
1110
  function $H(object) {
994
1111
  return new Hash(object);
995
1112
  };
996
1113
 
997
1114
  var Hash = Class.create(Enumerable, (function() {
1115
+ function initialize(object) {
1116
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1117
+ }
1118
+
1119
+ function _each(iterator) {
1120
+ for (var key in this._object) {
1121
+ var value = this._object[key], pair = [key, value];
1122
+ pair.key = key;
1123
+ pair.value = value;
1124
+ iterator(pair);
1125
+ }
1126
+ }
1127
+
1128
+ function set(key, value) {
1129
+ return this._object[key] = value;
1130
+ }
1131
+
1132
+ function get(key) {
1133
+ if (this._object[key] !== Object.prototype[key])
1134
+ return this._object[key];
1135
+ }
1136
+
1137
+ function unset(key) {
1138
+ var value = this._object[key];
1139
+ delete this._object[key];
1140
+ return value;
1141
+ }
1142
+
1143
+ function toObject() {
1144
+ return Object.clone(this._object);
1145
+ }
1146
+
1147
+ function keys() {
1148
+ return this.pluck('key');
1149
+ }
1150
+
1151
+ function values() {
1152
+ return this.pluck('value');
1153
+ }
1154
+
1155
+ function index(value) {
1156
+ var match = this.detect(function(pair) {
1157
+ return pair.value === value;
1158
+ });
1159
+ return match && match.key;
1160
+ }
1161
+
1162
+ function merge(object) {
1163
+ return this.clone().update(object);
1164
+ }
1165
+
1166
+ function update(object) {
1167
+ return new Hash(object).inject(this, function(result, pair) {
1168
+ result.set(pair.key, pair.value);
1169
+ return result;
1170
+ });
1171
+ }
998
1172
 
999
1173
  function toQueryPair(key, value) {
1000
1174
  if (Object.isUndefined(value)) return key;
1001
1175
  return key + '=' + encodeURIComponent(String.interpret(value));
1002
1176
  }
1003
1177
 
1004
- return {
1005
- initialize: function(object) {
1006
- this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1007
- },
1008
-
1009
- _each: function(iterator) {
1010
- for (var key in this._object) {
1011
- var value = this._object[key], pair = [key, value];
1012
- pair.key = key;
1013
- pair.value = value;
1014
- iterator(pair);
1015
- }
1016
- },
1178
+ function toQueryString() {
1179
+ return this.inject([], function(results, pair) {
1180
+ var key = encodeURIComponent(pair.key), values = pair.value;
1017
1181
 
1018
- set: function(key, value) {
1019
- return this._object[key] = value;
1020
- },
1182
+ if (values && typeof values == 'object') {
1183
+ if (Object.isArray(values))
1184
+ return results.concat(values.map(toQueryPair.curry(key)));
1185
+ } else results.push(toQueryPair(key, values));
1186
+ return results;
1187
+ }).join('&');
1188
+ }
1021
1189
 
1022
- get: function(key) {
1023
- // simulating poorly supported hasOwnProperty
1024
- if (this._object[key] !== Object.prototype[key])
1025
- return this._object[key];
1026
- },
1190
+ function inspect() {
1191
+ return '#<Hash:{' + this.map(function(pair) {
1192
+ return pair.map(Object.inspect).join(': ');
1193
+ }).join(', ') + '}>';
1194
+ }
1027
1195
 
1028
- unset: function(key) {
1029
- var value = this._object[key];
1030
- delete this._object[key];
1031
- return value;
1032
- },
1196
+ function toJSON() {
1197
+ return Object.toJSON(this.toObject());
1198
+ }
1033
1199
 
1034
- toObject: function() {
1035
- return Object.clone(this._object);
1036
- },
1200
+ function clone() {
1201
+ return new Hash(this);
1202
+ }
1037
1203
 
1038
- keys: function() {
1039
- return this.pluck('key');
1040
- },
1204
+ return {
1205
+ initialize: initialize,
1206
+ _each: _each,
1207
+ set: set,
1208
+ get: get,
1209
+ unset: unset,
1210
+ toObject: toObject,
1211
+ toTemplateReplacements: toObject,
1212
+ keys: keys,
1213
+ values: values,
1214
+ index: index,
1215
+ merge: merge,
1216
+ update: update,
1217
+ toQueryString: toQueryString,
1218
+ inspect: inspect,
1219
+ toJSON: toJSON,
1220
+ clone: clone
1221
+ };
1222
+ })());
1041
1223
 
1042
- values: function() {
1043
- return this.pluck('value');
1044
- },
1224
+ Hash.from = $H;
1225
+ Object.extend(Number.prototype, (function() {
1226
+ function toColorPart() {
1227
+ return this.toPaddedString(2, 16);
1228
+ }
1045
1229
 
1046
- index: function(value) {
1047
- var match = this.detect(function(pair) {
1048
- return pair.value === value;
1049
- });
1050
- return match && match.key;
1051
- },
1230
+ function succ() {
1231
+ return this + 1;
1232
+ }
1052
1233
 
1053
- merge: function(object) {
1054
- return this.clone().update(object);
1055
- },
1234
+ function times(iterator, context) {
1235
+ $R(0, this, true).each(iterator, context);
1236
+ return this;
1237
+ }
1056
1238
 
1057
- update: function(object) {
1058
- return new Hash(object).inject(this, function(result, pair) {
1059
- result.set(pair.key, pair.value);
1060
- return result;
1061
- });
1062
- },
1239
+ function toPaddedString(length, radix) {
1240
+ var string = this.toString(radix || 10);
1241
+ return '0'.times(length - string.length) + string;
1242
+ }
1063
1243
 
1064
- toQueryString: function() {
1065
- return this.inject([], function(results, pair) {
1066
- var key = encodeURIComponent(pair.key), values = pair.value;
1244
+ function toJSON() {
1245
+ return isFinite(this) ? this.toString() : 'null';
1246
+ }
1067
1247
 
1068
- if (values && typeof values == 'object') {
1069
- if (Object.isArray(values))
1070
- return results.concat(values.map(toQueryPair.curry(key)));
1071
- } else results.push(toQueryPair(key, values));
1072
- return results;
1073
- }).join('&');
1074
- },
1248
+ function abs() {
1249
+ return Math.abs(this);
1250
+ }
1075
1251
 
1076
- inspect: function() {
1077
- return '#<Hash:{' + this.map(function(pair) {
1078
- return pair.map(Object.inspect).join(': ');
1079
- }).join(', ') + '}>';
1080
- },
1252
+ function round() {
1253
+ return Math.round(this);
1254
+ }
1081
1255
 
1082
- toJSON: function() {
1083
- return Object.toJSON(this.toObject());
1084
- },
1256
+ function ceil() {
1257
+ return Math.ceil(this);
1258
+ }
1085
1259
 
1086
- clone: function() {
1087
- return new Hash(this);
1088
- }
1260
+ function floor() {
1261
+ return Math.floor(this);
1089
1262
  }
1263
+
1264
+ return {
1265
+ toColorPart: toColorPart,
1266
+ succ: succ,
1267
+ times: times,
1268
+ toPaddedString: toPaddedString,
1269
+ toJSON: toJSON,
1270
+ abs: abs,
1271
+ round: round,
1272
+ ceil: ceil,
1273
+ floor: floor
1274
+ };
1090
1275
  })());
1091
1276
 
1092
- Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
1093
- Hash.from = $H;
1094
- var ObjectRange = Class.create(Enumerable, {
1095
- initialize: function(start, end, exclusive) {
1277
+ function $R(start, end, exclusive) {
1278
+ return new ObjectRange(start, end, exclusive);
1279
+ }
1280
+
1281
+ var ObjectRange = Class.create(Enumerable, (function() {
1282
+ function initialize(start, end, exclusive) {
1096
1283
  this.start = start;
1097
1284
  this.end = end;
1098
1285
  this.exclusive = exclusive;
1099
- },
1286
+ }
1100
1287
 
1101
- _each: function(iterator) {
1288
+ function _each(iterator) {
1102
1289
  var value = this.start;
1103
1290
  while (this.include(value)) {
1104
1291
  iterator(value);
1105
1292
  value = value.succ();
1106
1293
  }
1107
- },
1294
+ }
1108
1295
 
1109
- include: function(value) {
1296
+ function include(value) {
1110
1297
  if (value < this.start)
1111
1298
  return false;
1112
1299
  if (this.exclusive)
1113
1300
  return value < this.end;
1114
1301
  return value <= this.end;
1115
1302
  }
1116
- });
1117
1303
 
1118
- var $R = function(start, end, exclusive) {
1119
- return new ObjectRange(start, end, exclusive);
1120
- };
1304
+ return {
1305
+ initialize: initialize,
1306
+ _each: _each,
1307
+ include: include
1308
+ };
1309
+ })());
1310
+
1311
+
1121
1312
 
1122
1313
  var Ajax = {
1123
1314
  getTransport: function() {
@@ -1164,7 +1355,6 @@ Ajax.Responders.register({
1164
1355
  onCreate: function() { Ajax.activeRequestCount++ },
1165
1356
  onComplete: function() { Ajax.activeRequestCount-- }
1166
1357
  });
1167
-
1168
1358
  Ajax.Base = Class.create({
1169
1359
  initialize: function(options) {
1170
1360
  this.options = {
@@ -1186,7 +1376,6 @@ Ajax.Base = Class.create({
1186
1376
  this.options.parameters = this.options.parameters.toObject();
1187
1377
  }
1188
1378
  });
1189
-
1190
1379
  Ajax.Request = Class.create(Ajax.Base, {
1191
1380
  _complete: false,
1192
1381
 
@@ -1202,7 +1391,6 @@ Ajax.Request = Class.create(Ajax.Base, {
1202
1391
  var params = Object.clone(this.options.parameters);
1203
1392
 
1204
1393
  if (!['get', 'post'].include(this.method)) {
1205
- // simulate other verbs over post
1206
1394
  params['_method'] = this.method;
1207
1395
  this.method = 'post';
1208
1396
  }
@@ -1210,7 +1398,6 @@ Ajax.Request = Class.create(Ajax.Base, {
1210
1398
  this.parameters = params;
1211
1399
 
1212
1400
  if (params = Object.toQueryString(params)) {
1213
- // when GET, append parameters to URL
1214
1401
  if (this.method == 'get')
1215
1402
  this.url += (this.url.include('?') ? '&' : '?') + params;
1216
1403
  else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
@@ -1269,7 +1456,6 @@ Ajax.Request = Class.create(Ajax.Base, {
1269
1456
  headers['Connection'] = 'close';
1270
1457
  }
1271
1458
 
1272
- // user-defined headers
1273
1459
  if (typeof this.options.requestHeaders == 'object') {
1274
1460
  var extras = this.options.requestHeaders;
1275
1461
 
@@ -1323,7 +1509,6 @@ Ajax.Request = Class.create(Ajax.Base, {
1323
1509
  }
1324
1510
 
1325
1511
  if (state == 'Complete') {
1326
- // avoid memory leak in MSIE: clean up
1327
1512
  this.transport.onreadystatechange = Prototype.emptyFunction;
1328
1513
  }
1329
1514
  },
@@ -1340,7 +1525,7 @@ Ajax.Request = Class.create(Ajax.Base, {
1340
1525
  getHeader: function(name) {
1341
1526
  try {
1342
1527
  return this.transport.getResponseHeader(name) || null;
1343
- } catch (e) { return null }
1528
+ } catch (e) { return null; }
1344
1529
  },
1345
1530
 
1346
1531
  evalResponse: function() {
@@ -1360,6 +1545,13 @@ Ajax.Request = Class.create(Ajax.Base, {
1360
1545
  Ajax.Request.Events =
1361
1546
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1362
1547
 
1548
+
1549
+
1550
+
1551
+
1552
+
1553
+
1554
+
1363
1555
  Ajax.Response = Class.create({
1364
1556
  initialize: function(request){
1365
1557
  this.request = request;
@@ -1381,6 +1573,7 @@ Ajax.Response = Class.create({
1381
1573
  },
1382
1574
 
1383
1575
  status: 0,
1576
+
1384
1577
  statusText: '',
1385
1578
 
1386
1579
  getStatus: Ajax.Request.prototype.getStatus,
@@ -1510,6 +1703,9 @@ Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1510
1703
  this.updater = new Ajax.Updater(this.container, this.url, this.options);
1511
1704
  }
1512
1705
  });
1706
+
1707
+
1708
+
1513
1709
  function $(element) {
1514
1710
  if (arguments.length > 1) {
1515
1711
  for (var i = 0, elements = [], length = arguments.length; i < length; i++)
@@ -1537,7 +1733,6 @@ if (Prototype.BrowserFeatures.XPath) {
1537
1733
  if (!window.Node) var Node = { };
1538
1734
 
1539
1735
  if (!Node.ELEMENT_NODE) {
1540
- // DOM level 2 ECMAScript Language Binding
1541
1736
  Object.extend(Node, {
1542
1737
  ELEMENT_NODE: 1,
1543
1738
  ATTRIBUTE_NODE: 2,
@@ -1554,13 +1749,30 @@ if (!Node.ELEMENT_NODE) {
1554
1749
  });
1555
1750
  }
1556
1751
 
1557
- (function() {
1558
- var element = this.Element;
1559
- this.Element = function(tagName, attributes) {
1752
+
1753
+ (function(global) {
1754
+
1755
+ var SETATTRIBUTE_IGNORES_NAME = (function(){
1756
+ var elForm = document.createElement("form");
1757
+ var elInput = document.createElement("input");
1758
+ var root = document.documentElement;
1759
+ elInput.setAttribute("name", "test");
1760
+ elForm.appendChild(elInput);
1761
+ root.appendChild(elForm);
1762
+ var isBuggy = elForm.elements
1763
+ ? (typeof elForm.elements.test == "undefined")
1764
+ : null;
1765
+ root.removeChild(elForm);
1766
+ elForm = elInput = null;
1767
+ return isBuggy;
1768
+ })();
1769
+
1770
+ var element = global.Element;
1771
+ global.Element = function(tagName, attributes) {
1560
1772
  attributes = attributes || { };
1561
1773
  tagName = tagName.toLowerCase();
1562
1774
  var cache = Element.cache;
1563
- if (Prototype.Browser.IE && attributes.name) {
1775
+ if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {
1564
1776
  tagName = '<' + tagName + ' name="' + attributes.name + '">';
1565
1777
  delete attributes.name;
1566
1778
  return Element.writeAttribute(document.createElement(tagName), attributes);
@@ -1568,11 +1780,12 @@ if (!Node.ELEMENT_NODE) {
1568
1780
  if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
1569
1781
  return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
1570
1782
  };
1571
- Object.extend(this.Element, element || { });
1572
- if (element) this.Element.prototype = element.prototype;
1573
- }).call(window);
1783
+ Object.extend(global.Element, element || { });
1784
+ if (element) global.Element.prototype = element.prototype;
1785
+ })(this);
1574
1786
 
1575
1787
  Element.cache = { };
1788
+ Element.idCounter = 1;
1576
1789
 
1577
1790
  Element.Methods = {
1578
1791
  visible: function(element) {
@@ -1585,6 +1798,7 @@ Element.Methods = {
1585
1798
  return element;
1586
1799
  },
1587
1800
 
1801
+
1588
1802
  hide: function(element) {
1589
1803
  element = $(element);
1590
1804
  element.style.display = 'none';
@@ -1603,15 +1817,89 @@ Element.Methods = {
1603
1817
  return element;
1604
1818
  },
1605
1819
 
1606
- update: function(element, content) {
1607
- element = $(element);
1608
- if (content && content.toElement) content = content.toElement();
1609
- if (Object.isElement(content)) return element.update().insert(content);
1610
- content = Object.toHTML(content);
1611
- element.innerHTML = content.stripScripts();
1612
- content.evalScripts.bind(content).defer();
1613
- return element;
1614
- },
1820
+ update: (function(){
1821
+
1822
+ var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
1823
+ var el = document.createElement("select"),
1824
+ isBuggy = true;
1825
+ el.innerHTML = "<option value=\"test\">test</option>";
1826
+ if (el.options && el.options[0]) {
1827
+ isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
1828
+ }
1829
+ el = null;
1830
+ return isBuggy;
1831
+ })();
1832
+
1833
+ var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
1834
+ try {
1835
+ var el = document.createElement("table");
1836
+ if (el && el.tBodies) {
1837
+ el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
1838
+ var isBuggy = typeof el.tBodies[0] == "undefined";
1839
+ el = null;
1840
+ return isBuggy;
1841
+ }
1842
+ } catch (e) {
1843
+ return true;
1844
+ }
1845
+ })();
1846
+
1847
+ var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
1848
+ var s = document.createElement("script"),
1849
+ isBuggy = false;
1850
+ try {
1851
+ s.appendChild(document.createTextNode(""));
1852
+ isBuggy = !s.firstChild ||
1853
+ s.firstChild && s.firstChild.nodeType !== 3;
1854
+ } catch (e) {
1855
+ isBuggy = true;
1856
+ }
1857
+ s = null;
1858
+ return isBuggy;
1859
+ })();
1860
+
1861
+ function update(element, content) {
1862
+ element = $(element);
1863
+
1864
+ if (content && content.toElement)
1865
+ content = content.toElement();
1866
+
1867
+ if (Object.isElement(content))
1868
+ return element.update().insert(content);
1869
+
1870
+ content = Object.toHTML(content);
1871
+
1872
+ var tagName = element.tagName.toUpperCase();
1873
+
1874
+ if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
1875
+ element.text = content;
1876
+ return element;
1877
+ }
1878
+
1879
+ if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
1880
+ if (tagName in Element._insertionTranslations.tags) {
1881
+ while (element.firstChild) {
1882
+ element.removeChild(element.firstChild);
1883
+ }
1884
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
1885
+ .each(function(node) {
1886
+ element.appendChild(node)
1887
+ });
1888
+ }
1889
+ else {
1890
+ element.innerHTML = content.stripScripts();
1891
+ }
1892
+ }
1893
+ else {
1894
+ element.innerHTML = content.stripScripts();
1895
+ }
1896
+
1897
+ content.evalScripts.bind(content).defer();
1898
+ return element;
1899
+ }
1900
+
1901
+ return update;
1902
+ })(),
1615
1903
 
1616
1904
  replace: function(element, content) {
1617
1905
  element = $(element);
@@ -1696,11 +1984,11 @@ Element.Methods = {
1696
1984
  },
1697
1985
 
1698
1986
  ancestors: function(element) {
1699
- return $(element).recursivelyCollect('parentNode');
1987
+ return Element.recursivelyCollect(element, 'parentNode');
1700
1988
  },
1701
1989
 
1702
1990
  descendants: function(element) {
1703
- return $(element).select("*");
1991
+ return Element.select(element, "*");
1704
1992
  },
1705
1993
 
1706
1994
  firstDescendant: function(element) {
@@ -1717,16 +2005,17 @@ Element.Methods = {
1717
2005
  },
1718
2006
 
1719
2007
  previousSiblings: function(element) {
1720
- return $(element).recursivelyCollect('previousSibling');
2008
+ return Element.recursivelyCollect(element, 'previousSibling');
1721
2009
  },
1722
2010
 
1723
2011
  nextSiblings: function(element) {
1724
- return $(element).recursivelyCollect('nextSibling');
2012
+ return Element.recursivelyCollect(element, 'nextSibling');
1725
2013
  },
1726
2014
 
1727
2015
  siblings: function(element) {
1728
2016
  element = $(element);
1729
- return element.previousSiblings().reverse().concat(element.nextSiblings());
2017
+ return Element.previousSiblings(element).reverse()
2018
+ .concat(Element.nextSiblings(element));
1730
2019
  },
1731
2020
 
1732
2021
  match: function(element, selector) {
@@ -1738,22 +2027,22 @@ Element.Methods = {
1738
2027
  up: function(element, expression, index) {
1739
2028
  element = $(element);
1740
2029
  if (arguments.length == 1) return $(element.parentNode);
1741
- var ancestors = element.ancestors();
2030
+ var ancestors = Element.ancestors(element);
1742
2031
  return Object.isNumber(expression) ? ancestors[expression] :
1743
2032
  Selector.findElement(ancestors, expression, index);
1744
2033
  },
1745
2034
 
1746
2035
  down: function(element, expression, index) {
1747
2036
  element = $(element);
1748
- if (arguments.length == 1) return element.firstDescendant();
1749
- return Object.isNumber(expression) ? element.descendants()[expression] :
2037
+ if (arguments.length == 1) return Element.firstDescendant(element);
2038
+ return Object.isNumber(expression) ? Element.descendants(element)[expression] :
1750
2039
  Element.select(element, expression)[index || 0];
1751
2040
  },
1752
2041
 
1753
2042
  previous: function(element, expression, index) {
1754
2043
  element = $(element);
1755
2044
  if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
1756
- var previousSiblings = element.previousSiblings();
2045
+ var previousSiblings = Element.previousSiblings(element);
1757
2046
  return Object.isNumber(expression) ? previousSiblings[expression] :
1758
2047
  Selector.findElement(previousSiblings, expression, index);
1759
2048
  },
@@ -1761,27 +2050,28 @@ Element.Methods = {
1761
2050
  next: function(element, expression, index) {
1762
2051
  element = $(element);
1763
2052
  if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
1764
- var nextSiblings = element.nextSiblings();
2053
+ var nextSiblings = Element.nextSiblings(element);
1765
2054
  return Object.isNumber(expression) ? nextSiblings[expression] :
1766
2055
  Selector.findElement(nextSiblings, expression, index);
1767
2056
  },
1768
2057
 
1769
- select: function() {
1770
- var args = $A(arguments), element = $(args.shift());
2058
+
2059
+ select: function(element) {
2060
+ var args = Array.prototype.slice.call(arguments, 1);
1771
2061
  return Selector.findChildElements(element, args);
1772
2062
  },
1773
2063
 
1774
- adjacent: function() {
1775
- var args = $A(arguments), element = $(args.shift());
2064
+ adjacent: function(element) {
2065
+ var args = Array.prototype.slice.call(arguments, 1);
1776
2066
  return Selector.findChildElements(element.parentNode, args).without(element);
1777
2067
  },
1778
2068
 
1779
2069
  identify: function(element) {
1780
2070
  element = $(element);
1781
- var id = element.readAttribute('id'), self = arguments.callee;
2071
+ var id = Element.readAttribute(element, 'id');
1782
2072
  if (id) return id;
1783
- do { id = 'anonymous_element_' + self.counter++ } while ($(id));
1784
- element.writeAttribute('id', id);
2073
+ do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
2074
+ Element.writeAttribute(element, 'id', id);
1785
2075
  return id;
1786
2076
  },
1787
2077
 
@@ -1820,11 +2110,11 @@ Element.Methods = {
1820
2110
  },
1821
2111
 
1822
2112
  getHeight: function(element) {
1823
- return $(element).getDimensions().height;
2113
+ return Element.getDimensions(element).height;
1824
2114
  },
1825
2115
 
1826
2116
  getWidth: function(element) {
1827
- return $(element).getDimensions().width;
2117
+ return Element.getDimensions(element).width;
1828
2118
  },
1829
2119
 
1830
2120
  classNames: function(element) {
@@ -1840,7 +2130,7 @@ Element.Methods = {
1840
2130
 
1841
2131
  addClassName: function(element, className) {
1842
2132
  if (!(element = $(element))) return;
1843
- if (!element.hasClassName(className))
2133
+ if (!Element.hasClassName(element, className))
1844
2134
  element.className += (element.className ? ' ' : '') + className;
1845
2135
  return element;
1846
2136
  },
@@ -1854,11 +2144,10 @@ Element.Methods = {
1854
2144
 
1855
2145
  toggleClassName: function(element, className) {
1856
2146
  if (!(element = $(element))) return;
1857
- return element[element.hasClassName(className) ?
1858
- 'removeClassName' : 'addClassName'](className);
2147
+ return Element[Element.hasClassName(element, className) ?
2148
+ 'removeClassName' : 'addClassName'](element, className);
1859
2149
  },
1860
2150
 
1861
- // removes whitespace-only text node children
1862
2151
  cleanWhitespace: function(element) {
1863
2152
  element = $(element);
1864
2153
  var node = element.firstChild;
@@ -1892,7 +2181,7 @@ Element.Methods = {
1892
2181
 
1893
2182
  scrollTo: function(element) {
1894
2183
  element = $(element);
1895
- var pos = element.cumulativeOffset();
2184
+ var pos = Element.cumulativeOffset(element);
1896
2185
  window.scrollTo(pos[0], pos[1]);
1897
2186
  return element;
1898
2187
  },
@@ -1940,18 +2229,17 @@ Element.Methods = {
1940
2229
 
1941
2230
  getDimensions: function(element) {
1942
2231
  element = $(element);
1943
- var display = element.getStyle('display');
2232
+ var display = Element.getStyle(element, 'display');
1944
2233
  if (display != 'none' && display != null) // Safari bug
1945
2234
  return {width: element.offsetWidth, height: element.offsetHeight};
1946
2235
 
1947
- // All *Width and *Height properties give 0 on elements with display none,
1948
- // so enable the element temporarily
1949
2236
  var els = element.style;
1950
2237
  var originalVisibility = els.visibility;
1951
2238
  var originalPosition = els.position;
1952
2239
  var originalDisplay = els.display;
1953
2240
  els.visibility = 'hidden';
1954
- els.position = 'absolute';
2241
+ if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
2242
+ els.position = 'absolute';
1955
2243
  els.display = 'block';
1956
2244
  var originalWidth = element.clientWidth;
1957
2245
  var originalHeight = element.clientHeight;
@@ -1967,8 +2255,6 @@ Element.Methods = {
1967
2255
  if (pos == 'static' || !pos) {
1968
2256
  element._madePositioned = true;
1969
2257
  element.style.position = 'relative';
1970
- // Opera returns the offset relative to the positioning context, when an
1971
- // element is position relative but top and left have not been defined
1972
2258
  if (Prototype.Browser.Opera) {
1973
2259
  element.style.top = 0;
1974
2260
  element.style.left = 0;
@@ -2034,10 +2320,9 @@ Element.Methods = {
2034
2320
 
2035
2321
  absolutize: function(element) {
2036
2322
  element = $(element);
2037
- if (element.getStyle('position') == 'absolute') return element;
2038
- // Position.prepare(); // To be done manually by Scripty when it needs it.
2323
+ if (Element.getStyle(element, 'position') == 'absolute') return element;
2039
2324
 
2040
- var offsets = element.positionedOffset();
2325
+ var offsets = Element.positionedOffset(element);
2041
2326
  var top = offsets[1];
2042
2327
  var left = offsets[0];
2043
2328
  var width = element.clientWidth;
@@ -2058,8 +2343,7 @@ Element.Methods = {
2058
2343
 
2059
2344
  relativize: function(element) {
2060
2345
  element = $(element);
2061
- if (element.getStyle('position') == 'relative') return element;
2062
- // Position.prepare(); // To be done manually by Scripty when it needs it.
2346
+ if (Element.getStyle(element, 'position') == 'relative') return element;
2063
2347
 
2064
2348
  element.style.position = 'relative';
2065
2349
  var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
@@ -2101,7 +2385,6 @@ Element.Methods = {
2101
2385
  valueT += element.offsetTop || 0;
2102
2386
  valueL += element.offsetLeft || 0;
2103
2387
 
2104
- // Safari fix
2105
2388
  if (element.offsetParent == document.body &&
2106
2389
  Element.getStyle(element, 'position') == 'absolute') break;
2107
2390
 
@@ -2128,28 +2411,22 @@ Element.Methods = {
2128
2411
  offsetLeft: 0
2129
2412
  }, arguments[2] || { });
2130
2413
 
2131
- // find page position of source
2132
2414
  source = $(source);
2133
- var p = source.viewportOffset();
2415
+ var p = Element.viewportOffset(source);
2134
2416
 
2135
- // find coordinate system to use
2136
2417
  element = $(element);
2137
2418
  var delta = [0, 0];
2138
2419
  var parent = null;
2139
- // delta [0,0] will do fine with position: fixed elements,
2140
- // position:absolute needs offsetParent deltas
2141
2420
  if (Element.getStyle(element, 'position') == 'absolute') {
2142
- parent = element.getOffsetParent();
2143
- delta = parent.viewportOffset();
2421
+ parent = Element.getOffsetParent(element);
2422
+ delta = Element.viewportOffset(parent);
2144
2423
  }
2145
2424
 
2146
- // correct by body offsets (fixes Safari)
2147
2425
  if (parent == document.body) {
2148
2426
  delta[0] -= document.body.offsetLeft;
2149
2427
  delta[1] -= document.body.offsetTop;
2150
2428
  }
2151
2429
 
2152
- // set position
2153
2430
  if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
2154
2431
  if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
2155
2432
  if (options.setWidth) element.style.width = source.offsetWidth + 'px';
@@ -2158,10 +2435,9 @@ Element.Methods = {
2158
2435
  }
2159
2436
  };
2160
2437
 
2161
- Element.Methods.identify.counter = 1;
2162
-
2163
2438
  Object.extend(Element.Methods, {
2164
2439
  getElementsBySelector: Element.Methods.select,
2440
+
2165
2441
  childElements: Element.Methods.immediateDescendants
2166
2442
  });
2167
2443
 
@@ -2182,11 +2458,8 @@ if (Prototype.Browser.Opera) {
2182
2458
  case 'left': case 'top': case 'right': case 'bottom':
2183
2459
  if (proceed(element, 'position') === 'static') return null;
2184
2460
  case 'height': case 'width':
2185
- // returns '0px' for hidden elements; we want it to return null
2186
2461
  if (!Element.visible(element)) return null;
2187
2462
 
2188
- // returns the border-box dimensions rather than the content-box
2189
- // dimensions, so we subtract padding and borders from the value
2190
2463
  var dim = parseInt(proceed(element, style), 10);
2191
2464
 
2192
2465
  if (dim !== element['offset' + style.capitalize()])
@@ -2219,12 +2492,9 @@ if (Prototype.Browser.Opera) {
2219
2492
  }
2220
2493
 
2221
2494
  else if (Prototype.Browser.IE) {
2222
- // IE doesn't report offsets correctly for static elements, so we change them
2223
- // to "relative" to get the values, then change them back.
2224
2495
  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
2225
2496
  function(proceed, element) {
2226
2497
  element = $(element);
2227
- // IE throws an error if element is not in document
2228
2498
  try { element.offsetParent }
2229
2499
  catch(e) { return $(document.body) }
2230
2500
  var position = element.getStyle('position');
@@ -2244,8 +2514,6 @@ else if (Prototype.Browser.IE) {
2244
2514
  catch(e) { return Element._returnOffset(0,0) }
2245
2515
  var position = element.getStyle('position');
2246
2516
  if (position !== 'static') return proceed(element);
2247
- // Trigger hasLayout on the offset parent so that IE6 reports
2248
- // accurate offsetTop and offsetLeft values for position: fixed.
2249
2517
  var offsetParent = element.getOffsetParent();
2250
2518
  if (offsetParent && offsetParent.getStyle('position') === 'fixed')
2251
2519
  offsetParent.setStyle({ zoom: 1 });
@@ -2306,36 +2574,92 @@ else if (Prototype.Browser.IE) {
2306
2574
  return element;
2307
2575
  };
2308
2576
 
2309
- Element._attributeTranslations = {
2310
- read: {
2311
- names: {
2312
- 'class': 'className',
2313
- 'for': 'htmlFor'
2314
- },
2315
- values: {
2316
- _getAttr: function(element, attribute) {
2317
- return element.getAttribute(attribute, 2);
2318
- },
2319
- _getAttrNode: function(element, attribute) {
2320
- var node = element.getAttributeNode(attribute);
2321
- return node ? node.value : "";
2322
- },
2323
- _getEv: function(element, attribute) {
2324
- attribute = element.getAttribute(attribute);
2325
- return attribute ? attribute.toString().slice(23, -2) : null;
2326
- },
2327
- _flag: function(element, attribute) {
2328
- return $(element).hasAttribute(attribute) ? attribute : null;
2329
- },
2330
- style: function(element) {
2331
- return element.style.cssText.toLowerCase();
2577
+ Element._attributeTranslations = (function(){
2578
+
2579
+ var classProp = 'className';
2580
+ var forProp = 'for';
2581
+
2582
+ var el = document.createElement('div');
2583
+
2584
+ el.setAttribute(classProp, 'x');
2585
+
2586
+ if (el.className !== 'x') {
2587
+ el.setAttribute('class', 'x');
2588
+ if (el.className === 'x') {
2589
+ classProp = 'class';
2590
+ }
2591
+ }
2592
+ el = null;
2593
+
2594
+ el = document.createElement('label');
2595
+ el.setAttribute(forProp, 'x');
2596
+ if (el.htmlFor !== 'x') {
2597
+ el.setAttribute('htmlFor', 'x');
2598
+ if (el.htmlFor === 'x') {
2599
+ forProp = 'htmlFor';
2600
+ }
2601
+ }
2602
+ el = null;
2603
+
2604
+ return {
2605
+ read: {
2606
+ names: {
2607
+ 'class': classProp,
2608
+ 'className': classProp,
2609
+ 'for': forProp,
2610
+ 'htmlFor': forProp
2332
2611
  },
2333
- title: function(element) {
2334
- return element.title;
2612
+ values: {
2613
+ _getAttr: function(element, attribute) {
2614
+ return element.getAttribute(attribute);
2615
+ },
2616
+ _getAttr2: function(element, attribute) {
2617
+ return element.getAttribute(attribute, 2);
2618
+ },
2619
+ _getAttrNode: function(element, attribute) {
2620
+ var node = element.getAttributeNode(attribute);
2621
+ return node ? node.value : "";
2622
+ },
2623
+ _getEv: (function(){
2624
+
2625
+ var el = document.createElement('div');
2626
+ el.onclick = Prototype.emptyFunction;
2627
+ var value = el.getAttribute('onclick');
2628
+ var f;
2629
+
2630
+ if (String(value).indexOf('{') > -1) {
2631
+ f = function(element, attribute) {
2632
+ attribute = element.getAttribute(attribute);
2633
+ if (!attribute) return null;
2634
+ attribute = attribute.toString();
2635
+ attribute = attribute.split('{')[1];
2636
+ attribute = attribute.split('}')[0];
2637
+ return attribute.strip();
2638
+ };
2639
+ }
2640
+ else if (value === '') {
2641
+ f = function(element, attribute) {
2642
+ attribute = element.getAttribute(attribute);
2643
+ if (!attribute) return null;
2644
+ return attribute.strip();
2645
+ };
2646
+ }
2647
+ el = null;
2648
+ return f;
2649
+ })(),
2650
+ _flag: function(element, attribute) {
2651
+ return $(element).hasAttribute(attribute) ? attribute : null;
2652
+ },
2653
+ style: function(element) {
2654
+ return element.style.cssText.toLowerCase();
2655
+ },
2656
+ title: function(element) {
2657
+ return element.title;
2658
+ }
2335
2659
  }
2336
2660
  }
2337
2661
  }
2338
- };
2662
+ })();
2339
2663
 
2340
2664
  Element._attributeTranslations.write = {
2341
2665
  names: Object.extend({
@@ -2363,8 +2687,8 @@ else if (Prototype.Browser.IE) {
2363
2687
 
2364
2688
  (function(v) {
2365
2689
  Object.extend(v, {
2366
- href: v._getAttr,
2367
- src: v._getAttr,
2690
+ href: v._getAttr2,
2691
+ src: v._getAttr2,
2368
2692
  type: v._getAttr,
2369
2693
  action: v._getAttrNode,
2370
2694
  disabled: v._flag,
@@ -2391,6 +2715,26 @@ else if (Prototype.Browser.IE) {
2391
2715
  onchange: v._getEv
2392
2716
  });
2393
2717
  })(Element._attributeTranslations.read.values);
2718
+
2719
+ if (Prototype.BrowserFeatures.ElementExtensions) {
2720
+ (function() {
2721
+ function _descendants(element) {
2722
+ var nodes = element.getElementsByTagName('*'), results = [];
2723
+ for (var i = 0, node; node = nodes[i]; i++)
2724
+ if (node.tagName !== "!") // Filter out comment nodes.
2725
+ results.push(node);
2726
+ return results;
2727
+ }
2728
+
2729
+ Element.Methods.down = function(element, expression, index) {
2730
+ element = $(element);
2731
+ if (arguments.length == 1) return element.firstDescendant();
2732
+ return Object.isNumber(expression) ? _descendants(element)[expression] :
2733
+ Element.select(element, expression)[index || 0];
2734
+ }
2735
+ })();
2736
+ }
2737
+
2394
2738
  }
2395
2739
 
2396
2740
  else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
@@ -2420,9 +2764,6 @@ else if (Prototype.Browser.WebKit) {
2420
2764
  return element;
2421
2765
  };
2422
2766
 
2423
- // Safari returns margins on body which is incorrect if the child is absolutely
2424
- // positioned. For performance reasons, redefine Element#cumulativeOffset for
2425
- // KHTML/WebKit only.
2426
2767
  Element.Methods.cumulativeOffset = function(element) {
2427
2768
  var valueT = 0, valueL = 0;
2428
2769
  do {
@@ -2438,30 +2779,7 @@ else if (Prototype.Browser.WebKit) {
2438
2779
  };
2439
2780
  }
2440
2781
 
2441
- if (Prototype.Browser.IE || Prototype.Browser.Opera) {
2442
- // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
2443
- Element.Methods.update = function(element, content) {
2444
- element = $(element);
2445
-
2446
- if (content && content.toElement) content = content.toElement();
2447
- if (Object.isElement(content)) return element.update().insert(content);
2448
-
2449
- content = Object.toHTML(content);
2450
- var tagName = element.tagName.toUpperCase();
2451
-
2452
- if (tagName in Element._insertionTranslations.tags) {
2453
- $A(element.childNodes).each(function(node) { element.removeChild(node) });
2454
- Element._getContentFromAnonymousElement(tagName, content.stripScripts())
2455
- .each(function(node) { element.appendChild(node) });
2456
- }
2457
- else element.innerHTML = content.stripScripts();
2458
-
2459
- content.evalScripts.bind(content).defer();
2460
- return element;
2461
- };
2462
- }
2463
-
2464
- if ('outerHTML' in document.createElement('div')) {
2782
+ if ('outerHTML' in document.documentElement) {
2465
2783
  Element.Methods.replace = function(element, content) {
2466
2784
  element = $(element);
2467
2785
 
@@ -2529,12 +2847,13 @@ Element._insertionTranslations = {
2529
2847
  };
2530
2848
 
2531
2849
  (function() {
2532
- Object.extend(this.tags, {
2533
- THEAD: this.tags.TBODY,
2534
- TFOOT: this.tags.TBODY,
2535
- TH: this.tags.TD
2850
+ var tags = Element._insertionTranslations.tags;
2851
+ Object.extend(tags, {
2852
+ THEAD: tags.TBODY,
2853
+ TFOOT: tags.TBODY,
2854
+ TH: tags.TD
2536
2855
  });
2537
- }).call(Element._insertionTranslations);
2856
+ })();
2538
2857
 
2539
2858
  Element.Methods.Simulated = {
2540
2859
  hasAttribute: function(element, attribute) {
@@ -2548,41 +2867,81 @@ Element.Methods.ByTag = { };
2548
2867
 
2549
2868
  Object.extend(Element, Element.Methods);
2550
2869
 
2551
- if (!Prototype.BrowserFeatures.ElementExtensions &&
2552
- document.createElement('div')['__proto__']) {
2553
- window.HTMLElement = { };
2554
- window.HTMLElement.prototype = document.createElement('div')['__proto__'];
2555
- Prototype.BrowserFeatures.ElementExtensions = true;
2556
- }
2870
+ (function(div) {
2871
+
2872
+ if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
2873
+ window.HTMLElement = { };
2874
+ window.HTMLElement.prototype = div['__proto__'];
2875
+ Prototype.BrowserFeatures.ElementExtensions = true;
2876
+ }
2877
+
2878
+ div = null;
2879
+
2880
+ })(document.createElement('div'))
2557
2881
 
2558
2882
  Element.extend = (function() {
2559
- if (Prototype.BrowserFeatures.SpecificElementExtensions)
2883
+
2884
+ function checkDeficiency(tagName) {
2885
+ if (typeof window.Element != 'undefined') {
2886
+ var proto = window.Element.prototype;
2887
+ if (proto) {
2888
+ var id = '_' + (Math.random()+'').slice(2);
2889
+ var el = document.createElement(tagName);
2890
+ proto[id] = 'x';
2891
+ var isBuggy = (el[id] !== 'x');
2892
+ delete proto[id];
2893
+ el = null;
2894
+ return isBuggy;
2895
+ }
2896
+ }
2897
+ return false;
2898
+ }
2899
+
2900
+ function extendElementWith(element, methods) {
2901
+ for (var property in methods) {
2902
+ var value = methods[property];
2903
+ if (Object.isFunction(value) && !(property in element))
2904
+ element[property] = value.methodize();
2905
+ }
2906
+ }
2907
+
2908
+ var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
2909
+
2910
+ if (Prototype.BrowserFeatures.SpecificElementExtensions) {
2911
+ if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
2912
+ return function(element) {
2913
+ if (element && typeof element._extendedByPrototype == 'undefined') {
2914
+ var t = element.tagName;
2915
+ if (t && (/^(?:object|applet|embed)$/i.test(t))) {
2916
+ extendElementWith(element, Element.Methods);
2917
+ extendElementWith(element, Element.Methods.Simulated);
2918
+ extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
2919
+ }
2920
+ }
2921
+ return element;
2922
+ }
2923
+ }
2560
2924
  return Prototype.K;
2925
+ }
2561
2926
 
2562
2927
  var Methods = { }, ByTag = Element.Methods.ByTag;
2563
2928
 
2564
2929
  var extend = Object.extend(function(element) {
2565
- if (!element || element._extendedByPrototype ||
2930
+ if (!element || typeof element._extendedByPrototype != 'undefined' ||
2566
2931
  element.nodeType != 1 || element == window) return element;
2567
2932
 
2568
2933
  var methods = Object.clone(Methods),
2569
- tagName = element.tagName.toUpperCase(), property, value;
2934
+ tagName = element.tagName.toUpperCase();
2570
2935
 
2571
- // extend methods for specific tags
2572
2936
  if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
2573
2937
 
2574
- for (property in methods) {
2575
- value = methods[property];
2576
- if (Object.isFunction(value) && !(property in element))
2577
- element[property] = value.methodize();
2578
- }
2938
+ extendElementWith(element, methods);
2579
2939
 
2580
2940
  element._extendedByPrototype = Prototype.emptyFunction;
2581
2941
  return element;
2582
2942
 
2583
2943
  }, {
2584
2944
  refresh: function() {
2585
- // extend methods for all tags (Safari doesn't need this)
2586
2945
  if (!Prototype.BrowserFeatures.ElementExtensions) {
2587
2946
  Object.extend(Methods, Element.Methods);
2588
2947
  Object.extend(Methods, Element.Methods.Simulated);
@@ -2661,14 +3020,18 @@ Element.addMethods = function(methods) {
2661
3020
  klass = 'HTML' + tagName.capitalize() + 'Element';
2662
3021
  if (window[klass]) return window[klass];
2663
3022
 
2664
- window[klass] = { };
2665
- window[klass].prototype = document.createElement(tagName)['__proto__'];
2666
- return window[klass];
3023
+ var element = document.createElement(tagName);
3024
+ var proto = element['__proto__'] || element.constructor.prototype;
3025
+ element = null;
3026
+ return proto;
2667
3027
  }
2668
3028
 
3029
+ var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
3030
+ Element.prototype;
3031
+
2669
3032
  if (F.ElementExtensions) {
2670
- copy(Element.Methods, HTMLElement.prototype);
2671
- copy(Element.Methods.Simulated, HTMLElement.prototype, true);
3033
+ copy(Element.Methods, elementPrototype);
3034
+ copy(Element.Methods.Simulated, elementPrototype, true);
2672
3035
  }
2673
3036
 
2674
3037
  if (F.SpecificElementExtensions) {
@@ -2686,38 +3049,109 @@ Element.addMethods = function(methods) {
2686
3049
  Element.cache = { };
2687
3050
  };
2688
3051
 
2689
- document.viewport = {
2690
- getDimensions: function() {
2691
- var dimensions = { }, B = Prototype.Browser;
2692
- $w('width height').each(function(d) {
2693
- var D = d.capitalize();
2694
- if (B.WebKit && !document.evaluate) {
2695
- // Safari <3.0 needs self.innerWidth/Height
2696
- dimensions[d] = self['inner' + D];
2697
- } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
2698
- // Opera <9.5 needs document.body.clientWidth/Height
2699
- dimensions[d] = document.body['client' + D]
2700
- } else {
2701
- dimensions[d] = document.documentElement['client' + D];
2702
- }
2703
- });
2704
- return dimensions;
2705
- },
2706
3052
 
2707
- getWidth: function() {
2708
- return this.getDimensions().width;
2709
- },
3053
+ document.viewport = {
2710
3054
 
2711
- getHeight: function() {
2712
- return this.getDimensions().height;
3055
+ getDimensions: function() {
3056
+ return { width: this.getWidth(), height: this.getHeight() };
2713
3057
  },
2714
3058
 
2715
3059
  getScrollOffsets: function() {
2716
3060
  return Element._returnOffset(
2717
3061
  window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
2718
- window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
3062
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
2719
3063
  }
2720
3064
  };
3065
+
3066
+ (function(viewport) {
3067
+ var B = Prototype.Browser, doc = document, element, property = {};
3068
+
3069
+ function getRootElement() {
3070
+ if (B.WebKit && !doc.evaluate)
3071
+ return document;
3072
+
3073
+ if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
3074
+ return document.body;
3075
+
3076
+ return document.documentElement;
3077
+ }
3078
+
3079
+ function define(D) {
3080
+ if (!element) element = getRootElement();
3081
+
3082
+ property[D] = 'client' + D;
3083
+
3084
+ viewport['get' + D] = function() { return element[property[D]] };
3085
+ return viewport['get' + D]();
3086
+ }
3087
+
3088
+ viewport.getWidth = define.curry('Width');
3089
+
3090
+ viewport.getHeight = define.curry('Height');
3091
+ })(document.viewport);
3092
+
3093
+
3094
+ Element.Storage = {
3095
+ UID: 1
3096
+ };
3097
+
3098
+ Element.addMethods({
3099
+ getStorage: function(element) {
3100
+ if (!(element = $(element))) return;
3101
+
3102
+ var uid;
3103
+ if (element === window) {
3104
+ uid = 0;
3105
+ } else {
3106
+ if (typeof element._prototypeUID === "undefined")
3107
+ element._prototypeUID = [Element.Storage.UID++];
3108
+ uid = element._prototypeUID[0];
3109
+ }
3110
+
3111
+ if (!Element.Storage[uid])
3112
+ Element.Storage[uid] = $H();
3113
+
3114
+ return Element.Storage[uid];
3115
+ },
3116
+
3117
+ store: function(element, key, value) {
3118
+ if (!(element = $(element))) return;
3119
+
3120
+ if (arguments.length === 2) {
3121
+ Element.getStorage(element).update(key);
3122
+ } else {
3123
+ Element.getStorage(element).set(key, value);
3124
+ }
3125
+
3126
+ return element;
3127
+ },
3128
+
3129
+ retrieve: function(element, key, defaultValue) {
3130
+ if (!(element = $(element))) return;
3131
+ var hash = Element.getStorage(element), value = hash.get(key);
3132
+
3133
+ if (Object.isUndefined(value)) {
3134
+ hash.set(key, defaultValue);
3135
+ value = defaultValue;
3136
+ }
3137
+
3138
+ return value;
3139
+ },
3140
+
3141
+ clone: function(element, deep) {
3142
+ if (!(element = $(element))) return;
3143
+ var clone = element.cloneNode(deep);
3144
+ clone._prototypeUID = void 0;
3145
+ if (deep) {
3146
+ var descendants = Element.select(clone, '*'),
3147
+ i = descendants.length;
3148
+ while (i--) {
3149
+ descendants[i]._prototypeUID = void 0;
3150
+ }
3151
+ }
3152
+ return Element.extend(clone);
3153
+ }
3154
+ });
2721
3155
  /* Portions of the Selector class are derived from Jack Slocum's DomQuery,
2722
3156
  * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
2723
3157
  * license. Please see http://www.yui-ext.com/ for more information. */
@@ -2738,31 +3172,52 @@ var Selector = Class.create({
2738
3172
 
2739
3173
  },
2740
3174
 
2741
- shouldUseXPath: function() {
2742
- if (!Prototype.BrowserFeatures.XPath) return false;
3175
+ shouldUseXPath: (function() {
2743
3176
 
2744
- var e = this.expression;
3177
+ var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
3178
+ var isBuggy = false;
3179
+ if (document.evaluate && window.XPathResult) {
3180
+ var el = document.createElement('div');
3181
+ el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';
2745
3182
 
2746
- // Safari 3 chokes on :*-of-type and :empty
2747
- if (Prototype.Browser.WebKit &&
2748
- (e.include("-of-type") || e.include(":empty")))
2749
- return false;
3183
+ var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
3184
+ "//*[local-name()='li' or local-name()='LI']";
2750
3185
 
2751
- // XPath can't do namespaced attributes, nor can it read
2752
- // the "checked" property from DOM nodes
2753
- if ((/(\[[\w-]*?:|:checked)/).test(e))
2754
- return false;
3186
+ var result = document.evaluate(xpath, el, null,
3187
+ XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
2755
3188
 
2756
- return true;
2757
- },
3189
+ isBuggy = (result.snapshotLength !== 2);
3190
+ el = null;
3191
+ }
3192
+ return isBuggy;
3193
+ })();
3194
+
3195
+ return function() {
3196
+ if (!Prototype.BrowserFeatures.XPath) return false;
3197
+
3198
+ var e = this.expression;
3199
+
3200
+ if (Prototype.Browser.WebKit &&
3201
+ (e.include("-of-type") || e.include(":empty")))
3202
+ return false;
3203
+
3204
+ if ((/(\[[\w-]*?:|:checked)/).test(e))
3205
+ return false;
3206
+
3207
+ if (IS_DESCENDANT_SELECTOR_BUGGY) return false;
3208
+
3209
+ return true;
3210
+ }
3211
+
3212
+ })(),
2758
3213
 
2759
3214
  shouldUseSelectorsAPI: function() {
2760
3215
  if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
2761
3216
 
3217
+ if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;
3218
+
2762
3219
  if (!Selector._div) Selector._div = new Element('div');
2763
3220
 
2764
- // Make sure the browser treats the selector as valid. Test on an
2765
- // isolated element to minimize cost of this check.
2766
3221
  try {
2767
3222
  Selector._div.querySelector(this.expression);
2768
3223
  } catch(e) {
@@ -2774,7 +3229,7 @@ var Selector = Class.create({
2774
3229
 
2775
3230
  compileMatcher: function() {
2776
3231
  var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
2777
- c = Selector.criteria, le, p, m;
3232
+ c = Selector.criteria, le, p, m, len = ps.length, name;
2778
3233
 
2779
3234
  if (Selector._cache[e]) {
2780
3235
  this.matcher = Selector._cache[e];
@@ -2786,11 +3241,12 @@ var Selector = Class.create({
2786
3241
 
2787
3242
  while (e && le != e && (/\S/).test(e)) {
2788
3243
  le = e;
2789
- for (var i in ps) {
2790
- p = ps[i];
3244
+ for (var i = 0; i<len; i++) {
3245
+ p = ps[i].re;
3246
+ name = ps[i].name;
2791
3247
  if (m = e.match(p)) {
2792
- this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
2793
- new Template(c[i]).evaluate(m));
3248
+ this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :
3249
+ new Template(c[name]).evaluate(m));
2794
3250
  e = e.replace(m[0], '');
2795
3251
  break;
2796
3252
  }
@@ -2804,7 +3260,7 @@ var Selector = Class.create({
2804
3260
 
2805
3261
  compileXPathMatcher: function() {
2806
3262
  var e = this.expression, ps = Selector.patterns,
2807
- x = Selector.xpath, le, m;
3263
+ x = Selector.xpath, le, m, len = ps.length, name;
2808
3264
 
2809
3265
  if (Selector._cache[e]) {
2810
3266
  this.xpath = Selector._cache[e]; return;
@@ -2813,10 +3269,11 @@ var Selector = Class.create({
2813
3269
  this.matcher = ['.//*'];
2814
3270
  while (e && le != e && (/\S/).test(e)) {
2815
3271
  le = e;
2816
- for (var i in ps) {
2817
- if (m = e.match(ps[i])) {
2818
- this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
2819
- new Template(x[i]).evaluate(m));
3272
+ for (var i = 0; i<len; i++) {
3273
+ name = ps[i].name;
3274
+ if (m = e.match(ps[i].re)) {
3275
+ this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :
3276
+ new Template(x[name]).evaluate(m));
2820
3277
  e = e.replace(m[0], '');
2821
3278
  break;
2822
3279
  }
@@ -2833,11 +3290,9 @@ var Selector = Class.create({
2833
3290
 
2834
3291
  switch (this.mode) {
2835
3292
  case 'selectorsAPI':
2836
- // querySelectorAll queries document-wide, then filters to descendants
2837
- // of the context element. That's not what we want.
2838
- // Add an explicit context to the selector if necessary.
2839
3293
  if (root !== document) {
2840
3294
  var oldId = root.id, id = $(root).identify();
3295
+ id = id.replace(/([\.:])/g, "\\$1");
2841
3296
  e = "#" + id + " " + e;
2842
3297
  }
2843
3298
 
@@ -2856,21 +3311,18 @@ var Selector = Class.create({
2856
3311
  this.tokens = [];
2857
3312
 
2858
3313
  var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
2859
- var le, p, m;
3314
+ var le, p, m, len = ps.length, name;
2860
3315
 
2861
3316
  while (e && le !== e && (/\S/).test(e)) {
2862
3317
  le = e;
2863
- for (var i in ps) {
2864
- p = ps[i];
3318
+ for (var i = 0; i<len; i++) {
3319
+ p = ps[i].re;
3320
+ name = ps[i].name;
2865
3321
  if (m = e.match(p)) {
2866
- // use the Selector.assertions methods unless the selector
2867
- // is too complex.
2868
- if (as[i]) {
2869
- this.tokens.push([i, Object.clone(m)]);
3322
+ if (as[name]) {
3323
+ this.tokens.push([name, Object.clone(m)]);
2870
3324
  e = e.replace(m[0], '');
2871
3325
  } else {
2872
- // reluctantly do a document-wide search
2873
- // and look for a match in the array
2874
3326
  return this.findElements(document).include(element);
2875
3327
  }
2876
3328
  }
@@ -2897,6 +3349,21 @@ var Selector = Class.create({
2897
3349
  }
2898
3350
  });
2899
3351
 
3352
+ if (Prototype.BrowserFeatures.SelectorsAPI &&
3353
+ document.compatMode === 'BackCompat') {
3354
+ Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){
3355
+ var div = document.createElement('div'),
3356
+ span = document.createElement('span');
3357
+
3358
+ div.id = "prototype_test_id";
3359
+ span.className = 'Test';
3360
+ div.appendChild(span);
3361
+ var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);
3362
+ div = span = null;
3363
+ return isIgnored;
3364
+ })();
3365
+ }
3366
+
2900
3367
  Object.extend(Selector, {
2901
3368
  _cache: { },
2902
3369
 
@@ -2946,14 +3413,15 @@ Object.extend(Selector, {
2946
3413
  'enabled': "[not(@disabled) and (@type!='hidden')]",
2947
3414
  'not': function(m) {
2948
3415
  var e = m[6], p = Selector.patterns,
2949
- x = Selector.xpath, le, v;
3416
+ x = Selector.xpath, le, v, len = p.length, name;
2950
3417
 
2951
3418
  var exclusion = [];
2952
3419
  while (e && le != e && (/\S/).test(e)) {
2953
3420
  le = e;
2954
- for (var i in p) {
2955
- if (m = e.match(p[i])) {
2956
- v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
3421
+ for (var i = 0; i<len; i++) {
3422
+ name = p[i].name
3423
+ if (m = e.match(p[i].re)) {
3424
+ v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m);
2957
3425
  exclusion.push("(" + v.substring(1, v.length - 1) + ")");
2958
3426
  e = e.replace(m[0], '');
2959
3427
  break;
@@ -3021,25 +3489,20 @@ Object.extend(Selector, {
3021
3489
  laterSibling: 'c = "laterSibling";'
3022
3490
  },
3023
3491
 
3024
- patterns: {
3025
- // combinators must be listed first
3026
- // (and descendant needs to be last combinator)
3027
- laterSibling: /^\s*~\s*/,
3028
- child: /^\s*>\s*/,
3029
- adjacent: /^\s*\+\s*/,
3030
- descendant: /^\s/,
3492
+ patterns: [
3493
+ { name: 'laterSibling', re: /^\s*~\s*/ },
3494
+ { name: 'child', re: /^\s*>\s*/ },
3495
+ { name: 'adjacent', re: /^\s*\+\s*/ },
3496
+ { name: 'descendant', re: /^\s/ },
3031
3497
 
3032
- // selectors follow
3033
- tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
3034
- id: /^#([\w\-\*]+)(\b|$)/,
3035
- className: /^\.([\w\-\*]+)(\b|$)/,
3036
- pseudo:
3037
- /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
3038
- attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
3039
- attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
3040
- },
3498
+ { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ },
3499
+ { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ },
3500
+ { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ },
3501
+ { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ },
3502
+ { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ },
3503
+ { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }
3504
+ ],
3041
3505
 
3042
- // for Selector.match and Element#match
3043
3506
  assertions: {
3044
3507
  tagName: function(element, matches) {
3045
3508
  return matches[1].toUpperCase() == element.tagName.toUpperCase();
@@ -3064,15 +3527,12 @@ Object.extend(Selector, {
3064
3527
  },
3065
3528
 
3066
3529
  handlers: {
3067
- // UTILITY FUNCTIONS
3068
- // joins two collections
3069
3530
  concat: function(a, b) {
3070
3531
  for (var i = 0, node; node = b[i]; i++)
3071
3532
  a.push(node);
3072
3533
  return a;
3073
3534
  },
3074
3535
 
3075
- // marks an array of nodes for counting
3076
3536
  mark: function(nodes) {
3077
3537
  var _true = Prototype.emptyFunction;
3078
3538
  for (var i = 0, node; node = nodes[i]; i++)
@@ -3080,15 +3540,32 @@ Object.extend(Selector, {
3080
3540
  return nodes;
3081
3541
  },
3082
3542
 
3083
- unmark: function(nodes) {
3084
- for (var i = 0, node; node = nodes[i]; i++)
3085
- node._countedByPrototype = undefined;
3086
- return nodes;
3087
- },
3543
+ unmark: (function(){
3544
+
3545
+ var PROPERTIES_ATTRIBUTES_MAP = (function(){
3546
+ var el = document.createElement('div'),
3547
+ isBuggy = false,
3548
+ propName = '_countedByPrototype',
3549
+ value = 'x'
3550
+ el[propName] = value;
3551
+ isBuggy = (el.getAttribute(propName) === value);
3552
+ el = null;
3553
+ return isBuggy;
3554
+ })();
3555
+
3556
+ return PROPERTIES_ATTRIBUTES_MAP ?
3557
+ function(nodes) {
3558
+ for (var i = 0, node; node = nodes[i]; i++)
3559
+ node.removeAttribute('_countedByPrototype');
3560
+ return nodes;
3561
+ } :
3562
+ function(nodes) {
3563
+ for (var i = 0, node; node = nodes[i]; i++)
3564
+ node._countedByPrototype = void 0;
3565
+ return nodes;
3566
+ }
3567
+ })(),
3088
3568
 
3089
- // mark each child node with its position (for nth calls)
3090
- // "ofType" flag indicates whether we're indexing for nth-of-type
3091
- // rather than nth-child
3092
3569
  index: function(parentNode, reverse, ofType) {
3093
3570
  parentNode._countedByPrototype = Prototype.emptyFunction;
3094
3571
  if (reverse) {
@@ -3102,19 +3579,17 @@ Object.extend(Selector, {
3102
3579
  }
3103
3580
  },
3104
3581
 
3105
- // filters out duplicates and extends all nodes
3106
3582
  unique: function(nodes) {
3107
3583
  if (nodes.length == 0) return nodes;
3108
3584
  var results = [], n;
3109
3585
  for (var i = 0, l = nodes.length; i < l; i++)
3110
- if (!(n = nodes[i])._countedByPrototype) {
3586
+ if (typeof (n = nodes[i])._countedByPrototype == 'undefined') {
3111
3587
  n._countedByPrototype = Prototype.emptyFunction;
3112
3588
  results.push(Element.extend(n));
3113
3589
  }
3114
3590
  return Selector.handlers.unmark(results);
3115
3591
  },
3116
3592
 
3117
- // COMBINATOR FUNCTIONS
3118
3593
  descendant: function(nodes) {
3119
3594
  var h = Selector.handlers;
3120
3595
  for (var i = 0, results = [], node; node = nodes[i]; i++)
@@ -3158,13 +3633,11 @@ Object.extend(Selector, {
3158
3633
  return null;
3159
3634
  },
3160
3635
 
3161
- // TOKEN FUNCTIONS
3162
3636
  tagName: function(nodes, root, tagName, combinator) {
3163
3637
  var uTagName = tagName.toUpperCase();
3164
3638
  var results = [], h = Selector.handlers;
3165
3639
  if (nodes) {
3166
3640
  if (combinator) {
3167
- // fastlane for ordinary descendant combinators
3168
3641
  if (combinator == "descendant") {
3169
3642
  for (var i = 0, node; node = nodes[i]; i++)
3170
3643
  h.concat(results, node.getElementsByTagName(tagName));
@@ -3180,8 +3653,19 @@ Object.extend(Selector, {
3180
3653
 
3181
3654
  id: function(nodes, root, id, combinator) {
3182
3655
  var targetNode = $(id), h = Selector.handlers;
3183
- if (!targetNode) return [];
3184
- if (!nodes && root == document) return [targetNode];
3656
+
3657
+ if (root == document) {
3658
+ if (!targetNode) return [];
3659
+ if (!nodes) return [targetNode];
3660
+ } else {
3661
+ if (!root.sourceIndex || root.sourceIndex < 1) {
3662
+ var nodes = root.getElementsByTagName('*');
3663
+ for (var j = 0, node; node = nodes[j]; j++) {
3664
+ if (node.id === id) return [node];
3665
+ }
3666
+ }
3667
+ }
3668
+
3185
3669
  if (nodes) {
3186
3670
  if (combinator) {
3187
3671
  if (combinator == 'child') {
@@ -3293,7 +3777,6 @@ Object.extend(Selector, {
3293
3777
  return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
3294
3778
  },
3295
3779
 
3296
- // handles the an+b logic
3297
3780
  getIndices: function(a, b, total) {
3298
3781
  if (a == 0) return b > 0 ? [b] : [];
3299
3782
  return $R(1, total).inject([], function(memo, i) {
@@ -3302,7 +3785,6 @@ Object.extend(Selector, {
3302
3785
  });
3303
3786
  },
3304
3787
 
3305
- // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
3306
3788
  nth: function(nodes, formula, root, reverse, ofType) {
3307
3789
  if (nodes.length == 0) return [];
3308
3790
  if (formula == 'even') formula = '2n+0';
@@ -3336,7 +3818,6 @@ Object.extend(Selector, {
3336
3818
 
3337
3819
  'empty': function(nodes, value, root) {
3338
3820
  for (var i = 0, results = [], node; node = nodes[i]; i++) {
3339
- // IE treats comments as element nodes
3340
3821
  if (node.tagName == '!' || node.firstChild) continue;
3341
3822
  results.push(node);
3342
3823
  }
@@ -3379,8 +3860,6 @@ Object.extend(Selector, {
3379
3860
  '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
3380
3861
  '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
3381
3862
  '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
3382
- '$=': function(nv, v) { return nv.endsWith(v); },
3383
- '*=': function(nv, v) { return nv.include(v); },
3384
3863
  '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
3385
3864
  '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
3386
3865
  '-').include('-' + (v || "").toUpperCase() + '-'); }
@@ -3423,19 +3902,10 @@ Object.extend(Selector, {
3423
3902
 
3424
3903
  if (Prototype.Browser.IE) {
3425
3904
  Object.extend(Selector.handlers, {
3426
- // IE returns comment nodes on getElementsByTagName("*").
3427
- // Filter them out.
3428
3905
  concat: function(a, b) {
3429
3906
  for (var i = 0, node; node = b[i]; i++)
3430
3907
  if (node.tagName !== "!") a.push(node);
3431
3908
  return a;
3432
- },
3433
-
3434
- // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
3435
- unmark: function(nodes) {
3436
- for (var i = 0, node; node = nodes[i]; i++)
3437
- node.removeAttribute('_countedByPrototype');
3438
- return nodes;
3439
3909
  }
3440
3910
  });
3441
3911
  }
@@ -3443,9 +3913,11 @@ if (Prototype.Browser.IE) {
3443
3913
  function $$() {
3444
3914
  return Selector.findChildElements(document, $A(arguments));
3445
3915
  }
3916
+
3446
3917
  var Form = {
3447
3918
  reset: function(form) {
3448
- $(form).reset();
3919
+ form = $(form);
3920
+ form.reset();
3449
3921
  return form;
3450
3922
  },
3451
3923
 
@@ -3460,7 +3932,6 @@ var Form = {
3460
3932
  if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
3461
3933
  submit !== false && (!submit || key == submit) && (submitted = true)))) {
3462
3934
  if (key in result) {
3463
- // a key is already present; construct an array of values
3464
3935
  if (!Object.isArray(result[key])) result[key] = [result[key]];
3465
3936
  result[key].push(value);
3466
3937
  }
@@ -3480,13 +3951,18 @@ Form.Methods = {
3480
3951
  },
3481
3952
 
3482
3953
  getElements: function(form) {
3483
- return $A($(form).getElementsByTagName('*')).inject([],
3484
- function(elements, child) {
3485
- if (Form.Element.Serializers[child.tagName.toLowerCase()])
3486
- elements.push(Element.extend(child));
3487
- return elements;
3488
- }
3489
- );
3954
+ var elements = $(form).getElementsByTagName('*'),
3955
+ element,
3956
+ arr = [ ],
3957
+ serializers = Form.Element.Serializers;
3958
+ for (var i = 0; element = elements[i]; i++) {
3959
+ arr.push(element);
3960
+ }
3961
+ return arr.inject([], function(elements, child) {
3962
+ if (serializers[child.tagName.toLowerCase()])
3963
+ elements.push(Element.extend(child));
3964
+ return elements;
3965
+ })
3490
3966
  },
3491
3967
 
3492
3968
  getInputs: function(form, typeName, name) {
@@ -3526,7 +4002,7 @@ Form.Methods = {
3526
4002
  }).sortBy(function(element) { return element.tabIndex }).first();
3527
4003
 
3528
4004
  return firstByIndex ? firstByIndex : elements.find(function(element) {
3529
- return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
4005
+ return /^(?:input|select|textarea)$/i.test(element.tagName);
3530
4006
  });
3531
4007
  },
3532
4008
 
@@ -3557,6 +4033,7 @@ Form.Methods = {
3557
4033
 
3558
4034
  /*--------------------------------------------------------------------------*/
3559
4035
 
4036
+
3560
4037
  Form.Element = {
3561
4038
  focus: function(element) {
3562
4039
  $(element).focus();
@@ -3570,6 +4047,7 @@ Form.Element = {
3570
4047
  };
3571
4048
 
3572
4049
  Form.Element.Methods = {
4050
+
3573
4051
  serialize: function(element) {
3574
4052
  element = $(element);
3575
4053
  if (!element.disabled && element.name) {
@@ -3610,7 +4088,7 @@ Form.Element.Methods = {
3610
4088
  try {
3611
4089
  element.focus();
3612
4090
  if (element.select && (element.tagName.toLowerCase() != 'input' ||
3613
- !['button', 'reset', 'submit'].include(element.type)))
4091
+ !(/^(?:button|reset|submit)$/i.test(element.type))))
3614
4092
  element.select();
3615
4093
  } catch (e) { }
3616
4094
  return element;
@@ -3632,6 +4110,7 @@ Form.Element.Methods = {
3632
4110
  /*--------------------------------------------------------------------------*/
3633
4111
 
3634
4112
  var Field = Form.Element;
4113
+
3635
4114
  var $F = Form.Element.Methods.getValue;
3636
4115
 
3637
4116
  /*--------------------------------------------------------------------------*/
@@ -3694,13 +4173,13 @@ Form.Element.Serializers = {
3694
4173
  },
3695
4174
 
3696
4175
  optionValue: function(opt) {
3697
- // extend element because hasAttribute may not be native
3698
4176
  return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
3699
4177
  }
3700
4178
  };
3701
4179
 
3702
4180
  /*--------------------------------------------------------------------------*/
3703
4181
 
4182
+
3704
4183
  Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
3705
4184
  initialize: function($super, element, frequency, callback) {
3706
4185
  $super(callback, frequency);
@@ -3782,354 +4261,441 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
3782
4261
  return Form.serialize(this.element);
3783
4262
  }
3784
4263
  });
3785
- if (!window.Event) var Event = { };
3786
-
3787
- Object.extend(Event, {
3788
- KEY_BACKSPACE: 8,
3789
- KEY_TAB: 9,
3790
- KEY_RETURN: 13,
3791
- KEY_ESC: 27,
3792
- KEY_LEFT: 37,
3793
- KEY_UP: 38,
3794
- KEY_RIGHT: 39,
3795
- KEY_DOWN: 40,
3796
- KEY_DELETE: 46,
3797
- KEY_HOME: 36,
3798
- KEY_END: 35,
3799
- KEY_PAGEUP: 33,
3800
- KEY_PAGEDOWN: 34,
3801
- KEY_INSERT: 45,
3802
-
3803
- cache: { },
3804
-
3805
- relatedTarget: function(event) {
3806
- var element;
3807
- switch(event.type) {
3808
- case 'mouseover': element = event.fromElement; break;
3809
- case 'mouseout': element = event.toElement; break;
3810
- default: return null;
3811
- }
3812
- return Element.extend(element);
3813
- }
3814
- });
4264
+ (function() {
4265
+
4266
+ var Event = {
4267
+ KEY_BACKSPACE: 8,
4268
+ KEY_TAB: 9,
4269
+ KEY_RETURN: 13,
4270
+ KEY_ESC: 27,
4271
+ KEY_LEFT: 37,
4272
+ KEY_UP: 38,
4273
+ KEY_RIGHT: 39,
4274
+ KEY_DOWN: 40,
4275
+ KEY_DELETE: 46,
4276
+ KEY_HOME: 36,
4277
+ KEY_END: 35,
4278
+ KEY_PAGEUP: 33,
4279
+ KEY_PAGEDOWN: 34,
4280
+ KEY_INSERT: 45,
4281
+
4282
+ cache: {}
4283
+ };
3815
4284
 
3816
- Event.Methods = (function() {
3817
- var isButton;
4285
+ var docEl = document.documentElement;
4286
+ var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
4287
+ && 'onmouseleave' in docEl;
3818
4288
 
4289
+ var _isButton;
3819
4290
  if (Prototype.Browser.IE) {
3820
4291
  var buttonMap = { 0: 1, 1: 4, 2: 2 };
3821
- isButton = function(event, code) {
3822
- return event.button == buttonMap[code];
4292
+ _isButton = function(event, code) {
4293
+ return event.button === buttonMap[code];
3823
4294
  };
3824
-
3825
4295
  } else if (Prototype.Browser.WebKit) {
3826
- isButton = function(event, code) {
4296
+ _isButton = function(event, code) {
3827
4297
  switch (code) {
3828
4298
  case 0: return event.which == 1 && !event.metaKey;
3829
4299
  case 1: return event.which == 1 && event.metaKey;
3830
4300
  default: return false;
3831
4301
  }
3832
4302
  };
3833
-
3834
4303
  } else {
3835
- isButton = function(event, code) {
4304
+ _isButton = function(event, code) {
3836
4305
  return event.which ? (event.which === code + 1) : (event.button === code);
3837
4306
  };
3838
4307
  }
3839
4308
 
3840
- return {
3841
- isLeftClick: function(event) { return isButton(event, 0) },
3842
- isMiddleClick: function(event) { return isButton(event, 1) },
3843
- isRightClick: function(event) { return isButton(event, 2) },
3844
-
3845
- element: function(event) {
3846
- event = Event.extend(event);
3847
-
3848
- var node = event.target,
3849
- type = event.type,
3850
- currentTarget = event.currentTarget;
3851
-
3852
- if (currentTarget && currentTarget.tagName) {
3853
- // Firefox screws up the "click" event when moving between radio buttons
3854
- // via arrow keys. It also screws up the "load" and "error" events on images,
3855
- // reporting the document as the target instead of the original image.
3856
- if (type === 'load' || type === 'error' ||
3857
- (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
3858
- && currentTarget.type === 'radio'))
3859
- node = currentTarget;
3860
- }
3861
- if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
3862
- return Element.extend(node);
3863
- },
4309
+ function isLeftClick(event) { return _isButton(event, 0) }
3864
4310
 
3865
- findElement: function(event, expression) {
3866
- var element = Event.element(event);
3867
- if (!expression) return element;
3868
- var elements = [element].concat(element.ancestors());
3869
- return Selector.findElement(elements, expression, 0);
3870
- },
4311
+ function isMiddleClick(event) { return _isButton(event, 1) }
3871
4312
 
3872
- pointer: function(event) {
3873
- var docElement = document.documentElement,
3874
- body = document.body || { scrollLeft: 0, scrollTop: 0 };
3875
- return {
3876
- x: event.pageX || (event.clientX +
3877
- (docElement.scrollLeft || body.scrollLeft) -
3878
- (docElement.clientLeft || 0)),
3879
- y: event.pageY || (event.clientY +
3880
- (docElement.scrollTop || body.scrollTop) -
3881
- (docElement.clientTop || 0))
3882
- };
3883
- },
4313
+ function isRightClick(event) { return _isButton(event, 2) }
4314
+
4315
+ function element(event) {
4316
+ event = Event.extend(event);
3884
4317
 
3885
- pointerX: function(event) { return Event.pointer(event).x },
3886
- pointerY: function(event) { return Event.pointer(event).y },
4318
+ var node = event.target, type = event.type,
4319
+ currentTarget = event.currentTarget;
3887
4320
 
3888
- stop: function(event) {
3889
- Event.extend(event);
3890
- event.preventDefault();
3891
- event.stopPropagation();
3892
- event.stopped = true;
4321
+ if (currentTarget && currentTarget.tagName) {
4322
+ if (type === 'load' || type === 'error' ||
4323
+ (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
4324
+ && currentTarget.type === 'radio'))
4325
+ node = currentTarget;
3893
4326
  }
4327
+
4328
+ if (node.nodeType == Node.TEXT_NODE)
4329
+ node = node.parentNode;
4330
+
4331
+ return Element.extend(node);
4332
+ }
4333
+
4334
+ function findElement(event, expression) {
4335
+ var element = Event.element(event);
4336
+ if (!expression) return element;
4337
+ var elements = [element].concat(element.ancestors());
4338
+ return Selector.findElement(elements, expression, 0);
4339
+ }
4340
+
4341
+ function pointer(event) {
4342
+ return { x: pointerX(event), y: pointerY(event) };
4343
+ }
4344
+
4345
+ function pointerX(event) {
4346
+ var docElement = document.documentElement,
4347
+ body = document.body || { scrollLeft: 0 };
4348
+
4349
+ return event.pageX || (event.clientX +
4350
+ (docElement.scrollLeft || body.scrollLeft) -
4351
+ (docElement.clientLeft || 0));
4352
+ }
4353
+
4354
+ function pointerY(event) {
4355
+ var docElement = document.documentElement,
4356
+ body = document.body || { scrollTop: 0 };
4357
+
4358
+ return event.pageY || (event.clientY +
4359
+ (docElement.scrollTop || body.scrollTop) -
4360
+ (docElement.clientTop || 0));
4361
+ }
4362
+
4363
+
4364
+ function stop(event) {
4365
+ Event.extend(event);
4366
+ event.preventDefault();
4367
+ event.stopPropagation();
4368
+
4369
+ event.stopped = true;
4370
+ }
4371
+
4372
+ Event.Methods = {
4373
+ isLeftClick: isLeftClick,
4374
+ isMiddleClick: isMiddleClick,
4375
+ isRightClick: isRightClick,
4376
+
4377
+ element: element,
4378
+ findElement: findElement,
4379
+
4380
+ pointer: pointer,
4381
+ pointerX: pointerX,
4382
+ pointerY: pointerY,
4383
+
4384
+ stop: stop
3894
4385
  };
3895
- })();
3896
4386
 
3897
- Event.extend = (function() {
4387
+
3898
4388
  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
3899
4389
  m[name] = Event.Methods[name].methodize();
3900
4390
  return m;
3901
4391
  });
3902
4392
 
3903
4393
  if (Prototype.Browser.IE) {
4394
+ function _relatedTarget(event) {
4395
+ var element;
4396
+ switch (event.type) {
4397
+ case 'mouseover': element = event.fromElement; break;
4398
+ case 'mouseout': element = event.toElement; break;
4399
+ default: return null;
4400
+ }
4401
+ return Element.extend(element);
4402
+ }
4403
+
3904
4404
  Object.extend(methods, {
3905
4405
  stopPropagation: function() { this.cancelBubble = true },
3906
4406
  preventDefault: function() { this.returnValue = false },
3907
- inspect: function() { return "[object Event]" }
4407
+ inspect: function() { return '[object Event]' }
3908
4408
  });
3909
4409
 
3910
- return function(event) {
4410
+ Event.extend = function(event, element) {
3911
4411
  if (!event) return false;
3912
4412
  if (event._extendedByPrototype) return event;
3913
4413
 
3914
4414
  event._extendedByPrototype = Prototype.emptyFunction;
3915
4415
  var pointer = Event.pointer(event);
4416
+
3916
4417
  Object.extend(event, {
3917
- target: event.srcElement,
3918
- relatedTarget: Event.relatedTarget(event),
4418
+ target: event.srcElement || element,
4419
+ relatedTarget: _relatedTarget(event),
3919
4420
  pageX: pointer.x,
3920
4421
  pageY: pointer.y
3921
4422
  });
4423
+
3922
4424
  return Object.extend(event, methods);
3923
4425
  };
3924
-
3925
4426
  } else {
3926
- Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
4427
+ Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
3927
4428
  Object.extend(Event.prototype, methods);
3928
- return Prototype.K;
4429
+ Event.extend = Prototype.K;
3929
4430
  }
3930
- })();
3931
4431
 
3932
- Object.extend(Event, (function() {
3933
- var cache = Event.cache;
3934
-
3935
- function getEventID(element) {
3936
- if (element._prototypeEventID) return element._prototypeEventID[0];
3937
- arguments.callee.id = arguments.callee.id || 1;
3938
- return element._prototypeEventID = [++arguments.callee.id];
3939
- }
4432
+ function _createResponder(element, eventName, handler) {
4433
+ var registry = Element.retrieve(element, 'prototype_event_registry');
3940
4434
 
3941
- function getDOMEventName(eventName) {
3942
- if (eventName && eventName.include(':')) return "dataavailable";
3943
- return eventName;
3944
- }
4435
+ if (Object.isUndefined(registry)) {
4436
+ CACHE.push(element);
4437
+ registry = Element.retrieve(element, 'prototype_event_registry', $H());
4438
+ }
3945
4439
 
3946
- function getCacheForID(id) {
3947
- return cache[id] = cache[id] || { };
3948
- }
4440
+ var respondersForEvent = registry.get(eventName);
4441
+ if (Object.isUndefined(respondersForEvent)) {
4442
+ respondersForEvent = [];
4443
+ registry.set(eventName, respondersForEvent);
4444
+ }
3949
4445
 
3950
- function getWrappersForEventName(id, eventName) {
3951
- var c = getCacheForID(id);
3952
- return c[eventName] = c[eventName] || [];
3953
- }
4446
+ if (respondersForEvent.pluck('handler').include(handler)) return false;
3954
4447
 
3955
- function createWrapper(element, eventName, handler) {
3956
- var id = getEventID(element);
3957
- var c = getWrappersForEventName(id, eventName);
3958
- if (c.pluck("handler").include(handler)) return false;
4448
+ var responder;
4449
+ if (eventName.include(":")) {
4450
+ responder = function(event) {
4451
+ if (Object.isUndefined(event.eventName))
4452
+ return false;
3959
4453
 
3960
- var wrapper = function(event) {
3961
- if (!Event || !Event.extend ||
3962
- (event.eventName && event.eventName != eventName))
4454
+ if (event.eventName !== eventName)
3963
4455
  return false;
3964
4456
 
3965
- Event.extend(event);
3966
- handler.call(element, event);
3967
- };
4457
+ Event.extend(event, element);
4458
+ handler.call(element, event);
4459
+ };
4460
+ } else {
4461
+ if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
4462
+ (eventName === "mouseenter" || eventName === "mouseleave")) {
4463
+ if (eventName === "mouseenter" || eventName === "mouseleave") {
4464
+ responder = function(event) {
4465
+ Event.extend(event, element);
4466
+
4467
+ var parent = event.relatedTarget;
4468
+ while (parent && parent !== element) {
4469
+ try { parent = parent.parentNode; }
4470
+ catch(e) { parent = element; }
4471
+ }
3968
4472
 
3969
- wrapper.handler = handler;
3970
- c.push(wrapper);
3971
- return wrapper;
3972
- }
4473
+ if (parent === element) return;
3973
4474
 
3974
- function findWrapper(id, eventName, handler) {
3975
- var c = getWrappersForEventName(id, eventName);
3976
- return c.find(function(wrapper) { return wrapper.handler == handler });
3977
- }
4475
+ handler.call(element, event);
4476
+ };
4477
+ }
4478
+ } else {
4479
+ responder = function(event) {
4480
+ Event.extend(event, element);
4481
+ handler.call(element, event);
4482
+ };
4483
+ }
4484
+ }
3978
4485
 
3979
- function destroyWrapper(id, eventName, handler) {
3980
- var c = getCacheForID(id);
3981
- if (!c[eventName]) return false;
3982
- c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
4486
+ responder.handler = handler;
4487
+ respondersForEvent.push(responder);
4488
+ return responder;
3983
4489
  }
3984
4490
 
3985
- function destroyCache() {
3986
- for (var id in cache)
3987
- for (var eventName in cache[id])
3988
- cache[id][eventName] = null;
4491
+ function _destroyCache() {
4492
+ for (var i = 0, length = CACHE.length; i < length; i++) {
4493
+ Event.stopObserving(CACHE[i]);
4494
+ CACHE[i] = null;
4495
+ }
3989
4496
  }
3990
4497
 
4498
+ var CACHE = [];
3991
4499
 
3992
- // Internet Explorer needs to remove event handlers on page unload
3993
- // in order to avoid memory leaks.
3994
- if (window.attachEvent) {
3995
- window.attachEvent("onunload", destroyCache);
3996
- }
4500
+ if (Prototype.Browser.IE)
4501
+ window.attachEvent('onunload', _destroyCache);
3997
4502
 
3998
- // Safari has a dummy event handler on page unload so that it won't
3999
- // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
4000
- // object when page is returned to via the back button using its bfcache.
4001
- if (Prototype.Browser.WebKit) {
4503
+ if (Prototype.Browser.WebKit)
4002
4504
  window.addEventListener('unload', Prototype.emptyFunction, false);
4505
+
4506
+
4507
+ var _getDOMEventName = Prototype.K;
4508
+
4509
+ if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
4510
+ _getDOMEventName = function(eventName) {
4511
+ var translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
4512
+ return eventName in translations ? translations[eventName] : eventName;
4513
+ };
4003
4514
  }
4004
4515
 
4005
- return {
4006
- observe: function(element, eventName, handler) {
4007
- element = $(element);
4008
- var name = getDOMEventName(eventName);
4516
+ function observe(element, eventName, handler) {
4517
+ element = $(element);
4009
4518
 
4010
- var wrapper = createWrapper(element, eventName, handler);
4011
- if (!wrapper) return element;
4519
+ var responder = _createResponder(element, eventName, handler);
4012
4520
 
4013
- if (element.addEventListener) {
4014
- element.addEventListener(name, wrapper, false);
4015
- } else {
4016
- element.attachEvent("on" + name, wrapper);
4521
+ if (!responder) return element;
4522
+
4523
+ if (eventName.include(':')) {
4524
+ if (element.addEventListener)
4525
+ element.addEventListener("dataavailable", responder, false);
4526
+ else {
4527
+ element.attachEvent("ondataavailable", responder);
4528
+ element.attachEvent("onfilterchange", responder);
4017
4529
  }
4530
+ } else {
4531
+ var actualEventName = _getDOMEventName(eventName);
4018
4532
 
4019
- return element;
4020
- },
4533
+ if (element.addEventListener)
4534
+ element.addEventListener(actualEventName, responder, false);
4535
+ else
4536
+ element.attachEvent("on" + actualEventName, responder);
4537
+ }
4021
4538
 
4022
- stopObserving: function(element, eventName, handler) {
4023
- element = $(element);
4024
- var id = getEventID(element), name = getDOMEventName(eventName);
4539
+ return element;
4540
+ }
4025
4541
 
4026
- if (!handler && eventName) {
4027
- getWrappersForEventName(id, eventName).each(function(wrapper) {
4028
- element.stopObserving(eventName, wrapper.handler);
4029
- });
4030
- return element;
4542
+ function stopObserving(element, eventName, handler) {
4543
+ element = $(element);
4031
4544
 
4032
- } else if (!eventName) {
4033
- Object.keys(getCacheForID(id)).each(function(eventName) {
4034
- element.stopObserving(eventName);
4035
- });
4036
- return element;
4037
- }
4545
+ var registry = Element.retrieve(element, 'prototype_event_registry');
4038
4546
 
4039
- var wrapper = findWrapper(id, eventName, handler);
4040
- if (!wrapper) return element;
4547
+ if (Object.isUndefined(registry)) return element;
4041
4548
 
4042
- if (element.removeEventListener) {
4043
- element.removeEventListener(name, wrapper, false);
4044
- } else {
4045
- element.detachEvent("on" + name, wrapper);
4046
- }
4549
+ if (eventName && !handler) {
4550
+ var responders = registry.get(eventName);
4047
4551
 
4048
- destroyWrapper(id, eventName, handler);
4552
+ if (Object.isUndefined(responders)) return element;
4049
4553
 
4554
+ responders.each( function(r) {
4555
+ Element.stopObserving(element, eventName, r.handler);
4556
+ });
4050
4557
  return element;
4051
- },
4558
+ } else if (!eventName) {
4559
+ registry.each( function(pair) {
4560
+ var eventName = pair.key, responders = pair.value;
4052
4561
 
4053
- fire: function(element, eventName, memo) {
4054
- element = $(element);
4055
- if (element == document && document.createEvent && !element.dispatchEvent)
4056
- element = document.documentElement;
4562
+ responders.each( function(r) {
4563
+ Element.stopObserving(element, eventName, r.handler);
4564
+ });
4565
+ });
4566
+ return element;
4567
+ }
4057
4568
 
4058
- var event;
4059
- if (document.createEvent) {
4060
- event = document.createEvent("HTMLEvents");
4061
- event.initEvent("dataavailable", true, true);
4062
- } else {
4063
- event = document.createEventObject();
4064
- event.eventType = "ondataavailable";
4065
- }
4569
+ var responders = registry.get(eventName);
4066
4570
 
4067
- event.eventName = eventName;
4068
- event.memo = memo || { };
4571
+ if (!responders) return;
4069
4572
 
4070
- if (document.createEvent) {
4071
- element.dispatchEvent(event);
4072
- } else {
4073
- element.fireEvent(event.eventType, event);
4573
+ var responder = responders.find( function(r) { return r.handler === handler; });
4574
+ if (!responder) return element;
4575
+
4576
+ var actualEventName = _getDOMEventName(eventName);
4577
+
4578
+ if (eventName.include(':')) {
4579
+ if (element.removeEventListener)
4580
+ element.removeEventListener("dataavailable", responder, false);
4581
+ else {
4582
+ element.detachEvent("ondataavailable", responder);
4583
+ element.detachEvent("onfilterchange", responder);
4074
4584
  }
4585
+ } else {
4586
+ if (element.removeEventListener)
4587
+ element.removeEventListener(actualEventName, responder, false);
4588
+ else
4589
+ element.detachEvent('on' + actualEventName, responder);
4590
+ }
4591
+
4592
+ registry.set(eventName, responders.without(responder));
4593
+
4594
+ return element;
4595
+ }
4596
+
4597
+ function fire(element, eventName, memo, bubble) {
4598
+ element = $(element);
4599
+
4600
+ if (Object.isUndefined(bubble))
4601
+ bubble = true;
4075
4602
 
4076
- return Event.extend(event);
4603
+ if (element == document && document.createEvent && !element.dispatchEvent)
4604
+ element = document.documentElement;
4605
+
4606
+ var event;
4607
+ if (document.createEvent) {
4608
+ event = document.createEvent('HTMLEvents');
4609
+ event.initEvent('dataavailable', true, true);
4610
+ } else {
4611
+ event = document.createEventObject();
4612
+ event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
4077
4613
  }
4078
- };
4079
- })());
4080
4614
 
4081
- Object.extend(Event, Event.Methods);
4615
+ event.eventName = eventName;
4616
+ event.memo = memo || { };
4082
4617
 
4083
- Element.addMethods({
4084
- fire: Event.fire,
4085
- observe: Event.observe,
4086
- stopObserving: Event.stopObserving
4087
- });
4618
+ if (document.createEvent)
4619
+ element.dispatchEvent(event);
4620
+ else
4621
+ element.fireEvent(event.eventType, event);
4088
4622
 
4089
- Object.extend(document, {
4090
- fire: Element.Methods.fire.methodize(),
4091
- observe: Element.Methods.observe.methodize(),
4092
- stopObserving: Element.Methods.stopObserving.methodize(),
4093
- loaded: false
4094
- });
4623
+ return Event.extend(event);
4624
+ }
4625
+
4626
+
4627
+ Object.extend(Event, Event.Methods);
4628
+
4629
+ Object.extend(Event, {
4630
+ fire: fire,
4631
+ observe: observe,
4632
+ stopObserving: stopObserving
4633
+ });
4634
+
4635
+ Element.addMethods({
4636
+ fire: fire,
4637
+
4638
+ observe: observe,
4639
+
4640
+ stopObserving: stopObserving
4641
+ });
4642
+
4643
+ Object.extend(document, {
4644
+ fire: fire.methodize(),
4645
+
4646
+ observe: observe.methodize(),
4647
+
4648
+ stopObserving: stopObserving.methodize(),
4649
+
4650
+ loaded: false
4651
+ });
4652
+
4653
+ if (window.Event) Object.extend(window.Event, Event);
4654
+ else window.Event = Event;
4655
+ })();
4095
4656
 
4096
4657
  (function() {
4097
4658
  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
4098
- Matthias Miller, Dean Edwards and John Resig. */
4659
+ Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
4099
4660
 
4100
4661
  var timer;
4101
4662
 
4102
4663
  function fireContentLoadedEvent() {
4103
4664
  if (document.loaded) return;
4104
- if (timer) window.clearInterval(timer);
4105
- document.fire("dom:loaded");
4665
+ if (timer) window.clearTimeout(timer);
4106
4666
  document.loaded = true;
4667
+ document.fire('dom:loaded');
4107
4668
  }
4108
4669
 
4109
- if (document.addEventListener) {
4110
- if (Prototype.Browser.WebKit) {
4111
- timer = window.setInterval(function() {
4112
- if (/loaded|complete/.test(document.readyState))
4113
- fireContentLoadedEvent();
4114
- }, 0);
4115
-
4116
- Event.observe(window, "load", fireContentLoadedEvent);
4670
+ function checkReadyState() {
4671
+ if (document.readyState === 'complete') {
4672
+ document.stopObserving('readystatechange', checkReadyState);
4673
+ fireContentLoadedEvent();
4674
+ }
4675
+ }
4117
4676
 
4118
- } else {
4119
- document.addEventListener("DOMContentLoaded",
4120
- fireContentLoadedEvent, false);
4677
+ function pollDoScroll() {
4678
+ try { document.documentElement.doScroll('left'); }
4679
+ catch(e) {
4680
+ timer = pollDoScroll.defer();
4681
+ return;
4121
4682
  }
4683
+ fireContentLoadedEvent();
4684
+ }
4122
4685
 
4686
+ if (document.addEventListener) {
4687
+ document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
4123
4688
  } else {
4124
- document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
4125
- $("__onDOMContentLoaded").onreadystatechange = function() {
4126
- if (this.readyState == "complete") {
4127
- this.onreadystatechange = null;
4128
- fireContentLoadedEvent();
4129
- }
4130
- };
4689
+ document.observe('readystatechange', checkReadyState);
4690
+ if (window == top)
4691
+ timer = pollDoScroll.defer();
4131
4692
  }
4693
+
4694
+ Event.observe(window, 'load', fireContentLoadedEvent);
4132
4695
  })();
4696
+
4697
+ Element.addMethods();
4698
+
4133
4699
  /*------------------------------- DEPRECATED -------------------------------*/
4134
4700
 
4135
4701
  Hash.toQueryString = Object.toQueryString;
@@ -4158,16 +4724,9 @@ var Insertion = {
4158
4724
 
4159
4725
  var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
4160
4726
 
4161
- // This should be moved to script.aculo.us; notice the deprecated methods
4162
- // further below, that map to the newer Element methods.
4163
4727
  var Position = {
4164
- // set to true if needed, warning: firefox performance problems
4165
- // NOT neeeded for page scrolling, only if draggable contained in
4166
- // scrollable elements
4167
4728
  includeScrollOffsets: false,
4168
4729
 
4169
- // must be called before calling withinIncludingScrolloffset, every time the
4170
- // page is scrolled
4171
4730
  prepare: function() {
4172
4731
  this.deltaX = window.pageXOffset
4173
4732
  || document.documentElement.scrollLeft
@@ -4179,7 +4738,6 @@ var Position = {
4179
4738
  || 0;
4180
4739
  },
4181
4740
 
4182
- // caches x/y coordinate pair to use with overlap
4183
4741
  within: function(element, x, y) {
4184
4742
  if (this.includeScrollOffsets)
4185
4743
  return this.withinIncludingScrolloffsets(element, x, y);
@@ -4206,7 +4764,6 @@ var Position = {
4206
4764
  this.xcomp < this.offset[0] + element.offsetWidth);
4207
4765
  },
4208
4766
 
4209
- // within must be called directly before
4210
4767
  overlap: function(mode, element) {
4211
4768
  if (!mode) return 0;
4212
4769
  if (mode == 'vertical')
@@ -4217,7 +4774,6 @@ var Position = {
4217
4774
  element.offsetWidth;
4218
4775
  },
4219
4776
 
4220
- // Deprecation layer -- use newer Element methods now (1.5.2).
4221
4777
 
4222
4778
  cumulativeOffset: Element.Methods.cumulativeOffset,
4223
4779
 
@@ -4316,5 +4872,3 @@ Element.ClassNames.prototype = {
4316
4872
  Object.extend(Element.ClassNames.prototype, Enumerable);
4317
4873
 
4318
4874
  /*--------------------------------------------------------------------------*/
4319
-
4320
- Element.addMethods();