rspec 1.1.12 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (267) hide show
  1. data/.autotest +2 -1
  2. data/.document +7 -0
  3. data/History.txt +58 -0
  4. data/License.txt +1 -1
  5. data/Manifest.txt +45 -82
  6. data/README.txt +3 -6
  7. data/Rakefile +33 -13
  8. data/Ruby1.9.markdown +32 -0
  9. data/TODO.txt +10 -4
  10. data/Upgrade.markdown +63 -0
  11. data/bin/spec +1 -1
  12. data/cucumber.yml +3 -0
  13. data/examples/failing/{failing_autogenerated_docstrings_example.rb → failing_implicit_docstrings_example.rb} +0 -0
  14. data/examples/failing/pending_example.rb +9 -0
  15. data/examples/failing/spec_helper.rb +1 -1
  16. data/examples/passing/{custom_expectation_matchers.rb → custom_matchers.rb} +0 -0
  17. data/examples/passing/filtered_formatter.rb +18 -0
  18. data/examples/passing/filtered_formatter_example.rb +31 -0
  19. data/examples/passing/implicit_docstrings_example.rb +18 -0
  20. data/examples/passing/spec_helper.rb +1 -1
  21. data/examples/ruby1.9.compatibility/access_to_constants_spec.rb +17 -18
  22. data/features/before_and_after_blocks/before_and_after_blocks.feature +4 -4
  23. data/features/example_groups/example_group_with_should_methods.feature +1 -1
  24. data/features/example_groups/{autogenerated_docstrings.feature → implicit_docstrings.feature} +7 -9
  25. data/features/example_groups/nested_groups.feature +1 -1
  26. data/features/heckle/heckle.feature +56 -0
  27. data/features/interop/examples_and_tests_together.feature +1 -1
  28. data/features/interop/test_but_not_test_unit.feature +1 -1
  29. data/features/interop/test_case_with_should_methods.feature +1 -1
  30. data/features/matchers/create_matcher.feature +115 -0
  31. data/features/mock_framework_integration/use_flexmock.feature +22 -4
  32. data/features/mock_framework_integration/use_mocha.feature +27 -0
  33. data/features/mock_framework_integration/use_rr.feature +27 -0
  34. data/features/mocks/mix_stubs_and_mocks.feature +22 -0
  35. data/features/pending/pending_examples.feature +81 -0
  36. data/features/step_definitions/running_rspec.rb +5 -3
  37. data/features/support/env.rb +1 -1
  38. data/features/support/matchers/smart_match.rb +2 -2
  39. data/lib/autotest/rspec.rb +1 -1
  40. data/lib/spec.rb +1 -1
  41. data/lib/{adapters → spec/adapters}/mock_frameworks/flexmock.rb +0 -0
  42. data/lib/{adapters → spec/adapters}/mock_frameworks/mocha.rb +0 -0
  43. data/lib/{adapters → spec/adapters}/mock_frameworks/rr.rb +0 -0
  44. data/lib/{adapters → spec/adapters}/mock_frameworks/rspec.rb +0 -1
  45. data/lib/spec/autorun.rb +3 -0
  46. data/lib/spec/dsl.rb +3 -1
  47. data/lib/spec/dsl/matchers.rb +13 -0
  48. data/lib/spec/example.rb +4 -0
  49. data/lib/spec/example/before_and_after_hooks.rb +5 -20
  50. data/lib/spec/example/errors.rb +3 -3
  51. data/lib/spec/example/example_description.rb +15 -0
  52. data/lib/spec/example/example_group.rb +0 -15
  53. data/lib/spec/example/example_group_factory.rb +34 -46
  54. data/lib/spec/example/example_group_hierarchy.rb +53 -0
  55. data/lib/spec/example/example_group_methods.rb +101 -211
  56. data/lib/spec/example/example_methods.rb +61 -81
  57. data/lib/spec/example/module_reopening_fix.rb +23 -1
  58. data/lib/spec/example/pending.rb +3 -2
  59. data/lib/spec/example/predicate_matchers.rb +47 -0
  60. data/lib/spec/example/subject.rb +91 -0
  61. data/lib/spec/expectations.rb +1 -1
  62. data/lib/spec/expectations/differs/default.rb +0 -1
  63. data/lib/spec/expectations/extensions.rb +0 -1
  64. data/lib/spec/expectations/handler.rb +13 -6
  65. data/lib/spec/interop/test.rb +5 -0
  66. data/lib/spec/interop/test/unit/testcase.rb +5 -22
  67. data/lib/spec/matchers.rb +22 -8
  68. data/lib/spec/matchers/be.rb +4 -9
  69. data/lib/spec/matchers/be_close.rb +20 -5
  70. data/lib/spec/matchers/be_instance_of.rb +45 -0
  71. data/lib/spec/matchers/be_kind_of.rb +45 -0
  72. data/lib/spec/matchers/change.rb +8 -6
  73. data/lib/spec/matchers/compatibility.rb +14 -0
  74. data/lib/spec/matchers/eql.rb +24 -6
  75. data/lib/spec/matchers/equal.rb +24 -6
  76. data/lib/spec/matchers/exist.rb +21 -5
  77. data/lib/spec/matchers/extensions/instance_exec.rb +25 -0
  78. data/lib/spec/matchers/generated_descriptions.rb +2 -2
  79. data/lib/spec/matchers/has.rb +28 -11
  80. data/lib/spec/matchers/have.rb +2 -2
  81. data/lib/spec/matchers/include.rb +2 -2
  82. data/lib/spec/matchers/match.rb +25 -7
  83. data/lib/spec/matchers/match_array.rb +3 -3
  84. data/lib/spec/matchers/matcher.rb +51 -0
  85. data/lib/spec/matchers/method_missing.rb +2 -2
  86. data/lib/spec/matchers/operator_matcher.rb +12 -5
  87. data/lib/spec/matchers/raise_error.rb +3 -3
  88. data/lib/spec/matchers/respond_to.rb +3 -3
  89. data/lib/spec/matchers/satisfy.rb +7 -7
  90. data/lib/spec/matchers/throw_symbol.rb +3 -5
  91. data/lib/spec/mocks.rb +3 -3
  92. data/lib/spec/mocks/argument_expectation.rb +15 -15
  93. data/lib/spec/mocks/{argument_constraints.rb → argument_matchers.rb} +19 -23
  94. data/lib/spec/mocks/error_generator.rb +5 -8
  95. data/lib/spec/mocks/framework.rb +1 -1
  96. data/lib/spec/mocks/message_expectation.rb +5 -13
  97. data/lib/spec/mocks/mock.rb +4 -5
  98. data/lib/spec/mocks/proxy.rb +9 -5
  99. data/lib/spec/mocks/spec_methods.rb +10 -1
  100. data/lib/spec/rake/spectask.rb +0 -1
  101. data/lib/spec/runner.rb +6 -28
  102. data/lib/spec/runner/configuration.rb +3 -3
  103. data/lib/spec/runner/drb_command_line.rb +2 -1
  104. data/lib/spec/runner/example_group_runner.rb +3 -2
  105. data/lib/spec/runner/formatter/base_text_formatter.rb +34 -19
  106. data/lib/spec/runner/formatter/failing_example_groups_formatter.rb +3 -5
  107. data/lib/spec/runner/formatter/html_formatter.rb +2 -3
  108. data/lib/spec/runner/formatter/nested_text_formatter.rb +7 -25
  109. data/lib/spec/runner/formatter/progress_bar_formatter.rb +1 -1
  110. data/lib/spec/runner/formatter/snippet_extractor.rb +1 -1
  111. data/lib/spec/runner/formatter/specdoc_formatter.rb +1 -7
  112. data/lib/spec/runner/heckle_runner.rb +3 -6
  113. data/lib/spec/runner/heckle_runner_unsupported.rb +1 -1
  114. data/lib/spec/runner/option_parser.rb +19 -21
  115. data/lib/spec/runner/options.rb +32 -27
  116. data/lib/spec/runner/reporter.rb +8 -9
  117. data/lib/spec/test/unit.rb +10 -0
  118. data/lib/spec/version.rb +2 -2
  119. data/{features/support → resources}/helpers/cmdline.rb +2 -2
  120. data/resources/rake/verify_rcov.rake +1 -1
  121. data/resources/spec/example_group_with_should_methods.rb +1 -1
  122. data/resources/spec/simple_spec.rb +1 -1
  123. data/resources/test/spec_and_test_together.rb +2 -3
  124. data/resources/test/spec_including_test_but_not_unit.rb +1 -1
  125. data/resources/test/test_case_with_should_methods.rb +2 -3
  126. data/spec/autotest/autotest_helper.rb +0 -1
  127. data/spec/autotest/rspec_spec.rb +95 -98
  128. data/spec/spec/dsl/main_spec.rb +3 -3
  129. data/spec/spec/dsl/matchers_spec.rb +25 -0
  130. data/spec/spec/example/example_group_class_definition_spec.rb +14 -15
  131. data/spec/spec/example/example_group_factory_spec.rb +31 -44
  132. data/spec/spec/example/example_group_methods_spec.rb +86 -52
  133. data/spec/spec/example/example_group_spec.rb +32 -79
  134. data/spec/spec/example/example_matcher_spec.rb +10 -10
  135. data/spec/spec/example/example_methods_spec.rb +108 -242
  136. data/spec/spec/example/nested_example_group_spec.rb +2 -2
  137. data/spec/spec/example/pending_module_spec.rb +66 -41
  138. data/spec/spec/example/shared_example_group_spec.rb +4 -4
  139. data/spec/spec/{matchers → expectations}/handler_spec.rb +52 -4
  140. data/spec/spec/interop/test/unit/resources/spec_that_fails.rb +2 -2
  141. data/spec/spec/interop/test/unit/resources/spec_that_passes.rb +2 -2
  142. data/spec/spec/interop/test/unit/resources/spec_with_errors.rb +2 -2
  143. data/spec/spec/interop/test/unit/resources/spec_with_options_hash.rb +2 -2
  144. data/spec/spec/interop/test/unit/resources/test_case_that_fails.rb +2 -2
  145. data/spec/spec/interop/test/unit/resources/test_case_that_passes.rb +2 -2
  146. data/spec/spec/interop/test/unit/resources/test_case_with_errors.rb +2 -2
  147. data/spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb +2 -2
  148. data/spec/spec/interop/test/unit/testcase_spec.rb +0 -4
  149. data/spec/spec/matchers/be_close_spec.rb +1 -1
  150. data/spec/spec/matchers/be_instance_of_spec.rb +29 -0
  151. data/spec/spec/matchers/be_kind_of_spec.rb +29 -0
  152. data/spec/spec/matchers/change_spec.rb +20 -0
  153. data/spec/spec/matchers/compatibility_spec.rb +34 -0
  154. data/spec/spec/matchers/description_generation_spec.rb +0 -12
  155. data/spec/spec/matchers/eql_spec.rb +2 -2
  156. data/spec/spec/matchers/equal_spec.rb +2 -2
  157. data/spec/spec/matchers/exist_spec.rb +8 -4
  158. data/spec/spec/matchers/have_spec.rb +4 -4
  159. data/spec/spec/matchers/match_spec.rb +2 -2
  160. data/spec/spec/matchers/matcher_methods_spec.rb +1 -1
  161. data/spec/spec/matchers/matcher_spec.rb +97 -0
  162. data/spec/spec/matchers/throw_symbol_spec.rb +8 -8
  163. data/spec/spec/mocks/{bug_report_496.rb → bug_report_496_spec.rb} +0 -0
  164. data/spec/spec/mocks/{failing_mock_argument_constraints_spec.rb → failing_argument_matchers_spec.rb} +2 -2
  165. data/spec/spec/mocks/hash_including_matcher_spec.rb +4 -4
  166. data/spec/spec/mocks/hash_not_including_matcher_spec.rb +3 -3
  167. data/spec/spec/mocks/mock_spec.rb +27 -2
  168. data/spec/spec/mocks/nil_expectation_warning_spec.rb +1 -1
  169. data/spec/spec/mocks/partial_mock_spec.rb +18 -3
  170. data/spec/spec/mocks/{passing_mock_argument_constraints_spec.rb → passing_argument_matchers_spec.rb} +6 -6
  171. data/spec/spec/mocks/stubbed_message_expectations_spec.rb +13 -1
  172. data/spec/spec/package/bin_spec_spec.rb +2 -2
  173. data/spec/spec/runner/configuration_spec.rb +12 -12
  174. data/spec/spec/runner/drb_command_line_spec.rb +71 -73
  175. data/spec/spec/runner/formatter/base_text_formatter_spec.rb +82 -1
  176. data/spec/spec/runner/formatter/failing_example_groups_formatter_spec.rb +8 -8
  177. data/spec/spec/runner/formatter/failing_examples_formatter_spec.rb +4 -4
  178. data/spec/spec/runner/formatter/html_formatted-1.8.6.html +8 -8
  179. data/spec/spec/runner/formatter/html_formatted-1.8.7.html +38 -26
  180. data/spec/spec/runner/formatter/html_formatted-1.9.1.html +61 -53
  181. data/spec/spec/runner/formatter/html_formatter_spec.rb +100 -48
  182. data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +20 -34
  183. data/spec/spec/runner/formatter/profile_formatter_spec.rb +2 -1
  184. data/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +9 -6
  185. data/spec/spec/runner/formatter/specdoc_formatter_spec.rb +6 -6
  186. data/spec/spec/runner/formatter/text_mate_formatted-1.8.6.html +20 -20
  187. data/spec/spec/runner/formatter/text_mate_formatted-1.8.7.html +38 -26
  188. data/spec/spec/runner/formatter/text_mate_formatted-1.9.1.html +55 -47
  189. data/spec/spec/runner/formatter/{spec_mate_formatter_spec.rb → text_mate_formatter_spec.rb} +11 -9
  190. data/spec/spec/runner/heckle_runner_spec.rb +1 -1
  191. data/spec/spec/runner/heckler_spec.rb +1 -1
  192. data/spec/spec/runner/option_parser_spec.rb +28 -11
  193. data/spec/spec/runner/options_spec.rb +34 -0
  194. data/spec/spec/runner/reporter_spec.rb +66 -62
  195. data/spec/spec/runner/resources/utf8_encoded.rb +1 -0
  196. data/spec/spec/runner/spec_drb.opts +1 -0
  197. data/spec/spec/runner_spec.rb +7 -5
  198. data/spec/spec_helper.rb +24 -2
  199. metadata +49 -90
  200. data/examples/passing/autogenerated_docstrings_example.rb +0 -25
  201. data/examples/passing/before_and_after_example.rb +0 -40
  202. data/examples/passing/behave_as_example.rb +0 -45
  203. data/examples/passing/legacy_spec.rb +0 -11
  204. data/examples/passing/priority.txt +0 -1
  205. data/features/support/helpers/story_helper.rb +0 -16
  206. data/lib/spec/expectations/extensions/string_and_symbol.rb +0 -17
  207. data/lib/spec/runner/formatter/story/html_formatter.rb +0 -174
  208. data/lib/spec/runner/formatter/story/plain_text_formatter.rb +0 -194
  209. data/lib/spec/runner/formatter/story/progress_bar_formatter.rb +0 -42
  210. data/lib/spec/story.rb +0 -10
  211. data/lib/spec/story/extensions.rb +0 -3
  212. data/lib/spec/story/extensions/main.rb +0 -86
  213. data/lib/spec/story/extensions/regexp.rb +0 -9
  214. data/lib/spec/story/extensions/string.rb +0 -9
  215. data/lib/spec/story/given_scenario.rb +0 -14
  216. data/lib/spec/story/runner.rb +0 -57
  217. data/lib/spec/story/runner/plain_text_story_runner.rb +0 -48
  218. data/lib/spec/story/runner/scenario_collector.rb +0 -18
  219. data/lib/spec/story/runner/scenario_runner.rb +0 -54
  220. data/lib/spec/story/runner/story_mediator.rb +0 -137
  221. data/lib/spec/story/runner/story_parser.rb +0 -247
  222. data/lib/spec/story/runner/story_runner.rb +0 -74
  223. data/lib/spec/story/scenario.rb +0 -14
  224. data/lib/spec/story/step.rb +0 -70
  225. data/lib/spec/story/step_group.rb +0 -89
  226. data/lib/spec/story/step_mother.rb +0 -38
  227. data/lib/spec/story/story.rb +0 -39
  228. data/lib/spec/story/world.rb +0 -124
  229. data/resources/spec/spec_with_flexmock.rb +0 -19
  230. data/rspec.gemspec +0 -32
  231. data/spec/spec/matchers/mock_constraint_matchers_spec.rb +0 -24
  232. data/spec/spec/runner/formatter/story/html_formatter_spec.rb +0 -135
  233. data/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb +0 -600
  234. data/spec/spec/runner/formatter/story/progress_bar_formatter_spec.rb +0 -82
  235. data/spec/spec/spec_spec.rb +0 -21
  236. data/spec/spec/story/builders.rb +0 -46
  237. data/spec/spec/story/extensions/main_spec.rb +0 -161
  238. data/spec/spec/story/extensions_spec.rb +0 -14
  239. data/spec/spec/story/given_scenario_spec.rb +0 -27
  240. data/spec/spec/story/runner/plain_text_story_runner_spec.rb +0 -90
  241. data/spec/spec/story/runner/scenario_collector_spec.rb +0 -27
  242. data/spec/spec/story/runner/scenario_runner_spec.rb +0 -214
  243. data/spec/spec/story/runner/story_mediator_spec.rb +0 -143
  244. data/spec/spec/story/runner/story_parser_spec.rb +0 -401
  245. data/spec/spec/story/runner/story_runner_spec.rb +0 -294
  246. data/spec/spec/story/runner_spec.rb +0 -93
  247. data/spec/spec/story/scenario_spec.rb +0 -18
  248. data/spec/spec/story/step_group_spec.rb +0 -157
  249. data/spec/spec/story/step_mother_spec.rb +0 -84
  250. data/spec/spec/story/step_spec.rb +0 -272
  251. data/spec/spec/story/story_helper.rb +0 -2
  252. data/spec/spec/story/story_spec.rb +0 -84
  253. data/spec/spec/story/world_spec.rb +0 -423
  254. data/story_server/prototype/javascripts/builder.js +0 -136
  255. data/story_server/prototype/javascripts/controls.js +0 -972
  256. data/story_server/prototype/javascripts/dragdrop.js +0 -976
  257. data/story_server/prototype/javascripts/effects.js +0 -1117
  258. data/story_server/prototype/javascripts/prototype.js +0 -4140
  259. data/story_server/prototype/javascripts/rspec.js +0 -149
  260. data/story_server/prototype/javascripts/scriptaculous.js +0 -58
  261. data/story_server/prototype/javascripts/slider.js +0 -276
  262. data/story_server/prototype/javascripts/sound.js +0 -55
  263. data/story_server/prototype/javascripts/unittest.js +0 -568
  264. data/story_server/prototype/lib/server.rb +0 -24
  265. data/story_server/prototype/stories.html +0 -176
  266. data/story_server/prototype/stylesheets/rspec.css +0 -136
  267. data/story_server/prototype/stylesheets/test.css +0 -90
