actionpack 1.9.1 → 1.10.1
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 +237 -0
- data/README +12 -12
- data/lib/action_controller.rb +17 -12
- data/lib/action_controller/assertions.rb +119 -67
- data/lib/action_controller/base.rb +184 -102
- data/lib/action_controller/benchmarking.rb +35 -6
- data/lib/action_controller/caching.rb +115 -58
- data/lib/action_controller/cgi_ext/cgi_methods.rb +54 -21
- data/lib/action_controller/cgi_ext/cookie_performance_fix.rb +39 -35
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +34 -21
- data/lib/action_controller/cgi_process.rb +23 -20
- data/lib/action_controller/components.rb +11 -2
- data/lib/action_controller/dependencies.rb +0 -5
- data/lib/action_controller/deprecated_redirects.rb +17 -0
- data/lib/action_controller/filters.rb +13 -9
- data/lib/action_controller/flash.rb +7 -7
- data/lib/action_controller/helpers.rb +1 -14
- data/lib/action_controller/layout.rb +40 -29
- data/lib/action_controller/macros/auto_complete.rb +52 -0
- data/lib/action_controller/macros/in_place_editing.rb +32 -0
- data/lib/action_controller/pagination.rb +44 -28
- data/lib/action_controller/request.rb +54 -40
- data/lib/action_controller/rescue.rb +8 -6
- data/lib/action_controller/routing.rb +77 -28
- data/lib/action_controller/scaffolding.rb +10 -14
- data/lib/action_controller/session/active_record_store.rb +36 -7
- data/lib/action_controller/session_management.rb +126 -0
- data/lib/action_controller/streaming.rb +14 -5
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +1 -1
- data/lib/action_controller/templates/rescues/_trace.rhtml +24 -0
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -13
- data/lib/action_controller/templates/rescues/template_error.rhtml +4 -2
- data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
- data/lib/action_controller/test_process.rb +35 -17
- data/lib/action_controller/upload_progress.rb +52 -0
- data/lib/action_controller/url_rewriter.rb +21 -16
- data/lib/action_controller/vendor/html-scanner/html/document.rb +2 -2
- data/lib/action_controller/vendor/html-scanner/html/node.rb +30 -3
- data/lib/action_pack/version.rb +9 -0
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +204 -60
- data/lib/action_view/compiled_templates.rb +70 -0
- data/lib/action_view/helpers/active_record_helper.rb +7 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +22 -12
- data/lib/action_view/helpers/capture_helper.rb +2 -10
- data/lib/action_view/helpers/date_helper.rb +21 -13
- data/lib/action_view/helpers/form_helper.rb +14 -10
- data/lib/action_view/helpers/form_options_helper.rb +4 -4
- data/lib/action_view/helpers/form_tag_helper.rb +59 -25
- data/lib/action_view/helpers/java_script_macros_helper.rb +188 -0
- data/lib/action_view/helpers/javascript_helper.rb +68 -133
- data/lib/action_view/helpers/javascripts/controls.js +427 -165
- data/lib/action_view/helpers/javascripts/dragdrop.js +256 -277
- data/lib/action_view/helpers/javascripts/effects.js +766 -277
- data/lib/action_view/helpers/javascripts/prototype.js +906 -218
- data/lib/action_view/helpers/javascripts/slider.js +258 -0
- data/lib/action_view/helpers/number_helper.rb +4 -3
- data/lib/action_view/helpers/pagination_helper.rb +42 -27
- data/lib/action_view/helpers/tag_helper.rb +25 -11
- data/lib/action_view/helpers/text_helper.rb +119 -13
- data/lib/action_view/helpers/upload_progress_helper.rb +2 -2
- data/lib/action_view/helpers/url_helper.rb +68 -21
- data/lib/action_view/partials.rb +17 -6
- data/lib/action_view/template_error.rb +19 -24
- data/rakefile +4 -3
- data/test/abstract_unit.rb +2 -1
- data/test/controller/action_pack_assertions_test.rb +62 -2
- data/test/controller/active_record_assertions_test.rb +5 -6
- data/test/controller/active_record_store_test.rb +23 -1
- data/test/controller/addresses_render_test.rb +4 -0
- data/test/controller/{base_tests.rb → base_test.rb} +4 -3
- data/test/controller/benchmark_test.rb +36 -0
- data/test/controller/caching_filestore.rb +22 -40
- data/test/controller/capture_test.rb +10 -1
- data/test/controller/cgi_test.rb +145 -23
- data/test/controller/components_test.rb +50 -0
- data/test/controller/custom_handler_test.rb +3 -3
- data/test/controller/fake_controllers.rb +24 -0
- data/test/controller/filters_test.rb +6 -6
- data/test/controller/flash_test.rb +6 -6
- data/test/controller/fragment_store_setting_test.rb +45 -0
- data/test/controller/helper_test.rb +1 -3
- data/test/controller/new_render_test.rb +119 -7
- data/test/controller/redirect_test.rb +11 -1
- data/test/controller/render_test.rb +34 -1
- data/test/controller/request_test.rb +14 -5
- data/test/controller/routing_test.rb +238 -42
- data/test/controller/send_file_test.rb +11 -10
- data/test/controller/session_management_test.rb +94 -0
- data/test/controller/test_test.rb +194 -5
- data/test/controller/url_rewriter_test.rb +46 -0
- data/test/fixtures/layouts/talk_from_action.rhtml +2 -0
- data/test/fixtures/layouts/yield.rhtml +2 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/multipart/large_text_file +10 -0
- data/test/fixtures/multipart/mixed_files +0 -0
- data/test/fixtures/multipart/single_parameter +5 -0
- data/test/fixtures/multipart/text_file +10 -0
- data/test/fixtures/test/_customer_greeting.rhtml +1 -0
- data/test/fixtures/test/_hash_object.rhtml +1 -0
- data/test/fixtures/test/_person.rhtml +2 -0
- data/test/fixtures/test/action_talk_to_layout.rhtml +2 -0
- data/test/fixtures/test/content_for.rhtml +2 -0
- data/test/fixtures/test/potential_conflicts.rhtml +4 -0
- data/test/template/active_record_helper_test.rb +15 -8
- data/test/template/asset_tag_helper_test.rb +40 -16
- data/test/template/compiled_templates_tests.rb +63 -0
- data/test/template/date_helper_test.rb +80 -4
- data/test/template/form_helper_test.rb +48 -42
- data/test/template/form_options_helper_test.rb +40 -40
- data/test/template/form_tag_helper_test.rb +21 -15
- data/test/template/java_script_macros_helper_test.rb +56 -0
- data/test/template/javascript_helper_test.rb +70 -47
- data/test/template/number_helper_test.rb +2 -0
- data/test/template/tag_helper_test.rb +9 -0
- data/test/template/text_helper_test.rb +146 -1
- data/test/template/upload_progress_helper_testx.rb +11 -147
- data/test/template/url_helper_test.rb +90 -22
- data/test/testing_sandbox.rb +26 -0
- metadata +37 -7
- data/lib/action_controller/auto_complete.rb +0 -47
- data/lib/action_controller/deprecated_renders_and_redirects.rb +0 -76
- data/lib/action_controller/session.rb +0 -14
@@ -2,193 +2,79 @@
|
|
2
2
|
//
|
3
3
|
// Element.Class part Copyright (c) 2005 by Rick Olson
|
4
4
|
//
|
5
|
-
//
|
6
|
-
// a copy of this software and associated documentation files (the
|
7
|
-
// "Software"), to deal in the Software without restriction, including
|
8
|
-
// without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
// distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
// permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
// the following conditions:
|
12
|
-
//
|
13
|
-
// The above copyright notice and this permission notice shall be
|
14
|
-
// included in all copies or substantial portions of the Software.
|
15
|
-
//
|
16
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
-
|
24
|
-
Element.Class = {
|
25
|
-
// Element.toggleClass(element, className) toggles the class being on/off
|
26
|
-
// Element.toggleClass(element, className1, className2) toggles between both classes,
|
27
|
-
// defaulting to className1 if neither exist
|
28
|
-
toggle: function(element, className) {
|
29
|
-
if(Element.Class.has(element, className)) {
|
30
|
-
Element.Class.remove(element, className);
|
31
|
-
if(arguments.length == 3) Element.Class.add(element, arguments[2]);
|
32
|
-
} else {
|
33
|
-
Element.Class.add(element, className);
|
34
|
-
if(arguments.length == 3) Element.Class.remove(element, arguments[2]);
|
35
|
-
}
|
36
|
-
},
|
37
|
-
|
38
|
-
// gets space-delimited classnames of an element as an array
|
39
|
-
get: function(element) {
|
40
|
-
element = $(element);
|
41
|
-
return element.className.split(' ');
|
42
|
-
},
|
43
|
-
|
44
|
-
// functions adapted from original functions by Gavin Kistner
|
45
|
-
remove: function(element) {
|
46
|
-
element = $(element);
|
47
|
-
var regEx;
|
48
|
-
for(var i = 1; i < arguments.length; i++) {
|
49
|
-
regEx = new RegExp("^" + arguments[i] + "\\b\\s*|\\s*\\b" + arguments[i] + "\\b", 'g');
|
50
|
-
element.className = element.className.replace(regEx, '')
|
51
|
-
}
|
52
|
-
},
|
53
|
-
|
54
|
-
add: function(element) {
|
55
|
-
element = $(element);
|
56
|
-
for(var i = 1; i < arguments.length; i++) {
|
57
|
-
Element.Class.remove(element, arguments[i]);
|
58
|
-
element.className += (element.className.length > 0 ? ' ' : '') + arguments[i];
|
59
|
-
}
|
60
|
-
},
|
61
|
-
|
62
|
-
// returns true if all given classes exist in said element
|
63
|
-
has: function(element) {
|
64
|
-
element = $(element);
|
65
|
-
if(!element || !element.className) return false;
|
66
|
-
var regEx;
|
67
|
-
for(var i = 1; i < arguments.length; i++) {
|
68
|
-
regEx = new RegExp("\\b" + arguments[i] + "\\b");
|
69
|
-
if(!regEx.test(element.className)) return false;
|
70
|
-
}
|
71
|
-
return true;
|
72
|
-
},
|
73
|
-
|
74
|
-
// expects arrays of strings and/or strings as optional paramters
|
75
|
-
// Element.Class.has_any(element, ['classA','classB','classC'], 'classD')
|
76
|
-
has_any: function(element) {
|
77
|
-
element = $(element);
|
78
|
-
if(!element || !element.className) return false;
|
79
|
-
var regEx;
|
80
|
-
for(var i = 1; i < arguments.length; i++) {
|
81
|
-
if((typeof arguments[i] == 'object') &&
|
82
|
-
(arguments[i].constructor == Array)) {
|
83
|
-
for(var j = 0; j < arguments[i].length; j++) {
|
84
|
-
regEx = new RegExp("\\b" + arguments[i][j] + "\\b");
|
85
|
-
if(regEx.test(element.className)) return true;
|
86
|
-
}
|
87
|
-
} else {
|
88
|
-
regEx = new RegExp("\\b" + arguments[i] + "\\b");
|
89
|
-
if(regEx.test(element.className)) return true;
|
90
|
-
}
|
91
|
-
}
|
92
|
-
return false;
|
93
|
-
},
|
94
|
-
|
95
|
-
childrenWith: function(element, className) {
|
96
|
-
var children = $(element).getElementsByTagName('*');
|
97
|
-
var elements = new Array();
|
98
|
-
|
99
|
-
for (var i = 0; i < children.length; i++) {
|
100
|
-
if (Element.Class.has(children[i], className)) {
|
101
|
-
elements.push(children[i]);
|
102
|
-
break;
|
103
|
-
}
|
104
|
-
}
|
105
|
-
|
106
|
-
return elements;
|
107
|
-
}
|
108
|
-
}
|
5
|
+
// See scriptaculous.js for full license.
|
109
6
|
|
110
7
|
/*--------------------------------------------------------------------------*/
|
111
8
|
|
112
9
|
var Droppables = {
|
113
|
-
drops:
|
114
|
-
|
10
|
+
drops: [],
|
11
|
+
|
115
12
|
remove: function(element) {
|
116
|
-
|
117
|
-
if(this.drops[i].element == element)
|
118
|
-
this.drops.splice(i,1);
|
13
|
+
this.drops = this.drops.reject(function(d) { return d.element==element });
|
119
14
|
},
|
120
|
-
|
15
|
+
|
121
16
|
add: function(element) {
|
122
|
-
|
17
|
+
element = $(element);
|
123
18
|
var options = Object.extend({
|
124
19
|
greedy: true,
|
125
20
|
hoverclass: null
|
126
21
|
}, arguments[1] || {});
|
127
|
-
|
22
|
+
|
128
23
|
// cache containers
|
129
24
|
if(options.containment) {
|
130
|
-
options._containers =
|
25
|
+
options._containers = [];
|
131
26
|
var containment = options.containment;
|
132
27
|
if((typeof containment == 'object') &&
|
133
28
|
(containment.constructor == Array)) {
|
134
|
-
|
135
|
-
options._containers.push($(containment[i]));
|
29
|
+
containment.each( function(c) { options._containers.push($(c)) });
|
136
30
|
} else {
|
137
31
|
options._containers.push($(containment));
|
138
32
|
}
|
139
|
-
options._containers_length =
|
140
|
-
options._containers.length-1;
|
141
33
|
}
|
142
|
-
|
34
|
+
|
143
35
|
Element.makePositioned(element); // fix IE
|
144
|
-
|
145
36
|
options.element = element;
|
146
|
-
|
147
|
-
// activate the droppable
|
148
|
-
if(!this.drops) this.drops = [];
|
37
|
+
|
149
38
|
this.drops.push(options);
|
150
39
|
},
|
151
|
-
|
152
|
-
|
153
|
-
var containers = drop._containers;
|
40
|
+
|
41
|
+
isContained: function(element, drop) {
|
154
42
|
var parentNode = element.parentNode;
|
155
|
-
|
156
|
-
do { if(parentNode==containers[i]) return true; } while (i--);
|
157
|
-
return false;
|
43
|
+
return drop._containers.detect(function(c) { return parentNode == c });
|
158
44
|
},
|
159
|
-
|
160
|
-
|
45
|
+
|
46
|
+
isAffected: function(pX, pY, element, drop) {
|
161
47
|
return (
|
162
48
|
(drop.element!=element) &&
|
163
49
|
((!drop._containers) ||
|
164
|
-
this.
|
50
|
+
this.isContained(element, drop)) &&
|
165
51
|
((!drop.accept) ||
|
166
52
|
(Element.Class.has_any(element, drop.accept))) &&
|
167
53
|
Position.within(drop.element, pX, pY) );
|
168
54
|
},
|
169
|
-
|
55
|
+
|
170
56
|
deactivate: function(drop) {
|
171
|
-
|
57
|
+
if(drop.hoverclass)
|
58
|
+
Element.Class.remove(drop.element, drop.hoverclass);
|
172
59
|
this.last_active = null;
|
173
60
|
},
|
174
|
-
|
61
|
+
|
175
62
|
activate: function(drop) {
|
176
63
|
if(this.last_active) this.deactivate(this.last_active);
|
177
|
-
if(drop.hoverclass)
|
64
|
+
if(drop.hoverclass)
|
178
65
|
Element.Class.add(drop.element, drop.hoverclass);
|
179
|
-
|
180
|
-
}
|
66
|
+
this.last_active = drop;
|
181
67
|
},
|
182
|
-
|
68
|
+
|
183
69
|
show: function(event, element) {
|
184
|
-
if(!this.drops) return;
|
70
|
+
if(!this.drops.length) return;
|
185
71
|
var pX = Event.pointerX(event);
|
186
72
|
var pY = Event.pointerY(event);
|
187
73
|
Position.prepare();
|
188
|
-
|
74
|
+
|
189
75
|
var i = this.drops.length-1; do {
|
190
76
|
var drop = this.drops[i];
|
191
|
-
if(this.
|
77
|
+
if(this.isAffected(pX, pY, element, drop)) {
|
192
78
|
if(drop.onHover)
|
193
79
|
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
|
194
80
|
if(drop.greedy) {
|
@@ -197,43 +83,41 @@ var Droppables = {
|
|
197
83
|
}
|
198
84
|
}
|
199
85
|
} while (i--);
|
86
|
+
|
87
|
+
if(this.last_active) this.deactivate(this.last_active);
|
200
88
|
},
|
201
|
-
|
89
|
+
|
202
90
|
fire: function(event, element) {
|
203
91
|
if(!this.last_active) return;
|
204
92
|
Position.prepare();
|
205
|
-
|
206
|
-
if (this.
|
93
|
+
|
94
|
+
if (this.isAffected(Event.pointerX(event), Event.pointerY(event), element, this.last_active))
|
207
95
|
if (this.last_active.onDrop)
|
208
|
-
this.last_active.onDrop(element, this.last_active);
|
209
|
-
|
96
|
+
this.last_active.onDrop(element, this.last_active.element, event);
|
210
97
|
},
|
211
|
-
|
98
|
+
|
212
99
|
reset: function() {
|
213
100
|
if(this.last_active)
|
214
101
|
this.deactivate(this.last_active);
|
215
102
|
}
|
216
103
|
}
|
217
104
|
|
218
|
-
Draggables = {
|
219
|
-
observers:
|
105
|
+
var Draggables = {
|
106
|
+
observers: [],
|
220
107
|
addObserver: function(observer) {
|
221
108
|
this.observers.push(observer);
|
222
109
|
},
|
223
110
|
removeObserver: function(element) { // element instead of obsever fixes mem leaks
|
224
|
-
|
225
|
-
if(this.observers[i].element && (this.observers[i].element == element))
|
226
|
-
this.observers.splice(i,1);
|
111
|
+
this.observers = this.observers.reject( function(o) { return o.element==element });
|
227
112
|
},
|
228
113
|
notify: function(eventName, draggable) { // 'onStart', 'onEnd'
|
229
|
-
|
230
|
-
this.observers[i][eventName](draggable);
|
114
|
+
this.observers.invoke(eventName, draggable);
|
231
115
|
}
|
232
116
|
}
|
233
117
|
|
234
118
|
/*--------------------------------------------------------------------------*/
|
235
119
|
|
236
|
-
Draggable = Class.create();
|
120
|
+
var Draggable = Class.create();
|
237
121
|
Draggable.prototype = {
|
238
122
|
initialize: function(element) {
|
239
123
|
var options = Object.extend({
|
@@ -242,7 +126,8 @@ Draggable.prototype = {
|
|
242
126
|
new Effect.Opacity(element, {duration:0.2, from:1.0, to:0.7});
|
243
127
|
},
|
244
128
|
reverteffect: function(element, top_offset, left_offset) {
|
245
|
-
|
129
|
+
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
|
130
|
+
new Effect.MoveBy(element, -top_offset, -left_offset, {duration:dur});
|
246
131
|
},
|
247
132
|
endeffect: function(element) {
|
248
133
|
new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0});
|
@@ -250,40 +135,50 @@ Draggable.prototype = {
|
|
250
135
|
zindex: 1000,
|
251
136
|
revert: false
|
252
137
|
}, arguments[1] || {});
|
253
|
-
|
138
|
+
|
254
139
|
this.element = $(element);
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
140
|
+
if(options.handle && (typeof options.handle == 'string'))
|
141
|
+
this.handle = Element.Class.childrenWith(this.element, options.handle)[0];
|
142
|
+
|
143
|
+
if(!this.handle) this.handle = $(options.handle);
|
144
|
+
if(!this.handle) this.handle = this.element;
|
145
|
+
|
146
|
+
Element.makePositioned(this.element); // fix IE
|
147
|
+
|
259
148
|
this.offsetX = 0;
|
260
149
|
this.offsetY = 0;
|
261
150
|
this.originalLeft = this.currentLeft();
|
262
151
|
this.originalTop = this.currentTop();
|
263
152
|
this.originalX = this.element.offsetLeft;
|
264
153
|
this.originalY = this.element.offsetTop;
|
265
|
-
|
266
|
-
|
154
|
+
|
267
155
|
this.options = options;
|
268
|
-
|
156
|
+
|
269
157
|
this.active = false;
|
270
158
|
this.dragging = false;
|
271
|
-
|
159
|
+
|
272
160
|
this.eventMouseDown = this.startDrag.bindAsEventListener(this);
|
273
161
|
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
|
274
162
|
this.eventMouseMove = this.update.bindAsEventListener(this);
|
275
163
|
this.eventKeypress = this.keyPress.bindAsEventListener(this);
|
276
164
|
|
277
|
-
|
165
|
+
this.registerEvents();
|
166
|
+
},
|
167
|
+
destroy: function() {
|
168
|
+
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
|
169
|
+
this.unregisterEvents();
|
170
|
+
},
|
171
|
+
registerEvents: function() {
|
278
172
|
Event.observe(document, "mouseup", this.eventMouseUp);
|
279
173
|
Event.observe(document, "mousemove", this.eventMouseMove);
|
280
174
|
Event.observe(document, "keypress", this.eventKeypress);
|
175
|
+
Event.observe(this.handle, "mousedown", this.eventMouseDown);
|
281
176
|
},
|
282
|
-
|
283
|
-
|
284
|
-
Event.stopObserving(document, "mouseup", this.eventMouseUp);
|
285
|
-
Event.stopObserving(document, "mousemove", this.eventMouseMove);
|
286
|
-
Event.stopObserving(document, "keypress", this.eventKeypress);
|
177
|
+
unregisterEvents: function() {
|
178
|
+
//if(!this.active) return;
|
179
|
+
//Event.stopObserving(document, "mouseup", this.eventMouseUp);
|
180
|
+
//Event.stopObserving(document, "mousemove", this.eventMouseMove);
|
181
|
+
//Event.stopObserving(document, "keypress", this.eventKeypress);
|
287
182
|
},
|
288
183
|
currentLeft: function() {
|
289
184
|
return parseInt(this.element.style.left || '0');
|
@@ -293,27 +188,42 @@ Draggable.prototype = {
|
|
293
188
|
},
|
294
189
|
startDrag: function(event) {
|
295
190
|
if(Event.isLeftClick(event)) {
|
296
|
-
this.active = true;
|
297
191
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
192
|
+
// abort on form elements, fixes a Firefox issue
|
193
|
+
var src = Event.element(event);
|
194
|
+
if(src.tagName && (
|
195
|
+
src.tagName=='INPUT' ||
|
196
|
+
src.tagName=='SELECT' ||
|
197
|
+
src.tagName=='BUTTON' ||
|
198
|
+
src.tagName=='TEXTAREA')) return;
|
303
199
|
|
200
|
+
// this.registerEvents();
|
201
|
+
this.active = true;
|
202
|
+
var pointer = [Event.pointerX(event), Event.pointerY(event)];
|
203
|
+
var offsets = Position.cumulativeOffset(this.element);
|
204
|
+
this.offsetX = (pointer[0] - offsets[0]);
|
205
|
+
this.offsetY = (pointer[1] - offsets[1]);
|
304
206
|
Event.stop(event);
|
305
207
|
}
|
306
208
|
},
|
307
209
|
finishDrag: function(event, success) {
|
210
|
+
// this.unregisterEvents();
|
211
|
+
|
308
212
|
this.active = false;
|
309
213
|
this.dragging = false;
|
310
|
-
|
214
|
+
|
215
|
+
if(this.options.ghosting) {
|
216
|
+
Position.relativize(this.element);
|
217
|
+
Element.remove(this._clone);
|
218
|
+
this._clone = null;
|
219
|
+
}
|
220
|
+
|
311
221
|
if(success) Droppables.fire(event, this.element);
|
312
222
|
Draggables.notify('onEnd', this);
|
313
|
-
|
223
|
+
|
314
224
|
var revert = this.options.revert;
|
315
225
|
if(revert && typeof revert == 'function') revert = revert(this.element);
|
316
|
-
|
226
|
+
|
317
227
|
if(revert && this.options.reverteffect) {
|
318
228
|
this.options.reverteffect(this.element,
|
319
229
|
this.currentTop()-this.originalTop,
|
@@ -322,12 +232,14 @@ Draggable.prototype = {
|
|
322
232
|
this.originalLeft = this.currentLeft();
|
323
233
|
this.originalTop = this.currentTop();
|
324
234
|
}
|
325
|
-
|
326
|
-
this.
|
327
|
-
|
235
|
+
|
236
|
+
if(this.options.zindex)
|
237
|
+
this.element.style.zIndex = this.originalZ;
|
238
|
+
|
328
239
|
if(this.options.endeffect)
|
329
240
|
this.options.endeffect(this.element);
|
330
|
-
|
241
|
+
|
242
|
+
|
331
243
|
Droppables.reset();
|
332
244
|
},
|
333
245
|
keyPress: function(event) {
|
@@ -347,13 +259,15 @@ Draggable.prototype = {
|
|
347
259
|
this.dragging = false;
|
348
260
|
},
|
349
261
|
draw: function(event) {
|
262
|
+
var pointer = [Event.pointerX(event), Event.pointerY(event)];
|
263
|
+
var offsets = Position.cumulativeOffset(this.element);
|
264
|
+
offsets[0] -= this.currentLeft();
|
265
|
+
offsets[1] -= this.currentTop();
|
350
266
|
var style = this.element.style;
|
351
|
-
this.originalX = this.element.offsetLeft - this.currentLeft() - this.originalLeft;
|
352
|
-
this.originalY = this.element.offsetTop - this.currentTop() - this.originalTop;
|
353
267
|
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
|
354
|
-
style.left = (
|
268
|
+
style.left = (pointer[0] - offsets[0] - this.offsetX) + "px";
|
355
269
|
if((!this.options.constraint) || (this.options.constraint=='vertical'))
|
356
|
-
style.top = (
|
270
|
+
style.top = (pointer[1] - offsets[1] - this.offsetY) + "px";
|
357
271
|
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
|
358
272
|
},
|
359
273
|
update: function(event) {
|
@@ -361,19 +275,32 @@ Draggable.prototype = {
|
|
361
275
|
if(!this.dragging) {
|
362
276
|
var style = this.element.style;
|
363
277
|
this.dragging = true;
|
364
|
-
|
365
|
-
|
278
|
+
|
279
|
+
if(Element.getStyle(this.element,'position')=='')
|
280
|
+
style.position = "relative";
|
281
|
+
|
282
|
+
if(this.options.zindex) {
|
283
|
+
this.options.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
|
284
|
+
style.zIndex = this.options.zindex;
|
285
|
+
}
|
286
|
+
|
287
|
+
if(this.options.ghosting) {
|
288
|
+
this._clone = this.element.cloneNode(true);
|
289
|
+
Position.absolutize(this.element);
|
290
|
+
this.element.parentNode.insertBefore(this._clone, this.element);
|
291
|
+
}
|
292
|
+
|
366
293
|
Draggables.notify('onStart', this);
|
367
294
|
if(this.options.starteffect) this.options.starteffect(this.element);
|
368
295
|
}
|
369
|
-
|
296
|
+
|
370
297
|
Droppables.show(event, this.element);
|
371
298
|
this.draw(event);
|
372
299
|
if(this.options.change) this.options.change(this);
|
373
|
-
|
300
|
+
|
374
301
|
// fix AppleWebKit rendering
|
375
302
|
if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
|
376
|
-
|
303
|
+
|
377
304
|
Event.stop(event);
|
378
305
|
}
|
379
306
|
}
|
@@ -381,7 +308,7 @@ Draggable.prototype = {
|
|
381
308
|
|
382
309
|
/*--------------------------------------------------------------------------*/
|
383
310
|
|
384
|
-
SortableObserver = Class.create();
|
311
|
+
var SortableObserver = Class.create();
|
385
312
|
SortableObserver.prototype = {
|
386
313
|
initialize: function(element, observer) {
|
387
314
|
this.element = $(element);
|
@@ -391,147 +318,199 @@ SortableObserver.prototype = {
|
|
391
318
|
onStart: function() {
|
392
319
|
this.lastValue = Sortable.serialize(this.element);
|
393
320
|
},
|
394
|
-
onEnd: function() {
|
321
|
+
onEnd: function() {
|
322
|
+
Sortable.unmark();
|
395
323
|
if(this.lastValue != Sortable.serialize(this.element))
|
396
324
|
this.observer(this.element)
|
397
325
|
}
|
398
326
|
}
|
399
327
|
|
400
|
-
Sortable = {
|
328
|
+
var Sortable = {
|
401
329
|
sortables: new Array(),
|
402
330
|
options: function(element){
|
403
|
-
|
404
|
-
|
405
|
-
if(this.sortables[i].element == element)
|
406
|
-
return this.sortables[i];
|
407
|
-
return null;
|
331
|
+
element = $(element);
|
332
|
+
return this.sortables.detect(function(s) { return s.element == element });
|
408
333
|
},
|
409
334
|
destroy: function(element){
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
for(var j=0;j<s.draggables.length;j++)
|
418
|
-
s.draggables[j].destroy();
|
419
|
-
this.sortables.splice(i,1);
|
420
|
-
}
|
421
|
-
}
|
335
|
+
element = $(element);
|
336
|
+
this.sortables.findAll(function(s) { return s.element == element }).each(function(s){
|
337
|
+
Draggables.removeObserver(s.element);
|
338
|
+
s.droppables.each(function(d){ Droppables.remove(d) });
|
339
|
+
s.draggables.invoke('destroy');
|
340
|
+
});
|
341
|
+
this.sortables = this.sortables.reject(function(s) { return s.element == element });
|
422
342
|
},
|
423
343
|
create: function(element) {
|
424
|
-
|
344
|
+
element = $(element);
|
425
345
|
var options = Object.extend({
|
426
346
|
element: element,
|
427
347
|
tag: 'li', // assumes li children, override with tag: 'tagname'
|
348
|
+
dropOnEmpty: false,
|
349
|
+
tree: false, // fixme: unimplemented
|
428
350
|
overlap: 'vertical', // one of 'vertical', 'horizontal'
|
429
351
|
constraint: 'vertical', // one of 'vertical', 'horizontal', false
|
430
352
|
containment: element, // also takes array of elements (or id's); or false
|
431
353
|
handle: false, // or a CSS class
|
432
354
|
only: false,
|
433
355
|
hoverclass: null,
|
356
|
+
ghosting: false,
|
357
|
+
format: null,
|
434
358
|
onChange: function() {},
|
435
359
|
onUpdate: function() {}
|
436
360
|
}, arguments[1] || {});
|
437
|
-
|
361
|
+
|
438
362
|
// clear any old sortable with same element
|
439
363
|
this.destroy(element);
|
440
|
-
|
364
|
+
|
441
365
|
// build options for the draggables
|
442
366
|
var options_for_draggable = {
|
443
367
|
revert: true,
|
368
|
+
ghosting: options.ghosting,
|
444
369
|
constraint: options.constraint,
|
445
|
-
handle: handle };
|
370
|
+
handle: options.handle };
|
371
|
+
|
446
372
|
if(options.starteffect)
|
447
373
|
options_for_draggable.starteffect = options.starteffect;
|
374
|
+
|
448
375
|
if(options.reverteffect)
|
449
376
|
options_for_draggable.reverteffect = options.reverteffect;
|
377
|
+
else
|
378
|
+
if(options.ghosting) options_for_draggable.reverteffect = function(element) {
|
379
|
+
element.style.top = 0;
|
380
|
+
element.style.left = 0;
|
381
|
+
};
|
382
|
+
|
450
383
|
if(options.endeffect)
|
451
384
|
options_for_draggable.endeffect = options.endeffect;
|
385
|
+
|
452
386
|
if(options.zindex)
|
453
387
|
options_for_draggable.zindex = options.zindex;
|
454
|
-
|
388
|
+
|
455
389
|
// build options for the droppables
|
456
390
|
var options_for_droppable = {
|
457
391
|
overlap: options.overlap,
|
458
392
|
containment: options.containment,
|
459
393
|
hoverclass: options.hoverclass,
|
460
|
-
onHover:
|
461
|
-
|
462
|
-
if(dropon.previousSibling != element) {
|
463
|
-
var oldParentNode = element.parentNode;
|
464
|
-
element.style.visibility = "hidden"; // fix gecko rendering
|
465
|
-
dropon.parentNode.insertBefore(element, dropon);
|
466
|
-
if(dropon.parentNode!=oldParentNode && oldParentNode.sortable)
|
467
|
-
oldParentNode.sortable.onChange(element);
|
468
|
-
if(dropon.parentNode.sortable)
|
469
|
-
dropon.parentNode.sortable.onChange(element);
|
470
|
-
}
|
471
|
-
} else {
|
472
|
-
var nextElement = dropon.nextSibling || null;
|
473
|
-
if(nextElement != element) {
|
474
|
-
var oldParentNode = element.parentNode;
|
475
|
-
element.style.visibility = "hidden"; // fix gecko rendering
|
476
|
-
dropon.parentNode.insertBefore(element, nextElement);
|
477
|
-
if(dropon.parentNode!=oldParentNode && oldParentNode.sortable)
|
478
|
-
oldParentNode.sortable.onChange(element);
|
479
|
-
if(dropon.parentNode.sortable)
|
480
|
-
dropon.parentNode.sortable.onChange(element);
|
481
|
-
}
|
482
|
-
}
|
483
|
-
}
|
394
|
+
onHover: Sortable.onHover,
|
395
|
+
greedy: !options.dropOnEmpty
|
484
396
|
}
|
485
397
|
|
486
398
|
// fix for gecko engine
|
487
399
|
Element.cleanWhitespace(element);
|
488
|
-
|
400
|
+
|
489
401
|
options.draggables = [];
|
490
402
|
options.droppables = [];
|
491
|
-
|
492
|
-
// make it so
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
403
|
+
|
404
|
+
// make it so
|
405
|
+
|
406
|
+
// drop on empty handling
|
407
|
+
if(options.dropOnEmpty) {
|
408
|
+
Droppables.add(element,
|
409
|
+
{containment: options.containment, onHover: Sortable.onEmptyHover, greedy: false});
|
410
|
+
options.droppables.push(element);
|
411
|
+
}
|
412
|
+
|
413
|
+
(this.findElements(element, options) || []).each( function(e) {
|
414
|
+
// handles are per-draggable
|
415
|
+
var handle = options.handle ?
|
416
|
+
Element.Class.childrenWith(e, options.handle)[0] : e;
|
417
|
+
options.draggables.push(
|
418
|
+
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
|
419
|
+
Droppables.add(e, options_for_droppable);
|
420
|
+
options.droppables.push(e);
|
421
|
+
});
|
422
|
+
|
509
423
|
// keep reference
|
510
424
|
this.sortables.push(options);
|
511
|
-
|
425
|
+
|
512
426
|
// for onupdate
|
513
427
|
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
|
514
428
|
|
515
429
|
},
|
430
|
+
|
431
|
+
// return all suitable-for-sortable elements in a guaranteed order
|
432
|
+
findElements: function(element, options) {
|
433
|
+
if(!element.hasChildNodes()) return null;
|
434
|
+
var elements = [];
|
435
|
+
$A(element.childNodes).each( function(e) {
|
436
|
+
if(e.tagName && e.tagName==options.tag.toUpperCase() &&
|
437
|
+
(!options.only || (Element.Class.has(e, options.only))))
|
438
|
+
elements.push(e);
|
439
|
+
if(options.tree) {
|
440
|
+
var grandchildren = this.findElements(e, options);
|
441
|
+
if(grandchildren) elements.push(grandchildren);
|
442
|
+
}
|
443
|
+
});
|
444
|
+
|
445
|
+
return (elements.length>0 ? elements.flatten() : null);
|
446
|
+
},
|
447
|
+
|
448
|
+
onHover: function(element, dropon, overlap) {
|
449
|
+
if(overlap>0.5) {
|
450
|
+
Sortable.mark(dropon, 'before');
|
451
|
+
if(dropon.previousSibling != element) {
|
452
|
+
var oldParentNode = element.parentNode;
|
453
|
+
element.style.visibility = "hidden"; // fix gecko rendering
|
454
|
+
dropon.parentNode.insertBefore(element, dropon);
|
455
|
+
if(dropon.parentNode!=oldParentNode)
|
456
|
+
Sortable.options(oldParentNode).onChange(element);
|
457
|
+
Sortable.options(dropon.parentNode).onChange(element);
|
458
|
+
}
|
459
|
+
} else {
|
460
|
+
Sortable.mark(dropon, 'after');
|
461
|
+
var nextElement = dropon.nextSibling || null;
|
462
|
+
if(nextElement != element) {
|
463
|
+
var oldParentNode = element.parentNode;
|
464
|
+
element.style.visibility = "hidden"; // fix gecko rendering
|
465
|
+
dropon.parentNode.insertBefore(element, nextElement);
|
466
|
+
if(dropon.parentNode!=oldParentNode)
|
467
|
+
Sortable.options(oldParentNode).onChange(element);
|
468
|
+
Sortable.options(dropon.parentNode).onChange(element);
|
469
|
+
}
|
470
|
+
}
|
471
|
+
},
|
472
|
+
|
473
|
+
onEmptyHover: function(element, dropon) {
|
474
|
+
if(element.parentNode!=dropon) {
|
475
|
+
dropon.appendChild(element);
|
476
|
+
}
|
477
|
+
},
|
478
|
+
|
479
|
+
unmark: function() {
|
480
|
+
if(Sortable._marker) Element.hide(Sortable._marker);
|
481
|
+
},
|
482
|
+
|
483
|
+
mark: function(dropon, position) {
|
484
|
+
// mark on ghosting only
|
485
|
+
var sortable = Sortable.options(dropon.parentNode);
|
486
|
+
if(sortable && !sortable.ghosting) return;
|
487
|
+
|
488
|
+
if(!Sortable._marker) {
|
489
|
+
Sortable._marker = $('dropmarker') || document.createElement('DIV');
|
490
|
+
Element.hide(Sortable._marker);
|
491
|
+
Element.Class.add(Sortable._marker, 'dropmarker');
|
492
|
+
Sortable._marker.style.position = 'absolute';
|
493
|
+
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
|
494
|
+
}
|
495
|
+
var offsets = Position.cumulativeOffset(dropon);
|
496
|
+
Sortable._marker.style.top = offsets[1] + 'px';
|
497
|
+
if(position=='after') Sortable._marker.style.top = (offsets[1]+dropon.clientHeight) + 'px';
|
498
|
+
Sortable._marker.style.left = offsets[0] + 'px';
|
499
|
+
Element.show(Sortable._marker);
|
500
|
+
},
|
501
|
+
|
516
502
|
serialize: function(element) {
|
517
|
-
|
503
|
+
element = $(element);
|
518
504
|
var sortableOptions = this.options(element);
|
519
505
|
var options = Object.extend({
|
520
506
|
tag: sortableOptions.tag,
|
521
507
|
only: sortableOptions.only,
|
522
|
-
name: element.id
|
508
|
+
name: element.id,
|
509
|
+
format: sortableOptions.format || /^[^_]*_(.*)$/
|
523
510
|
}, arguments[1] || {});
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
for(var i=0; i<items.length; i++)
|
529
|
-
if(items[i].tagName && items[i].tagName==options.tag.toUpperCase() &&
|
530
|
-
(!options.only || (Element.Class.has(items[i], options.only))))
|
531
|
-
queryComponents.push(
|
532
|
-
encodeURIComponent(options.name) + "[]=" +
|
533
|
-
encodeURIComponent(items[i].id.split("_")[1]));
|
534
|
-
|
535
|
-
return queryComponents.join("&");
|
511
|
+
return $(this.findElements(element, options) || []).collect( function(item) {
|
512
|
+
return (encodeURIComponent(options.name) + "[]=" +
|
513
|
+
encodeURIComponent(item.id.match(options.format) ? item.id.match(options.format)[1] : ''));
|
514
|
+
}).join("&");
|
536
515
|
}
|
537
|
-
}
|
516
|
+
}
|