Mercurial > hg > cmmr2012-drupal-site
comparison vendor/jcalderonzumba/gastonjs/src/Client/browser.js @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | 5311817fb629 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
1 var __indexOf = [].indexOf || function (item) { | |
2 for (var i = 0, l = this.length; i < l; i++) { | |
3 if (i in this && this[i] === item) return i; | |
4 } | |
5 return -1; | |
6 }; | |
7 | |
8 var xpathStringLiteral = function (s) { | |
9 if (s.indexOf('"') === -1) | |
10 return '"' + s + '"'; | |
11 if (s.indexOf("'") === -1) | |
12 return "'" + s + "'"; | |
13 return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")'; | |
14 }; | |
15 | |
16 Poltergeist.Browser = (function () { | |
17 /** | |
18 * Creates the "browser" inside phantomjs | |
19 * @param owner | |
20 * @param width | |
21 * @param height | |
22 * @param jsErrors | |
23 * @constructor | |
24 */ | |
25 function Browser(owner, width, height, jsErrors) { | |
26 this.owner = owner; | |
27 this.width = width || 1024; | |
28 this.height = height || 768; | |
29 this.pages = []; | |
30 this.js_errors = (typeof jsErrors === 'boolean') ? jsErrors : true; | |
31 this._debug = false; | |
32 this._counter = 0; | |
33 this.resetPage(); | |
34 } | |
35 | |
36 /** | |
37 * Resets the browser to a clean slate | |
38 * @return {Function} | |
39 */ | |
40 Browser.prototype.resetPage = function () { | |
41 var _ref; | |
42 var self = this; | |
43 | |
44 _ref = [0, []]; | |
45 this._counter = _ref[0]; | |
46 this.pages = _ref[1]; | |
47 | |
48 if (this.page != null) { | |
49 if (!this.page.closed) { | |
50 if (this.page.currentUrl() !== 'about:blank') { | |
51 this.page.clearLocalStorage(); | |
52 } | |
53 this.page.release(); | |
54 } | |
55 phantom.clearCookies(); | |
56 } | |
57 | |
58 this.page = this.currentPage = new Poltergeist.WebPage; | |
59 this.page.setViewportSize({ | |
60 width: this.width, | |
61 height: this.height | |
62 }); | |
63 this.page.handle = "" + (this._counter++); | |
64 this.pages.push(this.page); | |
65 | |
66 return this.page.onPageCreated = function (newPage) { | |
67 var page; | |
68 page = new Poltergeist.WebPage(newPage); | |
69 page.handle = "" + (self._counter++); | |
70 return self.pages.push(page); | |
71 }; | |
72 }; | |
73 | |
74 /** | |
75 * Given a page handle id, tries to get it from the browser page list | |
76 * @param handle | |
77 * @return {WebPage} | |
78 */ | |
79 Browser.prototype.getPageByHandle = function (handle) { | |
80 var filteredPages; | |
81 | |
82 //TODO: perhaps we should throw a PageNotFoundByHandle or something like that.. | |
83 if (handle === null || typeof handle == "undefined") { | |
84 return null; | |
85 } | |
86 | |
87 filteredPages = this.pages.filter(function (p) { | |
88 return !p.closed && p.handle === handle; | |
89 }); | |
90 | |
91 if (filteredPages.length === 1) { | |
92 return filteredPages[0]; | |
93 } | |
94 | |
95 return null; | |
96 }; | |
97 | |
98 /** | |
99 * Sends a debug message to the console | |
100 * @param message | |
101 * @return {*} | |
102 */ | |
103 Browser.prototype.debug = function (message) { | |
104 if (this._debug) { | |
105 return console.log("poltergeist [" + (new Date().getTime()) + "] " + message); | |
106 } | |
107 }; | |
108 | |
109 /** | |
110 * Given a page_id and id, gets if possible the node in such page | |
111 * @param page_id | |
112 * @param id | |
113 * @return {Poltergeist.Node} | |
114 */ | |
115 Browser.prototype.node = function (page_id, id) { | |
116 if (this.currentPage.id === page_id) { | |
117 return this.currentPage.get(id); | |
118 } else { | |
119 throw new Poltergeist.ObsoleteNode; | |
120 } | |
121 }; | |
122 | |
123 /** | |
124 * Returns the frameUrl related to the frame given by name | |
125 * @param frame_name | |
126 * @return {*} | |
127 */ | |
128 Browser.prototype.frameUrl = function (frame_name) { | |
129 return this.currentPage.frameUrl(frame_name); | |
130 }; | |
131 | |
132 /** | |
133 * This method defines the rectangular area of the web page to be rasterized when render is invoked. | |
134 * If no clipping rectangle is set, render will process the entire web page. | |
135 * @param full | |
136 * @param selector | |
137 * @return {*} | |
138 */ | |
139 Browser.prototype.set_clip_rect = function (full, selector) { | |
140 var dimensions, clipDocument, rect, clipViewport; | |
141 | |
142 dimensions = this.currentPage.validatedDimensions(); | |
143 clipDocument = dimensions.document; | |
144 clipViewport = dimensions.viewport; | |
145 | |
146 if (full) { | |
147 rect = { | |
148 left: 0, | |
149 top: 0, | |
150 width: clipDocument.width, | |
151 height: clipDocument.height | |
152 }; | |
153 } else { | |
154 if (selector != null) { | |
155 rect = this.currentPage.elementBounds(selector); | |
156 } else { | |
157 rect = { | |
158 left: 0, | |
159 top: 0, | |
160 width: clipViewport.width, | |
161 height: clipViewport.height | |
162 }; | |
163 } | |
164 } | |
165 | |
166 this.currentPage.setClipRect(rect); | |
167 return dimensions; | |
168 }; | |
169 | |
170 /** | |
171 * Kill the browser, i.e kill phantomjs current process | |
172 * @return {int} | |
173 */ | |
174 Browser.prototype.exit = function () { | |
175 return phantom.exit(0); | |
176 }; | |
177 | |
178 /** | |
179 * Do nothing | |
180 */ | |
181 Browser.prototype.noop = function () { | |
182 }; | |
183 | |
184 /** | |
185 * Throws a new Object error | |
186 */ | |
187 Browser.prototype.browser_error = function () { | |
188 throw new Error('zomg'); | |
189 }; | |
190 | |
191 /** | |
192 * Visits a page and load its content | |
193 * @param serverResponse | |
194 * @param url | |
195 * @return {*} | |
196 */ | |
197 Browser.prototype.visit = function (serverResponse, url) { | |
198 var prevUrl; | |
199 var self = this; | |
200 this.currentPage.state = 'loading'; | |
201 prevUrl = this.currentPage.source === null ? 'about:blank' : this.currentPage.currentUrl(); | |
202 this.currentPage.open(url); | |
203 if (/#/.test(url) && prevUrl.split('#')[0] === url.split('#')[0]) { | |
204 this.currentPage.state = 'default'; | |
205 return this.serverSendResponse({ | |
206 status: 'success' | |
207 }, serverResponse); | |
208 } else { | |
209 return this.currentPage.waitState('default', function () { | |
210 if (self.currentPage.statusCode === null && self.currentPage.status === 'fail') { | |
211 return self.owner.serverSendError(new Poltergeist.StatusFailError, serverResponse); | |
212 } else { | |
213 return self.serverSendResponse({ | |
214 status: self.currentPage.status | |
215 }, serverResponse); | |
216 } | |
217 }); | |
218 } | |
219 }; | |
220 | |
221 /** | |
222 * Puts the control of the browser inside the IFRAME given by name | |
223 * @param serverResponse | |
224 * @param name | |
225 * @param timeout | |
226 * @return {*} | |
227 */ | |
228 Browser.prototype.push_frame = function (serverResponse, name, timeout) { | |
229 var _ref; | |
230 var self = this; | |
231 | |
232 if (timeout == null) { | |
233 timeout = new Date().getTime() + 2000; | |
234 } | |
235 | |
236 //TODO: WTF, else if after a if with return COMMON | |
237 if (_ref = this.frameUrl(name), __indexOf.call(this.currentPage.blockedUrls(), _ref) >= 0) { | |
238 return this.serverSendResponse(true, serverResponse); | |
239 } else if (this.currentPage.pushFrame(name)) { | |
240 if (this.currentPage.currentUrl() === 'about:blank') { | |
241 this.currentPage.state = 'awaiting_frame_load'; | |
242 return this.currentPage.waitState('default', function () { | |
243 return self.serverSendResponse(true, serverResponse); | |
244 }); | |
245 } else { | |
246 return this.serverSendResponse(true, serverResponse); | |
247 } | |
248 } else { | |
249 if (new Date().getTime() < timeout) { | |
250 return setTimeout((function () { | |
251 return self.push_frame(serverResponse, name, timeout); | |
252 }), 50); | |
253 } else { | |
254 return this.owner.serverSendError(new Poltergeist.FrameNotFound(name), serverResponse); | |
255 } | |
256 } | |
257 }; | |
258 | |
259 /** | |
260 * Injects a javascript into the current page | |
261 * @param serverResponse | |
262 * @param extension | |
263 * @return {*} | |
264 */ | |
265 Browser.prototype.add_extension = function (serverResponse, extension) { | |
266 //TODO: error control when the injection was not possible | |
267 this.currentPage.injectExtension(extension); | |
268 return this.serverSendResponse('success', serverResponse); | |
269 }; | |
270 | |
271 /** | |
272 * Returns the url we are currently in | |
273 * @param serverResponse | |
274 * @return {*} | |
275 */ | |
276 Browser.prototype.current_url = function (serverResponse) { | |
277 return this.serverSendResponse(this.currentPage.currentUrl(), serverResponse); | |
278 }; | |
279 | |
280 /** | |
281 * Returns the current page window name | |
282 * @param serverResponse | |
283 * @returns {*} | |
284 */ | |
285 Browser.prototype.window_name = function (serverResponse) { | |
286 return this.serverSendResponse(this.currentPage.windowName(), serverResponse); | |
287 }; | |
288 | |
289 /** | |
290 * Returns the status code associated to the page | |
291 * @param serverResponse | |
292 * @return {*} | |
293 */ | |
294 Browser.prototype.status_code = function (serverResponse) { | |
295 if (this.currentPage.statusCode === undefined || this.currentPage.statusCode === null) { | |
296 return this.owner.serverSendError(new Poltergeist.StatusFailError("status_code_error"), serverResponse); | |
297 } | |
298 return this.serverSendResponse(this.currentPage.statusCode, serverResponse); | |
299 }; | |
300 | |
301 /** | |
302 * Returns the source code of the active frame, useful for when inside an IFRAME | |
303 * @param serverResponse | |
304 * @return {*} | |
305 */ | |
306 Browser.prototype.body = function (serverResponse) { | |
307 return this.serverSendResponse(this.currentPage.content(), serverResponse); | |
308 }; | |
309 | |
310 /** | |
311 * Returns the source code of the page all the html | |
312 * @param serverResponse | |
313 * @return {*} | |
314 */ | |
315 Browser.prototype.source = function (serverResponse) { | |
316 return this.serverSendResponse(this.currentPage.source, serverResponse); | |
317 }; | |
318 | |
319 /** | |
320 * Returns the current page title | |
321 * @param serverResponse | |
322 * @return {*} | |
323 */ | |
324 Browser.prototype.title = function (serverResponse) { | |
325 return this.serverSendResponse(this.currentPage.title(), serverResponse); | |
326 }; | |
327 | |
328 /** | |
329 * Finds the elements that match a method of selection and a selector | |
330 * @param serverResponse | |
331 * @param method | |
332 * @param selector | |
333 * @return {*} | |
334 */ | |
335 Browser.prototype.find = function (serverResponse, method, selector) { | |
336 return this.serverSendResponse({ | |
337 page_id: this.currentPage.id, | |
338 ids: this.currentPage.find(method, selector) | |
339 }, serverResponse); | |
340 }; | |
341 | |
342 /** | |
343 * Find elements within a given element | |
344 * @param serverResponse | |
345 * @param page_id | |
346 * @param id | |
347 * @param method | |
348 * @param selector | |
349 * @return {*} | |
350 */ | |
351 Browser.prototype.find_within = function (serverResponse, page_id, id, method, selector) { | |
352 return this.serverSendResponse(this.node(page_id, id).find(method, selector), serverResponse); | |
353 }; | |
354 | |
355 /** | |
356 * Returns ALL the text, visible and not visible from the given element | |
357 * @param serverResponse | |
358 * @param page_id | |
359 * @param id | |
360 * @return {*} | |
361 */ | |
362 Browser.prototype.all_text = function (serverResponse, page_id, id) { | |
363 return this.serverSendResponse(this.node(page_id, id).allText(), serverResponse); | |
364 }; | |
365 | |
366 /** | |
367 * Returns the inner or outer html of a given id | |
368 * @param serverResponse | |
369 * @param page_id | |
370 * @param id | |
371 * @param type | |
372 * @returns Object | |
373 */ | |
374 Browser.prototype.all_html = function (serverResponse, page_id, id, type) { | |
375 return this.serverSendResponse(this.node(page_id, id).allHTML(type), serverResponse); | |
376 }; | |
377 | |
378 /** | |
379 * Returns only the visible text in a given element | |
380 * @param serverResponse | |
381 * @param page_id | |
382 * @param id | |
383 * @return {*} | |
384 */ | |
385 Browser.prototype.visible_text = function (serverResponse, page_id, id) { | |
386 return this.serverSendResponse(this.node(page_id, id).visibleText(), serverResponse); | |
387 }; | |
388 | |
389 /** | |
390 * Deletes the text in a given element leaving it empty | |
391 * @param serverResponse | |
392 * @param page_id | |
393 * @param id | |
394 * @return {*} | |
395 */ | |
396 Browser.prototype.delete_text = function (serverResponse, page_id, id) { | |
397 return this.serverSendResponse(this.node(page_id, id).deleteText(), serverResponse); | |
398 }; | |
399 | |
400 /** | |
401 * Gets the value of a given attribute in an element | |
402 * @param serverResponse | |
403 * @param page_id | |
404 * @param id | |
405 * @param name | |
406 * @return {*} | |
407 */ | |
408 Browser.prototype.attribute = function (serverResponse, page_id, id, name) { | |
409 return this.serverSendResponse(this.node(page_id, id).getAttribute(name), serverResponse); | |
410 }; | |
411 | |
412 /** | |
413 * Allows the possibility to set an attribute on a given element | |
414 * @param serverResponse | |
415 * @param page_id | |
416 * @param id | |
417 * @param name | |
418 * @param value | |
419 * @returns {*} | |
420 */ | |
421 Browser.prototype.set_attribute = function (serverResponse, page_id, id, name, value) { | |
422 return this.serverSendResponse(this.node(page_id, id).setAttribute(name, value), serverResponse); | |
423 }; | |
424 | |
425 /** | |
426 * Allows the possibility to remove an attribute on a given element | |
427 * @param serverResponse | |
428 * @param page_id | |
429 * @param id | |
430 * @param name | |
431 * @returns {*} | |
432 */ | |
433 Browser.prototype.remove_attribute = function (serverResponse, page_id, id, name) { | |
434 return this.serverSendResponse(this.node(page_id, id).removeAttribute(name), serverResponse); | |
435 }; | |
436 | |
437 /** | |
438 * Returns all the attributes of a given element | |
439 * @param serverResponse | |
440 * @param page_id | |
441 * @param id | |
442 * @param name | |
443 * @return {*} | |
444 */ | |
445 Browser.prototype.attributes = function (serverResponse, page_id, id, name) { | |
446 return this.serverSendResponse(this.node(page_id, id).getAttributes(), serverResponse); | |
447 }; | |
448 | |
449 /** | |
450 * Returns all the way to the document level the parents of a given element | |
451 * @param serverResponse | |
452 * @param page_id | |
453 * @param id | |
454 * @return {*} | |
455 */ | |
456 Browser.prototype.parents = function (serverResponse, page_id, id) { | |
457 return this.serverSendResponse(this.node(page_id, id).parentIds(), serverResponse); | |
458 }; | |
459 | |
460 /** | |
461 * Returns the element.value of an element given by its page and id | |
462 * @param serverResponse | |
463 * @param page_id | |
464 * @param id | |
465 * @return {*} | |
466 */ | |
467 Browser.prototype.value = function (serverResponse, page_id, id) { | |
468 return this.serverSendResponse(this.node(page_id, id).value(), serverResponse); | |
469 }; | |
470 | |
471 /** | |
472 * Sets the element.value of an element by the given value | |
473 * @param serverResponse | |
474 * @param page_id | |
475 * @param id | |
476 * @param value | |
477 * @return {*} | |
478 */ | |
479 Browser.prototype.set = function (serverResponse, page_id, id, value) { | |
480 this.node(page_id, id).set(value); | |
481 return this.serverSendResponse(true, serverResponse); | |
482 }; | |
483 | |
484 /** | |
485 * Uploads a file to an input file element | |
486 * @param serverResponse | |
487 * @param page_id | |
488 * @param id | |
489 * @param file_path | |
490 * @return {*} | |
491 */ | |
492 Browser.prototype.select_file = function (serverResponse, page_id, id, file_path) { | |
493 var node = this.node(page_id, id); | |
494 | |
495 this.currentPage.beforeUpload(node.id); | |
496 this.currentPage.uploadFile('[_poltergeist_selected]', file_path); | |
497 this.currentPage.afterUpload(node.id); | |
498 | |
499 return this.serverSendResponse(true, serverResponse); | |
500 }; | |
501 | |
502 /** | |
503 * Sets a value to the selected element (to be used in select elements) | |
504 * @param serverResponse | |
505 * @param page_id | |
506 * @param id | |
507 * @param value | |
508 * @return {*} | |
509 */ | |
510 Browser.prototype.select = function (serverResponse, page_id, id, value) { | |
511 return this.serverSendResponse(this.node(page_id, id).select(value), serverResponse); | |
512 }; | |
513 | |
514 /** | |
515 * Selects an option with the given value | |
516 * @param serverResponse | |
517 * @param page_id | |
518 * @param id | |
519 * @param value | |
520 * @param multiple | |
521 * @return {*} | |
522 */ | |
523 Browser.prototype.select_option = function (serverResponse, page_id, id, value, multiple) { | |
524 return this.serverSendResponse(this.node(page_id, id).select_option(value, multiple), serverResponse); | |
525 }; | |
526 | |
527 /** | |
528 * | |
529 * @param serverResponse | |
530 * @param page_id | |
531 * @param id | |
532 * @return {*} | |
533 */ | |
534 Browser.prototype.tag_name = function (serverResponse, page_id, id) { | |
535 return this.serverSendResponse(this.node(page_id, id).tagName(), serverResponse); | |
536 }; | |
537 | |
538 | |
539 /** | |
540 * Tells if an element is visible or not | |
541 * @param serverResponse | |
542 * @param page_id | |
543 * @param id | |
544 * @return {*} | |
545 */ | |
546 Browser.prototype.visible = function (serverResponse, page_id, id) { | |
547 return this.serverSendResponse(this.node(page_id, id).isVisible(), serverResponse); | |
548 }; | |
549 | |
550 /** | |
551 * Tells if an element is disabled | |
552 * @param serverResponse | |
553 * @param page_id | |
554 * @param id | |
555 * @return {*} | |
556 */ | |
557 Browser.prototype.disabled = function (serverResponse, page_id, id) { | |
558 return this.serverSendResponse(this.node(page_id, id).isDisabled(), serverResponse); | |
559 }; | |
560 | |
561 /** | |
562 * Evaluates a javascript and returns the outcome to the client | |
563 * This will be JSON response so your script better be returning objects that can be used | |
564 * in JSON.stringify | |
565 * @param serverResponse | |
566 * @param script | |
567 * @return {*} | |
568 */ | |
569 Browser.prototype.evaluate = function (serverResponse, script) { | |
570 return this.serverSendResponse(this.currentPage.evaluate("function() { return " + script + " }"), serverResponse); | |
571 }; | |
572 | |
573 /** | |
574 * Executes a javascript and goes back to the client with true if there were no errors | |
575 * @param serverResponse | |
576 * @param script | |
577 * @return {*} | |
578 */ | |
579 Browser.prototype.execute = function (serverResponse, script) { | |
580 this.currentPage.execute("function() { " + script + " }"); | |
581 return this.serverSendResponse(true, serverResponse); | |
582 }; | |
583 | |
584 /** | |
585 * If inside a frame then we will go back to the parent | |
586 * Not defined behaviour if you pop and are not inside an iframe | |
587 * @param serverResponse | |
588 * @return {*} | |
589 */ | |
590 Browser.prototype.pop_frame = function (serverResponse) { | |
591 return this.serverSendResponse(this.currentPage.popFrame(), serverResponse); | |
592 }; | |
593 | |
594 /** | |
595 * Gets the window handle id by a given window name | |
596 * @param serverResponse | |
597 * @param name | |
598 * @return {*} | |
599 */ | |
600 Browser.prototype.window_handle = function (serverResponse, name) { | |
601 var handle, pageByWindowName; | |
602 | |
603 if (name === null || typeof name == "undefined" || name.length === 0) { | |
604 return this.serverSendResponse(this.currentPage.handle, serverResponse); | |
605 } | |
606 | |
607 handle = null; | |
608 | |
609 //Lets search the handle by the given window name | |
610 var filteredPages = this.pages.filter(function (p) { | |
611 return !p.closed && p.windowName() === name; | |
612 }); | |
613 | |
614 //A bit of error control is always good | |
615 if (Array.isArray(filteredPages) && filteredPages.length >= 1) { | |
616 pageByWindowName = filteredPages[0]; | |
617 } else { | |
618 pageByWindowName = null; | |
619 } | |
620 | |
621 if (pageByWindowName !== null && typeof pageByWindowName != "undefined") { | |
622 handle = pageByWindowName.handle; | |
623 } | |
624 | |
625 return this.serverSendResponse(handle, serverResponse); | |
626 }; | |
627 | |
628 /** | |
629 * Returns all the window handles of opened windows | |
630 * @param serverResponse | |
631 * @return {*} | |
632 */ | |
633 Browser.prototype.window_handles = function (serverResponse) { | |
634 var handles, filteredPages; | |
635 | |
636 filteredPages = this.pages.filter(function (p) { | |
637 return !p.closed; | |
638 }); | |
639 | |
640 if (filteredPages.length > 0) { | |
641 handles = filteredPages.map(function (p) { | |
642 return p.handle; | |
643 }); | |
644 if (handles.length === 0) { | |
645 handles = null; | |
646 } | |
647 } else { | |
648 handles = null; | |
649 } | |
650 | |
651 return this.serverSendResponse(handles, serverResponse); | |
652 }; | |
653 | |
654 /** | |
655 * Tries to switch to a window given by the handle id | |
656 * @param serverResponse | |
657 * @param handle | |
658 * @return {*} | |
659 */ | |
660 Browser.prototype.switch_to_window = function (serverResponse, handle) { | |
661 var page; | |
662 var self = this; | |
663 | |
664 page = this.getPageByHandle(handle); | |
665 if (page === null || typeof page == "undefined") { | |
666 throw new Poltergeist.NoSuchWindowError; | |
667 } | |
668 | |
669 if (page !== this.currentPage) { | |
670 return page.waitState('default', function () { | |
671 self.currentPage = page; | |
672 return self.serverSendResponse(true, serverResponse); | |
673 }); | |
674 } | |
675 | |
676 return this.serverSendResponse(true, serverResponse); | |
677 }; | |
678 | |
679 /** | |
680 * Opens a new window where we can do stuff | |
681 * @param serverResponse | |
682 * @return {*} | |
683 */ | |
684 Browser.prototype.open_new_window = function (serverResponse) { | |
685 return this.execute(serverResponse, 'window.open()'); | |
686 }; | |
687 | |
688 /** | |
689 * Closes the window given by handle name if possible | |
690 * @param serverResponse | |
691 * @param handle | |
692 * @return {*} | |
693 */ | |
694 Browser.prototype.close_window = function (serverResponse, handle) { | |
695 var page; | |
696 | |
697 page = this.getPageByHandle(handle); | |
698 if (page === null || typeof page == "undefined") { | |
699 //TODO: should we throw error since we actually could not find the window? | |
700 return this.serverSendResponse(false, serverResponse); | |
701 } | |
702 | |
703 //TODO: we have to add some control here to actually asses that the release has been done | |
704 page.release(); | |
705 return this.serverSendResponse(true, serverResponse); | |
706 }; | |
707 | |
708 /** | |
709 * Generic mouse event on an element | |
710 * @param serverResponse | |
711 * @param page_id | |
712 * @param id | |
713 * @param name | |
714 * @return {number} | |
715 */ | |
716 Browser.prototype.mouse_event = function (serverResponse, page_id, id, name) { | |
717 var node; | |
718 var self = this; | |
719 node = this.node(page_id, id); | |
720 this.currentPage.state = 'mouse_event'; | |
721 this.last_mouse_event = node.mouseEvent(name); | |
722 return setTimeout(function () { | |
723 if (self.currentPage.state === 'mouse_event') { | |
724 self.currentPage.state = 'default'; | |
725 return self.serverSendResponse({ | |
726 position: self.last_mouse_event | |
727 }, serverResponse); | |
728 } else { | |
729 return self.currentPage.waitState('default', function () { | |
730 return self.serverSendResponse({ | |
731 position: self.last_mouse_event | |
732 }, serverResponse); | |
733 }); | |
734 } | |
735 }, 5); | |
736 }; | |
737 | |
738 /** | |
739 * Simple click on the element | |
740 * @param serverResponse | |
741 * @param page_id | |
742 * @param id | |
743 * @return {*} | |
744 */ | |
745 Browser.prototype.click = function (serverResponse, page_id, id) { | |
746 return this.mouse_event(serverResponse, page_id, id, 'click'); | |
747 }; | |
748 | |
749 /** | |
750 * Right click on the element | |
751 * @param serverResponse | |
752 * @param page_id | |
753 * @param id | |
754 * @return {*} | |
755 */ | |
756 Browser.prototype.right_click = function (serverResponse, page_id, id) { | |
757 return this.mouse_event(serverResponse, page_id, id, 'rightclick'); | |
758 }; | |
759 | |
760 /** | |
761 * Double click on the element given by page and id | |
762 * @param serverResponse | |
763 * @param page_id | |
764 * @param id | |
765 * @return {*} | |
766 */ | |
767 Browser.prototype.double_click = function (serverResponse, page_id, id) { | |
768 return this.mouse_event(serverResponse, page_id, id, 'doubleclick'); | |
769 }; | |
770 | |
771 /** | |
772 * Executes a mousemove event on the page and given element | |
773 * @param serverResponse | |
774 * @param page_id | |
775 * @param id | |
776 * @return {*} | |
777 */ | |
778 Browser.prototype.hover = function (serverResponse, page_id, id) { | |
779 return this.mouse_event(serverResponse, page_id, id, 'mousemove'); | |
780 }; | |
781 | |
782 /** | |
783 * Triggers a mouse click event on the given coordinates | |
784 * @param serverResponse | |
785 * @param x | |
786 * @param y | |
787 * @return {*} | |
788 */ | |
789 Browser.prototype.click_coordinates = function (serverResponse, x, y) { | |
790 var response; | |
791 | |
792 this.currentPage.sendEvent('click', x, y); | |
793 response = { | |
794 click: { | |
795 x: x, | |
796 y: y | |
797 } | |
798 }; | |
799 | |
800 return this.serverSendResponse(response, serverResponse); | |
801 }; | |
802 | |
803 /** | |
804 * Drags one element into another, useful for nice javascript thingies | |
805 * @param serverResponse | |
806 * @param page_id | |
807 * @param id | |
808 * @param other_id | |
809 * @return {*} | |
810 */ | |
811 Browser.prototype.drag = function (serverResponse, page_id, id, other_id) { | |
812 this.node(page_id, id).dragTo(this.node(page_id, other_id)); | |
813 return this.serverSendResponse(true, serverResponse); | |
814 }; | |
815 | |
816 /** | |
817 * Triggers an event on the given page and element | |
818 * @param serverResponse | |
819 * @param page_id | |
820 * @param id | |
821 * @param event | |
822 * @return {*} | |
823 */ | |
824 Browser.prototype.trigger = function (serverResponse, page_id, id, event) { | |
825 this.node(page_id, id).trigger(event); | |
826 return this.serverSendResponse(event, serverResponse); | |
827 }; | |
828 | |
829 /** | |
830 * Checks if two elements are equal on a dom level | |
831 * @param serverResponse | |
832 * @param page_id | |
833 * @param id | |
834 * @param other_id | |
835 * @return {*} | |
836 */ | |
837 Browser.prototype.equals = function (serverResponse, page_id, id, other_id) { | |
838 return this.serverSendResponse(this.node(page_id, id).isEqual(this.node(page_id, other_id)), serverResponse); | |
839 }; | |
840 | |
841 /** | |
842 * Resets the current page to a clean slate | |
843 * @param serverResponse | |
844 * @return {*} | |
845 */ | |
846 Browser.prototype.reset = function (serverResponse) { | |
847 this.resetPage(); | |
848 return this.serverSendResponse(true, serverResponse); | |
849 }; | |
850 | |
851 /** | |
852 * Scrolls to a position given by the left, top coordinates | |
853 * @param serverResponse | |
854 * @param left | |
855 * @param top | |
856 * @return {*} | |
857 */ | |
858 Browser.prototype.scroll_to = function (serverResponse, left, top) { | |
859 this.currentPage.setScrollPosition({ | |
860 left: left, | |
861 top: top | |
862 }); | |
863 return this.serverSendResponse(true, serverResponse); | |
864 }; | |
865 | |
866 /** | |
867 * Sends keys to an element simulating as closest as possible what a user would do | |
868 * when typing | |
869 * @param serverResponse | |
870 * @param page_id | |
871 * @param id | |
872 * @param keys | |
873 * @return {*} | |
874 */ | |
875 Browser.prototype.send_keys = function (serverResponse, page_id, id, keys) { | |
876 var key, sequence, target, _i, _len; | |
877 target = this.node(page_id, id); | |
878 if (!target.containsSelection()) { | |
879 target.mouseEvent('click'); | |
880 } | |
881 for (_i = 0, _len = keys.length; _i < _len; _i++) { | |
882 sequence = keys[_i]; | |
883 key = sequence.key != null ? this.currentPage.keyCode(sequence.key) : sequence; | |
884 this.currentPage.sendEvent('keypress', key); | |
885 } | |
886 return this.serverSendResponse(true, serverResponse); | |
887 }; | |
888 | |
889 /** | |
890 * Sends a native phantomjs key event to element | |
891 * @param serverResponse | |
892 * @param page_id | |
893 * @param id | |
894 * @param keyEvent | |
895 * @param key | |
896 * @param modifier | |
897 */ | |
898 Browser.prototype.key_event = function (serverResponse, page_id, id, keyEvent, key, modifier) { | |
899 var keyEventModifierMap; | |
900 var keyEventModifier; | |
901 var target; | |
902 | |
903 keyEventModifierMap = { | |
904 'none': 0x0, | |
905 'shift': 0x02000000, | |
906 'ctrl': 0x04000000, | |
907 'alt': 0x08000000, | |
908 'meta': 0x10000000 | |
909 }; | |
910 keyEventModifier = keyEventModifierMap[modifier]; | |
911 | |
912 target = this.node(page_id, id); | |
913 if (!target.containsSelection()) { | |
914 target.mouseEvent('click'); | |
915 } | |
916 target.page.sendEvent(keyEvent, key, null, null, keyEventModifier); | |
917 | |
918 return this.serverSendResponse(true, serverResponse); | |
919 }; | |
920 | |
921 /** | |
922 * Sends the rendered page in a base64 encoding | |
923 * @param serverResponse | |
924 * @param format | |
925 * @param full | |
926 * @param selector | |
927 * @return {*} | |
928 */ | |
929 Browser.prototype.render_base64 = function (serverResponse, format, full, selector) { | |
930 var encoded_image; | |
931 if (selector == null) { | |
932 selector = null; | |
933 } | |
934 this.set_clip_rect(full, selector); | |
935 encoded_image = this.currentPage.renderBase64(format); | |
936 return this.serverSendResponse(encoded_image, serverResponse); | |
937 }; | |
938 | |
939 /** | |
940 * Renders the current page entirely or a given selection | |
941 * @param serverResponse | |
942 * @param path | |
943 * @param full | |
944 * @param selector | |
945 * @return {*} | |
946 */ | |
947 Browser.prototype.render = function (serverResponse, path, full, selector) { | |
948 var dimensions; | |
949 if (selector == null) { | |
950 selector = null; | |
951 } | |
952 dimensions = this.set_clip_rect(full, selector); | |
953 this.currentPage.setScrollPosition({ | |
954 left: 0, | |
955 top: 0 | |
956 }); | |
957 this.currentPage.render(path); | |
958 this.currentPage.setScrollPosition({ | |
959 left: dimensions.left, | |
960 top: dimensions.top | |
961 }); | |
962 return this.serverSendResponse(true, serverResponse); | |
963 }; | |
964 | |
965 | |
966 /** | |
967 * Sets the paper size, useful when printing to PDF | |
968 * @param serverResponse | |
969 * @param size | |
970 * @return {*} | |
971 */ | |
972 Browser.prototype.set_paper_size = function (serverResponse, size) { | |
973 this.currentPage.setPaperSize(size); | |
974 return this.serverSendResponse(true, serverResponse); | |
975 }; | |
976 | |
977 /** | |
978 * Sets the zoom factor on the current page | |
979 * @param serverResponse | |
980 * @param zoom_factor | |
981 * @return {*} | |
982 */ | |
983 Browser.prototype.set_zoom_factor = function (serverResponse, zoom_factor) { | |
984 this.currentPage.setZoomFactor(zoom_factor); | |
985 return this.serverSendResponse(true, serverResponse); | |
986 }; | |
987 | |
988 /** | |
989 * Resizes the browser viewport, useful when testing mobile stuff | |
990 * @param serverResponse | |
991 * @param width | |
992 * @param height | |
993 * @return {*} | |
994 */ | |
995 Browser.prototype.resize = function (serverResponse, width, height) { | |
996 this.currentPage.setViewportSize({ | |
997 width: width, | |
998 height: height | |
999 }); | |
1000 return this.serverSendResponse(true, serverResponse); | |
1001 }; | |
1002 | |
1003 /** | |
1004 * Gets the browser viewport size | |
1005 * Because PhantomJS is headless (nothing is shown) | |
1006 * viewportSize effectively simulates the size of the window like in a traditional browser. | |
1007 * @param serverResponse | |
1008 * @param handle | |
1009 * @return {*} | |
1010 */ | |
1011 Browser.prototype.window_size = function (serverResponse, handle) { | |
1012 //TODO: add support for window handles | |
1013 return this.serverSendResponse(this.currentPage.viewportSize(), serverResponse); | |
1014 }; | |
1015 | |
1016 /** | |
1017 * Returns the network traffic that the current page has generated | |
1018 * @param serverResponse | |
1019 * @return {*} | |
1020 */ | |
1021 Browser.prototype.network_traffic = function (serverResponse) { | |
1022 return this.serverSendResponse(this.currentPage.networkTraffic(), serverResponse); | |
1023 }; | |
1024 | |
1025 /** | |
1026 * Clears the accumulated network_traffic in the current page | |
1027 * @param serverResponse | |
1028 * @return {*} | |
1029 */ | |
1030 Browser.prototype.clear_network_traffic = function (serverResponse) { | |
1031 this.currentPage.clearNetworkTraffic(); | |
1032 return this.serverSendResponse(true, serverResponse); | |
1033 }; | |
1034 | |
1035 /** | |
1036 * Gets the headers of the current page | |
1037 * @param serverResponse | |
1038 * @return {*} | |
1039 */ | |
1040 Browser.prototype.get_headers = function (serverResponse) { | |
1041 return this.serverSendResponse(this.currentPage.getCustomHeaders(), serverResponse); | |
1042 }; | |
1043 | |
1044 /** | |
1045 * Set headers in the browser | |
1046 * @param serverResponse | |
1047 * @param headers | |
1048 * @return {*} | |
1049 */ | |
1050 Browser.prototype.set_headers = function (serverResponse, headers) { | |
1051 if (headers['User-Agent']) { | |
1052 this.currentPage.setUserAgent(headers['User-Agent']); | |
1053 } | |
1054 this.currentPage.setCustomHeaders(headers); | |
1055 return this.serverSendResponse(true, serverResponse); | |
1056 }; | |
1057 | |
1058 /** | |
1059 * Given an array of headers, adds them to the page | |
1060 * @param serverResponse | |
1061 * @param headers | |
1062 * @return {*} | |
1063 */ | |
1064 Browser.prototype.add_headers = function (serverResponse, headers) { | |
1065 var allHeaders, name, value; | |
1066 allHeaders = this.currentPage.getCustomHeaders(); | |
1067 for (name in headers) { | |
1068 if (headers.hasOwnProperty(name)) { | |
1069 value = headers[name]; | |
1070 allHeaders[name] = value; | |
1071 } | |
1072 } | |
1073 return this.set_headers(serverResponse, allHeaders); | |
1074 }; | |
1075 | |
1076 /** | |
1077 * Adds a header to the page temporary or permanently | |
1078 * @param serverResponse | |
1079 * @param header | |
1080 * @param permanent | |
1081 * @return {*} | |
1082 */ | |
1083 Browser.prototype.add_header = function (serverResponse, header, permanent) { | |
1084 if (!permanent) { | |
1085 this.currentPage.addTempHeader(header); | |
1086 } | |
1087 return this.add_headers(serverResponse, header); | |
1088 }; | |
1089 | |
1090 | |
1091 /** | |
1092 * Sends back the client the response headers sent from the browser when making | |
1093 * the page request | |
1094 * @param serverResponse | |
1095 * @return {*} | |
1096 */ | |
1097 Browser.prototype.response_headers = function (serverResponse) { | |
1098 return this.serverSendResponse(this.currentPage.responseHeaders(), serverResponse); | |
1099 }; | |
1100 | |
1101 /** | |
1102 * Returns the cookies of the current page being browsed | |
1103 * @param serverResponse | |
1104 * @return {*} | |
1105 */ | |
1106 Browser.prototype.cookies = function (serverResponse) { | |
1107 return this.serverSendResponse(this.currentPage.cookies(), serverResponse); | |
1108 }; | |
1109 | |
1110 /** | |
1111 * Sets a cookie in the browser, the format of the cookies has to be the format it says | |
1112 * on phantomjs documentation and as such you can set it in other domains, not on the | |
1113 * current page | |
1114 * @param serverResponse | |
1115 * @param cookie | |
1116 * @return {*} | |
1117 */ | |
1118 Browser.prototype.set_cookie = function (serverResponse, cookie) { | |
1119 return this.serverSendResponse(phantom.addCookie(cookie), serverResponse); | |
1120 }; | |
1121 | |
1122 /** | |
1123 * Remove a cookie set on the current page | |
1124 * @param serverResponse | |
1125 * @param name | |
1126 * @return {*} | |
1127 */ | |
1128 Browser.prototype.remove_cookie = function (serverResponse, name) { | |
1129 //TODO: add error control to check if the cookie was properly deleted | |
1130 this.currentPage.deleteCookie(name); | |
1131 phantom.deleteCookie(name); | |
1132 return this.serverSendResponse(true, serverResponse); | |
1133 }; | |
1134 | |
1135 /** | |
1136 * Clear the cookies in the browser | |
1137 * @param serverResponse | |
1138 * @return {*} | |
1139 */ | |
1140 Browser.prototype.clear_cookies = function (serverResponse) { | |
1141 phantom.clearCookies(); | |
1142 return this.serverSendResponse(true, serverResponse); | |
1143 }; | |
1144 | |
1145 /** | |
1146 * Enables / Disables the cookies on the browser | |
1147 * @param serverResponse | |
1148 * @param flag | |
1149 * @return {*} | |
1150 */ | |
1151 Browser.prototype.cookies_enabled = function (serverResponse, flag) { | |
1152 phantom.cookiesEnabled = flag; | |
1153 return this.serverSendResponse(true, serverResponse); | |
1154 }; | |
1155 | |
1156 /** | |
1157 * US19: DONE | |
1158 * Sets a basic authentication credential to access a page | |
1159 * THIS SHOULD BE USED BEFORE accessing a page | |
1160 * @param serverResponse | |
1161 * @param user | |
1162 * @param password | |
1163 * @return {*} | |
1164 */ | |
1165 Browser.prototype.set_http_auth = function (serverResponse, user, password) { | |
1166 this.currentPage.setHttpAuth(user, password); | |
1167 return this.serverSendResponse(true, serverResponse); | |
1168 }; | |
1169 | |
1170 /** | |
1171 * Sets the flag whether to fail on javascript errors or not. | |
1172 * @param serverResponse | |
1173 * @param value | |
1174 * @return {*} | |
1175 */ | |
1176 Browser.prototype.set_js_errors = function (serverResponse, value) { | |
1177 this.js_errors = value; | |
1178 return this.serverSendResponse(true, serverResponse); | |
1179 }; | |
1180 | |
1181 /** | |
1182 * Sets the debug mode to boolean value | |
1183 * @param serverResponse | |
1184 * @param value | |
1185 * @return {*} | |
1186 */ | |
1187 Browser.prototype.set_debug = function (serverResponse, value) { | |
1188 this._debug = value; | |
1189 return this.serverSendResponse(true, serverResponse); | |
1190 }; | |
1191 | |
1192 /** | |
1193 * Goes back in the history when possible | |
1194 * @param serverResponse | |
1195 * @return {*} | |
1196 */ | |
1197 Browser.prototype.go_back = function (serverResponse) { | |
1198 var self = this; | |
1199 if (this.currentPage.canGoBack()) { | |
1200 this.currentPage.state = 'loading'; | |
1201 this.currentPage.goBack(); | |
1202 return this.currentPage.waitState('default', function () { | |
1203 return self.serverSendResponse(true, serverResponse); | |
1204 }); | |
1205 } else { | |
1206 return this.serverSendResponse(false, serverResponse); | |
1207 } | |
1208 }; | |
1209 | |
1210 /** | |
1211 * Reloads the page if possible | |
1212 * @return {*} | |
1213 */ | |
1214 Browser.prototype.reload = function (serverResponse) { | |
1215 var self = this; | |
1216 this.currentPage.state = 'loading'; | |
1217 this.currentPage.reload(); | |
1218 return this.currentPage.waitState('default', function () { | |
1219 return self.serverSendResponse(true, serverResponse); | |
1220 }); | |
1221 }; | |
1222 | |
1223 /** | |
1224 * Goes forward in the browser history if possible | |
1225 * @param serverResponse | |
1226 * @return {*} | |
1227 */ | |
1228 Browser.prototype.go_forward = function (serverResponse) { | |
1229 var self = this; | |
1230 if (this.currentPage.canGoForward()) { | |
1231 this.currentPage.state = 'loading'; | |
1232 this.currentPage.goForward(); | |
1233 return this.currentPage.waitState('default', function () { | |
1234 return self.serverSendResponse(true, serverResponse); | |
1235 }); | |
1236 } else { | |
1237 return this.serverSendResponse(false, serverResponse); | |
1238 } | |
1239 }; | |
1240 | |
1241 /** | |
1242 * Sets the urlBlacklist for the given urls as parameters | |
1243 * @return {boolean} | |
1244 */ | |
1245 Browser.prototype.set_url_blacklist = function (serverResponse, blackList) { | |
1246 this.currentPage.urlBlacklist = Array.prototype.slice.call(blackList); | |
1247 return this.serverSendResponse(true, serverResponse); | |
1248 }; | |
1249 | |
1250 /** | |
1251 * Runs a browser command and returns the response back to the client | |
1252 * when the command has finished the execution | |
1253 * @param command | |
1254 * @param serverResponse | |
1255 * @return {*} | |
1256 */ | |
1257 Browser.prototype.serverRunCommand = function (command, serverResponse) { | |
1258 var commandData; | |
1259 var commandArgs; | |
1260 var commandName; | |
1261 | |
1262 commandName = command.name; | |
1263 commandArgs = command.args; | |
1264 this.currentPage.state = 'default'; | |
1265 commandData = [serverResponse].concat(commandArgs); | |
1266 | |
1267 if (typeof this[commandName] !== "function") { | |
1268 //We can not run such command | |
1269 throw new Poltergeist.Error(); | |
1270 } | |
1271 | |
1272 return this[commandName].apply(this, commandData); | |
1273 }; | |
1274 | |
1275 /** | |
1276 * Sends a response back to the client who made the request | |
1277 * @param response | |
1278 * @param serverResponse | |
1279 * @return {*} | |
1280 */ | |
1281 Browser.prototype.serverSendResponse = function (response, serverResponse) { | |
1282 var errors; | |
1283 errors = this.currentPage.errors; | |
1284 this.currentPage.clearErrors(); | |
1285 if (errors.length > 0 && this.js_errors) { | |
1286 return this.owner.serverSendError(new Poltergeist.JavascriptError(errors), serverResponse); | |
1287 } else { | |
1288 return this.owner.serverSendResponse(response, serverResponse); | |
1289 } | |
1290 }; | |
1291 | |
1292 return Browser; | |
1293 | |
1294 })(); |