gettext 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (288) hide show
  1. data/ChangeLog +194 -0
  2. data/NEWS +49 -0
  3. data/README +28 -9
  4. data/Rakefile +54 -41
  5. data/bin/rgettext +2 -0
  6. data/bin/rmsgfmt +2 -0
  7. data/bin/rmsgmerge +24 -0
  8. data/data/locale/cs/LC_MESSAGES/rails.mo +0 -0
  9. data/data/locale/cs/LC_MESSAGES/rgettext.mo +0 -0
  10. data/data/locale/de/LC_MESSAGES/rails.mo +0 -0
  11. data/data/locale/de/LC_MESSAGES/rgettext.mo +0 -0
  12. data/data/locale/es/LC_MESSAGES/rails.mo +0 -0
  13. data/data/locale/es/LC_MESSAGES/rgettext.mo +0 -0
  14. data/data/locale/fr/LC_MESSAGES/rails.mo +0 -0
  15. data/data/locale/fr/LC_MESSAGES/rgettext.mo +0 -0
  16. data/data/locale/it/LC_MESSAGES/rgettext.mo +0 -0
  17. data/data/locale/ja/LC_MESSAGES/rails.mo +0 -0
  18. data/data/locale/ja/LC_MESSAGES/rgettext.mo +0 -0
  19. data/data/locale/ko/LC_MESSAGES/rails.mo +0 -0
  20. data/data/locale/ko/LC_MESSAGES/rgettext.mo +0 -0
  21. data/data/locale/nl/LC_MESSAGES/rails.mo +0 -0
  22. data/data/locale/nl/LC_MESSAGES/rgettext.mo +0 -0
  23. data/data/locale/pt_BR/LC_MESSAGES/rails.mo +0 -0
  24. data/data/locale/pt_BR/LC_MESSAGES/rgettext.mo +0 -0
  25. data/data/locale/sv/LC_MESSAGES/rgettext.mo +0 -0
  26. data/lib/gettext.rb +17 -4
  27. data/lib/gettext/cgi.rb +34 -19
  28. data/lib/gettext/locale.rb +3 -13
  29. data/lib/gettext/locale_default.rb +2 -2
  30. data/lib/gettext/locale_win32.rb +27 -7
  31. data/lib/gettext/mo.rb +6 -1
  32. data/lib/gettext/parser/activerecord.rb +115 -0
  33. data/lib/gettext/parser/glade.rb +3 -1
  34. data/lib/gettext/parser/ruby.rb +56 -57
  35. data/lib/gettext/poparser.rb +297 -0
  36. data/lib/gettext/rails.rb +161 -3
  37. data/lib/gettext/rgettext.rb +19 -9
  38. data/lib/gettext/rmsgfmt.rb +7 -275
  39. data/lib/gettext/rmsgmerge.rb +381 -0
  40. data/lib/gettext/string.rb +26 -0
  41. data/lib/gettext/textdomain.rb +21 -18
  42. data/lib/gettext/utils.rb +55 -0
  43. data/lib/gettext/version.rb +1 -1
  44. data/po/cs/rails.po +83 -0
  45. data/po/cs/rgettext.po +104 -0
  46. data/po/de/rails.po +79 -0
  47. data/po/de/rgettext.po +72 -21
  48. data/po/es/rails.po +80 -0
  49. data/po/es/rgettext.po +75 -19
  50. data/po/fr/rails.po +81 -0
  51. data/po/fr/rgettext.po +75 -19
  52. data/po/it/rgettext.po +68 -17
  53. data/po/ja/rails.po +78 -0
  54. data/po/ja/rgettext.po +71 -20
  55. data/po/ko/rails.po +77 -0
  56. data/po/ko/rgettext.po +74 -22
  57. data/po/nl/rails.po +80 -0
  58. data/po/nl/rgettext.po +102 -0
  59. data/po/pt_BR/rails.po +79 -0
  60. data/po/pt_BR/rgettext.po +77 -24
  61. data/po/rails.pot +80 -0
  62. data/po/rgettext.pot +63 -13
  63. data/po/sv/rgettext.po +63 -15
  64. data/samples/cgi/cookie.cgi +5 -0
  65. data/samples/cgi/helloerb1.cgi +4 -0
  66. data/samples/cgi/helloerb2.cgi +5 -0
  67. data/samples/cgi/index.cgi +5 -0
  68. data/samples/cgi/locale/cs/LC_MESSAGES/helloerb1.mo +0 -0
  69. data/samples/cgi/locale/cs/LC_MESSAGES/helloerb2.mo +0 -0
  70. data/samples/cgi/locale/cs/LC_MESSAGES/hellolib.mo +0 -0
  71. data/samples/cgi/locale/cs/LC_MESSAGES/main.mo +0 -0
  72. data/samples/cgi/locale/fr/LC_MESSAGES/main.mo +0 -0
  73. data/samples/cgi/locale/ko/LC_MESSAGES/helloerb1.mo +0 -0
  74. data/samples/cgi/locale/ko/LC_MESSAGES/helloerb2.mo +0 -0
  75. data/samples/cgi/locale/ko/LC_MESSAGES/hellolib.mo +0 -0
  76. data/samples/cgi/locale/ko/LC_MESSAGES/main.mo +0 -0
  77. data/samples/cgi/locale/nl/LC_MESSAGES/helloerb1.mo +0 -0
  78. data/samples/cgi/locale/nl/LC_MESSAGES/helloerb2.mo +0 -0
  79. data/samples/cgi/locale/nl/LC_MESSAGES/hellolib.mo +0 -0
  80. data/samples/cgi/locale/nl/LC_MESSAGES/main.mo +0 -0
  81. data/samples/cgi/locale/pt_BR/LC_MESSAGES/helloerb1.mo +0 -0
  82. data/samples/cgi/locale/pt_BR/LC_MESSAGES/helloerb2.mo +0 -0
  83. data/samples/cgi/locale/pt_BR/LC_MESSAGES/hellolib.mo +0 -0
  84. data/samples/cgi/locale/pt_BR/LC_MESSAGES/main.mo +0 -0
  85. data/samples/cgi/po/cs/helloerb1.po +66 -0
  86. data/samples/cgi/po/cs/helloerb2.po +52 -0
  87. data/samples/cgi/po/cs/hellolib.po +25 -0
  88. data/samples/cgi/po/cs/main.po +78 -0
  89. data/samples/cgi/po/fr/main.po +8 -8
  90. data/samples/cgi/po/ko/helloerb1.po +2 -3
  91. data/samples/cgi/po/ko/helloerb2.po +1 -2
  92. data/samples/cgi/po/ko/hellolib.po +1 -2
  93. data/samples/cgi/po/ko/main.po +2 -3
  94. data/samples/cgi/po/nl/helloerb1.po +60 -0
  95. data/samples/cgi/po/nl/helloerb2.po +52 -0
  96. data/samples/cgi/po/nl/hellolib.po +24 -0
  97. data/samples/cgi/po/nl/main.po +76 -0
  98. data/samples/cgi/po/pt_BR/helloerb1.po +59 -0
  99. data/samples/cgi/po/pt_BR/helloerb2.po +51 -0
  100. data/samples/cgi/po/pt_BR/hellolib.po +22 -0
  101. data/samples/cgi/po/pt_BR/main.po +75 -0
  102. data/samples/locale/cs/LC_MESSAGES/hello.mo +0 -0
  103. data/samples/locale/cs/LC_MESSAGES/hello2.mo +0 -0
  104. data/samples/locale/cs/LC_MESSAGES/hello_noop.mo +0 -0
  105. data/samples/locale/cs/LC_MESSAGES/hello_plural.mo +0 -0
  106. data/samples/locale/cs/LC_MESSAGES/helloglade2.mo +0 -0
  107. data/samples/locale/cs/LC_MESSAGES/hellogtk.mo +0 -0
  108. data/samples/locale/cs/LC_MESSAGES/hellotk.mo +0 -0
  109. data/samples/locale/fr/LC_MESSAGES/helloglade2.mo +0 -0
  110. data/samples/locale/ko/LC_MESSAGES/hello.mo +0 -0
  111. data/samples/locale/ko/LC_MESSAGES/hello2.mo +0 -0
  112. data/samples/locale/ko/LC_MESSAGES/hello_noop.mo +0 -0
  113. data/samples/locale/ko/LC_MESSAGES/hello_plural.mo +0 -0
  114. data/samples/locale/ko/LC_MESSAGES/helloglade2.mo +0 -0
  115. data/samples/locale/ko/LC_MESSAGES/hellogtk.mo +0 -0
  116. data/samples/locale/ko/LC_MESSAGES/hellotk.mo +0 -0
  117. data/samples/locale/nl/LC_MESSAGES/hello.mo +0 -0
  118. data/samples/locale/nl/LC_MESSAGES/hello2.mo +0 -0
  119. data/samples/locale/nl/LC_MESSAGES/hello_noop.mo +0 -0
  120. data/samples/locale/nl/LC_MESSAGES/hello_plural.mo +0 -0
  121. data/samples/locale/nl/LC_MESSAGES/helloglade2.mo +0 -0
  122. data/samples/locale/nl/LC_MESSAGES/hellogtk.mo +0 -0
  123. data/samples/locale/nl/LC_MESSAGES/hellotk.mo +0 -0
  124. data/samples/locale/pt_BR/LC_MESSAGES/hello.mo +0 -0
  125. data/samples/locale/pt_BR/LC_MESSAGES/hello2.mo +0 -0
  126. data/samples/locale/pt_BR/LC_MESSAGES/hello_noop.mo +0 -0
  127. data/samples/locale/pt_BR/LC_MESSAGES/hello_plural.mo +0 -0
  128. data/samples/locale/pt_BR/LC_MESSAGES/helloglade2.mo +0 -0
  129. data/samples/locale/pt_BR/LC_MESSAGES/hellogtk.mo +0 -0
  130. data/samples/locale/pt_BR/LC_MESSAGES/hellotk.mo +0 -0
  131. data/samples/po/cs/hello.po +23 -0
  132. data/samples/po/cs/hello2.po +31 -0
  133. data/samples/po/cs/hello_noop.po +27 -0
  134. data/samples/po/cs/hello_plural.po +26 -0
  135. data/samples/po/cs/helloglade2.po +37 -0
  136. data/samples/po/cs/hellogtk.po +23 -0
  137. data/samples/po/cs/hellotk.po +23 -0
  138. data/samples/po/fr/helloglade2.po +2 -2
  139. data/samples/po/hello.pot +1 -0
  140. data/samples/po/hello2.pot +1 -0
  141. data/samples/po/hello_noop.pot +2 -1
  142. data/samples/po/hello_plural.pot +6 -2
  143. data/samples/po/helloglade2.pot +8 -3
  144. data/samples/po/hellotk.pot +4 -0
  145. data/samples/po/ko/hello.po +1 -2
  146. data/samples/po/ko/hello2.po +1 -2
  147. data/samples/po/ko/hello_noop.po +1 -2
  148. data/samples/po/ko/hello_plural.po +1 -2
  149. data/samples/po/ko/helloglade2.po +2 -2
  150. data/samples/po/ko/hellogtk.po +1 -2
  151. data/samples/po/ko/hellotk.po +1 -2
  152. data/samples/po/nl/hello.po +24 -0
  153. data/samples/po/nl/hello2.po +32 -0
  154. data/samples/po/nl/hello_noop.po +28 -0
  155. data/samples/po/nl/hello_plural.po +26 -0
  156. data/samples/po/nl/helloglade2.po +31 -0
  157. data/samples/po/nl/hellogtk.po +24 -0
  158. data/samples/po/nl/hellotk.po +24 -0
  159. data/samples/po/pt_BR/hello.po +6 -5
  160. data/samples/po/pt_BR/hello2.po +6 -5
  161. data/samples/po/pt_BR/hello_noop.po +6 -5
  162. data/samples/po/pt_BR/hello_plural.po +6 -6
  163. data/samples/po/pt_BR/helloglade2.po +6 -5
  164. data/samples/po/pt_BR/hellogtk.po +6 -5
  165. data/samples/po/pt_BR/hellotk.po +6 -5
  166. data/samples/rails/README +21 -15
  167. data/samples/rails/Rakefile +10 -1
  168. data/samples/rails/app/controllers/application.rb +10 -18
  169. data/samples/rails/app/controllers/blog_controller.rb +1 -5
  170. data/samples/rails/app/helpers/blog_helper.rb +1 -1
  171. data/samples/rails/app/models/article.rb +15 -0
  172. data/samples/rails/app/views/blog/_form.rhtml +2 -2
  173. data/samples/rails/config/boot.rb +17 -0
  174. data/samples/rails/config/database.yml +5 -3
  175. data/samples/rails/config/environment.rb +40 -75
  176. data/samples/rails/config/environments/development.rb +12 -7
  177. data/samples/rails/config/environments/production.rb +17 -6
  178. data/samples/rails/config/environments/test.rb +8 -6
  179. data/samples/rails/locale/cs/LC_MESSAGES/blog.mo +0 -0
  180. data/samples/rails/locale/cs/LC_MESSAGES/gettext_plugin.mo +0 -0
  181. data/samples/rails/locale/de/LC_MESSAGES/blog.mo +0 -0
  182. data/samples/rails/locale/de/LC_MESSAGES/gettext_plugin.mo +0 -0
  183. data/samples/rails/locale/en/LC_MESSAGES/blog.mo +0 -0
  184. data/samples/rails/locale/es/LC_MESSAGES/blog.mo +0 -0
  185. data/samples/rails/locale/es/LC_MESSAGES/gettext_plugin.mo +0 -0
  186. data/samples/rails/locale/fr/LC_MESSAGES/blog.mo +0 -0
  187. data/samples/rails/locale/fr/LC_MESSAGES/{lang_helper.mo → gettext_plugin.mo} +0 -0
  188. data/samples/rails/locale/ja/LC_MESSAGES/blog.mo +0 -0
  189. data/samples/rails/locale/ja/LC_MESSAGES/{lang_helper.mo → gettext_plugin.mo} +0 -0
  190. data/samples/rails/locale/ko/LC_MESSAGES/blog.mo +0 -0
  191. data/samples/rails/locale/ko/LC_MESSAGES/gettext_plugin.mo +0 -0
  192. data/samples/rails/locale/nl/LC_MESSAGES/blog.mo +0 -0
  193. data/samples/rails/locale/nl/LC_MESSAGES/gettext_plugin.mo +0 -0
  194. data/samples/rails/locale/pt_BR/LC_MESSAGES/blog.mo +0 -0
  195. data/samples/rails/locale/pt_BR/LC_MESSAGES/gettext_plugin.mo +0 -0
  196. data/samples/rails/po/blog.pot +57 -37
  197. data/samples/rails/po/cs/blog.po +116 -0
  198. data/samples/rails/po/cs/gettext_plugin.po +29 -0
  199. data/samples/rails/po/de/blog.po +70 -51
  200. data/samples/rails/po/de/{lang_helper.po → gettext_plugin.po} +4 -5
  201. data/samples/rails/po/en/blog.po +111 -0
  202. data/samples/rails/po/es/blog.po +67 -47
  203. data/samples/rails/po/es/{lang_helper.po → gettext_plugin.po} +5 -5
  204. data/samples/rails/po/fr/blog.po +65 -45
  205. data/samples/rails/po/fr/{lang_helper.po → gettext_plugin.po} +4 -4
  206. data/samples/rails/po/{lang_helper.pot → gettext_plugin.pot} +4 -4
  207. data/samples/rails/po/ja/blog.po +64 -44
  208. data/samples/rails/po/ja/{lang_helper.po → gettext_plugin.po} +4 -4
  209. data/samples/rails/po/ko/blog.po +65 -46
  210. data/samples/rails/po/ko/{lang_helper.po → gettext_plugin.po} +5 -6
  211. data/samples/rails/po/nl/blog.po +115 -0
  212. data/samples/rails/po/nl/gettext_plugin.po +28 -0
  213. data/samples/rails/po/pt_BR/blog.po +109 -0
  214. data/samples/rails/po/pt_BR/gettext_plugin.po +27 -0
  215. data/samples/rails/public/images/rails.png +0 -0
  216. data/samples/rails/public/index.html +272 -71
  217. data/samples/rails/public/javascripts/controls.js +441 -166
  218. data/samples/rails/public/javascripts/dragdrop.js +261 -279
  219. data/samples/rails/public/javascripts/effects.js +657 -277
  220. data/samples/rails/public/javascripts/prototype.js +911 -223
  221. data/samples/rails/public/robots.txt +1 -0
  222. data/samples/rails/public/stylesheets/scaffold.css +1 -1
  223. data/samples/rails/script/about +3 -0
  224. data/samples/rails/script/breakpointer +3 -4
  225. data/samples/rails/script/console +3 -23
  226. data/samples/rails/script/destroy +3 -7
  227. data/samples/rails/script/generate +3 -7
  228. data/samples/rails/script/performance/benchmarker +3 -0
  229. data/samples/rails/script/performance/profiler +3 -0
  230. data/samples/rails/script/plugin +3 -0
  231. data/samples/rails/script/process/reaper +3 -0
  232. data/samples/rails/script/process/spawner +3 -0
  233. data/samples/rails/script/process/spinner +3 -0
  234. data/samples/rails/script/runner +3 -29
  235. data/samples/rails/script/server +3 -49
  236. data/samples/rails/vendor/plugins/gettext/init.rb +19 -0
  237. data/samples/rails/vendor/{lang_helper.rb → plugins/gettext/lib/gettext_plugin.rb} +15 -11
  238. data/src/poparser.ry +171 -0
  239. data/test/gettext_runner.rb +3 -1
  240. data/test/gettext_test.rb +56 -31
  241. data/test/gettext_test_cgi.rb +12 -0
  242. data/test/gettext_test_parser.rb +3 -0
  243. data/test/gettext_test_string.rb +14 -0
  244. data/test/locale/cr/LC_MESSAGES/plural.mo +0 -0
  245. data/test/locale/da/LC_MESSAGES/plural.mo +0 -0
  246. data/test/locale/da/LC_MESSAGES/plural_error.mo +0 -0
  247. data/test/locale/fr/LC_MESSAGES/plural.mo +0 -0
  248. data/test/locale/fr/LC_MESSAGES/plural_error.mo +0 -0
  249. data/test/locale/ir/LC_MESSAGES/plural.mo +0 -0
  250. data/test/locale/la/LC_MESSAGES/plural.mo +0 -0
  251. data/test/locale/li/LC_MESSAGES/plural.mo +0 -0
  252. data/test/locale/po/LC_MESSAGES/plural.mo +0 -0
  253. data/test/locale/sl/LC_MESSAGES/plural.mo +0 -0
  254. data/test/po/cr/plural.po +3 -3
  255. data/test/po/da/plural.po +2 -2
  256. data/test/po/da/plural_error.po +2 -1
  257. data/test/po/fr/plural.po +2 -2
  258. data/test/po/fr/plural_error.po +2 -1
  259. data/test/po/ir/plural.po +3 -3
  260. data/test/po/la/plural.po +3 -3
  261. data/test/po/li/plural.po +3 -3
  262. data/test/po/po/plural.po +3 -3
  263. data/test/po/sl/plural.po +4 -4
  264. data/test/test.sh +1 -0
  265. data/test/test_rubyparser.rb +20 -0
  266. metadata +678 -551
  267. data/README.ja +0 -115
  268. data/data/locale/de/LC_MESSAGES/rmsgfmt.mo +0 -0
  269. data/data/locale/es/LC_MESSAGES/rmsgfmt.mo +0 -0
  270. data/data/locale/fr/LC_MESSAGES/rmsgfmt.mo +0 -0
  271. data/data/locale/it/LC_MESSAGES/rmsgfmt.mo +0 -0
  272. data/data/locale/ja/LC_MESSAGES/rmsgfmt.mo +0 -0
  273. data/data/locale/ko/LC_MESSAGES/rmsgfmt.mo +0 -0
  274. data/data/locale/pt_BR/LC_MESSAGES/rmsgfmt.mo +0 -0
  275. data/data/locale/sv/LC_MESSAGES/rmsgfmt.mo +0 -0
  276. data/po/de/rmsgfmt.po +0 -45
  277. data/po/es/rmsgfmt.po +0 -43
  278. data/po/fr/rmsgfmt.po +0 -43
  279. data/po/it/rmsgfmt.po +0 -44
  280. data/po/ja/rmsgfmt.po +0 -43
  281. data/po/ko/rmsgfmt.po +0 -40
  282. data/po/pt_BR/rmsgfmt.po +0 -42
  283. data/po/rmsgfmt.pot +0 -40
  284. data/po/sv/rmsgfmt.po +0 -43
  285. data/samples/rails/locale/de/LC_MESSAGES/lang_helper.mo +0 -0
  286. data/samples/rails/locale/es/LC_MESSAGES/lang_helper.mo +0 -0
  287. data/samples/rails/locale/ko/LC_MESSAGES/lang_helper.mo +0 -0
  288. data/src/rmsgfmt.ry +0 -233
