rainux-selenium-webdriver 0.0.17

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 (192) hide show
  1. data/COPYING +204 -0
  2. data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
  3. data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
  4. data/chrome/src/extension/background.html +9 -0
  5. data/chrome/src/extension/background.js +995 -0
  6. data/chrome/src/extension/content_script.js +1321 -0
  7. data/chrome/src/extension/icons/busy.png +0 -0
  8. data/chrome/src/extension/icons/free.png +0 -0
  9. data/chrome/src/extension/manifest-nonwin.json +19 -0
  10. data/chrome/src/extension/manifest-win.json +20 -0
  11. data/chrome/src/extension/utils.js +231 -0
  12. data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +8 -0
  13. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +358 -0
  14. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +124 -0
  15. data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +135 -0
  16. data/common/src/js/abstractcommandprocessor.js +134 -0
  17. data/common/src/js/asserts.js +296 -0
  18. data/common/src/js/by.js +149 -0
  19. data/common/src/js/command.js +304 -0
  20. data/common/src/js/context.js +58 -0
  21. data/common/src/js/core/Blank.html +7 -0
  22. data/common/src/js/core/InjectedRemoteRunner.html +8 -0
  23. data/common/src/js/core/RemoteRunner.html +101 -0
  24. data/common/src/js/core/SeleniumLog.html +109 -0
  25. data/common/src/js/core/TestPrompt.html +145 -0
  26. data/common/src/js/core/TestRunner-splash.html +55 -0
  27. data/common/src/js/core/TestRunner.html +165 -0
  28. data/common/src/js/core/icons/all.png +0 -0
  29. data/common/src/js/core/icons/continue.png +0 -0
  30. data/common/src/js/core/icons/continue_disabled.png +0 -0
  31. data/common/src/js/core/icons/pause.png +0 -0
  32. data/common/src/js/core/icons/pause_disabled.png +0 -0
  33. data/common/src/js/core/icons/selected.png +0 -0
  34. data/common/src/js/core/icons/step.png +0 -0
  35. data/common/src/js/core/icons/step_disabled.png +0 -0
  36. data/common/src/js/core/lib/cssQuery/cssQuery-p.js +6 -0
  37. data/common/src/js/core/lib/cssQuery/src/cssQuery-level2.js +142 -0
  38. data/common/src/js/core/lib/cssQuery/src/cssQuery-level3.js +150 -0
  39. data/common/src/js/core/lib/cssQuery/src/cssQuery-standard.js +53 -0
  40. data/common/src/js/core/lib/cssQuery/src/cssQuery.js +356 -0
  41. data/common/src/js/core/lib/prototype.js +2006 -0
  42. data/common/src/js/core/lib/scriptaculous/builder.js +101 -0
  43. data/common/src/js/core/lib/scriptaculous/controls.js +815 -0
  44. data/common/src/js/core/lib/scriptaculous/dragdrop.js +915 -0
  45. data/common/src/js/core/lib/scriptaculous/effects.js +958 -0
  46. data/common/src/js/core/lib/scriptaculous/scriptaculous.js +47 -0
  47. data/common/src/js/core/lib/scriptaculous/slider.js +283 -0
  48. data/common/src/js/core/lib/scriptaculous/unittest.js +383 -0
  49. data/common/src/js/core/lib/snapsie.js +91 -0
  50. data/common/src/js/core/scripts/find_matching_child.js +69 -0
  51. data/common/src/js/core/scripts/htmlutils.js +8716 -0
  52. data/common/src/js/core/scripts/injection.html +72 -0
  53. data/common/src/js/core/scripts/selenium-api.js +3291 -0
  54. data/common/src/js/core/scripts/selenium-browserbot.js +2457 -0
  55. data/common/src/js/core/scripts/selenium-browserdetect.js +153 -0
  56. data/common/src/js/core/scripts/selenium-commandhandlers.js +379 -0
  57. data/common/src/js/core/scripts/selenium-executionloop.js +175 -0
  58. data/common/src/js/core/scripts/selenium-logging.js +148 -0
  59. data/common/src/js/core/scripts/selenium-remoterunner.js +695 -0
  60. data/common/src/js/core/scripts/selenium-testrunner.js +1362 -0
  61. data/common/src/js/core/scripts/selenium-version.js +5 -0
  62. data/common/src/js/core/scripts/ui-doc.html +808 -0
  63. data/common/src/js/core/scripts/ui-element.js +1644 -0
  64. data/common/src/js/core/scripts/ui-map-sample.js +979 -0
  65. data/common/src/js/core/scripts/user-extensions.js +3 -0
  66. data/common/src/js/core/scripts/user-extensions.js.sample +75 -0
  67. data/common/src/js/core/scripts/xmlextras.js +153 -0
  68. data/common/src/js/core/selenium-logo.png +0 -0
  69. data/common/src/js/core/selenium-test.css +43 -0
  70. data/common/src/js/core/selenium.css +316 -0
  71. data/common/src/js/core/xpath/dom.js +566 -0
  72. data/common/src/js/core/xpath/javascript-xpath-0.1.11.js +2816 -0
  73. data/common/src/js/core/xpath/util.js +549 -0
  74. data/common/src/js/core/xpath/xmltoken.js +149 -0
  75. data/common/src/js/core/xpath/xpath.js +2481 -0
  76. data/common/src/js/extension/README +2 -0
  77. data/common/src/js/extension/dommessenger.js +152 -0
  78. data/common/src/js/factory.js +55 -0
  79. data/common/src/js/future.js +141 -0
  80. data/common/src/js/jsunit.js +40 -0
  81. data/common/src/js/jsunit/app/css/jsUnitStyle.css +50 -0
  82. data/common/src/js/jsunit/app/css/readme +10 -0
  83. data/common/src/js/jsunit/app/emptyPage.html +11 -0
  84. data/common/src/js/jsunit/app/jsUnitCore.js +534 -0
  85. data/common/src/js/jsunit/app/jsUnitMockTimeout.js +81 -0
  86. data/common/src/js/jsunit/app/jsUnitTestManager.js +705 -0
  87. data/common/src/js/jsunit/app/jsUnitTestSuite.js +44 -0
  88. data/common/src/js/jsunit/app/jsUnitTracer.js +102 -0
  89. data/common/src/js/jsunit/app/jsUnitVersionCheck.js +59 -0
  90. data/common/src/js/jsunit/app/main-counts-errors.html +12 -0
  91. data/common/src/js/jsunit/app/main-counts-failures.html +13 -0
  92. data/common/src/js/jsunit/app/main-counts-runs.html +13 -0
  93. data/common/src/js/jsunit/app/main-counts.html +21 -0
  94. data/common/src/js/jsunit/app/main-data.html +178 -0
  95. data/common/src/js/jsunit/app/main-errors.html +23 -0
  96. data/common/src/js/jsunit/app/main-frame.html +19 -0
  97. data/common/src/js/jsunit/app/main-loader.html +45 -0
  98. data/common/src/js/jsunit/app/main-progress.html +25 -0
  99. data/common/src/js/jsunit/app/main-results.html +67 -0
  100. data/common/src/js/jsunit/app/main-status.html +13 -0
  101. data/common/src/js/jsunit/app/testContainer.html +16 -0
  102. data/common/src/js/jsunit/app/testContainerController.html +77 -0
  103. data/common/src/js/jsunit/app/xbDebug.js +306 -0
  104. data/common/src/js/jsunit/changelog.txt +60 -0
  105. data/common/src/js/jsunit/css/jsUnitStyle.css +83 -0
  106. data/common/src/js/jsunit/images/green.gif +0 -0
  107. data/common/src/js/jsunit/images/logo_jsunit.gif +0 -0
  108. data/common/src/js/jsunit/images/powerby-transparent.gif +0 -0
  109. data/common/src/js/jsunit/images/red.gif +0 -0
  110. data/common/src/js/jsunit/licenses/JDOM_license.txt +56 -0
  111. data/common/src/js/jsunit/licenses/Jetty_license.html +213 -0
  112. data/common/src/js/jsunit/licenses/MPL-1.1.txt +470 -0
  113. data/common/src/js/jsunit/licenses/gpl-2.txt +340 -0
  114. data/common/src/js/jsunit/licenses/index.html +141 -0
  115. data/common/src/js/jsunit/licenses/lgpl-2.1.txt +504 -0
  116. data/common/src/js/jsunit/licenses/mpl-tri-license-c.txt +35 -0
  117. data/common/src/js/jsunit/licenses/mpl-tri-license-html.txt +35 -0
  118. data/common/src/js/jsunit/readme.txt +19 -0
  119. data/common/src/js/jsunit/testRunner.html +167 -0
  120. data/common/src/js/jsunit/version.txt +1 -0
  121. data/common/src/js/key.js +117 -0
  122. data/common/src/js/localcommandprocessor.js +185 -0
  123. data/common/src/js/testcase.js +217 -0
  124. data/common/src/js/timing.js +89 -0
  125. data/common/src/js/webdriver.js +890 -0
  126. data/common/src/js/webelement.js +485 -0
  127. data/common/src/rb/README +30 -0
  128. data/common/src/rb/lib/selenium-webdriver.rb +1 -0
  129. data/common/src/rb/lib/selenium/webdriver.rb +67 -0
  130. data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +91 -0
  131. data/common/src/rb/lib/selenium/webdriver/child_process.rb +180 -0
  132. data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +41 -0
  133. data/common/src/rb/lib/selenium/webdriver/driver.rb +252 -0
  134. data/common/src/rb/lib/selenium/webdriver/driver_extensions/takes_screenshot.rb +24 -0
  135. data/common/src/rb/lib/selenium/webdriver/element.rb +262 -0
  136. data/common/src/rb/lib/selenium/webdriver/error.rb +67 -0
  137. data/common/src/rb/lib/selenium/webdriver/find.rb +89 -0
  138. data/common/src/rb/lib/selenium/webdriver/keys.rb +84 -0
  139. data/common/src/rb/lib/selenium/webdriver/navigation.rb +27 -0
  140. data/common/src/rb/lib/selenium/webdriver/options.rb +50 -0
  141. data/common/src/rb/lib/selenium/webdriver/platform.rb +86 -0
  142. data/common/src/rb/lib/selenium/webdriver/target_locator.rb +70 -0
  143. data/firefox/prebuilt/Win32/Release/webdriver-firefox.dll +0 -0
  144. data/firefox/prebuilt/linux/Release/libwebdriver-firefox.so +0 -0
  145. data/firefox/prebuilt/linux/Release/x_ignore_nofocus.so +0 -0
  146. data/firefox/prebuilt/linux64/Release/libwebdriver-firefox.so +0 -0
  147. data/firefox/prebuilt/linux64/Release/x_ignore_nofocus.so +0 -0
  148. data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
  149. data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
  150. data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
  151. data/firefox/src/extension/chrome.manifest +3 -0
  152. data/firefox/src/extension/components/badCertListener.js +294 -0
  153. data/firefox/src/extension/components/context.js +37 -0
  154. data/firefox/src/extension/components/driver-component.js +127 -0
  155. data/firefox/src/extension/components/firefoxDriver.js +810 -0
  156. data/firefox/src/extension/components/json2.js +273 -0
  157. data/firefox/src/extension/components/keytest.html +554 -0
  158. data/firefox/src/extension/components/nsCommandProcessor.js +643 -0
  159. data/firefox/src/extension/components/promptService.js +208 -0
  160. data/firefox/src/extension/components/screenshooter.js +81 -0
  161. data/firefox/src/extension/components/socketListener.js +185 -0
  162. data/firefox/src/extension/components/utils.js +1263 -0
  163. data/firefox/src/extension/components/webLoadingListener.js +57 -0
  164. data/firefox/src/extension/components/webdriverserver.js +106 -0
  165. data/firefox/src/extension/components/wrappedElement.js +683 -0
  166. data/firefox/src/extension/content/fxdriver.xul +30 -0
  167. data/firefox/src/extension/content/server.js +95 -0
  168. data/firefox/src/extension/idl/nsICommandProcessor.idl +38 -0
  169. data/firefox/src/extension/idl/nsIResponseHandler.idl +34 -0
  170. data/firefox/src/extension/install.rdf +29 -0
  171. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +31 -0
  172. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +107 -0
  173. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +484 -0
  174. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +90 -0
  175. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +155 -0
  176. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +233 -0
  177. data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +59 -0
  178. data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +23 -0
  179. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  180. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  181. data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +14 -0
  182. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +565 -0
  183. data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +99 -0
  184. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +147 -0
  185. data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +16 -0
  186. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +408 -0
  187. data/remote/client/src/rb/lib/selenium/webdriver/remote/capabilities.rb +105 -0
  188. data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +53 -0
  189. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +71 -0
  190. data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +49 -0
  191. data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +32 -0
  192. metadata +303 -0
