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