[483] | 1 | define(["../_base/lang", "../sniff", "../_base/window", "../dom-geometry", "../dom-style", "../window"], |
---|
| 2 | function(lang, has, win, domGeom, domStyle, winUtils){ |
---|
| 3 | |
---|
| 4 | // module: |
---|
| 5 | // dojo/dnd/autoscroll |
---|
| 6 | |
---|
| 7 | var exports = { |
---|
| 8 | // summary: |
---|
| 9 | // Used by dojo/dnd/Manager to scroll document or internal node when the user |
---|
| 10 | // drags near the edge of the viewport or a scrollable node |
---|
| 11 | }; |
---|
| 12 | lang.setObject("dojo.dnd.autoscroll", exports); |
---|
| 13 | |
---|
| 14 | exports.getViewport = winUtils.getBox; |
---|
| 15 | |
---|
| 16 | exports.V_TRIGGER_AUTOSCROLL = 32; |
---|
| 17 | exports.H_TRIGGER_AUTOSCROLL = 32; |
---|
| 18 | |
---|
| 19 | exports.V_AUTOSCROLL_VALUE = 16; |
---|
| 20 | exports.H_AUTOSCROLL_VALUE = 16; |
---|
| 21 | |
---|
| 22 | // These are set by autoScrollStart(). |
---|
| 23 | // Set to default values in case autoScrollStart() isn't called. (back-compat, remove for 2.0) |
---|
| 24 | var viewport, |
---|
| 25 | doc = win.doc, |
---|
| 26 | maxScrollTop = Infinity, |
---|
| 27 | maxScrollLeft = Infinity; |
---|
| 28 | |
---|
| 29 | exports.autoScrollStart = function(d){ |
---|
| 30 | // summary: |
---|
| 31 | // Called at the start of a drag. |
---|
| 32 | // d: Document |
---|
| 33 | // The document of the node being dragged. |
---|
| 34 | |
---|
| 35 | doc = d; |
---|
| 36 | viewport = winUtils.getBox(doc); |
---|
| 37 | |
---|
| 38 | // Save height/width of document at start of drag, before it gets distorted by a user dragging an avatar past |
---|
| 39 | // the document's edge |
---|
| 40 | var html = win.body(doc).parentNode; |
---|
| 41 | maxScrollTop = Math.max(html.scrollHeight - viewport.h, 0); |
---|
| 42 | maxScrollLeft = Math.max(html.scrollWidth - viewport.w, 0); // usually 0 |
---|
| 43 | }; |
---|
| 44 | |
---|
| 45 | exports.autoScroll = function(e){ |
---|
| 46 | // summary: |
---|
| 47 | // a handler for mousemove and touchmove events, which scrolls the window, if |
---|
| 48 | // necessary |
---|
| 49 | // e: Event |
---|
| 50 | // mousemove/touchmove event |
---|
| 51 | |
---|
| 52 | // FIXME: needs more docs! |
---|
| 53 | var v = viewport || winUtils.getBox(doc), // getBox() call for back-compat, in case autoScrollStart() wasn't called |
---|
| 54 | html = win.body(doc).parentNode, |
---|
| 55 | dx = 0, dy = 0; |
---|
| 56 | if(e.clientX < exports.H_TRIGGER_AUTOSCROLL){ |
---|
| 57 | dx = -exports.H_AUTOSCROLL_VALUE; |
---|
| 58 | }else if(e.clientX > v.w - exports.H_TRIGGER_AUTOSCROLL){ |
---|
| 59 | dx = Math.min(exports.H_AUTOSCROLL_VALUE, maxScrollLeft - html.scrollLeft); // don't scroll past edge of doc |
---|
| 60 | } |
---|
| 61 | if(e.clientY < exports.V_TRIGGER_AUTOSCROLL){ |
---|
| 62 | dy = -exports.V_AUTOSCROLL_VALUE; |
---|
| 63 | }else if(e.clientY > v.h - exports.V_TRIGGER_AUTOSCROLL){ |
---|
| 64 | dy = Math.min(exports.V_AUTOSCROLL_VALUE, maxScrollTop - html.scrollTop); // don't scroll past edge of doc |
---|
| 65 | } |
---|
| 66 | window.scrollBy(dx, dy); |
---|
| 67 | }; |
---|
| 68 | |
---|
| 69 | exports._validNodes = {"div": 1, "p": 1, "td": 1}; |
---|
| 70 | exports._validOverflow = {"auto": 1, "scroll": 1}; |
---|
| 71 | |
---|
| 72 | exports.autoScrollNodes = function(e){ |
---|
| 73 | // summary: |
---|
| 74 | // a handler for mousemove and touchmove events, which scrolls the first available |
---|
| 75 | // Dom element, it falls back to exports.autoScroll() |
---|
| 76 | // e: Event |
---|
| 77 | // mousemove/touchmove event |
---|
| 78 | |
---|
| 79 | // FIXME: needs more docs! |
---|
| 80 | |
---|
| 81 | var b, t, w, h, rx, ry, dx = 0, dy = 0, oldLeft, oldTop; |
---|
| 82 | |
---|
| 83 | for(var n = e.target; n;){ |
---|
| 84 | if(n.nodeType == 1 && (n.tagName.toLowerCase() in exports._validNodes)){ |
---|
| 85 | var s = domStyle.getComputedStyle(n), |
---|
| 86 | overflow = (s.overflow.toLowerCase() in exports._validOverflow), |
---|
| 87 | overflowX = (s.overflowX.toLowerCase() in exports._validOverflow), |
---|
| 88 | overflowY = (s.overflowY.toLowerCase() in exports._validOverflow); |
---|
| 89 | if(overflow || overflowX || overflowY){ |
---|
| 90 | b = domGeom.getContentBox(n, s); |
---|
| 91 | t = domGeom.position(n, true); |
---|
| 92 | } |
---|
| 93 | // overflow-x |
---|
| 94 | if(overflow || overflowX){ |
---|
| 95 | w = Math.min(exports.H_TRIGGER_AUTOSCROLL, b.w / 2); |
---|
| 96 | rx = e.pageX - t.x; |
---|
| 97 | if(has("webkit") || has("opera")){ |
---|
| 98 | // FIXME: this code should not be here, it should be taken into account |
---|
| 99 | // either by the event fixing code, or the domGeom.position() |
---|
| 100 | // FIXME: this code doesn't work on Opera 9.5 Beta |
---|
| 101 | rx += win.body().scrollLeft; |
---|
| 102 | } |
---|
| 103 | dx = 0; |
---|
| 104 | if(rx > 0 && rx < b.w){ |
---|
| 105 | if(rx < w){ |
---|
| 106 | dx = -w; |
---|
| 107 | }else if(rx > b.w - w){ |
---|
| 108 | dx = w; |
---|
| 109 | } |
---|
| 110 | oldLeft = n.scrollLeft; |
---|
| 111 | n.scrollLeft = n.scrollLeft + dx; |
---|
| 112 | } |
---|
| 113 | } |
---|
| 114 | // overflow-y |
---|
| 115 | if(overflow || overflowY){ |
---|
| 116 | //console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop); |
---|
| 117 | h = Math.min(exports.V_TRIGGER_AUTOSCROLL, b.h / 2); |
---|
| 118 | ry = e.pageY - t.y; |
---|
| 119 | if(has("webkit") || has("opera")){ |
---|
| 120 | // FIXME: this code should not be here, it should be taken into account |
---|
| 121 | // either by the event fixing code, or the domGeom.position() |
---|
| 122 | // FIXME: this code doesn't work on Opera 9.5 Beta |
---|
| 123 | ry += win.body().scrollTop; |
---|
| 124 | } |
---|
| 125 | dy = 0; |
---|
| 126 | if(ry > 0 && ry < b.h){ |
---|
| 127 | if(ry < h){ |
---|
| 128 | dy = -h; |
---|
| 129 | }else if(ry > b.h - h){ |
---|
| 130 | dy = h; |
---|
| 131 | } |
---|
| 132 | oldTop = n.scrollTop; |
---|
| 133 | n.scrollTop = n.scrollTop + dy; |
---|
| 134 | } |
---|
| 135 | } |
---|
| 136 | if(dx || dy){ return; } |
---|
| 137 | } |
---|
| 138 | try{ |
---|
| 139 | n = n.parentNode; |
---|
| 140 | }catch(x){ |
---|
| 141 | n = null; |
---|
| 142 | } |
---|
| 143 | } |
---|
| 144 | exports.autoScroll(e); |
---|
| 145 | }; |
---|
| 146 | |
---|
| 147 | return exports; |
---|
| 148 | |
---|
| 149 | }); |
---|