gettext 1.10.0 → 1.90.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. data/ChangeLog +156 -2
  2. data/NEWS +28 -0
  3. data/README +128 -138
  4. data/Rakefile +83 -43
  5. data/data/locale/es/LC_MESSAGES/rails.mo +0 -0
  6. data/data/locale/hu/LC_MESSAGES/rails.mo +0 -0
  7. data/data/locale/hu/LC_MESSAGES/rgettext.mo +0 -0
  8. data/data/locale/ua/LC_MESSAGES/rails.mo +0 -0
  9. data/data/locale/ua/LC_MESSAGES/rgettext.mo +0 -0
  10. data/doc/classes/ActiveRecord/Base.html +360 -0
  11. data/doc/classes/ActiveRecord/ConnectionAdapters/Column.html +182 -0
  12. data/doc/classes/ActiveRecord/Migration.html +118 -0
  13. data/doc/classes/GetText.html +1790 -0
  14. data/doc/classes/GetText/ActiveRecordParser.html +236 -0
  15. data/doc/classes/GetText/Container.html +119 -0
  16. data/doc/classes/GetText/ErbContainer.html +223 -0
  17. data/doc/classes/GetText/ErbParser.html +156 -0
  18. data/doc/classes/GetText/GladeParser.html +133 -0
  19. data/doc/classes/GetText/NoboundTextDomainError.html +119 -0
  20. data/doc/classes/GetText/PoParser.html +169 -0
  21. data/doc/classes/GetText/Rails.html +293 -0
  22. data/doc/classes/GetText/RubyParser.html +123 -0
  23. data/doc/classes/GetText/TextDomain.html +572 -0
  24. data/doc/classes/GetText/TextDomainManager.html +443 -0
  25. data/doc/classes/Iconv.html +257 -0
  26. data/doc/classes/Iconv/Failure.html +105 -0
  27. data/doc/classes/Iconv/IllegalSequence.html +118 -0
  28. data/doc/classes/Iconv/InvalidCharacter.html +118 -0
  29. data/doc/classes/Iconv/InvalidEncoding.html +118 -0
  30. data/doc/classes/Locale.html +839 -0
  31. data/doc/classes/Locale/Object.html +799 -0
  32. data/doc/classes/Locale/SystemBase.html +271 -0
  33. data/doc/classes/Locale/SystemCGI.html +312 -0
  34. data/doc/classes/Locale/SystemJRuby.html +112 -0
  35. data/doc/classes/Locale/SystemPosix.html +113 -0
  36. data/doc/classes/Locale/SystemWin32.html +182 -0
  37. data/doc/classes/MOFile.html +678 -0
  38. data/doc/classes/MOFile/InvalidFormat.html +111 -0
  39. data/doc/classes/Module.html +158 -0
  40. data/doc/classes/String.html +225 -0
  41. data/doc/created.rid +1 -0
  42. data/doc/files/ChangeLog.html +2355 -0
  43. data/doc/files/README.html +510 -0
  44. data/doc/files/lib/gettext/active_record_rb.html +110 -0
  45. data/doc/files/lib/gettext/cgi_rb.html +110 -0
  46. data/doc/files/lib/gettext/container_rb.html +108 -0
  47. data/doc/files/lib/gettext/erb_rb.html +109 -0
  48. data/doc/files/lib/gettext/iconv_rb.html +109 -0
  49. data/doc/files/lib/gettext/mo_rb.html +108 -0
  50. data/doc/files/lib/gettext/parser/active_record_rb.html +119 -0
  51. data/doc/files/lib/gettext/parser/erb_rb.html +109 -0
  52. data/doc/files/lib/gettext/parser/glade_rb.html +109 -0
  53. data/doc/files/lib/gettext/parser/ruby_rb.html +110 -0
  54. data/doc/files/lib/gettext/poparser_rb.html +108 -0
  55. data/doc/files/lib/gettext/rails_compat_rb.html +108 -0
  56. data/doc/files/lib/gettext/rails_rb.html +112 -0
  57. data/doc/files/lib/gettext/rgettext_rb.html +110 -0
  58. data/doc/files/lib/gettext/rmsgfmt_rb.html +112 -0
  59. data/doc/files/lib/gettext/rmsgmerge_rb.html +112 -0
  60. data/doc/files/lib/gettext/string_rb.html +101 -0
  61. data/doc/files/lib/gettext/textdomain_rb.html +109 -0
  62. data/doc/files/lib/gettext/textdomainmanager_rb.html +109 -0
  63. data/doc/files/lib/gettext/utils_rb.html +111 -0
  64. data/doc/files/lib/gettext/version_rb.html +101 -0
  65. data/doc/files/lib/gettext_rb.html +113 -0
  66. data/doc/files/lib/locale/base_rb.html +101 -0
  67. data/doc/files/lib/locale/cgi_rb.html +108 -0
  68. data/doc/files/lib/locale/jruby_rb.html +110 -0
  69. data/doc/files/lib/locale/object_rb.html +101 -0
  70. data/doc/files/lib/locale/posix_rb.html +108 -0
  71. data/doc/files/lib/locale/win32_rb.html +110 -0
  72. data/doc/files/lib/locale/win32_table_rb.html +101 -0
  73. data/doc/files/lib/locale_rb.html +111 -0
  74. data/doc/fr_class_index.html +57 -0
  75. data/doc/fr_file_index.html +58 -0
  76. data/doc/fr_method_index.html +155 -0
  77. data/doc/index.html +24 -0
  78. data/doc/rdoc-style.css +208 -0
  79. data/lib/gettext.rb +102 -50
  80. data/lib/gettext/cgi.rb +2 -27
  81. data/lib/gettext/iconv.rb +76 -62
  82. data/lib/gettext/mo.rb +3 -3
  83. data/lib/gettext/parser/erb.rb +2 -2
  84. data/lib/gettext/rails.rb +69 -48
  85. data/lib/gettext/rgettext.rb +2 -2
  86. data/lib/gettext/rmsgmerge.rb +2 -2
  87. data/lib/gettext/string.rb +9 -5
  88. data/lib/gettext/textdomain.rb +3 -3
  89. data/lib/gettext/textdomainmanager.rb +5 -5
  90. data/lib/gettext/utils.rb +4 -3
  91. data/lib/gettext/version.rb +1 -1
  92. data/lib/{gettext/locale.rb → locale.rb} +11 -58
  93. data/lib/locale/base.rb +60 -0
  94. data/lib/{gettext/locale_cgi.rb → locale/cgi.rb} +30 -28
  95. data/lib/locale/jruby.rb +36 -0
  96. data/lib/{gettext/locale_object.rb → locale/object.rb} +78 -24
  97. data/lib/locale/posix.rb +22 -0
  98. data/lib/locale/win32.rb +48 -0
  99. data/lib/{gettext/locale_table_win32.rb → locale/win32_table.rb} +3 -2
  100. data/po/es/rails.po +1 -2
  101. data/po/hu/rails.po +139 -0
  102. data/po/hu/rgettext.po +126 -0
  103. data/po/ja/rails.po +5 -5
  104. data/po/ua/rails.po +150 -0
  105. data/po/ua/rgettext.po +132 -0
  106. data/pre-setup.rb +2 -4
  107. data/samples/cgi/cookie.cgi +1 -0
  108. data/samples/cgi/helloerb1.cgi +6 -3
  109. data/samples/cgi/helloerb2.cgi +6 -3
  110. data/samples/cgi/http.rb +3 -7
  111. data/samples/cgi/index.cgi +2 -1
  112. data/samples/cgi/locale/hu/LC_MESSAGES/helloerb1.mo +0 -0
  113. data/samples/cgi/locale/hu/LC_MESSAGES/helloerb2.mo +0 -0
  114. data/samples/cgi/locale/hu/LC_MESSAGES/hellolib.mo +0 -0
  115. data/samples/cgi/locale/hu/LC_MESSAGES/main.mo +0 -0
  116. data/samples/cgi/locale/ua/LC_MESSAGES/helloerb1.mo +0 -0
  117. data/samples/cgi/locale/ua/LC_MESSAGES/helloerb2.mo +0 -0
  118. data/samples/cgi/locale/ua/LC_MESSAGES/hellolib.mo +0 -0
  119. data/samples/cgi/locale/ua/LC_MESSAGES/main.mo +0 -0
  120. data/samples/cgi/po/hu/helloerb1.po +59 -0
  121. data/samples/cgi/po/hu/helloerb2.po +51 -0
  122. data/samples/cgi/po/hu/hellolib.po +23 -0
  123. data/samples/cgi/po/hu/main.po +82 -0
  124. data/samples/cgi/po/ua/helloerb1.po +62 -0
  125. data/samples/cgi/po/ua/helloerb2.po +54 -0
  126. data/samples/cgi/po/ua/hellolib.po +26 -0
  127. data/samples/cgi/po/ua/main.po +84 -0
  128. data/samples/locale/hu/LC_MESSAGES/hello.mo +0 -0
  129. data/samples/locale/hu/LC_MESSAGES/hello2.mo +0 -0
  130. data/samples/locale/hu/LC_MESSAGES/hello_noop.mo +0 -0
  131. data/samples/locale/hu/LC_MESSAGES/hello_plural.mo +0 -0
  132. data/samples/locale/hu/LC_MESSAGES/helloglade2.mo +0 -0
  133. data/samples/locale/hu/LC_MESSAGES/hellogtk.mo +0 -0
  134. data/samples/locale/hu/LC_MESSAGES/hellotk.mo +0 -0
  135. data/samples/locale/ua/LC_MESSAGES/hello.mo +0 -0
  136. data/samples/locale/ua/LC_MESSAGES/hello2.mo +0 -0
  137. data/samples/locale/ua/LC_MESSAGES/hello_noop.mo +0 -0
  138. data/samples/locale/ua/LC_MESSAGES/hello_plural.mo +0 -0
  139. data/samples/locale/ua/LC_MESSAGES/helloglade2.mo +0 -0
  140. data/samples/locale/ua/LC_MESSAGES/hellogtk.mo +0 -0
  141. data/samples/locale/ua/LC_MESSAGES/hellotk.mo +0 -0
  142. data/samples/po/hu/hello.po +22 -0
  143. data/samples/po/hu/hello2.po +30 -0
  144. data/samples/po/hu/hello_noop.po +26 -0
  145. data/samples/po/hu/hello_plural.po +25 -0
  146. data/samples/po/hu/helloglade2.po +31 -0
  147. data/samples/po/hu/hellogtk.po +22 -0
  148. data/samples/po/hu/hellotk.po +23 -0
  149. data/samples/po/ua/hello.po +22 -0
  150. data/samples/po/ua/hello2.po +30 -0
  151. data/samples/po/ua/hello_noop.po +26 -0
  152. data/samples/po/ua/hello_plural.po +29 -0
  153. data/samples/po/ua/helloglade2.po +34 -0
  154. data/samples/po/ua/hellogtk.po +22 -0
  155. data/samples/po/ua/hellotk.po +26 -0
  156. data/samples/rails/README +15 -31
  157. data/samples/rails/Rakefile +1 -1
  158. data/samples/rails/app/controllers/application.rb +11 -4
  159. data/samples/rails/app/controllers/articles_controller.rb +96 -0
  160. data/samples/rails/app/helpers/application_helper.rb +1 -1
  161. data/samples/rails/app/helpers/{blog_helper.rb → articles_helper.rb} +6 -7
  162. data/samples/rails/app/views/articles/edit.html.erb +18 -0
  163. data/samples/rails/app/views/articles/index.html.erb +17 -0
  164. data/samples/rails/app/views/articles/new.html.erb +16 -0
  165. data/samples/rails/app/views/articles/show.html.erb +6 -0
  166. data/samples/rails/app/views/layouts/articles.html.erb +26 -0
  167. data/samples/rails/config/boot.rb +104 -13
  168. data/samples/rails/config/database.yml +24 -21
  169. data/samples/rails/config/environment.rb +35 -30
  170. data/samples/rails/config/environments/development.rb +5 -6
  171. data/samples/rails/config/environments/production.rb +2 -3
  172. data/samples/rails/config/environments/test.rb +5 -2
  173. data/samples/rails/config/initializers/inflections.rb +10 -0
  174. data/samples/rails/config/initializers/mime_types.rb +5 -0
  175. data/samples/rails/config/routes.rb +30 -11
  176. data/samples/rails/db/migrate/001_create_articles.rb +14 -0
  177. data/samples/rails/db/schema.rb +16 -5
  178. data/samples/rails/lib/tasks/gettext.rake +2 -2
  179. data/samples/rails/locale/bs/LC_MESSAGES/blog.mo +0 -0
  180. data/samples/rails/locale/ca/LC_MESSAGES/blog.mo +0 -0
  181. data/samples/rails/locale/cs/LC_MESSAGES/blog.mo +0 -0
  182. data/samples/rails/locale/de/LC_MESSAGES/blog.mo +0 -0
  183. data/samples/rails/locale/el/LC_MESSAGES/blog.mo +0 -0
  184. data/samples/rails/locale/en/LC_MESSAGES/blog.mo +0 -0
  185. data/samples/rails/locale/eo/LC_MESSAGES/blog.mo +0 -0
  186. data/samples/rails/locale/es/LC_MESSAGES/blog.mo +0 -0
  187. data/samples/rails/locale/fr/LC_MESSAGES/blog.mo +0 -0
  188. data/samples/rails/locale/hr/LC_MESSAGES/blog.mo +0 -0
  189. data/samples/rails/locale/hu/LC_MESSAGES/blog.mo +0 -0
  190. data/samples/rails/locale/it/LC_MESSAGES/blog.mo +0 -0
  191. data/samples/rails/locale/ja/LC_MESSAGES/blog.mo +0 -0
  192. data/samples/rails/locale/ko/LC_MESSAGES/blog.mo +0 -0
  193. data/samples/rails/locale/nb/LC_MESSAGES/blog.mo +0 -0
  194. data/samples/rails/locale/nl/LC_MESSAGES/blog.mo +0 -0
  195. data/samples/rails/locale/pt_BR/LC_MESSAGES/blog.mo +0 -0
  196. data/samples/rails/locale/ru/LC_MESSAGES/blog.mo +0 -0
  197. data/samples/rails/locale/ua/LC_MESSAGES/blog.mo +0 -0
  198. data/samples/rails/locale/vi/LC_MESSAGES/blog.mo +0 -0
  199. data/samples/rails/locale/zh/LC_MESSAGES/blog.mo +0 -0
  200. data/samples/rails/locale/zh_TW/LC_MESSAGES/blog.mo +0 -0
  201. data/samples/rails/po/blog.pot +24 -24
  202. data/samples/rails/po/bs/blog.po +29 -29
  203. data/samples/rails/po/ca/blog.po +27 -27
  204. data/samples/rails/po/cs/blog.po +27 -27
  205. data/samples/rails/po/de/blog.po +27 -27
  206. data/samples/rails/po/el/blog.po +27 -27
  207. data/samples/rails/po/en/blog.po +24 -24
  208. data/samples/rails/po/eo/blog.po +27 -27
  209. data/samples/rails/po/es/blog.po +27 -27
  210. data/samples/rails/po/fr/blog.po +27 -27
  211. data/samples/rails/po/hr/blog.po +29 -29
  212. data/samples/rails/po/hu/blog.po +105 -0
  213. data/samples/rails/po/it/blog.po +27 -27
  214. data/samples/rails/po/ja/blog.po +27 -27
  215. data/samples/rails/po/ko/blog.po +27 -27
  216. data/samples/rails/po/nb/blog.po +26 -27
  217. data/samples/rails/po/nl/blog.po +27 -27
  218. data/samples/rails/po/pt_BR/blog.po +27 -27
  219. data/samples/rails/po/ru/blog.po +27 -27
  220. data/samples/rails/po/ua/blog.po +108 -0
  221. data/samples/rails/po/vi/blog.po +26 -31
  222. data/samples/rails/po/zh/blog.po +27 -27
  223. data/samples/rails/po/zh_TW/blog.po +27 -27
  224. data/samples/rails/public/404.html +27 -5
  225. data/samples/rails/public/422.html +30 -0
  226. data/samples/rails/public/500.html +27 -5
  227. data/samples/rails/public/index.html +6 -6
  228. data/samples/rails/public/javascripts/application.js +2 -0
  229. data/samples/rails/public/javascripts/controls.js +532 -319
  230. data/samples/rails/public/javascripts/dragdrop.js +521 -133
  231. data/samples/rails/public/javascripts/effects.js +708 -442
  232. data/samples/rails/public/javascripts/prototype.js +3393 -953
  233. data/samples/rails/public/stylesheets/blog.css +4 -0
  234. data/samples/rails/public/stylesheets/scaffold.css +5 -5
  235. data/samples/rails/test/functional/articles_controller_test.rb +51 -0
  236. data/samples/rails/test/test_helper.rb +31 -19
  237. data/samples/rails/test/unit/article_test.rb +2 -9
  238. data/samples/rails/vendor/plugins/gettext/init.rb +5 -3
  239. data/samples/rails/vendor/plugins/gettext/lib/gettext_plugin.rb +9 -10
  240. data/samples/rails/vendor/plugins/gettext/locale/eo/LC_MESSAGES/gettext_plugin.mo +0 -0
  241. data/samples/rails/vendor/plugins/gettext/locale/hu/LC_MESSAGES/gettext_plugin.mo +0 -0
  242. data/samples/rails/vendor/plugins/gettext/locale/ua/LC_MESSAGES/gettext_plugin.mo +0 -0
  243. data/samples/rails/vendor/plugins/gettext/po/eo/gettext_plugin.po +28 -0
  244. data/samples/rails/vendor/plugins/gettext/po/hu/gettext_plugin.po +27 -0
  245. data/samples/rails/vendor/plugins/gettext/po/ua/gettext_plugin.po +30 -0
  246. data/test/Rakefile +2 -1
  247. data/test/benchmark.rb +28 -0
  248. data/test/fixtures/topic.rb +15 -0
  249. data/test/rails/Rakefile +2 -1
  250. data/test/rails/app/controllers/articles_controller.rb +1 -1
  251. data/test/rails/app/controllers/users_controller.rb +10 -0
  252. data/test/rails/app/models/user.rb +2 -1
  253. data/test/rails/app/views/articles/{_form.rhtml → _form.html.erb} +0 -0
  254. data/test/rails/app/views/articles/active_form_error.html.erb +1 -0
  255. data/test/rails/app/views/articles/change_title_error_messages_for.html.erb +21 -0
  256. data/test/rails/app/views/articles/{edit.rhtml → edit.html.erb} +0 -0
  257. data/test/rails/app/views/articles/{list.rhtml → list.html.erb} +0 -3
  258. data/test/rails/app/views/articles/{list_fr.rhtml → list_fr.html.erb} +0 -0
  259. data/test/rails/app/views/articles/{multi_error_messages_for.rhtml → multi_error_messages_for.html.erb} +0 -0
  260. data/test/rails/app/views/articles/{new.rhtml → new.html.erb} +0 -0
  261. data/test/rails/app/views/articles/{show.rhtml → show.html.erb} +0 -0
  262. data/test/rails/app/views/layouts/{application.rhtml → application.html.erb} +0 -0
  263. data/test/rails/app/views/layouts/{mailer.rhtml → mailer.html.erb} +0 -0
  264. data/test/rails/app/views/layouts/users.html.erb +13 -0
  265. data/test/rails/app/views/users/custom_error_message.html.erb +13 -0
  266. data/test/rails/app/views/users/custom_error_message_fr.html.erb +13 -0
  267. data/test/rails/config/environment.rb +6 -1
  268. data/test/rails/config/environments/development.rb +0 -3
  269. data/test/rails/db/schema.rb +17 -10
  270. data/test/rails/locale/ja/LC_MESSAGES/rails_test.mo +0 -0
  271. data/test/rails/log/development.log +136 -29
  272. data/test/rails/log/test.log +2002 -128
  273. data/test/rails/po/ja/rails_test.po +68 -61
  274. data/test/rails/po/rails_test.pot +57 -55
  275. data/test/rails/test/fixtures/users.yml +5 -0
  276. data/test/rails/test/functional/articles_controller_test.rb +6 -1
  277. data/test/rails/test/functional/users_controller_test.rb +65 -0
  278. data/test/rails/test/result/en/custom_error_message.html +83 -0
  279. data/test/rails/test/result/en/custom_error_message_with_plural.html +83 -0
  280. data/test/rails/test/result/en/list.html +0 -3
  281. data/test/rails/test/result/en/multi_error_messages_for.html +1 -1
  282. data/test/rails/test/result/fr/custom_error_message.html +83 -0
  283. data/test/rails/test/result/fr/custom_error_message_with_plural.html +83 -0
  284. data/test/rails/test/result/ja/custom_error_message.html +83 -0
  285. data/test/rails/test/result/ja/custom_error_message_with_plural.html +83 -0
  286. data/test/rails/test/result/ja/list.html +0 -3
  287. data/test/rails/test/result/ja/multi_error_messages_for.html +1 -1
  288. data/test/test.sh +5 -7
  289. data/test/{gettext_test_active_record.rb → test_active_record.rb} +20 -10
  290. data/test/{gettext_test_cgi.rb → test_cgi.rb} +0 -0
  291. data/test/{gettext_test.rb → test_gettext.rb} +91 -9
  292. data/test/test_java.sh +12 -0
  293. data/test/{gettext_test_locale.rb → test_locale.rb} +3 -8
  294. data/test/{gettext_test_multi_textdomain.rb → test_multi_textdomain.rb} +2 -2
  295. data/test/{gettext_test_parser.rb → test_parser.rb} +77 -77
  296. data/test/{gettext_test_rails.rb → test_rails.rb} +0 -0
  297. data/test/{gettext_test_rails_caching.rb → test_rails_caching.rb} +16 -2
  298. data/test/{gettext_test_string.rb → test_string.rb} +1 -0
  299. data/test/{test_rubyparser_N.rb → testlib/N_.rb} +0 -0
  300. data/test/testlib/erb.rhtml +15 -0
  301. data/test/testlib/erb.rxml +16 -0
  302. data/test/{test_rubyparser.rb → testlib/gettext.rb} +0 -0
  303. data/test/testlib/gladeparser.glade +183 -0
  304. data/test/{test_rubyparser_n_.rb → testlib/ngettext.rb} +0 -0
  305. data/test/{test_nsgettext.rb → testlib/nsgettext.rb} +0 -0
  306. data/test/{test_sgettext.rb → testlib/sgettext.rb} +0 -0
  307. data/test/{testlib1.rb → testlib/testlib1.rb} +0 -0
  308. data/test/{testlib2.rb → testlib/testlib2.rb} +1 -1
  309. data/test/{testlib3.rb → testlib/testlib3.rb} +0 -0
  310. data/test/{testlib4.rb → testlib/testlib4.rb} +1 -1
  311. data/test/{testlib5.rb → testlib/testlib5.rb} +0 -0
  312. data/test/{testlib6.rb → testlib/testlib6.rb} +0 -0
  313. metadata +1374 -1171
  314. data/ext/gettext/extconf.rb +0 -20
  315. data/ext/gettext/locale_system.c +0 -83
  316. data/lib/gettext/locale_posix.rb +0 -82
  317. data/lib/gettext/locale_win32.rb +0 -82
  318. data/samples/cgi/ruby.bat +0 -4
  319. data/samples/rails/app/controllers/blog_controller.rb +0 -58
  320. data/samples/rails/app/views/blog/_form.rhtml +0 -25
  321. data/samples/rails/app/views/blog/edit.rhtml +0 -22
  322. data/samples/rails/app/views/blog/list.rhtml +0 -29
  323. data/samples/rails/app/views/blog/new.rhtml +0 -21
  324. data/samples/rails/app/views/blog/show.rhtml +0 -18
  325. data/samples/rails/app/views/layouts/blog.rhtml +0 -36
  326. data/samples/rails/test/functional/blog_controller_test.rb +0 -98
  327. data/test/gettext_runner.rb +0 -22
