define("dojo/dnd/autoscroll", ["../_base/lang", "../sniff", "../_base/window", "../dom-geometry", "../dom-style", "../window"], function(lang, has, win, domGeom, domStyle, winUtils){ // module: // dojo/dnd/autoscroll var exports = { // summary: // Used by dojo/dnd/Manager to scroll document or internal node when the user // drags near the edge of the viewport or a scrollable node }; lang.setObject("dojo.dnd.autoscroll", exports); exports.getViewport = winUtils.getBox; exports.V_TRIGGER_AUTOSCROLL = 32; exports.H_TRIGGER_AUTOSCROLL = 32; exports.V_AUTOSCROLL_VALUE = 16; exports.H_AUTOSCROLL_VALUE = 16; // These are set by autoScrollStart(). // Set to default values in case autoScrollStart() isn't called. (back-compat, remove for 2.0) var viewport, doc = win.doc, maxScrollTop = Infinity, maxScrollLeft = Infinity; exports.autoScrollStart = function(d){ // summary: // Called at the start of a drag. // d: Document // The document of the node being dragged. doc = d; viewport = winUtils.getBox(doc); // Save height/width of document at start of drag, before it gets distorted by a user dragging an avatar past // the document's edge var html = win.body(doc).parentNode; maxScrollTop = Math.max(html.scrollHeight - viewport.h, 0); maxScrollLeft = Math.max(html.scrollWidth - viewport.w, 0); // usually 0 }; exports.autoScroll = function(e){ // summary: // a handler for mousemove and touchmove events, which scrolls the window, if // necessary // e: Event // mousemove/touchmove event // FIXME: needs more docs! var v = viewport || winUtils.getBox(doc), // getBox() call for back-compat, in case autoScrollStart() wasn't called html = win.body(doc).parentNode, dx = 0, dy = 0; if(e.clientX < exports.H_TRIGGER_AUTOSCROLL){ dx = -exports.H_AUTOSCROLL_VALUE; }else if(e.clientX > v.w - exports.H_TRIGGER_AUTOSCROLL){ dx = Math.min(exports.H_AUTOSCROLL_VALUE, maxScrollLeft - html.scrollLeft); // don't scroll past edge of doc } if(e.clientY < exports.V_TRIGGER_AUTOSCROLL){ dy = -exports.V_AUTOSCROLL_VALUE; }else if(e.clientY > v.h - exports.V_TRIGGER_AUTOSCROLL){ dy = Math.min(exports.V_AUTOSCROLL_VALUE, maxScrollTop - html.scrollTop); // don't scroll past edge of doc } window.scrollBy(dx, dy); }; exports._validNodes = {"div": 1, "p": 1, "td": 1}; exports._validOverflow = {"auto": 1, "scroll": 1}; exports.autoScrollNodes = function(e){ // summary: // a handler for mousemove and touchmove events, which scrolls the first available // Dom element, it falls back to exports.autoScroll() // e: Event // mousemove/touchmove event // FIXME: needs more docs! var b, t, w, h, rx, ry, dx = 0, dy = 0, oldLeft, oldTop; for(var n = e.target; n;){ if(n.nodeType == 1 && (n.tagName.toLowerCase() in exports._validNodes)){ var s = domStyle.getComputedStyle(n), overflow = (s.overflow.toLowerCase() in exports._validOverflow), overflowX = (s.overflowX.toLowerCase() in exports._validOverflow), overflowY = (s.overflowY.toLowerCase() in exports._validOverflow); if(overflow || overflowX || overflowY){ b = domGeom.getContentBox(n, s); t = domGeom.position(n, true); } // overflow-x if(overflow || overflowX){ w = Math.min(exports.H_TRIGGER_AUTOSCROLL, b.w / 2); rx = e.pageX - t.x; if(has("webkit") || has("opera")){ // FIXME: this code should not be here, it should be taken into account // either by the event fixing code, or the domGeom.position() // FIXME: this code doesn't work on Opera 9.5 Beta rx += win.body().scrollLeft; } dx = 0; if(rx > 0 && rx < b.w){ if(rx < w){ dx = -w; }else if(rx > b.w - w){ dx = w; } oldLeft = n.scrollLeft; n.scrollLeft = n.scrollLeft + dx; } } // overflow-y if(overflow || overflowY){ //console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop); h = Math.min(exports.V_TRIGGER_AUTOSCROLL, b.h / 2); ry = e.pageY - t.y; if(has("webkit") || has("opera")){ // FIXME: this code should not be here, it should be taken into account // either by the event fixing code, or the domGeom.position() // FIXME: this code doesn't work on Opera 9.5 Beta ry += win.body().scrollTop; } dy = 0; if(ry > 0 && ry < b.h){ if(ry < h){ dy = -h; }else if(ry > b.h - h){ dy = h; } oldTop = n.scrollTop; n.scrollTop = n.scrollTop + dy; } } if(dx || dy){ return; } } try{ n = n.parentNode; }catch(x){ n = null; } } exports.autoScroll(e); }; return exports; });