@@ -1,8 +1,8 @@
1
- /* Prototype JavaScript framework, version 1.3.1
1
+ /* Prototype JavaScript framework, version 1.4.0_rc2
2
2
  * (c) 2005 Sam Stephenson <sam@conio.net>
3
3
  *
4
4
  * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
5
- * against the source tree, available from the Prototype darcs repository.
5
+ * against the source tree, available from the Prototype darcs repository.
6
6
  *
7
7
  * Prototype is freely distributable under the terms of an MIT-style license.
8
8
  *
@@ -11,13 +11,15 @@
11
11
  /*--------------------------------------------------------------------------*/
12
12
 
13
13
  var Prototype = {
14
- Version: '1.3.1',
15
- emptyFunction: function() {}
14
+ Version: '1.4.0_rc2',
15
+
16
+ emptyFunction: function() {},
17
+ K: function(x) {return x}
16
18
  }
17
19
 
18
20
  var Class = {
19
21
  create: function() {
20
- return function() {
22
+ return function() {
21
23
  this.initialize.apply(this, arguments);
22
24
  }
23
25
  }
@@ -32,29 +34,47 @@ Object.extend = function(destination, source) {
32
34
  return destination;
33
35
  }
34
36
 
35
- Object.prototype.extend = function(object) {
36
- return Object.extend.apply(this, [this, object]);
37
+ Object.inspect = function(object) {
38
+ try {
39
+ if (object == undefined) return 'undefined';
40
+ if (object == null) return 'null';
41
+ return object.inspect ? object.inspect() : object.toString();
42
+ } catch (e) {
43
+ if (e instanceof RangeError) return '...';
44
+ throw e;
45
+ }
37
46
  }
38
47
 
39
48
  Function.prototype.bind = function(object) {
40
49
  var __method = this;
41
50
  return function() {
42
- __method.apply(object, arguments);
51
+ return __method.apply(object, arguments);
43
52
  }
44
53
  }
45
54
 
46
55
  Function.prototype.bindAsEventListener = function(object) {
47
56
  var __method = this;
48
57
  return function(event) {
49
- __method.call(object, event || window.event);
58
+ return __method.call(object, event || window.event);
50
59
  }
51
60
  }
52
61
 
53
- Number.prototype.toColorPart = function() {
54
- var digits = this.toString(16);
55
- if (this < 16) return '0' + digits;
56
- return digits;
57
- }
62
+ Object.extend(Number.prototype, {
63
+ toColorPart: function() {
64
+ var digits = this.toString(16);
65
+ if (this < 16) return '0' + digits;
66
+ return digits;
67
+ },
68
+
69
+ succ: function() {
70
+ return this + 1;
71
+ },
72
+
73
+ times: function(iterator) {
74
+ $R(0, this, true).each(iterator);
75
+ return this;
76
+ }
77
+ });
58
78
 
59
79
  var Try = {
60
80
  these: function() {
@@ -90,10 +110,10 @@ PeriodicalExecuter.prototype = {
90
110
 
91
111
  onTimerEvent: function() {
92
112
  if (!this.currentlyExecuting) {
93
- try {
113
+ try {
94
114
  this.currentlyExecuting = true;
95
- this.callback();
96
- } finally {
115
+ this.callback();
116
+ } finally {
97
117
  this.currentlyExecuting = false;
98
118
  }
99
119
  }
@@ -110,7 +130,7 @@ function $() {
110
130
  if (typeof element == 'string')
111
131
  element = document.getElementById(element);
112
132
 
113
- if (arguments.length == 1)
133
+ if (arguments.length == 1)
114
134
  return element;
115
135
 
116
136
  elements.push(element);
@@ -118,36 +138,7 @@ function $() {
118
138
 
119
139
  return elements;
120
140
  }
121
-
122
- if (!Array.prototype.push) {
123
- Array.prototype.push = function() {
124
- var startLength = this.length;
125
- for (var i = 0; i < arguments.length; i++)
126
- this[startLength + i] = arguments[i];
127
- return this.length;
128
- }
129
- }
130
-
131
- if (!Function.prototype.apply) {
132
- // Based on code from http://www.youngpup.net/
133
- Function.prototype.apply = function(object, parameters) {
134
- var parameterStrings = new Array();
135
- if (!object) object = window;
136
- if (!parameters) parameters = new Array();
137
-
138
- for (var i = 0; i < parameters.length; i++)
139
- parameterStrings[i] = 'parameters[' + i + ']';
140
-
141
- object.__apply__ = this;
142
- var result = eval('object.__apply__(' +
143
- parameterStrings[i].join(', ') + ')');
144
- object.__apply__ = null;
145
-
146
- return result;
147
- }
148
- }
149
-
150
- String.prototype.extend({
141
+ Object.extend(String.prototype, {
151
142
  stripTags: function() {
152
143
  return this.replace(/<\/?[^>]+>/gi, '');
153
144
  },
@@ -162,10 +153,369 @@ String.prototype.extend({
162
153
  unescapeHTML: function() {
163
154
  var div = document.createElement('div');
164
155
  div.innerHTML = this.stripTags();
165
- return div.childNodes[0].nodeValue;
156
+ return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
157
+ },
158
+
159
+ toQueryParams: function() {
160
+ var pairs = this.match(/^\??(.*)$/)[1].split('&');
161
+ return pairs.inject({}, function(params, pairString) {
162
+ var pair = pairString.split('=');
163
+ params[pair[0]] = pair[1];
164
+ return params;
165
+ });
166
+ },
167
+
168
+ toArray: function() {
169
+ return this.split('');
170
+ },
171
+
172
+ camelize: function() {
173
+ var oStringList = this.split('-');
174
+ if (oStringList.length == 1) return oStringList[0];
175
+
176
+ var camelizedString = this.indexOf('-') == 0
177
+ ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
178
+ : oStringList[0];
179
+
180
+ for (var i = 1, len = oStringList.length; i < len; i++) {
181
+ var s = oStringList[i];
182
+ camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
183
+ }
184
+
185
+ return camelizedString;
186
+ },
187
+
188
+ inspect: function() {
189
+ return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
190
+ }
191
+ });
192
+
193
+ String.prototype.parseQuery = String.prototype.toQueryParams;
194
+
195
+ var $break = new Object();
196
+ var $continue = new Object();
197
+
198
+ var Enumerable = {
199
+ each: function(iterator) {
200
+ var index = 0;
201
+ try {
202
+ this._each(function(value) {
203
+ try {
204
+ iterator(value, index++);
205
+ } catch (e) {
206
+ if (e != $continue) throw e;
207
+ }
208
+ });
209
+ } catch (e) {
210
+ if (e != $break) throw e;
211
+ }
212
+ },
213
+
214
+ all: function(iterator) {
215
+ var result = true;
216
+ this.each(function(value, index) {
217
+ if (!(result &= (iterator || Prototype.K)(value, index)))
218
+ throw $break;
219
+ });
220
+ return result;
221
+ },
222
+
223
+ any: function(iterator) {
224
+ var result = true;
225
+ this.each(function(value, index) {
226
+ if (result &= (iterator || Prototype.K)(value, index))
227
+ throw $break;
228
+ });
229
+ return result;
230
+ },
231
+
232
+ collect: function(iterator) {
233
+ var results = [];
234
+ this.each(function(value, index) {
235
+ results.push(iterator(value, index));
236
+ });
237
+ return results;
238
+ },
239
+
240
+ detect: function (iterator) {
241
+ var result;
242
+ this.each(function(value, index) {
243
+ if (iterator(value, index)) {
244
+ result = value;
245
+ throw $break;
246
+ }
247
+ });
248
+ return result;
249
+ },
250
+
251
+ findAll: function(iterator) {
252
+ var results = [];
253
+ this.each(function(value, index) {
254
+ if (iterator(value, index))
255
+ results.push(value);
256
+ });
257
+ return results;
258
+ },
259
+
260
+ grep: function(pattern, iterator) {
261
+ var results = [];
262
+ this.each(function(value, index) {
263
+ var stringValue = value.toString();
264
+ if (stringValue.match(pattern))
265
+ results.push((iterator || Prototype.K)(value, index));
266
+ })
267
+ return results;
268
+ },
269
+
270
+ include: function(object) {
271
+ var found = false;
272
+ this.each(function(value) {
273
+ if (value == object) {
274
+ found = true;
275
+ throw $break;
276
+ }
277
+ });
278
+ return found;
279
+ },
280
+
281
+ inject: function(memo, iterator) {
282
+ this.each(function(value, index) {
283
+ memo = iterator(memo, value, index);
284
+ });
285
+ return memo;
286
+ },
287
+
288
+ invoke: function(method) {
289
+ var args = $A(arguments).slice(1);
290
+ return this.collect(function(value) {
291
+ return value[method].apply(value, args);
292
+ });
293
+ },
294
+
295
+ max: function(iterator) {
296
+ var result;
297
+ this.each(function(value, index) {
298
+ value = (iterator || Prototype.K)(value, index);
299
+ if (value >= (result || value))
300
+ result = value;
301
+ });
302
+ return result;
303
+ },
304
+
305
+ min: function(iterator) {
306
+ var result;
307
+ this.each(function(value, index) {
308
+ value = (iterator || Prototype.K)(value, index);
309
+ if (value <= (result || value))
310
+ result = value;
311
+ });
312
+ return result;
313
+ },
314
+
315
+ partition: function(iterator) {
316
+ var trues = [], falses = [];
317
+ this.each(function(value, index) {
318
+ ((iterator || Prototype.K)(value, index) ?
319
+ trues : falses).push(value);
320
+ });
321
+ return [trues, falses];
322
+ },
323
+
324
+ pluck: function(property) {
325
+ var results = [];
326
+ this.each(function(value, index) {
327
+ results.push(value[property]);
328
+ });
329
+ return results;
330
+ },
331
+
332
+ reject: function(iterator) {
333
+ var results = [];
334
+ this.each(function(value, index) {
335
+ if (!iterator(value, index))
336
+ results.push(value);
337
+ });
338
+ return results;
339
+ },
340
+
341
+ sortBy: function(iterator) {
342
+ return this.collect(function(value, index) {
343
+ return {value: value, criteria: iterator(value, index)};
344
+ }).sort(function(left, right) {
345
+ var a = left.criteria, b = right.criteria;
346
+ return a < b ? -1 : a > b ? 1 : 0;
347
+ }).pluck('value');
348
+ },
349
+
350
+ toArray: function() {
351
+ return this.collect(Prototype.K);
352
+ },
353
+
354
+ zip: function() {
355
+ var iterator = Prototype.K, args = $A(arguments);
356
+ if (typeof args.last() == 'function')
357
+ iterator = args.pop();
358
+
359
+ var collections = [this].concat(args).map($A);
360
+ return this.map(function(value, index) {
361
+ iterator(value = collections.pluck(index));
362
+ return value;
363
+ });
364
+ },
365
+
366
+ inspect: function() {
367
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
368
+ }
369
+ }
370
+
371
+ Object.extend(Enumerable, {
372
+ map: Enumerable.collect,
373
+ find: Enumerable.detect,
374
+ select: Enumerable.findAll,
375
+ member: Enumerable.include,
376
+ entries: Enumerable.toArray
377
+ });
378
+ var $A = Array.from = function(iterable) {
379
+ if (iterable.toArray) {
380
+ return iterable.toArray();
381
+ } else {
382
+ var results = [];
383
+ for (var i = 0; i < iterable.length; i++)
384
+ results.push(iterable[i]);
385
+ return results;
386
+ }
387
+ }
388
+
389
+ Object.extend(Array.prototype, Enumerable);
390
+
391
+ Object.extend(Array.prototype, {
392
+ _each: function(iterator) {
393
+ for (var i = 0; i < this.length; i++)
394
+ iterator(this[i]);
395
+ },
396
+
397
+ first: function() {
398
+ return this[0];
399
+ },
400
+
401
+ last: function() {
402
+ return this[this.length - 1];
403
+ },
404
+
405
+ compact: function() {
406
+ return this.select(function(value) {
407
+ return value != undefined || value != null;
408
+ });
409
+ },
410
+
411
+ flatten: function() {
412
+ return this.inject([], function(array, value) {
413
+ return array.concat(value.constructor == Array ?
414
+ value.flatten() : [value]);
415
+ });
416
+ },
417
+
418
+ without: function() {
419
+ var values = $A(arguments);
420
+ return this.select(function(value) {
421
+ return !values.include(value);
422
+ });
423
+ },
424
+
425
+ indexOf: function(object) {
426
+ for (var i = 0; i < this.length; i++)
427
+ if (this[i] == object) return i;
428
+ return false;
429
+ },
430
+
431
+ reverse: function() {
432
+ var result = [];
433
+ for (var i = this.length; i > 0; i--)
434
+ result.push(this[i-1]);
435
+ return result;
436
+ },
437
+
438
+ inspect: function() {
439
+ return '[' + this.map(Object.inspect).join(', ') + ']';
440
+ }
441
+ });
442
+ var Hash = {
443
+ _each: function(iterator) {
444
+ for (key in this) {
445
+ var value = this[key];
446
+ if (typeof value == 'function') continue;
447
+
448
+ var pair = [key, value];
449
+ pair.key = key;
450
+ pair.value = value;
451
+ iterator(pair);
452
+ }
453
+ },
454
+
455
+ keys: function() {
456
+ return this.pluck('key');
457
+ },
458
+
459
+ values: function() {
460
+ return this.pluck('value');
461
+ },
462
+
463
+ merge: function(hash) {
464
+ return $H(hash).inject($H(this), function(mergedHash, pair) {
465
+ mergedHash[pair.key] = pair.value;
466
+ return mergedHash;
467
+ });
468
+ },
469
+
470
+ toQueryString: function() {
471
+ return this.map(function(pair) {
472
+ return pair.map(encodeURIComponent).join('=');
473
+ }).join('&');
474
+ },
475
+
476
+ inspect: function() {
477
+ return '#<Hash:{' + this.map(function(pair) {
478
+ return pair.map(Object.inspect).join(': ');
479
+ }).join(', ') + '}>';
480
+ }
481
+ }
482
+
483
+ function $H(object) {
484
+ var hash = Object.extend({}, object || {});
485
+ Object.extend(hash, Enumerable);
486
+ Object.extend(hash, Hash);
487
+ return hash;
488
+ }
489
+ var Range = Class.create();
490
+ Object.extend(Range.prototype, Enumerable);
491
+ Object.extend(Range.prototype, {
492
+ initialize: function(start, end, exclusive) {
493
+ this.start = start;
494
+ this.end = end;
495
+ this.exclusive = exclusive;
496
+ },
497
+
498
+ _each: function(iterator) {
499
+ var value = this.start;
500
+ do {
501
+ iterator(value);
502
+ value = value.succ();
503
+ } while (this.include(value));
504
+ },
505
+
506
+ include: function(value) {
507
+ if (value < this.start)
508
+ return false;
509
+ if (this.exclusive)
510
+ return value < this.end;
511
+ return value <= this.end;
166
512
  }
167
513
  });
168
514
 
515
+ var $R = function(start, end, exclusive) {
516
+ return new Range(start, end, exclusive);
517
+ }
518
+
169
519
  var Ajax = {
170
520
  getTransport: function() {
171
521
  return Try.these(
@@ -173,9 +523,51 @@ var Ajax = {
173
523
  function() {return new ActiveXObject('Microsoft.XMLHTTP')},
174
524
  function() {return new XMLHttpRequest()}
175
525
  ) || false;
176
- }
526
+ },
527
+
528
+ activeRequestCount: 0
177
529
  }
178
530
 
531
+ Ajax.Responders = {
532
+ responders: [],
533
+
534
+ _each: function(iterator) {
535
+ this.responders._each(iterator);
536
+ },
537
+
538
+ register: function(responderToAdd) {
539
+ if (!this.include(responderToAdd))
540
+ this.responders.push(responderToAdd);
541
+ },
542
+
543
+ unregister: function(responderToRemove) {
544
+ this.responders = this.responders.without(responderToRemove);
545
+ },
546
+
547
+ dispatch: function(callback, request, transport, json) {
548
+ this.each(function(responder) {
549
+ if (responder[callback] && typeof responder[callback] == 'function') {
550
+ try {
551
+ responder[callback].apply(responder, [request, transport, json]);
552
+ } catch (e) {
553
+ }
554
+ }
555
+ });
556
+ }
557
+ };
558
+
559
+ Object.extend(Ajax.Responders, Enumerable);
560
+
561
+ Ajax.Responders.register({
562
+ onCreate: function() {
563
+ Ajax.activeRequestCount++;
564
+ },
565
+
566
+ onComplete: function() {
567
+ Ajax.activeRequestCount--;
568
+ }
569
+ });
570
+
179
571
  Ajax.Base = function() {};
180
572
  Ajax.Base.prototype = {
181
573
  setOptions: function(options) {
@@ -183,12 +575,13 @@ Ajax.Base.prototype = {
183
575
  method: 'post',
184
576
  asynchronous: true,
185
577
  parameters: ''
186
- }.extend(options || {});
578
+ }
579
+ Object.extend(this.options, options || {});
187
580
  },
188
581
 
189
582
  responseIsSuccess: function() {
190
583
  return this.transport.status == undefined
191
- || this.transport.status == 0
584
+ || this.transport.status == 0
192
585
  || (this.transport.status >= 200 && this.transport.status < 300);
193
586
  },
194
587
 
@@ -198,10 +591,10 @@ Ajax.Base.prototype = {
198
591
  }
199
592
 
200
593
  Ajax.Request = Class.create();
201
- Ajax.Request.Events =
594
+ Ajax.Request.Events =
202
595
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
203
596
 
204
- Ajax.Request.prototype = (new Ajax.Base()).extend({
597
+ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
205
598
  initialize: function(url, options) {
206
599
  this.transport = Ajax.getTransport();
207
600
  this.setOptions(options);
@@ -213,10 +606,13 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
213
606
  if (parameters.length > 0) parameters += '&_=';
214
607
 
215
608
  try {
216
- if (this.options.method == 'get')
217
- url += '?' + parameters;
609
+ this.url = url;
610
+ if (this.options.method == 'get' && parameters.length > 0)
611
+ this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
612
+
613
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
218
614
 
219
- this.transport.open(this.options.method, url,
615
+ this.transport.open(this.options.method, this.url,
220
616
  this.options.asynchronous);
221
617
 
222
618
  if (this.options.asynchronous) {
@@ -230,21 +626,23 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
230
626
  this.transport.send(this.options.method == 'post' ? body : null);
231
627
 
232
628
  } catch (e) {
629
+ (this.options.onException || Prototype.emptyFunction)(this, e);
630
+ Ajax.Responders.dispatch('onException', this, e);
233
631
  }
234
632
  },
235
633
 
236
634
  setRequestHeaders: function() {
237
- var requestHeaders =
635
+ var requestHeaders =
238
636
  ['X-Requested-With', 'XMLHttpRequest',
239
637
  'X-Prototype-Version', Prototype.Version];
240
638
 
241
639
  if (this.options.method == 'post') {
242
- requestHeaders.push('Content-type',
640
+ requestHeaders.push('Content-type',
243
641
  'application/x-www-form-urlencoded');
244
642
 
245
643
  /* Force "Connection: close" for Mozilla browsers to work around
246
644
  * a bug where XMLHttpReqeuest sends an incorrect Content-length
247
- * header. See Mozilla Bugzilla #246651.
645
+ * header. See Mozilla Bugzilla #246651.
248
646
  */
249
647
  if (this.transport.overrideMimeType)
250
648
  requestHeaders.push('Connection', 'close');
@@ -263,15 +661,26 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
263
661
  this.respondToReadyState(this.transport.readyState);
264
662
  },
265
663
 
664
+ evalJSON: function() {
665
+ try {
666
+ var json = this.transport.getResponseHeader('X-JSON'), object;
667
+ object = eval(json);
668
+ return object;
669
+ } catch (e) {
670
+ }
671
+ },
672
+
266
673
  respondToReadyState: function(readyState) {
267
674
  var event = Ajax.Request.Events[readyState];
675
+ var transport = this.transport, json = this.evalJSON();
268
676
 
269
677
  if (event == 'Complete')
270
678
  (this.options['on' + this.transport.status]
271
- || this.options['on' + this.responseIsSuccess() ? 'Success' : 'Failure']
272
- || Prototype.emptyFunction)(this.transport);
679
+ || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
680
+ || Prototype.emptyFunction)(transport, json);
273
681
 
274
- (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
682
+ (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
683
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
275
684
 
276
685
  /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
277
686
  if (event == 'Complete')
@@ -282,7 +691,7 @@ Ajax.Request.prototype = (new Ajax.Base()).extend({
282
691
  Ajax.Updater = Class.create();
283
692
  Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
284
693
 
285
- Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
694
+ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
286
695
  initialize: function(container, url, options) {
287
696
  this.containers = {
288
697
  success: container.success ? $(container.success) : $(container),
@@ -294,9 +703,9 @@ Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
294
703
  this.setOptions(options);
295
704
 
296
705
  var onComplete = this.options.onComplete || Prototype.emptyFunction;
297
- this.options.onComplete = (function() {
706
+ this.options.onComplete = (function(transport, object) {
298
707
  this.updateContent();
299
- onComplete(this.transport);
708
+ onComplete(transport, object);
300
709
  }).bind(this);
301
710
 
302
711
  this.request(url);
@@ -320,8 +729,7 @@ Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
320
729
 
321
730
  if (this.responseIsSuccess()) {
322
731
  if (this.onComplete)
323
- setTimeout((function() {this.onComplete(
324
- this.transport)}).bind(this), 10);
732
+ setTimeout(this.onComplete.bind(this), 10);
325
733
  }
326
734
 
327
735
  if (this.options.evalScripts && scripts) {
@@ -335,13 +743,13 @@ Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
335
743
  });
336
744
 
337
745
  Ajax.PeriodicalUpdater = Class.create();
338
- Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
746
+ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
339
747
  initialize: function(container, url, options) {
340
748
  this.setOptions(options);
341
749
  this.onComplete = this.options.onComplete;
342
750
 
343
751
  this.frequency = (this.options.frequency || 2);
344
- this.decay = 1;
752
+ this.decay = (this.options.decay || 1);
345
753
 
346
754
  this.updater = {};
347
755
  this.container = container;
@@ -358,17 +766,17 @@ Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
358
766
  stop: function() {
359
767
  this.updater.onComplete = undefined;
360
768
  clearTimeout(this.timer);
361
- (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
769
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
362
770
  },
363
771
 
364
772
  updateComplete: function(request) {
365
773
  if (this.options.decay) {
366
- this.decay = (request.responseText == this.lastText ?
774
+ this.decay = (request.responseText == this.lastText ?
367
775
  this.decay * this.options.decay : 1);
368
776
 
369
777
  this.lastText = request.responseText;
370
778
  }
371
- this.timer = setTimeout(this.onTimerEvent.bind(this),
779
+ this.timer = setTimeout(this.onTimerEvent.bind(this),
372
780
  this.decay * this.frequency * 1000);
373
781
  },
374
782
 
@@ -376,23 +784,13 @@ Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
376
784
  this.updater = new Ajax.Updater(this.container, this.url, this.options);
377
785
  }
378
786
  });
379
-
380
- document.getElementsByClassName = function(className) {
381
- var children = document.getElementsByTagName('*') || document.all;
382
- var elements = new Array();
383
-
384
- for (var i = 0; i < children.length; i++) {
385
- var child = children[i];
386
- var classNames = child.className.split(' ');
387
- for (var j = 0; j < classNames.length; j++) {
388
- if (classNames[j] == className) {
389
- elements.push(child);
390
- break;
391
- }
392
- }
393
- }
394
-
395
- return elements;
787
+ document.getElementsByClassName = function(className, parentElement) {
788
+ var children = ($(parentElement) || document.body).getElementsByTagName('*');
789
+ return $A(children).inject([], function(elements, child) {
790
+ if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
791
+ elements.push(child);
792
+ return elements;
793
+ });
396
794
  }
397
795
 
398
796
  /*--------------------------------------------------------------------------*/
@@ -402,11 +800,14 @@ if (!window.Element) {
402
800
  }
403
801
 
404
802
  Object.extend(Element, {
803
+ visible: function(element) {
804
+ return $(element).style.display != 'none';
805
+ },
806
+
405
807
  toggle: function() {
406
808
  for (var i = 0; i < arguments.length; i++) {
407
809
  var element = $(arguments[i]);
408
- element.style.display =
409
- (element.style.display == 'none' ? '' : 'none');
810
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
410
811
  }
411
812
  },
412
813
 
@@ -428,54 +829,131 @@ Object.extend(Element, {
428
829
  element = $(element);
429
830
  element.parentNode.removeChild(element);
430
831
  },
431
-
832
+
432
833
  getHeight: function(element) {
433
834
  element = $(element);
434
- return element.offsetHeight;
835
+ return element.offsetHeight;
836
+ },
837
+
838
+ classNames: function(element) {
839
+ return new Element.ClassNames(element);
435
840
  },
436
841
 
437
842
  hasClassName: function(element, className) {
438
- element = $(element);
439
- if (!element)
440
- return;
441
- var a = element.className.split(' ');
442
- for (var i = 0; i < a.length; i++) {
443
- if (a[i] == className)
444
- return true;
445
- }
446
- return false;
843
+ if (!(element = $(element))) return;
844
+ return Element.classNames(element).include(className);
447
845
  },
448
846
 
449
847
  addClassName: function(element, className) {
450
- element = $(element);
451
- Element.removeClassName(element, className);
452
- element.className += ' ' + className;
848
+ if (!(element = $(element))) return;
849
+ return Element.classNames(element).add(className);
453
850
  },
454
851
 
455
852
  removeClassName: function(element, className) {
456
- element = $(element);
457
- if (!element)
458
- return;
459
- var newClassName = '';
460
- var a = element.className.split(' ');
461
- for (var i = 0; i < a.length; i++) {
462
- if (a[i] != className) {
463
- if (i > 0)
464
- newClassName += ' ';
465
- newClassName += a[i];
466
- }
467
- }
468
- element.className = newClassName;
853
+ if (!(element = $(element))) return;
854
+ return Element.classNames(element).remove(className);
469
855
  },
470
-
856
+
471
857
  // removes whitespace-only text node children
472
858
  cleanWhitespace: function(element) {
473
- var element = $(element);
859
+ element = $(element);
474
860
  for (var i = 0; i < element.childNodes.length; i++) {
475
861
  var node = element.childNodes[i];
476
- if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
862
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
477
863
  Element.remove(node);
478
864
  }
865
+ },
866
+
867
+ empty: function(element) {
868
+ return $(element).innerHTML.match(/^\s*$/);
869
+ },
870
+
871
+ scrollTo: function(element) {
872
+ element = $(element);
873
+ var x = element.x ? element.x : element.offsetLeft,
874
+ y = element.y ? element.y : element.offsetTop;
875
+ window.scrollTo(x, y);
876
+ },
877
+
878
+ getStyle: function(element, style) {
879
+ element = $(element);
880
+ var value = element.style[style.camelize()];
881
+ if (!value) {
882
+ if (document.defaultView && document.defaultView.getComputedStyle) {
883
+ var css = document.defaultView.getComputedStyle(element, null);
884
+ value = css ? css.getPropertyValue(style) : null;
885
+ } else if (element.currentStyle) {
886
+ value = element.currentStyle[style.camelize()];
887
+ }
888
+ }
889
+
890
+ if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
891
+ if (Element.getStyle(element, 'position') == 'static') value = 'auto';
892
+
893
+ return value == 'auto' ? null : value;
894
+ },
895
+
896
+ getDimensions: function(element) {
897
+ element = $(element);
898
+ if (Element.getStyle(element, 'display') != 'none')
899
+ return {width: element.offsetWidth, height: element.offsetHeight};
900
+
901
+ // All *Width and *Height properties give 0 on elements with display none,
902
+ // so enable the element temporarily
903
+ var els = element.style;
904
+ var originalVisibility = els.visibility;
905
+ var originalPosition = els.position;
906
+ els.visibility = 'hidden';
907
+ els.position = 'absolute';
908
+ els.display = '';
909
+ var originalWidth = element.clientWidth;
910
+ var originalHeight = element.clientHeight;
911
+ els.display = 'none';
912
+ els.position = originalPosition;
913
+ els.visibility = originalVisibility;
914
+ return {width: originalWidth, height: originalHeight};
915
+ },
916
+
917
+ makePositioned: function(element) {
918
+ element = $(element);
919
+ var pos = Element.getStyle(element, 'position');
920
+ if (pos == 'static' || !pos) {
921
+ element._madePositioned = true;
922
+ element.style.position = 'relative';
923
+ // Opera returns the offset relative to the positioning context, when an
924
+ // element is position relative but top and left have not been defined
925
+ if (window.opera) {
926
+ element.style.top = 0;
927
+ element.style.left = 0;
928
+ }
929
+ }
930
+ },
931
+
932
+ undoPositioned: function(element) {
933
+ element = $(element);
934
+ if (element._madePositioned) {
935
+ element._madePositioned = undefined;
936
+ element.style.position =
937
+ element.style.top =
938
+ element.style.left =
939
+ element.style.bottom =
940
+ element.style.right = '';
941
+ }
942
+ },
943
+
944
+ makeClipping: function(element) {
945
+ element = $(element);
946
+ if (element._overflow) return;
947
+ element._overflow = element.style.overflow;
948
+ if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
949
+ element.style.overflow = 'hidden';
950
+ },
951
+
952
+ undoClipping: function(element) {
953
+ element = $(element);
954
+ if (element._overflow) return;
955
+ element.style.overflow = element._overflow;
956
+ element._overflow = undefined;
479
957
  }
480
958
  });
481
959
 
@@ -492,67 +970,124 @@ Abstract.Insertion.prototype = {
492
970
  initialize: function(element, content) {
493
971
  this.element = $(element);
494
972
  this.content = content;
495
-
973
+
496
974
  if (this.adjacency && this.element.insertAdjacentHTML) {
497
- this.element.insertAdjacentHTML(this.adjacency, this.content);
975
+ try {
976
+ this.element.insertAdjacentHTML(this.adjacency, this.content);
977
+ } catch (e) {
978
+ if (this.element.tagName.toLowerCase() == 'tbody') {
979
+ this.insertContent(this.contentFromAnonymousTable());
980
+ } else {
981
+ throw e;
982
+ }
983
+ }
498
984
  } else {
499
985
  this.range = this.element.ownerDocument.createRange();
500
986
  if (this.initializeRange) this.initializeRange();
501
- this.fragment = this.range.createContextualFragment(this.content);
502
- this.insertContent();
987
+ this.insertContent([this.range.createContextualFragment(this.content)]);
503
988
  }
989
+ },
990
+
991
+ contentFromAnonymousTable: function() {
992
+ var div = document.createElement('div');
993
+ div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
994
+ return $A(div.childNodes[0].childNodes[0].childNodes);
504
995
  }
505
996
  }
506
997
 
507
998
  var Insertion = new Object();
508
999
 
509
1000
  Insertion.Before = Class.create();
510
- Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
1001
+ Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
511
1002
  initializeRange: function() {
512
1003
  this.range.setStartBefore(this.element);
513
1004
  },
514
-
515
- insertContent: function() {
516
- this.element.parentNode.insertBefore(this.fragment, this.element);
1005
+
1006
+ insertContent: function(fragments) {
1007
+ fragments.each((function(fragment) {
1008
+ this.element.parentNode.insertBefore(fragment, this.element);
1009
+ }).bind(this));
517
1010
  }
518
1011
  });
519
1012
 
520
1013
  Insertion.Top = Class.create();
521
- Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
1014
+ Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
522
1015
  initializeRange: function() {
523
1016
  this.range.selectNodeContents(this.element);
524
1017
  this.range.collapse(true);
525
1018
  },
526
-
527
- insertContent: function() {
528
- this.element.insertBefore(this.fragment, this.element.firstChild);
1019
+
1020
+ insertContent: function(fragments) {
1021
+ fragments.reverse().each((function(fragment) {
1022
+ this.element.insertBefore(fragment, this.element.firstChild);
1023
+ }).bind(this));
529
1024
  }
530
1025
  });
531
1026
 
532
1027
  Insertion.Bottom = Class.create();
533
- Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
1028
+ Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
534
1029
  initializeRange: function() {
535
1030
  this.range.selectNodeContents(this.element);
536
1031
  this.range.collapse(this.element);
537
1032
  },
538
-
539
- insertContent: function() {
540
- this.element.appendChild(this.fragment);
1033
+
1034
+ insertContent: function(fragments) {
1035
+ fragments.each((function(fragment) {
1036
+ this.element.appendChild(fragment);
1037
+ }).bind(this));
541
1038
  }
542
1039
  });
543
1040
 
544
1041
  Insertion.After = Class.create();
545
- Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
1042
+ Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
546
1043
  initializeRange: function() {
547
1044
  this.range.setStartAfter(this.element);
548
1045
  },
549
-
550
- insertContent: function() {
551
- this.element.parentNode.insertBefore(this.fragment,
552
- this.element.nextSibling);
1046
+
1047
+ insertContent: function(fragments) {
1048
+ fragments.each((function(fragment) {
1049
+ this.element.parentNode.insertBefore(fragment,
1050
+ this.element.nextSibling);
1051
+ }).bind(this));
553
1052
  }
554
1053
  });
555
1054
 
1055
+ /*--------------------------------------------------------------------------*/
1056
+
1057
+ Element.ClassNames = Class.create();
1058
+ Element.ClassNames.prototype = {
1059
+ initialize: function(element) {
1060
+ this.element = $(element);
1061
+ },
1062
+
1063
+ _each: function(iterator) {
1064
+ this.element.className.split(/\s+/).select(function(name) {
1065
+ return name.length > 0;
1066
+ })._each(iterator);
1067
+ },
1068
+
1069
+ set: function(className) {
1070
+ this.element.className = className;
1071
+ },
1072
+
1073
+ add: function(classNameToAdd) {
1074
+ if (this.include(classNameToAdd)) return;
1075
+ this.set(this.toArray().concat(classNameToAdd).join(' '));
1076
+ },
1077
+
1078
+ remove: function(classNameToRemove) {
1079
+ if (!this.include(classNameToRemove)) return;
1080
+ this.set(this.select(function(className) {
1081
+ return className != classNameToRemove;
1082
+ }));
1083
+ },
1084
+
1085
+ toString: function() {
1086
+ return this.toArray().join(' ');
1087
+ }
1088
+ }
1089
+
1090
+ Object.extend(Element.ClassNames.prototype, Enumerable);
556
1091
  var Field = {
557
1092
  clear: function() {
558
1093
  for (var i = 0; i < arguments.length; i++)
@@ -562,17 +1097,17 @@ var Field = {
562
1097
  focus: function(element) {
563
1098
  $(element).focus();
564
1099
  },
565
-
1100
+
566
1101
  present: function() {
567
1102
  for (var i = 0; i < arguments.length; i++)
568
1103
  if ($(arguments[i]).value == '') return false;
569
1104
  return true;
570
1105
  },
571
-
1106
+
572
1107
  select: function(element) {
573
1108
  $(element).select();
574
1109
  },
575
-
1110
+
576
1111
  activate: function(element) {
577
1112
  $(element).focus();
578
1113
  $(element).select();
@@ -585,18 +1120,18 @@ var Form = {
585
1120
  serialize: function(form) {
586
1121
  var elements = Form.getElements($(form));
587
1122
  var queryComponents = new Array();
588
-
1123
+
589
1124
  for (var i = 0; i < elements.length; i++) {
590
1125
  var queryComponent = Form.Element.serialize(elements[i]);
591
1126
  if (queryComponent)
592
1127
  queryComponents.push(queryComponent);
593
1128
  }
594
-
1129
+
595
1130
  return queryComponents.join('&');
596
1131
  },
597
-
1132
+
598
1133
  getElements: function(form) {
599
- var form = $(form);
1134
+ form = $(form);
600
1135
  var elements = new Array();
601
1136
 
602
1137
  for (tagName in Form.Element.Serializers) {
@@ -606,19 +1141,19 @@ var Form = {
606
1141
  }
607
1142
  return elements;
608
1143
  },
609
-
1144
+
610
1145
  getInputs: function(form, typeName, name) {
611
- var form = $(form);
1146
+ form = $(form);
612
1147
  var inputs = form.getElementsByTagName('input');
613
-
1148
+
614
1149
  if (!typeName && !name)
615
1150
  return inputs;
616
-
1151
+
617
1152
  var matchingInputs = new Array();
618
1153
  for (var i = 0; i < inputs.length; i++) {
619
1154
  var input = inputs[i];
620
1155
  if ((typeName && input.type != typeName) ||
621
- (name && input.name != name))
1156
+ (name && input.name != name))
622
1157
  continue;
623
1158
  matchingInputs.push(input);
624
1159
  }
@@ -644,7 +1179,7 @@ var Form = {
644
1179
  },
645
1180
 
646
1181
  focusFirstElement: function(form) {
647
- var form = $(form);
1182
+ form = $(form);
648
1183
  var elements = Form.getElements(form);
649
1184
  for (var i = 0; i < elements.length; i++) {
650
1185
  var element = elements[i];
@@ -662,21 +1197,21 @@ var Form = {
662
1197
 
663
1198
  Form.Element = {
664
1199
  serialize: function(element) {
665
- var element = $(element);
1200
+ element = $(element);
666
1201
  var method = element.tagName.toLowerCase();
667
1202
  var parameter = Form.Element.Serializers[method](element);
668
-
1203
+
669
1204
  if (parameter)
670
- return encodeURIComponent(parameter[0]) + '=' +
671
- encodeURIComponent(parameter[1]);
1205
+ return encodeURIComponent(parameter[0]) + '=' +
1206
+ encodeURIComponent(parameter[1]);
672
1207
  },
673
-
1208
+
674
1209
  getValue: function(element) {
675
- var element = $(element);
1210
+ element = $(element);
676
1211
  var method = element.tagName.toLowerCase();
677
1212
  var parameter = Form.Element.Serializers[method](element);
678
-
679
- if (parameter)
1213
+
1214
+ if (parameter)
680
1215
  return parameter[1];
681
1216
  }
682
1217
  }
@@ -689,7 +1224,7 @@ Form.Element.Serializers = {
689
1224
  case 'password':
690
1225
  case 'text':
691
1226
  return Form.Element.Serializers.textarea(element);
692
- case 'checkbox':
1227
+ case 'checkbox':
693
1228
  case 'radio':
694
1229
  return Form.Element.Serializers.inputSelector(element);
695
1230
  }
@@ -706,17 +1241,30 @@ Form.Element.Serializers = {
706
1241
  },
707
1242
 
708
1243
  select: function(element) {
709
- var value = '';
710
- if (element.type == 'select-one') {
711
- var index = element.selectedIndex;
712
- if (index >= 0)
713
- value = element.options[index].value || element.options[index].text;
714
- } else {
715
- value = new Array();
716
- for (var i = 0; i < element.length; i++) {
717
- var opt = element.options[i];
718
- if (opt.selected)
719
- value.push(opt.value || opt.text);
1244
+ return Form.Element.Serializers[element.type == 'select-one' ?
1245
+ 'selectOne' : 'selectMany'](element);
1246
+ },
1247
+
1248
+ selectOne: function(element) {
1249
+ var value = '', opt, index = element.selectedIndex;
1250
+ if (index >= 0) {
1251
+ opt = element.options[index];
1252
+ value = opt.value;
1253
+ if (!value && !('value' in opt))
1254
+ value = opt.text;
1255
+ }
1256
+ return [element.name, value];
1257
+ },
1258
+
1259
+ selectMany: function(element) {
1260
+ var value = new Array();
1261
+ for (var i = 0; i < element.length; i++) {
1262
+ var opt = element.options[i];
1263
+ if (opt.selected) {
1264
+ var optValue = opt.value;
1265
+ if (!optValue && !('value' in opt))
1266
+ optValue = opt.text;
1267
+ value.push(optValue);
720
1268
  }
721
1269
  }
722
1270
  return [element.name, value];
@@ -735,15 +1283,15 @@ Abstract.TimedObserver.prototype = {
735
1283
  this.frequency = frequency;
736
1284
  this.element = $(element);
737
1285
  this.callback = callback;
738
-
1286
+
739
1287
  this.lastValue = this.getValue();
740
1288
  this.registerCallback();
741
1289
  },
742
-
1290
+
743
1291
  registerCallback: function() {
744
1292
  setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
745
1293
  },
746
-
1294
+
747
1295
  onTimerEvent: function() {
748
1296
  var value = this.getValue();
749
1297
  if (this.lastValue != value) {
@@ -754,14 +1302,14 @@ Abstract.TimedObserver.prototype = {
754
1302
  }
755
1303
 
756
1304
  Form.Element.Observer = Class.create();
757
- Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
1305
+ Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
758
1306
  getValue: function() {
759
1307
  return Form.Element.getValue(this.element);
760
1308
  }
761
1309
  });
762
1310
 
763
1311
  Form.Observer = Class.create();
764
- Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
1312
+ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
765
1313
  getValue: function() {
766
1314
  return Form.serialize(this.element);
767
1315
  }
@@ -774,14 +1322,14 @@ Abstract.EventObserver.prototype = {
774
1322
  initialize: function(element, callback) {
775
1323
  this.element = $(element);
776
1324
  this.callback = callback;
777
-
1325
+
778
1326
  this.lastValue = this.getValue();
779
1327
  if (this.element.tagName.toLowerCase() == 'form')
780
1328
  this.registerFormCallbacks();
781
1329
  else
782
1330
  this.registerCallback(this.element);
783
1331
  },
784
-
1332
+
785
1333
  onElementEvent: function() {
786
1334
  var value = this.getValue();
787
1335
  if (this.lastValue != value) {
@@ -789,22 +1337,22 @@ Abstract.EventObserver.prototype = {
789
1337
  this.lastValue = value;
790
1338
  }
791
1339
  },
792
-
1340
+
793
1341
  registerFormCallbacks: function() {
794
1342
  var elements = Form.getElements(this.element);
795
1343
  for (var i = 0; i < elements.length; i++)
796
1344
  this.registerCallback(elements[i]);
797
1345
  },
798
-
1346
+
799
1347
  registerCallback: function(element) {
800
1348
  if (element.type) {
801
1349
  switch (element.type.toLowerCase()) {
802
- case 'checkbox':
1350
+ case 'checkbox':
803
1351
  case 'radio':
804
1352
  element.target = this;
805
1353
  element.prev_onclick = element.onclick || Prototype.emptyFunction;
806
1354
  element.onclick = function() {
807
- this.prev_onclick();
1355
+ this.prev_onclick();
808
1356
  this.target.onElementEvent();
809
1357
  }
810
1358
  break;
@@ -816,30 +1364,28 @@ Abstract.EventObserver.prototype = {
816
1364
  element.target = this;
817
1365
  element.prev_onchange = element.onchange || Prototype.emptyFunction;
818
1366
  element.onchange = function() {
819
- this.prev_onchange();
1367
+ this.prev_onchange();
820
1368
  this.target.onElementEvent();
821
1369
  }
822
1370
  break;
823
1371
  }
824
- }
1372
+ }
825
1373
  }
826
1374
  }
827
1375
 
828
1376
  Form.Element.EventObserver = Class.create();
829
- Form.Element.EventObserver.prototype = (new Abstract.EventObserver()).extend({
1377
+ Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
830
1378
  getValue: function() {
831
1379
  return Form.Element.getValue(this.element);
832
1380
  }
833
1381
  });
834
1382
 
835
1383
  Form.EventObserver = Class.create();
836
- Form.EventObserver.prototype = (new Abstract.EventObserver()).extend({
1384
+ Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
837
1385
  getValue: function() {
838
1386
  return Form.serialize(this.element);
839
1387
  }
840
1388
  });
841
-
842
-
843
1389
  if (!window.Event) {
844
1390
  var Event = new Object();
845
1391
  }
@@ -865,21 +1411,22 @@ Object.extend(Event, {
865
1411
  },
866
1412
 
867
1413
  pointerX: function(event) {
868
- return event.pageX || (event.clientX +
1414
+ return event.pageX || (event.clientX +
869
1415
  (document.documentElement.scrollLeft || document.body.scrollLeft));
870
1416
  },
871
1417
 
872
1418
  pointerY: function(event) {
873
- return event.pageY || (event.clientY +
1419
+ return event.pageY || (event.clientY +
874
1420
  (document.documentElement.scrollTop || document.body.scrollTop));
875
1421
  },
876
1422
 
877
1423
  stop: function(event) {
878
- if (event.preventDefault) {
879
- event.preventDefault();
880
- event.stopPropagation();
1424
+ if (event.preventDefault) {
1425
+ event.preventDefault();
1426
+ event.stopPropagation();
881
1427
  } else {
882
1428
  event.returnValue = false;
1429
+ event.cancelBubble = true;
883
1430
  }
884
1431
  },
885
1432
 
@@ -894,7 +1441,7 @@ Object.extend(Event, {
894
1441
  },
895
1442
 
896
1443
  observers: false,
897
-
1444
+
898
1445
  _observeAndCache: function(element, name, observer, useCapture) {
899
1446
  if (!this.observers) this.observers = [];
900
1447
  if (element.addEventListener) {
@@ -905,7 +1452,7 @@ Object.extend(Event, {
905
1452
  element.attachEvent('on' + name, observer);
906
1453
  }
907
1454
  },
908
-
1455
+
909
1456
  unloadCache: function() {
910
1457
  if (!Event.observers) return;
911
1458
  for (var i = 0; i < Event.observers.length; i++) {
@@ -918,24 +1465,24 @@ Object.extend(Event, {
918
1465
  observe: function(element, name, observer, useCapture) {
919
1466
  var element = $(element);
920
1467
  useCapture = useCapture || false;
921
-
1468
+
922
1469
  if (name == 'keypress' &&
923
- ((navigator.appVersion.indexOf('AppleWebKit') > 0)
1470
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
924
1471
  || element.attachEvent))
925
1472
  name = 'keydown';
926
-
1473
+
927
1474
  this._observeAndCache(element, name, observer, useCapture);
928
1475
  },
929
1476
 
930
1477
  stopObserving: function(element, name, observer, useCapture) {
931
1478
  var element = $(element);
932
1479
  useCapture = useCapture || false;
933
-
1480
+
934
1481
  if (name == 'keypress' &&
935
- ((navigator.appVersion.indexOf('AppleWebKit') > 0)
1482
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
936
1483
  || element.detachEvent))
937
1484
  name = 'keydown';
938
-
1485
+
939
1486
  if (element.removeEventListener) {
940
1487
  element.removeEventListener(name, observer, useCapture);
941
1488
  } else if (element.detachEvent) {
@@ -946,24 +1493,22 @@ Object.extend(Event, {
946
1493
 
947
1494
  /* prevent memory leaks in IE */
948
1495
  Event.observe(window, 'unload', Event.unloadCache, false);
949
-
950
1496
  var Position = {
951
-
952
1497
  // set to true if needed, warning: firefox performance problems
953
1498
  // NOT neeeded for page scrolling, only if draggable contained in
954
1499
  // scrollable elements
955
- includeScrollOffsets: false,
1500
+ includeScrollOffsets: false,
956
1501
 
957
1502
  // must be called before calling withinIncludingScrolloffset, every time the
958
1503
  // page is scrolled
959
1504
  prepare: function() {
960
- this.deltaX = window.pageXOffset
961
- || document.documentElement.scrollLeft
962
- || document.body.scrollLeft
1505
+ this.deltaX = window.pageXOffset
1506
+ || document.documentElement.scrollLeft
1507
+ || document.body.scrollLeft
963
1508
  || 0;
964
- this.deltaY = window.pageYOffset
965
- || document.documentElement.scrollTop
966
- || document.body.scrollTop
1509
+ this.deltaY = window.pageYOffset
1510
+ || document.documentElement.scrollTop
1511
+ || document.body.scrollTop
967
1512
  || 0;
968
1513
  },
969
1514
 
@@ -971,7 +1516,7 @@ var Position = {
971
1516
  var valueT = 0, valueL = 0;
972
1517
  do {
973
1518
  valueT += element.scrollTop || 0;
974
- valueL += element.scrollLeft || 0;
1519
+ valueL += element.scrollLeft || 0;
975
1520
  element = element.parentNode;
976
1521
  } while (element);
977
1522
  return [valueL, valueT];
@@ -987,6 +1532,31 @@ var Position = {
987
1532
  return [valueL, valueT];
988
1533
  },
989
1534
 
1535
+ positionedOffset: function(element) {
1536
+ var valueT = 0, valueL = 0;
1537
+ do {
1538
+ valueT += element.offsetTop || 0;
1539
+ valueL += element.offsetLeft || 0;
1540
+ element = element.offsetParent;
1541
+ if (element) {
1542
+ p = Element.getStyle(element, 'position');
1543
+ if (p == 'relative' || p == 'absolute') break;
1544
+ }
1545
+ } while (element);
1546
+ return [valueL, valueT];
1547
+ },
1548
+
1549
+ offsetParent: function(element) {
1550
+ if (element.offsetParent) return element.offsetParent;
1551
+ if (element == document.body) return element;
1552
+
1553
+ while ((element = element.parentNode) && element != document.body)
1554
+ if (Element.getStyle(element, 'position') != 'static')
1555
+ return element;
1556
+
1557
+ return document.body;
1558
+ },
1559
+
990
1560
  // caches x/y coordinate pair to use with overlap
991
1561
  within: function(element, x, y) {
992
1562
  if (this.includeScrollOffsets)
@@ -997,7 +1567,7 @@ var Position = {
997
1567
 
998
1568
  return (y >= this.offset[1] &&
999
1569
  y < this.offset[1] + element.offsetHeight &&
1000
- x >= this.offset[0] &&
1570
+ x >= this.offset[0] &&
1001
1571
  x < this.offset[0] + element.offsetWidth);
1002
1572
  },
1003
1573
 
@@ -1010,18 +1580,18 @@ var Position = {
1010
1580
 
1011
1581
  return (this.ycomp >= this.offset[1] &&
1012
1582
  this.ycomp < this.offset[1] + element.offsetHeight &&
1013
- this.xcomp >= this.offset[0] &&
1583
+ this.xcomp >= this.offset[0] &&
1014
1584
  this.xcomp < this.offset[0] + element.offsetWidth);
1015
1585
  },
1016
1586
 
1017
1587
  // within must be called directly before
1018
- overlap: function(mode, element) {
1019
- if (!mode) return 0;
1020
- if (mode == 'vertical')
1021
- return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1588
+ overlap: function(mode, element) {
1589
+ if (!mode) return 0;
1590
+ if (mode == 'vertical')
1591
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1022
1592
  element.offsetHeight;
1023
1593
  if (mode == 'horizontal')
1024
- return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1594
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1025
1595
  element.offsetWidth;
1026
1596
  },
1027
1597
 
@@ -1034,5 +1604,123 @@ var Position = {
1034
1604
  target.style.left = offsets[0] + 'px';
1035
1605
  target.style.width = source.offsetWidth + 'px';
1036
1606
  target.style.height = source.offsetHeight + 'px';
1607
+ },
1608
+
1609
+ page: function(forElement) {
1610
+ var valueT = 0, valueL = 0;
1611
+
1612
+ var element = forElement;
1613
+ do {
1614
+ valueT += element.offsetTop || 0;
1615
+ valueL += element.offsetLeft || 0;
1616
+
1617
+ // Safari fix
1618
+ if (element.offsetParent==document.body)
1619
+ if (Element.getStyle(element,'position')=='absolute') break;
1620
+
1621
+ } while (element = element.offsetParent);
1622
+
1623
+ element = forElement;
1624
+ do {
1625
+ valueT -= element.scrollTop || 0;
1626
+ valueL -= element.scrollLeft || 0;
1627
+ } while (element = element.parentNode);
1628
+
1629
+ return [valueL, valueT];
1630
+ },
1631
+
1632
+ clone: function(source, target) {
1633
+ var options = Object.extend({
1634
+ setLeft: true,
1635
+ setTop: true,
1636
+ setWidth: true,
1637
+ setHeight: true,
1638
+ offsetTop: 0,
1639
+ offsetLeft: 0
1640
+ }, arguments[2] || {})
1641
+
1642
+ // find page position of source
1643
+ source = $(source);
1644
+ var p = Position.page(source);
1645
+
1646
+ // find coordinate system to use
1647
+ target = $(target);
1648
+ var delta = [0, 0];
1649
+ var parent = null;
1650
+ // delta [0,0] will do fine with position: fixed elements,
1651
+ // position:absolute needs offsetParent deltas
1652
+ if (Element.getStyle(target,'position') == 'absolute') {
1653
+ parent = Position.offsetParent(target);
1654
+ delta = Position.page(parent);
1655
+ }
1656
+
1657
+ // correct by body offsets (fixes Safari)
1658
+ if (parent == document.body) {
1659
+ delta[0] -= document.body.offsetLeft;
1660
+ delta[1] -= document.body.offsetTop;
1661
+ }
1662
+
1663
+ // set position
1664
+ if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
1665
+ if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
1666
+ if(options.setWidth) target.style.width = source.offsetWidth + 'px';
1667
+ if(options.setHeight) target.style.height = source.offsetHeight + 'px';
1668
+ },
1669
+
1670
+ absolutize: function(element) {
1671
+ element = $(element);
1672
+ if (element.style.position == 'absolute') return;
1673
+ Position.prepare();
1674
+
1675
+ var offsets = Position.positionedOffset(element);
1676
+ var top = offsets[1];
1677
+ var left = offsets[0];
1678
+ var width = element.clientWidth;
1679
+ var height = element.clientHeight;
1680
+
1681
+ element._originalLeft = left - parseFloat(element.style.left || 0);
1682
+ element._originalTop = top - parseFloat(element.style.top || 0);
1683
+ element._originalWidth = element.style.width;
1684
+ element._originalHeight = element.style.height;
1685
+
1686
+ element.style.position = 'absolute';
1687
+ element.style.top = top + 'px';;
1688
+ element.style.left = left + 'px';;
1689
+ element.style.width = width + 'px';;
1690
+ element.style.height = height + 'px';;
1691
+ },
1692
+
1693
+ relativize: function(element) {
1694
+ element = $(element);
1695
+ if (element.style.position == 'relative') return;
1696
+ Position.prepare();
1697
+
1698
+ element.style.position = 'relative';
1699
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
1700
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
1701
+
1702
+ element.style.top = top + 'px';
1703
+ element.style.left = left + 'px';
1704
+ element.style.height = element._originalHeight;
1705
+ element.style.width = element._originalWidth;
1037
1706
  }
1038
1707
  }
1708
+
1709
+ // Safari returns margins on body which is incorrect if the child is absolutely
1710
+ // positioned. For performance reasons, redefine Position.cumulativeOffset for
1711
+ // KHTML/WebKit only.
1712
+ if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1713
+ Position.cumulativeOffset = function(element) {
1714
+ var valueT = 0, valueL = 0;
1715
+ do {
1716
+ valueT += element.offsetTop || 0;
1717
+ valueL += element.offsetLeft || 0;
1718
+ if (element.offsetParent == document.body)
1719
+ if (Element.getStyle(element, 'position') == 'absolute') break;
1720
+
1721
+ element = element.offsetParent;
1722
+ } while (element);
1723
+
1724
+ return [valueL, valueT];
1725
+ }
1726
+ }