@@ -1,109 +1,124 @@
1
- // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
1
+ // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
2
  // Contributors:
3
3
  // Justin Palmer (http://encytemedia.com/)
4
4
  // Mark Pilgrim (http://diveintomark.org/)
5
5
  // Martin Bialasinki
6
6
  //
7
- // See scriptaculous.js for full license.
7
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
8
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
8
9
 
9
- /* ------------- element ext -------------- */
10
-
11
10
  // converts rgb() and #xxx to #xxxxxx format,
12
11
  // returns self (or first argument) if not convertable
13
12
  String.prototype.parseColor = function() {
14
- var color = '#';
15
- if(this.slice(0,4) == 'rgb(') {
13
+ var color = '#';
14
+ if (this.slice(0,4) == 'rgb(') {
16
15
  var cols = this.slice(4,this.length-1).split(',');
17
16
  var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
18
17
  } else {
19
- if(this.slice(0,1) == '#') {
20
- if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
21
- if(this.length==7) color = this.toLowerCase();
18
+ if (this.slice(0,1) == '#') {
19
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
20
+ if (this.length==7) color = this.toLowerCase();
22
21
  }
23
22
  }
24
- return(color.length==7 ? color : (arguments[0] || this));
25
- }
26
-
27
- Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
28
- var children = $(element).childNodes;
29
- var text = '';
30
- var classtest = new RegExp('^([^ ]+ )*' + ignoreclass+ '( [^ ]+)*$','i');
31
-
32
- for (var i = 0; i < children.length; i++) {
33
- if(children[i].nodeType==3) {
34
- text+=children[i].nodeValue;
35
- } else {
36
- if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
37
- text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
38
- }
39
- }
40
-
41
- return text;
42
- }
23
+ return (color.length==7 ? color : (arguments[0] || this));
24
+ };
43
25
 
