actionpack 1.12.5 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +517 -15
- data/MIT-LICENSE +1 -1
- data/README +18 -20
- data/Rakefile +7 -4
- data/examples/address_book_controller.rb +3 -3
- data/examples/blog_controller.cgi +3 -3
- data/examples/debate_controller.cgi +5 -5
- data/lib/action_controller.rb +2 -2
- data/lib/action_controller/assertions.rb +73 -311
- data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
- data/lib/action_controller/assertions/dom_assertions.rb +25 -0
- data/lib/action_controller/assertions/model_assertions.rb +12 -0
- data/lib/action_controller/assertions/response_assertions.rb +140 -0
- data/lib/action_controller/assertions/routing_assertions.rb +82 -0
- data/lib/action_controller/assertions/selector_assertions.rb +571 -0
- data/lib/action_controller/assertions/tag_assertions.rb +117 -0
- data/lib/action_controller/base.rb +334 -163
- data/lib/action_controller/benchmarking.rb +3 -6
- data/lib/action_controller/caching.rb +83 -22
- data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
- data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
- data/lib/action_controller/cgi_process.rb +50 -27
- data/lib/action_controller/components.rb +21 -25
- data/lib/action_controller/cookies.rb +10 -9
- data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
- data/lib/action_controller/filters.rb +448 -225
- data/lib/action_controller/flash.rb +24 -20
- data/lib/action_controller/helpers.rb +2 -5
- data/lib/action_controller/integration.rb +40 -16
- data/lib/action_controller/layout.rb +11 -8
- data/lib/action_controller/macros/auto_complete.rb +3 -2
- data/lib/action_controller/macros/in_place_editing.rb +3 -2
- data/lib/action_controller/mime_responds.rb +41 -29
- data/lib/action_controller/mime_type.rb +68 -10
- data/lib/action_controller/pagination.rb +4 -3
- data/lib/action_controller/request.rb +22 -14
- data/lib/action_controller/rescue.rb +25 -22
- data/lib/action_controller/resources.rb +302 -0
- data/lib/action_controller/response.rb +20 -2
- data/lib/action_controller/response.rb.rej +17 -0
- data/lib/action_controller/routing.rb +1165 -567
- data/lib/action_controller/scaffolding.rb +30 -31
- data/lib/action_controller/session/active_record_store.rb +2 -0
- data/lib/action_controller/session/drb_store.rb +4 -0
- data/lib/action_controller/session/mem_cache_store.rb +4 -0
- data/lib/action_controller/session_management.rb +6 -9
- data/lib/action_controller/status_codes.rb +89 -0
- data/lib/action_controller/streaming.rb +6 -15
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
- data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
- data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
- data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
- data/lib/action_controller/test_process.rb +52 -30
- data/lib/action_controller/url_rewriter.rb +63 -29
- data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
- data/lib/action_controller/verification.rb +22 -11
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +46 -43
- data/lib/action_view/compiled_templates.rb +1 -1
- data/lib/action_view/helpers/active_record_helper.rb +54 -17
- data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
- data/lib/action_view/helpers/capture_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +258 -136
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/deprecated_helper.rb +34 -0
- data/lib/action_view/helpers/form_helper.rb +75 -35
- data/lib/action_view/helpers/form_options_helper.rb +7 -5
- data/lib/action_view/helpers/form_tag_helper.rb +44 -6
- data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
- data/lib/action_view/helpers/javascript_helper.rb +71 -10
- data/lib/action_view/helpers/javascripts/controls.js +41 -23
- data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
- data/lib/action_view/helpers/javascripts/effects.js +293 -163
- data/lib/action_view/helpers/javascripts/prototype.js +897 -389
- data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
- data/lib/action_view/helpers/number_helper.rb +111 -65
- data/lib/action_view/helpers/prototype_helper.rb +84 -109
- data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
- data/lib/action_view/helpers/tag_helper.rb +69 -16
- data/lib/action_view/helpers/text_helper.rb +149 -112
- data/lib/action_view/helpers/url_helper.rb +200 -107
- data/lib/action_view/template_error.rb +66 -42
- data/test/abstract_unit.rb +4 -2
- data/test/active_record_unit.rb +84 -56
- data/test/activerecord/active_record_assertions_test.rb +26 -18
- data/test/activerecord/active_record_store_test.rb +4 -36
- data/test/activerecord/pagination_test.rb +1 -6
- data/test/controller/action_pack_assertions_test.rb +230 -113
- data/test/controller/addresses_render_test.rb +2 -6
- data/test/controller/assert_select_test.rb +576 -0
- data/test/controller/base_test.rb +73 -3
- data/test/controller/caching_test.rb +228 -0
- data/test/controller/capture_test.rb +12 -10
- data/test/controller/cgi_test.rb +89 -12
- data/test/controller/components_test.rb +24 -2
- data/test/controller/content_type_test.rb +139 -0
- data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
- data/test/controller/cookie_test.rb +33 -25
- data/test/controller/deprecated_instance_variables_test.rb +48 -0
- data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
- data/test/controller/fake_controllers.rb +0 -1
- data/test/controller/filters_test.rb +301 -16
- data/test/controller/flash_test.rb +19 -2
- data/test/controller/helper_test.rb +2 -2
- data/test/controller/integration_test.rb +154 -0
- data/test/controller/layout_test.rb +115 -1
- data/test/controller/mime_responds_test.rb +94 -0
- data/test/controller/mime_type_test.rb +9 -0
- data/test/controller/new_render_test.rb +161 -11
- data/test/controller/raw_post_test.rb +52 -15
- data/test/controller/redirect_test.rb +27 -14
- data/test/controller/render_test.rb +76 -29
- data/test/controller/request_test.rb +55 -4
- data/test/controller/resources_test.rb +274 -0
- data/test/controller/routing_test.rb +1533 -824
- data/test/controller/selector_test.rb +628 -0
- data/test/controller/send_file_test.rb +9 -1
- data/test/controller/session_management_test.rb +51 -0
- data/test/controller/test_test.rb +113 -29
- data/test/controller/url_rewriter_test.rb +86 -17
- data/test/controller/verification_test.rb +19 -17
- data/test/controller/webservice_test.rb +0 -7
- data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
- data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/public/javascripts/application.js +1 -0
- data/test/fixtures/test/_hello.rxml +1 -0
- data/test/fixtures/test/hello_world_container.rxml +3 -0
- data/test/fixtures/topic.rb +2 -2
- data/test/template/active_record_helper_test.rb +83 -12
- data/test/template/asset_tag_helper_test.rb +75 -95
- data/test/template/compiled_templates_test.rb +1 -0
- data/test/template/date_helper_test.rb +873 -181
- data/test/template/deprecated_helper_test.rb +36 -0
- data/test/template/deprecated_instance_variables_test.rb +43 -0
- data/test/template/form_helper_test.rb +77 -1
- data/test/template/form_options_helper_test.rb +4 -0
- data/test/template/form_tag_helper_test.rb +66 -2
- data/test/template/java_script_macros_helper_test.rb +4 -1
- data/test/template/javascript_helper_test.rb +29 -0
- data/test/template/number_helper_test.rb +63 -27
- data/test/template/prototype_helper_test.rb +77 -34
- data/test/template/tag_helper_test.rb +34 -6
- data/test/template/text_helper_test.rb +69 -34
- data/test/template/url_helper_test.rb +168 -16
- data/test/testing_sandbox.rb +7 -22
- metadata +66 -20
- data/filler.txt +0 -50
- data/lib/action_controller/code_generation.rb +0 -235
- data/lib/action_controller/vendor/xml_simple.rb +0 -1019
- data/test/controller/caching_filestore.rb +0 -74
- data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
- data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
- data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
- data/test/fixtures/dont_load.rb +0 -3
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/tag_helper'
|
2
|
+
require File.dirname(__FILE__) + '/prototype_helper'
|
2
3
|
|
3
4
|
module ActionView
|
4
5
|
module Helpers
|
@@ -40,15 +41,50 @@ module ActionView
|
|
40
41
|
unless const_defined? :JAVASCRIPT_PATH
|
41
42
|
JAVASCRIPT_PATH = File.join(File.dirname(__FILE__), 'javascripts')
|
42
43
|
end
|
44
|
+
|
45
|
+
include PrototypeHelper
|
43
46
|
|
44
|
-
# Returns a link that
|
47
|
+
# Returns a link that will trigger a JavaScript +function+ using the
|
45
48
|
# onclick handler and return false after the fact.
|
46
49
|
#
|
50
|
+
# The +function+ argument can be omitted in favor of an +update_page+
|
51
|
+
# block, which evaluates to a string when the template is rendered
|
52
|
+
# (instead of making an Ajax request first).
|
53
|
+
#
|
47
54
|
# Examples:
|
48
55
|
# link_to_function "Greeting", "alert('Hello world!')"
|
49
|
-
#
|
50
|
-
|
56
|
+
# Produces:
|
57
|
+
# <a onclick="alert('Hello world!'); return false;" href="#">Greeting</a>
|
58
|
+
#
|
59
|
+
# link_to_function(image_tag("delete"), "if (confirm('Really?')) do_delete()")
|
60
|
+
# Produces:
|
61
|
+
# <a onclick="if (confirm('Really?')) do_delete(); return false;" href="#">
|
62
|
+
# <img src="/images/delete.png?" alt="Delete"/>
|
63
|
+
# </a>
|
64
|
+
#
|
65
|
+
# link_to_function("Show me more", nil, :id => "more_link") do |page|
|
66
|
+
# page[:details].visual_effect :toggle_blind
|
67
|
+
# page[:more_link].replace_html "Show me less"
|
68
|
+
# end
|
69
|
+
# Produces:
|
70
|
+
# <a href="#" id="more_link" onclick="try {
|
71
|
+
# $("details").visualEffect("toggle_blind");
|
72
|
+
# $("more_link").update("Show me less");
|
73
|
+
# }
|
74
|
+
# catch (e) {
|
75
|
+
# alert('RJS error:\n\n' + e.toString());
|
76
|
+
# alert('$(\"details\").visualEffect(\"toggle_blind\");
|
77
|
+
# \n$(\"more_link\").update(\"Show me less\");');
|
78
|
+
# throw e
|
79
|
+
# };
|
80
|
+
# return false;">Show me more</a>
|
81
|
+
#
|
82
|
+
def link_to_function(name, *args, &block)
|
83
|
+
html_options = args.last.is_a?(Hash) ? args.pop : {}
|
84
|
+
function = args[0] || ''
|
85
|
+
|
51
86
|
html_options.symbolize_keys!
|
87
|
+
function = update_page(&block) if block_given?
|
52
88
|
content_tag(
|
53
89
|
"a", name,
|
54
90
|
html_options.merge({
|
@@ -58,14 +94,28 @@ module ActionView
|
|
58
94
|
)
|
59
95
|
end
|
60
96
|
|
61
|
-
# Returns a
|
97
|
+
# Returns a button that'll trigger a JavaScript +function+ using the
|
62
98
|
# onclick handler.
|
63
99
|
#
|
100
|
+
# The +function+ argument can be omitted in favor of an +update_page+
|
101
|
+
# block, which evaluates to a string when the template is rendered
|
102
|
+
# (instead of making an Ajax request first).
|
103
|
+
#
|
64
104
|
# Examples:
|
65
105
|
# button_to_function "Greeting", "alert('Hello world!')"
|
66
|
-
# button_to_function "Delete", "if confirm('Really?')
|
67
|
-
|
106
|
+
# button_to_function "Delete", "if (confirm('Really?')) do_delete()"
|
107
|
+
# button_to_function "Details" do |page|
|
108
|
+
# page[:details].visual_effect :toggle_slide
|
109
|
+
# end
|
110
|
+
# button_to_function "Details", :class => "details_button" do |page|
|
111
|
+
# page[:details].visual_effect :toggle_slide
|
112
|
+
# end
|
113
|
+
def button_to_function(name, *args, &block)
|
114
|
+
html_options = args.last.is_a?(Hash) ? args.pop : {}
|
115
|
+
function = args[0] || ''
|
116
|
+
|
68
117
|
html_options.symbolize_keys!
|
118
|
+
function = update_page(&block) if block_given?
|
69
119
|
tag(:input, html_options.merge({
|
70
120
|
:type => "button", :value => name,
|
71
121
|
:onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
|
@@ -99,13 +149,24 @@ module ActionView
|
|
99
149
|
|
100
150
|
# Escape carrier returns and single and double quotes for JavaScript segments.
|
101
151
|
def escape_javascript(javascript)
|
102
|
-
(javascript || '').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
|
152
|
+
(javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
|
103
153
|
end
|
104
154
|
|
105
155
|
# Returns a JavaScript tag with the +content+ inside. Example:
|
106
|
-
# javascript_tag "alert('All is good')"
|
107
|
-
|
108
|
-
|
156
|
+
# javascript_tag "alert('All is good')"
|
157
|
+
#
|
158
|
+
# Returns:
|
159
|
+
#
|
160
|
+
# <script type="text/javascript">
|
161
|
+
# //<![CDATA[
|
162
|
+
# alert('All is good')
|
163
|
+
# //]]>
|
164
|
+
# </script>
|
165
|
+
#
|
166
|
+
# +html_options+ may be a hash of attributes for the <script> tag. Example:
|
167
|
+
# javascript_tag "alert('All is good')", :defer => 'true' # => <script defer="true" type="text/javascript">alert('All is good')</script>
|
168
|
+
def javascript_tag(content, html_options = {})
|
169
|
+
content_tag("script", javascript_cdata_section(content), html_options.merge(:type => "text/javascript"))
|
109
170
|
end
|
110
171
|
|
111
172
|
def javascript_cdata_section(content) #:nodoc:
|
@@ -1,12 +1,13 @@
|
|
1
|
-
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
2
|
-
// (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
|
3
|
-
// (c) 2005 Jon Tirsen (http://www.tirsen.com)
|
1
|
+
// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
2
|
+
// (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
|
3
|
+
// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
|
4
4
|
// Contributors:
|
5
5
|
// Richard Livsey
|
6
6
|
// Rahul Bhargava
|
7
7
|
// Rob Wills
|
8
8
|
//
|
9
|
-
//
|
9
|
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
10
|
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
10
11
|
|
11
12
|
// Autocompleter.Base handles all the autocompletion functionality
|
12
13
|
// that's independent of the data source for autocompletion. This
|
@@ -33,6 +34,9 @@
|
|
33
34
|
// useful when one of the tokens is \n (a newline), as it
|
34
35
|
// allows smart autocompletion after linebreaks.
|
35
36
|
|
37
|
+
if(typeof Effect == 'undefined')
|
38
|
+
throw("controls.js requires including script.aculo.us' effects.js library");
|
39
|
+
|
36
40
|
var Autocompleter = {}
|
37
41
|
Autocompleter.Base = function() {};
|
38
42
|
Autocompleter.Base.prototype = {
|
@@ -45,7 +49,7 @@ Autocompleter.Base.prototype = {
|
|
45
49
|
this.index = 0;
|
46
50
|
this.entryCount = 0;
|
47
51
|
|
48
|
-
if
|
52
|
+
if(this.setOptions)
|
49
53
|
this.setOptions(options);
|
50
54
|
else
|
51
55
|
this.options = options || {};
|
@@ -55,17 +59,20 @@ Autocompleter.Base.prototype = {
|
|
55
59
|
this.options.frequency = this.options.frequency || 0.4;
|
56
60
|
this.options.minChars = this.options.minChars || 1;
|
57
61
|
this.options.onShow = this.options.onShow ||
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
function(element, update){
|
63
|
+
if(!update.style.position || update.style.position=='absolute') {
|
64
|
+
update.style.position = 'absolute';
|
65
|
+
Position.clone(element, update, {
|
66
|
+
setHeight: false,
|
67
|
+
offsetTop: element.offsetHeight
|
68
|
+
});
|
69
|
+
}
|
70
|
+
Effect.Appear(update,{duration:0.15});
|
71
|
+
};
|
65
72
|
this.options.onHide = this.options.onHide ||
|
66
|
-
|
73
|
+
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
|
67
74
|
|
68
|
-
if
|
75
|
+
if(typeof(this.options.tokens) == 'string')
|
69
76
|
this.options.tokens = new Array(this.options.tokens);
|
70
77
|
|
71
78
|
this.observer = null;
|
@@ -94,7 +101,7 @@ Autocompleter.Base.prototype = {
|
|
94
101
|
},
|
95
102
|
|
96
103
|
fixIEOverlapping: function() {
|
97
|
-
Position.clone(this.update, this.iefix);
|
104
|
+
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
|
98
105
|
this.iefix.style.zIndex = 1;
|
99
106
|
this.update.style.zIndex = 2;
|
100
107
|
Element.show(this.iefix);
|
@@ -202,11 +209,13 @@ Autocompleter.Base.prototype = {
|
|
202
209
|
markPrevious: function() {
|
203
210
|
if(this.index > 0) this.index--
|
204
211
|
else this.index = this.entryCount-1;
|
212
|
+
this.getEntry(this.index).scrollIntoView(true);
|
205
213
|
},
|
206
214
|
|
207
215
|
markNext: function() {
|
208
216
|
if(this.index < this.entryCount-1) this.index++
|
209
217
|
else this.index = 0;
|
218
|
+
this.getEntry(this.index).scrollIntoView(false);
|
210
219
|
},
|
211
220
|
|
212
221
|
getEntry: function(index) {
|
@@ -254,11 +263,11 @@ Autocompleter.Base.prototype = {
|
|
254
263
|
if(!this.changed && this.hasFocus) {
|
255
264
|
this.update.innerHTML = choices;
|
256
265
|
Element.cleanWhitespace(this.update);
|
257
|
-
Element.cleanWhitespace(this.update.
|
266
|
+
Element.cleanWhitespace(this.update.down());
|
258
267
|
|
259
|
-
if(this.update.firstChild && this.update.
|
268
|
+
if(this.update.firstChild && this.update.down().childNodes) {
|
260
269
|
this.entryCount =
|
261
|
-
this.update.
|
270
|
+
this.update.down().childNodes.length;
|
262
271
|
for (var i = 0; i < this.entryCount; i++) {
|
263
272
|
var entry = this.getEntry(i);
|
264
273
|
entry.autocompleteIndex = i;
|
@@ -269,9 +278,14 @@ Autocompleter.Base.prototype = {
|
|
269
278
|
}
|
270
279
|
|
271
280
|
this.stopIndicator();
|
272
|
-
|
273
281
|
this.index = 0;
|
274
|
-
|
282
|
+
|
283
|
+
if(this.entryCount==1 && this.options.autoSelect) {
|
284
|
+
this.selectEntry();
|
285
|
+
this.hide();
|
286
|
+
} else {
|
287
|
+
this.render();
|
288
|
+
}
|
275
289
|
}
|
276
290
|
},
|
277
291
|
|
@@ -459,6 +473,7 @@ Ajax.InPlaceEditor.prototype = {
|
|
459
473
|
this.element = $(element);
|
460
474
|
|
461
475
|
this.options = Object.extend({
|
476
|
+
paramName: "value",
|
462
477
|
okButton: true,
|
463
478
|
okText: "ok",
|
464
479
|
cancelLink: true,
|
@@ -531,7 +546,7 @@ Ajax.InPlaceEditor.prototype = {
|
|
531
546
|
Element.hide(this.element);
|
532
547
|
this.createForm();
|
533
548
|
this.element.parentNode.insertBefore(this.form, this.element);
|
534
|
-
Field.scrollFreeActivate(this.editField);
|
549
|
+
if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);
|
535
550
|
// stop the event to avoid a page refresh in Safari
|
536
551
|
if (evt) {
|
537
552
|
Event.stop(evt);
|
@@ -590,7 +605,7 @@ Ajax.InPlaceEditor.prototype = {
|
|
590
605
|
var textField = document.createElement("input");
|
591
606
|
textField.obj = this;
|
592
607
|
textField.type = "text";
|
593
|
-
textField.name =
|
608
|
+
textField.name = this.options.paramName;
|
594
609
|
textField.value = text;
|
595
610
|
textField.style.backgroundColor = this.options.highlightcolor;
|
596
611
|
textField.className = 'editor_field';
|
@@ -603,7 +618,7 @@ Ajax.InPlaceEditor.prototype = {
|
|
603
618
|
this.options.textarea = true;
|
604
619
|
var textArea = document.createElement("textarea");
|
605
620
|
textArea.obj = this;
|
606
|
-
textArea.name =
|
621
|
+
textArea.name = this.options.paramName;
|
607
622
|
textArea.value = this.convertHTMLLineBreaks(text);
|
608
623
|
textArea.rows = this.options.rows;
|
609
624
|
textArea.cols = this.options.cols || 40;
|
@@ -636,6 +651,7 @@ Ajax.InPlaceEditor.prototype = {
|
|
636
651
|
Element.removeClassName(this.form, this.options.loadingClassName);
|
637
652
|
this.editField.disabled = false;
|
638
653
|
this.editField.value = transport.responseText.stripTags();
|
654
|
+
Field.scrollFreeActivate(this.editField);
|
639
655
|
},
|
640
656
|
onclickCancel: function() {
|
641
657
|
this.onComplete();
|
@@ -772,6 +788,8 @@ Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
|
|
772
788
|
collection.each(function(e,i) {
|
773
789
|
optionTag = document.createElement("option");
|
774
790
|
optionTag.value = (e instanceof Array) ? e[0] : e;
|
791
|
+
if((typeof this.options.value == 'undefined') &&
|
792
|
+
((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true;
|
775
793
|
if(this.options.value==optionTag.value) optionTag.selected = true;
|
776
794
|
optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
|
777
795
|
selectTag.appendChild(optionTag);
|
@@ -1,9 +1,11 @@
|
|
1
|
-
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
2
|
-
// (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
|
1
|
+
// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
2
|
+
// (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
|
3
3
|
//
|
4
|
-
//
|
4
|
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
5
|
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
5
6
|
|
6
|
-
|
7
|
+
if(typeof Effect == 'undefined')
|
8
|
+
throw("dragdrop.js requires including script.aculo.us' effects.js library");
|
7
9
|
|
8
10
|
var Droppables = {
|
9
11
|
drops: [],
|
@@ -145,8 +147,16 @@ var Draggables = {
|
|
145
147
|
},
|
146
148
|
|
147
149
|
activate: function(draggable) {
|
148
|
-
|
149
|
-
|
150
|
+
if(draggable.options.delay) {
|
151
|
+
this._timeout = setTimeout(function() {
|
152
|
+
Draggables._timeout = null;
|
153
|
+
window.focus();
|
154
|
+
Draggables.activeDraggable = draggable;
|
155
|
+
}.bind(this), draggable.options.delay);
|
156
|
+
} else {
|
157
|
+
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
|
158
|
+
this.activeDraggable = draggable;
|
159
|
+
}
|
150
160
|
},
|
151
161
|
|
152
162
|
deactivate: function() {
|
@@ -160,10 +170,15 @@ var Draggables = {
|
|
160
170
|
// the same coordinates, prevent needless redrawing (moz bug?)
|
161
171
|
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
|
162
172
|
this._lastPointer = pointer;
|
173
|
+
|
163
174
|
this.activeDraggable.updateDrag(event, pointer);
|
164
175
|
},
|
165
176
|
|
166
177
|
endDrag: function(event) {
|
178
|
+
if(this._timeout) {
|
179
|
+
clearTimeout(this._timeout);
|
180
|
+
this._timeout = null;
|
181
|
+
}
|
167
182
|
if(!this.activeDraggable) return;
|
168
183
|
this._lastPointer = null;
|
169
184
|
this.activeDraggable.endDrag(event);
|
@@ -190,6 +205,7 @@ var Draggables = {
|
|
190
205
|
this.observers.each( function(o) {
|
191
206
|
if(o[eventName]) o[eventName](eventName, draggable, event);
|
192
207
|
});
|
208
|
+
if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
|
193
209
|
},
|
194
210
|
|
195
211
|
_cacheObserverCallbacks: function() {
|
@@ -204,39 +220,59 @@ var Draggables = {
|
|
204
220
|
/*--------------------------------------------------------------------------*/
|
205
221
|
|
206
222
|
var Draggable = Class.create();
|
223
|
+
Draggable._dragging = {};
|
224
|
+
|
207
225
|
Draggable.prototype = {
|
208
226
|
initialize: function(element) {
|
209
|
-
var
|
227
|
+
var defaults = {
|
210
228
|
handle: false,
|
211
|
-
starteffect: function(element) {
|
212
|
-
new Effect.Opacity(element, {duration:0.2, from:1.0, to:0.7});
|
213
|
-
},
|
214
229
|
reverteffect: function(element, top_offset, left_offset) {
|
215
230
|
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
|
216
|
-
|
231
|
+
new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
|
232
|
+
queue: {scope:'_draggable', position:'end'}
|
233
|
+
});
|
217
234
|
},
|
218
|
-
endeffect: function(element) {
|
219
|
-
|
235
|
+
endeffect: function(element) {
|
236
|
+
var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0;
|
237
|
+
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
|
238
|
+
queue: {scope:'_draggable', position:'end'},
|
239
|
+
afterFinish: function(){
|
240
|
+
Draggable._dragging[element] = false
|
241
|
+
}
|
242
|
+
});
|
220
243
|
},
|
221
244
|
zindex: 1000,
|
222
245
|
revert: false,
|
223
246
|
scroll: false,
|
224
247
|
scrollSensitivity: 20,
|
225
248
|
scrollSpeed: 15,
|
226
|
-
snap: false
|
227
|
-
|
249
|
+
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
|
250
|
+
delay: 0
|
251
|
+
};
|
252
|
+
|
253
|
+
if(!arguments[1] || typeof arguments[1].endeffect == 'undefined')
|
254
|
+
Object.extend(defaults, {
|
255
|
+
starteffect: function(element) {
|
256
|
+
element._opacity = Element.getOpacity(element);
|
257
|
+
Draggable._dragging[element] = true;
|
258
|
+
new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
|
259
|
+
}
|
260
|
+
});
|
261
|
+
|
262
|
+
var options = Object.extend(defaults, arguments[1] || {});
|
228
263
|
|
229
264
|
this.element = $(element);
|
230
265
|
|
231
|
-
if(options.handle && (typeof options.handle == 'string'))
|
232
|
-
|
233
|
-
|
234
|
-
}
|
266
|
+
if(options.handle && (typeof options.handle == 'string'))
|
267
|
+
this.handle = this.element.down('.'+options.handle, 0);
|
268
|
+
|
235
269
|
if(!this.handle) this.handle = $(options.handle);
|
236
270
|
if(!this.handle) this.handle = this.element;
|
237
271
|
|
238
|
-
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML)
|
272
|
+
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
|
239
273
|
options.scroll = $(options.scroll);
|
274
|
+
this._isScrollChild = Element.childOf(this.element, options.scroll);
|
275
|
+
}
|
240
276
|
|
241
277
|
Element.makePositioned(this.element); // fix IE
|
242
278
|
|
@@ -262,6 +298,8 @@ Draggable.prototype = {
|
|
262
298
|
},
|
263
299
|
|
264
300
|
initDrag: function(event) {
|
301
|
+
if(typeof Draggable._dragging[this.element] != 'undefined' &&
|
302
|
+
Draggable._dragging[this.element]) return;
|
265
303
|
if(Event.isLeftClick(event)) {
|
266
304
|
// abort on form elements, fixes a Firefox issue
|
267
305
|
var src = Event.element(event);
|
@@ -272,11 +310,6 @@ Draggable.prototype = {
|
|
272
310
|
src.tagName=='BUTTON' ||
|
273
311
|
src.tagName=='TEXTAREA')) return;
|
274
312
|
|
275
|
-
if(this.element._revert) {
|
276
|
-
this.element._revert.cancel();
|
277
|
-
this.element._revert = null;
|
278
|
-
}
|
279
|
-
|
280
313
|
var pointer = [Event.pointerX(event), Event.pointerY(event)];
|
281
314
|
var pos = Position.cumulativeOffset(this.element);
|
282
315
|
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
|
@@ -312,6 +345,7 @@ Draggable.prototype = {
|
|
312
345
|
}
|
313
346
|
|
314
347
|
Draggables.notify('onStart', this, event);
|
348
|
+
|
315
349
|
if(this.options.starteffect) this.options.starteffect(this.element);
|
316
350
|
},
|
317
351
|
|
@@ -320,6 +354,7 @@ Draggable.prototype = {
|
|
320
354
|
Position.prepare();
|
321
355
|
Droppables.show(pointer, this.element);
|
322
356
|
Draggables.notify('onDrag', this, event);
|
357
|
+
|
323
358
|
this.draw(pointer);
|
324
359
|
if(this.options.change) this.options.change(this);
|
325
360
|
|
@@ -331,8 +366,8 @@ Draggable.prototype = {
|
|
331
366
|
with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
|
332
367
|
} else {
|
333
368
|
p = Position.page(this.options.scroll);
|
334
|
-
p[0] += this.options.scroll.scrollLeft;
|
335
|
-
p[1] += this.options.scroll.scrollTop;
|
369
|
+
p[0] += this.options.scroll.scrollLeft + Position.deltaX;
|
370
|
+
p[1] += this.options.scroll.scrollTop + Position.deltaY;
|
336
371
|
p.push(p[0]+this.options.scroll.offsetWidth);
|
337
372
|
p.push(p[1]+this.options.scroll.offsetHeight);
|
338
373
|
}
|
@@ -378,7 +413,7 @@ Draggable.prototype = {
|
|
378
413
|
|
379
414
|
if(this.options.endeffect)
|
380
415
|
this.options.endeffect(this.element);
|
381
|
-
|
416
|
+
|
382
417
|
Draggables.deactivate(this);
|
383
418
|
Droppables.reset();
|
384
419
|
},
|
@@ -398,10 +433,15 @@ Draggable.prototype = {
|
|
398
433
|
|
399
434
|
draw: function(point) {
|
400
435
|
var pos = Position.cumulativeOffset(this.element);
|
436
|
+
if(this.options.ghosting) {
|
437
|
+
var r = Position.realOffset(this.element);
|
438
|
+
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
|
439
|
+
}
|
440
|
+
|
401
441
|
var d = this.currentDelta();
|
402
442
|
pos[0] -= d[0]; pos[1] -= d[1];
|
403
443
|
|
404
|
-
if(this.options.scroll && (this.options.scroll != window)) {
|
444
|
+
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
|
405
445
|
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
|
406
446
|
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
|
407
447
|
}
|
@@ -412,7 +452,7 @@ Draggable.prototype = {
|
|
412
452
|
|
413
453
|
if(this.options.snap) {
|
414
454
|
if(typeof this.options.snap == 'function') {
|
415
|
-
p = this.options.snap(p[0],p[1]);
|
455
|
+
p = this.options.snap(p[0],p[1],this);
|
416
456
|
} else {
|
417
457
|
if(this.options.snap instanceof Array) {
|
418
458
|
p = p.map( function(v, i) {
|
@@ -428,6 +468,7 @@ Draggable.prototype = {
|
|
428
468
|
style.left = p[0] + "px";
|
429
469
|
if((!this.options.constraint) || (this.options.constraint=='vertical'))
|
430
470
|
style.top = p[1] + "px";
|
471
|
+
|
431
472
|
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
|
432
473
|
},
|
433
474
|
|
@@ -440,6 +481,7 @@ Draggable.prototype = {
|
|
440
481
|
},
|
441
482
|
|
442
483
|
startScrolling: function(speed) {
|
484
|
+
if(!(speed[0] || speed[1])) return;
|
443
485
|
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
|
444
486
|
this.lastScrolled = new Date();
|
445
487
|
this.scrollInterval = setInterval(this.scroll.bind(this), 10);
|
@@ -464,14 +506,16 @@ Draggable.prototype = {
|
|
464
506
|
Position.prepare();
|
465
507
|
Droppables.show(Draggables._lastPointer, this.element);
|
466
508
|
Draggables.notify('onDrag', this);
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
Draggables._lastScrollPointer[0]
|
472
|
-
|
473
|
-
Draggables._lastScrollPointer[1]
|
474
|
-
|
509
|
+
if (this._isScrollChild) {
|
510
|
+
Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
|
511
|
+
Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
|
512
|
+
Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
|
513
|
+
if (Draggables._lastScrollPointer[0] < 0)
|
514
|
+
Draggables._lastScrollPointer[0] = 0;
|
515
|
+
if (Draggables._lastScrollPointer[1] < 0)
|
516
|
+
Draggables._lastScrollPointer[1] = 0;
|
517
|
+
this.draw(Draggables._lastScrollPointer);
|
518
|
+
}
|
475
519
|
|
476
520
|
if(this.options.change) this.options.change(this);
|
477
521
|
},
|
@@ -523,6 +567,8 @@ SortableObserver.prototype = {
|
|
523
567
|
}
|
524
568
|
|
525
569
|
var Sortable = {
|
570
|
+
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
|
571
|
+
|
526
572
|
sortables: {},
|
527
573
|
|
528
574
|
_findRootElement: function(element) {
|
@@ -563,12 +609,13 @@ var Sortable = {
|
|
563
609
|
containment: element, // also takes array of elements (or id's); or false
|
564
610
|
handle: false, // or a CSS class
|
565
611
|
only: false,
|
612
|
+
delay: 0,
|
566
613
|
hoverclass: null,
|
567
614
|
ghosting: false,
|
568
615
|
scroll: false,
|
569
616
|
scrollSensitivity: 20,
|
570
617
|
scrollSpeed: 15,
|
571
|
-
format:
|
618
|
+
format: this.SERIALIZE_RULE,
|
572
619
|
onChange: Prototype.emptyFunction,
|
573
620
|
onUpdate: Prototype.emptyFunction
|
574
621
|
}, arguments[1] || {});
|
@@ -582,6 +629,7 @@ var Sortable = {
|
|
582
629
|
scroll: options.scroll,
|
583
630
|
scrollSpeed: options.scrollSpeed,
|
584
631
|
scrollSensitivity: options.scrollSensitivity,
|
632
|
+
delay: options.delay,
|
585
633
|
ghosting: options.ghosting,
|
586
634
|
constraint: options.constraint,
|
587
635
|
handle: options.handle };
|
@@ -610,7 +658,6 @@ var Sortable = {
|
|
610
658
|
tree: options.tree,
|
611
659
|
hoverclass: options.hoverclass,
|
612
660
|
onHover: Sortable.onHover
|
613
|
-
//greedy: !options.dropOnEmpty
|
614
661
|
}
|
615
662
|
|
616
663
|
var options_for_tree = {
|
@@ -635,7 +682,7 @@ var Sortable = {
|
|
635
682
|
(this.findElements(element, options) || []).each( function(e) {
|
636
683
|
// handles are per-draggable
|
637
684
|
var handle = options.handle ?
|
638
|
-
|
685
|
+
$(e).down('.'+options.handle,0) : e;
|
639
686
|
options.draggables.push(
|
640
687
|
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
|
641
688
|
Droppables.add(e, options_for_droppable);
|
@@ -706,7 +753,7 @@ var Sortable = {
|
|
706
753
|
if(!Element.isParent(dropon, element)) {
|
707
754
|
var index;
|
708
755
|
|
709
|
-
var children = Sortable.findElements(dropon, {tag: droponOptions.tag});
|
756
|
+
var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
|
710
757
|
var child = null;
|
711
758
|
|
712
759
|
if(children) {
|
@@ -733,7 +780,7 @@ var Sortable = {
|
|
733
780
|
},
|
734
781
|
|
735
782
|
unmark: function() {
|
736
|
-
if(Sortable._marker)
|
783
|
+
if(Sortable._marker) Sortable._marker.hide();
|
737
784
|
},
|
738
785
|
|
739
786
|
mark: function(dropon, position) {
|
@@ -742,23 +789,21 @@ var Sortable = {
|
|
742
789
|
if(sortable && !sortable.ghosting) return;
|
743
790
|
|
744
791
|
if(!Sortable._marker) {
|
745
|
-
Sortable._marker =
|
746
|
-
|
747
|
-
|
748
|
-
Sortable._marker.style.position = 'absolute';
|
792
|
+
Sortable._marker =
|
793
|
+
($('dropmarker') || Element.extend(document.createElement('DIV'))).
|
794
|
+
hide().addClassName('dropmarker').setStyle({position:'absolute'});
|
749
795
|
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
|
750
796
|
}
|
751
797
|
var offsets = Position.cumulativeOffset(dropon);
|
752
|
-
Sortable._marker.
|
753
|
-
Sortable._marker.style.top = offsets[1] + 'px';
|
798
|
+
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
|
754
799
|
|
755
800
|
if(position=='after')
|
756
801
|
if(sortable.overlap == 'horizontal')
|
757
|
-
Sortable._marker.
|
802
|
+
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
|
758
803
|
else
|
759
|
-
Sortable._marker.
|
804
|
+
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
|
760
805
|
|
761
|
-
|
806
|
+
Sortable._marker.show();
|
762
807
|
},
|
763
808
|
|
764
809
|
_tree: function(element, options, parent) {
|
@@ -773,9 +818,9 @@ var Sortable = {
|
|
773
818
|
id: encodeURIComponent(match ? match[1] : null),
|
774
819
|
element: element,
|
775
820
|
parent: parent,
|
776
|
-
children:
|
821
|
+
children: [],
|
777
822
|
position: parent.children.length,
|
778
|
-
container:
|
823
|
+
container: $(children[i]).down(options.treeTag)
|
779
824
|
}
|
780
825
|
|
781
826
|
/* Get the element containing the children and recurse over it */
|
@@ -788,17 +833,6 @@ var Sortable = {
|
|
788
833
|
return parent;
|
789
834
|
},
|
790
835
|
|
791
|
-
/* Finds the first element of the given tag type within a parent element.
|
792
|
-
Used for finding the first LI[ST] within a L[IST]I[TEM].*/
|
793
|
-
_findChildrenElement: function (element, containerTag) {
|
794
|
-
if (element && element.hasChildNodes)
|
795
|
-
for (var i = 0; i < element.childNodes.length; ++i)
|
796
|
-
if (element.childNodes[i].tagName == containerTag)
|
797
|
-
return element.childNodes[i];
|
798
|
-
|
799
|
-
return null;
|
800
|
-
},
|
801
|
-
|
802
836
|
tree: function(element) {
|
803
837
|
element = $(element);
|
804
838
|
var sortableOptions = this.options(element);
|
@@ -813,12 +847,12 @@ var Sortable = {
|
|
813
847
|
var root = {
|
814
848
|
id: null,
|
815
849
|
parent: null,
|
816
|
-
children:
|
850
|
+
children: [],
|
817
851
|
container: element,
|
818
852
|
position: 0
|
819
853
|
}
|
820
854
|
|
821
|
-
return Sortable._tree
|
855
|
+
return Sortable._tree(element, options, root);
|
822
856
|
},
|
823
857
|
|
824
858
|
/* Construct a [i] index for a particular node */
|
@@ -867,7 +901,7 @@ var Sortable = {
|
|
867
901
|
|
868
902
|
if (options.tree) {
|
869
903
|
return Sortable.tree(element, arguments[1]).children.map( function (item) {
|
870
|
-
return [name + Sortable._constructIndex(item) + "=" +
|
904
|
+
return [name + Sortable._constructIndex(item) + "[id]=" +
|
871
905
|
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
|
872
906
|
}).flatten().join('&');
|
873
907
|
} else {
|
@@ -878,12 +912,10 @@ var Sortable = {
|
|
878
912
|
}
|
879
913
|
}
|
880
914
|
|
881
|
-
|
915
|
+
// Returns true if child is contained within element
|
882
916
|
Element.isParent = function(child, element) {
|
883
917
|
if (!child.parentNode || child == element) return false;
|
884
|
-
|
885
918
|
if (child.parentNode == element) return true;
|
886
|
-
|
887
919
|
return Element.isParent(child.parentNode, element);
|
888
920
|
}
|
889
921
|
|
@@ -906,8 +938,5 @@ Element.findChildren = function(element, only, recursive, tagName) {
|
|
906
938
|
}
|
907
939
|
|
908
940
|
Element.offsetSize = function (element, type) {
|
909
|
-
|
910
|
-
|
911
|
-
else
|
912
|
-
return element.offsetWidth;
|
913
|
-
}
|
941
|
+
return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
|
942
|
+
}
|