source: Dev/trunk/src/client/dojo/robot.js @ 487

Last change on this file since 487 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

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