testing/mochitest/MochiKit/Sortable.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial