1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/DragAndDrop.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,824 @@ 1.4 +/*** 1.5 +MochiKit.DragAndDrop 1.4 1.6 + 1.7 +See <http://mochikit.com/> for documentation, downloads, license, etc. 1.8 + 1.9 +Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 1.10 + Mochi-ized By Thomas Herve (_firstname_@nimail.org) 1.11 + 1.12 +***/ 1.13 + 1.14 +if (typeof(dojo) != 'undefined') { 1.15 + dojo.provide('MochiKit.DragAndDrop'); 1.16 + dojo.require('MochiKit.Base'); 1.17 + dojo.require('MochiKit.DOM'); 1.18 + dojo.require('MochiKit.Iter'); 1.19 + dojo.require('MochiKit.Visual'); 1.20 + dojo.require('MochiKit.Signal'); 1.21 +} 1.22 + 1.23 +if (typeof(JSAN) != 'undefined') { 1.24 + JSAN.use("MochiKit.Base", []); 1.25 + JSAN.use("MochiKit.DOM", []); 1.26 + JSAN.use("MochiKit.Visual", []); 1.27 + JSAN.use("MochiKit.Iter", []); 1.28 + JSAN.use("MochiKit.Signal", []); 1.29 +} 1.30 + 1.31 +try { 1.32 + if (typeof(MochiKit.Base) == 'undefined' || 1.33 + typeof(MochiKit.DOM) == 'undefined' || 1.34 + typeof(MochiKit.Visual) == 'undefined' || 1.35 + typeof(MochiKit.Signal) == 'undefined' || 1.36 + typeof(MochiKit.Iter) == 'undefined') { 1.37 + throw ""; 1.38 + } 1.39 +} catch (e) { 1.40 + throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM, MochiKit.Visual, MochiKit.Signal and MochiKit.Iter!"; 1.41 +} 1.42 + 1.43 +if (typeof(MochiKit.DragAndDrop) == 'undefined') { 1.44 + MochiKit.DragAndDrop = {}; 1.45 +} 1.46 + 1.47 +MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop'; 1.48 +MochiKit.DragAndDrop.VERSION = '1.4'; 1.49 + 1.50 +MochiKit.DragAndDrop.__repr__ = function () { 1.51 + return '[' + this.NAME + ' ' + this.VERSION + ']'; 1.52 +}; 1.53 + 1.54 +MochiKit.DragAndDrop.toString = function () { 1.55 + return this.__repr__(); 1.56 +}; 1.57 + 1.58 +MochiKit.DragAndDrop.EXPORT = [ 1.59 + "Droppable", 1.60 + "Draggable" 1.61 +]; 1.62 + 1.63 +MochiKit.DragAndDrop.EXPORT_OK = [ 1.64 + "Droppables", 1.65 + "Draggables" 1.66 +]; 1.67 + 1.68 +MochiKit.DragAndDrop.Droppables = { 1.69 + /*** 1.70 + 1.71 + Manage all droppables. Shouldn't be used, use the Droppable object instead. 1.72 + 1.73 + ***/ 1.74 + drops: [], 1.75 + 1.76 + remove: function (element) { 1.77 + this.drops = MochiKit.Base.filter(function (d) { 1.78 + return d.element != MochiKit.DOM.getElement(element); 1.79 + }, this.drops); 1.80 + }, 1.81 + 1.82 + register: function (drop) { 1.83 + this.drops.push(drop); 1.84 + }, 1.85 + 1.86 + unregister: function (drop) { 1.87 + this.drops = MochiKit.Base.filter(function (d) { 1.88 + return d != drop; 1.89 + }, this.drops); 1.90 + }, 1.91 + 1.92 + prepare: function (element) { 1.93 + MochiKit.Base.map(function (drop) { 1.94 + if (drop.isAccepted(element)) { 1.95 + if (drop.options.activeclass) { 1.96 + MochiKit.DOM.addElementClass(drop.element, 1.97 + drop.options.activeclass); 1.98 + } 1.99 + drop.options.onactive(drop.element, element); 1.100 + } 1.101 + }, this.drops); 1.102 + }, 1.103 + 1.104 + findDeepestChild: function (drops) { 1.105 + deepest = drops[0]; 1.106 + 1.107 + for (i = 1; i < drops.length; ++i) { 1.108 + if (MochiKit.DOM.isParent(drops[i].element, deepest.element)) { 1.109 + deepest = drops[i]; 1.110 + } 1.111 + } 1.112 + return deepest; 1.113 + }, 1.114 + 1.115 + show: function (point, element) { 1.116 + if (!this.drops.length) { 1.117 + return; 1.118 + } 1.119 + var affected = []; 1.120 + 1.121 + if (this.last_active) { 1.122 + this.last_active.deactivate(); 1.123 + } 1.124 + MochiKit.Iter.forEach(this.drops, function (drop) { 1.125 + if (drop.isAffected(point, element)) { 1.126 + affected.push(drop); 1.127 + } 1.128 + }); 1.129 + if (affected.length > 0) { 1.130 + drop = this.findDeepestChild(affected); 1.131 + MochiKit.Position.within(drop.element, point.page.x, point.page.y); 1.132 + drop.options.onhover(element, drop.element, 1.133 + MochiKit.Position.overlap(drop.options.overlap, drop.element)); 1.134 + drop.activate(); 1.135 + } 1.136 + }, 1.137 + 1.138 + fire: function (event, element) { 1.139 + if (!this.last_active) { 1.140 + return; 1.141 + } 1.142 + MochiKit.Position.prepare(); 1.143 + 1.144 + if (this.last_active.isAffected(event.mouse(), element)) { 1.145 + this.last_active.options.ondrop(element, 1.146 + this.last_active.element, event); 1.147 + } 1.148 + }, 1.149 + 1.150 + reset: function (element) { 1.151 + MochiKit.Base.map(function (drop) { 1.152 + if (drop.options.activeclass) { 1.153 + MochiKit.DOM.removeElementClass(drop.element, 1.154 + drop.options.activeclass); 1.155 + } 1.156 + drop.options.ondesactive(drop.element, element); 1.157 + }, this.drops); 1.158 + if (this.last_active) { 1.159 + this.last_active.deactivate(); 1.160 + } 1.161 + } 1.162 +}; 1.163 + 1.164 +/** @id MochiKit.DragAndDrop.Droppable */ 1.165 +MochiKit.DragAndDrop.Droppable = function (element, options) { 1.166 + var cls = arguments.callee; 1.167 + if (!(this instanceof cls)) { 1.168 + return new cls(element, options); 1.169 + } 1.170 + this.__init__(element, options); 1.171 +}; 1.172 + 1.173 +MochiKit.DragAndDrop.Droppable.prototype = { 1.174 + /*** 1.175 + 1.176 + A droppable object. Simple use is to create giving an element: 1.177 + 1.178 + new MochiKit.DragAndDrop.Droppable('myelement'); 1.179 + 1.180 + Generally you'll want to define the 'ondrop' function and maybe the 1.181 + 'accept' option to filter draggables. 1.182 + 1.183 + ***/ 1.184 + __class__: MochiKit.DragAndDrop.Droppable, 1.185 + 1.186 + __init__: function (element, /* optional */options) { 1.187 + var d = MochiKit.DOM; 1.188 + var b = MochiKit.Base; 1.189 + this.element = d.getElement(element); 1.190 + this.options = b.update({ 1.191 + 1.192 + /** @id MochiKit.DragAndDrop.greedy */ 1.193 + greedy: true, 1.194 + 1.195 + /** @id MochiKit.DragAndDrop.hoverclass */ 1.196 + hoverclass: null, 1.197 + 1.198 + /** @id MochiKit.DragAndDrop.activeclass */ 1.199 + activeclass: null, 1.200 + 1.201 + /** @id MochiKit.DragAndDrop.hoverfunc */ 1.202 + hoverfunc: b.noop, 1.203 + 1.204 + /** @id MochiKit.DragAndDrop.accept */ 1.205 + accept: null, 1.206 + 1.207 + /** @id MochiKit.DragAndDrop.onactive */ 1.208 + onactive: b.noop, 1.209 + 1.210 + /** @id MochiKit.DragAndDrop.ondesactive */ 1.211 + ondesactive: b.noop, 1.212 + 1.213 + /** @id MochiKit.DragAndDrop.onhover */ 1.214 + onhover: b.noop, 1.215 + 1.216 + /** @id MochiKit.DragAndDrop.ondrop */ 1.217 + ondrop: b.noop, 1.218 + 1.219 + /** @id MochiKit.DragAndDrop.containment */ 1.220 + containment: [], 1.221 + tree: false 1.222 + }, options || {}); 1.223 + 1.224 + // cache containers 1.225 + this.options._containers = []; 1.226 + b.map(MochiKit.Base.bind(function (c) { 1.227 + this.options._containers.push(d.getElement(c)); 1.228 + }, this), this.options.containment); 1.229 + 1.230 + d.makePositioned(this.element); // fix IE 1.231 + 1.232 + MochiKit.DragAndDrop.Droppables.register(this); 1.233 + }, 1.234 + 1.235 + /** @id MochiKit.DragAndDrop.isContained */ 1.236 + isContained: function (element) { 1.237 + if (this.options._containers.length) { 1.238 + var containmentNode; 1.239 + if (this.options.tree) { 1.240 + containmentNode = element.treeNode; 1.241 + } else { 1.242 + containmentNode = element.parentNode; 1.243 + } 1.244 + return MochiKit.Iter.some(this.options._containers, function (c) { 1.245 + return containmentNode == c; 1.246 + }); 1.247 + } else { 1.248 + return true; 1.249 + } 1.250 + }, 1.251 + 1.252 + /** @id MochiKit.DragAndDrop.isAccepted */ 1.253 + isAccepted: function (element) { 1.254 + return ((!this.options.accept) || MochiKit.Iter.some( 1.255 + this.options.accept, function (c) { 1.256 + return MochiKit.DOM.hasElementClass(element, c); 1.257 + })); 1.258 + }, 1.259 + 1.260 + /** @id MochiKit.DragAndDrop.isAffected */ 1.261 + isAffected: function (point, element) { 1.262 + return ((this.element != element) && 1.263 + this.isContained(element) && 1.264 + this.isAccepted(element) && 1.265 + MochiKit.Position.within(this.element, point.page.x, 1.266 + point.page.y)); 1.267 + }, 1.268 + 1.269 + /** @id MochiKit.DragAndDrop.deactivate */ 1.270 + deactivate: function () { 1.271 + /*** 1.272 + 1.273 + A droppable is deactivate when a draggable has been over it and left. 1.274 + 1.275 + ***/ 1.276 + if (this.options.hoverclass) { 1.277 + MochiKit.DOM.removeElementClass(this.element, 1.278 + this.options.hoverclass); 1.279 + } 1.280 + this.options.hoverfunc(this.element, false); 1.281 + MochiKit.DragAndDrop.Droppables.last_active = null; 1.282 + }, 1.283 + 1.284 + /** @id MochiKit.DragAndDrop.activate */ 1.285 + activate: function () { 1.286 + /*** 1.287 + 1.288 + A droppable is active when a draggable is over it. 1.289 + 1.290 + ***/ 1.291 + if (this.options.hoverclass) { 1.292 + MochiKit.DOM.addElementClass(this.element, this.options.hoverclass); 1.293 + } 1.294 + this.options.hoverfunc(this.element, true); 1.295 + MochiKit.DragAndDrop.Droppables.last_active = this; 1.296 + }, 1.297 + 1.298 + /** @id MochiKit.DragAndDrop.destroy */ 1.299 + destroy: function () { 1.300 + /*** 1.301 + 1.302 + Delete this droppable. 1.303 + 1.304 + ***/ 1.305 + MochiKit.DragAndDrop.Droppables.unregister(this); 1.306 + }, 1.307 + 1.308 + /** @id MochiKit.DragAndDrop.repr */ 1.309 + repr: function () { 1.310 + return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]"; 1.311 + } 1.312 +}; 1.313 + 1.314 +MochiKit.DragAndDrop.Draggables = { 1.315 + /*** 1.316 + 1.317 + Manage draggables elements. Not intended to direct use. 1.318 + 1.319 + ***/ 1.320 + drags: [], 1.321 + 1.322 + register: function (draggable) { 1.323 + if (this.drags.length === 0) { 1.324 + var conn = MochiKit.Signal.connect; 1.325 + this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag); 1.326 + this.eventMouseMove = conn(document, 'onmousemove', this, 1.327 + this.updateDrag); 1.328 + this.eventKeypress = conn(document, 'onkeypress', this, 1.329 + this.keyPress); 1.330 + } 1.331 + this.drags.push(draggable); 1.332 + }, 1.333 + 1.334 + unregister: function (draggable) { 1.335 + this.drags = MochiKit.Base.filter(function (d) { 1.336 + return d != draggable; 1.337 + }, this.drags); 1.338 + if (this.drags.length === 0) { 1.339 + var disc = MochiKit.Signal.disconnect; 1.340 + disc(this.eventMouseUp); 1.341 + disc(this.eventMouseMove); 1.342 + disc(this.eventKeypress); 1.343 + } 1.344 + }, 1.345 + 1.346 + activate: function (draggable) { 1.347 + // allows keypress events if window is not currently focused 1.348 + // fails for Safari 1.349 + window.focus(); 1.350 + this.activeDraggable = draggable; 1.351 + }, 1.352 + 1.353 + deactivate: function () { 1.354 + this.activeDraggable = null; 1.355 + }, 1.356 + 1.357 + updateDrag: function (event) { 1.358 + if (!this.activeDraggable) { 1.359 + return; 1.360 + } 1.361 + var pointer = event.mouse(); 1.362 + // Mozilla-based browsers fire successive mousemove events with 1.363 + // the same coordinates, prevent needless redrawing (moz bug?) 1.364 + if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) == 1.365 + MochiKit.Base.repr(pointer.page))) { 1.366 + return; 1.367 + } 1.368 + this._lastPointer = pointer; 1.369 + this.activeDraggable.updateDrag(event, pointer); 1.370 + }, 1.371 + 1.372 + endDrag: function (event) { 1.373 + if (!this.activeDraggable) { 1.374 + return; 1.375 + } 1.376 + this._lastPointer = null; 1.377 + this.activeDraggable.endDrag(event); 1.378 + this.activeDraggable = null; 1.379 + }, 1.380 + 1.381 + keyPress: function (event) { 1.382 + if (this.activeDraggable) { 1.383 + this.activeDraggable.keyPress(event); 1.384 + } 1.385 + }, 1.386 + 1.387 + notify: function (eventName, draggable, event) { 1.388 + MochiKit.Signal.signal(this, eventName, draggable, event); 1.389 + } 1.390 +}; 1.391 + 1.392 +/** @id MochiKit.DragAndDrop.Draggable */ 1.393 +MochiKit.DragAndDrop.Draggable = function (element, options) { 1.394 + var cls = arguments.callee; 1.395 + if (!(this instanceof cls)) { 1.396 + return new cls(element, options); 1.397 + } 1.398 + this.__init__(element, options); 1.399 +}; 1.400 + 1.401 +MochiKit.DragAndDrop.Draggable.prototype = { 1.402 + /*** 1.403 + 1.404 + A draggable object. Simple instantiate : 1.405 + 1.406 + new MochiKit.DragAndDrop.Draggable('myelement'); 1.407 + 1.408 + ***/ 1.409 + __class__ : MochiKit.DragAndDrop.Draggable, 1.410 + 1.411 + __init__: function (element, /* optional */options) { 1.412 + var v = MochiKit.Visual; 1.413 + var b = MochiKit.Base; 1.414 + options = b.update({ 1.415 + 1.416 + /** @id MochiKit.DragAndDrop.handle */ 1.417 + handle: false, 1.418 + 1.419 + /** @id MochiKit.DragAndDrop.starteffect */ 1.420 + starteffect: function (innerelement) { 1.421 + this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0; 1.422 + new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7}); 1.423 + }, 1.424 + /** @id MochiKit.DragAndDrop.reverteffect */ 1.425 + reverteffect: function (innerelement, top_offset, left_offset) { 1.426 + var dur = Math.sqrt(Math.abs(top_offset^2) + 1.427 + Math.abs(left_offset^2))*0.02; 1.428 + return new v.Move(innerelement, 1.429 + {x: -left_offset, y: -top_offset, duration: dur}); 1.430 + }, 1.431 + 1.432 + /** @id MochiKit.DragAndDrop.endeffect */ 1.433 + endeffect: function (innerelement) { 1.434 + new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity}); 1.435 + }, 1.436 + 1.437 + /** @id MochiKit.DragAndDrop.onchange */ 1.438 + onchange: b.noop, 1.439 + 1.440 + /** @id MochiKit.DragAndDrop.zindex */ 1.441 + zindex: 1000, 1.442 + 1.443 + /** @id MochiKit.DragAndDrop.revert */ 1.444 + revert: false, 1.445 + 1.446 + /** @id MochiKit.DragAndDrop.scroll */ 1.447 + scroll: false, 1.448 + 1.449 + /** @id MochiKit.DragAndDrop.scrollSensitivity */ 1.450 + scrollSensitivity: 20, 1.451 + 1.452 + /** @id MochiKit.DragAndDrop.scrollSpeed */ 1.453 + scrollSpeed: 15, 1.454 + // false, or xy or [x, y] or function (x, y){return [x, y];} 1.455 + 1.456 + /** @id MochiKit.DragAndDrop.snap */ 1.457 + snap: false 1.458 + }, options || {}); 1.459 + 1.460 + var d = MochiKit.DOM; 1.461 + this.element = d.getElement(element); 1.462 + 1.463 + if (options.handle && (typeof(options.handle) == 'string')) { 1.464 + this.handle = d.getFirstElementByTagAndClassName(null, 1.465 + options.handle, this.element); 1.466 + } 1.467 + if (!this.handle) { 1.468 + this.handle = d.getElement(options.handle); 1.469 + } 1.470 + if (!this.handle) { 1.471 + this.handle = this.element; 1.472 + } 1.473 + 1.474 + if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { 1.475 + options.scroll = d.getElement(options.scroll); 1.476 + this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll); 1.477 + } 1.478 + 1.479 + d.makePositioned(this.element); // fix IE 1.480 + 1.481 + this.delta = this.currentDelta(); 1.482 + this.options = options; 1.483 + this.dragging = false; 1.484 + 1.485 + this.eventMouseDown = MochiKit.Signal.connect(this.handle, 1.486 + 'onmousedown', this, this.initDrag); 1.487 + MochiKit.DragAndDrop.Draggables.register(this); 1.488 + }, 1.489 + 1.490 + /** @id MochiKit.DragAndDrop.destroy */ 1.491 + destroy: function () { 1.492 + MochiKit.Signal.disconnect(this.eventMouseDown); 1.493 + MochiKit.DragAndDrop.Draggables.unregister(this); 1.494 + }, 1.495 + 1.496 + /** @id MochiKit.DragAndDrop.currentDelta */ 1.497 + currentDelta: function () { 1.498 + var s = MochiKit.Style.getStyle; 1.499 + return [ 1.500 + parseInt(s(this.element, 'left') || '0'), 1.501 + parseInt(s(this.element, 'top') || '0')]; 1.502 + }, 1.503 + 1.504 + /** @id MochiKit.DragAndDrop.initDrag */ 1.505 + initDrag: function (event) { 1.506 + if (!event.mouse().button.left) { 1.507 + return; 1.508 + } 1.509 + // abort on form elements, fixes a Firefox issue 1.510 + var src = event.target(); 1.511 + var tagName = (src.tagName || '').toUpperCase(); 1.512 + if (tagName === 'INPUT' || tagName === 'SELECT' || 1.513 + tagName === 'OPTION' || tagName === 'BUTTON' || 1.514 + tagName === 'TEXTAREA') { 1.515 + return; 1.516 + } 1.517 + 1.518 + if (this._revert) { 1.519 + this._revert.cancel(); 1.520 + this._revert = null; 1.521 + } 1.522 + 1.523 + var pointer = event.mouse(); 1.524 + var pos = MochiKit.Position.cumulativeOffset(this.element); 1.525 + this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y]; 1.526 + 1.527 + MochiKit.DragAndDrop.Draggables.activate(this); 1.528 + event.stop(); 1.529 + }, 1.530 + 1.531 + /** @id MochiKit.DragAndDrop.startDrag */ 1.532 + startDrag: function (event) { 1.533 + this.dragging = true; 1.534 + if (this.options.selectclass) { 1.535 + MochiKit.DOM.addElementClass(this.element, 1.536 + this.options.selectclass); 1.537 + } 1.538 + if (this.options.zindex) { 1.539 + this.originalZ = parseInt(MochiKit.Style.getStyle(this.element, 1.540 + 'z-index') || '0'); 1.541 + this.element.style.zIndex = this.options.zindex; 1.542 + } 1.543 + 1.544 + if (this.options.ghosting) { 1.545 + this._clone = this.element.cloneNode(true); 1.546 + this.ghostPosition = MochiKit.Position.absolutize(this.element); 1.547 + this.element.parentNode.insertBefore(this._clone, this.element); 1.548 + } 1.549 + 1.550 + if (this.options.scroll) { 1.551 + if (this.options.scroll == window) { 1.552 + var where = this._getWindowScroll(this.options.scroll); 1.553 + this.originalScrollLeft = where.left; 1.554 + this.originalScrollTop = where.top; 1.555 + } else { 1.556 + this.originalScrollLeft = this.options.scroll.scrollLeft; 1.557 + this.originalScrollTop = this.options.scroll.scrollTop; 1.558 + } 1.559 + } 1.560 + 1.561 + MochiKit.DragAndDrop.Droppables.prepare(this.element); 1.562 + MochiKit.DragAndDrop.Draggables.notify('start', this, event); 1.563 + if (this.options.starteffect) { 1.564 + this.options.starteffect(this.element); 1.565 + } 1.566 + }, 1.567 + 1.568 + /** @id MochiKit.DragAndDrop.updateDrag */ 1.569 + updateDrag: function (event, pointer) { 1.570 + if (!this.dragging) { 1.571 + this.startDrag(event); 1.572 + } 1.573 + MochiKit.Position.prepare(); 1.574 + MochiKit.DragAndDrop.Droppables.show(pointer, this.element); 1.575 + MochiKit.DragAndDrop.Draggables.notify('drag', this, event); 1.576 + this.draw(pointer); 1.577 + this.options.onchange(this); 1.578 + 1.579 + if (this.options.scroll) { 1.580 + this.stopScrolling(); 1.581 + var p, q; 1.582 + if (this.options.scroll == window) { 1.583 + var s = this._getWindowScroll(this.options.scroll); 1.584 + p = new MochiKit.Style.Coordinates(s.left, s.top); 1.585 + q = new MochiKit.Style.Coordinates(s.left + s.width, 1.586 + s.top + s.height); 1.587 + } else { 1.588 + p = MochiKit.Position.page(this.options.scroll); 1.589 + p.x += this.options.scroll.scrollLeft; 1.590 + p.y += this.options.scroll.scrollTop; 1.591 + p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0); 1.592 + p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0); 1.593 + q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth, 1.594 + p.y + this.options.scroll.offsetHeight); 1.595 + } 1.596 + var speed = [0, 0]; 1.597 + if (pointer.page.x > (q.x - this.options.scrollSensitivity)) { 1.598 + speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity); 1.599 + } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) { 1.600 + speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity); 1.601 + } 1.602 + if (pointer.page.y > (q.y - this.options.scrollSensitivity)) { 1.603 + speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity); 1.604 + } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) { 1.605 + speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity); 1.606 + } 1.607 + this.startScrolling(speed); 1.608 + } 1.609 + 1.610 + // fix AppleWebKit rendering 1.611 + if (/AppleWebKit'/.test(navigator.appVersion)) { 1.612 + window.scrollBy(0, 0); 1.613 + } 1.614 + event.stop(); 1.615 + }, 1.616 + 1.617 + /** @id MochiKit.DragAndDrop.finishDrag */ 1.618 + finishDrag: function (event, success) { 1.619 + var dr = MochiKit.DragAndDrop; 1.620 + this.dragging = false; 1.621 + if (this.options.selectclass) { 1.622 + MochiKit.DOM.removeElementClass(this.element, 1.623 + this.options.selectclass); 1.624 + } 1.625 + 1.626 + if (this.options.ghosting) { 1.627 + // XXX: from a user point of view, it would be better to remove 1.628 + // the node only *after* the MochiKit.Visual.Move end when used 1.629 + // with revert. 1.630 + MochiKit.Position.relativize(this.element, this.ghostPosition); 1.631 + MochiKit.DOM.removeElement(this._clone); 1.632 + this._clone = null; 1.633 + } 1.634 + 1.635 + if (success) { 1.636 + dr.Droppables.fire(event, this.element); 1.637 + } 1.638 + dr.Draggables.notify('end', this, event); 1.639 + 1.640 + var revert = this.options.revert; 1.641 + if (revert && typeof(revert) == 'function') { 1.642 + revert = revert(this.element); 1.643 + } 1.644 + 1.645 + var d = this.currentDelta(); 1.646 + if (revert && this.options.reverteffect) { 1.647 + this._revert = this.options.reverteffect(this.element, 1.648 + d[1] - this.delta[1], d[0] - this.delta[0]); 1.649 + } else { 1.650 + this.delta = d; 1.651 + } 1.652 + 1.653 + if (this.options.zindex) { 1.654 + this.element.style.zIndex = this.originalZ; 1.655 + } 1.656 + 1.657 + if (this.options.endeffect) { 1.658 + this.options.endeffect(this.element); 1.659 + } 1.660 + 1.661 + dr.Draggables.deactivate(); 1.662 + dr.Droppables.reset(this.element); 1.663 + }, 1.664 + 1.665 + /** @id MochiKit.DragAndDrop.keyPress */ 1.666 + keyPress: function (event) { 1.667 + if (event.key().string != "KEY_ESCAPE") { 1.668 + return; 1.669 + } 1.670 + this.finishDrag(event, false); 1.671 + event.stop(); 1.672 + }, 1.673 + 1.674 + /** @id MochiKit.DragAndDrop.endDrag */ 1.675 + endDrag: function (event) { 1.676 + if (!this.dragging) { 1.677 + return; 1.678 + } 1.679 + this.stopScrolling(); 1.680 + this.finishDrag(event, true); 1.681 + event.stop(); 1.682 + }, 1.683 + 1.684 + /** @id MochiKit.DragAndDrop.draw */ 1.685 + draw: function (point) { 1.686 + var pos = MochiKit.Position.cumulativeOffset(this.element); 1.687 + var d = this.currentDelta(); 1.688 + pos.x -= d[0]; 1.689 + pos.y -= d[1]; 1.690 + 1.691 + if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { 1.692 + pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft; 1.693 + pos.y -= this.options.scroll.scrollTop - this.originalScrollTop; 1.694 + } 1.695 + 1.696 + var p = [point.page.x - pos.x - this.offset[0], 1.697 + point.page.y - pos.y - this.offset[1]]; 1.698 + 1.699 + if (this.options.snap) { 1.700 + if (typeof(this.options.snap) == 'function') { 1.701 + p = this.options.snap(p[0], p[1]); 1.702 + } else { 1.703 + if (this.options.snap instanceof Array) { 1.704 + var i = -1; 1.705 + p = MochiKit.Base.map(MochiKit.Base.bind(function (v) { 1.706 + i += 1; 1.707 + return Math.round(v/this.options.snap[i]) * 1.708 + this.options.snap[i]; 1.709 + }, this), p); 1.710 + } else { 1.711 + p = MochiKit.Base.map(MochiKit.Base.bind(function (v) { 1.712 + return Math.round(v/this.options.snap) * 1.713 + this.options.snap; 1.714 + }, this), p); 1.715 + } 1.716 + } 1.717 + } 1.718 + var style = this.element.style; 1.719 + if ((!this.options.constraint) || 1.720 + (this.options.constraint == 'horizontal')) { 1.721 + style.left = p[0] + 'px'; 1.722 + } 1.723 + if ((!this.options.constraint) || 1.724 + (this.options.constraint == 'vertical')) { 1.725 + style.top = p[1] + 'px'; 1.726 + } 1.727 + if (style.visibility == 'hidden') { 1.728 + style.visibility = ''; // fix gecko rendering 1.729 + } 1.730 + }, 1.731 + 1.732 + /** @id MochiKit.DragAndDrop.stopScrolling */ 1.733 + stopScrolling: function () { 1.734 + if (this.scrollInterval) { 1.735 + clearInterval(this.scrollInterval); 1.736 + this.scrollInterval = null; 1.737 + MochiKit.DragAndDrop.Draggables._lastScrollPointer = null; 1.738 + } 1.739 + }, 1.740 + 1.741 + /** @id MochiKit.DragAndDrop.startScrolling */ 1.742 + startScrolling: function (speed) { 1.743 + if (!speed[0] && !speed[1]) { 1.744 + return; 1.745 + } 1.746 + this.scrollSpeed = [speed[0] * this.options.scrollSpeed, 1.747 + speed[1] * this.options.scrollSpeed]; 1.748 + this.lastScrolled = new Date(); 1.749 + this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10); 1.750 + }, 1.751 + 1.752 + /** @id MochiKit.DragAndDrop.scroll */ 1.753 + scroll: function () { 1.754 + var current = new Date(); 1.755 + var delta = current - this.lastScrolled; 1.756 + this.lastScrolled = current; 1.757 + 1.758 + if (this.options.scroll == window) { 1.759 + var s = this._getWindowScroll(this.options.scroll); 1.760 + if (this.scrollSpeed[0] || this.scrollSpeed[1]) { 1.761 + var dm = delta / 1000; 1.762 + this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0], 1.763 + s.top + dm * this.scrollSpeed[1]); 1.764 + } 1.765 + } else { 1.766 + this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; 1.767 + this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; 1.768 + } 1.769 + 1.770 + var d = MochiKit.DragAndDrop; 1.771 + 1.772 + MochiKit.Position.prepare(); 1.773 + d.Droppables.show(d.Draggables._lastPointer, this.element); 1.774 + d.Draggables.notify('drag', this); 1.775 + if (this._isScrollChild) { 1.776 + d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer; 1.777 + d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000; 1.778 + d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000; 1.779 + if (d.Draggables._lastScrollPointer.x < 0) { 1.780 + d.Draggables._lastScrollPointer.x = 0; 1.781 + } 1.782 + if (d.Draggables._lastScrollPointer.y < 0) { 1.783 + d.Draggables._lastScrollPointer.y = 0; 1.784 + } 1.785 + this.draw(d.Draggables._lastScrollPointer); 1.786 + } 1.787 + 1.788 + this.options.onchange(this); 1.789 + }, 1.790 + 1.791 + _getWindowScroll: function (win) { 1.792 + var vp, w, h; 1.793 + MochiKit.DOM.withWindow(win, function () { 1.794 + vp = MochiKit.Style.getViewportPosition(win.document); 1.795 + }); 1.796 + if (win.innerWidth) { 1.797 + w = win.innerWidth; 1.798 + h = win.innerHeight; 1.799 + } else if (win.document.documentElement && win.document.documentElement.clientWidth) { 1.800 + w = win.document.documentElement.clientWidth; 1.801 + h = win.document.documentElement.clientHeight; 1.802 + } else { 1.803 + w = win.document.body.offsetWidth; 1.804 + h = win.document.body.offsetHeight; 1.805 + } 1.806 + return {top: vp.x, left: vp.y, width: w, height: h}; 1.807 + }, 1.808 + 1.809 + /** @id MochiKit.DragAndDrop.repr */ 1.810 + repr: function () { 1.811 + return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]"; 1.812 + } 1.813 +}; 1.814 + 1.815 +MochiKit.DragAndDrop.__new__ = function () { 1.816 + MochiKit.Base.nameFunctions(this); 1.817 + 1.818 + this.EXPORT_TAGS = { 1.819 + ":common": this.EXPORT, 1.820 + ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) 1.821 + }; 1.822 +}; 1.823 + 1.824 +MochiKit.DragAndDrop.__new__(); 1.825 + 1.826 +MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop); 1.827 +