@@ -0,0 +1,53 @@
1
+ /*
2
+ cssQuery, version 2.0.2 (2005-08-19)
3
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
4
+ License: http://creativecommons.org/licenses/LGPL/2.1/
5
+ */
6
+
7
+ cssQuery.addModule("css-standard", function() { // override IE optimisation
8
+
9
+ // cssQuery was originally written as the CSS engine for IE7. It is
10
+ // optimised (in terms of size not speed) for IE so this module is
11
+ // provided separately to provide cross-browser support.
12
+
13
+ // -----------------------------------------------------------------------
14
+ // browser compatibility
15
+ // -----------------------------------------------------------------------
16
+
17
+ // sniff for Win32 Explorer
18
+ isMSIE = eval("false;/*@cc_on@if(@\x5fwin32)isMSIE=true@end@*/");
19
+
20
+ if (!isMSIE) {
21
+ getElementsByTagName = function($element, $tagName, $namespace) {
22
+ return $namespace ? $element.getElementsByTagNameNS("*", $tagName) :
23
+ $element.getElementsByTagName($tagName);
24
+ };
25
+
26
+ compareNamespace = function($element, $namespace) {
27
+ return !$namespace || ($namespace == "*") || ($element.prefix == $namespace);
28
+ };
29
+
30
+ isXML = document.contentType ? function($element) {
31
+ return /xml/i.test(getDocument($element).contentType);
32
+ } : function($element) {
33
+ return getDocument($element).documentElement.tagName != "HTML";
34
+ };
35
+
36
+ getTextContent = function($element) {
37
+ // mozilla || opera || other
38
+ return $element.textContent || $element.innerText || _getTextContent($element);
39
+ };
40
+
41
+ function _getTextContent($element) {
42
+ var $textContent = "", $node, i;
43
+ for (i = 0; ($node = $element.childNodes[i]); i++) {
44
+ switch ($node.nodeType) {
45
+ case 11: // document fragment
46
+ case 1: $textContent += _getTextContent($node); break;
47
+ case 3: $textContent += $node.nodeValue; break;
48
+ }
49
+ }
50
+ return $textContent;
51
+ };
52
+ }
53
+ }); // addModule
@@ -0,0 +1,356 @@
1
+ /*
2
+ cssQuery, version 2.0.2 (2005-08-19)
3
+ Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
4
+ License: http://creativecommons.org/licenses/LGPL/2.1/
5
+ */
6
+
7
+ // the following functions allow querying of the DOM using CSS selectors
8
+ var cssQuery = function() {
9
+ var version = "2.0.2";
10
+
11
+ // -----------------------------------------------------------------------
12
+ // main query function
13
+ // -----------------------------------------------------------------------
14
+
15
+ var $COMMA = /\s*,\s*/;
16
+ var cssQuery = function($selector, $$from) {
17
+ try {
18
+ var $match = [];
19
+ var $useCache = arguments.callee.caching && !$$from;
20
+ var $base = ($$from) ? ($$from.constructor == Array) ? $$from : [$$from] : [document];
21
+ // process comma separated selectors
22
+ var $$selectors = parseSelector($selector).split($COMMA), i;
23
+ for (i = 0; i < $$selectors.length; i++) {
24
+ // convert the selector to a stream
25
+ $selector = _toStream($$selectors[i]);
26
+ // faster chop if it starts with id (MSIE only)
27
+ if (isMSIE && $selector.slice(0, 3).join("") == " *#") {
28
+ $selector = $selector.slice(2);
29
+ $$from = _msie_selectById([], $base, $selector[1]);
30
+ } else $$from = $base;
31
+ // process the stream
32
+ var j = 0, $token, $filter, $arguments, $cacheSelector = "";
33
+ while (j < $selector.length) {
34
+ $token = $selector[j++];
35
+ $filter = $selector[j++];
36
+ $cacheSelector += $token + $filter;
37
+ // some pseudo-classes allow arguments to be passed
38
+ // e.g. nth-child(even)
39
+ $arguments = "";
40
+ if ($selector[j] == "(") {
41
+ while ($selector[j++] != ")" && j < $selector.length) {
42
+ $arguments += $selector[j];
43
+ }
44
+ $arguments = $arguments.slice(0, -1);
45
+ $cacheSelector += "(" + $arguments + ")";
46
+ }
47
+ // process a token/filter pair use cached results if possible
48
+ $$from = ($useCache && cache[$cacheSelector]) ?
49
+ cache[$cacheSelector] : select($$from, $token, $filter, $arguments);
50
+ if ($useCache) cache[$cacheSelector] = $$from;
51
+ }
52
+ $match = $match.concat($$from);
53
+ }
54
+ delete cssQuery.error;
55
+ return $match;
56
+ } catch ($error) {
57
+ cssQuery.error = $error;
58
+ return [];
59
+ }};
60
+
61
+ // -----------------------------------------------------------------------
62
+ // public interface
63
+ // -----------------------------------------------------------------------
64
+
65
+ cssQuery.toString = function() {
66
+ return "function cssQuery() {\n [version " + version + "]\n}";
67
+ };
68
+
69
+ // caching
70
+ var cache = {};
71
+ cssQuery.caching = false;
72
+ cssQuery.clearCache = function($selector) {
73
+ if ($selector) {
74
+ $selector = _toStream($selector).join("");
75
+ delete cache[$selector];
76
+ } else cache = {};
77
+ };
78
+
79
+ // allow extensions
80
+ var modules = {};
81
+ var loaded = false;
82
+ cssQuery.addModule = function($name, $script) {
83
+ if (loaded) eval("$script=" + String($script));
84
+ modules[$name] = new $script();;
85
+ };
86
+
87
+ // hackery
88
+ cssQuery.valueOf = function($code) {
89
+ return $code ? eval($code) : this;
90
+ };
91
+
92
+ // -----------------------------------------------------------------------
93
+ // declarations
94
+ // -----------------------------------------------------------------------
95
+
96
+ var selectors = {};
97
+ var pseudoClasses = {};
98
+ // a safari bug means that these have to be declared here
99
+ var AttributeSelector = {match: /\[([\w-]+(\|[\w-]+)?)\s*(\W?=)?\s*([^\]]*)\]/};
100
+ var attributeSelectors = [];
101
+
102
+ // -----------------------------------------------------------------------
103
+ // selectors
104
+ // -----------------------------------------------------------------------
105
+
106
+ // descendant selector
107
+ selectors[" "] = function($results, $from, $tagName, $namespace) {
108
+ // loop through current selection
109
+ var $element, i, j;
110
+ for (i = 0; i < $from.length; i++) {
111
+ // get descendants
112
+ var $subset = getElementsByTagName($from[i], $tagName, $namespace);
113
+ // loop through descendants and add to results selection
114
+ for (j = 0; ($element = $subset[j]); j++) {
115
+ if (thisElement($element) && compareNamespace($element, $namespace))
116
+ $results.push($element);
117
+ }
118
+ }
119
+ };
120
+
121
+ // ID selector
122
+ selectors["#"] = function($results, $from, $id) {
123
+ // loop through current selection and check ID
124
+ var $element, j;
125
+ for (j = 0; ($element = $from[j]); j++) if ($element.id == $id) $results.push($element);
126
+ };
127
+
128
+ // class selector
129
+ selectors["."] = function($results, $from, $className) {
130
+ // create a RegExp version of the class
131
+ $className = new RegExp("(^|\\s)" + $className + "(\\s|$)");
132
+ // loop through current selection and check class
133
+ var $element, i;
134
+ for (i = 0; ($element = $from[i]); i++)
135
+ if ($className.test($element.className)) $results.push($element);
136
+ };
137
+
138
+ // pseudo-class selector
139
+ selectors[":"] = function($results, $from, $pseudoClass, $arguments) {
140
+ // retrieve the cssQuery pseudo-class function
141
+ var $test = pseudoClasses[$pseudoClass], $element, i;
142
+ // loop through current selection and apply pseudo-class filter
143
+ if ($test) for (i = 0; ($element = $from[i]); i++)
144
+ // if the cssQuery pseudo-class function returns "true" add the element
145
+ if ($test($element, $arguments)) $results.push($element);
146
+ };
147
+
148
+ // -----------------------------------------------------------------------
149
+ // pseudo-classes
150
+ // -----------------------------------------------------------------------
151
+
152
+ pseudoClasses["link"] = function($element) {
153
+ var $document = getDocument($element);
154
+ if ($document.links) for (var i = 0; i < $document.links.length; i++) {
155
+ if ($document.links[i] == $element) return true;
156
+ }
157
+ };
158
+
159
+ pseudoClasses["visited"] = function($element) {
160
+ // can't do this without jiggery-pokery
161
+ };
162
+
163
+ // -----------------------------------------------------------------------
164
+ // DOM traversal
165
+ // -----------------------------------------------------------------------
166
+
167
+ // IE5/6 includes comments (LOL) in it's elements collections.
168
+ // so we have to check for this. the test is tagName != "!". LOL (again).
169
+ var thisElement = function($element) {
170
+ return ($element && $element.nodeType == 1 && $element.tagName != "!") ? $element : null;
171
+ };
172
+
173
+ // return the previous element to the supplied element
174
+ // previousSibling is not good enough as it might return a text or comment node
175
+ var previousElementSibling = function($element) {
176
+ while ($element && ($element = $element.previousSibling) && !thisElement($element)) continue;
177
+ return $element;
178
+ };
179
+
180
+ // return the next element to the supplied element
181
+ var nextElementSibling = function($element) {
182
+ while ($element && ($element = $element.nextSibling) && !thisElement($element)) continue;
183
+ return $element;
184
+ };
185
+
186
+ // return the first child ELEMENT of an element
187
+ // NOT the first child node (though they may be the same thing)
188
+ var firstElementChild = function($element) {
189
+ return thisElement($element.firstChild) || nextElementSibling($element.firstChild);
190
+ };
191
+
192
+ var lastElementChild = function($element) {
193
+ return thisElement($element.lastChild) || previousElementSibling($element.lastChild);
194
+ };
195
+
196
+ // return child elements of an element (not child nodes)
197
+ var childElements = function($element) {
198
+ var $childElements = [];
199
+ $element = firstElementChild($element);
200
+ while ($element) {
201
+ $childElements.push($element);
202
+ $element = nextElementSibling($element);
203
+ }
204
+ return $childElements;
205
+ };
206
+
207
+ // -----------------------------------------------------------------------
208
+ // browser compatibility
209
+ // -----------------------------------------------------------------------
210
+
211
+ // all of the functions in this section can be overwritten. the default
212
+ // configuration is for IE. The functions below reflect this. standard
213
+ // methods are included in a separate module. It would probably be better
214
+ // the other way round of course but this makes it easier to keep IE7 trim.
215
+
216
+ var isMSIE = true;
217
+
218
+ var isXML = function($element) {
219
+ var $document = getDocument($element);
220
+ return (typeof $document.mimeType == "unknown") ?
221
+ /\.xml$/i.test($document.URL) :
222
+ Boolean($document.mimeType == "XML Document");
223
+ };
224
+
225
+ // return the element's containing document
226
+ var getDocument = function($element) {
227
+ return $element.ownerDocument || $element.document;
228
+ };
229
+
230
+ var getElementsByTagName = function($element, $tagName) {
231
+ return ($tagName == "*" && $element.all) ? $element.all : $element.getElementsByTagName($tagName);
232
+ };
233
+
234
+ var compareTagName = function($element, $tagName, $namespace) {
235
+ if ($tagName == "*") return thisElement($element);
236
+ if (!compareNamespace($element, $namespace)) return false;
237
+ if (!isXML($element)) $tagName = $tagName.toUpperCase();
238
+ return $element.tagName == $tagName;
239
+ };
240
+
241
+ var compareNamespace = function($element, $namespace) {
242
+ return !$namespace || ($namespace == "*") || ($element.scopeName == $namespace);
243
+ };
244
+
245
+ var getTextContent = function($element) {
246
+ return $element.innerText;
247
+ };
248
+
249
+ function _msie_selectById($results, $from, id) {
250
+ var $match, i, j;
251
+ for (i = 0; i < $from.length; i++) {
252
+ if ($match = $from[i].all.item(id)) {
253
+ if ($match.id == id) $results.push($match);
254
+ else if ($match.length != null) {
255
+ for (j = 0; j < $match.length; j++) {
256
+ if ($match[j].id == id) $results.push($match[j]);
257
+ }
258
+ }
259
+ }
260
+ }
261
+ return $results;
262
+ };
263
+
264
+ // for IE5.0
265
+ if (![].push) Array.prototype.push = function() {
266
+ for (var i = 0; i < arguments.length; i++) {
267
+ this[this.length] = arguments[i];
268
+ }
269
+ return this.length;
270
+ };
271
+
272
+ // -----------------------------------------------------------------------
273
+ // query support
274
+ // -----------------------------------------------------------------------
275
+
276
+ // select a set of matching elements.
277
+ // "from" is an array of elements.
278
+ // "token" is a character representing the type of filter
279
+ // e.g. ">" means child selector
280
+ // "filter" represents the tag name, id or class name that is being selected
281
+ // the function returns an array of matching elements
282
+ var $NAMESPACE = /\|/;
283
+ function select($$from, $token, $filter, $arguments) {
284
+ if ($NAMESPACE.test($filter)) {
285
+ $filter = $filter.split($NAMESPACE);
286
+ $arguments = $filter[0];
287
+ $filter = $filter[1];
288
+ }
289
+ var $results = [];
290
+ if (selectors[$token]) {
291
+ selectors[$token]($results, $$from, $filter, $arguments);
292
+ }
293
+ return $results;
294
+ };
295
+
296
+ // -----------------------------------------------------------------------
297
+ // parsing
298
+ // -----------------------------------------------------------------------
299
+
300
+ // convert css selectors to a stream of tokens and filters
301
+ // it's not a real stream. it's just an array of strings.
302
+ var $STANDARD_SELECT = /^[^\s>+~]/;
303
+ var $$STREAM = /[\s#.:>+~()@]|[^\s#.:>+~()@]+/g;
304
+ function _toStream($selector) {
305
+ if ($STANDARD_SELECT.test($selector)) $selector = " " + $selector;
306
+ return $selector.match($$STREAM) || [];
307
+ };
308
+
309
+ var $WHITESPACE = /\s*([\s>+~(),]|^|$)\s*/g;
310
+ var $IMPLIED_ALL = /([\s>+~,]|[^(]\+|^)([#.:@])/g;
311
+ var parseSelector = function($selector) {
312
+ return $selector
313
+ // trim whitespace
314
+ .replace($WHITESPACE, "$1")
315
+ // e.g. ".class1" --> "*.class1"
316
+ .replace($IMPLIED_ALL, "$1*$2");
317
+ };
318
+
319
+ var Quote = {
320
+ toString: function() {return "'"},
321
+ match: /^('[^']*')|("[^"]*")$/,
322
+ test: function($string) {
323
+ return this.match.test($string);
324
+ },
325
+ add: function($string) {
326
+ return this.test($string) ? $string : this + $string + this;
327
+ },
328
+ remove: function($string) {
329
+ return this.test($string) ? $string.slice(1, -1) : $string;
330
+ }
331
+ };
332
+
333
+ var getText = function($text) {
334
+ return Quote.remove($text);
335
+ };
336
+
337
+ var $ESCAPE = /([\/()[\]?{}|*+-])/g;
338
+ function regEscape($string) {
339
+ return $string.replace($ESCAPE, "\\$1");
340
+ };
341
+
342
+ // -----------------------------------------------------------------------
343
+ // modules
344
+ // -----------------------------------------------------------------------
345
+
346
+ // -------- >> insert modules here for packaging << -------- \\
347
+
348
+ loaded = true;
349
+
350
+ // -----------------------------------------------------------------------
351
+ // return the query function
352
+ // -----------------------------------------------------------------------
353
+
354
+ return cssQuery;
355
+
356
+ }(); // cssQuery
@@ -0,0 +1,2006 @@
1
+ /* Prototype JavaScript framework, version 1.5.0_rc0
2
+ * (c) 2005 Sam Stephenson <sam@conio.net>
3
+ *
4
+ * Prototype is freely distributable under the terms of an MIT-style license.
5
+ * For details, see the Prototype web site: http://prototype.conio.net/
6
+ *
7
+ /*--------------------------------------------------------------------------*/
8
+
9
+ var Prototype = {
10
+ Version: '1.5.0_rc0',
11
+ ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
12
+
13
+ emptyFunction: function() {},
14
+ K: function(x) {return x}
15
+ }
16
+
17
+ var Class = {
18
+ create: function() {
19
+ return function() {
20
+ this.initialize.apply(this, arguments);
21
+ }
22
+ }
23
+ }
24
+
25
+ var Abstract = new Object();
26
+
27
+ Object.extend = function(destination, source) {
28
+ for (var property in source) {
29
+ destination[property] = source[property];
30
+ }
31
+ return destination;
32
+ }
33
+
34
+ Object.inspect = function(object) {
35
+ try {
36
+ if (object == undefined) return 'undefined';
37
+ if (object == null) return 'null';
38
+ return object.inspect ? object.inspect() : object.toString();
39
+ } catch (e) {
40
+ if (e instanceof RangeError) return '...';
41
+ throw e;
42
+ }
43
+ }
44
+
45
+ Function.prototype.bind = function() {
46
+ var __method = this, args = $A(arguments), object = args.shift();
47
+ return function() {
48
+ return __method.apply(object, args.concat($A(arguments)));
49
+ }
50
+ }
51
+
52
+ Function.prototype.bindAsEventListener = function(object) {
53
+ var __method = this;
54
+ return function(event) {
55
+ return __method.call(object, event || window.event);
56
+ }
57
+ }
58
+
59
+ Object.extend(Number.prototype, {
60
+ toColorPart: function() {
61
+ var digits = this.toString(16);
62
+ if (this < 16) return '0' + digits;
63
+ return digits;
64
+ },
65
+
66
+ succ: function() {
67
+ return this + 1;
68
+ },
69
+
70
+ times: function(iterator) {
71
+ $R(0, this, true).each(iterator);
72
+ return this;
73
+ }
74
+ });
75
+
76
+ var Try = {
77
+ these: function() {
78
+ var returnValue;
79
+
80
+ for (var i = 0; i < arguments.length; i++) {
81
+ var lambda = arguments[i];
82
+ try {
83
+ returnValue = lambda();
84
+ break;
85
+ } catch (e) {}
86
+ }
87
+
88
+ return returnValue;
89
+ }
90
+ }
91
+
92
+ /*--------------------------------------------------------------------------*/
93
+
94
+ var PeriodicalExecuter = Class.create();
95
+ PeriodicalExecuter.prototype = {
96
+ initialize: function(callback, frequency) {
97
+ this.callback = callback;
98
+ this.frequency = frequency;
99
+ this.currentlyExecuting = false;
100
+
101
+ this.registerCallback();
102
+ },
103
+
104
+ registerCallback: function() {
105
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
106
+ },
107
+
108
+ onTimerEvent: function() {
109
+ if (!this.currentlyExecuting) {
110
+ try {
111
+ this.currentlyExecuting = true;
112
+ this.callback();
113
+ } finally {
114
+ this.currentlyExecuting = false;
115
+ }
116
+ }
117
+ }
118
+ }
119
+ Object.extend(String.prototype, {
120
+ gsub: function(pattern, replacement) {
121
+ var result = '', source = this, match;
122
+ replacement = arguments.callee.prepareReplacement(replacement);
123
+
124
+ while (source.length > 0) {
125
+ if (match = source.match(pattern)) {
126
+ result += source.slice(0, match.index);
127
+ result += (replacement(match) || '').toString();
128
+ source = source.slice(match.index + match[0].length);
129
+ } else {
130
+ result += source, source = '';
131
+ }
132
+ }
133
+ return result;
134
+ },
135
+
136
+ sub: function(pattern, replacement, count) {
137
+ replacement = this.gsub.prepareReplacement(replacement);
138
+ count = count === undefined ? 1 : count;
139
+
140
+ return this.gsub(pattern, function(match) {
141
+ if (--count < 0) return match[0];
142
+ return replacement(match);
143
+ });
144
+ },
145
+
146
+ scan: function(pattern, iterator) {
147
+ this.gsub(pattern, iterator);
148
+ return this;
149
+ },
150
+
151
+ truncate: function(length, truncation) {
152
+ length = length || 30;
153
+ truncation = truncation === undefined ? '...' : truncation;
154
+ return this.length > length ?
155
+ this.slice(0, length - truncation.length) + truncation : this;
156
+ },
157
+
158
+ strip: function() {
159
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
160
+ },
161
+
162
+ stripTags: function() {
163
+ return this.replace(/<\/?[^>]+>/gi, '');
164
+ },
165
+
166
+ stripScripts: function() {
167
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
168
+ },
169
+
170
+ extractScripts: function() {
171
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
172
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
173
+ return (this.match(matchAll) || []).map(function(scriptTag) {
174
+ return (scriptTag.match(matchOne) || ['', ''])[1];
175
+ });
176
+ },
177
+
178
+ evalScripts: function() {
179
+ return this.extractScripts().map(function(script) { return eval(script) });
180
+ },
181
+
182
+ escapeHTML: function() {
183
+ var div = document.createElement('div');
184
+ var text = document.createTextNode(this);
185
+ div.appendChild(text);
186
+ return div.innerHTML;
187
+ },
188
+
189
+ unescapeHTML: function() {
190
+ var div = document.createElement('div');
191
+ div.innerHTML = this.stripTags();
192
+ return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
193
+ },
194
+
195
+ toQueryParams: function() {
196
+ var pairs = this.match(/^\??(.*)$/)[1].split('&');
197
+ return pairs.inject({}, function(params, pairString) {
198
+ var pair = pairString.split('=');
199
+ params[pair[0]] = pair[1];
200
+ return params;
201
+ });
202
+ },
203
+
204
+ toArray: function() {
205
+ return this.split('');
206
+ },
207
+
208
+ camelize: function() {
209
+ var oStringList = this.split('-');
210
+ if (oStringList.length == 1) return oStringList[0];
211
+
212
+ var camelizedString = this.indexOf('-') == 0
213
+ ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
214
+ : oStringList[0];
215
+
216
+ for (var i = 1, len = oStringList.length; i < len; i++) {
217
+ var s = oStringList[i];
218
+ camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
219
+ }
220
+
221
+ return camelizedString;
222
+ },
223
+
224
+ inspect: function() {
225
+ return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
226
+ }
227
+ });
228
+
229
+ String.prototype.gsub.prepareReplacement = function(replacement) {
230
+ if (typeof replacement == 'function') return replacement;
231
+ var template = new Template(replacement);
232
+ return function(match) { return template.evaluate(match) };
233
+ }
234
+
235
+ String.prototype.parseQuery = String.prototype.toQueryParams;
236
+
237
+ var Template = Class.create();
238
+ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
239
+ Template.prototype = {
240
+ initialize: function(template, pattern) {
241
+ this.template = template.toString();
242
+ this.pattern = pattern || Template.Pattern;
243
+ },
244
+
245
+ evaluate: function(object) {
246
+ return this.template.gsub(this.pattern, function(match) {
247
+ var before = match[1];
248
+ if (before == '\\') return match[2];
249
+ return before + (object[match[3]] || '').toString();
250
+ });
251
+ }
252
+ }
253
+
254
+ var $break = new Object();
255
+ var $continue = new Object();
256
+
257
+ var Enumerable = {
258
+ each: function(iterator) {
259
+ var index = 0;
260
+ try {
261
+ this._each(function(value) {
262
+ try {
263
+ iterator(value, index++);
264
+ } catch (e) {
265
+ if (e != $continue) throw e;
266
+ }
267
+ });
268
+ } catch (e) {
269
+ if (e != $break) throw e;
270
+ }
271
+ },
272
+
273
+ all: function(iterator) {
274
+ var result = true;
275
+ this.each(function(value, index) {
276
+ result = result && !!(iterator || Prototype.K)(value, index);
277
+ if (!result) throw $break;
278
+ });
279
+ return result;
280
+ },
281
+
282
+ any: function(iterator) {
283
+ var result = true;
284
+ this.each(function(value, index) {
285
+ if (result = !!(iterator || Prototype.K)(value, index))
286
+ throw $break;
287
+ });
288
+ return result;
289
+ },
290
+
291
+ collect: function(iterator) {
292
+ var results = [];
293
+ this.each(function(value, index) {
294
+ results.push(iterator(value, index));
295
+ });
296
+ return results;
297
+ },
298
+
299
+ detect: function (iterator) {
300
+ var result;
301
+ this.each(function(value, index) {
302
+ if (iterator(value, index)) {
303
+ result = value;
304
+ throw $break;
305
+ }
306
+ });
307
+ return result;
308
+ },
309
+
310
+ findAll: function(iterator) {
311
+ var results = [];
312
+ this.each(function(value, index) {
313
+ if (iterator(value, index))
314
+ results.push(value);
315
+ });
316
+ return results;
317
+ },
318
+
319
+ grep: function(pattern, iterator) {
320
+ var results = [];
321
+ this.each(function(value, index) {
322
+ var stringValue = value.toString();
323
+ if (stringValue.match(pattern))
324
+ results.push((iterator || Prototype.K)(value, index));
325
+ })
326
+ return results;
327
+ },
328
+
329
+ include: function(object) {
330
+ var found = false;
331
+ this.each(function(value) {
332
+ if (value == object) {
333
+ found = true;
334
+ throw $break;
335
+ }
336
+ });
337
+ return found;
338
+ },
339
+
340
+ inject: function(memo, iterator) {
341
+ this.each(function(value, index) {
342
+ memo = iterator(memo, value, index);
343
+ });
344
+ return memo;
345
+ },
346
+
347
+ invoke: function(method) {
348
+ var args = $A(arguments).slice(1);
349
+ return this.collect(function(value) {
350
+ return value[method].apply(value, args);
351
+ });
352
+ },
353
+
354
+ max: function(iterator) {
355
+ var result;
356
+ this.each(function(value, index) {
357
+ value = (iterator || Prototype.K)(value, index);
358
+ if (result == undefined || value >= result)
359
+ result = value;
360
+ });
361
+ return result;
362
+ },
363
+
364
+ min: function(iterator) {
365
+ var result;
366
+ this.each(function(value, index) {
367
+ value = (iterator || Prototype.K)(value, index);
368
+ if (result == undefined || value < result)
369
+ result = value;
370
+ });
371
+ return result;
372
+ },
373
+
374
+ partition: function(iterator) {
375
+ var trues = [], falses = [];
376
+ this.each(function(value, index) {
377
+ ((iterator || Prototype.K)(value, index) ?
378
+ trues : falses).push(value);
379
+ });
380
+ return [trues, falses];
381
+ },
382
+
383
+ pluck: function(property) {
384
+ var results = [];
385
+ this.each(function(value, index) {
386
+ results.push(value[property]);
387
+ });
388
+ return results;
389
+ },
390
+
391
+ reject: function(iterator) {
392
+ var results = [];
393
+ this.each(function(value, index) {
394
+ if (!iterator(value, index))
395
+ results.push(value);
396
+ });
397
+ return results;
398
+ },
399
+
400
+ sortBy: function(iterator) {
401
+ return this.collect(function(value, index) {
402
+ return {value: value, criteria: iterator(value, index)};
403
+ }).sort(function(left, right) {
404
+ var a = left.criteria, b = right.criteria;
405
+ return a < b ? -1 : a > b ? 1 : 0;
406
+ }).pluck('value');
407
+ },
408
+
409
+ toArray: function() {
410
+ return this.collect(Prototype.K);
411
+ },
412
+
413
+ zip: function() {
414
+ var iterator = Prototype.K, args = $A(arguments);
415
+ if (typeof args.last() == 'function')
416
+ iterator = args.pop();
417
+
418
+ var collections = [this].concat(args).map($A);
419
+ return this.map(function(value, index) {
420
+ return iterator(collections.pluck(index));
421
+ });
422
+ },
423
+
424
+ inspect: function() {
425
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
426
+ }
427
+ }
428
+
429
+ Object.extend(Enumerable, {
430
+ map: Enumerable.collect,
431
+ find: Enumerable.detect,
432
+ select: Enumerable.findAll,
433
+ member: Enumerable.include,
434
+ entries: Enumerable.toArray
435
+ });
436
+ var $A = Array.from = function(iterable) {
437
+ if (!iterable) return [];
438
+ if (iterable.toArray) {
439
+ return iterable.toArray();
440
+ } else {
441
+ var results = [];
442
+ for (var i = 0; i < iterable.length; i++)
443
+ results.push(iterable[i]);
444
+ return results;
445
+ }
446
+ }
447
+
448
+ Object.extend(Array.prototype, Enumerable);
449
+
450
+ if (!Array.prototype._reverse)
451
+ Array.prototype._reverse = Array.prototype.reverse;
452
+
453
+ Object.extend(Array.prototype, {
454
+ _each: function(iterator) {
455
+ for (var i = 0; i < this.length; i++)
456
+ iterator(this[i]);
457
+ },
458
+
459
+ clear: function() {
460
+ this.length = 0;
461
+ return this;
462
+ },
463
+
464
+ first: function() {
465
+ return this[0];
466
+ },
467
+
468
+ last: function() {
469
+ return this[this.length - 1];
470
+ },
471
+
472
+ compact: function() {
473
+ return this.select(function(value) {
474
+ return value != undefined || value != null;
475
+ });
476
+ },
477
+
478
+ flatten: function() {
479
+ return this.inject([], function(array, value) {
480
+ return array.concat(value && value.constructor == Array ?
481
+ value.flatten() : [value]);
482
+ });
483
+ },
484
+
485
+ without: function() {
486
+ var values = $A(arguments);
487
+ return this.select(function(value) {
488
+ return !values.include(value);
489
+ });
490
+ },
491
+
492
+ indexOf: function(object) {
493
+ for (var i = 0; i < this.length; i++)
494
+ if (this[i] == object) return i;
495
+ return -1;
496
+ },
497
+
498
+ reverse: function(inline) {
499
+ return (inline !== false ? this : this.toArray())._reverse();
500
+ },
501
+
502
+ inspect: function() {
503
+ return '[' + this.map(Object.inspect).join(', ') + ']';
504
+ }
505
+ });
506
+ var Hash = {
507
+ _each: function(iterator) {
508
+ for (var key in this) {
509
+ var value = this[key];
510
+ if (typeof value == 'function') continue;
511
+
512
+ var pair = [key, value];
513
+ pair.key = key;
514
+ pair.value = value;
515
+ iterator(pair);
516
+ }
517
+ },
518
+
519
+ keys: function() {
520
+ return this.pluck('key');
521
+ },
522
+
523
+ values: function() {
524
+ return this.pluck('value');
525
+ },
526
+
527
+ merge: function(hash) {
528
+ return $H(hash).inject($H(this), function(mergedHash, pair) {
529
+ mergedHash[pair.key] = pair.value;
530
+ return mergedHash;
531
+ });
532
+ },
533
+
534
+ toQueryString: function() {
535
+ return this.map(function(pair) {
536
+ return pair.map(encodeURIComponent).join('=');
537
+ }).join('&');
538
+ },
539
+
540
+ inspect: function() {
541
+ return '#<Hash:{' + this.map(function(pair) {
542
+ return pair.map(Object.inspect).join(': ');
543
+ }).join(', ') + '}>';
544
+ }
545
+ }
546
+
547
+ function $H(object) {
548
+ var hash = Object.extend({}, object || {});
549
+ Object.extend(hash, Enumerable);
550
+ Object.extend(hash, Hash);
551
+ return hash;
552
+ }
553
+ ObjectRange = Class.create();
554
+ Object.extend(ObjectRange.prototype, Enumerable);
555
+ Object.extend(ObjectRange.prototype, {
556
+ initialize: function(start, end, exclusive) {
557
+ this.start = start;
558
+ this.end = end;
559
+ this.exclusive = exclusive;
560
+ },
561
+
562
+ _each: function(iterator) {
563
+ var value = this.start;
564
+ do {
565
+ iterator(value);
566
+ value = value.succ();
567
+ } while (this.include(value));
568
+ },
569
+
570
+ include: function(value) {
571
+ if (value < this.start)
572
+ return false;
573
+ if (this.exclusive)
574
+ return value < this.end;
575
+ return value <= this.end;
576
+ }
577
+ });
578
+
579
+ var $R = function(start, end, exclusive) {
580
+ return new ObjectRange(start, end, exclusive);
581
+ }
582
+
583
+ var Ajax = {
584
+ getTransport: function() {
585
+ return Try.these(
586
+ function() {return new XMLHttpRequest()},
587
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
588
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
589
+ ) || false;
590
+ },
591
+
592
+ activeRequestCount: 0
593
+ }
594
+
595
+ Ajax.Responders = {
596
+ responders: [],
597
+
598
+ _each: function(iterator) {
599
+ this.responders._each(iterator);
600
+ },
601
+
602
+ register: function(responderToAdd) {
603
+ if (!this.include(responderToAdd))
604
+ this.responders.push(responderToAdd);
605
+ },
606
+
607
+ unregister: function(responderToRemove) {
608
+ this.responders = this.responders.without(responderToRemove);
609
+ },
610
+
611
+ dispatch: function(callback, request, transport, json) {
612
+ this.each(function(responder) {
613
+ if (responder[callback] && typeof responder[callback] == 'function') {
614
+ try {
615
+ responder[callback].apply(responder, [request, transport, json]);
616
+ } catch (e) {}
617
+ }
618
+ });
619
+ }
620
+ };
621
+
622
+ Object.extend(Ajax.Responders, Enumerable);
623
+
624
+ Ajax.Responders.register({
625
+ onCreate: function() {
626
+ Ajax.activeRequestCount++;
627
+ },
628
+
629
+ onComplete: function() {
630
+ Ajax.activeRequestCount--;
631
+ }
632
+ });
633
+
634
+ Ajax.Base = function() {};
635
+ Ajax.Base.prototype = {
636
+ setOptions: function(options) {
637
+ this.options = {
638
+ method: 'post',
639
+ asynchronous: true,
640
+ contentType: 'application/x-www-form-urlencoded',
641
+ parameters: ''
642
+ }
643
+ Object.extend(this.options, options || {});
644
+ },
645
+
646
+ responseIsSuccess: function() {
647
+ return this.transport.status == undefined
648
+ || this.transport.status == 0
649
+ || (this.transport.status >= 200 && this.transport.status < 300);
650
+ },
651
+
652
+ responseIsFailure: function() {
653
+ return !this.responseIsSuccess();
654
+ }
655
+ }
656
+
657
+ Ajax.Request = Class.create();
658
+ Ajax.Request.Events =
659
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
660
+
661
+ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
662
+ initialize: function(url, options) {
663
+ this.transport = Ajax.getTransport();
664
+ this.setOptions(options);
665
+ this.request(url);
666
+ },
667
+
668
+ request: function(url) {
669
+ var parameters = this.options.parameters || '';
670
+ if (parameters.length > 0) parameters += '&_=';
671
+
672
+ try {
673
+ this.url = url;
674
+ if (this.options.method == 'get' && parameters.length > 0)
675
+ this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
676
+
677
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
678
+
679
+ this.transport.open(this.options.method, this.url,
680
+ this.options.asynchronous);
681
+
682
+ if (this.options.asynchronous) {
683
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
684
+ setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
685
+ }
686
+
687
+ this.setRequestHeaders();
688
+
689
+ var body = this.options.postBody ? this.options.postBody : parameters;
690
+ this.transport.send(this.options.method == 'post' ? body : null);
691
+
692
+ } catch (e) {
693
+ this.dispatchException(e);
694
+ }
695
+ },
696
+
697
+ setRequestHeaders: function() {
698
+ var requestHeaders =
699
+ ['X-Requested-With', 'XMLHttpRequest',
700
+ 'X-Prototype-Version', Prototype.Version,
701
+ 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
702
+
703
+ if (this.options.method == 'post') {
704
+ requestHeaders.push('Content-type', this.options.contentType);
705
+
706
+ /* Force "Connection: close" for Mozilla browsers to work around
707
+ * a bug where XMLHttpReqeuest sends an incorrect Content-length
708
+ * header. See Mozilla Bugzilla #246651.
709
+ */
710
+ if (this.transport.overrideMimeType)
711
+ requestHeaders.push('Connection', 'close');
712
+ }
713
+
714
+ if (this.options.requestHeaders)
715
+ requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
716
+
717
+ for (var i = 0; i < requestHeaders.length; i += 2)
718
+ this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
719
+ },
720
+
721
+ onStateChange: function() {
722
+ var readyState = this.transport.readyState;
723
+ if (readyState != 1)
724
+ this.respondToReadyState(this.transport.readyState);
725
+ },
726
+
727
+ header: function(name) {
728
+ try {
729
+ return this.transport.getResponseHeader(name);
730
+ } catch (e) {}
731
+ },
732
+
733
+ evalJSON: function() {
734
+ try {
735
+ return eval('(' + this.header('X-JSON') + ')');
736
+ } catch (e) {}
737
+ },
738
+
739
+ evalResponse: function() {
740
+ try {
741
+ return eval(this.transport.responseText);
742
+ } catch (e) {
743
+ this.dispatchException(e);
744
+ }
745
+ },
746
+
747
+ respondToReadyState: function(readyState) {
748
+ var event = Ajax.Request.Events[readyState];
749
+ var transport = this.transport, json = this.evalJSON();
750
+
751
+ if (event == 'Complete') {
752
+ try {
753
+ (this.options['on' + this.transport.status]
754
+ || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
755
+ || Prototype.emptyFunction)(transport, json);
756
+ } catch (e) {
757
+ this.dispatchException(e);
758
+ }
759
+
760
+ if ((this.header('Content-type') || '').match(/^text\/javascript/i))
761
+ this.evalResponse();
762
+ }
763
+
764
+ try {
765
+ (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
766
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
767
+ } catch (e) {
768
+ this.dispatchException(e);
769
+ }
770
+
771
+ /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
772
+ if (event == 'Complete')
773
+ this.transport.onreadystatechange = Prototype.emptyFunction;
774
+ },
775
+
776
+ dispatchException: function(exception) {
777
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
778
+ Ajax.Responders.dispatch('onException', this, exception);
779
+ }
780
+ });
781
+
782
+ Ajax.Updater = Class.create();
783
+
784
+ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
785
+ initialize: function(container, url, options) {
786
+ this.containers = {
787
+ success: container.success ? $(container.success) : $(container),
788
+ failure: container.failure ? $(container.failure) :
789
+ (container.success ? null : $(container))
790
+ }
791
+
792
+ this.transport = Ajax.getTransport();
793
+ this.setOptions(options);
794
+
795
+ var onComplete = this.options.onComplete || Prototype.emptyFunction;
796
+ this.options.onComplete = (function(transport, object) {
797
+ this.updateContent();
798
+ onComplete(transport, object);
799
+ }).bind(this);
800
+
801
+ this.request(url);
802
+ },
803
+
804
+ updateContent: function() {
805
+ var receiver = this.responseIsSuccess() ?
806
+ this.containers.success : this.containers.failure;
807
+ var response = this.transport.responseText;
808
+
809
+ if (!this.options.evalScripts)
810
+ response = response.stripScripts();
811
+
812
+ if (receiver) {
813
+ if (this.options.insertion) {
814
+ new this.options.insertion(receiver, response);
815
+ } else {
816
+ Element.update(receiver, response);
817
+ }
818
+ }
819
+
820
+ if (this.responseIsSuccess()) {
821
+ if (this.onComplete)
822
+ setTimeout(this.onComplete.bind(this), 10);
823
+ }
824
+ }
825
+ });
826
+
827
+ Ajax.PeriodicalUpdater = Class.create();
828
+ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
829
+ initialize: function(container, url, options) {
830
+ this.setOptions(options);
831
+ this.onComplete = this.options.onComplete;
832
+
833
+ this.frequency = (this.options.frequency || 2);
834
+ this.decay = (this.options.decay || 1);
835
+
836
+ this.updater = {};
837
+ this.container = container;
838
+ this.url = url;
839
+
840
+ this.start();
841
+ },
842
+
843
+ start: function() {
844
+ this.options.onComplete = this.updateComplete.bind(this);
845
+ this.onTimerEvent();
846
+ },
847
+
848
+ stop: function() {
849
+ this.updater.onComplete = undefined;
850
+ clearTimeout(this.timer);
851
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
852
+ },
853
+
854
+ updateComplete: function(request) {
855
+ if (this.options.decay) {
856
+ this.decay = (request.responseText == this.lastText ?
857
+ this.decay * this.options.decay : 1);
858
+
859
+ this.lastText = request.responseText;
860
+ }
861
+ this.timer = setTimeout(this.onTimerEvent.bind(this),
862
+ this.decay * this.frequency * 1000);
863
+ },
864
+
865
+ onTimerEvent: function() {
866
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
867
+ }
868
+ });
869
+ function $() {
870
+ var results = [], element;
871
+ for (var i = 0; i < arguments.length; i++) {
872
+ element = arguments[i];
873
+ if (typeof element == 'string')
874
+ element = document.getElementById(element);
875
+ results.push(Element.extend(element));
876
+ }
877
+ return results.length < 2 ? results[0] : results;
878
+ }
879
+
880
+ document.getElementsByClassName = function(className, parentElement) {
881
+ var children = ($(parentElement) || document.body).getElementsByTagName('*');
882
+ return $A(children).inject([], function(elements, child) {
883
+ if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
884
+ elements.push(Element.extend(child));
885
+ return elements;
886
+ });
887
+ }
888
+
889
+ /*--------------------------------------------------------------------------*/
890
+
891
+ if (!window.Element)
892
+ var Element = new Object();
893
+
894
+ Element.extend = function(element) {
895
+ if (!element) return;
896
+ if (_nativeExtensions) return element;
897
+
898
+ if (!element._extended && element.tagName && element != window) {
899
+ var methods = Element.Methods, cache = Element.extend.cache;
900
+ for (property in methods) {
901
+ var value = methods[property];
902
+ if (typeof value == 'function')
903
+ element[property] = cache.findOrStore(value);
904
+ }
905
+ }
906
+
907
+ element._extended = true;
908
+ return element;
909
+ }
910
+
911
+ Element.extend.cache = {
912
+ findOrStore: function(value) {
913
+ return this[value] = this[value] || function() {
914
+ return value.apply(null, [this].concat($A(arguments)));
915
+ }
916
+ }
917
+ }
918
+
919
+ Element.Methods = {
920
+ visible: function(element) {
921
+ return $(element).style.display != 'none';
922
+ },
923
+
924
+ toggle: function() {
925
+ for (var i = 0; i < arguments.length; i++) {
926
+ var element = $(arguments[i]);
927
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
928
+ }
929
+ },
930
+
931
+ hide: function() {
932
+ for (var i = 0; i < arguments.length; i++) {
933
+ var element = $(arguments[i]);
934
+ element.style.display = 'none';
935
+ }
936
+ },
937
+
938
+ show: function() {
939
+ for (var i = 0; i < arguments.length; i++) {
940
+ var element = $(arguments[i]);
941
+ element.style.display = '';
942
+ }
943
+ },
944
+
945
+ remove: function(element) {
946
+ element = $(element);
947
+ element.parentNode.removeChild(element);
948
+ },
949
+
950
+ update: function(element, html) {
951
+ $(element).innerHTML = html.stripScripts();
952
+ setTimeout(function() {html.evalScripts()}, 10);
953
+ },
954
+
955
+ replace: function(element, html) {
956
+ element = $(element);
957
+ if (element.outerHTML) {
958
+ element.outerHTML = html.stripScripts();
959
+ } else {
960
+ var range = element.ownerDocument.createRange();
961
+ range.selectNodeContents(element);
962
+ element.parentNode.replaceChild(
963
+ range.createContextualFragment(html.stripScripts()), element);
964
+ }
965
+ setTimeout(function() {html.evalScripts()}, 10);
966
+ },
967
+
968
+ getHeight: function(element) {
969
+ element = $(element);
970
+ return element.offsetHeight;
971
+ },
972
+
973
+ classNames: function(element) {
974
+ return new Element.ClassNames(element);
975
+ },
976
+
977
+ hasClassName: function(element, className) {
978
+ if (!(element = $(element))) return;
979
+ return Element.classNames(element).include(className);
980
+ },
981
+
982
+ addClassName: function(element, className) {
983
+ if (!(element = $(element))) return;
984
+ return Element.classNames(element).add(className);
985
+ },
986
+
987
+ removeClassName: function(element, className) {
988
+ if (!(element = $(element))) return;
989
+ return Element.classNames(element).remove(className);
990
+ },
991
+
992
+ // removes whitespace-only text node children
993
+ cleanWhitespace: function(element) {
994
+ element = $(element);
995
+ for (var i = 0; i < element.childNodes.length; i++) {
996
+ var node = element.childNodes[i];
997
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
998
+ Element.remove(node);
999
+ }
1000
+ },
1001
+
1002
+ empty: function(element) {
1003
+ return $(element).innerHTML.match(/^\s*$/);
1004
+ },
1005
+
1006
+ childOf: function(element, ancestor) {
1007
+ element = $(element), ancestor = $(ancestor);
1008
+ while (element = element.parentNode)
1009
+ if (element == ancestor) return true;
1010
+ return false;
1011
+ },
1012
+
1013
+ scrollTo: function(element) {
1014
+ element = $(element);
1015
+ var x = element.x ? element.x : element.offsetLeft,
1016
+ y = element.y ? element.y : element.offsetTop;
1017
+ window.scrollTo(x, y);
1018
+ },
1019
+
1020
+ getStyle: function(element, style) {
1021
+ element = $(element);
1022
+ var value = element.style[style.camelize()];
1023
+ if (!value) {
1024
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1025
+ var css = document.defaultView.getComputedStyle(element, null);
1026
+ value = css ? css.getPropertyValue(style) : null;
1027
+ } else if (element.currentStyle) {
1028
+ value = element.currentStyle[style.camelize()];
1029
+ }
1030
+ }
1031
+
1032
+ if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
1033
+ if (Element.getStyle(element, 'position') == 'static') value = 'auto';
1034
+
1035
+ return value == 'auto' ? null : value;
1036
+ },
1037
+
1038
+ setStyle: function(element, style) {
1039
+ element = $(element);
1040
+ for (var name in style)
1041
+ element.style[name.camelize()] = style[name];
1042
+ },
1043
+
1044
+ getDimensions: function(element) {
1045
+ element = $(element);
1046
+ if (Element.getStyle(element, 'display') != 'none')
1047
+ return {width: element.offsetWidth, height: element.offsetHeight};
1048
+
1049
+ // All *Width and *Height properties give 0 on elements with display none,
1050
+ // so enable the element temporarily
1051
+ var els = element.style;
1052
+ var originalVisibility = els.visibility;
1053
+ var originalPosition = els.position;
1054
+ els.visibility = 'hidden';
1055
+ els.position = 'absolute';
1056
+ els.display = '';
1057
+ var originalWidth = element.clientWidth;
1058
+ var originalHeight = element.clientHeight;
1059
+ els.display = 'none';
1060
+ els.position = originalPosition;
1061
+ els.visibility = originalVisibility;
1062
+ return {width: originalWidth, height: originalHeight};
1063
+ },
1064
+
1065
+ makePositioned: function(element) {
1066
+ element = $(element);
1067
+ var pos = Element.getStyle(element, 'position');
1068
+ if (pos == 'static' || !pos) {
1069
+ element._madePositioned = true;
1070
+ element.style.position = 'relative';
1071
+ // Opera returns the offset relative to the positioning context, when an
1072
+ // element is position relative but top and left have not been defined
1073
+ if (window.opera) {
1074
+ element.style.top = 0;
1075
+ element.style.left = 0;
1076
+ }
1077
+ }
1078
+ },
1079
+
1080
+ undoPositioned: function(element) {
1081
+ element = $(element);
1082
+ if (element._madePositioned) {
1083
+ element._madePositioned = undefined;
1084
+ element.style.position =
1085
+ element.style.top =
1086
+ element.style.left =
1087
+ element.style.bottom =
1088
+ element.style.right = '';
1089
+ }
1090
+ },
1091
+
1092
+ makeClipping: function(element) {
1093
+ element = $(element);
1094
+ if (element._overflow) return;
1095
+ element._overflow = element.style.overflow;
1096
+ if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1097
+ element.style.overflow = 'hidden';
1098
+ },
1099
+
1100
+ undoClipping: function(element) {
1101
+ element = $(element);
1102
+ if (element._overflow) return;
1103
+ element.style.overflow = element._overflow;
1104
+ element._overflow = undefined;
1105
+ }
1106
+ }
1107
+
1108
+ Object.extend(Element, Element.Methods);
1109
+
1110
+ var _nativeExtensions = false;
1111
+
1112
+ if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1113
+ var HTMLElement = {}
1114
+ HTMLElement.prototype = document.createElement('div').__proto__;
1115
+ }
1116
+
1117
+ Element.addMethods = function(methods) {
1118
+ Object.extend(Element.Methods, methods || {});
1119
+
1120
+ if(typeof HTMLElement != 'undefined') {
1121
+ var methods = Element.Methods, cache = Element.extend.cache;
1122
+ for (property in methods) {
1123
+ var value = methods[property];
1124
+ if (typeof value == 'function')
1125
+ HTMLElement.prototype[property] = cache.findOrStore(value);
1126
+ }
1127
+ _nativeExtensions = true;
1128
+ }
1129
+ }
1130
+
1131
+ Element.addMethods();
1132
+
1133
+ var Toggle = new Object();
1134
+ Toggle.display = Element.toggle;
1135
+
1136
+ /*--------------------------------------------------------------------------*/
1137
+
1138
+ Abstract.Insertion = function(adjacency) {
1139
+ this.adjacency = adjacency;
1140
+ }
1141
+
1142
+ Abstract.Insertion.prototype = {
1143
+ initialize: function(element, content) {
1144
+ this.element = $(element);
1145
+ this.content = content.stripScripts();
1146
+
1147
+ if (this.adjacency && this.element.insertAdjacentHTML) {
1148
+ try {
1149
+ this.element.insertAdjacentHTML(this.adjacency, this.content);
1150
+ } catch (e) {
1151
+ var tagName = this.element.tagName.toLowerCase();
1152
+ if (tagName == 'tbody' || tagName == 'tr') {
1153
+ this.insertContent(this.contentFromAnonymousTable());
1154
+ } else {
1155
+ throw e;
1156
+ }
1157
+ }
1158
+ } else {
1159
+ this.range = this.element.ownerDocument.createRange();
1160
+ if (this.initializeRange) this.initializeRange();
1161
+ this.insertContent([this.range.createContextualFragment(this.content)]);
1162
+ }
1163
+
1164
+ setTimeout(function() {content.evalScripts()}, 10);
1165
+ },
1166
+
1167
+ contentFromAnonymousTable: function() {
1168
+ var div = document.createElement('div');
1169
+ div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1170
+ return $A(div.childNodes[0].childNodes[0].childNodes);
1171
+ }
1172
+ }
1173
+
1174
+ var Insertion = new Object();
1175
+
1176
+ Insertion.Before = Class.create();
1177
+ Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1178
+ initializeRange: function() {
1179
+ this.range.setStartBefore(this.element);
1180
+ },
1181
+
1182
+ insertContent: function(fragments) {
1183
+ fragments.each((function(fragment) {
1184
+ this.element.parentNode.insertBefore(fragment, this.element);
1185
+ }).bind(this));
1186
+ }
1187
+ });
1188
+
1189
+ Insertion.Top = Class.create();
1190
+ Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1191
+ initializeRange: function() {
1192
+ this.range.selectNodeContents(this.element);
1193
+ this.range.collapse(true);
1194
+ },
1195
+
1196
+ insertContent: function(fragments) {
1197
+ fragments.reverse(false).each((function(fragment) {
1198
+ this.element.insertBefore(fragment, this.element.firstChild);
1199
+ }).bind(this));
1200
+ }
1201
+ });
1202
+
1203
+ Insertion.Bottom = Class.create();
1204
+ Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
1205
+ initializeRange: function() {
1206
+ this.range.selectNodeContents(this.element);
1207
+ this.range.collapse(this.element);
1208
+ },
1209
+
1210
+ insertContent: function(fragments) {
1211
+ fragments.each((function(fragment) {
1212
+ this.element.appendChild(fragment);
1213
+ }).bind(this));
1214
+ }
1215
+ });
1216
+
1217
+ Insertion.After = Class.create();
1218
+ Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
1219
+ initializeRange: function() {
1220
+ this.range.setStartAfter(this.element);
1221
+ },
1222
+
1223
+ insertContent: function(fragments) {
1224
+ fragments.each((function(fragment) {
1225
+ this.element.parentNode.insertBefore(fragment,
1226
+ this.element.nextSibling);
1227
+ }).bind(this));
1228
+ }
1229
+ });
1230
+
1231
+ /*--------------------------------------------------------------------------*/
1232
+
1233
+ Element.ClassNames = Class.create();
1234
+ Element.ClassNames.prototype = {
1235
+ initialize: function(element) {
1236
+ this.element = $(element);
1237
+ },
1238
+
1239
+ _each: function(iterator) {
1240
+ this.element.className.split(/\s+/).select(function(name) {
1241
+ return name.length > 0;
1242
+ })._each(iterator);
1243
+ },
1244
+
1245
+ set: function(className) {
1246
+ this.element.className = className;
1247
+ },
1248
+
1249
+ add: function(classNameToAdd) {
1250
+ if (this.include(classNameToAdd)) return;
1251
+ this.set(this.toArray().concat(classNameToAdd).join(' '));
1252
+ },
1253
+
1254
+ remove: function(classNameToRemove) {
1255
+ if (!this.include(classNameToRemove)) return;
1256
+ this.set(this.select(function(className) {
1257
+ return className != classNameToRemove;
1258
+ }).join(' '));
1259
+ },
1260
+
1261
+ toString: function() {
1262
+ return this.toArray().join(' ');
1263
+ }
1264
+ }
1265
+
1266
+ Object.extend(Element.ClassNames.prototype, Enumerable);
1267
+ var Selector = Class.create();
1268
+ Selector.prototype = {
1269
+ initialize: function(expression) {
1270
+ this.params = {classNames: []};
1271
+ this.expression = expression.toString().strip();
1272
+ this.parseExpression();
1273
+ this.compileMatcher();
1274
+ },
1275
+
1276
+ parseExpression: function() {
1277
+ function abort(message) { throw 'Parse error in selector: ' + message; }
1278
+
1279
+ if (this.expression == '') abort('empty expression');
1280
+
1281
+ var params = this.params, expr = this.expression, match, modifier, clause, rest;
1282
+ while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
1283
+ params.attributes = params.attributes || [];
1284
+ params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
1285
+ expr = match[1];
1286
+ }
1287
+
1288
+ if (expr == '*') return this.params.wildcard = true;
1289
+
1290
+ while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
1291
+ modifier = match[1], clause = match[2], rest = match[3];
1292
+ switch (modifier) {
1293
+ case '#': params.id = clause; break;
1294
+ case '.': params.classNames.push(clause); break;
1295
+ case '':
1296
+ case undefined: params.tagName = clause.toUpperCase(); break;
1297
+ default: abort(expr.inspect());
1298
+ }
1299
+ expr = rest;
1300
+ }
1301
+
1302
+ if (expr.length > 0) abort(expr.inspect());
1303
+ },
1304
+
1305
+ buildMatchExpression: function() {
1306
+ var params = this.params, conditions = [], clause;
1307
+
1308
+ if (params.wildcard)
1309
+ conditions.push('true');
1310
+ if (clause = params.id)
1311
+ conditions.push('element.id == ' + clause.inspect());
1312
+ if (clause = params.tagName)
1313
+ conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
1314
+ if ((clause = params.classNames).length > 0)
1315
+ for (var i = 0; i < clause.length; i++)
1316
+ conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
1317
+ if (clause = params.attributes) {
1318
+ clause.each(function(attribute) {
1319
+ var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
1320
+ var splitValueBy = function(delimiter) {
1321
+ return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
1322
+ }
1323
+
1324
+ switch (attribute.operator) {
1325
+ case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
1326
+ case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
1327
+ case '|=': conditions.push(
1328
+ splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
1329
+ ); break;
1330
+ case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
1331
+ case '':
1332
+ case undefined: conditions.push(value + ' != null'); break;
1333
+ default: throw 'Unknown operator ' + attribute.operator + ' in selector';
1334
+ }
1335
+ });
1336
+ }
1337
+
1338
+ return conditions.join(' && ');
1339
+ },
1340
+
1341
+ compileMatcher: function() {
1342
+ this.match = new Function('element', 'if (!element.tagName) return false; \n' +
1343
+ 'return ' + this.buildMatchExpression());
1344
+ },
1345
+
1346
+ findElements: function(scope) {
1347
+ var element;
1348
+
1349
+ if (element = $(this.params.id))
1350
+ if (this.match(element))
1351
+ if (!scope || Element.childOf(element, scope))
1352
+ return [element];
1353
+
1354
+ scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
1355
+
1356
+ var results = [];
1357
+ for (var i = 0; i < scope.length; i++)
1358
+ if (this.match(element = scope[i]))
1359
+ results.push(Element.extend(element));
1360
+
1361
+ return results;
1362
+ },
1363
+
1364
+ toString: function() {
1365
+ return this.expression;
1366
+ }
1367
+ }
1368
+
1369
+ function $$() {
1370
+ return $A(arguments).map(function(expression) {
1371
+ return expression.strip().split(/\s+/).inject([null], function(results, expr) {
1372
+ var selector = new Selector(expr);
1373
+ return results.map(selector.findElements.bind(selector)).flatten();
1374
+ });
1375
+ }).flatten();
1376
+ }
1377
+ var Field = {
1378
+ clear: function() {
1379
+ for (var i = 0; i < arguments.length; i++)
1380
+ $(arguments[i]).value = '';
1381
+ },
1382
+
1383
+ focus: function(element) {
1384
+ $(element).focus();
1385
+ },
1386
+
1387
+ present: function() {
1388
+ for (var i = 0; i < arguments.length; i++)
1389
+ if ($(arguments[i]).value == '') return false;
1390
+ return true;
1391
+ },
1392
+
1393
+ select: function(element) {
1394
+ $(element).select();
1395
+ },
1396
+
1397
+ activate: function(element) {
1398
+ element = $(element);
1399
+ element.focus();
1400
+ if (element.select)
1401
+ element.select();
1402
+ }
1403
+ }
1404
+
1405
+ /*--------------------------------------------------------------------------*/
1406
+
1407
+ var Form = {
1408
+ serialize: function(form) {
1409
+ var elements = Form.getElements($(form));
1410
+ var queryComponents = new Array();
1411
+
1412
+ for (var i = 0; i < elements.length; i++) {
1413
+ var queryComponent = Form.Element.serialize(elements[i]);
1414
+ if (queryComponent)
1415
+ queryComponents.push(queryComponent);
1416
+ }
1417
+
1418
+ return queryComponents.join('&');
1419
+ },
1420
+
1421
+ getElements: function(form) {
1422
+ form = $(form);
1423
+ var elements = new Array();
1424
+
1425
+ for (var tagName in Form.Element.Serializers) {
1426
+ var tagElements = form.getElementsByTagName(tagName);
1427
+ for (var j = 0; j < tagElements.length; j++)
1428
+ elements.push(tagElements[j]);
1429
+ }
1430
+ return elements;
1431
+ },
1432
+
1433
+ getInputs: function(form, typeName, name) {
1434
+ form = $(form);
1435
+ var inputs = form.getElementsByTagName('input');
1436
+
1437
+ if (!typeName && !name)
1438
+ return inputs;
1439
+
1440
+ var matchingInputs = new Array();
1441
+ for (var i = 0; i < inputs.length; i++) {
1442
+ var input = inputs[i];
1443
+ if ((typeName && input.type != typeName) ||
1444
+ (name && input.name != name))
1445
+ continue;
1446
+ matchingInputs.push(input);
1447
+ }
1448
+
1449
+ return matchingInputs;
1450
+ },
1451
+
1452
+ disable: function(form) {
1453
+ var elements = Form.getElements(form);
1454
+ for (var i = 0; i < elements.length; i++) {
1455
+ var element = elements[i];
1456
+ element.blur();
1457
+ element.disabled = 'true';
1458
+ }
1459
+ },
1460
+
1461
+ enable: function(form) {
1462
+ var elements = Form.getElements(form);
1463
+ for (var i = 0; i < elements.length; i++) {
1464
+ var element = elements[i];
1465
+ element.disabled = '';
1466
+ }
1467
+ },
1468
+
1469
+ findFirstElement: function(form) {
1470
+ return Form.getElements(form).find(function(element) {
1471
+ return element.type != 'hidden' && !element.disabled &&
1472
+ ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1473
+ });
1474
+ },
1475
+
1476
+ focusFirstElement: function(form) {
1477
+ Field.activate(Form.findFirstElement(form));
1478
+ },
1479
+
1480
+ reset: function(form) {
1481
+ $(form).reset();
1482
+ }
1483
+ }
1484
+
1485
+ Form.Element = {
1486
+ serialize: function(element) {
1487
+ element = $(element);
1488
+ var method = element.tagName.toLowerCase();
1489
+ var parameter = Form.Element.Serializers[method](element);
1490
+
1491
+ if (parameter) {
1492
+ var key = encodeURIComponent(parameter[0]);
1493
+ if (key.length == 0) return;
1494
+
1495
+ if (parameter[1].constructor != Array)
1496
+ parameter[1] = [parameter[1]];
1497
+
1498
+ return parameter[1].map(function(value) {
1499
+ return key + '=' + encodeURIComponent(value);
1500
+ }).join('&');
1501
+ }
1502
+ },
1503
+
1504
+ getValue: function(element) {
1505
+ element = $(element);
1506
+ var method = element.tagName.toLowerCase();
1507
+ var parameter = Form.Element.Serializers[method](element);
1508
+
1509
+ if (parameter)
1510
+ return parameter[1];
1511
+ }
1512
+ }
1513
+
1514
+ Form.Element.Serializers = {
1515
+ input: function(element) {
1516
+ switch (element.type.toLowerCase()) {
1517
+ case 'submit':
1518
+ case 'hidden':
1519
+ case 'password':
1520
+ case 'text':
1521
+ return Form.Element.Serializers.textarea(element);
1522
+ case 'checkbox':
1523
+ case 'radio':
1524
+ return Form.Element.Serializers.inputSelector(element);
1525
+ }
1526
+ return false;
1527
+ },
1528
+
1529
+ inputSelector: function(element) {
1530
+ if (element.checked)
1531
+ return [element.name, element.value];
1532
+ },
1533
+
1534
+ textarea: function(element) {
1535
+ return [element.name, element.value];
1536
+ },
1537
+
1538
+ select: function(element) {
1539
+ return Form.Element.Serializers[element.type == 'select-one' ?
1540
+ 'selectOne' : 'selectMany'](element);
1541
+ },
1542
+
1543
+ selectOne: function(element) {
1544
+ var value = '', opt, index = element.selectedIndex;
1545
+ if (index >= 0) {
1546
+ opt = element.options[index];
1547
+ value = opt.value || opt.text;
1548
+ }
1549
+ return [element.name, value];
1550
+ },
1551
+
1552
+ selectMany: function(element) {
1553
+ var value = [];
1554
+ for (var i = 0; i < element.length; i++) {
1555
+ var opt = element.options[i];
1556
+ if (opt.selected)
1557
+ value.push(opt.value || opt.text);
1558
+ }
1559
+ return [element.name, value];
1560
+ }
1561
+ }
1562
+
1563
+ /*--------------------------------------------------------------------------*/
1564
+
1565
+ var $F = Form.Element.getValue;
1566
+
1567
+ /*--------------------------------------------------------------------------*/
1568
+
1569
+ Abstract.TimedObserver = function() {}
1570
+ Abstract.TimedObserver.prototype = {
1571
+ initialize: function(element, frequency, callback) {
1572
+ this.frequency = frequency;
1573
+ this.element = $(element);
1574
+ this.callback = callback;
1575
+
1576
+ this.lastValue = this.getValue();
1577
+ this.registerCallback();
1578
+ },
1579
+
1580
+ registerCallback: function() {
1581
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
1582
+ },
1583
+
1584
+ onTimerEvent: function() {
1585
+ var value = this.getValue();
1586
+ if (this.lastValue != value) {
1587
+ this.callback(this.element, value);
1588
+ this.lastValue = value;
1589
+ }
1590
+ }
1591
+ }
1592
+
1593
+ Form.Element.Observer = Class.create();
1594
+ Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1595
+ getValue: function() {
1596
+ return Form.Element.getValue(this.element);
1597
+ }
1598
+ });
1599
+
1600
+ Form.Observer = Class.create();
1601
+ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1602
+ getValue: function() {
1603
+ return Form.serialize(this.element);
1604
+ }
1605
+ });
1606
+
1607
+ /*--------------------------------------------------------------------------*/
1608
+
1609
+ Abstract.EventObserver = function() {}
1610
+ Abstract.EventObserver.prototype = {
1611
+ initialize: function(element, callback) {
1612
+ this.element = $(element);
1613
+ this.callback = callback;
1614
+
1615
+ this.lastValue = this.getValue();
1616
+ if (this.element.tagName.toLowerCase() == 'form')
1617
+ this.registerFormCallbacks();
1618
+ else
1619
+ this.registerCallback(this.element);
1620
+ },
1621
+
1622
+ onElementEvent: function() {
1623
+ var value = this.getValue();
1624
+ if (this.lastValue != value) {
1625
+ this.callback(this.element, value);
1626
+ this.lastValue = value;
1627
+ }
1628
+ },
1629
+
1630
+ registerFormCallbacks: function() {
1631
+ var elements = Form.getElements(this.element);
1632
+ for (var i = 0; i < elements.length; i++)
1633
+ this.registerCallback(elements[i]);
1634
+ },
1635
+
1636
+ registerCallback: function(element) {
1637
+ if (element.type) {
1638
+ switch (element.type.toLowerCase()) {
1639
+ case 'checkbox':
1640
+ case 'radio':
1641
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
1642
+ break;
1643
+ case 'password':
1644
+ case 'text':
1645
+ case 'textarea':
1646
+ case 'select-one':
1647
+ case 'select-multiple':
1648
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
1649
+ break;
1650
+ }
1651
+ }
1652
+ }
1653
+ }
1654
+
1655
+ Form.Element.EventObserver = Class.create();
1656
+ Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1657
+ getValue: function() {
1658
+ return Form.Element.getValue(this.element);
1659
+ }
1660
+ });
1661
+
1662
+ Form.EventObserver = Class.create();
1663
+ Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1664
+ getValue: function() {
1665
+ return Form.serialize(this.element);
1666
+ }
1667
+ });
1668
+ if (!window.Event) {
1669
+ var Event = new Object();
1670
+ }
1671
+
1672
+ Object.extend(Event, {
1673
+ KEY_BACKSPACE: 8,
1674
+ KEY_TAB: 9,
1675
+ KEY_RETURN: 13,
1676
+ KEY_ESC: 27,
1677
+ KEY_LEFT: 37,
1678
+ KEY_UP: 38,
1679
+ KEY_RIGHT: 39,
1680
+ KEY_DOWN: 40,
1681
+ KEY_DELETE: 46,
1682
+
1683
+ element: function(event) {
1684
+ return event.target || event.srcElement;
1685
+ },
1686
+
1687
+ isLeftClick: function(event) {
1688
+ return (((event.which) && (event.which == 1)) ||
1689
+ ((event.button) && (event.button == 1)));
1690
+ },
1691
+
1692
+ pointerX: function(event) {
1693
+ return event.pageX || (event.clientX +
1694
+ (document.documentElement.scrollLeft || document.body.scrollLeft));
1695
+ },
1696
+
1697
+ pointerY: function(event) {
1698
+ return event.pageY || (event.clientY +
1699
+ (document.documentElement.scrollTop || document.body.scrollTop));
1700
+ },
1701
+
1702
+ stop: function(event) {
1703
+ if (event.preventDefault) {
1704
+ event.preventDefault();
1705
+ event.stopPropagation();
1706
+ } else {
1707
+ event.returnValue = false;
1708
+ event.cancelBubble = true;
1709
+ }
1710
+ },
1711
+
1712
+ // find the first node with the given tagName, starting from the
1713
+ // node the event was triggered on; traverses the DOM upwards
1714
+ findElement: function(event, tagName) {
1715
+ var element = Event.element(event);
1716
+ while (element.parentNode && (!element.tagName ||
1717
+ (element.tagName.toUpperCase() != tagName.toUpperCase())))
1718
+ element = element.parentNode;
1719
+ return element;
1720
+ },
1721
+
1722
+ observers: false,
1723
+
1724
+ _observeAndCache: function(element, name, observer, useCapture) {
1725
+ if (!this.observers) this.observers = [];
1726
+ if (element.addEventListener) {
1727
+ this.observers.push([element, name, observer, useCapture]);
1728
+ element.addEventListener(name, observer, useCapture);
1729
+ } else if (element.attachEvent) {
1730
+ this.observers.push([element, name, observer, useCapture]);
1731
+ element.attachEvent('on' + name, observer);
1732
+ }
1733
+ },
1734
+
1735
+ unloadCache: function() {
1736
+ if (!Event.observers) return;
1737
+ for (var i = 0; i < Event.observers.length; i++) {
1738
+ Event.stopObserving.apply(this, Event.observers[i]);
1739
+ Event.observers[i][0] = null;
1740
+ }
1741
+ Event.observers = false;
1742
+ },
1743
+
1744
+ observe: function(element, name, observer, useCapture) {
1745
+ var element = $(element);
1746
+ useCapture = useCapture || false;
1747
+
1748
+ if (name == 'keypress' &&
1749
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1750
+ || element.attachEvent))
1751
+ name = 'keydown';
1752
+
1753
+ this._observeAndCache(element, name, observer, useCapture);
1754
+ },
1755
+
1756
+ stopObserving: function(element, name, observer, useCapture) {
1757
+ var element = $(element);
1758
+ useCapture = useCapture || false;
1759
+
1760
+ if (name == 'keypress' &&
1761
+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1762
+ || element.detachEvent))
1763
+ name = 'keydown';
1764
+
1765
+ if (element.removeEventListener) {
1766
+ element.removeEventListener(name, observer, useCapture);
1767
+ } else if (element.detachEvent) {
1768
+ element.detachEvent('on' + name, observer);
1769
+ }
1770
+ }
1771
+ });
1772
+
1773
+ /* prevent memory leaks in IE */
1774
+ if (navigator.appVersion.match(/\bMSIE\b/))
1775
+ Event.observe(window, 'unload', Event.unloadCache, false);
1776
+ var Position = {
1777
+ // set to true if needed, warning: firefox performance problems
1778
+ // NOT neeeded for page scrolling, only if draggable contained in
1779
+ // scrollable elements
1780
+ includeScrollOffsets: false,
1781
+
1782
+ // must be called before calling withinIncludingScrolloffset, every time the
1783
+ // page is scrolled
1784
+ prepare: function() {
1785
+ this.deltaX = window.pageXOffset
1786
+ || document.documentElement.scrollLeft
1787
+ || document.body.scrollLeft
1788
+ || 0;
1789
+ this.deltaY = window.pageYOffset
1790
+ || document.documentElement.scrollTop
1791
+ || document.body.scrollTop
1792
+ || 0;
1793
+ },
1794
+
1795
+ realOffset: function(element) {
1796
+ var valueT = 0, valueL = 0;
1797
+ do {
1798
+ valueT += element.scrollTop || 0;
1799
+ valueL += element.scrollLeft || 0;
1800
+ element = element.parentNode;
1801
+ } while (element);
1802
+ return [valueL, valueT];
1803
+ },
1804
+
1805
+ cumulativeOffset: function(element) {
1806
+ var valueT = 0, valueL = 0;
1807
+ do {
1808
+ valueT += element.offsetTop || 0;
1809
+ valueL += element.offsetLeft || 0;
1810
+ element = element.offsetParent;
1811
+ } while (element);
1812
+ return [valueL, valueT];
1813
+ },
1814
+
1815
+ positionedOffset: function(element) {
1816
+ var valueT = 0, valueL = 0;
1817
+ do {
1818
+ valueT += element.offsetTop || 0;
1819
+ valueL += element.offsetLeft || 0;
1820
+ element = element.offsetParent;
1821
+ if (element) {
1822
+ p = Element.getStyle(element, 'position');
1823
+ if (p == 'relative' || p == 'absolute') break;
1824
+ }
1825
+ } while (element);
1826
+ return [valueL, valueT];
1827
+ },
1828
+
1829
+ offsetParent: function(element) {
1830
+ if (element.offsetParent) return element.offsetParent;
1831
+ if (element == document.body) return element;
1832
+
1833
+ while ((element = element.parentNode) && element != document.body)
1834
+ if (Element.getStyle(element, 'position') != 'static')
1835
+ return element;
1836
+
1837
+ return document.body;
1838
+ },
1839
+
1840
+ // caches x/y coordinate pair to use with overlap
1841
+ within: function(element, x, y) {
1842
+ if (this.includeScrollOffsets)
1843
+ return this.withinIncludingScrolloffsets(element, x, y);
1844
+ this.xcomp = x;
1845
+ this.ycomp = y;
1846
+ this.offset = this.cumulativeOffset(element);
1847
+
1848
+ return (y >= this.offset[1] &&
1849
+ y < this.offset[1] + element.offsetHeight &&
1850
+ x >= this.offset[0] &&
1851
+ x < this.offset[0] + element.offsetWidth);
1852
+ },
1853
+
1854
+ withinIncludingScrolloffsets: function(element, x, y) {
1855
+ var offsetcache = this.realOffset(element);
1856
+
1857
+ this.xcomp = x + offsetcache[0] - this.deltaX;
1858
+ this.ycomp = y + offsetcache[1] - this.deltaY;
1859
+ this.offset = this.cumulativeOffset(element);
1860
+
1861
+ return (this.ycomp >= this.offset[1] &&
1862
+ this.ycomp < this.offset[1] + element.offsetHeight &&
1863
+ this.xcomp >= this.offset[0] &&
1864
+ this.xcomp < this.offset[0] + element.offsetWidth);
1865
+ },
1866
+
1867
+ // within must be called directly before
1868
+ overlap: function(mode, element) {
1869
+ if (!mode) return 0;
1870
+ if (mode == 'vertical')
1871
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1872
+ element.offsetHeight;
1873
+ if (mode == 'horizontal')
1874
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1875
+ element.offsetWidth;
1876
+ },
1877
+
1878
+ clone: function(source, target) {
1879
+ source = $(source);
1880
+ target = $(target);
1881
+ target.style.position = 'absolute';
1882
+ var offsets = this.cumulativeOffset(source);
1883
+ target.style.top = offsets[1] + 'px';
1884
+ target.style.left = offsets[0] + 'px';
1885
+ target.style.width = source.offsetWidth + 'px';
1886
+ target.style.height = source.offsetHeight + 'px';
1887
+ },
1888
+
1889
+ page: function(forElement) {
1890
+ var valueT = 0, valueL = 0;
1891
+
1892
+ var element = forElement;
1893
+ do {
1894
+ valueT += element.offsetTop || 0;
1895
+ valueL += element.offsetLeft || 0;
1896
+
1897
+ // Safari fix
1898
+ if (element.offsetParent==document.body)
1899
+ if (Element.getStyle(element,'position')=='absolute') break;
1900
+
1901
+ } while (element = element.offsetParent);
1902
+
1903
+ element = forElement;
1904
+ do {
1905
+ valueT -= element.scrollTop || 0;
1906
+ valueL -= element.scrollLeft || 0;
1907
+ } while (element = element.parentNode);
1908
+
1909
+ return [valueL, valueT];
1910
+ },
1911
+
1912
+ clone: function(source, target) {
1913
+ var options = Object.extend({
1914
+ setLeft: true,
1915
+ setTop: true,
1916
+ setWidth: true,
1917
+ setHeight: true,
1918
+ offsetTop: 0,
1919
+ offsetLeft: 0
1920
+ }, arguments[2] || {})
1921
+
1922
+ // find page position of source
1923
+ source = $(source);
1924
+ var p = Position.page(source);
1925
+
1926
+ // find coordinate system to use
1927
+ target = $(target);
1928
+ var delta = [0, 0];
1929
+ var parent = null;
1930
+ // delta [0,0] will do fine with position: fixed elements,
1931
+ // position:absolute needs offsetParent deltas
1932
+ if (Element.getStyle(target,'position') == 'absolute') {
1933
+ parent = Position.offsetParent(target);
1934
+ delta = Position.page(parent);
1935
+ }
1936
+
1937
+ // correct by body offsets (fixes Safari)
1938
+ if (parent == document.body) {
1939
+ delta[0] -= document.body.offsetLeft;
1940
+ delta[1] -= document.body.offsetTop;
1941
+ }
1942
+
1943
+ // set position
1944
+ if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
1945
+ if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
1946
+ if(options.setWidth) target.style.width = source.offsetWidth + 'px';
1947
+ if(options.setHeight) target.style.height = source.offsetHeight + 'px';
1948
+ },
1949
+
1950
+ absolutize: function(element) {
1951
+ element = $(element);
1952
+ if (element.style.position == 'absolute') return;
1953
+ Position.prepare();
1954
+
1955
+ var offsets = Position.positionedOffset(element);
1956
+ var top = offsets[1];
1957
+ var left = offsets[0];
1958
+ var width = element.clientWidth;
1959
+ var height = element.clientHeight;
1960
+
1961
+ element._originalLeft = left - parseFloat(element.style.left || 0);
1962
+ element._originalTop = top - parseFloat(element.style.top || 0);
1963
+ element._originalWidth = element.style.width;
1964
+ element._originalHeight = element.style.height;
1965
+
1966
+ element.style.position = 'absolute';
1967
+ element.style.top = top + 'px';;
1968
+ element.style.left = left + 'px';;
1969
+ element.style.width = width + 'px';;
1970
+ element.style.height = height + 'px';;
1971
+ },
1972
+
1973
+ relativize: function(element) {
1974
+ element = $(element);
1975
+ if (element.style.position == 'relative') return;
1976
+ Position.prepare();
1977
+
1978
+ element.style.position = 'relative';
1979
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
1980
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
1981
+
1982
+ element.style.top = top + 'px';
1983
+ element.style.left = left + 'px';
1984
+ element.style.height = element._originalHeight;
1985
+ element.style.width = element._originalWidth;
1986
+ }
1987
+ }
1988
+
1989
+ // Safari returns margins on body which is incorrect if the child is absolutely
1990
+ // positioned. For performance reasons, redefine Position.cumulativeOffset for
1991
+ // KHTML/WebKit only.
1992
+ if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1993
+ Position.cumulativeOffset = function(element) {
1994
+ var valueT = 0, valueL = 0;
1995
+ do {
1996
+ valueT += element.offsetTop || 0;
1997
+ valueL += element.offsetLeft || 0;
1998
+ if (element.offsetParent == document.body)
1999
+ if (Element.getStyle(element, 'position') == 'absolute') break;
2000
+
2001
+ element = element.offsetParent;
2002
+ } while (element);
2003
+
2004
+ return [valueL, valueT];
2005
+ }
2006
+ }