[256] | 1 | define(["dojo", "doh/_browserRunner", "doh/robot", "dojo/window"], function(dojo, doh) { |
---|
| 2 | |
---|
| 3 | dojo.experimental("dojo.robot"); |
---|
| 4 | |
---|
| 5 | // users who use doh+dojo get the added convenience of dojo.mouseMoveAt, |
---|
| 6 | // instead of computing the absolute coordinates of their elements themselves |
---|
| 7 | dojo.mixin(doh.robot,{ |
---|
| 8 | |
---|
| 9 | _resolveNode: function(/*String||DOMNode||Function*/ n){ |
---|
| 10 | if(typeof n == "function"){ |
---|
| 11 | // if the user passed a function returning a node, evaluate it |
---|
| 12 | n = n(); |
---|
| 13 | } |
---|
| 14 | return n? dojo.byId(n) : null; |
---|
| 15 | }, |
---|
| 16 | |
---|
| 17 | _scrollIntoView: function(/*Node*/ n){ |
---|
| 18 | // scrolls the passed node into view, scrolling all ancester frames/windows as well. |
---|
| 19 | // Assumes parent iframes can be made fully visible given the current browser window size |
---|
| 20 | var dr = doh.robot, |
---|
| 21 | p = null; |
---|
| 22 | dojo.forEach(dr._getWindowChain(n), function(w){ |
---|
| 23 | dojo.withGlobal(w, function(){ |
---|
| 24 | // get the position of the node wrt its parent window |
---|
| 25 | // if it is a parent frame, its padding and border extents will get added in |
---|
| 26 | var p2 = dojo.position(n, false), |
---|
| 27 | b = dojo._getPadBorderExtents(n), |
---|
| 28 | oldp = null; |
---|
| 29 | // if p2 is the position of the original passed node, store the position away as p |
---|
| 30 | // otherwise, node is actually an iframe. in this case, add the iframe's position wrt its parent window and also the iframe's padding and border extents |
---|
| 31 | if(!p){ |
---|
| 32 | p = p2; |
---|
| 33 | }else{ |
---|
| 34 | oldp = p; |
---|
| 35 | p = {x: p.x+p2.x+b.l, |
---|
| 36 | y: p.y+p2.y+b.t, |
---|
| 37 | w: p.w, |
---|
| 38 | h: p.h}; |
---|
| 39 | |
---|
| 40 | } |
---|
| 41 | // scroll the parent window so that the node translated into the parent window's coordinate space is in view |
---|
| 42 | dojo.window.scrollIntoView(n,p); |
---|
| 43 | // adjust position for the new scroll offsets |
---|
| 44 | p2 = dojo.position(n, false); |
---|
| 45 | if(!oldp){ |
---|
| 46 | p = p2; |
---|
| 47 | }else{ |
---|
| 48 | p = {x: oldp.x+p2.x+b.l, |
---|
| 49 | y: oldp.y+p2.y+b.t, |
---|
| 50 | w: p.w, |
---|
| 51 | h: p.h}; |
---|
| 52 | } |
---|
| 53 | // get the parent iframe so it can be scrolled too |
---|
| 54 | n = w.frameElement; |
---|
| 55 | }); |
---|
| 56 | }); |
---|
| 57 | }, |
---|
| 58 | |
---|
| 59 | _position: function(/*Node*/ n){ |
---|
| 60 | // Returns the dojo.position of the passed node wrt the passed window's viewport, |
---|
| 61 | // following any parent iframes containing the node and clipping the node to each iframe. |
---|
| 62 | // precondition: _scrollIntoView already called |
---|
| 63 | var p = null, M = Math.max, m = Math.min; |
---|
| 64 | // p: the returned position of the node |
---|
| 65 | dojo.forEach(doh.robot._getWindowChain(n), function(w){ |
---|
| 66 | dojo.withGlobal(w, function(){ |
---|
| 67 | // get the position of the node wrt its parent window |
---|
| 68 | // if it is a parent frame, its padding and border extents will get added in |
---|
| 69 | var p2 = dojo.position(n, false), b = dojo._getPadBorderExtents(n); |
---|
| 70 | // if p2 is the position of the original passed node, store the position away as p |
---|
| 71 | // otherwise, node is actually an iframe. in this case, add the iframe's position wrt its parent window and also the iframe's padding and border extents |
---|
| 72 | if(!p){ |
---|
| 73 | p = p2; |
---|
| 74 | }else{ |
---|
| 75 | var view; |
---|
| 76 | dojo.withGlobal(n.contentWindow,function(){ |
---|
| 77 | view=dojo.window.getBox(); |
---|
| 78 | }); |
---|
| 79 | p2.r = p2.x+view.w; |
---|
| 80 | p2.b = p2.y+view.h; |
---|
| 81 | p = {x: M(p.x+p2.x,p2.x)+b.l, // clip left edge of node wrt the iframe |
---|
| 82 | y: M(p.y+p2.y,p2.y)+b.t, // top edge |
---|
| 83 | r: m(p.x+p2.x+p.w,p2.r)+b.l, // right edge (to compute width) |
---|
| 84 | b: m(p.y+p2.y+p.h,p2.b)+b.t}; // bottom edge (to compute height) |
---|
| 85 | // save a few bytes by computing width and height from r and b |
---|
| 86 | p.w = p.r-p.x; |
---|
| 87 | p.h = p.b-p.y; |
---|
| 88 | } |
---|
| 89 | // the new node is now the old node's parent iframe |
---|
| 90 | n=w.frameElement; |
---|
| 91 | }); |
---|
| 92 | }); |
---|
| 93 | return p; |
---|
| 94 | }, |
---|
| 95 | |
---|
| 96 | _getWindowChain : function(/*Node*/ n){ |
---|
| 97 | // Returns an array of windows starting from the passed node's parent window and ending at dojo's window |
---|
| 98 | var cW = dojo.window.get(n.ownerDocument); |
---|
| 99 | var arr=[cW]; |
---|
| 100 | var f = cW.frameElement; |
---|
| 101 | return (cW == dojo.global || f == null)? arr : arr.concat(doh.robot._getWindowChain(f)); |
---|
| 102 | }, |
---|
| 103 | |
---|
| 104 | scrollIntoView : function(/*String||DOMNode||Function*/ node, /*Number, optional*/ delay){ |
---|
| 105 | // summary: |
---|
| 106 | // Scroll the passed node into view, if it is not. |
---|
| 107 | // |
---|
| 108 | // node: |
---|
| 109 | // The id of the node, or the node itself, to move the mouse to. |
---|
| 110 | // If you pass an id or a function that returns a node, the node will not be evaluated until the movement executes. |
---|
| 111 | // This is useful if you need to move the mouse to an node that is not yet present. |
---|
| 112 | // |
---|
| 113 | // delay: |
---|
| 114 | // Delay, in milliseconds, to wait before firing. |
---|
| 115 | // The delay is a delta with respect to the previous automation call. |
---|
| 116 | // |
---|
| 117 | doh.robot.sequence(function(){ |
---|
| 118 | doh.robot._scrollIntoView(doh.robot._resolveNode(node)); |
---|
| 119 | }, delay); |
---|
| 120 | }, |
---|
| 121 | |
---|
| 122 | mouseMoveAt : function(/*String||DOMNode||Function*/ node, /*Integer, optional*/ delay, /*Integer, optional*/ duration, /*Number, optional*/ offsetX, /*Number, optional*/ offsetY){ |
---|
| 123 | // summary: |
---|
| 124 | // Moves the mouse over the specified node at the specified relative x,y offset. |
---|
| 125 | // |
---|
| 126 | // description: |
---|
| 127 | // Moves the mouse over the specified node at the specified relative x,y offset. |
---|
| 128 | // If you do not specify an offset, mouseMove will default to move to the middle of the node. |
---|
| 129 | // Example: to move the mouse over a ComboBox's down arrow node, call doh.mouseMoveAt(dijit.byId('setvaluetest').downArrowNode); |
---|
| 130 | // |
---|
| 131 | // node: |
---|
| 132 | // The id of the node, or the node itself, to move the mouse to. |
---|
| 133 | // If you pass an id or a function that returns a node, the node will not be evaluated until the movement executes. |
---|
| 134 | // This is useful if you need to move the mouse to an node that is not yet present. |
---|
| 135 | // |
---|
| 136 | // delay: |
---|
| 137 | // Delay, in milliseconds, to wait before firing. |
---|
| 138 | // The delay is a delta with respect to the previous automation call. |
---|
| 139 | // For example, the following code ends after 600ms: |
---|
| 140 | // doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms |
---|
| 141 | // doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all |
---|
| 142 | // |
---|
| 143 | // duration: |
---|
| 144 | // Approximate time Robot will spend moving the mouse |
---|
| 145 | // The default is 100ms. |
---|
| 146 | // |
---|
| 147 | // offsetX: |
---|
| 148 | // x offset relative to the node, in pixels, to move the mouse. The default is half the node's width. |
---|
| 149 | // |
---|
| 150 | // offsetY: |
---|
| 151 | // y offset relative to the node, in pixels, to move the mouse. The default is half the node's height. |
---|
| 152 | // |
---|
| 153 | |
---|
| 154 | doh.robot._assertRobot(); |
---|
| 155 | duration = duration||100; |
---|
| 156 | this.sequence(function(){ |
---|
| 157 | node=doh.robot._resolveNode(node); |
---|
| 158 | doh.robot._scrollIntoView(node); |
---|
| 159 | var pos = doh.robot._position(node); |
---|
| 160 | if(offsetY === undefined){ |
---|
| 161 | offsetX=pos.w/2; |
---|
| 162 | offsetY=pos.h/2; |
---|
| 163 | } |
---|
| 164 | var x = pos.x+offsetX; |
---|
| 165 | var y = pos.y+offsetY; |
---|
| 166 | doh.robot._mouseMove(x, y, false, duration); |
---|
| 167 | }, delay, duration); |
---|
| 168 | } |
---|
| 169 | }); |
---|
| 170 | |
---|
| 171 | return doh.robot; |
---|
| 172 | }); |
---|