44
- Element.setStyle = function(element, style) {
45
- element = $(element);
46
- for(k in style) element.style[k.camelize()] = style[k];
47
- }
48
-
49
- Element.setContentZoom = function(element, percent) {
50
- Element.setStyle(element, {fontSize: (percent/100) + 'em'});
51
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
52
- }
53
-
54
- Element.getOpacity = function(element){
55
- var opacity;
56
- if (opacity = Element.getStyle(element, 'opacity'))
57
- return parseFloat(opacity);
58
- if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))
59
- if(opacity[1]) return parseFloat(opacity[1]) / 100;
60
- return 1.0;
61
- }
62
-
63
- Element.setOpacity = function(element, value){
64
- element= $(element);
65
- if (value == 1){
66
- Element.setStyle(element, { opacity:
67
- (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ?
68
- 0.999999 : null });
69
- if(/MSIE/.test(navigator.userAgent))
70
- Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});
71
- } else {
72
- if(value < 0.00001) value = 0;
73
- Element.setStyle(element, {opacity: value});
74
- if(/MSIE/.test(navigator.userAgent))
75
- Element.setStyle(element,
76
- { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
77
- 'alpha(opacity='+value*100+')' });
78
- }
79
- }
80
-
81
- Element.getInlineOpacity = function(element){
82
- return $(element).style.opacity || '';
83
- }
26
+ /*--------------------------------------------------------------------------*/
27
+
28
+ Element.collectTextNodes = function(element) {
29
+ return $A($(element).childNodes).collect( function(node) {
30
+ return (node.nodeType==3 ? node.nodeValue :
31
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
32
+ }).flatten().join('');
33
+ };
84
34
 
85
- Element.childrenWithClassName = function(element, className) {
86
- return $A($(element).getElementsByTagName('*')).select(
87
- function(c) { return Element.hasClassName(c, className) });
88
- }
35
+ Element.collectTextNodesIgnoreClass = function(element, className) {
36
+ return $A($(element).childNodes).collect( function(node) {
37
+ return (node.nodeType==3 ? node.nodeValue :
38
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
39
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
40
+ }).flatten().join('');
41
+ };
89
42
 
90
- Array.prototype.call = function() {
91
- var args = arguments;
92
- this.each(function(f){ f.apply(this, args) });
93
- }
43
+ Element.setContentZoom = function(element, percent) {
44
+ element = $(element);
45
+ element.setStyle({fontSize: (percent/100) + 'em'});
46
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
47
+ return element;
48
+ };
49
+
50
+ Element.getInlineOpacity = function(element){
51
+ return $(element).style.opacity || '';
52
+ };
53
+
54
+ Element.forceRerendering = function(element) {
55
+ try {
56
+ element = $(element);
57
+ var n = document.createTextNode(' ');
58
+ element.appendChild(n);
59
+ element.removeChild(n);
60
+ } catch(e) { }
61
+ };
94
62
 
95
63
  /*--------------------------------------------------------------------------*/
96
64
 
97
65
  var Effect = {
66
+ _elementDoesNotExistError: {
67
+ name: 'ElementDoesNotExistError',
68
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
69
+ },
70
+ Transitions: {
71
+ linear: Prototype.K,
72
+ sinoidal: function(pos) {
73
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
74
+ },
75
+ reverse: function(pos) {
76
+ return 1-pos;
77
+ },
78
+ flicker: function(pos) {
79
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
80
+ return pos > 1 ? 1 : pos;
81
+ },
82
+ wobble: function(pos) {
83
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
84
+ },
85
+ pulse: function(pos, pulses) {
86
+ pulses = pulses || 5;
87
+ return (
88
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
89
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
90
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
91
+ );
92
+ },
93
+ spring: function(pos) {
94
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
95
+ },
96
+ none: function(pos) {
97
+ return 0;
98
+ },
99
+ full: function(pos) {
100
+ return 1;
101
+ }
102
+ },
103
+ DefaultOptions: {
104
+ duration: 1.0, // seconds
105
+ fps: 100, // 100= assume 66fps max.
106
+ sync: false, // true for combining
107
+ from: 0.0,
108
+ to: 1.0,
109
+ delay: 0.0,
110
+ queue: 'parallel'
111
+ },
98
112
  tagifyText: function(element) {
99
113
  var tagifyStyle = 'position:relative';
100
- if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
114
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
115
+
101
116
  element = $(element);
102
117
  $A(element.childNodes).each( function(child) {
103
- if(child.nodeType==3) {
118
+ if (child.nodeType==3) {
104
119
  child.nodeValue.toArray().each( function(character) {
105
120
  element.insertBefore(
106
- Builder.node('span',{style: tagifyStyle},
121
+ new Element('span', {style: tagifyStyle}).update(
107
122
  character == ' ' ? String.fromCharCode(160) : character),
108
123
  child);
109
124
  });
@@ -113,8 +128,8 @@ var Effect = {
113
128
  },
114
129
  multiple: function(element, effect) {
115
130
  var elements;
116
- if(((typeof element == 'object') ||
117
- (typeof element == 'function')) &&
131
+ if (((typeof element == 'object') ||
132
+ Object.isFunction(element)) &&
118
133
  (element.length))
119
134
  elements = element;
120
135
  else
@@ -123,59 +138,48 @@ var Effect = {
123
138
  var options = Object.extend({
124
139
  speed: 0.1,
125
140
  delay: 0.0
126
- }, arguments[2] || {});
141
+ }, arguments[2] || { });
127
142
  var masterDelay = options.delay;
128
143
 
129
144
  $A(elements).each( function(element, index) {
130
145
  new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
131
146
  });
147
+ },
148
+ PAIRS: {
149
+ 'slide': ['SlideDown','SlideUp'],
150
+ 'blind': ['BlindDown','BlindUp'],
151
+ 'appear': ['Appear','Fade']
152
+ },
153
+ toggle: function(element, effect) {
154
+ element = $(element);
155
+ effect = (effect || 'appear').toLowerCase();
156
+ var options = Object.extend({
157
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
158
+ }, arguments[2] || { });
159
+ Effect[element.visible() ?
160
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
132
161
  }
133
162
  };
134
163
 
135
- var Effect2 = Effect; // deprecated
136
-
137
- /* ------------- transitions ------------- */
138
-
139
- Effect.Transitions = {}
140
-
141
- Effect.Transitions.linear = function(pos) {
142
- return pos;
143
- }
144
- Effect.Transitions.sinoidal = function(pos) {
145
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
146
- }
147
- Effect.Transitions.reverse = function(pos) {
148
- return 1-pos;
149
- }
150
- Effect.Transitions.flicker = function(pos) {
151
- return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
152
- }
153
- Effect.Transitions.wobble = function(pos) {
154
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
155
- }
156
- Effect.Transitions.pulse = function(pos) {
157
- return (Math.floor(pos*10) % 2 == 0 ?
158
- (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
159
- }
160
- Effect.Transitions.none = function(pos) {
161
- return 0;
162
- }
163
- Effect.Transitions.full = function(pos) {
164
- return 1;
165
- }
164
+ Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
166
165
 
167
166
  /* ------------- core effects ------------- */
168
167
 
169
- Effect.Queue = {
170
- effects: [],
168
+ Effect.ScopedQueue = Class.create(Enumerable, {
169
+ initialize: function() {
170
+ this.effects = [];
171
+ this.interval = null;
172
+ },
171
173
  _each: function(iterator) {
172
174
  this.effects._each(iterator);
173
175
  },
174
- interval: null,
175
176
  add: function(effect) {
176
177
  var timestamp = new Date().getTime();
177
178
 
178
- switch(effect.options.queue) {
179
+ var position = Object.isString(effect.options.queue) ?
180
+ effect.options.queue : effect.options.queue.position;
181
+
182
+ switch(position) {
179
183
  case 'front':
180
184
  // move unstarted effects after this effect
181
185
  this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
@@ -183,6 +187,9 @@ Effect.Queue = {
183
187
  e.finishOn += effect.finishOn;
184
188
  });
185
189
  break;
190
+ case 'with-last':
191
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
192
+ break;
186
193
  case 'end':
187
194
  // start effect after last queued effect has finished
188
195
  timestamp = this.effects.pluck('finishOn').max() || timestamp;
@@ -191,98 +198,112 @@ Effect.Queue = {
191
198
 
192
199
  effect.startOn += timestamp;
193
200
  effect.finishOn += timestamp;
194
- this.effects.push(effect);
195
- if(!this.interval)
196
- this.interval = setInterval(this.loop.bind(this), 40);
201
+
202
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
203
+ this.effects.push(effect);
204
+
205
+ if (!this.interval)
206
+ this.interval = setInterval(this.loop.bind(this), 15);
197
207
  },
198
208
  remove: function(effect) {
199
209
  this.effects = this.effects.reject(function(e) { return e==effect });
200
- if(this.effects.length == 0) {
210
+ if (this.effects.length == 0) {
201
211
  clearInterval(this.interval);
202
212
  this.interval = null;
203
213
  }
204
214
  },
205
215
  loop: function() {
206
216
  var timePos = new Date().getTime();
207
- this.effects.invoke('loop', timePos);
217
+ for(var i=0, len=this.effects.length;i<len;i++)
218
+ this.effects[i] && this.effects[i].loop(timePos);
219
+ }
220
+ });
221
+
222
+ Effect.Queues = {
223
+ instances: $H(),
224
+ get: function(queueName) {
225
+ if (!Object.isString(queueName)) return queueName;
226
+
227
+ return this.instances.get(queueName) ||
228
+ this.instances.set(queueName, new Effect.ScopedQueue());
208
229
  }
209
- }
210
- Object.extend(Effect.Queue, Enumerable);
230
+ };
231
+ Effect.Queue = Effect.Queues.get('global');
211
232
 
212
- Effect.Base = function() {};
213
- Effect.Base.prototype = {
233
+ Effect.Base = Class.create({
214
234
  position: null,
215
- setOptions: function(options) {
216
- this.options = Object.extend({
217
- transition: Effect.Transitions.sinoidal,
218
- duration: 1.0, // seconds
219
- fps: 25.0, // max. 25fps due to Effect.Queue implementation
220
- sync: false, // true for combining
221
- from: 0.0,
222
- to: 1.0,
223
- delay: 0.0,
224
- queue: 'parallel'
225
- }, options || {});
226
- },
227
235
  start: function(options) {
228
- this.setOptions(options || {});
236
+ function codeForEvent(options,eventName){
237
+ return (
238
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
239
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
240
+ );
241
+ }
242
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
243
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
229
244
  this.currentFrame = 0;
230
245
  this.state = 'idle';
231
246
  this.startOn = this.options.delay*1000;
232
- this.finishOn = this.startOn + (this.options.duration*1000);
247
+ this.finishOn = this.startOn+(this.options.duration*1000);
248
+ this.fromToDelta = this.options.to-this.options.from;
249
+ this.totalTime = this.finishOn-this.startOn;
250
+ this.totalFrames = this.options.fps*this.options.duration;
251
+
252
+ eval('this.render = function(pos){ '+
253
+ 'if (this.state=="idle"){this.state="running";'+
254
+ codeForEvent(this.options,'beforeSetup')+
255
+ (this.setup ? 'this.setup();':'')+
256
+ codeForEvent(this.options,'afterSetup')+
257
+ '};if (this.state=="running"){'+
258
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
259
+ 'this.position=pos;'+
260
+ codeForEvent(this.options,'beforeUpdate')+
261
+ (this.update ? 'this.update(pos);':'')+
262
+ codeForEvent(this.options,'afterUpdate')+
263
+ '}}');
264
+
233
265
  this.event('beforeStart');
234
- if(!this.options.sync) Effect.Queue.add(this);
266
+ if (!this.options.sync)
267
+ Effect.Queues.get(Object.isString(this.options.queue) ?
268
+ 'global' : this.options.queue.scope).add(this);
235
269
  },
236
270
  loop: function(timePos) {
237
- if(timePos >= this.startOn) {
238
- if(timePos >= this.finishOn) {
271
+ if (timePos >= this.startOn) {
272
+ if (timePos >= this.finishOn) {
239
273
  this.render(1.0);
240
274
  this.cancel();
241
275
  this.event('beforeFinish');
242
- if(this.finish) this.finish();
276
+ if (this.finish) this.finish();
243
277
  this.event('afterFinish');
244
278
  return;
245
279
  }
246
- var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
247
- var frame = Math.round(pos * this.options.fps * this.options.duration);
248
- if(frame > this.currentFrame) {
280
+ var pos = (timePos - this.startOn) / this.totalTime,
281
+ frame = (pos * this.totalFrames).round();
282
+ if (frame > this.currentFrame) {
249
283
  this.render(pos);
250
284
  this.currentFrame = frame;
251
285
  }
252
286
  }
253
287
  },
254
- render: function(pos) {
255
- if(this.state == 'idle') {
256
- this.state = 'running';
257
- this.event('beforeSetup');
258
- if(this.setup) this.setup();
259
- this.event('afterSetup');
260
- }
261
- if(this.state == 'running') {
262
- if(this.options.transition) pos = this.options.transition(pos);
263
- pos *= (this.options.to-this.options.from);
264
- pos += this.options.from;
265
- this.position = pos;
266
- this.event('beforeUpdate');
267
- if(this.update) this.update(pos);
268
- this.event('afterUpdate');
269
- }
270
- },
271
288
  cancel: function() {
272
- if(!this.options.sync) Effect.Queue.remove(this);
289
+ if (!this.options.sync)
290
+ Effect.Queues.get(Object.isString(this.options.queue) ?
291
+ 'global' : this.options.queue.scope).remove(this);
273
292
  this.state = 'finished';
274
293
  },
275
294
  event: function(eventName) {
276
- if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
277
- if(this.options[eventName]) this.options[eventName](this);
295
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
296
+ if (this.options[eventName]) this.options[eventName](this);
278
297
  },
279
298
  inspect: function() {
280
- return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
299
+ var data = $H();
300
+ for(property in this)
301
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
302
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
281
303
  }
282
- }
304
+ });
283
305
 
284
- Effect.Parallel = Class.create();
285
- Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
306
+ Effect.Parallel = Class.create(Effect.Base, {
286
307
  initialize: function(effects) {
287
308
  this.effects = effects || [];
288
309
  this.start(arguments[1]);
@@ -295,75 +316,106 @@ Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
295
316
  effect.render(1.0);
296
317
  effect.cancel();
297
318
  effect.event('beforeFinish');
298
- if(effect.finish) effect.finish(position);
319
+ if (effect.finish) effect.finish(position);
299
320
  effect.event('afterFinish');
300
321
  });
301
322
  }
302
323
  });
303
324
 
304
- Effect.Opacity = Class.create();
305
- Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
325
+ Effect.Tween = Class.create(Effect.Base, {
326
+ initialize: function(object, from, to) {
327
+ object = Object.isString(object) ? $(object) : object;
328
+ var args = $A(arguments), method = args.last(),
329
+ options = args.length == 5 ? args[3] : null;
330
+ this.method = Object.isFunction(method) ? method.bind(object) :
331
+ Object.isFunction(object[method]) ? object[method].bind(object) :
332
+ function(value) { object[method] = value };
333
+ this.start(Object.extend({ from: from, to: to }, options || { }));
334
+ },
335
+ update: function(position) {
336
+ this.method(position);
337
+ }
338
+ });
339
+
340
+ Effect.Event = Class.create(Effect.Base, {
341
+ initialize: function() {
342
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
343
+ },
344
+ update: Prototype.emptyFunction
345
+ });
346
+
347
+ Effect.Opacity = Class.create(Effect.Base, {
306
348
  initialize: function(element) {
307
349
  this.element = $(element);
350
+ if (!this.element) throw(Effect._elementDoesNotExistError);
308
351
  // make this work on IE on elements without 'layout'
309
- if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
310
- Element.setStyle(this.element, {zoom: 1});
352
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
353
+ this.element.setStyle({zoom: 1});
311
354
  var options = Object.extend({
312
- from: Element.getOpacity(this.element) || 0.0,
355
+ from: this.element.getOpacity() || 0.0,
313
356
  to: 1.0
314
- }, arguments[1] || {});
357
+ }, arguments[1] || { });
315
358
  this.start(options);
316
359
  },
317
360
  update: function(position) {
318
- Element.setOpacity(this.element, position);
361
+ this.element.setOpacity(position);
319
362
  }
320
363
  });
321
364
 
322
- Effect.MoveBy = Class.create();
323
- Object.extend(Object.extend(Effect.MoveBy.prototype, Effect.Base.prototype), {
324
- initialize: function(element, toTop, toLeft) {
325
- this.element = $(element);
326
- this.toTop = toTop;
327
- this.toLeft = toLeft;
328
- this.start(arguments[3]);
365
+ Effect.Move = Class.create(Effect.Base, {
366
+ initialize: function(element) {
367
+ this.element = $(element);
368
+ if (!this.element) throw(Effect._elementDoesNotExistError);
369
+ var options = Object.extend({
370
+ x: 0,
371
+ y: 0,
372
+ mode: 'relative'
373
+ }, arguments[1] || { });
374
+ this.start(options);
329
375
  },
330
376
  setup: function() {
331
- // Bug in Opera: Opera returns the "real" position of a static element or
332
- // relative element that does not have top/left explicitly set.
333
- // ==> Always set top and left for position relative elements in your stylesheets
334
- // (to 0 if you do not need them)
335
- Element.makePositioned(this.element);
336
- this.originalTop = parseFloat(Element.getStyle(this.element,'top') || '0');
337
- this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0');
377
+ this.element.makePositioned();
378
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
379
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
380
+ if (this.options.mode == 'absolute') {
381
+ this.options.x = this.options.x - this.originalLeft;
382
+ this.options.y = this.options.y - this.originalTop;
383
+ }
338
384
  },
339
385
  update: function(position) {
340
- Element.setStyle(this.element, {
341
- top: this.toTop * position + this.originalTop + 'px',
342
- left: this.toLeft * position + this.originalLeft + 'px'
386
+ this.element.setStyle({
387
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
388
+ top: (this.options.y * position + this.originalTop).round() + 'px'
343
389
  });
344
390
  }
345
391
  });
346
392
 
347
- Effect.Scale = Class.create();
348
- Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
393
+ // for backwards compatibility
394
+ Effect.MoveBy = function(element, toTop, toLeft) {
395
+ return new Effect.Move(element,
396
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
397
+ };
398
+
399
+ Effect.Scale = Class.create(Effect.Base, {
349
400
  initialize: function(element, percent) {
350
- this.element = $(element)
401
+ this.element = $(element);
402
+ if (!this.element) throw(Effect._elementDoesNotExistError);
351
403
  var options = Object.extend({
352
404
  scaleX: true,
353
405
  scaleY: true,
354
406
  scaleContent: true,
355
407
  scaleFromCenter: false,
356
- scaleMode: 'box', // 'box' or 'contents' or {} with provided values
408
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
357
409
  scaleFrom: 100.0,
358
410
  scaleTo: percent
359
- }, arguments[2] || {});
411
+ }, arguments[2] || { });
360
412
  this.start(options);
361
413
  },
362
414
  setup: function() {
363
415
  this.restoreAfterFinish = this.options.restoreAfterFinish || false;
364
- this.elementPositioning = Element.getStyle(this.element,'position');
416
+ this.elementPositioning = this.element.getStyle('position');
365
417
 
366
- this.originalStyle = {};
418
+ this.originalStyle = { };
367
419
  ['top','left','width','height','fontSize'].each( function(k) {
368
420
  this.originalStyle[k] = this.element.style[k];
369
421
  }.bind(this));
@@ -371,9 +423,9 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
371
423
  this.originalTop = this.element.offsetTop;
372
424
  this.originalLeft = this.element.offsetLeft;
373
425
 
374
- var fontSize = Element.getStyle(this.element,'font-size') || '100%';
375
- ['em','px','%'].each( function(fontSizeType) {
376
- if(fontSize.indexOf(fontSizeType)>0) {
426
+ var fontSize = this.element.getStyle('font-size') || '100%';
427
+ ['em','px','%','pt'].each( function(fontSizeType) {
428
+ if (fontSize.indexOf(fontSizeType)>0) {
377
429
  this.fontSize = parseFloat(fontSize);
378
430
  this.fontSizeType = fontSizeType;
379
431
  }
@@ -382,183 +434,184 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
382
434
  this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
383
435
 
384
436
  this.dims = null;
385
- if(this.options.scaleMode=='box')
437
+ if (this.options.scaleMode=='box')
386
438
  this.dims = [this.element.offsetHeight, this.element.offsetWidth];
387
- if(/^content/.test(this.options.scaleMode))
439
+ if (/^content/.test(this.options.scaleMode))
388
440
  this.dims = [this.element.scrollHeight, this.element.scrollWidth];
389
- if(!this.dims)
441
+ if (!this.dims)
390
442
  this.dims = [this.options.scaleMode.originalHeight,
391
443
  this.options.scaleMode.originalWidth];
392
444
  },
393
445
  update: function(position) {
394
446
  var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
395
- if(this.options.scaleContent && this.fontSize)
396
- Element.setStyle(this.element, {fontSize: this.fontSize * currentScale + this.fontSizeType });
447
+ if (this.options.scaleContent && this.fontSize)
448
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
397
449
  this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
398
450
  },
399
451
  finish: function(position) {
400
- if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle);
452
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
401
453
  },
402
454
  setDimensions: function(height, width) {
403
- var d = {};
404
- if(this.options.scaleX) d.width = width + 'px';
405
- if(this.options.scaleY) d.height = height + 'px';
406
- if(this.options.scaleFromCenter) {
455
+ var d = { };
456
+ if (this.options.scaleX) d.width = width.round() + 'px';
457
+ if (this.options.scaleY) d.height = height.round() + 'px';
458
+ if (this.options.scaleFromCenter) {
407
459
  var topd = (height - this.dims[0])/2;
408
460
  var leftd = (width - this.dims[1])/2;
409
- if(this.elementPositioning == 'absolute') {
410
- if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
411
- if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
461
+ if (this.elementPositioning == 'absolute') {
462
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
463
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
412
464
  } else {
413
- if(this.options.scaleY) d.top = -topd + 'px';
414
- if(this.options.scaleX) d.left = -leftd + 'px';
465
+ if (this.options.scaleY) d.top = -topd + 'px';
466
+ if (this.options.scaleX) d.left = -leftd + 'px';
415
467
  }
416
468
  }
417
- Element.setStyle(this.element, d);
469
+ this.element.setStyle(d);
418
470
  }
419
471
  });
420
472
 
421
- Effect.Highlight = Class.create();
422
- Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
473
+ Effect.Highlight = Class.create(Effect.Base, {
423
474
  initialize: function(element) {
424
475
  this.element = $(element);
425
- var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
476
+ if (!this.element) throw(Effect._elementDoesNotExistError);
477
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
426
478
  this.start(options);
427
479
  },
428
480
  setup: function() {
429
481
  // Prevent executing on elements not in the layout flow
430
- if(Element.getStyle(this.element, 'display')=='none') { this.cancel(); return; }
482
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
431
483
  // Disable background image during the effect
432
- this.oldStyle = {
433
- backgroundImage: Element.getStyle(this.element, 'background-image') };
434
- Element.setStyle(this.element, {backgroundImage: 'none'});
435
- if(!this.options.endcolor)
436
- this.options.endcolor = Element.getStyle(this.element, 'background-color').parseColor('#ffffff');
437
- if(!this.options.restorecolor)
438
- this.options.restorecolor = Element.getStyle(this.element, 'background-color');
484
+ this.oldStyle = { };
485
+ if (!this.options.keepBackgroundImage) {
486
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
487
+ this.element.setStyle({backgroundImage: 'none'});
488
+ }
489
+ if (!this.options.endcolor)
490
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
491
+ if (!this.options.restorecolor)
492
+ this.options.restorecolor = this.element.getStyle('background-color');
439
493
  // init color calculations
440
494
  this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
441
495
  this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
442
496
  },
443
497
  update: function(position) {
444
- Element.setStyle(this.element,{backgroundColor: $R(0,2).inject('#',function(m,v,i){
445
- return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
498
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
499
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
446
500
  },
447
501
  finish: function() {
448
- Element.setStyle(this.element, Object.extend(this.oldStyle, {
502
+ this.element.setStyle(Object.extend(this.oldStyle, {
449
503
  backgroundColor: this.options.restorecolor
450
504
  }));
451
505
  }
452
506
  });
453
507
 
454
- Effect.ScrollTo = Class.create();
455
- Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
456
- initialize: function(element) {
457
- this.element = $(element);
458
- this.start(arguments[1] || {});
459
- },
460
- setup: function() {
461
- Position.prepare();
462
- var offsets = Position.cumulativeOffset(this.element);
463
- if(this.options.offset) offsets[1] += this.options.offset;
464
- var max = window.innerHeight ?
465
- window.height - window.innerHeight :
466
- document.body.scrollHeight -
467
- (document.documentElement.clientHeight ?
468
- document.documentElement.clientHeight : document.body.clientHeight);
469
- this.scrollStart = Position.deltaY;
470
- this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
471
- },
472
- update: function(position) {
473
- Position.prepare();
474
- window.scrollTo(Position.deltaX,
475
- this.scrollStart + (position*this.delta));
476
- }
477
- });
508
+ Effect.ScrollTo = function(element) {
509
+ var options = arguments[1] || { },
510
+ scrollOffsets = document.viewport.getScrollOffsets(),
511
+ elementOffsets = $(element).cumulativeOffset(),
512
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
513
+
514
+ if (options.offset) elementOffsets[1] += options.offset;
515
+
516
+ return new Effect.Tween(null,
517
+ scrollOffsets.top,
518
+ elementOffsets[1] > max ? max : elementOffsets[1],
519
+ options,
520
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
521
+ );
522
+ };
478
523
 
479
524
  /* ------------- combination effects ------------- */
480
525
 
481
526
  Effect.Fade = function(element) {
482
- var oldOpacity = Element.getInlineOpacity(element);
527
+ element = $(element);
528
+ var oldOpacity = element.getInlineOpacity();
483
529
  var options = Object.extend({
484
- from: Element.getOpacity(element) || 1.0,
485
- to: 0.0,
486
- afterFinishInternal: function(effect) { with(Element) {
487
- if(effect.options.to!=0) return;
488
- hide(effect.element);
489
- setStyle(effect.element, {opacity: oldOpacity}); }}
490
- }, arguments[1] || {});
530
+ from: element.getOpacity() || 1.0,
531
+ to: 0.0,
532
+ afterFinishInternal: function(effect) {
533
+ if (effect.options.to!=0) return;
534
+ effect.element.hide().setStyle({opacity: oldOpacity});
535
+ }
536
+ }, arguments[1] || { });
491
537
  return new Effect.Opacity(element,options);
492
- }
538
+ };
493
539
 
494
540
  Effect.Appear = function(element) {
541
+ element = $(element);
495
542
  var options = Object.extend({
496
- from: (Element.getStyle(element, 'display') == 'none' ? 0.0 : Element.getOpacity(element) || 0.0),
543
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
497
544
  to: 1.0,
498
- beforeSetup: function(effect) { with(Element) {
499
- setOpacity(effect.element, effect.options.from);
500
- show(effect.element); }}
501
- }, arguments[1] || {});
545
+ // force Safari to render floated elements properly
546
+ afterFinishInternal: function(effect) {
547
+ effect.element.forceRerendering();
548
+ },
549
+ beforeSetup: function(effect) {
550
+ effect.element.setOpacity(effect.options.from).show();
551
+ }}, arguments[1] || { });
502
552
  return new Effect.Opacity(element,options);
503
- }
553
+ };
504
554
 
505
555
  Effect.Puff = function(element) {
506
556
  element = $(element);
507
- var oldStyle = { opacity: Element.getInlineOpacity(element), position: Element.getStyle(element, 'position') };
557
+ var oldStyle = {
558
+ opacity: element.getInlineOpacity(),
559
+ position: element.getStyle('position'),
560
+ top: element.style.top,
561
+ left: element.style.left,
562
+ width: element.style.width,
563
+ height: element.style.height
564
+ };
508
565
  return new Effect.Parallel(
509
566
  [ new Effect.Scale(element, 200,
510
567
  { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
511
568
  new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
512
569
  Object.extend({ duration: 1.0,
513
- beforeSetupInternal: function(effect) { with(Element) {
514
- setStyle(effect.effects[0].element, {position: 'absolute'}); }},
515
- afterFinishInternal: function(effect) { with(Element) {
516
- hide(effect.effects[0].element);
517
- setStyle(effect.effects[0].element, oldStyle); }}
518
- }, arguments[1] || {})
570
+ beforeSetupInternal: function(effect) {
571
+ Position.absolutize(effect.effects[0].element)
572
+ },
573
+ afterFinishInternal: function(effect) {
574
+ effect.effects[0].element.hide().setStyle(oldStyle); }
575
+ }, arguments[1] || { })
519
576
  );
520
- }
577
+ };
521
578
 
522
579
  Effect.BlindUp = function(element) {
523
580
  element = $(element);
524
- Element.makeClipping(element);
525
- return new Effect.Scale(element, 0,
581
+ element.makeClipping();
582
+ return new Effect.Scale(element, 0,
526
583
  Object.extend({ scaleContent: false,
527
584
  scaleX: false,
528
585
  restoreAfterFinish: true,
529
- afterFinishInternal: function(effect) { with(Element) {
530
- [hide, undoClipping].call(effect.element); }}
531
- }, arguments[1] || {})
586
+ afterFinishInternal: function(effect) {
587
+ effect.element.hide().undoClipping();
588
+ }
589
+ }, arguments[1] || { })
532
590
  );
533
- }
591
+ };
534
592
 
535
593
  Effect.BlindDown = function(element) {
536
594
  element = $(element);
537
- var oldHeight = Element.getStyle(element, 'height');
538
- var elementDimensions = Element.getDimensions(element);
539
- return new Effect.Scale(element, 100,
540
- Object.extend({ scaleContent: false,
541
- scaleX: false,
542
- scaleFrom: 0,
543
- scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
544
- restoreAfterFinish: true,
545
- afterSetup: function(effect) { with(Element) {
546
- makeClipping(effect.element);
547
- setStyle(effect.element, {height: '0px'});
548
- show(effect.element);
549
- }},
550
- afterFinishInternal: function(effect) { with(Element) {
551
- undoClipping(effect.element);
552
- setStyle(effect.element, {height: oldHeight});
553
- }}
554
- }, arguments[1] || {})
555
- );
556
- }
595
+ var elementDimensions = element.getDimensions();
596
+ return new Effect.Scale(element, 100, Object.extend({
597
+ scaleContent: false,
598
+ scaleX: false,
599
+ scaleFrom: 0,
600
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
601
+ restoreAfterFinish: true,
602
+ afterSetup: function(effect) {
603
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
604
+ },
605
+ afterFinishInternal: function(effect) {
606
+ effect.element.undoClipping();
607
+ }
608
+ }, arguments[1] || { }));
609
+ };
557
610
 
558
611
  Effect.SwitchOff = function(element) {
559
612
  element = $(element);
560
- var oldOpacity = Element.getInlineOpacity(element);
561
- return new Effect.Appear(element, {
613
+ var oldOpacity = element.getInlineOpacity();
614
+ return new Effect.Appear(element, Object.extend({
562
615
  duration: 0.4,
563
616
  from: 0,
564
617
  transition: Effect.Transitions.flicker,
@@ -566,146 +619,150 @@ Effect.SwitchOff = function(element) {
566
619
  new Effect.Scale(effect.element, 1, {
567
620
  duration: 0.3, scaleFromCenter: true,
568
621
  scaleX: false, scaleContent: false, restoreAfterFinish: true,
569
- beforeSetup: function(effect) { with(Element) {
570
- [makePositioned,makeClipping].call(effect.element);
571
- }},
572
- afterFinishInternal: function(effect) { with(Element) {
573
- [hide,undoClipping,undoPositioned].call(effect.element);
574
- setStyle(effect.element, {opacity: oldOpacity});
575
- }}
622
+ beforeSetup: function(effect) {
623
+ effect.element.makePositioned().makeClipping();
624
+ },
625
+ afterFinishInternal: function(effect) {
626
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
627
+ }
576
628
  })
577
629
  }
578
- });
579
- }
630
+ }, arguments[1] || { }));
631
+ };
580
632
 
581
633
  Effect.DropOut = function(element) {
582
634
  element = $(element);
583
635
  var oldStyle = {
584
- top: Element.getStyle(element, 'top'),
585
- left: Element.getStyle(element, 'left'),
586
- opacity: Element.getInlineOpacity(element) };
636
+ top: element.getStyle('top'),
637
+ left: element.getStyle('left'),
638
+ opacity: element.getInlineOpacity() };
587
639
  return new Effect.Parallel(
588
- [ new Effect.MoveBy(element, 100, 0, { sync: true }),
640
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
589
641
  new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
590
642
  Object.extend(
591
643
  { duration: 0.5,
592
- beforeSetup: function(effect) { with(Element) {
593
- makePositioned(effect.effects[0].element); }},
594
- afterFinishInternal: function(effect) { with(Element) {
595
- [hide, undoPositioned].call(effect.effects[0].element);
596
- setStyle(effect.effects[0].element, oldStyle); }}
597
- }, arguments[1] || {}));
598
- }
644
+ beforeSetup: function(effect) {
645
+ effect.effects[0].element.makePositioned();
646
+ },
647
+ afterFinishInternal: function(effect) {
648
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
649
+ }
650
+ }, arguments[1] || { }));
651
+ };
599
652
 
600
653
  Effect.Shake = function(element) {
601
654
  element = $(element);
655
+ var options = Object.extend({
656
+ distance: 20,
657
+ duration: 0.5
658
+ }, arguments[1] || {});
659
+ var distance = parseFloat(options.distance);
660
+ var split = parseFloat(options.duration) / 10.0;
602
661
  var oldStyle = {
603
- top: Element.getStyle(element, 'top'),
604
- left: Element.getStyle(element, 'left') };
605
- return new Effect.MoveBy(element, 0, 20,
606
- { duration: 0.05, afterFinishInternal: function(effect) {
607
- new Effect.MoveBy(effect.element, 0, -40,
608
- { duration: 0.1, afterFinishInternal: function(effect) {
609
- new Effect.MoveBy(effect.element, 0, 40,
610
- { duration: 0.1, afterFinishInternal: function(effect) {
611
- new Effect.MoveBy(effect.element, 0, -40,
612
- { duration: 0.1, afterFinishInternal: function(effect) {
613
- new Effect.MoveBy(effect.element, 0, 40,
614
- { duration: 0.1, afterFinishInternal: function(effect) {
615
- new Effect.MoveBy(effect.element, 0, -20,
616
- { duration: 0.05, afterFinishInternal: function(effect) { with(Element) {
617
- undoPositioned(effect.element);
618
- setStyle(effect.element, oldStyle);
619
- }}}) }}) }}) }}) }}) }});
620
- }
662
+ top: element.getStyle('top'),
663
+ left: element.getStyle('left') };
664
+ return new Effect.Move(element,
665
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
666
+ new Effect.Move(effect.element,
667
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
668
+ new Effect.Move(effect.element,
669
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
670
+ new Effect.Move(effect.element,
671
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
672
+ new Effect.Move(effect.element,
673
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
674
+ new Effect.Move(effect.element,
675
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
676
+ effect.element.undoPositioned().setStyle(oldStyle);
677
+ }}) }}) }}) }}) }}) }});
678
+ };
621
679
 
