Chris@0: var __indexOf = [].indexOf || function (item) { Chris@0: for (var i = 0, l = this.length; i < l; i++) { Chris@0: if (i in this && this[i] === item) return i; Chris@0: } Chris@0: return -1; Chris@0: }; Chris@0: Chris@0: var xpathStringLiteral = function (s) { Chris@0: if (s.indexOf('"') === -1) Chris@0: return '"' + s + '"'; Chris@0: if (s.indexOf("'") === -1) Chris@0: return "'" + s + "'"; Chris@0: return 'concat("' + s.replace(/"/g, '",\'"\',"') + '")'; Chris@0: }; Chris@0: Chris@0: Poltergeist.Browser = (function () { Chris@0: /** Chris@0: * Creates the "browser" inside phantomjs Chris@0: * @param owner Chris@0: * @param width Chris@0: * @param height Chris@0: * @param jsErrors Chris@0: * @constructor Chris@0: */ Chris@0: function Browser(owner, width, height, jsErrors) { Chris@0: this.owner = owner; Chris@0: this.width = width || 1024; Chris@0: this.height = height || 768; Chris@0: this.pages = []; Chris@0: this.js_errors = (typeof jsErrors === 'boolean') ? jsErrors : true; Chris@2: this._resourceTimeout = false; Chris@0: this._debug = false; Chris@0: this._counter = 0; Chris@0: this.resetPage(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Resets the browser to a clean slate Chris@0: */ Chris@0: Browser.prototype.resetPage = function () { Chris@0: var _ref; Chris@0: var self = this; Chris@0: Chris@0: _ref = [0, []]; Chris@0: this._counter = _ref[0]; Chris@0: this.pages = _ref[1]; Chris@0: Chris@0: if (this.page != null) { Chris@0: if (!this.page.closed) { Chris@0: if (this.page.currentUrl() !== 'about:blank') { Chris@0: this.page.clearLocalStorage(); Chris@0: } Chris@0: this.page.release(); Chris@0: } Chris@0: phantom.clearCookies(); Chris@0: } Chris@0: Chris@2: this.page = this.currentPage = new Poltergeist.WebPage(null, this); Chris@0: this.page.setViewportSize({ Chris@0: width: this.width, Chris@0: height: this.height Chris@0: }); Chris@2: }; Chris@0: Chris@2: /** Chris@2: * Adds given newly opened Poltergeist.WebPage to the list of available windows/frames Chris@2: * consulted by methods getPageByHandle, window_handle, window_handles, switch_to_window and close_window. Chris@2: * Chris@2: * @param {WebPage} page Chris@2: */ Chris@2: Browser.prototype.registerPage = function (page) { Chris@2: if (!('handle' in page)) Chris@2: { Chris@2: page.handle = "" + (this._counter++); Chris@2: this.pages.push(page); Chris@2: } Chris@2: }; Chris@2: Chris@2: /** Chris@2: * Removes given closed Poltergeist.WebPage from the list of available windows/frames Chris@2: * consulted by methods getPageByHandle, window_handle, window_handles, switch_to_window and close_window. Chris@2: * Chris@2: * @param {Poltergeist.WebPage} page Chris@2: */ Chris@2: Browser.prototype.unregisterPage = function (page) { Chris@2: if (('handle' in page) && (page.handle !== null)) Chris@2: { Chris@2: for (var i = this.pages.length; i--;) { Chris@2: if (page === this.pages[i]) { Chris@2: this.pages.splice(i,1); Chris@2: break; Chris@2: } Chris@2: } Chris@2: page.handle = null; Chris@2: } Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Given a page handle id, tries to get it from the browser page list Chris@0: * @param handle Chris@0: * @return {WebPage} Chris@0: */ Chris@0: Browser.prototype.getPageByHandle = function (handle) { Chris@0: var filteredPages; Chris@0: Chris@0: //TODO: perhaps we should throw a PageNotFoundByHandle or something like that.. Chris@0: if (handle === null || typeof handle == "undefined") { Chris@0: return null; Chris@0: } Chris@0: Chris@0: filteredPages = this.pages.filter(function (p) { Chris@0: return !p.closed && p.handle === handle; Chris@0: }); Chris@0: Chris@0: if (filteredPages.length === 1) { Chris@0: return filteredPages[0]; Chris@0: } Chris@0: Chris@0: return null; Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sends a debug message to the console Chris@0: * @param message Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.debug = function (message) { Chris@0: if (this._debug) { Chris@0: return console.log("poltergeist [" + (new Date().getTime()) + "] " + message); Chris@0: } Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Given a page_id and id, gets if possible the node in such page Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {Poltergeist.Node} Chris@0: */ Chris@0: Browser.prototype.node = function (page_id, id) { Chris@0: if (this.currentPage.id === page_id) { Chris@0: return this.currentPage.get(id); Chris@0: } else { Chris@0: throw new Poltergeist.ObsoleteNode; Chris@0: } Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the frameUrl related to the frame given by name Chris@0: * @param frame_name Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.frameUrl = function (frame_name) { Chris@0: return this.currentPage.frameUrl(frame_name); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * This method defines the rectangular area of the web page to be rasterized when render is invoked. Chris@0: * If no clipping rectangle is set, render will process the entire web page. Chris@0: * @param full Chris@0: * @param selector Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set_clip_rect = function (full, selector) { Chris@0: var dimensions, clipDocument, rect, clipViewport; Chris@0: Chris@0: dimensions = this.currentPage.validatedDimensions(); Chris@0: clipDocument = dimensions.document; Chris@0: clipViewport = dimensions.viewport; Chris@0: Chris@0: if (full) { Chris@0: rect = { Chris@0: left: 0, Chris@0: top: 0, Chris@0: width: clipDocument.width, Chris@0: height: clipDocument.height Chris@0: }; Chris@0: } else { Chris@0: if (selector != null) { Chris@0: rect = this.currentPage.elementBounds(selector); Chris@0: } else { Chris@0: rect = { Chris@0: left: 0, Chris@0: top: 0, Chris@0: width: clipViewport.width, Chris@0: height: clipViewport.height Chris@0: }; Chris@0: } Chris@0: } Chris@0: Chris@0: this.currentPage.setClipRect(rect); Chris@0: return dimensions; Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Kill the browser, i.e kill phantomjs current process Chris@0: * @return {int} Chris@0: */ Chris@0: Browser.prototype.exit = function () { Chris@0: return phantom.exit(0); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Do nothing Chris@0: */ Chris@0: Browser.prototype.noop = function () { Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Throws a new Object error Chris@0: */ Chris@0: Browser.prototype.browser_error = function () { Chris@0: throw new Error('zomg'); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Visits a page and load its content Chris@0: * @param serverResponse Chris@0: * @param url Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.visit = function (serverResponse, url) { Chris@0: var prevUrl; Chris@0: var self = this; Chris@0: this.currentPage.state = 'loading'; Chris@2: Chris@2: if (this._resourceTimeout) { Chris@2: this.currentPage._native.settings.resourceTimeout = this._resourceTimeout; Chris@2: this.currentPage._native.onResourceTimeout = function (request) { Chris@2: console.log('Response (#' + request.id + '): ' + JSON.stringify(request)); Chris@2: }; Chris@2: } Chris@2: Chris@0: prevUrl = this.currentPage.source === null ? 'about:blank' : this.currentPage.currentUrl(); Chris@0: this.currentPage.open(url); Chris@0: if (/#/.test(url) && prevUrl.split('#')[0] === url.split('#')[0]) { Chris@0: this.currentPage.state = 'default'; Chris@0: return this.serverSendResponse({ Chris@0: status: 'success' Chris@0: }, serverResponse); Chris@0: } else { Chris@0: return this.currentPage.waitState('default', function () { Chris@0: if (self.currentPage.statusCode === null && self.currentPage.status === 'fail') { Chris@0: return self.owner.serverSendError(new Poltergeist.StatusFailError, serverResponse); Chris@0: } else { Chris@0: return self.serverSendResponse({ Chris@0: status: self.currentPage.status Chris@0: }, serverResponse); Chris@0: } Chris@0: }); Chris@0: } Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Puts the control of the browser inside the IFRAME given by name Chris@0: * @param serverResponse Chris@0: * @param name Chris@0: * @param timeout Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.push_frame = function (serverResponse, name, timeout) { Chris@0: var _ref; Chris@0: var self = this; Chris@0: Chris@0: if (timeout == null) { Chris@0: timeout = new Date().getTime() + 2000; Chris@0: } Chris@0: Chris@0: //TODO: WTF, else if after a if with return COMMON Chris@0: if (_ref = this.frameUrl(name), __indexOf.call(this.currentPage.blockedUrls(), _ref) >= 0) { Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: } else if (this.currentPage.pushFrame(name)) { Chris@0: if (this.currentPage.currentUrl() === 'about:blank') { Chris@0: this.currentPage.state = 'awaiting_frame_load'; Chris@0: return this.currentPage.waitState('default', function () { Chris@0: return self.serverSendResponse(true, serverResponse); Chris@0: }); Chris@0: } else { Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: } Chris@0: } else { Chris@0: if (new Date().getTime() < timeout) { Chris@0: return setTimeout((function () { Chris@0: return self.push_frame(serverResponse, name, timeout); Chris@0: }), 50); Chris@0: } else { Chris@0: return this.owner.serverSendError(new Poltergeist.FrameNotFound(name), serverResponse); Chris@0: } Chris@0: } Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Injects a javascript into the current page Chris@0: * @param serverResponse Chris@0: * @param extension Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.add_extension = function (serverResponse, extension) { Chris@0: //TODO: error control when the injection was not possible Chris@0: this.currentPage.injectExtension(extension); Chris@0: return this.serverSendResponse('success', serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the url we are currently in Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.current_url = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.currentUrl(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the current page window name Chris@0: * @param serverResponse Chris@0: * @returns {*} Chris@0: */ Chris@0: Browser.prototype.window_name = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.windowName(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the status code associated to the page Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.status_code = function (serverResponse) { Chris@0: if (this.currentPage.statusCode === undefined || this.currentPage.statusCode === null) { Chris@0: return this.owner.serverSendError(new Poltergeist.StatusFailError("status_code_error"), serverResponse); Chris@0: } Chris@0: return this.serverSendResponse(this.currentPage.statusCode, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the source code of the active frame, useful for when inside an IFRAME Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.body = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.content(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the source code of the page all the html Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.source = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.source, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the current page title Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.title = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.title(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Finds the elements that match a method of selection and a selector Chris@0: * @param serverResponse Chris@0: * @param method Chris@0: * @param selector Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.find = function (serverResponse, method, selector) { Chris@0: return this.serverSendResponse({ Chris@0: page_id: this.currentPage.id, Chris@0: ids: this.currentPage.find(method, selector) Chris@0: }, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Find elements within a given element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param method Chris@0: * @param selector Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.find_within = function (serverResponse, page_id, id, method, selector) { Chris@0: return this.serverSendResponse(this.node(page_id, id).find(method, selector), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns ALL the text, visible and not visible from the given element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.all_text = function (serverResponse, page_id, id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).allText(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the inner or outer html of a given id Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param type Chris@0: * @returns Object Chris@0: */ Chris@0: Browser.prototype.all_html = function (serverResponse, page_id, id, type) { Chris@0: return this.serverSendResponse(this.node(page_id, id).allHTML(type), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns only the visible text in a given element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.visible_text = function (serverResponse, page_id, id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).visibleText(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Deletes the text in a given element leaving it empty Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.delete_text = function (serverResponse, page_id, id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).deleteText(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Gets the value of a given attribute in an element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param name Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.attribute = function (serverResponse, page_id, id, name) { Chris@0: return this.serverSendResponse(this.node(page_id, id).getAttribute(name), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Allows the possibility to set an attribute on a given element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param name Chris@0: * @param value Chris@0: * @returns {*} Chris@0: */ Chris@0: Browser.prototype.set_attribute = function (serverResponse, page_id, id, name, value) { Chris@0: return this.serverSendResponse(this.node(page_id, id).setAttribute(name, value), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Allows the possibility to remove an attribute on a given element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param name Chris@0: * @returns {*} Chris@0: */ Chris@0: Browser.prototype.remove_attribute = function (serverResponse, page_id, id, name) { Chris@0: return this.serverSendResponse(this.node(page_id, id).removeAttribute(name), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns all the attributes of a given element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param name Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.attributes = function (serverResponse, page_id, id, name) { Chris@0: return this.serverSendResponse(this.node(page_id, id).getAttributes(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns all the way to the document level the parents of a given element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.parents = function (serverResponse, page_id, id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).parentIds(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the element.value of an element given by its page and id Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.value = function (serverResponse, page_id, id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).value(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sets the element.value of an element by the given value Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param value Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set = function (serverResponse, page_id, id, value) { Chris@0: this.node(page_id, id).set(value); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Uploads a file to an input file element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param file_path Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.select_file = function (serverResponse, page_id, id, file_path) { Chris@0: var node = this.node(page_id, id); Chris@0: Chris@0: this.currentPage.beforeUpload(node.id); Chris@0: this.currentPage.uploadFile('[_poltergeist_selected]', file_path); Chris@0: this.currentPage.afterUpload(node.id); Chris@0: Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sets a value to the selected element (to be used in select elements) Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param value Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.select = function (serverResponse, page_id, id, value) { Chris@0: return this.serverSendResponse(this.node(page_id, id).select(value), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Selects an option with the given value Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param value Chris@0: * @param multiple Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.select_option = function (serverResponse, page_id, id, value, multiple) { Chris@0: return this.serverSendResponse(this.node(page_id, id).select_option(value, multiple), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.tag_name = function (serverResponse, page_id, id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).tagName(), serverResponse); Chris@0: }; Chris@0: Chris@0: Chris@0: /** Chris@0: * Tells if an element is visible or not Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.visible = function (serverResponse, page_id, id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).isVisible(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Tells if an element is disabled Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.disabled = function (serverResponse, page_id, id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).isDisabled(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Evaluates a javascript and returns the outcome to the client Chris@0: * This will be JSON response so your script better be returning objects that can be used Chris@0: * in JSON.stringify Chris@0: * @param serverResponse Chris@0: * @param script Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.evaluate = function (serverResponse, script) { Chris@0: return this.serverSendResponse(this.currentPage.evaluate("function() { return " + script + " }"), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Executes a javascript and goes back to the client with true if there were no errors Chris@0: * @param serverResponse Chris@0: * @param script Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.execute = function (serverResponse, script) { Chris@0: this.currentPage.execute("function() { " + script + " }"); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * If inside a frame then we will go back to the parent Chris@0: * Not defined behaviour if you pop and are not inside an iframe Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.pop_frame = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.popFrame(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Gets the window handle id by a given window name Chris@0: * @param serverResponse Chris@0: * @param name Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.window_handle = function (serverResponse, name) { Chris@0: var handle, pageByWindowName; Chris@0: Chris@0: if (name === null || typeof name == "undefined" || name.length === 0) { Chris@0: return this.serverSendResponse(this.currentPage.handle, serverResponse); Chris@0: } Chris@0: Chris@0: handle = null; Chris@0: Chris@0: //Lets search the handle by the given window name Chris@0: var filteredPages = this.pages.filter(function (p) { Chris@0: return !p.closed && p.windowName() === name; Chris@0: }); Chris@0: Chris@0: //A bit of error control is always good Chris@0: if (Array.isArray(filteredPages) && filteredPages.length >= 1) { Chris@0: pageByWindowName = filteredPages[0]; Chris@0: } else { Chris@0: pageByWindowName = null; Chris@0: } Chris@0: Chris@0: if (pageByWindowName !== null && typeof pageByWindowName != "undefined") { Chris@0: handle = pageByWindowName.handle; Chris@0: } Chris@0: Chris@0: return this.serverSendResponse(handle, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns all the window handles of opened windows Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.window_handles = function (serverResponse) { Chris@0: var handles, filteredPages; Chris@0: Chris@0: filteredPages = this.pages.filter(function (p) { Chris@0: return !p.closed; Chris@0: }); Chris@0: Chris@0: if (filteredPages.length > 0) { Chris@0: handles = filteredPages.map(function (p) { Chris@0: return p.handle; Chris@0: }); Chris@0: if (handles.length === 0) { Chris@0: handles = null; Chris@0: } Chris@0: } else { Chris@0: handles = null; Chris@0: } Chris@0: Chris@0: return this.serverSendResponse(handles, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Tries to switch to a window given by the handle id Chris@0: * @param serverResponse Chris@0: * @param handle Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.switch_to_window = function (serverResponse, handle) { Chris@0: var page; Chris@0: var self = this; Chris@0: Chris@0: page = this.getPageByHandle(handle); Chris@0: if (page === null || typeof page == "undefined") { Chris@0: throw new Poltergeist.NoSuchWindowError; Chris@0: } Chris@0: Chris@0: if (page !== this.currentPage) { Chris@0: return page.waitState('default', function () { Chris@0: self.currentPage = page; Chris@0: return self.serverSendResponse(true, serverResponse); Chris@0: }); Chris@0: } Chris@0: Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Opens a new window where we can do stuff Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.open_new_window = function (serverResponse) { Chris@0: return this.execute(serverResponse, 'window.open()'); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Closes the window given by handle name if possible Chris@2: * NOTE: Closing a page in PhantomJS also closes new windows/frames opened from that page (QWebPage behaviour) Chris@0: * @param serverResponse Chris@0: * @param handle Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.close_window = function (serverResponse, handle) { Chris@0: var page; Chris@0: Chris@0: page = this.getPageByHandle(handle); Chris@0: if (page === null || typeof page == "undefined") { Chris@0: //TODO: should we throw error since we actually could not find the window? Chris@0: return this.serverSendResponse(false, serverResponse); Chris@0: } Chris@0: Chris@0: //TODO: we have to add some control here to actually asses that the release has been done Chris@0: page.release(); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Generic mouse event on an element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param name Chris@0: * @return {number} Chris@0: */ Chris@0: Browser.prototype.mouse_event = function (serverResponse, page_id, id, name) { Chris@0: var node; Chris@0: var self = this; Chris@0: node = this.node(page_id, id); Chris@0: this.currentPage.state = 'mouse_event'; Chris@0: this.last_mouse_event = node.mouseEvent(name); Chris@0: return setTimeout(function () { Chris@0: if (self.currentPage.state === 'mouse_event') { Chris@0: self.currentPage.state = 'default'; Chris@0: return self.serverSendResponse({ Chris@0: position: self.last_mouse_event Chris@0: }, serverResponse); Chris@0: } else { Chris@0: return self.currentPage.waitState('default', function () { Chris@0: return self.serverSendResponse({ Chris@0: position: self.last_mouse_event Chris@0: }, serverResponse); Chris@0: }); Chris@0: } Chris@0: }, 5); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Simple click on the element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.click = function (serverResponse, page_id, id) { Chris@0: return this.mouse_event(serverResponse, page_id, id, 'click'); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Right click on the element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.right_click = function (serverResponse, page_id, id) { Chris@0: return this.mouse_event(serverResponse, page_id, id, 'rightclick'); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Double click on the element given by page and id Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.double_click = function (serverResponse, page_id, id) { Chris@0: return this.mouse_event(serverResponse, page_id, id, 'doubleclick'); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Executes a mousemove event on the page and given element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.hover = function (serverResponse, page_id, id) { Chris@0: return this.mouse_event(serverResponse, page_id, id, 'mousemove'); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Triggers a mouse click event on the given coordinates Chris@0: * @param serverResponse Chris@0: * @param x Chris@0: * @param y Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.click_coordinates = function (serverResponse, x, y) { Chris@0: var response; Chris@0: Chris@0: this.currentPage.sendEvent('click', x, y); Chris@0: response = { Chris@0: click: { Chris@0: x: x, Chris@0: y: y Chris@0: } Chris@0: }; Chris@0: Chris@0: return this.serverSendResponse(response, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Drags one element into another, useful for nice javascript thingies Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param other_id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.drag = function (serverResponse, page_id, id, other_id) { Chris@0: this.node(page_id, id).dragTo(this.node(page_id, other_id)); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Triggers an event on the given page and element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param event Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.trigger = function (serverResponse, page_id, id, event) { Chris@0: this.node(page_id, id).trigger(event); Chris@0: return this.serverSendResponse(event, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Checks if two elements are equal on a dom level Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param other_id Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.equals = function (serverResponse, page_id, id, other_id) { Chris@0: return this.serverSendResponse(this.node(page_id, id).isEqual(this.node(page_id, other_id)), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Resets the current page to a clean slate Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.reset = function (serverResponse) { Chris@0: this.resetPage(); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Scrolls to a position given by the left, top coordinates Chris@0: * @param serverResponse Chris@0: * @param left Chris@0: * @param top Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.scroll_to = function (serverResponse, left, top) { Chris@0: this.currentPage.setScrollPosition({ Chris@0: left: left, Chris@0: top: top Chris@0: }); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sends keys to an element simulating as closest as possible what a user would do Chris@0: * when typing Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param keys Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.send_keys = function (serverResponse, page_id, id, keys) { Chris@0: var key, sequence, target, _i, _len; Chris@0: target = this.node(page_id, id); Chris@0: if (!target.containsSelection()) { Chris@0: target.mouseEvent('click'); Chris@0: } Chris@0: for (_i = 0, _len = keys.length; _i < _len; _i++) { Chris@0: sequence = keys[_i]; Chris@0: key = sequence.key != null ? this.currentPage.keyCode(sequence.key) : sequence; Chris@0: this.currentPage.sendEvent('keypress', key); Chris@0: } Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sends a native phantomjs key event to element Chris@0: * @param serverResponse Chris@0: * @param page_id Chris@0: * @param id Chris@0: * @param keyEvent Chris@0: * @param key Chris@0: * @param modifier Chris@0: */ Chris@0: Browser.prototype.key_event = function (serverResponse, page_id, id, keyEvent, key, modifier) { Chris@0: var keyEventModifierMap; Chris@0: var keyEventModifier; Chris@0: var target; Chris@0: Chris@0: keyEventModifierMap = { Chris@0: 'none': 0x0, Chris@0: 'shift': 0x02000000, Chris@0: 'ctrl': 0x04000000, Chris@0: 'alt': 0x08000000, Chris@0: 'meta': 0x10000000 Chris@0: }; Chris@0: keyEventModifier = keyEventModifierMap[modifier]; Chris@0: Chris@0: target = this.node(page_id, id); Chris@0: if (!target.containsSelection()) { Chris@0: target.mouseEvent('click'); Chris@0: } Chris@0: target.page.sendEvent(keyEvent, key, null, null, keyEventModifier); Chris@0: Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sends the rendered page in a base64 encoding Chris@0: * @param serverResponse Chris@0: * @param format Chris@0: * @param full Chris@0: * @param selector Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.render_base64 = function (serverResponse, format, full, selector) { Chris@0: var encoded_image; Chris@0: if (selector == null) { Chris@0: selector = null; Chris@0: } Chris@0: this.set_clip_rect(full, selector); Chris@0: encoded_image = this.currentPage.renderBase64(format); Chris@0: return this.serverSendResponse(encoded_image, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Renders the current page entirely or a given selection Chris@0: * @param serverResponse Chris@0: * @param path Chris@0: * @param full Chris@0: * @param selector Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.render = function (serverResponse, path, full, selector) { Chris@0: var dimensions; Chris@0: if (selector == null) { Chris@0: selector = null; Chris@0: } Chris@0: dimensions = this.set_clip_rect(full, selector); Chris@0: this.currentPage.setScrollPosition({ Chris@0: left: 0, Chris@0: top: 0 Chris@0: }); Chris@0: this.currentPage.render(path); Chris@0: this.currentPage.setScrollPosition({ Chris@0: left: dimensions.left, Chris@0: top: dimensions.top Chris@0: }); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: Chris@0: /** Chris@0: * Sets the paper size, useful when printing to PDF Chris@0: * @param serverResponse Chris@0: * @param size Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set_paper_size = function (serverResponse, size) { Chris@0: this.currentPage.setPaperSize(size); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sets the zoom factor on the current page Chris@0: * @param serverResponse Chris@0: * @param zoom_factor Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set_zoom_factor = function (serverResponse, zoom_factor) { Chris@0: this.currentPage.setZoomFactor(zoom_factor); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Resizes the browser viewport, useful when testing mobile stuff Chris@0: * @param serverResponse Chris@0: * @param width Chris@0: * @param height Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.resize = function (serverResponse, width, height) { Chris@0: this.currentPage.setViewportSize({ Chris@0: width: width, Chris@0: height: height Chris@0: }); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Gets the browser viewport size Chris@0: * Because PhantomJS is headless (nothing is shown) Chris@0: * viewportSize effectively simulates the size of the window like in a traditional browser. Chris@0: * @param serverResponse Chris@0: * @param handle Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.window_size = function (serverResponse, handle) { Chris@0: //TODO: add support for window handles Chris@0: return this.serverSendResponse(this.currentPage.viewportSize(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the network traffic that the current page has generated Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.network_traffic = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.networkTraffic(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Clears the accumulated network_traffic in the current page Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.clear_network_traffic = function (serverResponse) { Chris@0: this.currentPage.clearNetworkTraffic(); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Gets the headers of the current page Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.get_headers = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.getCustomHeaders(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Set headers in the browser Chris@0: * @param serverResponse Chris@0: * @param headers Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set_headers = function (serverResponse, headers) { Chris@0: if (headers['User-Agent']) { Chris@0: this.currentPage.setUserAgent(headers['User-Agent']); Chris@0: } Chris@0: this.currentPage.setCustomHeaders(headers); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Given an array of headers, adds them to the page Chris@0: * @param serverResponse Chris@0: * @param headers Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.add_headers = function (serverResponse, headers) { Chris@0: var allHeaders, name, value; Chris@0: allHeaders = this.currentPage.getCustomHeaders(); Chris@0: for (name in headers) { Chris@0: if (headers.hasOwnProperty(name)) { Chris@0: value = headers[name]; Chris@0: allHeaders[name] = value; Chris@0: } Chris@0: } Chris@0: return this.set_headers(serverResponse, allHeaders); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Adds a header to the page temporary or permanently Chris@0: * @param serverResponse Chris@0: * @param header Chris@0: * @param permanent Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.add_header = function (serverResponse, header, permanent) { Chris@0: if (!permanent) { Chris@0: this.currentPage.addTempHeader(header); Chris@0: } Chris@0: return this.add_headers(serverResponse, header); Chris@0: }; Chris@0: Chris@0: Chris@0: /** Chris@0: * Sends back the client the response headers sent from the browser when making Chris@0: * the page request Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.response_headers = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.responseHeaders(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Returns the cookies of the current page being browsed Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.cookies = function (serverResponse) { Chris@0: return this.serverSendResponse(this.currentPage.cookies(), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sets a cookie in the browser, the format of the cookies has to be the format it says Chris@0: * on phantomjs documentation and as such you can set it in other domains, not on the Chris@0: * current page Chris@0: * @param serverResponse Chris@0: * @param cookie Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set_cookie = function (serverResponse, cookie) { Chris@0: return this.serverSendResponse(phantom.addCookie(cookie), serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Remove a cookie set on the current page Chris@0: * @param serverResponse Chris@0: * @param name Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.remove_cookie = function (serverResponse, name) { Chris@0: //TODO: add error control to check if the cookie was properly deleted Chris@0: this.currentPage.deleteCookie(name); Chris@0: phantom.deleteCookie(name); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Clear the cookies in the browser Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.clear_cookies = function (serverResponse) { Chris@0: phantom.clearCookies(); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Enables / Disables the cookies on the browser Chris@0: * @param serverResponse Chris@0: * @param flag Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.cookies_enabled = function (serverResponse, flag) { Chris@0: phantom.cookiesEnabled = flag; Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@2: * Sets proxy or unsets web proxy Chris@2: * @param {Object} serverResponse Phantomjs response object associated to the client request Chris@2: * @param {String} ip IP or host name, or null/'' to unset Chris@2: * @param {Number} port port number Chris@2: * @param {String} proxyType socks5 or anything else for http(s) Chris@2: * @param {String} user optional username for proxy authentication Chris@2: * @param {String} password optional password for proxy authentication Chris@2: * @return {*} Chris@2: * @see {@link https://github.com/ariya/phantomjs/pull/11829/commits/84c31822a2e5eba21fe42298ec27ec4ccab95667} Chris@2: */ Chris@2: Browser.prototype.set_proxy = function (serverResponse, ip, port, proxyType, user, password) { Chris@2: phantom.setProxy(ip, port, proxyType, user, password); Chris@2: return this.serverSendResponse(true, serverResponse); Chris@2: }; Chris@2: Chris@2: /** Chris@0: * US19: DONE Chris@0: * Sets a basic authentication credential to access a page Chris@0: * THIS SHOULD BE USED BEFORE accessing a page Chris@0: * @param serverResponse Chris@0: * @param user Chris@0: * @param password Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set_http_auth = function (serverResponse, user, password) { Chris@0: this.currentPage.setHttpAuth(user, password); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sets the flag whether to fail on javascript errors or not. Chris@0: * @param serverResponse Chris@0: * @param value Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set_js_errors = function (serverResponse, value) { Chris@0: this.js_errors = value; Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sets the debug mode to boolean value Chris@0: * @param serverResponse Chris@0: * @param value Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.set_debug = function (serverResponse, value) { Chris@0: this._debug = value; Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Goes back in the history when possible Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.go_back = function (serverResponse) { Chris@0: var self = this; Chris@0: if (this.currentPage.canGoBack()) { Chris@0: this.currentPage.state = 'loading'; Chris@0: this.currentPage.goBack(); Chris@0: return this.currentPage.waitState('default', function () { Chris@0: return self.serverSendResponse(true, serverResponse); Chris@0: }); Chris@0: } else { Chris@0: return this.serverSendResponse(false, serverResponse); Chris@0: } Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Reloads the page if possible Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.reload = function (serverResponse) { Chris@0: var self = this; Chris@0: this.currentPage.state = 'loading'; Chris@0: this.currentPage.reload(); Chris@0: return this.currentPage.waitState('default', function () { Chris@0: return self.serverSendResponse(true, serverResponse); Chris@0: }); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Goes forward in the browser history if possible Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.go_forward = function (serverResponse) { Chris@0: var self = this; Chris@0: if (this.currentPage.canGoForward()) { Chris@0: this.currentPage.state = 'loading'; Chris@0: this.currentPage.goForward(); Chris@0: return this.currentPage.waitState('default', function () { Chris@0: return self.serverSendResponse(true, serverResponse); Chris@0: }); Chris@0: } else { Chris@0: return this.serverSendResponse(false, serverResponse); Chris@0: } Chris@0: }; Chris@0: Chris@0: /** Chris@2: * Sets the timeout in milliseconds, after which any resource requested will stop Chris@2: * trying and proceed with other parts of the page Chris@2: * @param serverResponse Chris@2: * @param value Chris@2: * @return {*} Chris@2: */ Chris@2: Browser.prototype.set_resource_timeout = function (serverResponse, value) { Chris@2: this._resourceTimeout = value; Chris@2: return this.serverSendResponse(true, serverResponse); Chris@2: }; Chris@2: Chris@2: /** Chris@0: * Sets the urlBlacklist for the given urls as parameters Chris@0: * @return {boolean} Chris@0: */ Chris@0: Browser.prototype.set_url_blacklist = function (serverResponse, blackList) { Chris@0: this.currentPage.urlBlacklist = Array.prototype.slice.call(blackList); Chris@0: return this.serverSendResponse(true, serverResponse); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Runs a browser command and returns the response back to the client Chris@0: * when the command has finished the execution Chris@0: * @param command Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.serverRunCommand = function (command, serverResponse) { Chris@0: var commandData; Chris@0: var commandArgs; Chris@0: var commandName; Chris@0: Chris@0: commandName = command.name; Chris@0: commandArgs = command.args; Chris@0: this.currentPage.state = 'default'; Chris@0: commandData = [serverResponse].concat(commandArgs); Chris@0: Chris@0: if (typeof this[commandName] !== "function") { Chris@0: //We can not run such command Chris@0: throw new Poltergeist.Error(); Chris@0: } Chris@0: Chris@0: return this[commandName].apply(this, commandData); Chris@0: }; Chris@0: Chris@0: /** Chris@0: * Sends a response back to the client who made the request Chris@0: * @param response Chris@0: * @param serverResponse Chris@0: * @return {*} Chris@0: */ Chris@0: Browser.prototype.serverSendResponse = function (response, serverResponse) { Chris@0: var errors; Chris@0: errors = this.currentPage.errors; Chris@0: this.currentPage.clearErrors(); Chris@0: if (errors.length > 0 && this.js_errors) { Chris@0: return this.owner.serverSendError(new Poltergeist.JavascriptError(errors), serverResponse); Chris@0: } else { Chris@0: return this.owner.serverSendResponse(response, serverResponse); Chris@0: } Chris@0: }; Chris@0: Chris@0: return Browser; Chris@0: Chris@0: })();