summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/MochiKit/Sortable.js
Unidiff
Diffstat (limited to 'frontend/gamma/js/MochiKit/Sortable.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/gamma/js/MochiKit/Sortable.js12
1 files changed, 6 insertions, 6 deletions
diff --git a/frontend/gamma/js/MochiKit/Sortable.js b/frontend/gamma/js/MochiKit/Sortable.js
index 863b506..ca9db21 100644
--- a/frontend/gamma/js/MochiKit/Sortable.js
+++ b/frontend/gamma/js/MochiKit/Sortable.js
@@ -1,286 +1,286 @@
1/*** 1/***
2Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 2Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
3 Mochi-ized By Thomas Herve (_firstname_@nimail.org) 3 Mochi-ized By Thomas Herve (_firstname_@nimail.org)
4 4
5See scriptaculous.js for full license. 5See scriptaculous.js for full license.
6 6
7***/ 7***/
8 8
9MochiKit.Base._module('Sortable', '1.5', ['Base', 'Iter', 'DOM', 'Position', 'DragAndDrop']); 9MochiKit.Base.module(MochiKit, 'Sortable', '1.5', ['Base', 'Iter', 'DOM', 'Position', 'DragAndDrop']);
10 10
11MochiKit.Base.update(MochiKit.Sortable, { 11MochiKit.Base.update(MochiKit.Sortable, {
12 __export__: false, 12 __export__: false,
13 13
14 /*** 14 /***
15 15
16 Manage sortables. Mainly use the create function to add a sortable. 16 Manage sortables. Mainly use the create function to add a sortable.
17 17
18 ***/ 18 ***/
19 sortables: {}, 19 sortables: {},
20 20
21 _findRootElement: function (element) { 21 _findRootElement: function (element) {
22 while (element.tagName.toUpperCase() != "BODY") { 22 while (element.tagName.toUpperCase() != "BODY") {
23 if (element.id && MochiKit.Sortable.sortables[element.id]) { 23 if (element.id && MochiKit.Sortable.sortables[element.id]) {
24 return element; 24 return element;
25 } 25 }
26 element = element.parentNode; 26 element = element.parentNode;
27 } 27 }
28 }, 28 },
29 29
30 _createElementId: function(element) { 30 _createElementId: function(element) {
31 if (element.id == null || element.id == "") { 31 if (element.id == null || element.id == "") {
32 var d = MochiKit.DOM; 32 var d = MochiKit.DOM;
33 var id; 33 var id;
34 var count = 1; 34 var count = 1;
35 while (d.getElement(id = "sortable" + count) != null) { 35 while (d.getElement(id = "sortable" + count) != null) {
36 count += 1; 36 count += 1;
37 } 37 }
38 d.setNodeAttribute(element, "id", id); 38 d.setNodeAttribute(element, "id", id);
39 } 39 }
40 }, 40 },
41 41
42 /** @id MochiKit.Sortable.options */ 42 /** @id MochiKit.Sortable.options */
43 options: function (element) { 43 options: function (element) {
44 element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element)); 44 element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element));
45 if (!element) { 45 if (!element) {
46 return; 46 return;
47 } 47 }
48 return MochiKit.Sortable.sortables[element.id]; 48 return MochiKit.Sortable.sortables[element.id];
49 }, 49 },
50 50
51 /** @id MochiKit.Sortable.destroy */ 51 /** @id MochiKit.Sortable.destroy */
52 destroy: function (element){ 52 destroy: function (element){
53 var s = MochiKit.Sortable.options(element); 53 var s = MochiKit.Sortable.options(element);
54 var b = MochiKit.Base; 54 var b = MochiKit.Base;
55 var d = MochiKit.DragAndDrop; 55 var d = MochiKit.DragAndDrop;
56 56
57 if (s) { 57 if (s) {
58 MochiKit.Signal.disconnect(s.startHandle); 58 MochiKit.Signal.disconnect(s.startHandle);
59 MochiKit.Signal.disconnect(s.endHandle); 59 MochiKit.Signal.disconnect(s.endHandle);
60 b.map(function (dr) { 60 b.map(function (dr) {
61 d.Droppables.remove(dr); 61 d.Droppables.remove(dr);
62 }, s.droppables); 62 }, s.droppables);
63 b.map(function (dr) { 63 b.map(function (dr) {
64 dr.destroy(); 64 dr.destroy();
65 }, s.draggables); 65 }, s.draggables);
66 66
67 delete MochiKit.Sortable.sortables[s.element.id]; 67 delete MochiKit.Sortable.sortables[s.element.id];
68 } 68 }
69 }, 69 },
70 70
71 /** @id MochiKit.Sortable.create */ 71 /** @id MochiKit.Sortable.create */
72 create: function (element, options) { 72 create: function (element, options) {
73 element = MochiKit.DOM.getElement(element); 73 element = MochiKit.DOM.getElement(element);
74 var self = MochiKit.Sortable; 74 var self = MochiKit.Sortable;
75 self._createElementId(element); 75 self._createElementId(element);
76 76
77 /** @id MochiKit.Sortable.options */ 77 /** @id MochiKit.Sortable.options */
78 options = MochiKit.Base.update({ 78 options = MochiKit.Base.update({
79 79
80 /** @id MochiKit.Sortable.element */ 80 /** @id MochiKit.Sortable.element */
81 element: element, 81 element: element,
82 82
83 /** @id MochiKit.Sortable.tag */ 83 /** @id MochiKit.Sortable.tag */
84 tag: 'li', // assumes li children, override with tag: 'tagname' 84 tag: 'li', // assumes li children, override with tag: 'tagname'
85 85
86 /** @id MochiKit.Sortable.dropOnEmpty */ 86 /** @id MochiKit.Sortable.dropOnEmpty */
87 dropOnEmpty: false, 87 dropOnEmpty: false,
88 88
89 /** @id MochiKit.Sortable.tree */ 89 /** @id MochiKit.Sortable.tree */
90 tree: false, 90 tree: false,
91 91
92 /** @id MochiKit.Sortable.treeTag */ 92 /** @id MochiKit.Sortable.treeTag */
93 treeTag: 'ul', 93 treeTag: 'ul',
94 94
95 /** @id MochiKit.Sortable.overlap */ 95 /** @id MochiKit.Sortable.overlap */
96 overlap: 'vertical', // one of 'vertical', 'horizontal' 96 overlap: 'vertical', // one of 'vertical', 'horizontal'
97 97
98 /** @id MochiKit.Sortable.constraint */ 98 /** @id MochiKit.Sortable.constraint */
99 constraint: 'vertical', // one of 'vertical', 'horizontal', false 99 constraint: 'vertical', // one of 'vertical', 'horizontal', false
100 // also takes array of elements (or ids); or false 100 // also takes array of elements (or ids); or false
101 101
102 /** @id MochiKit.Sortable.containment */ 102 /** @id MochiKit.Sortable.containment */
103 containment: [element], 103 containment: [element],
104 104
105 /** @id MochiKit.Sortable.handle */ 105 /** @id MochiKit.Sortable.handle */
106 handle: false, // or a CSS class 106 handle: false, // or a CSS class
107 107
108 /** @id MochiKit.Sortable.only */ 108 /** @id MochiKit.Sortable.only */
109 only: false, 109 only: false,
110 110
111 /** @id MochiKit.Sortable.hoverclass */ 111 /** @id MochiKit.Sortable.hoverclass */
112 hoverclass: null, 112 hoverclass: null,
113 113
114 /** @id MochiKit.Sortable.ghosting */ 114 /** @id MochiKit.Sortable.ghosting */
115 ghosting: false, 115 ghosting: false,
116 116
117 /** @id MochiKit.Sortable.scroll */ 117 /** @id MochiKit.Sortable.scroll */
118 scroll: false, 118 scroll: false,
119 119
120 /** @id MochiKit.Sortable.scrollSensitivity */ 120 /** @id MochiKit.Sortable.scrollSensitivity */
121 scrollSensitivity: 20, 121 scrollSensitivity: 20,
122 122
123 /** @id MochiKit.Sortable.scrollSpeed */ 123 /** @id MochiKit.Sortable.scrollSpeed */
124 scrollSpeed: 15, 124 scrollSpeed: 15,
125 125
126 /** @id MochiKit.Sortable.format */ 126 /** @id MochiKit.Sortable.format */
127 format: /^[^_]*_(.*)$/, 127 format: /^[^_]*_(.*)$/,
128 128
129 /** @id MochiKit.Sortable.onChange */ 129 /** @id MochiKit.Sortable.onChange */
130 onChange: MochiKit.Base.noop, 130 onChange: MochiKit.Base.noop,
131 131
132 /** @id MochiKit.Sortable.onUpdate */ 132 /** @id MochiKit.Sortable.onUpdate */
133 onUpdate: MochiKit.Base.noop, 133 onUpdate: MochiKit.Base.noop,
134 134
135 /** @id MochiKit.Sortable.accept */ 135 /** @id MochiKit.Sortable.accept */
136 accept: null 136 accept: null
137 }, options); 137 }, options);
138 138
139 // clear any old sortable with same element 139 // clear any old sortable with same element
140 self.destroy(element); 140 self.destroy(element);
141 141
142 // build options for the draggables 142 // build options for the draggables
143 var options_for_draggable = { 143 var options_for_draggable = {
144 revert: true, 144 revert: true,
145 ghosting: options.ghosting, 145 ghosting: options.ghosting,
146 scroll: options.scroll, 146 scroll: options.scroll,
147 scrollSensitivity: options.scrollSensitivity, 147 scrollSensitivity: options.scrollSensitivity,
148 scrollSpeed: options.scrollSpeed, 148 scrollSpeed: options.scrollSpeed,
149 constraint: options.constraint, 149 constraint: options.constraint,
150 handle: options.handle 150 handle: options.handle
151 }; 151 };
152 152
153 if (options.starteffect) { 153 if (options.starteffect) {
154 options_for_draggable.starteffect = options.starteffect; 154 options_for_draggable.starteffect = options.starteffect;
155 } 155 }
156 156
157 if (options.reverteffect) { 157 if (options.reverteffect) {
158 options_for_draggable.reverteffect = options.reverteffect; 158 options_for_draggable.reverteffect = options.reverteffect;
159 } else if (options.ghosting) { 159 } else if (options.ghosting) {
160 options_for_draggable.reverteffect = function (innerelement) { 160 options_for_draggable.reverteffect = function (innerelement) {
161 innerelement.style.top = 0; 161 innerelement.style.top = 0;
162 innerelement.style.left = 0; 162 innerelement.style.left = 0;
163 }; 163 };
164 } 164 }
165 165
166 if (options.endeffect) { 166 if (options.endeffect) {
167 options_for_draggable.endeffect = options.endeffect; 167 options_for_draggable.endeffect = options.endeffect;
168 } 168 }
169 169
170 if (options.zindex) { 170 if (options.zindex) {
171 options_for_draggable.zindex = options.zindex; 171 options_for_draggable.zindex = options.zindex;
172 } 172 }
173 173
174 // build options for the droppables 174 // build options for the droppables
175 var options_for_droppable = { 175 var options_for_droppable = {
176 overlap: options.overlap, 176 overlap: options.overlap,
177 containment: options.containment, 177 containment: options.containment,
178 hoverclass: options.hoverclass, 178 hoverclass: options.hoverclass,
179 onhover: self.onHover, 179 onhover: self.onHover,
180 tree: options.tree, 180 tree: options.tree,
181 accept: options.accept 181 accept: options.accept
182 } 182 };
183 183
184 var options_for_tree = { 184 var options_for_tree = {
185 onhover: self.onEmptyHover, 185 onhover: self.onEmptyHover,
186 overlap: options.overlap, 186 overlap: options.overlap,
187 containment: options.containment, 187 containment: options.containment,
188 hoverclass: options.hoverclass, 188 hoverclass: options.hoverclass,
189 accept: options.accept 189 accept: options.accept
190 } 190 };
191 191
192 // fix for gecko engine 192 // fix for gecko engine
193 MochiKit.DOM.removeEmptyTextNodes(element); 193 MochiKit.DOM.removeEmptyTextNodes(element);
194 194
195 options.draggables = []; 195 options.draggables = [];
196 options.droppables = []; 196 options.droppables = [];
197 197
198 // drop on empty handling 198 // drop on empty handling
199 if (options.dropOnEmpty || options.tree) { 199 if (options.dropOnEmpty || options.tree) {
200 new MochiKit.DragAndDrop.Droppable(element, options_for_tree); 200 new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
201 options.droppables.push(element); 201 options.droppables.push(element);
202 } 202 }
203 MochiKit.Base.map(function (e) { 203 MochiKit.Base.map(function (e) {
204 // handles are per-draggable 204 // handles are per-draggable
205 var handle = options.handle ? 205 var handle = options.handle ?
206 MochiKit.DOM.getFirstElementByTagAndClassName(null, 206 MochiKit.DOM.getFirstElementByTagAndClassName(null,
207 options.handle, e) : e; 207 options.handle, e) : e;
208 options.draggables.push( 208 options.draggables.push(
209 new MochiKit.DragAndDrop.Draggable(e, 209 new MochiKit.DragAndDrop.Draggable(e,
210 MochiKit.Base.update(options_for_draggable, 210 MochiKit.Base.update(options_for_draggable,
211 {handle: handle}))); 211 {handle: handle})));
212 new MochiKit.DragAndDrop.Droppable(e, options_for_droppable); 212 new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
213 if (options.tree) { 213 if (options.tree) {
214 e.treeNode = element; 214 e.treeNode = element;
215 } 215 }
216 options.droppables.push(e); 216 options.droppables.push(e);
217 }, (self.findElements(element, options) || [])); 217 }, (self.findElements(element, options) || []));
218 218
219 if (options.tree) { 219 if (options.tree) {
220 MochiKit.Base.map(function (e) { 220 MochiKit.Base.map(function (e) {
221 new MochiKit.DragAndDrop.Droppable(e, options_for_tree); 221 new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
222 e.treeNode = element; 222 e.treeNode = element;
223 options.droppables.push(e); 223 options.droppables.push(e);
224 }, (self.findTreeElements(element, options) || [])); 224 }, (self.findTreeElements(element, options) || []));
225 } 225 }
226 226
227 // keep reference 227 // keep reference
228 self.sortables[element.id] = options; 228 self.sortables[element.id] = options;
229 229
230 options.lastValue = self.serialize(element); 230 options.lastValue = self.serialize(element);
231 options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start', 231 options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start',
232 MochiKit.Base.partial(self.onStart, element)); 232 MochiKit.Base.partial(self.onStart, element));
233 options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end', 233 options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
234 MochiKit.Base.partial(self.onEnd, element)); 234 MochiKit.Base.partial(self.onEnd, element));
235 }, 235 },
236 236
237 /** @id MochiKit.Sortable.onStart */ 237 /** @id MochiKit.Sortable.onStart */
238 onStart: function (element, draggable) { 238 onStart: function (element, draggable) {
239 var self = MochiKit.Sortable; 239 var self = MochiKit.Sortable;
240 var options = self.options(element); 240 var options = self.options(element);
241 options.lastValue = self.serialize(options.element); 241 options.lastValue = self.serialize(options.element);
242 }, 242 },
243 243
244 /** @id MochiKit.Sortable.onEnd */ 244 /** @id MochiKit.Sortable.onEnd */
245 onEnd: function (element, draggable) { 245 onEnd: function (element, draggable) {
246 var self = MochiKit.Sortable; 246 var self = MochiKit.Sortable;
247 self.unmark(); 247 self.unmark();
248 var options = self.options(element); 248 var options = self.options(element);
249 if (options.lastValue != self.serialize(options.element)) { 249 if (options.lastValue != self.serialize(options.element)) {
250 options.onUpdate(options.element); 250 options.onUpdate(options.element);
251 } 251 }
252 }, 252 },
253 253
254 // return all suitable-for-sortable elements in a guaranteed order 254 // return all suitable-for-sortable elements in a guaranteed order
255 255
256 /** @id MochiKit.Sortable.findElements */ 256 /** @id MochiKit.Sortable.findElements */
257 findElements: function (element, options) { 257 findElements: function (element, options) {
258 return MochiKit.Sortable.findChildren(element, options.only, options.tree, options.tag); 258 return MochiKit.Sortable.findChildren(element, options.only, options.tree, options.tag);
259 }, 259 },
260 260
261 /** @id MochiKit.Sortable.findTreeElements */ 261 /** @id MochiKit.Sortable.findTreeElements */
262 findTreeElements: function (element, options) { 262 findTreeElements: function (element, options) {
263 return MochiKit.Sortable.findChildren( 263 return MochiKit.Sortable.findChildren(
264 element, options.only, options.tree ? true : false, options.treeTag); 264 element, options.only, options.tree ? true : false, options.treeTag);
265 }, 265 },
266 266
267 /** @id MochiKit.Sortable.findChildren */ 267 /** @id MochiKit.Sortable.findChildren */
268 findChildren: function (element, only, recursive, tagName) { 268 findChildren: function (element, only, recursive, tagName) {
269 if (!element.hasChildNodes()) { 269 if (!element.hasChildNodes()) {
270 return null; 270 return null;
271 } 271 }
272 tagName = tagName.toUpperCase(); 272 tagName = tagName.toUpperCase();
273 if (only) { 273 if (only) {
274 only = MochiKit.Base.flattenArray([only]); 274 only = MochiKit.Base.flattenArray([only]);
275 } 275 }
276 var elements = []; 276 var elements = [];
277 MochiKit.Base.map(function (e) { 277 MochiKit.Base.map(function (e) {
278 if (e.tagName && 278 if (e.tagName &&
279 e.tagName.toUpperCase() == tagName && 279 e.tagName.toUpperCase() == tagName &&
280 (!only || 280 (!only ||
281 MochiKit.Iter.some(only, function (c) { 281 MochiKit.Iter.some(only, function (c) {
282 return MochiKit.DOM.hasElementClass(e, c); 282 return MochiKit.DOM.hasElementClass(e, c);
283 }))) { 283 }))) {
284 elements.push(e); 284 elements.push(e);
285 } 285 }
286 if (recursive) { 286 if (recursive) {
@@ -337,233 +337,233 @@ MochiKit.Base.update(MochiKit.Sortable, {
337 }, 337 },
338 338
339 /** @id MochiKit.Sortable.onEmptyHover */ 339 /** @id MochiKit.Sortable.onEmptyHover */
340 onEmptyHover: function (element, dropon, overlap) { 340 onEmptyHover: function (element, dropon, overlap) {
341 var oldParentNode = element.parentNode; 341 var oldParentNode = element.parentNode;
342 var self = MochiKit.Sortable; 342 var self = MochiKit.Sortable;
343 var droponOptions = self.options(dropon); 343 var droponOptions = self.options(dropon);
344 344
345 if (!MochiKit.DOM.isChildNode(dropon, element)) { 345 if (!MochiKit.DOM.isChildNode(dropon, element)) {
346 var index; 346 var index;
347 347
348 var children = self.findElements(dropon, {tag: droponOptions.tag, 348 var children = self.findElements(dropon, {tag: droponOptions.tag,
349 only: droponOptions.only}); 349 only: droponOptions.only});
350 var child = null; 350 var child = null;
351 351
352 if (children) { 352 if (children) {
353 var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); 353 var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
354 354
355 for (index = 0; index < children.length; index += 1) { 355 for (index = 0; index < children.length; index += 1) {
356 if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) { 356 if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
357 offset -= self._offsetSize(children[index], droponOptions.overlap); 357 offset -= self._offsetSize(children[index], droponOptions.overlap);
358 } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { 358 } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
359 child = index + 1 < children.length ? children[index + 1] : null; 359 child = index + 1 < children.length ? children[index + 1] : null;
360 break; 360 break;
361 } else { 361 } else {
362 child = children[index]; 362 child = children[index];
363 break; 363 break;
364 } 364 }
365 } 365 }
366 } 366 }
367 367
368 dropon.insertBefore(element, child); 368 dropon.insertBefore(element, child);
369 369
370 self.options(oldParentNode).onChange(element); 370 self.options(oldParentNode).onChange(element);
371 droponOptions.onChange(element); 371 droponOptions.onChange(element);
372 } 372 }
373 }, 373 },
374 374
375 /** @id MochiKit.Sortable.unmark */ 375 /** @id MochiKit.Sortable.unmark */
376 unmark: function () { 376 unmark: function () {
377 var m = MochiKit.Sortable._marker; 377 var m = MochiKit.Sortable._marker;
378 if (m) { 378 if (m) {
379 MochiKit.Style.hideElement(m); 379 MochiKit.Style.hideElement(m);
380 } 380 }
381 }, 381 },
382 382
383 /** @id MochiKit.Sortable.mark */ 383 /** @id MochiKit.Sortable.mark */
384 mark: function (dropon, position) { 384 mark: function (dropon, position) {
385 // mark on ghosting only 385 // mark on ghosting only
386 var d = MochiKit.DOM; 386 var d = MochiKit.DOM;
387 var self = MochiKit.Sortable; 387 var self = MochiKit.Sortable;
388 var sortable = self.options(dropon.parentNode); 388 var sortable = self.options(dropon.parentNode);
389 if (sortable && !sortable.ghosting) { 389 if (sortable && !sortable.ghosting) {
390 return; 390 return;
391 } 391 }
392 392
393 if (!self._marker) { 393 if (!self._marker) {
394 self._marker = d.getElement('dropmarker') || 394 self._marker = d.getElement('dropmarker') ||
395 document.createElement('DIV'); 395 document.createElement('DIV');
396 MochiKit.Style.hideElement(self._marker); 396 MochiKit.Style.hideElement(self._marker);
397 d.addElementClass(self._marker, 'dropmarker'); 397 d.addElementClass(self._marker, 'dropmarker');
398 self._marker.style.position = 'absolute'; 398 self._marker.style.position = 'absolute';
399 document.getElementsByTagName('body').item(0).appendChild(self._marker); 399 document.getElementsByTagName('body').item(0).appendChild(self._marker);
400 } 400 }
401 var offsets = MochiKit.Position.cumulativeOffset(dropon); 401 var offsets = MochiKit.Position.cumulativeOffset(dropon);
402 self._marker.style.left = offsets.x + 'px'; 402 self._marker.style.left = offsets.x + 'px';
403 self._marker.style.top = offsets.y + 'px'; 403 self._marker.style.top = offsets.y + 'px';
404 404
405 if (position == 'after') { 405 if (position == 'after') {
406 if (sortable.overlap == 'horizontal') { 406 if (sortable.overlap == 'horizontal') {
407 self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px'; 407 self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
408 } else { 408 } else {
409 self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px'; 409 self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
410 } 410 }
411 } 411 }
412 MochiKit.Style.showElement(self._marker); 412 MochiKit.Style.showElement(self._marker);
413 }, 413 },
414 414
415 _tree: function (element, options, parent) { 415 _tree: function (element, options, parent) {
416 var self = MochiKit.Sortable; 416 var self = MochiKit.Sortable;
417 var children = self.findElements(element, options) || []; 417 var children = self.findElements(element, options) || [];
418 418
419 for (var i = 0; i < children.length; ++i) { 419 for (var i = 0; i < children.length; ++i) {
420 var match = children[i].id.match(options.format); 420 var match = children[i].id.match(options.format);
421 421
422 if (!match) { 422 if (!match) {
423 continue; 423 continue;
424 } 424 }
425 425
426 var child = { 426 var child = {
427 id: encodeURIComponent(match ? match[1] : null), 427 id: encodeURIComponent(match ? match[1] : null),
428 element: element, 428 element: element,
429 parent: parent, 429 parent: parent,
430 children: [], 430 children: [],
431 position: parent.children.length, 431 position: parent.children.length,
432 container: self._findChildrenElement(children[i], options.treeTag.toUpperCase()) 432 container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
433 } 433 };
434 434
435 /* Get the element containing the children and recurse over it */ 435 /* Get the element containing the children and recurse over it */
436 if (child.container) { 436 if (child.container) {
437 self._tree(child.container, options, child) 437 self._tree(child.container, options, child);
438 } 438 }
439 439
440 parent.children.push (child); 440 parent.children.push (child);
441 } 441 }
442 442
443 return parent; 443 return parent;
444 }, 444 },
445 445
446 /* Finds the first element of the given tag type within a parent element. 446 /* Finds the first element of the given tag type within a parent element.
447 Used for finding the first LI[ST] within a L[IST]I[TEM].*/ 447 Used for finding the first LI[ST] within a L[IST]I[TEM].*/
448 _findChildrenElement: function (element, containerTag) { 448 _findChildrenElement: function (element, containerTag) {
449 if (element && element.hasChildNodes) { 449 if (element && element.hasChildNodes) {
450 containerTag = containerTag.toUpperCase(); 450 containerTag = containerTag.toUpperCase();
451 for (var i = 0; i < element.childNodes.length; ++i) { 451 for (var i = 0; i < element.childNodes.length; ++i) {
452 if (element.childNodes[i].tagName.toUpperCase() == containerTag) { 452 if (element.childNodes[i].tagName.toUpperCase() == containerTag) {
453 return element.childNodes[i]; 453 return element.childNodes[i];
454 } 454 }
455 } 455 }
456 } 456 }
457 return null; 457 return null;
458 }, 458 },
459 459
460 /** @id MochiKit.Sortable.tree */ 460 /** @id MochiKit.Sortable.tree */
461 tree: function (element, options) { 461 tree: function (element, options) {
462 element = MochiKit.DOM.getElement(element); 462 element = MochiKit.DOM.getElement(element);
463 var sortableOptions = MochiKit.Sortable.options(element); 463 var sortableOptions = MochiKit.Sortable.options(element);
464 options = MochiKit.Base.update({ 464 options = MochiKit.Base.update({
465 tag: sortableOptions.tag, 465 tag: sortableOptions.tag,
466 treeTag: sortableOptions.treeTag, 466 treeTag: sortableOptions.treeTag,
467 only: sortableOptions.only, 467 only: sortableOptions.only,
468 name: element.id, 468 name: element.id,
469 format: sortableOptions.format 469 format: sortableOptions.format
470 }, options || {}); 470 }, options || {});
471 471
472 var root = { 472 var root = {
473 id: null, 473 id: null,
474 parent: null, 474 parent: null,
475 children: new Array, 475 children: new Array,
476 container: element, 476 container: element,
477 position: 0 477 position: 0
478 } 478 };
479 479
480 return MochiKit.Sortable._tree(element, options, root); 480 return MochiKit.Sortable._tree(element, options, root);
481 }, 481 },
482 482
483 /** 483 /**
484 * Specifies the sequence for the Sortable. 484 * Specifies the sequence for the Sortable.
485 * @param {Node} element Element to use as the Sortable. 485 * @param {Node} element Element to use as the Sortable.
486 * @param {Object} newSequence New sequence to use. 486 * @param {Object} newSequence New sequence to use.
487 * @param {Object} options Options to use fro the Sortable. 487 * @param {Object} options Options to use fro the Sortable.
488 */ 488 */
489 setSequence: function (element, newSequence, options) { 489 setSequence: function (element, newSequence, options) {
490 var self = MochiKit.Sortable; 490 var self = MochiKit.Sortable;
491 var b = MochiKit.Base; 491 var b = MochiKit.Base;
492 element = MochiKit.DOM.getElement(element); 492 element = MochiKit.DOM.getElement(element);
493 options = b.update(self.options(element), options || {}); 493 options = b.update(self.options(element), options || {});
494 494
495 var nodeMap = {}; 495 var nodeMap = {};
496 b.map(function (n) { 496 b.map(function (n) {
497 var m = n.id.match(options.format); 497 var m = n.id.match(options.format);
498 if (m) { 498 if (m) {
499 nodeMap[m[1]] = [n, n.parentNode]; 499 nodeMap[m[1]] = [n, n.parentNode];
500 } 500 }
501 n.parentNode.removeChild(n); 501 n.parentNode.removeChild(n);
502 }, self.findElements(element, options)); 502 }, self.findElements(element, options));
503 503
504 b.map(function (ident) { 504 b.map(function (ident) {
505 var n = nodeMap[ident]; 505 var n = nodeMap[ident];
506 if (n) { 506 if (n) {
507 n[1].appendChild(n[0]); 507 n[1].appendChild(n[0]);
508 delete nodeMap[ident]; 508 delete nodeMap[ident];
509 } 509 }
510 }, newSequence); 510 }, newSequence);
511 }, 511 },
512 512
513 /* Construct a [i] index for a particular node */ 513 /* Construct a [i] index for a particular node */
514 _constructIndex: function (node) { 514 _constructIndex: function (node) {
515 var index = ''; 515 var index = '';
516 do { 516 do {
517 if (node.id) { 517 if (node.id) {
518 index = '[' + node.position + ']' + index; 518 index = '[' + node.position + ']' + index;
519 } 519 }
520 } while ((node = node.parent) != null); 520 } while ((node = node.parent) != null);
521 return index; 521 return index;
522 }, 522 },
523 523
524 /** @id MochiKit.Sortable.sequence */ 524 /** @id MochiKit.Sortable.sequence */
525 sequence: function (element, options) { 525 sequence: function (element, options) {
526 element = MochiKit.DOM.getElement(element); 526 element = MochiKit.DOM.getElement(element);
527 var self = MochiKit.Sortable; 527 var self = MochiKit.Sortable;
528 var options = MochiKit.Base.update(self.options(element), options || {}); 528 var options = MochiKit.Base.update(self.options(element), options || {});
529 529
530 return MochiKit.Base.map(function (item) { 530 return MochiKit.Base.map(function (item) {
531 return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; 531 return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
532 }, MochiKit.DOM.getElement(self.findElements(element, options) || [])); 532 }, MochiKit.DOM.getElement(self.findElements(element, options) || []));
533 }, 533 },
534 534
535 /** 535 /**
536 * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest. 536 * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest.
537 * These options override the Sortable options for the serialization only. 537 * These options override the Sortable options for the serialization only.
538 * @param {Node} element Element to serialize. 538 * @param {Node} element Element to serialize.
539 * @param {Object} options Serialization options. 539 * @param {Object} options Serialization options.
540 */ 540 */
541 serialize: function (element, options) { 541 serialize: function (element, options) {
542 element = MochiKit.DOM.getElement(element); 542 element = MochiKit.DOM.getElement(element);
543 var self = MochiKit.Sortable; 543 var self = MochiKit.Sortable;
544 options = MochiKit.Base.update(self.options(element), options || {}); 544 options = MochiKit.Base.update(self.options(element), options || {});
545 var name = encodeURIComponent(options.name || element.id); 545 var name = encodeURIComponent(options.name || element.id);
546 546
547 if (options.tree) { 547 if (options.tree) {
548 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) { 548 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
549 return [name + self._constructIndex(item) + "[id]=" + 549 return [name + self._constructIndex(item) + "[id]=" +
550 encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); 550 encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
551 }, self.tree(element, options).children)).join('&'); 551 }, self.tree(element, options).children)).join('&');
552 } else { 552 } else {
553 return MochiKit.Base.map(function (item) { 553 return MochiKit.Base.map(function (item) {
554 return name + "[]=" + encodeURIComponent(item); 554 return name + "[]=" + encodeURIComponent(item);
555 }, self.sequence(element, options)).join('&'); 555 }, self.sequence(element, options)).join('&');
556 } 556 }
557 } 557 }
558}); 558});
559 559
560// trunk compatibility 560// trunk compatibility
561MochiKit.Sortable.Sortable = MochiKit.Sortable; 561MochiKit.Sortable.Sortable = MochiKit.Sortable;
562 562
563MochiKit.Sortable.__new__ = function () { 563MochiKit.Sortable.__new__ = function () {
564 MochiKit.Base.nameFunctions(this); 564 MochiKit.Base.nameFunctions(this);
565}; 565};
566 566
567MochiKit.Sortable.__new__(); 567MochiKit.Sortable.__new__();
568 568
569MochiKit.Base._exportSymbols(this, MochiKit.Sortable); 569MochiKit.Base._exportSymbols(this, MochiKit.Sortable);