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;
8 var xpathStringLiteral = function (s) {
9 if (s.indexOf('"') === -1)
11 if (s.indexOf("'") === -1)
13 return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")';
16 Poltergeist.Browser = (function () {
18 * Creates the "browser" inside phantomjs
25 function Browser(owner, width, height, jsErrors) {
27 this.width = width || 1024;
28 this.height = height || 768;
30 this.js_errors = (typeof jsErrors === 'boolean') ? jsErrors : true;
37 * Resets the browser to a clean slate
40 Browser.prototype.resetPage = function () {
45 this._counter = _ref[0];
48 if (this.page != null) {
49 if (!this.page.closed) {
50 if (this.page.currentUrl() !== 'about:blank') {
51 this.page.clearLocalStorage();
55 phantom.clearCookies();
58 this.page = this.currentPage = new Poltergeist.WebPage;
59 this.page.setViewportSize({
63 this.page.handle = "" + (this._counter++);
64 this.pages.push(this.page);
66 return this.page.onPageCreated = function (newPage) {
68 page = new Poltergeist.WebPage(newPage);
69 page.handle = "" + (self._counter++);
70 return self.pages.push(page);
75 * Given a page handle id, tries to get it from the browser page list
79 Browser.prototype.getPageByHandle = function (handle) {
82 //TODO: perhaps we should throw a PageNotFoundByHandle or something like that..
83 if (handle === null || typeof handle == "undefined") {
87 filteredPages = this.pages.filter(function (p) {
88 return !p.closed && p.handle === handle;
91 if (filteredPages.length === 1) {
92 return filteredPages[0];
99 * Sends a debug message to the console
103 Browser.prototype.debug = function (message) {
105 return console.log("poltergeist [" + (new Date().getTime()) + "] " + message);
110 * Given a page_id and id, gets if possible the node in such page
113 * @return {Poltergeist.Node}
115 Browser.prototype.node = function (page_id, id) {
116 if (this.currentPage.id === page_id) {
117 return this.currentPage.get(id);
119 throw new Poltergeist.ObsoleteNode;
124 * Returns the frameUrl related to the frame given by name
128 Browser.prototype.frameUrl = function (frame_name) {
129 return this.currentPage.frameUrl(frame_name);
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.
139 Browser.prototype.set_clip_rect = function (full, selector) {
140 var dimensions, clipDocument, rect, clipViewport;
142 dimensions = this.currentPage.validatedDimensions();
143 clipDocument = dimensions.document;
144 clipViewport = dimensions.viewport;
150 width: clipDocument.width,
151 height: clipDocument.height
154 if (selector != null) {
155 rect = this.currentPage.elementBounds(selector);
160 width: clipViewport.width,
161 height: clipViewport.height
166 this.currentPage.setClipRect(rect);
171 * Kill the browser, i.e kill phantomjs current process
174 Browser.prototype.exit = function () {
175 return phantom.exit(0);
181 Browser.prototype.noop = function () {
185 * Throws a new Object error
187 Browser.prototype.browser_error = function () {
188 throw new Error('zomg');
192 * Visits a page and load its content
193 * @param serverResponse
197 Browser.prototype.visit = function (serverResponse, url) {
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({
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);
213 return self.serverSendResponse({
214 status: self.currentPage.status
222 * Puts the control of the browser inside the IFRAME given by name
223 * @param serverResponse
228 Browser.prototype.push_frame = function (serverResponse, name, timeout) {
232 if (timeout == null) {
233 timeout = new Date().getTime() + 2000;
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);
246 return this.serverSendResponse(true, serverResponse);
249 if (new Date().getTime() < timeout) {
250 return setTimeout((function () {
251 return self.push_frame(serverResponse, name, timeout);
254 return this.owner.serverSendError(new Poltergeist.FrameNotFound(name), serverResponse);
260 * Injects a javascript into the current page
261 * @param serverResponse
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);
272 * Returns the url we are currently in
273 * @param serverResponse
276 Browser.prototype.current_url = function (serverResponse) {
277 return this.serverSendResponse(this.currentPage.currentUrl(), serverResponse);
281 * Returns the current page window name
282 * @param serverResponse
285 Browser.prototype.window_name = function (serverResponse) {
286 return this.serverSendResponse(this.currentPage.windowName(), serverResponse);
290 * Returns the status code associated to the page
291 * @param serverResponse
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);
298 return this.serverSendResponse(this.currentPage.statusCode, serverResponse);
302 * Returns the source code of the active frame, useful for when inside an IFRAME
303 * @param serverResponse
306 Browser.prototype.body = function (serverResponse) {
307 return this.serverSendResponse(this.currentPage.content(), serverResponse);
311 * Returns the source code of the page all the html
312 * @param serverResponse
315 Browser.prototype.source = function (serverResponse) {
316 return this.serverSendResponse(this.currentPage.source, serverResponse);
320 * Returns the current page title
321 * @param serverResponse
324 Browser.prototype.title = function (serverResponse) {
325 return this.serverSendResponse(this.currentPage.title(), serverResponse);
329 * Finds the elements that match a method of selection and a selector
330 * @param serverResponse
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)
343 * Find elements within a given element
344 * @param serverResponse
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);
356 * Returns ALL the text, visible and not visible from the given element
357 * @param serverResponse
362 Browser.prototype.all_text = function (serverResponse, page_id, id) {
363 return this.serverSendResponse(this.node(page_id, id).allText(), serverResponse);
367 * Returns the inner or outer html of a given id
368 * @param serverResponse
374 Browser.prototype.all_html = function (serverResponse, page_id, id, type) {
375 return this.serverSendResponse(this.node(page_id, id).allHTML(type), serverResponse);
379 * Returns only the visible text in a given element
380 * @param serverResponse
385 Browser.prototype.visible_text = function (serverResponse, page_id, id) {
386 return this.serverSendResponse(this.node(page_id, id).visibleText(), serverResponse);
390 * Deletes the text in a given element leaving it empty
391 * @param serverResponse
396 Browser.prototype.delete_text = function (serverResponse, page_id, id) {
397 return this.serverSendResponse(this.node(page_id, id).deleteText(), serverResponse);
401 * Gets the value of a given attribute in an element
402 * @param serverResponse
408 Browser.prototype.attribute = function (serverResponse, page_id, id, name) {
409 return this.serverSendResponse(this.node(page_id, id).getAttribute(name), serverResponse);
413 * Allows the possibility to set an attribute on a given element
414 * @param serverResponse
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);
426 * Allows the possibility to remove an attribute on a given element
427 * @param serverResponse
433 Browser.prototype.remove_attribute = function (serverResponse, page_id, id, name) {
434 return this.serverSendResponse(this.node(page_id, id).removeAttribute(name), serverResponse);
438 * Returns all the attributes of a given element
439 * @param serverResponse
445 Browser.prototype.attributes = function (serverResponse, page_id, id, name) {
446 return this.serverSendResponse(this.node(page_id, id).getAttributes(), serverResponse);
450 * Returns all the way to the document level the parents of a given element
451 * @param serverResponse
456 Browser.prototype.parents = function (serverResponse, page_id, id) {
457 return this.serverSendResponse(this.node(page_id, id).parentIds(), serverResponse);
461 * Returns the element.value of an element given by its page and id
462 * @param serverResponse
467 Browser.prototype.value = function (serverResponse, page_id, id) {
468 return this.serverSendResponse(this.node(page_id, id).value(), serverResponse);
472 * Sets the element.value of an element by the given value
473 * @param serverResponse
479 Browser.prototype.set = function (serverResponse, page_id, id, value) {
480 this.node(page_id, id).set(value);
481 return this.serverSendResponse(true, serverResponse);
485 * Uploads a file to an input file element
486 * @param serverResponse
492 Browser.prototype.select_file = function (serverResponse, page_id, id, file_path) {
493 var node = this.node(page_id, id);
495 this.currentPage.beforeUpload(node.id);
496 this.currentPage.uploadFile('[_poltergeist_selected]', file_path);
497 this.currentPage.afterUpload(node.id);
499 return this.serverSendResponse(true, serverResponse);
503 * Sets a value to the selected element (to be used in select elements)
504 * @param serverResponse
510 Browser.prototype.select = function (serverResponse, page_id, id, value) {
511 return this.serverSendResponse(this.node(page_id, id).select(value), serverResponse);
515 * Selects an option with the given value
516 * @param serverResponse
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);
529 * @param serverResponse
534 Browser.prototype.tag_name = function (serverResponse, page_id, id) {
535 return this.serverSendResponse(this.node(page_id, id).tagName(), serverResponse);
540 * Tells if an element is visible or not
541 * @param serverResponse
546 Browser.prototype.visible = function (serverResponse, page_id, id) {
547 return this.serverSendResponse(this.node(page_id, id).isVisible(), serverResponse);
551 * Tells if an element is disabled
552 * @param serverResponse
557 Browser.prototype.disabled = function (serverResponse, page_id, id) {
558 return this.serverSendResponse(this.node(page_id, id).isDisabled(), serverResponse);
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
565 * @param serverResponse
569 Browser.prototype.evaluate = function (serverResponse, script) {
570 return this.serverSendResponse(this.currentPage.evaluate("function() { return " + script + " }"), serverResponse);
574 * Executes a javascript and goes back to the client with true if there were no errors
575 * @param serverResponse
579 Browser.prototype.execute = function (serverResponse, script) {
580 this.currentPage.execute("function() { " + script + " }");
581 return this.serverSendResponse(true, serverResponse);
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
590 Browser.prototype.pop_frame = function (serverResponse) {
591 return this.serverSendResponse(this.currentPage.popFrame(), serverResponse);
595 * Gets the window handle id by a given window name
596 * @param serverResponse
600 Browser.prototype.window_handle = function (serverResponse, name) {
601 var handle, pageByWindowName;
603 if (name === null || typeof name == "undefined" || name.length === 0) {
604 return this.serverSendResponse(this.currentPage.handle, serverResponse);
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;
614 //A bit of error control is always good
615 if (Array.isArray(filteredPages) && filteredPages.length >= 1) {
616 pageByWindowName = filteredPages[0];
618 pageByWindowName = null;
621 if (pageByWindowName !== null && typeof pageByWindowName != "undefined") {
622 handle = pageByWindowName.handle;
625 return this.serverSendResponse(handle, serverResponse);
629 * Returns all the window handles of opened windows
630 * @param serverResponse
633 Browser.prototype.window_handles = function (serverResponse) {
634 var handles, filteredPages;
636 filteredPages = this.pages.filter(function (p) {
640 if (filteredPages.length > 0) {
641 handles = filteredPages.map(function (p) {
644 if (handles.length === 0) {
651 return this.serverSendResponse(handles, serverResponse);
655 * Tries to switch to a window given by the handle id
656 * @param serverResponse
660 Browser.prototype.switch_to_window = function (serverResponse, handle) {
664 page = this.getPageByHandle(handle);
665 if (page === null || typeof page == "undefined") {
666 throw new Poltergeist.NoSuchWindowError;
669 if (page !== this.currentPage) {
670 return page.waitState('default', function () {
671 self.currentPage = page;
672 return self.serverSendResponse(true, serverResponse);
676 return this.serverSendResponse(true, serverResponse);
680 * Opens a new window where we can do stuff
681 * @param serverResponse
684 Browser.prototype.open_new_window = function (serverResponse) {
685 return this.execute(serverResponse, 'window.open()');
689 * Closes the window given by handle name if possible
690 * @param serverResponse
694 Browser.prototype.close_window = function (serverResponse, handle) {
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);
703 //TODO: we have to add some control here to actually asses that the release has been done
705 return this.serverSendResponse(true, serverResponse);
709 * Generic mouse event on an element
710 * @param serverResponse
716 Browser.prototype.mouse_event = function (serverResponse, page_id, id, name) {
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
729 return self.currentPage.waitState('default', function () {
730 return self.serverSendResponse({
731 position: self.last_mouse_event
739 * Simple click on the element
740 * @param serverResponse
745 Browser.prototype.click = function (serverResponse, page_id, id) {
746 return this.mouse_event(serverResponse, page_id, id, 'click');
750 * Right click on the element
751 * @param serverResponse
756 Browser.prototype.right_click = function (serverResponse, page_id, id) {
757 return this.mouse_event(serverResponse, page_id, id, 'rightclick');
761 * Double click on the element given by page and id
762 * @param serverResponse
767 Browser.prototype.double_click = function (serverResponse, page_id, id) {
768 return this.mouse_event(serverResponse, page_id, id, 'doubleclick');
772 * Executes a mousemove event on the page and given element
773 * @param serverResponse
778 Browser.prototype.hover = function (serverResponse, page_id, id) {
779 return this.mouse_event(serverResponse, page_id, id, 'mousemove');
783 * Triggers a mouse click event on the given coordinates
784 * @param serverResponse
789 Browser.prototype.click_coordinates = function (serverResponse, x, y) {
792 this.currentPage.sendEvent('click', x, y);
800 return this.serverSendResponse(response, serverResponse);
804 * Drags one element into another, useful for nice javascript thingies
805 * @param serverResponse
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);
817 * Triggers an event on the given page and element
818 * @param serverResponse
824 Browser.prototype.trigger = function (serverResponse, page_id, id, event) {
825 this.node(page_id, id).trigger(event);
826 return this.serverSendResponse(event, serverResponse);
830 * Checks if two elements are equal on a dom level
831 * @param serverResponse
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);
842 * Resets the current page to a clean slate
843 * @param serverResponse
846 Browser.prototype.reset = function (serverResponse) {
848 return this.serverSendResponse(true, serverResponse);
852 * Scrolls to a position given by the left, top coordinates
853 * @param serverResponse
858 Browser.prototype.scroll_to = function (serverResponse, left, top) {
859 this.currentPage.setScrollPosition({
863 return this.serverSendResponse(true, serverResponse);
867 * Sends keys to an element simulating as closest as possible what a user would do
869 * @param serverResponse
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');
881 for (_i = 0, _len = keys.length; _i < _len; _i++) {
883 key = sequence.key != null ? this.currentPage.keyCode(sequence.key) : sequence;
884 this.currentPage.sendEvent('keypress', key);
886 return this.serverSendResponse(true, serverResponse);
890 * Sends a native phantomjs key event to element
891 * @param serverResponse
898 Browser.prototype.key_event = function (serverResponse, page_id, id, keyEvent, key, modifier) {
899 var keyEventModifierMap;
900 var keyEventModifier;
903 keyEventModifierMap = {
910 keyEventModifier = keyEventModifierMap[modifier];
912 target = this.node(page_id, id);
913 if (!target.containsSelection()) {
914 target.mouseEvent('click');
916 target.page.sendEvent(keyEvent, key, null, null, keyEventModifier);
918 return this.serverSendResponse(true, serverResponse);
922 * Sends the rendered page in a base64 encoding
923 * @param serverResponse
929 Browser.prototype.render_base64 = function (serverResponse, format, full, selector) {
931 if (selector == null) {
934 this.set_clip_rect(full, selector);
935 encoded_image = this.currentPage.renderBase64(format);
936 return this.serverSendResponse(encoded_image, serverResponse);
940 * Renders the current page entirely or a given selection
941 * @param serverResponse
947 Browser.prototype.render = function (serverResponse, path, full, selector) {
949 if (selector == null) {
952 dimensions = this.set_clip_rect(full, selector);
953 this.currentPage.setScrollPosition({
957 this.currentPage.render(path);
958 this.currentPage.setScrollPosition({
959 left: dimensions.left,
962 return this.serverSendResponse(true, serverResponse);
967 * Sets the paper size, useful when printing to PDF
968 * @param serverResponse
972 Browser.prototype.set_paper_size = function (serverResponse, size) {
973 this.currentPage.setPaperSize(size);
974 return this.serverSendResponse(true, serverResponse);
978 * Sets the zoom factor on the current page
979 * @param serverResponse
983 Browser.prototype.set_zoom_factor = function (serverResponse, zoom_factor) {
984 this.currentPage.setZoomFactor(zoom_factor);
985 return this.serverSendResponse(true, serverResponse);
989 * Resizes the browser viewport, useful when testing mobile stuff
990 * @param serverResponse
995 Browser.prototype.resize = function (serverResponse, width, height) {
996 this.currentPage.setViewportSize({
1000 return this.serverSendResponse(true, serverResponse);
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
1011 Browser.prototype.window_size = function (serverResponse, handle) {
1012 //TODO: add support for window handles
1013 return this.serverSendResponse(this.currentPage.viewportSize(), serverResponse);
1017 * Returns the network traffic that the current page has generated
1018 * @param serverResponse
1021 Browser.prototype.network_traffic = function (serverResponse) {
1022 return this.serverSendResponse(this.currentPage.networkTraffic(), serverResponse);
1026 * Clears the accumulated network_traffic in the current page
1027 * @param serverResponse
1030 Browser.prototype.clear_network_traffic = function (serverResponse) {
1031 this.currentPage.clearNetworkTraffic();
1032 return this.serverSendResponse(true, serverResponse);
1036 * Gets the headers of the current page
1037 * @param serverResponse
1040 Browser.prototype.get_headers = function (serverResponse) {
1041 return this.serverSendResponse(this.currentPage.getCustomHeaders(), serverResponse);
1045 * Set headers in the browser
1046 * @param serverResponse
1050 Browser.prototype.set_headers = function (serverResponse, headers) {
1051 if (headers['User-Agent']) {
1052 this.currentPage.setUserAgent(headers['User-Agent']);
1054 this.currentPage.setCustomHeaders(headers);
1055 return this.serverSendResponse(true, serverResponse);
1059 * Given an array of headers, adds them to the page
1060 * @param serverResponse
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;
1073 return this.set_headers(serverResponse, allHeaders);
1077 * Adds a header to the page temporary or permanently
1078 * @param serverResponse
1083 Browser.prototype.add_header = function (serverResponse, header, permanent) {
1085 this.currentPage.addTempHeader(header);
1087 return this.add_headers(serverResponse, header);
1092 * Sends back the client the response headers sent from the browser when making
1094 * @param serverResponse
1097 Browser.prototype.response_headers = function (serverResponse) {
1098 return this.serverSendResponse(this.currentPage.responseHeaders(), serverResponse);
1102 * Returns the cookies of the current page being browsed
1103 * @param serverResponse
1106 Browser.prototype.cookies = function (serverResponse) {
1107 return this.serverSendResponse(this.currentPage.cookies(), serverResponse);
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
1114 * @param serverResponse
1118 Browser.prototype.set_cookie = function (serverResponse, cookie) {
1119 return this.serverSendResponse(phantom.addCookie(cookie), serverResponse);
1123 * Remove a cookie set on the current page
1124 * @param serverResponse
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);
1136 * Clear the cookies in the browser
1137 * @param serverResponse
1140 Browser.prototype.clear_cookies = function (serverResponse) {
1141 phantom.clearCookies();
1142 return this.serverSendResponse(true, serverResponse);
1146 * Enables / Disables the cookies on the browser
1147 * @param serverResponse
1151 Browser.prototype.cookies_enabled = function (serverResponse, flag) {
1152 phantom.cookiesEnabled = flag;
1153 return this.serverSendResponse(true, serverResponse);
1158 * Sets a basic authentication credential to access a page
1159 * THIS SHOULD BE USED BEFORE accessing a page
1160 * @param serverResponse
1165 Browser.prototype.set_http_auth = function (serverResponse, user, password) {
1166 this.currentPage.setHttpAuth(user, password);
1167 return this.serverSendResponse(true, serverResponse);
1171 * Sets the flag whether to fail on javascript errors or not.
1172 * @param serverResponse
1176 Browser.prototype.set_js_errors = function (serverResponse, value) {
1177 this.js_errors = value;
1178 return this.serverSendResponse(true, serverResponse);
1182 * Sets the debug mode to boolean value
1183 * @param serverResponse
1187 Browser.prototype.set_debug = function (serverResponse, value) {
1188 this._debug = value;
1189 return this.serverSendResponse(true, serverResponse);
1193 * Goes back in the history when possible
1194 * @param serverResponse
1197 Browser.prototype.go_back = function (serverResponse) {
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);
1206 return this.serverSendResponse(false, serverResponse);
1211 * Reloads the page if possible
1214 Browser.prototype.reload = function (serverResponse) {
1216 this.currentPage.state = 'loading';
1217 this.currentPage.reload();
1218 return this.currentPage.waitState('default', function () {
1219 return self.serverSendResponse(true, serverResponse);
1224 * Goes forward in the browser history if possible
1225 * @param serverResponse
1228 Browser.prototype.go_forward = function (serverResponse) {
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);
1237 return this.serverSendResponse(false, serverResponse);
1242 * Sets the urlBlacklist for the given urls as parameters
1245 Browser.prototype.set_url_blacklist = function (serverResponse, blackList) {
1246 this.currentPage.urlBlacklist = Array.prototype.slice.call(blackList);
1247 return this.serverSendResponse(true, serverResponse);
1251 * Runs a browser command and returns the response back to the client
1252 * when the command has finished the execution
1254 * @param serverResponse
1257 Browser.prototype.serverRunCommand = function (command, serverResponse) {
1262 commandName = command.name;
1263 commandArgs = command.args;
1264 this.currentPage.state = 'default';
1265 commandData = [serverResponse].concat(commandArgs);
1267 if (typeof this[commandName] !== "function") {
1268 //We can not run such command
1269 throw new Poltergeist.Error();
1272 return this[commandName].apply(this, commandData);
1276 * Sends a response back to the client who made the request
1278 * @param serverResponse
1281 Browser.prototype.serverSendResponse = function (response, serverResponse) {
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);
1288 return this.owner.serverSendResponse(response, serverResponse);