UNPKG

dojo

Version:

Dojo core is a powerful, lightweight library that makes common tasks quicker and easier. Animate elements, manipulate the DOM, and query with easy CSS syntax, all without sacrificing performance.

149 lines (130 loc) 4.47 kB
define(["../_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), overflowX = (s.overflowX.toLowerCase() in exports._validOverflow), overflowY = (s.overflowY.toLowerCase() in exports._validOverflow); if(overflowX || overflowY){ b = domGeom.getContentBox(n, s); t = domGeom.position(n, true); } // overflow-x if(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(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; });