622
680
  Effect.SlideDown = function(element) {
623
- element = $(element);
624
- Element.cleanWhitespace(element);
681
+ element = $(element).cleanWhitespace();
625
682
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
626
- var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
627
- var elementDimensions = Element.getDimensions(element);
683
+ var oldInnerBottom = element.down().getStyle('bottom');
684
+ var elementDimensions = element.getDimensions();
628
685
  return new Effect.Scale(element, 100, Object.extend({
629
686
  scaleContent: false,
630
687
  scaleX: false,
631
- scaleFrom: 0,
688
+ scaleFrom: window.opera ? 0 : 1,
632
689
  scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
633
690
  restoreAfterFinish: true,
634
- afterSetup: function(effect) { with(Element) {
635
- makePositioned(effect.element);
636
- makePositioned(effect.element.firstChild);
637
- if(window.opera) setStyle(effect.element, {top: ''});
638
- makeClipping(effect.element);
639
- setStyle(effect.element, {height: '0px'});
640
- show(element); }},
641
- afterUpdateInternal: function(effect) { with(Element) {
642
- setStyle(effect.element.firstChild, {bottom:
643
- (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
644
- afterFinishInternal: function(effect) { with(Element) {
645
- undoClipping(effect.element);
646
- undoPositioned(effect.element.firstChild);
647
- undoPositioned(effect.element);
648
- setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
649
- }, arguments[1] || {})
691
+ afterSetup: function(effect) {
692
+ effect.element.makePositioned();
693
+ effect.element.down().makePositioned();
694
+ if (window.opera) effect.element.setStyle({top: ''});
695
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
696
+ },
697
+ afterUpdateInternal: function(effect) {
698
+ effect.element.down().setStyle({bottom:
699
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
700
+ },
701
+ afterFinishInternal: function(effect) {
702
+ effect.element.undoClipping().undoPositioned();
703
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
704
+ }, arguments[1] || { })
650
705
  );
651
- }
652
-
706
+ };
707
+
653
708
  Effect.SlideUp = function(element) {
654
- element = $(element);
655
- Element.cleanWhitespace(element);
656
- var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
657
- return new Effect.Scale(element, 0,
709
+ element = $(element).cleanWhitespace();
710
+ var oldInnerBottom = element.down().getStyle('bottom');
711
+ var elementDimensions = element.getDimensions();
712
+ return new Effect.Scale(element, window.opera ? 0 : 1,
658
713
  Object.extend({ scaleContent: false,
659
714
  scaleX: false,
660
715
  scaleMode: 'box',
661
716
  scaleFrom: 100,
717
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
662
718
  restoreAfterFinish: true,
663
- beforeStartInternal: function(effect) { with(Element) {
664
- makePositioned(effect.element);
665
- makePositioned(effect.element.firstChild);
666
- if(window.opera) setStyle(effect.element, {top: ''});
667
- makeClipping(effect.element);
668
- show(element); }},
669
- afterUpdateInternal: function(effect) { with(Element) {
670
- setStyle(effect.element.firstChild, {bottom:
671
- (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
672
- afterFinishInternal: function(effect) { with(Element) {
673
- [hide, undoClipping].call(effect.element);
674
- undoPositioned(effect.element.firstChild);
675
- undoPositioned(effect.element);
676
- setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
677
- }, arguments[1] || {})
719
+ afterSetup: function(effect) {
720
+ effect.element.makePositioned();
721
+ effect.element.down().makePositioned();
722
+ if (window.opera) effect.element.setStyle({top: ''});
723
+ effect.element.makeClipping().show();
724
+ },
725
+ afterUpdateInternal: function(effect) {
726
+ effect.element.down().setStyle({bottom:
727
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
728
+ },
729
+ afterFinishInternal: function(effect) {
730
+ effect.element.hide().undoClipping().undoPositioned();
731
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
732
+ }
733
+ }, arguments[1] || { })
678
734
  );
679
- }
735
+ };
680
736
 
681
737
  // Bug in opera makes the TD containing this element expand for a instance after finish
682
738
  Effect.Squish = function(element) {
683
- return new Effect.Scale(element, window.opera ? 1 : 0,
684
- { restoreAfterFinish: true,
685
- beforeSetup: function(effect) { with(Element) {
686
- makeClipping(effect.element); }},
687
- afterFinishInternal: function(effect) { with(Element) {
688
- hide(effect.element);
689
- undoClipping(effect.element); }}
739
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
740
+ restoreAfterFinish: true,
741
+ beforeSetup: function(effect) {
742
+ effect.element.makeClipping();
743
+ },
744
+ afterFinishInternal: function(effect) {
745
+ effect.element.hide().undoClipping();
746
+ }
690
747
  });
691
- }
748
+ };
692
749
 
693
750
  Effect.Grow = function(element) {
694
751
  element = $(element);
695
752
  var options = Object.extend({
696
753
  direction: 'center',
697
- moveTransistion: Effect.Transitions.sinoidal,
754
+ moveTransition: Effect.Transitions.sinoidal,
698
755
  scaleTransition: Effect.Transitions.sinoidal,
699
756
  opacityTransition: Effect.Transitions.full
700
- }, arguments[1] || {});
757
+ }, arguments[1] || { });
701
758
  var oldStyle = {
702
759
  top: element.style.top,
703
760
  left: element.style.left,
704
761
  height: element.style.height,
705
762
  width: element.style.width,
706
- opacity: Element.getInlineOpacity(element) };
763
+ opacity: element.getInlineOpacity() };
707
764
 
708
- var dims = Element.getDimensions(element);
765
+ var dims = element.getDimensions();
709
766
  var initialMoveX, initialMoveY;
710
767
  var moveX, moveY;
711
768
 
@@ -737,49 +794,49 @@ Effect.Grow = function(element) {
737
794
  break;
738
795
  }
739
796
 
740
- return new Effect.MoveBy(element, initialMoveY, initialMoveX, {
797
+ return new Effect.Move(element, {
798
+ x: initialMoveX,
799
+ y: initialMoveY,
741
800
  duration: 0.01,
742
- beforeSetup: function(effect) { with(Element) {
743
- hide(effect.element);
744
- makeClipping(effect.element);
745
- makePositioned(effect.element);
746
- }},
801
+ beforeSetup: function(effect) {
802
+ effect.element.hide().makeClipping().makePositioned();
803
+ },
747
804
  afterFinishInternal: function(effect) {
748
805
  new Effect.Parallel(
749
806
  [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
750
- new Effect.MoveBy(effect.element, moveY, moveX, { sync: true, transition: options.moveTransition }),
807
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
751
808
  new Effect.Scale(effect.element, 100, {
752
809
  scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
753
810
  sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
754
811
  ], Object.extend({
755
- beforeSetup: function(effect) { with(Element) {
756
- setStyle(effect.effects[0].element, {height: '0px'});
757
- show(effect.effects[0].element); }},
758
- afterFinishInternal: function(effect) { with(Element) {
759
- [undoClipping, undoPositioned].call(effect.effects[0].element);
760
- setStyle(effect.effects[0].element, oldStyle); }}
812
+ beforeSetup: function(effect) {
813
+ effect.effects[0].element.setStyle({height: '0px'}).show();
814
+ },
815
+ afterFinishInternal: function(effect) {
816
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
817
+ }
761
818
  }, options)
762
819
  )
763
820
  }
764
821
  });
765
- }
822
+ };
766
823
 
767
824
  Effect.Shrink = function(element) {
768
825
  element = $(element);
769
826
  var options = Object.extend({
770
827
  direction: 'center',
771
- moveTransistion: Effect.Transitions.sinoidal,
828
+ moveTransition: Effect.Transitions.sinoidal,
772
829
  scaleTransition: Effect.Transitions.sinoidal,
773
830
  opacityTransition: Effect.Transitions.none
774
- }, arguments[1] || {});
831
+ }, arguments[1] || { });
775
832
  var oldStyle = {
776
833
  top: element.style.top,
777
834
  left: element.style.left,
778
835
  height: element.style.height,
779
836
  width: element.style.width,
780
- opacity: Element.getInlineOpacity(element) };
837
+ opacity: element.getInlineOpacity() };
781
838
 
782
- var dims = Element.getDimensions(element);
839
+ var dims = element.getDimensions();
783
840
  var moveX, moveY;
784
841
 
785
842
  switch (options.direction) {
@@ -807,29 +864,29 @@ Effect.Shrink = function(element) {
807
864
  return new Effect.Parallel(
808
865
  [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
809
866
  new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
810
- new Effect.MoveBy(element, moveY, moveX, { sync: true, transition: options.moveTransition })
867
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
811
868
  ], Object.extend({
812
- beforeStartInternal: function(effect) { with(Element) {
813
- [makePositioned, makeClipping].call(effect.effects[0].element) }},
814
- afterFinishInternal: function(effect) { with(Element) {
815
- [hide, undoClipping, undoPositioned].call(effect.effects[0].element);
816
- setStyle(effect.effects[0].element, oldStyle); }}
869
+ beforeStartInternal: function(effect) {
870
+ effect.effects[0].element.makePositioned().makeClipping();
871
+ },
872
+ afterFinishInternal: function(effect) {
873
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
817
874
  }, options)
818
875
  );
819
- }
876
+ };
820
877
 
821
878
  Effect.Pulsate = function(element) {
822
879
  element = $(element);
823
- var options = arguments[1] || {};
824
- var oldOpacity = Element.getInlineOpacity(element);
880
+ var options = arguments[1] || { };
881
+ var oldOpacity = element.getInlineOpacity();
825
882
  var transition = options.transition || Effect.Transitions.sinoidal;
826
- var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
883
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
827
884
  reverser.bind(transition);
828
885
  return new Effect.Opacity(element,
829
- Object.extend(Object.extend({ duration: 3.0, from: 0,
830
- afterFinishInternal: function(effect) { Element.setStyle(effect.element, {opacity: oldOpacity}); }
886
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
887
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
831
888
  }, options), {transition: reverser}));
832
- }
889
+ };
833
890
 
834
891
  Effect.Fold = function(element) {
835
892
  element = $(element);
@@ -838,7 +895,7 @@ Effect.Fold = function(element) {
838
895
  left: element.style.left,
839
896
  width: element.style.width,
840
897
  height: element.style.height };
841
- Element.makeClipping(element);
898
+ element.makeClipping();
842
899
  return new Effect.Scale(element, 5, Object.extend({
843
900
  scaleContent: false,
844
901
  scaleX: false,
@@ -846,9 +903,218 @@ Effect.Fold = function(element) {
846
903
  new Effect.Scale(element, 1, {
847
904
  scaleContent: false,
848
905
  scaleY: false,
849
- afterFinishInternal: function(effect) { with(Element) {
850
- [hide, undoClipping].call(effect.element);
851
- setStyle(effect.element, oldStyle);
852
- }} });
853
- }}, arguments[1] || {}));
854
- }
906
+ afterFinishInternal: function(effect) {
907
+ effect.element.hide().undoClipping().setStyle(oldStyle);
908
+ } });
909
+ }}, arguments[1] || { }));
910
+ };
911
+
912
+ Effect.Morph = Class.create(Effect.Base, {
913
+ initialize: function(element) {
914
+ this.element = $(element);
915
+ if (!this.element) throw(Effect._elementDoesNotExistError);
916
+ var options = Object.extend({
917
+ style: { }
918
+ }, arguments[1] || { });
919
+
920
+ if (!Object.isString(options.style)) this.style = $H(options.style);
921
+ else {
922
+ if (options.style.include(':'))
923
+ this.style = options.style.parseStyle();
924
+ else {
925
+ this.element.addClassName(options.style);
926
+ this.style = $H(this.element.getStyles());
927
+ this.element.removeClassName(options.style);
928
+ var css = this.element.getStyles();
929
+ this.style = this.style.reject(function(style) {
930
+ return style.value == css[style.key];
931
+ });
932
+ options.afterFinishInternal = function(effect) {
933
+ effect.element.addClassName(effect.options.style);
934
+ effect.transforms.each(function(transform) {
935
+ effect.element.style[transform.style] = '';
936
+ });
937
+ }
938
+ }
939
+ }
940
+ this.start(options);
941
+ },
942
+
943
+ setup: function(){
944
+ function parseColor(color){
945
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
946
+ color = color.parseColor();
947
+ return $R(0,2).map(function(i){
948
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
949
+ });
950
+ }
951
+ this.transforms = this.style.map(function(pair){
952
+ var property = pair[0], value = pair[1], unit = null;
953
+
954
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
955
+ value = value.parseColor();
956
+ unit = 'color';
957
+ } else if (property == 'opacity') {
958
+ value = parseFloat(value);
959
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
960
+ this.element.setStyle({zoom: 1});
961
+ } else if (Element.CSS_LENGTH.test(value)) {
962
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
963
+ value = parseFloat(components[1]);
964
+ unit = (components.length == 3) ? components[2] : null;
965
+ }
966
+
967
+ var originalValue = this.element.getStyle(property);
968
+ return {
969
+ style: property.camelize(),
970
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
971
+ targetValue: unit=='color' ? parseColor(value) : value,
972
+ unit: unit
973
+ };
974
+ }.bind(this)).reject(function(transform){
975
+ return (
976
+ (transform.originalValue == transform.targetValue) ||
977
+ (
978
+ transform.unit != 'color' &&
979
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
980
+ )
981
+ )
982
+ });
983
+ },
984
+ update: function(position) {
985
+ var style = { }, transform, i = this.transforms.length;
986
+ while(i--)
987
+ style[(transform = this.transforms[i]).style] =
988
+ transform.unit=='color' ? '#'+
989
+ (Math.round(transform.originalValue[0]+
990
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
991
+ (Math.round(transform.originalValue[1]+
992
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
993
+ (Math.round(transform.originalValue[2]+
994
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
995
+ (transform.originalValue +
996
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
997
+ (transform.unit === null ? '' : transform.unit);
998
+ this.element.setStyle(style, true);
999
+ }
1000
+ });
1001
+
1002
+ Effect.Transform = Class.create({
1003
+ initialize: function(tracks){
1004
+ this.tracks = [];
1005
+ this.options = arguments[1] || { };
1006
+ this.addTracks(tracks);
1007
+ },
1008
+ addTracks: function(tracks){
1009
+ tracks.each(function(track){
1010
+ track = $H(track);
1011
+ var data = track.values().first();
1012
+ this.tracks.push($H({
1013
+ ids: track.keys().first(),
1014
+ effect: Effect.Morph,
1015
+ options: { style: data }
1016
+ }));
1017
+ }.bind(this));
1018
+ return this;
1019
+ },
1020
+ play: function(){
1021
+ return new Effect.Parallel(
1022
+ this.tracks.map(function(track){
1023
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
1024
+ var elements = [$(ids) || $$(ids)].flatten();
1025
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
1026
+ }).flatten(),
1027
+ this.options
1028
+ );
1029
+ }
1030
+ });
1031
+
1032
+ Element.CSS_PROPERTIES = $w(
1033
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1034
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1035
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1036
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
1037
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
1038
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
1039
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1040
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1041
+ 'right textIndent top width wordSpacing zIndex');
1042
+
1043
+ Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1044
+
1045
+ String.__parseStyleElement = document.createElement('div');
1046
+ String.prototype.parseStyle = function(){
1047
+ var style, styleRules = $H();
1048
+ if (Prototype.Browser.WebKit)
1049
+ style = new Element('div',{style:this}).style;
1050
+ else {
1051
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
1052
+ style = String.__parseStyleElement.childNodes[0].style;
1053
+ }
1054
+
1055
+ Element.CSS_PROPERTIES.each(function(property){
1056
+ if (style[property]) styleRules.set(property, style[property]);
1057
+ });
1058
+
1059
+ if (Prototype.Browser.IE && this.include('opacity'))
1060
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
1061
+
1062
+ return styleRules;
1063
+ };
1064
+
1065
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1066
+ Element.getStyles = function(element) {
1067
+ var css = document.defaultView.getComputedStyle($(element), null);
1068
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
1069
+ styles[property] = css[property];
1070
+ return styles;
1071
+ });
1072
+ };
1073
+ } else {
1074
+ Element.getStyles = function(element) {
1075
+ element = $(element);
1076
+ var css = element.currentStyle, styles;
1077
+ styles = Element.CSS_PROPERTIES.inject({ }, function(hash, property) {
1078
+ hash.set(property, css[property]);
1079
+ return hash;
1080
+ });
1081
+ if (!styles.opacity) styles.set('opacity', element.getOpacity());
1082
+ return styles;
1083
+ };
1084
+ };
1085
+
1086
+ Effect.Methods = {
1087
+ morph: function(element, style) {
1088
+ element = $(element);
1089
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
1090
+ return element;
1091
+ },
1092
+ visualEffect: function(element, effect, options) {
1093
+ element = $(element)
1094
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
1095
+ new Effect[klass](element, options);
1096
+ return element;
1097
+ },
1098
+ highlight: function(element, options) {
1099
+ element = $(element);
1100
+ new Effect.Highlight(element, options);
1101
+ return element;
1102
+ }
1103
+ };
1104
+
1105
+ $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
1106
+ 'pulsate shake puff squish switchOff dropOut').each(
1107
+ function(effect) {
1108
+ Effect.Methods[effect] = function(element, options){
1109
+ element = $(element);
1110
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
1111
+ return element;
1112
+ }
1113
+ }
1114
+ );
1115
+
1116
+ $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1117
+ function(f) { Effect.Methods[f] = Element[f]; }
1118
+ );
1119
+
1120
+ Element.addMethods(Effect.Methods);