@@ -1,136 +0,0 @@
1
- // script.aculo.us builder.js v1.8.0_pre1, Fri Oct 12 21:34:51 +0200 2007
2
-
3
- // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
- //
5
- // script.aculo.us is freely distributable under the terms of an MIT-style license.
6
- // For details, see the script.aculo.us web site: http://script.aculo.us/
7
-
8
- var Builder = {
9
- NODEMAP: {
10
- AREA: 'map',
11
- CAPTION: 'table',
12
- COL: 'table',
13
- COLGROUP: 'table',
14
- LEGEND: 'fieldset',
15
- OPTGROUP: 'select',
16
- OPTION: 'select',
17
- PARAM: 'object',
18
- TBODY: 'table',
19
- TD: 'table',
20
- TFOOT: 'table',
21
- TH: 'table',
22
- THEAD: 'table',
23
- TR: 'table'
24
- },
25
- // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
26
- // due to a Firefox bug
27
- node: function(elementName) {
28
- elementName = elementName.toUpperCase();
29
-
30
- // try innerHTML approach
31
- var parentTag = this.NODEMAP[elementName] || 'div';
32
- var parentElement = document.createElement(parentTag);
33
- try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
34
- parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
35
- } catch(e) {}
36
- var element = parentElement.firstChild || null;
37
-
38
- // see if browser added wrapping tags
39
- if(element && (element.tagName.toUpperCase() != elementName))
40
- element = element.getElementsByTagName(elementName)[0];
41
-
42
- // fallback to createElement approach
43
- if(!element) element = document.createElement(elementName);
44
-
45
- // abort if nothing could be created
46
- if(!element) return;
47
-
48
- // attributes (or text)
49
- if(arguments[1])
50
- if(this._isStringOrNumber(arguments[1]) ||
51
- (arguments[1] instanceof Array) ||
52
- arguments[1].tagName) {
53
- this._children(element, arguments[1]);
54
- } else {
55
- var attrs = this._attributes(arguments[1]);
56
- if(attrs.length) {
57
- try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
58
- parentElement.innerHTML = "<" +elementName + " " +
59
- attrs + "></" + elementName + ">";
60
- } catch(e) {}
61
- element = parentElement.firstChild || null;
62
- // workaround firefox 1.0.X bug
63
- if(!element) {
64
- element = document.createElement(elementName);
65
- for(attr in arguments[1])
66
- element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
67
- }
68
- if(element.tagName.toUpperCase() != elementName)
69
- element = parentElement.getElementsByTagName(elementName)[0];
70
- }
71
- }
72
-
73
- // text, or array of children
74
- if(arguments[2])
75
- this._children(element, arguments[2]);
76
-
77
- return element;
78
- },
79
- _text: function(text) {
80
- return document.createTextNode(text);
81
- },
82
-
83
- ATTR_MAP: {
84
- 'className': 'class',
85
- 'htmlFor': 'for'
86
- },
87
-
88
- _attributes: function(attributes) {
89
- var attrs = [];
90
- for(attribute in attributes)
91
- attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
92
- '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
93
- return attrs.join(" ");
94
- },
95
- _children: function(element, children) {
96
- if(children.tagName) {
97
- element.appendChild(children);
98
- return;
99
- }
100
- if(typeof children=='object') { // array can hold nodes and text
101
- children.flatten().each( function(e) {
102
- if(typeof e=='object')
103
- element.appendChild(e)
104
- else
105
- if(Builder._isStringOrNumber(e))
106
- element.appendChild(Builder._text(e));
107
- });
108
- } else
109
- if(Builder._isStringOrNumber(children))
110
- element.appendChild(Builder._text(children));
111
- },
112
- _isStringOrNumber: function(param) {
113
- return(typeof param=='string' || typeof param=='number');
114
- },
115
- build: function(html) {
116
- var element = this.node('div');
117
- $(element).update(html.strip());
118
- return element.down();
119
- },
120
- dump: function(scope) {
121
- if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
122
-
123
- var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
124
- "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
125
- "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
126
- "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
127
- "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
128
- "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
129
-
130
- tags.each( function(tag){
131
- scope[tag] = function() {
132
- return Builder.node.apply(Builder, [tag].concat($A(arguments)));
133
- }
134
- });
135
- }
136
- }
@@ -1,972 +0,0 @@
1
- // script.aculo.us controls.js v1.8.0_pre1, Fri Oct 12 21:34:51 +0200 2007
2
-
3
- // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
- // (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
5
- // (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
6
- // Contributors:
7
- // Richard Livsey
8
- // Rahul Bhargava
9
- // Rob Wills
10
- //
11
- // script.aculo.us is freely distributable under the terms of an MIT-style license.
12
- // For details, see the script.aculo.us web site: http://script.aculo.us/
13
-
14
- // Autocompleter.Base handles all the autocompletion functionality
15
- // that's independent of the data source for autocompletion. This
16
- // includes drawing the autocompletion menu, observing keyboard
17
- // and mouse events, and similar.
18
- //
19
- // Specific autocompleters need to provide, at the very least,
20
- // a getUpdatedChoices function that will be invoked every time
21
- // the text inside the monitored textbox changes. This method
22
- // should get the text for which to provide autocompletion by
23
- // invoking this.getToken(), NOT by directly accessing
24
- // this.element.value. This is to allow incremental tokenized
25
- // autocompletion. Specific auto-completion logic (AJAX, etc)
26
- // belongs in getUpdatedChoices.
27
- //
28
- // Tokenized incremental autocompletion is enabled automatically
29
- // when an autocompleter is instantiated with the 'tokens' option
30
- // in the options parameter, e.g.:
31
- // new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
32
- // will incrementally autocomplete with a comma as the token.
33
- // Additionally, ',' in the above example can be replaced with
34
- // a token array, e.g. { tokens: [',', '\n'] } which
35
- // enables autocompletion on multiple tokens. This is most
36
- // useful when one of the tokens is \n (a newline), as it
37
- // allows smart autocompletion after linebreaks.
38
- //
39
- // vim:expandtab ts=8 sw=2
40
-
41
- if(typeof Effect == 'undefined')
42
- throw("controls.js requires including script.aculo.us' effects.js library");
43
-
44
- var Autocompleter = { }
45
- Autocompleter.Base = function() { };
46
- Autocompleter.Base.prototype = {
47
- baseInitialize: function(element, update, options) {
48
- element = $(element)
49
- this.element = element;
50
- this.update = $(update);
51
- this.hasFocus = false;
52
- this.changed = false;
53
- this.active = false;
54
- this.index = 0;
55
- this.entryCount = 0;
56
- this.oldElementValue = this.element.value;
57
-
58
- if(this.setOptions)
59
- this.setOptions(options);
60
- else
61
- this.options = options || { };
62
-
63
- this.options.paramName = this.options.paramName || this.element.name;
64
- this.options.tokens = this.options.tokens || [];
65
- this.options.frequency = this.options.frequency || 0.4;
66
- this.options.minChars = this.options.minChars || 1;
67
- this.options.onShow = this.options.onShow ||
68
- function(element, update){
69
- if(!update.style.position || update.style.position=='absolute') {
70
- update.style.position = 'absolute';
71
- Position.clone(element, update, {
72
- setHeight: false,
73
- offsetTop: element.offsetHeight
74
- });
75
- }
76
- Effect.Appear(update,{duration:0.15});
77
- };
78
- this.options.onHide = this.options.onHide ||
79
- function(element, update){ new Effect.Fade(update,{duration:0.15}) };
80
-
81
- if(typeof(this.options.tokens) == 'string')
82
- this.options.tokens = new Array(this.options.tokens);
83
- // Force carriage returns as token delimiters anyway
84
- if (!this.options.tokens.include('\n'))
85
- this.options.tokens.push('\n');
86
-
87
- this.observer = null;
88
-
89
- this.element.setAttribute('autocomplete','off');
90
-
91
- Element.hide(this.update);
92
-
93
- Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
94
- Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this));
95
- },
96
-
97
- show: function() {
98
- if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
99
- if(!this.iefix &&
100
- (Prototype.Browser.IE) &&
101
- (Element.getStyle(this.update, 'position')=='absolute')) {
102
- new Insertion.After(this.update,
103
- '<iframe id="' + this.update.id + '_iefix" '+
104
- 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
105
- 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
106
- this.iefix = $(this.update.id+'_iefix');
107
- }
108
- if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
109
- },
110
-
111
- fixIEOverlapping: function() {
112
- Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
113
- this.iefix.style.zIndex = 1;
114
- this.update.style.zIndex = 2;
115
- Element.show(this.iefix);
116
- },
117
-
118
- hide: function() {
119
- this.stopIndicator();
120
- if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
121
- if(this.iefix) Element.hide(this.iefix);
122
- },
123
-
124
- startIndicator: function() {
125
- if(this.options.indicator) Element.show(this.options.indicator);
126
- },
127
-
128
- stopIndicator: function() {
129
- if(this.options.indicator) Element.hide(this.options.indicator);
130
- },
131
-
132
- onKeyPress: function(event) {
133
- if(this.active)
134
- switch(event.keyCode) {
135
- case Event.KEY_TAB:
136
- case Event.KEY_RETURN:
137
- this.selectEntry();
138
- Event.stop(event);
139
- case Event.KEY_ESC:
140
- this.hide();
141
- this.active = false;
142
- Event.stop(event);
143
- return;
144
- case Event.KEY_LEFT:
145
- case Event.KEY_RIGHT:
146
- return;
147
- case Event.KEY_UP:
148
- this.markPrevious();
149
- this.render();
150
- if(Prototype.Browser.WebKit) Event.stop(event);
151
- return;
152
- case Event.KEY_DOWN:
153
- this.markNext();
154
- this.render();
155
- if(Prototype.Browser.WebKit) Event.stop(event);
156
- return;
157
- }
158
- else
159
- if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
160
- (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
161
-
162
- this.changed = true;
163
- this.hasFocus = true;
164
-
165
- if(this.observer) clearTimeout(this.observer);
166
- this.observer =
167
- setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
168
- },
169
-
170
- activate: function() {
171
- this.changed = false;
172
- this.hasFocus = true;
173
- this.getUpdatedChoices();
174
- },
175
-
176
- onHover: function(event) {
177
- var element = Event.findElement(event, 'LI');
178
- if(this.index != element.autocompleteIndex)
179
- {
180
- this.index = element.autocompleteIndex;
181
- this.render();
182
- }
183
- Event.stop(event);
184
- },
185
-
186
- onClick: function(event) {
187
- var element = Event.findElement(event, 'LI');
188
- this.index = element.autocompleteIndex;
189
- this.selectEntry();
190
- this.hide();
191
- },
192
-
193
- onBlur: function(event) {
194
- // needed to make click events working
195
- setTimeout(this.hide.bind(this), 250);
196
- this.hasFocus = false;
197
- this.active = false;
198
- },
199
-
200
- render: function() {
201
- if(this.entryCount > 0) {
202
- for (var i = 0; i < this.entryCount; i++)
203
- this.index==i ?
204
- Element.addClassName(this.getEntry(i),"selected") :
205
- Element.removeClassName(this.getEntry(i),"selected");
206
- if(this.hasFocus) {
207
- this.show();
208
- this.active = true;
209
- }
210
- } else {
211
- this.active = false;
212
- this.hide();
213
- }
214
- },
215
-
216
- markPrevious: function() {
217
- if(this.index > 0) this.index--
218
- else this.index = this.entryCount-1;
219
- this.getEntry(this.index).scrollIntoView(true);
220
- },
221
-
222
- markNext: function() {
223
- if(this.index < this.entryCount-1) this.index++
224
- else this.index = 0;
225
- this.getEntry(this.index).scrollIntoView(false);
226
- },
227
-
228
- getEntry: function(index) {
229
- return this.update.firstChild.childNodes[index];
230
- },
231
-
232
- getCurrentEntry: function() {
233
- return this.getEntry(this.index);
234
- },
235
-
236
- selectEntry: function() {
237
- this.active = false;
238
- this.updateElement(this.getCurrentEntry());
239
- },
240
-
241
- updateElement: function(selectedElement) {
242
- if (this.options.updateElement) {
243
- this.options.updateElement(selectedElement);
244
- return;
245
- }
246
- var value = '';
247
- if (this.options.select) {
248
- var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
249
- if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
250
- } else
251
- value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
252
-
253
- var bounds = this.getTokenBounds();
254
- if (bounds[0] != -1) {
255
- var newValue = this.element.value.substr(0, bounds[0]);
256
- var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
257
- if (whitespace)
258
- newValue += whitespace[0];
259
- this.element.value = newValue + value + this.element.value.substr(bounds[1]);
260
- } else {
261
- this.element.value = value;
262
- }
263
- this.oldElementValue = this.element.value;
264
- this.element.focus();
265
-
266
- if (this.options.afterUpdateElement)
267
- this.options.afterUpdateElement(this.element, selectedElement);
268
- },
269
-
270
- updateChoices: function(choices) {
271
- if(!this.changed && this.hasFocus) {
272
- this.update.innerHTML = choices;
273
- Element.cleanWhitespace(this.update);
274
- Element.cleanWhitespace(this.update.down());
275
-
276
- if(this.update.firstChild && this.update.down().childNodes) {
277
- this.entryCount =
278
- this.update.down().childNodes.length;
279
- for (var i = 0; i < this.entryCount; i++) {
280
- var entry = this.getEntry(i);
281
- entry.autocompleteIndex = i;
282
- this.addObservers(entry);
283
- }
284
- } else {
285
- this.entryCount = 0;
286
- }
287
-
288
- this.stopIndicator();
289
- this.index = 0;
290
-
291
- if(this.entryCount==1 && this.options.autoSelect) {
292
- this.selectEntry();
293
- this.hide();
294
- } else {
295
- this.render();
296
- }
297
- }
298
- },
299
-
300
- addObservers: function(element) {
301
- Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
302
- Event.observe(element, "click", this.onClick.bindAsEventListener(this));
303
- },
304
-
305
- onObserverEvent: function() {
306
- this.changed = false;
307
- this.tokenBounds = null;
308
- if(this.getToken().length>=this.options.minChars) {
309
- this.getUpdatedChoices();
310
- } else {
311
- this.active = false;
312
- this.hide();
313
- }
314
- this.oldElementValue = this.element.value;
315
- },
316
-
317
- getToken: function() {
318
- var bounds = this.getTokenBounds();
319
- return this.element.value.substring(bounds[0], bounds[1]).strip();
320
- },
321
-
322
- getTokenBounds: function() {
323
- if (null != this.tokenBounds) return this.tokenBounds;
324
- var value = this.element.value;
325
- if (value.strip().empty()) return [-1, 0];
326
- var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
327
- var offset = (diff == this.oldElementValue.length ? 1 : 0);
328
- var prevTokenPos = -1, nextTokenPos = value.length;
329
- var tp;
330
- for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
331
- tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
332
- if (tp > prevTokenPos) prevTokenPos = tp;
333
- tp = value.indexOf(this.options.tokens[index], diff + offset);
334
- if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
335
- }
336
- return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
337
- }
338
- }
339
-
340
- Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
341
- var boundary = Math.min(newS.length, oldS.length);
342
- for (var index = 0; index < boundary; ++index)
343
- if (newS[index] != oldS[index])
344
- return index;
345
- return boundary;
346
- };
347
-
348
- Ajax.Autocompleter = Class.create();
349
- Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
350
- initialize: function(element, update, url, options) {
351
- this.baseInitialize(element, update, options);
352
- this.options.asynchronous = true;
353
- this.options.onComplete = this.onComplete.bind(this);
354
- this.options.defaultParams = this.options.parameters || null;
355
- this.url = url;
356
- },
357
-
358
- getUpdatedChoices: function() {
359
- this.startIndicator();
360
-
361
- var entry = encodeURIComponent(this.options.paramName) + '=' +
362
- encodeURIComponent(this.getToken());
363
-
364
- this.options.parameters = this.options.callback ?
365
- this.options.callback(this.element, entry) : entry;
366
-
367
- if(this.options.defaultParams)
368
- this.options.parameters += '&' + this.options.defaultParams;
369
-
370
- new Ajax.Request(this.url, this.options);
371
- },
372
-
373
- onComplete: function(request) {
374
- this.updateChoices(request.responseText);
375
- }
376
-
377
- });
378
-
379
- // The local array autocompleter. Used when you'd prefer to
380
- // inject an array of autocompletion options into the page, rather
381
- // than sending out Ajax queries, which can be quite slow sometimes.
382
- //
383
- // The constructor takes four parameters. The first two are, as usual,
384
- // the id of the monitored textbox, and id of the autocompletion menu.
385
- // The third is the array you want to autocomplete from, and the fourth
386
- // is the options block.
387
- //
388
- // Extra local autocompletion options:
389
- // - choices - How many autocompletion choices to offer
390
- //
391
- // - partialSearch - If false, the autocompleter will match entered
392
- // text only at the beginning of strings in the
393
- // autocomplete array. Defaults to true, which will
394
- // match text at the beginning of any *word* in the
395
- // strings in the autocomplete array. If you want to
396
- // search anywhere in the string, additionally set
397
- // the option fullSearch to true (default: off).
398
- //
399
- // - fullSsearch - Search anywhere in autocomplete array strings.
400
- //
401
- // - partialChars - How many characters to enter before triggering
402
- // a partial match (unlike minChars, which defines
403
- // how many characters are required to do any match
404
- // at all). Defaults to 2.
405
- //
406
- // - ignoreCase - Whether to ignore case when autocompleting.
407
- // Defaults to true.
408
- //
409
- // It's possible to pass in a custom function as the 'selector'
410
- // option, if you prefer to write your own autocompletion logic.
411
- // In that case, the other options above will not apply unless
412
- // you support them.
413
-
414
- Autocompleter.Local = Class.create();
415
- Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
416
- initialize: function(element, update, array, options) {
417
- this.baseInitialize(element, update, options);
418
- this.options.array = array;
419
- },
420
-
421
- getUpdatedChoices: function() {
422
- this.updateChoices(this.options.selector(this));
423
- },
424
-
425
- setOptions: function(options) {
426
- this.options = Object.extend({
427
- choices: 10,
428
- partialSearch: true,
429
- partialChars: 2,
430
- ignoreCase: true,
431
- fullSearch: false,
432
- selector: function(instance) {
433
- var ret = []; // Beginning matches
434
- var partial = []; // Inside matches
435
- var entry = instance.getToken();
436
- var count = 0;
437
-
438
- for (var i = 0; i < instance.options.array.length &&
439
- ret.length < instance.options.choices ; i++) {
440
-
441
- var elem = instance.options.array[i];
442
- var foundPos = instance.options.ignoreCase ?
443
- elem.toLowerCase().indexOf(entry.toLowerCase()) :
444
- elem.indexOf(entry);
445
-
446
- while (foundPos != -1) {
447
- if (foundPos == 0 && elem.length != entry.length) {
448
- ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
449
- elem.substr(entry.length) + "</li>");
450
- break;
451
- } else if (entry.length >= instance.options.partialChars &&
452
- instance.options.partialSearch && foundPos != -1) {
453
- if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
454
- partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
455
- elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
456
- foundPos + entry.length) + "</li>");
457
- break;
458
- }
459
- }
460
-
461
- foundPos = instance.options.ignoreCase ?
462
- elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
463
- elem.indexOf(entry, foundPos + 1);
464
-
465
- }
466
- }
467
- if (partial.length)
468
- ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
469
- return "<ul>" + ret.join('') + "</ul>";
470
- }
471
- }, options || { });
472
- }
473
- });
474
-
475
- // AJAX in-place editor and collection editor
476
- // Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
477
-
478
- // Use this if you notice weird scrolling problems on some browsers,
479
- // the DOM might be a bit confused when this gets called so do this
480
- // waits 1 ms (with setTimeout) until it does the activation
481
- Field.scrollFreeActivate = function(field) {
482
- setTimeout(function() {
483
- Field.activate(field);
484
- }, 1);
485
- }
486
-
487
- Ajax.InPlaceEditor = Class.create();
488
- Object.extend(Ajax.InPlaceEditor, {
489
- DefaultOptions: {
490
- ajaxOptions: { },
491
- autoRows: 3, // Use when multi-line w/ rows == 1
492
- cancelControl: 'link', // 'link'|'button'|false
493
- cancelText: 'cancel',
494
- clickToEditText: 'Click to edit',
495
- externalControl: null, // id|elt
496
- externalControlOnly: false,
497
- fieldPostCreation: 'activate', // 'activate'|'focus'|false
498
- formClassName: 'inplaceeditor-form',
499
- formId: null, // id|elt
500
- highlightColor: '#ffff99',
501
- highlightEndColor: '#ffffff',
502
- hoverClassName: '',
503
- htmlResponse: true,
504
- loadingClassName: 'inplaceeditor-loading',
505
- loadingText: 'Loading...',
506
- okControl: 'button', // 'link'|'button'|false
507
- okText: 'ok',
508
- paramName: 'value',
509
- rows: 1, // If 1 and multi-line, uses autoRows
510
- savingClassName: 'inplaceeditor-saving',
511
- savingText: 'Saving...',
512
- size: 0,
513
- stripLoadedTextTags: false,
514
- submitOnBlur: false,
515
- textAfterControls: '',
516
- textBeforeControls: '',
517
- textBetweenControls: ''
518
- },
519
- DefaultCallbacks: {
520
- callback: function(form) {
521
- return Form.serialize(form);
522
- },
523
- onComplete: function(transport, element) {
524
- // For backward compatibility, this one is bound to the IPE, and passes
525
- // the element directly. It was too often customized, so we don't break it.
526
- new Effect.Highlight(element, {
527
- startcolor: this.options.highlightColor, keepBackgroundImage: true });
528
- },
529
- onEnterEditMode: null,
530
- onEnterHover: function(ipe) {
531
- ipe.element.style.backgroundColor = ipe.options.highlightColor;
532
- if (ipe._effect)
533
- ipe._effect.cancel();
534
- },
535
- onFailure: function(transport, ipe) {
536
- alert('Error communication with the server: ' + transport.responseText.stripTags());
537
- },
538
- onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
539
- onLeaveEditMode: null,
540
- onLeaveHover: function(ipe) {
541
- ipe._effect = new Effect.Highlight(ipe.element, {
542
- startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
543
- restorecolor: ipe._originalBackground, keepBackgroundImage: true
544
- });
545
- }
546
- },
547
- Listeners: {
548
- click: 'enterEditMode',
549
- keydown: 'checkForEscapeOrReturn',
550
- mouseover: 'enterHover',
551
- mouseout: 'leaveHover'
552
- }
553
- });
554
- Ajax.InPlaceEditor.prototype = {
555
- initialize: function(element, url, options) {
556
- this.url = url;
557
- this.element = element = $(element);
558
- this.prepareOptions();
559
- this._controls = { };
560
- arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
561
- Object.extend(this.options, options || { });
562
- if (!this.options.formId && this.element.id) {
563
- this.options.formId = this.element.id + '-inplaceeditor';
564
- if ($(this.options.formId))
565
- this.options.formId = '';
566
- }
567
- if (this.options.externalControl)
568
- this.options.externalControl = $(this.options.externalControl);
569
- if (!this.options.externalControl)
570
- this.options.externalControlOnly = false;
571
- this._originalBackground = this.element.getStyle('background-color') || 'transparent';
572
- this.element.title = this.options.clickToEditText;
573
- this._boundCancelHandler = this.handleFormCancellation.bind(this);
574
- this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
575
- this._boundFailureHandler = this.handleAJAXFailure.bind(this);
576
- this._boundSubmitHandler = this.handleFormSubmission.bind(this);
577
- this._boundWrapperHandler = this.wrapUp.bind(this);
578
- this.registerListeners();
579
- },
580
- checkForEscapeOrReturn: function(e) {
581
- if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
582
- if (Event.KEY_ESC == e.keyCode)
583
- this.handleFormCancellation(e);
584
- else if (Event.KEY_RETURN == e.keyCode)
585
- this.handleFormSubmission(e);
586
- },
587
- createControl: function(mode, handler, extraClasses) {
588
- var control = this.options[mode + 'Control'];
589
- var text = this.options[mode + 'Text'];
590
- if ('button' == control) {
591
- var btn = document.createElement('input');
592
- btn.type = 'submit';
593
- btn.value = text;
594
- btn.className = 'editor_' + mode + '_button';
595
- if ('cancel' == mode)
596
- btn.onclick = this._boundCancelHandler;
597
- this._form.appendChild(btn);
598
- this._controls[mode] = btn;
599
- } else if ('link' == control) {
600
- var link = document.createElement('a');
601
- link.href = '#';
602
- link.appendChild(document.createTextNode(text));
603
- link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
604
- link.className = 'editor_' + mode + '_link';
605
- if (extraClasses)
606
- link.className += ' ' + extraClasses;
607
- this._form.appendChild(link);
608
- this._controls[mode] = link;
609
- }
610
- },
611
- createEditField: function() {
612
- var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
613
- var fld;
614
- if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
615
- fld = document.createElement('input');
616
- fld.type = 'text';
617
- var size = this.options.size || this.options.cols || 0;
618
- if (0 < size) fld.size = size;
619
- } else {
620
- fld = document.createElement('textarea');
621
- fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
622
- fld.cols = this.options.cols || 40;
623
- }
624
- fld.name = this.options.paramName;
625
- fld.value = text; // No HTML breaks conversion anymore
626
- fld.className = 'editor_field';
627
- if (this.options.submitOnBlur)
628
- fld.onblur = this._boundSubmitHandler;
629
- this._controls.editor = fld;
630
- if (this.options.loadTextURL)
631
- this.loadExternalText();
632
- this._form.appendChild(this._controls.editor);
633
- },
634
- createForm: function() {
635
- var ipe = this;
636
- function addText(mode, condition) {
637
- var text = ipe.options['text' + mode + 'Controls'];
638
- if (!text || condition === false) return;
639
- ipe._form.appendChild(document.createTextNode(text));
640
- };
641
- this._form = $(document.createElement('form'));
642
- this._form.id = this.options.formId;
643
- this._form.addClassName(this.options.formClassName);
644
- this._form.onsubmit = this._boundSubmitHandler;
645
- this.createEditField();
646
- if ('textarea' == this._controls.editor.tagName.toLowerCase())
647
- this._form.appendChild(document.createElement('br'));
648
- if (this.options.onFormCustomization)
649
- this.options.onFormCustomization(this, this._form);
650
- addText('Before', this.options.okControl || this.options.cancelControl);
651
- this.createControl('ok', this._boundSubmitHandler);
652
- addText('Between', this.options.okControl && this.options.cancelControl);
653
- this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
654
- addText('After', this.options.okControl || this.options.cancelControl);
655
- },
656
- destroy: function() {
657
- if (this._oldInnerHTML)
658
- this.element.innerHTML = this._oldInnerHTML;
659
- this.leaveEditMode();
660
- this.unregisterListeners();
661
- },
662
- enterEditMode: function(e) {
663
- if (this._saving || this._editing) return;
664
- this._editing = true;
665
- this.triggerCallback('onEnterEditMode');
666
- if (this.options.externalControl)
667
- this.options.externalControl.hide();
668
- this.element.hide();
669
- this.createForm();
670
- this.element.parentNode.insertBefore(this._form, this.element);
671
- if (!this.options.loadTextURL)
672
- this.postProcessEditField();
673
- if (e) Event.stop(e);
674
- },
675
- enterHover: function(e) {
676
- if (this.options.hoverClassName)
677
- this.element.addClassName(this.options.hoverClassName);
678
- if (this._saving) return;
679
- this.triggerCallback('onEnterHover');
680
- },
681
- getText: function() {
682
- return this.element.innerHTML;
683
- },
684
- handleAJAXFailure: function(transport) {
685
- this.triggerCallback('onFailure', transport);
686
- if (this._oldInnerHTML) {
687
- this.element.innerHTML = this._oldInnerHTML;
688
- this._oldInnerHTML = null;
689
- }
690
- },
691
- handleFormCancellation: function(e) {
692
- this.wrapUp();
693
- if (e) Event.stop(e);
694
- },
695
- handleFormSubmission: function(e) {
696
- var form = this._form;
697
- var value = $F(this._controls.editor);
698
- this.prepareSubmission();
699
- var params = this.options.callback(form, value);
700
- params = (params ? params + '&' : '?') + 'editorId=' + this.element.id;
701
- if (this.options.htmlResponse) {
702
- var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
703
- Object.extend(options, {
704
- parameters: params,
705
- onComplete: this._boundWrapperHandler,
706
- onFailure: this._boundFailureHandler
707
- });
708
- new Ajax.Updater({ success: this.element }, this.url, options);
709
- } else {
710
- var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
711
- Object.extend(options, {
712
- parameters: params,
713
- onComplete: this._boundWrapperHandler,
714
- onFailure: this._boundFailureHandler
715
- });
716
- new Ajax.Request(this.url, options);
717
- }
718
- if (e) Event.stop(e);
719
- },
720
- leaveEditMode: function() {
721
- this.element.removeClassName(this.options.savingClassName);
722
- this.removeForm();
723
- this.leaveHover();
724
- this.element.style.backgroundColor = this._originalBackground;
725
- this.element.show();
726
- if (this.options.externalControl)
727
- this.options.externalControl.show();
728
- this._saving = false;
729
- this._editing = false;
730
- this._oldInnerHTML = null;
731
- this.triggerCallback('onLeaveEditMode');
732
- },
733
- leaveHover: function(e) {
734
- if (this.options.hoverClassName)
735
- this.element.removeClassName(this.options.hoverClassName);
736
- if (this._saving) return;
737
- this.triggerCallback('onLeaveHover');
738
- },
739
- loadExternalText: function() {
740
- this._form.addClassName(this.options.loadingClassName);
741
- this._controls.editor.disabled = true;
742
- var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
743
- Object.extend(options, {
744
- parameters: 'editorId=' + encodeURIComponent(this.element.id),
745
- onComplete: Prototype.emptyFunction,
746
- onSuccess: function(transport) {
747
- this._form.removeClassName(this.options.loadingClassName);
748
- var text = transport.responseText;
749
- if (this.options.stripLoadedTextTags)
750
- text = text.stripTags();
751
- this._controls.editor.value = text;
752
- this._controls.editor.disabled = false;
753
- this.postProcessEditField();
754
- }.bind(this),
755
- onFailure: this._boundFailureHandler
756
- });
757
- new Ajax.Request(this.options.loadTextURL, options);
758
- },
759
- postProcessEditField: function() {
760
- var fpc = this.options.fieldPostCreation;
761
- if (fpc)
762
- $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
763
- },
764
- prepareOptions: function() {
765
- this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
766
- Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
767
- [this._extraDefaultOptions].flatten().compact().each(function(defs) {
768
- Object.extend(this.options, defs);
769
- }.bind(this));
770
- },
771
- prepareSubmission: function() {
772
- this._saving = true;
773
- this.removeForm();
774
- this.leaveHover();
775
- this.showSaving();
776
- },
777
- registerListeners: function() {
778
- this._listeners = { };
779
- var listener;
780
- $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
781
- listener = this[pair.value].bind(this);
782
- this._listeners[pair.key] = listener;
783
- if (!this.options.externalControlOnly)
784
- this.element.observe(pair.key, listener);
785
- if (this.options.externalControl)
786
- this.options.externalControl.observe(pair.key, listener);
787
- }.bind(this));
788
- },
789
- removeForm: function() {
790
- if (!this._form) return;
791
- this._form.remove();
792
- this._form = null;
793
- this._controls = { };
794
- },
795
- showSaving: function() {
796
- this._oldInnerHTML = this.element.innerHTML;
797
- this.element.innerHTML = this.options.savingText;
798
- this.element.addClassName(this.options.savingClassName);
799
- this.element.style.backgroundColor = this._originalBackground;
800
- this.element.show();
801
- },
802
- triggerCallback: function(cbName, arg) {
803
- if ('function' == typeof this.options[cbName]) {
804
- this.options[cbName](this, arg);
805
- }
806
- },
807
- unregisterListeners: function() {
808
- $H(this._listeners).each(function(pair) {
809
- if (!this.options.externalControlOnly)
810
- this.element.stopObserving(pair.key, pair.value);
811
- if (this.options.externalControl)
812
- this.options.externalControl.stopObserving(pair.key, pair.value);
813
- }.bind(this));
814
- },
815
- wrapUp: function(transport) {
816
- this.leaveEditMode();
817
- // Can't use triggerCallback due to backward compatibility: requires
818
- // binding + direct element
819
- this._boundComplete(transport, this.element);
820
- }
821
- };
822
- Object.extend(Ajax.InPlaceEditor.prototype, {
823
- dispose: Ajax.InPlaceEditor.prototype.destroy
824
- });
825
-
826
-
827
- Ajax.InPlaceCollectionEditor = Class.create();
828
- Ajax.InPlaceCollectionEditor.DefaultOptions = {
829
- loadingCollectionText: 'Loading options...'
830
- };
831
- Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
832
- Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
833
- initialize: function(element, url, options) {
834
- this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
835
- Ajax.InPlaceEditor.prototype.initialize.call(this, element, url, options);
836
- },
837
-
838
- createEditField: function() {
839
- var list = document.createElement('select');
840
- list.name = this.options.paramName;
841
- list.size = 1;
842
- this._controls.editor = list;
843
- this._collection = this.options.collection || [];
844
- if (this.options.loadCollectionURL)
845
- this.loadCollection();
846
- else
847
- this.checkForExternalText();
848
- this._form.appendChild(this._controls.editor);
849
- },
850
-
851
- loadCollection: function() {
852
- this._form.addClassName(this.options.loadingClassName);
853
- this.showLoadingText(this.options.loadingCollectionText);
854
- var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
855
- Object.extend(options, {
856
- parameters: 'editorId=' + encodeURIComponent(this.element.id),
857
- onComplete: Prototype.emptyFunction,
858
- onSuccess: function(transport) {
859
- var js = transport.responseText.strip();
860
- if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
861
- throw 'Server returned an invalid collection representation.';
862
- this._collection = eval(js);
863
- this.checkForExternalText();
864
- }.bind(this),
865
- onFailure: this.onFailure
866
- });
867
- new Ajax.Request(this.options.loadCollectionURL, options);
868
- },
869
-
870
- showLoadingText: function(text) {
871
- this._controls.editor.disabled = true;
872
- var tempOption = this._controls.editor.firstChild;
873
- if (!tempOption) {
874
- tempOption = document.createElement('option');
875
- tempOption.value = '';
876
- this._controls.editor.appendChild(tempOption);
877
- tempOption.selected = true;
878
- }
879
- tempOption.update((text || '').stripScripts().stripTags());
880
- },
881
-
882
- checkForExternalText: function() {
883
- this._text = this.getText();
884
- if (this.options.loadTextURL)
885
- this.loadExternalText();
886
- else
887
- this.buildOptionList();
888
- },
889
-
890
- loadExternalText: function() {
891
- this.showLoadingText(this.options.loadingText);
892
- var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
893
- Object.extend(options, {
894
- parameters: 'editorId=' + encodeURIComponent(this.element.id),
895
- onComplete: Prototype.emptyFunction,
896
- onSuccess: function(transport) {
897
- this._text = transport.responseText.strip();
898
- this.buildOptionList();
899
- }.bind(this),
900
- onFailure: this.onFailure
901
- });
902
- new Ajax.Request(this.options.loadTextURL, options);
903
- },
904
-
905
- buildOptionList: function() {
906
- this._form.removeClassName(this.options.loadingClassName);
907
- this._collection = this._collection.map(function(entry) {
908
- return 2 === entry.length ? entry : [entry, entry].flatten();
909
- });
910
- var marker = ('value' in this.options) ? this.options.value : this._text;
911
- var textFound = this._collection.any(function(entry) {
912
- return entry[0] == marker;
913
- }.bind(this));
914
- this._controls.editor.update('');
915
- var option;
916
- this._collection.each(function(entry, index) {
917
- option = document.createElement('option');
918
- option.value = entry[0];
919
- option.selected = textFound ? entry[0] == marker : 0 == index;
920
- option.appendChild(document.createTextNode(entry[1]));
921
- this._controls.editor.appendChild(option);
922
- }.bind(this));
923
- this._controls.editor.disabled = false;
924
- Field.scrollFreeActivate(this._controls.editor);
925
- }
926
- });
927
-
928
- //**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
929
- //**** This only exists for a while, in order to let ****
930
- //**** users adapt to the new API. Read up on the new ****
931
- //**** API and convert your code to it ASAP! ****
932
-
933
- Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
934
- if (!options) return;
935
- function fallback(name, expr) {
936
- if (name in options || expr === undefined) return;
937
- options[name] = expr;
938
- };
939
- fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
940
- options.cancelLink == options.cancelButton == false ? false : undefined)));
941
- fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
942
- options.okLink == options.okButton == false ? false : undefined)));
943
- fallback('highlightColor', options.highlightcolor);
944
- fallback('highlightEndColor', options.highlightendcolor);
945
- };
946
-
947
-
948
- // Delayed observer, like Form.Element.Observer,
949
- // but waits for delay after last key input
950
- // Ideal for live-search fields
951
-
952
- Form.Element.DelayedObserver = Class.create();
953
- Form.Element.DelayedObserver.prototype = {
954
- initialize: function(element, delay, callback) {
955
- this.delay = delay || 0.5;
956
- this.element = $(element);
957
- this.callback = callback;
958
- this.timer = null;
959
- this.lastValue = $F(this.element);
960
- Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
961
- },
962
- delayedListener: function(event) {
963
- if(this.lastValue == $F(this.element)) return;
964
- if(this.timer) clearTimeout(this.timer);
965
- this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
966
- this.lastValue = $F(this.element);
967
- },
968
- onTimerEvent: function() {
969
- this.timer = null;
970
- this.callback(this.element, $F(this.element));
971
- }
972
- };