You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
4.4 KiB
148 lines
4.4 KiB
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; |
|
|
|
});
|
|
|