1 | dojo.provide("dojox.robot.recorder"); |
---|
2 | dojo.experimental("dojox.robot.recorder"); |
---|
3 | // summary: |
---|
4 | // Generates a doh test as you interact with a Web page. |
---|
5 | // To record a test, click inside the document body and press CTRL-ALT-ENTER. |
---|
6 | // To finish recording a test and to display the autogenerated code, press CTRL-ALT-ENTER again. |
---|
7 | // |
---|
8 | |
---|
9 | |
---|
10 | (function(){ |
---|
11 | |
---|
12 | // CONSTANTS |
---|
13 | |
---|
14 | // consolidate keypresses into one typeKeys if they occur within 1 second of each other |
---|
15 | var KEYPRESS_MAXIMUM_DELAY = 1000; |
---|
16 | |
---|
17 | // consolidate mouse movements if they occur within .5 seconds of each other |
---|
18 | var MOUSEMOVE_MAXIMUM_DELAY = 500; |
---|
19 | |
---|
20 | // absolute longest wait between commands |
---|
21 | // anything longer gets chopped to 10 |
---|
22 | var MAXIMUM_DELAY = 10000; |
---|
23 | |
---|
24 | // stack of commands recorded from dojo.connects |
---|
25 | var commands = []; |
---|
26 | |
---|
27 | // number to write next to test name |
---|
28 | // goes up after each recording |
---|
29 | var testNumber = 0; |
---|
30 | |
---|
31 | // time user started test |
---|
32 | var startTime = null; |
---|
33 | |
---|
34 | // time since last user input |
---|
35 | // robot commands work on deltas |
---|
36 | var prevTime = null; |
---|
37 | |
---|
38 | var start = function(){ |
---|
39 | // summary: |
---|
40 | // Starts recording the user's input. |
---|
41 | // |
---|
42 | alert("Started recording."); |
---|
43 | commands = []; |
---|
44 | startTime = new Date(); |
---|
45 | prevTime = new Date(); |
---|
46 | } |
---|
47 | |
---|
48 | var addCommand = function(name, args){ |
---|
49 | // summary: |
---|
50 | // Add a command to the stack. |
---|
51 | // |
---|
52 | // name: |
---|
53 | // doh.robot function to call. |
---|
54 | // |
---|
55 | // args: |
---|
56 | // arguments array to pass to the doh.robot |
---|
57 | // |
---|
58 | |
---|
59 | // omit start/stop record |
---|
60 | if(startTime == null |
---|
61 | || name=="doh.robot.keyPress" |
---|
62 | && args[0]==dojo.keys.ENTER |
---|
63 | && eval("("+args[2]+")").ctrl |
---|
64 | && eval("("+args[2]+")").alt){ return; } |
---|
65 | var dt = Math.max(Math.min(Math.round((new Date()).getTime() - prevTime.getTime()),MAXIMUM_DELAY),1); |
---|
66 | // add in dt |
---|
67 | // is usually args[1] but there are exceptions |
---|
68 | if(name == "doh.robot.mouseMove"){ |
---|
69 | args[2]=dt; |
---|
70 | }else{ |
---|
71 | args[1]=dt; |
---|
72 | } |
---|
73 | commands.push({name:name,args:args}); |
---|
74 | prevTime = new Date(); |
---|
75 | } |
---|
76 | |
---|
77 | var _optimize = function(){ |
---|
78 | // make the stack more human-readable and remove any odditites |
---|
79 | var c = commands; |
---|
80 | |
---|
81 | // INITIAL OPTIMIZATIONS |
---|
82 | // remove starting ENTER press |
---|
83 | if(c[0].name == "doh.robot.keyPress" |
---|
84 | && (c[0].args[0] == dojo.keys.ENTER || c[0].args[0] == 77)){ |
---|
85 | c.splice(0,1); |
---|
86 | } |
---|
87 | // remove ending CTRL + ALT keypresses in IE |
---|
88 | for(var i = c.length-1; (i >= c.length-2) && (i>=0); i-- ){ |
---|
89 | if(c[i].name == "doh.robot.keyPress" |
---|
90 | && c[i].args[0]==dojo.keys.ALT || c[i].args[0]==dojo.keys.CTRL){ |
---|
91 | c.splice(i,1); |
---|
92 | } |
---|
93 | } |
---|
94 | // ITERATIVE OPTIMIZATIONS |
---|
95 | for(i = 0; i<c.length; i++){ |
---|
96 | var next, nextdt; |
---|
97 | if(c[i+1] |
---|
98 | && c[i].name=="doh.robot.mouseMove" |
---|
99 | && c[i+1].name==c[i].name |
---|
100 | && c[i+1].args[2]<MOUSEMOVE_MAXIMUM_DELAY){ |
---|
101 | // mouse movement optimization |
---|
102 | // if the movement is temporally close, collapse it |
---|
103 | // example: mouseMove(a,b,delay 5)+mouseMove(x,y,delay 10)+mousePress(delay 1) becomes mouseMove(x,y,delay 5)+mousePress(delay 11) |
---|
104 | // expected pattern: |
---|
105 | // c[i]: mouseMove |
---|
106 | // c[i+1]: mouseMove |
---|
107 | // ... |
---|
108 | // c[i+n-1]: last mouseMove |
---|
109 | // c[i+n]: something else |
---|
110 | // result: |
---|
111 | // c[i]: last mouseMove |
---|
112 | // c[i+1]: something else |
---|
113 | // the c[i] mouse location changes to move to c[i+n-1]'s location, c[i+n] gains c[i+1]+c[i+2]+...c[i+n-1] delay so the timing is the same |
---|
114 | |
---|
115 | next = c[i+1]; |
---|
116 | nextdt = 0; |
---|
117 | while(next |
---|
118 | && next.name==c[i].name |
---|
119 | && next.args[2]<MOUSEMOVE_MAXIMUM_DELAY){ |
---|
120 | // cut out next |
---|
121 | c.splice(i + 1,1); |
---|
122 | // add next's delay to the total |
---|
123 | nextdt += next.args[2]; |
---|
124 | // move to next mouse position |
---|
125 | c[i].args[0]=next.args[0]; |
---|
126 | c[i].args[1]=next.args[1]; |
---|
127 | next = c[i+1]; |
---|
128 | } |
---|
129 | // make the total delay the duration |
---|
130 | c[i].args[3]=nextdt; |
---|
131 | }else if(c[i+1] |
---|
132 | && c[i].name=="doh.robot.mouseWheel" |
---|
133 | && c[i+1].name==c[i].name |
---|
134 | && c[i+1].args[1]<MOUSEMOVE_MAXIMUM_DELAY){ |
---|
135 | // mouse wheel optimization |
---|
136 | // if the movement is temporally close, collapse it |
---|
137 | // example: mouseWheel(1,delay 5)+mouseWheel(-2,delay 10) becomes mouseWheel(-1,delay 5, speed 10) |
---|
138 | // expected pattern: |
---|
139 | // c[i]: mouseWheel |
---|
140 | |
---|
141 | // c[i+1]: mouseWheel |
---|
142 | // ... |
---|
143 | // c[i+n-1]: last mouseWheel |
---|
144 | // c[i+n]: something else |
---|
145 | // result: |
---|
146 | // c[i]: mouseWheel |
---|
147 | // c[i+1]: something else |
---|
148 | |
---|
149 | next = c[i+1]; |
---|
150 | nextdt = 0; |
---|
151 | while(next |
---|
152 | && next.name==c[i].name |
---|
153 | && next.args[1]<MOUSEMOVE_MAXIMUM_DELAY){ |
---|
154 | // cut out next |
---|
155 | c.splice(i + 1, 1); |
---|
156 | // add next's delay to the total |
---|
157 | nextdt += next.args[1]; |
---|
158 | // add in wheel amount |
---|
159 | c[i].args[0]+=next.args[0]; |
---|
160 | next = c[i+1]; |
---|
161 | } |
---|
162 | // make the total delay the duration |
---|
163 | c[i].args[2]=nextdt; |
---|
164 | }else if(c[i + 2] |
---|
165 | && c[i].name=="doh.robot.mouseMoveAt" |
---|
166 | && c[i+2].name=="doh.robot.scrollIntoView"){ |
---|
167 | // swap scrollIntoView of widget and mouseMoveAt |
---|
168 | // the recorder traps scrollIntoView after the mouse click registers, but in playback, it is better to go the other way |
---|
169 | // expected pattern: |
---|
170 | // c[i]: mouseMoveAt |
---|
171 | // c[i+1]: mousePress |
---|
172 | // c[i+2]: scrollIntoView |
---|
173 | // result: |
---|
174 | // c[i]: scrollIntoView |
---|
175 | // c[i+1]: mouseMoveAt |
---|
176 | // c[i+2]: mousePress |
---|
177 | var temp = c.splice(i+2,1)[0]; |
---|
178 | c.splice(i,0,temp); |
---|
179 | }else if(c[i + 1] |
---|
180 | && c[i].name=="doh.robot.mousePress" |
---|
181 | && c[i+1].name=="doh.robot.mouseRelease" |
---|
182 | && c[i].args[0]==c[i+1].args[0]){ |
---|
183 | // convert mousePress+mouseRelease to mouseClick |
---|
184 | // expected pattern: |
---|
185 | // c[i]: mousePress |
---|
186 | // c[i+1]: mouseRelease |
---|
187 | // mouse buttons are the same |
---|
188 | c[i].name = "doh.robot.mouseClick"; |
---|
189 | // delete extra mouseRelease |
---|
190 | c.splice(i + 1,1); |
---|
191 | // if this was already a mouse click, get rid of the next (dup) one |
---|
192 | if(c[i+1] && c[i+1].name == "doh.robot.mouseClick" && c[i].args[0] == c[i+1].args[0]){ |
---|
193 | c.splice(i + 1, 1); |
---|
194 | } |
---|
195 | }else if(c[i + 1] |
---|
196 | && c[i - 1] |
---|
197 | && c[i - 1].name=="doh.robot.mouseMoveAt" |
---|
198 | && c[i].name=="doh.robot.mousePress" |
---|
199 | && c[i+1].name=="doh.robot.mouseMove"){ |
---|
200 | // convert mouseMoveAt+mousePress+mouseMove to mouseMoveAt+mousePress+mouseMoveAt+mouseMove |
---|
201 | // this is to kick off dojo.dnd by moving the mouse 1 px |
---|
202 | // expected pattern: |
---|
203 | // c[i-1]: mouseMoveAt |
---|
204 | // c[i]: mousePress |
---|
205 | // c[i+1]: mouseMove |
---|
206 | |
---|
207 | // insert new mouseMoveAt, 1px to the right |
---|
208 | var cmd={name:"doh.robot.mouseMoveAt",args:[c[i-1].args[0], 1, 100, c[i-1].args[3]+1,c[i-1].args[4]]}; |
---|
209 | c.splice(i+1,0,cmd); |
---|
210 | }else if(c[i + 1] |
---|
211 | && ((c[i].name=="doh.robot.keyPress" |
---|
212 | && typeof c[i].args[0] =="string") |
---|
213 | || c[i].name=="doh.robot.typeKeys") |
---|
214 | && c[i+1].name=="doh.robot.keyPress" |
---|
215 | && typeof c[i+1].args[0] =="string" |
---|
216 | && c[i+1].args[1]<=KEYPRESS_MAXIMUM_DELAY |
---|
217 | && !eval("("+c[i].args[2]+")").ctrl |
---|
218 | && !eval("("+c[i].args[2]+")").alt |
---|
219 | && !eval("("+c[i+1].args[2]+")").ctrl |
---|
220 | && !eval("("+c[i+1].args[2]+")").alt){ |
---|
221 | // convert keyPress+keyPress+... to typeKeys |
---|
222 | // expected pattern: |
---|
223 | // c[i]: keyPress(a) |
---|
224 | // c[i+1]: keyPress(b) |
---|
225 | // ... |
---|
226 | // c[i+n-1]: last keyPress(z) |
---|
227 | // c[i+n]: something else |
---|
228 | // result: |
---|
229 | // c[i]: typeKeys(ab...z) |
---|
230 | // c[i+1]: something else |
---|
231 | // note: does not convert alt or ctrl keypresses, and does not convert non-character keypresses like enter |
---|
232 | c[i].name = "doh.robot.typeKeys"; |
---|
233 | c[i].args.splice(3,1); |
---|
234 | next = c[i+1]; |
---|
235 | var typeTime = 0; |
---|
236 | while(next |
---|
237 | && next.name == "doh.robot.keyPress" |
---|
238 | && typeof next.args[0] =="string" |
---|
239 | && next.args[1]<=KEYPRESS_MAXIMUM_DELAY |
---|
240 | && !eval("("+next.args[2]+")").ctrl |
---|
241 | && !eval("("+next.args[2]+")").alt){ |
---|
242 | c.splice(i + 1,1); |
---|
243 | c[i].args[0] += next.args[0]; |
---|
244 | typeTime += next.args[1]; |
---|
245 | next = c[i+1]; |
---|
246 | } |
---|
247 | // set the duration to the total type time |
---|
248 | c[i].args[2] = typeTime; |
---|
249 | // wrap string in quotes |
---|
250 | c[i].args[0] = "'"+c[i].args[0]+"'"; |
---|
251 | }else if(c[i].name == "doh.robot.keyPress"){ |
---|
252 | // take care of standalone keypresses |
---|
253 | // characters should be wrapped in quotes. |
---|
254 | // non-characters should be replaced with their corresponding dojo.keys constant |
---|
255 | if(typeof c[i].args[0] == "string"){ |
---|
256 | // one keypress of a character by itself should be wrapped in quotes |
---|
257 | c[i].args[0] = "'"+c[i].args[0]+"'"; |
---|
258 | }else{ |
---|
259 | if(c[i].args[0]==0){ |
---|
260 | // toss null keypresses |
---|
261 | c.splice(i,1); |
---|
262 | }else{ |
---|
263 | // look up dojo.keys.constant if possible |
---|
264 | for(var j in dojo.keys){ |
---|
265 | if(dojo.keys[j] == c[i].args[0]){ |
---|
266 | c[i].args[0] = "dojo.keys."+j; |
---|
267 | break; |
---|
268 | } |
---|
269 | } |
---|
270 | } |
---|
271 | } |
---|
272 | } |
---|
273 | } |
---|
274 | } |
---|
275 | |
---|
276 | var toggle = function(){ |
---|
277 | // summary: |
---|
278 | // Toggles recording the user's input. |
---|
279 | // Hotkey: CTRL- ALT-ENTER |
---|
280 | // |
---|
281 | if(!startTime){ start(); } |
---|
282 | else{ stop(); } |
---|
283 | } |
---|
284 | |
---|
285 | var stop = function(){ |
---|
286 | // summary: |
---|
287 | // Stops recording the user's input, |
---|
288 | // and displays the generated code. |
---|
289 | // |
---|
290 | |
---|
291 | var dt = Math.round((new Date()).getTime() - startTime.getTime()); |
---|
292 | startTime = null; |
---|
293 | _optimize(); |
---|
294 | var c = commands; |
---|
295 | console.log("Stop called. Commands: " + c.length); |
---|
296 | if(c.length){ |
---|
297 | var s = "doh.register('dojox.robot.AutoGeneratedTestGroup',{\n"; |
---|
298 | s += " name: 'autotest" + (testNumber++)+"',\n"; |
---|
299 | s += " timeout: " + (dt+2000)+",\n"; |
---|
300 | s += " runTest: function(){\n"; |
---|
301 | s += " var d = new doh.Deferred();\n"; |
---|
302 | for(var i = 0; i<c.length; i++){ |
---|
303 | s += " "+c[i].name+"("; |
---|
304 | for(var j = 0; j<c[i].args.length; j++){ |
---|
305 | var arg = c[i].args[j]; |
---|
306 | s += arg; |
---|
307 | if(j != c[i].args.length-1){ s += ", "; } |
---|
308 | } |
---|
309 | s += ");\n"; |
---|
310 | } |
---|
311 | s += " doh.robot.sequence(function(){\n"; |
---|
312 | s += " if(/*Your condition here*/){\n"; |
---|
313 | s += " d.callback(true);\n"; |
---|
314 | s += " }else{\n"; |
---|
315 | s += " d.errback(new Error('We got a failure'));\n"; |
---|
316 | s += " }\n"; |
---|
317 | s += " }, 1000);\n"; |
---|
318 | s += " return d;\n"; |
---|
319 | s += " }\n"; |
---|
320 | s += "});\n"; |
---|
321 | var div = document.createElement('div'); |
---|
322 | div.id="dojox.robot.recorder"; |
---|
323 | div.style.backgroundColor = "white"; |
---|
324 | div.style.position = "absolute"; |
---|
325 | var scroll = {y: (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0), |
---|
326 | x: (window.pageXOffset || (window["dojo"]?dojo._fixIeBiDiScrollLeft(document.documentElement.scrollLeft):undefined) || document.body.scrollLeft || 0)}; |
---|
327 | div.style.left = scroll.x+"px"; |
---|
328 | div.style.top = scroll.y+"px"; |
---|
329 | var h1 = document.createElement('h1'); |
---|
330 | h1.innerHTML = "Your code:"; |
---|
331 | div.appendChild(h1); |
---|
332 | var pre = document.createElement('pre'); |
---|
333 | if(pre.innerText !== undefined){ |
---|
334 | pre.innerText = s; |
---|
335 | }else{ |
---|
336 | pre.textContent = s; |
---|
337 | } |
---|
338 | div.appendChild(pre); |
---|
339 | var button = document.createElement('button'); |
---|
340 | button.innerHTML = "Close"; |
---|
341 | var connect = dojo.connect(button,'onmouseup',function(e){ |
---|
342 | dojo.stopEvent(e); |
---|
343 | document.body.removeChild(div); |
---|
344 | dojo.disconnect(connect); |
---|
345 | }); |
---|
346 | div.appendChild(button); |
---|
347 | document.body.appendChild(div); |
---|
348 | commands = []; |
---|
349 | } |
---|
350 | } |
---|
351 | |
---|
352 | var getSelector = function(node){ |
---|
353 | // Selenium/Windmill recorders have a concept of a "selector." |
---|
354 | // The idea is that recorders need some reference to an element that persists even after a page refresh. |
---|
355 | // For elements with ids, this is easy; just use the id. |
---|
356 | // For other elements, we have to be more sly. |
---|
357 | |
---|
358 | if(typeof node =="string"){ |
---|
359 | // it's already an id to be interpreted by dojo.byId |
---|
360 | return "'" + node+"'"; |
---|
361 | }else if(node.id){ |
---|
362 | // it has an id |
---|
363 | return "'" + node.id+"'"; |
---|
364 | }else{ |
---|
365 | // TODO: need a generic selector, like CSS3/dojo.query, for the default return value |
---|
366 | // for now, just do getElementsByTagName |
---|
367 | var nodes = document.getElementsByTagName(node.nodeName); |
---|
368 | var i; |
---|
369 | for(i = 0; i<nodes.length; i++){ |
---|
370 | if(nodes[i] == node){ |
---|
371 | break; |
---|
372 | } |
---|
373 | } |
---|
374 | // wrap in a function to defer evaluation |
---|
375 | return "function(){ return document.getElementsByTagName('" + node.nodeName+"')["+i+"]; }"; |
---|
376 | } |
---|
377 | } |
---|
378 | |
---|
379 | var getMouseButtonObject = function(b){ |
---|
380 | // convert native event to doh.robot API |
---|
381 | return "{left:" + (b==0)+", middle:" + (b==1)+", right:" + (b==2)+"}"; |
---|
382 | } |
---|
383 | |
---|
384 | |
---|
385 | var getModifierObject = function(e){ |
---|
386 | // convert native event to doh.robot API |
---|
387 | return "{'shift':" + (e.shiftKey)+", 'ctrl':" + (e.ctrlKey)+", 'alt':" + (e.altKey)+"}"; |
---|
388 | } |
---|
389 | |
---|
390 | // dojo.connects |
---|
391 | |
---|
392 | dojo.connect(document,"onkeydown",function(e){ |
---|
393 | // the CTRL- ALT-ENTER hotkey to activate the recorder |
---|
394 | //console.log(e.keyCode + ", " + e.ctrlKey+", " + e.altKey); |
---|
395 | if((e.keyCode == dojo.keys.ENTER || e.keyCode==77) && e.ctrlKey && e.altKey){ |
---|
396 | dojo.stopEvent(e); |
---|
397 | toggle(); |
---|
398 | } |
---|
399 | }); |
---|
400 | |
---|
401 | var lastEvent = {type:""}; |
---|
402 | |
---|
403 | var onmousedown = function(e){ |
---|
404 | // handler for mouse down |
---|
405 | if(!e || lastEvent.type==e.type && lastEvent.button==e.button){ return; } |
---|
406 | lastEvent={type:e.type, button:e.button}; |
---|
407 | var selector = getSelector(e.target); |
---|
408 | var coords = dojo.coords(e.target); |
---|
409 | addCommand("doh.robot.mouseMoveAt",[selector, 0, 100, e.clientX - coords.x, e.clientY-coords.y]); |
---|
410 | addCommand("doh.robot.mousePress",[getMouseButtonObject(e.button-(dojo.isIE?1:0)), 0]); |
---|
411 | }; |
---|
412 | |
---|
413 | var onclick = function(e){ |
---|
414 | // handler for mouse up |
---|
415 | if(!e || lastEvent.type==e.type && lastEvent.button==e.button){ return; } |
---|
416 | lastEvent={type:e.type, button:e.button}; |
---|
417 | var selector = getSelector(e.target); |
---|
418 | var coords = dojo.coords(e.target); |
---|
419 | addCommand("doh.robot.mouseClick",[getMouseButtonObject(e.button-(dojo.isIE?1:0)), 0]); |
---|
420 | }; |
---|
421 | |
---|
422 | var onmouseup = function(e){ |
---|
423 | // handler for mouse up |
---|
424 | if(!e || lastEvent.type==e.type && lastEvent.button==e.button){ return; } |
---|
425 | lastEvent={type:e.type, button:e.button}; |
---|
426 | var selector = getSelector(e.target); |
---|
427 | var coords = dojo.coords(e.target); |
---|
428 | addCommand("doh.robot.mouseRelease",[getMouseButtonObject(e.button-(dojo.isIE?1:0)), 0]); |
---|
429 | }; |
---|
430 | |
---|
431 | var onmousemove = function(e){ |
---|
432 | // handler for mouse move |
---|
433 | if(!e || lastEvent.type==e.type && lastEvent.pageX==e.pageX && lastEvent.pageY==e.pageY){ return; } |
---|
434 | lastEvent={type:e.type, pageX:e.pageX, pageY:e.pageY}; |
---|
435 | addCommand("doh.robot.mouseMove",[e.pageX, e.pageY, 0, 100, true]); |
---|
436 | }; |
---|
437 | |
---|
438 | var onmousewheel = function(e){ |
---|
439 | // handler for mouse move |
---|
440 | if(!e || lastEvent.type==e.type && lastEvent.pageX==e.pageX && lastEvent.pageY==e.pageY){ return; } |
---|
441 | lastEvent={type:e.type, detail:(e.detail ? (e.detail) : (-e.wheelDelta / 120))}; |
---|
442 | addCommand("doh.robot.mouseWheel",[lastEvent.detail]); |
---|
443 | }; |
---|
444 | |
---|
445 | var onkeypress = function(e){ |
---|
446 | // handler for key press |
---|
447 | if(!e || lastEvent.type==e.type && (lastEvent.charCode == e.charCode && lastEvent.keyCode == e.keyCode)){ return; } |
---|
448 | lastEvent={type:e.type, charCode:e.charCode, keyCode:e.keyCode}; |
---|
449 | addCommand("doh.robot.keyPress",[e.charOrCode==dojo.keys.SPACE?' ':e.charOrCode, 0, getModifierObject(e)]); |
---|
450 | }; |
---|
451 | |
---|
452 | var onkeyup = function(e){ |
---|
453 | if(!e || lastEvent.type==e.type && (lastEvent.charCode == e.charCode && lastEvent.keyCode == e.keyCode)){ return; } |
---|
454 | lastEvent={type:e.type, charCode:e.charCode, keyCode:e.keyCode}; |
---|
455 | } |
---|
456 | |
---|
457 | // trap all native elements' events |
---|
458 | dojo.connect(document,"onmousedown",onmousedown); |
---|
459 | dojo.connect(document,"onmouseup",onmouseup); |
---|
460 | dojo.connect(document,"onclick",onclick); |
---|
461 | dojo.connect(document,"onkeypress",onkeypress); |
---|
462 | dojo.connect(document,"onkeyup",onkeyup); |
---|
463 | dojo.connect(document,"onmousemove",onmousemove); |
---|
464 | dojo.connect(document,!dojo.isMozilla ? "onmousewheel" : 'DOMMouseScroll',onmousewheel); |
---|
465 | |
---|
466 | dojo.addOnLoad(function(){ |
---|
467 | // get scrollIntoView for good measure |
---|
468 | // catch: dojo.window might not be loaded (yet?) so addonload |
---|
469 | if(dojo.window){ |
---|
470 | dojo.connect(dojo.window,"scrollIntoView",function(node){ |
---|
471 | addCommand("doh.robot.scrollIntoView",[getSelector(node)]); |
---|
472 | }); |
---|
473 | } |
---|
474 | }); |
---|
475 | |
---|
476 | // Get Dojo widget events too! |
---|
477 | dojo.connect(dojo, "connect", |
---|
478 | function(/*dijit._Widget*/ widget, /*String*/ event, /*Function*/ f){ |
---|
479 | // kill recursion |
---|
480 | // check for private variable _mine to make sure this isn't a recursive loop |
---|
481 | if(widget && (!f || !f._mine)){ |
---|
482 | var hitchedf = null; |
---|
483 | if(event.toLowerCase() == "onmousedown"){ |
---|
484 | hitchedf = dojo.hitch(this,onmousedown); |
---|
485 | }else if(event.toLowerCase() == (!dojo.isMozilla ? "onmousewheel" : 'dommousescroll')){ |
---|
486 | hitchedf = dojo.hitch(this,onmousewheel); |
---|
487 | }else if(event.toLowerCase() == "onclick"){ |
---|
488 | hitchedf = dojo.hitch(this,onclick); |
---|
489 | }else if(event.toLowerCase() == "onmouseup"){ |
---|
490 | hitchedf = dojo.hitch(this,onmouseup); |
---|
491 | }else if(event.toLowerCase() == "onkeypress"){ |
---|
492 | hitchedf = dojo.hitch(this,onkeypress); |
---|
493 | }else if(event.toLowerCase() == "onkeyup"){ |
---|
494 | hitchedf = dojo.hitch(this,onkeyup); |
---|
495 | } |
---|
496 | if(hitchedf == null){ return; } |
---|
497 | hitchedf._mine = true; |
---|
498 | dojo.connect(widget,event,hitchedf); |
---|
499 | } |
---|
500 | }); |
---|
501 | })(); |
---|