Skip to content

API Reference WebPage

Darren Cook edited this page May 28, 2013 · 15 revisions

This is a living document. As the codebase is updated, we hope to keep this document updated as well. Unless otherwise stated, this document currently applies to the latest PhantomJS release: PhantomJS 1.8.0

Note: This page serves as a reference. To learn step-by-step on how to use PhantomJS, please refer to the Quick Start guide.

## Module: WebPage ## A `WebPage` object encapsulates a web page. It is usually instantiated using the following pattern: ```js var page = require('webpage').create(); ```

Note: For backward compatibility with legacy PhantomJS applications, the constructor also remains exposed as a deprecated global WebPage object:

var page = new WebPage();

Properties list

clipRect canGoBack canGoForward content cookies customHeaders event focusedFrameName frameContent frameName framePlainText frameTitle frameUrl framesCount framesName libraryPath navigationLocked offlineStoragePath offlineStorageQuota ownsPages pages pagesWindowName paperSize plainText scrollPosition settings title url viewportSize windowName zoomFactor

Functions list

addCookie() childFramesCount() childFramesName() clearCookies() close() currentFrameName() deleteCookie() evaluateJavaScript() evaluate() evaluateAsync() getPage() go() goBack() goForward() includeJs() injectJs() open() openUrl() release() reload() render() renderBase64() sendEvent() setContent() stop() switchToFocusedFrame() switchToFrame() switchToFrame() switchToChildFrame() switchToChildFrame() switchToMainFrame() switchToParentFrame() uploadFile()

Callbacks list

onAlert onCallback onClosing onConfirm onConsoleMessage onError onFilePicker onInitialized onLoadFinished onLoadStarted onNavigationRequested onPageCreated onPrompt onResourceRequested onResourceReceived onUrlChanged

Internal methods to trigger callbacks : closing() initialized() javaScriptAlertSent() javaScriptConsoleMessageSent() loadFinished() loadStarted() navigationRequested() rawPageCreated() resourceReceived() resourceRequested() urlChanged()

### Properties ### #### `canGoBack` #### #### `canGoForward` #### #### `clipRect` {object} #### This property defines the rectangular area of the web page to be rasterized when [`WebPage#render`](#webpage-render) is invoked. If no clipping rectangle is set, [`WebPage#render`](#webpage-render) will process the entire web page.

Example:

page.clipRect = { top: 14, left: 3, width: 400, height: 300 };
#### `content` {string} #### This property stores the content of the web page (main frame), enclosed in an HTML/XML element. Setting the property will effectively reload the web page with the new content.

See also plainText to get the content without any HTML tags.

#### `cookies` {[Cookie](#cookie)[]} #### Get or set [Cookies](#cookie) visible to the current URL (though, for setting, use of [`WebPage#addCookie`](#webpage-addCookie) is preferred). This array will be pre-populated by any existing Cookie data visible to this URL that is stored in the CookieJar, if any. See [`phantom.cookies`](#phantom-cookies) for more information on the CookieJar. #### `customHeaders` {object} #### **Introduced:** PhantomJS 1.5 This property specifies additional HTTP request headers that will be sent to the server for every request issued (for pages _and_ resources). The default value is an empty object `{}`. Headers names and values get encoded in US-ASCII before being sent. Please note that the 'User-Agent' should be set using the [`WebPage#settings`](#webpage-settings), setting the 'User-Agent' property in this property will _overwrite_ the value set via `WebPage#settings`.

Example:

// Send two additional headers 'X-Test' and 'DNT'.
page.customHeaders = {
    'X-Test': 'foo',
    'DNT': '1'
};

Do you only want these customHeaders passed to the initial WebPage#open request? Here's the recommended workaround:

// Send two additional headers 'X-Test' and 'DNT'.
page.customHeaders = {
    'X-Test': 'foo',
    'DNT': '1'
};
page.onInitialized = function() {
    page.customHeaders = {};
};
#### `event` #### #### `focusedFrameName` #### #### `frameContent` {string} #### **Introduced:** PhantomJS 1.7 This property stores the content of the web page's _currently active_ frame (which may or may not be the main frame), enclosed in an HTML/XML element. Setting the property will effectively reload the web page with the new content. #### `frameName` #### #### `framePlainText` {string} #### **Introduced:** PhantomJS 1.7 Read-only. This property stores the content of the web page's _currently active_ frame (which may or may not be the main frame) as plain text — no element tags! #### `frameTitle` #### #### `frameUrl` {string} #### **Introduced:** PhantomJS 1.7 Read-only. This property gets the current URL of the web page's _currently active_ frame (which may or may not be the main frame). #### `framesCount` #### #### `framesName` #### #### `libraryPath` {string} #### This property stores the path which is used by [`WebPage#injectJs`](#webpage-injectJs) function to resolve the script name. Initially it is set to the location of the script invoked by PhantomJS. #### `navigationLocked` {boolean} #### This property defines whether navigation away from the page is permitted or not. If it is set to `true`, then the page is locked to the current URL. Defaults to `false`. #### `offlineStoragePath` #### #### `offlineStorageQuota` #### #### `ownsPages` #### #### `pages` #### #### `pagesWindowName` #### #### `paperSize` {object} #### This property defines the size of the web page when rendered as a PDF.

The given object should be in one of the following two formats:

{ width: '200px', height: '300px', border: '0px' }
{ format: 'A4', orientation: 'portrait', border: '1cm' }

If no paperSize is defined, the size is defined by the web page. Supported dimension units are: 'mm', 'cm', 'in', 'px'. No unit means 'px'. Border is optional and defaults to 0. Supported formats are: 'A3', 'A4', 'A5', 'Legal', 'Letter', 'Tabloid'. Orientation ('portrait', 'landscape') is optional and defaults to 'portrait'.

Example:

page.paperSize = { width: '5in', height: '7in', border: '20px' };
#### `plainText` {string} #### Read-only. This property stores the content of the web page (main frame) as plain text — no element tags!

See also: content which returns the content with element tags.

#### `scrollPosition` {object} #### This property defines the scroll position of the web page.

Example:

page.scrollPosition = { top: 100, left: 0 };
#### `settings` {object} #### This property stores various settings of the web page: * `javascriptEnabled` defines whether to execute the script in the page or not (defaults to `true`). * `loadImages` defines whether to load the inlined images or not (defaults to `true`). * `localToRemoteUrlAccessEnabled` defines whether local resource (e.g. from file) can access remote URLs or not (defaults to `false`). * `userAgent` defines the user agent sent to server when the web page requests resources. * `userName` sets the user name used for HTTP authentication. * `password` sets the password used for HTTP authentication. * `XSSAuditingEnabled` defines whether load requests should be monitored for cross-site scripting attempts (defaults to `false`). * `webSecurityEnabled` defines whether web security should be enabled or not (defaults to `true`).

Note: The settings apply only during the initial call to the WebPage#open function. Subsequent modification of the settings object will not have any impact.

#### `title` #### #### `url` {string} #### **Introduced:** PhantomJS 1.7 Read-only. This property gets the current URL of the web page (main frame). #### `viewportSize` {object} #### This property sets the size of the viewport for the layout process. It is useful to set the preferred initial size before loading the page, e.g. to choose between `'landscape'` vs `'portrait'`.

Because PhantomJS is headless (nothing is shown), viewportSize effectively simulates the size of the window like in a traditional browser.

Example:

page.viewportSize = { width: 480, height: 800 };
#### `windowName` #### #### `zoomFactor` {number} #### This property specifies the scaling factor for the [`WebPage#render`](#webpage-render) and [`WebPage#renderBase64`](#webpage-renderBase64) functions. The default is `1`, i.e. 100% zoom.

Example:

// Create a thumbnail preview with 25% zoom
page.zoomFactor = 0.25;
page.render('capture.png');
### Functions ### #### `addCookie([Cookie](#cookie))` {boolean} #### **Introduced:** PhantomJS 1.7 Add a [Cookie](#cookie) to the page. If the domains do not match, the Cookie will be ignored/rejected. Returns `true` if successfully added, otherwise `false`.

Example:

page.addCookie({
    'name': 'Added-Cookie-Name',
    'value': 'Added-Cookie-Value'
});
#### `childFramesCount()` ####

Deprecated.

#### `childFramesName()` ####

Deprecated.

#### `clearCookies()` {void} #### **Introduced:** PhantomJS 1.7 Delete all [Cookies](#cookie) visible to the current URL. #### `close()` {void} #### **Introduced:** PhantomJS 1.7 Close the page and releases the memory heap associated with it. Do not use the page instance after calling this.

Due to some technical limitations, the web page object might not be completely garbage collected. This is often encountered when the same object is used over and over again. Calling this function may stop the increasing heap allocation.

#### `currentFrameName()` ####

Deprecated.

#### `deleteCookie(cookieName)` {boolean} #### **Introduced:** PhantomJS 1.7 Delete any [Cookies](#cookie) visible to the current URL with a 'name' property matching `cookieName`. Returns `true` if successfully deleted, otherwise `false`.

Example:

page.deleteCookie('Added-Cookie-Name');
#### `evaluate(function, arg1, arg2, ...)` {object} #### Evaluates the given function in the context of the web page. The execution is sandboxed, the web page has no access to the `phantom` object and it can't probe its own setting.

Example:

var page = require('webpage').create();
page.open('http://m.bing.com', function(status) {
    var title = page.evaluate(function() {
        return document.title;
    });
    console.log(title);
    phantom.exit();
});

As of PhantomJS 1.6, JSON-serializable arguments can be passed to the function. In the following example, the text value of a DOM element is extracted. The following example achieves the same end goal as the previous example but the element is chosen based on a selector which is passed to the evaluate call:

var page = require('webpage').create();
page.open('http://m.bing.com', function(status) {
    var title = page.evaluate(function(s) {
        return document.querySelector(s).innerText;
    }, 'title');
    console.log(title);
    phantom.exit();
});

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine. Closures, functions, DOM nodes, etc. will not work!

#### `evaluateAsync(function)` {void} #### Evaluates the given function in the context of the web page without blocking the current execution. The function returns immediately and there is no return value. This is useful to run some script asynchronously. #### `evaluateJavaScript(str)` #### #### `getPage(windowName)` #### #### `go(index)` #### #### `goBack()` #### #### `goForward()` #### #### `includeJs(url, callback)` {void} #### Includes external script from the specified `url` (usually a remote location) on the page and executes the `callback` upon completion.

Example:

page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js', function() {
    /* jQuery is loaded, now manipulate the DOM */
});
#### `injectJs(filename)` {boolean} #### Injects external script code from the specified file into the page (like [`WebPage#includeJs`](#webpage-includeJs), except that the file does not need to be accessible from the hosted page). If the file cannot be found in the current directory, `libraryPath` is used for additional look up. This function returns `true` if injection is successful, otherwise it returns `false`. #### `open(url, callback)` {void} #### Opens the `url` and loads it to the page. Once the page is loaded, the optional `callback` is called using [`WebPage#onLoadFinished`](#webpage-onLoadFinished), and also provides the page status to the function (`'success'` or `'fail'`).

Example:

page.open('http://www.google.com/', function(status) {
    console.log('Status: ' + status);
    // Do other things here...
});
#### `openUrl(url, httpConf, settings)` #### #### `release()` {void} #### **Stability:** _DEPRECATED_ - Use [`WebPage#close`](#webpage-close)) Releases memory heap associated with this page. Do not use the page instance after calling this.

Due to some technical limitations, the web page object might not be completely garbage collected. This is often encountered when the same object is used over and over again. Calling this function may stop the increasing heap allocation.

#### `reload()` #### #### `render(filename)` {void} #### Renders the web page to an image buffer and saves it as the specified `filename`.

Currently, the output format is automatically set based on the file extension. Supported formats include:

  • PNG
  • GIF
  • JPEG
  • PDF
#### `renderBase64(format)` #### Renders the web page to an image buffer and returns the result as a [Base64](http://en.wikipedia.org/wiki/Base64)-encoded string representation of that image.

Supported formats include:

  • PNG
  • GIF
  • JPEG
#### `sendEvent(mouseEventType[, mouseX, mouseY, button='left'])` or `sendEvent(keyboardEventType, keyOrKeys, [null, null, modifier])` #### Sends an event to the web page. [1.7 implementation source](https://github.com/ariya/phantomjs/blob/63e06cb/src/webpage.cpp#L1015).

The events are not like synthetic DOM events. Each event is sent to the web page as if it comes as part of user interaction.

Mouse events

The first argument is the event type. Supported types are 'mouseup', 'mousedown', 'mousemove', 'doubleclick' and 'click'. The next two arguments are optional but represent the mouse position for the event.

The button parameter (defaults to left) specifies the button to push.

For 'mousemove', however, there is no button pressed (i.e. it is not dragging).

Keyboard events

The first argument is the event type. The supported types are: keyup, keypress and keydown. The second parameter is a key (from page.event.key), or a string.

You can also indicate a fifth argument, which is an integer indicating the modifier key.

  • 0: No modifier key is pressed
  • 0x02000000: A Shift key on the keyboard is pressed
  • 0x04000000: A Ctrl key on the keyboard is pressed
  • 0x08000000: An Alt key on the keyboard is pressed
  • 0x10000000: A Meta key on the keyboard is pressed
  • 0x20000000: A keypad button is pressed

Third and fourth argument are not taken account for keyboard events. Just give null for them.

Example:

page.sendEvent('keypress', page.event.key.A, null, null, 0x02000000 | 0x08000000 );

It simulate a shift+alt+A keyboard combination.

#### `setContent(content, url)` #### **Introduced:** PhantomJS 1.8

Allows to set both WebPage#content and WebPage#url properties.

The webpage will be reloaded with the new content and the current location set as the given url, without any actual http request being made.

#### `stop()` #### #### `switchToFocusedFrame()` #### #### `switchToFrame(frameName)` or `switchToFrame(framePosition)` #### #### `switchToChildFrame(frameName)` or `switchToChildFrame(framePosition)` ####

deprecated

#### `switchToMainFrame()` #### #### `switchToParentFrame()` #### #### `uploadFile(selector, filename)` #### Uploads the specified file (`filename`) to the form element associated with the `selector`.

This function is used to automate the upload of a file, which is usually handled with a file dialog in a traditional browser. Since there is no dialog in this headless mode, such an upload mechanism is handled via this special function instead.

Example:

page.uploadFile('input[name=image]', '/path/to/some/photo.jpg');
### Callbacks ### #### `onAlert` ### **Introduced:** PhantomJS 1.0 This callback is invoked when there is a JavaScript `alert` on the web page. The only argument passed to the callback is the string for the message. There is no return value expected from the callback handler.

Example:

page.onAlert = function(msg) {
    console.log('ALERT: ' + msg);
};
#### `onCallback` #### **Stability:** _EXPERIMENTAL_ **Introduced:** PhantomJS 1.6 This callback is invoked when there is a JavaScript `window.callPhantom` call made on the web page. The only argument passed to the callback is a data object.

Note: window.callPhantom is still an experimental API. In the near future, it will be likely replaced with a message-based solution which will still provide the same functionality.

Although there are many possible use cases for this inversion of control, the primary one so far is to prevent the need for a PhantomJS script to be continually polling for some variable on the web page.

Example:
WebPage (client-side)

if (typeof window.callPhantom === 'function') {
    window.callPhantom({ hello: 'world' });
}

PhantomJS (server-side)

page.onCallback = function(data) {
    console.log('CALLBACK: ' + JSON.stringify(data));  // Prints 'CALLBACK: { "hello": "world" }'
};

Additionally, note that the WebPage#onCallback handler can return a data object that will be carried back as the result of the originating window.callPhantom call, too.

Example:
WebPage (client-side)

if (typeof window.callPhantom === 'function') {
    var status = window.callPhantom({ secret: 'ghostly' });
    alert(status);  // Will either print 'Accepted.' or 'DENIED!'
}

PhantomJS (server-side)

page.onCallback = function(data) {
    if (data && data.secret && (data.secret === 'ghostly') {
        return 'Accepted.';
    }
    return 'DENIED!';
};
#### `onClosing` #### **Introduced:** PhantomJS 1.7 This callback is invoked when the `WebPage` object is being closed, either via [`WebPage#close`](#webpage-close) in the PhantomJS outer space or via [`window.close`](https://developer.mozilla.org/docs/DOM/window.close) in the page's client-side. It is _not_ invoked when child/descendant pages are being closed unless you also hook them up individually. It takes one argument, `closingPage`, which is a reference to the page that is closing. Once the `onClosing` handler has finished executing (returned), the `WebPage` object `closingPage` will become invalid.

Example:

page.onClosing = function(closingPage) {
    console.log('The page is closing! URL: ' + closingPage.url);
};
#### `onConfirm` #### **Introduced:** PhantomJS 1.6 This callback is invoked when there is a JavaScript `confirm` on the web page. The only argument passed to the callback is the string for the message. The return value of the callback handler can be either `true` or `false`, which are equivalent to pressing the "OK" or "Cancel" buttons presented in a JavaScript `confirm`, respectively.

Example:

page.onConfirm = function(msg) {
    console.log('CONFIRM: ' + msg);
    return true;  // `true` === pressing the "OK" button, `false` === pressing the "Cancel" button
};
#### `onConsoleMessage` #### **Introduced:** PhantomJS 1.2 This callback is invoked when there is a JavaScript `console` message on the web page. The callback may accept up to three arguments: the string for the message, the line number, and the source identifier.

By default, console messages from the web page are not displayed. Using this callback is a typical way to redirect it.

Example:

page.onConsoleMessage = function(msg, lineNum, sourceId) {
    console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};

Note: line number and source identifier are not used yet, at least in phantomJS <= 1.8.1. You receive undefined values.

#### `onError` #### **Introduced:** PhantomJS 1.5 This callback is invoked when there is a JavaScript execution error. It is a good way to catch problems when evaluating a script in the web page context. The arguments passed to the callback are the error message and the stack trace [as an Array].

Example:

page.onError = function(msg, trace) {
    var msgStack = ['ERROR: ' + msg];
    if (trace && trace.length) {
        msgStack.push('TRACE:');
        trace.forEach(function(t) {
            msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function + '")' : ''));
        });
    }
    console.error(msgStack.join('\n'));
};
#### `onFilePicker` #### #### `onInitialized` #### **Introduced:** PhantomJS 1.3 This callback is invoked _after_ the web page is created but _before_ a URL is loaded. The callback may be used to change global objects.

Example:

page.onInitialized = function() {
    page.evaluate(function() {
        document.addEventListener('DOMContentLoaded', function() {
            console.log('DOM content has loaded.');
        }, false);
    });
};
#### `onLoadFinished` #### **Introduced:** PhantomJS 1.2 This callback is invoked when the page finishes the loading. It may accept a single argument indicating the page's `status`: `'success'` if no network errors occurred, otherwise `'fail'`.

Also see WebPage#open for an alternate hook for the onLoadFinished callback.

Example:

page.onLoadFinished = function(status) {
    console.log('Status: ' + status);
    // Do other things here...
};
#### `onLoadStarted` #### **Introduced:** PhantomJS 1.2 This callback is invoked when the page starts the loading. There is no argument passed to the callback.

Example:

page.onLoadStarted = function() {
    var currentUrl = page.evaluate(function() {
        return window.location.href;
    });
    console.log('Current page ' + currentUrl +' will gone...');
    console.log('Now loading a new page...');
};
#### `onNavigationRequested` #### **Introduced:** PhantomJS 1.6 By implementing this callback, you will be notified when a navigation event happens and know if it will be blocked (by [`WebPage#navigationLocked`](#webpage-navigationLocked)). Takes the following arguments: * `url`: The target URL of this navigation event * `type`: Possible values include: `'Undefined'`, `'LinkClicked'`, `'FormSubmitted'`, `'BackOrForward'`, `'Reload'`, `'FormResubmitted'`, `'Other'` * `willNavigate`: `true` if navigation will happen, `false` if it is locked (by [`WebPage#navigationLocked`](#webpage-navigationLocked)) * `main`: `true` if this event comes from the main frame, `false` if it comes from an iframe of some other sub-frame.

Example:

page.onNavigationRequested = function(url, type, willNavigate, main) {
    console.log('Trying to navigate to: ' + url);
    console.log('Caused by: ' + type);
    console.log('Will actually navigate: ' + willNavigate);
    console.log('Sent from the page\'s main frame: ' + main);
}
#### `onPageCreated` #### **Introduced:** PhantomJS 1.7 This callback is invoked when a new child window (but _not_ deeper descendant windows) is created by the page, e.g. using [`window.open`](https://developer.mozilla.org/docs/DOM/window.open). In the PhantomJS outer space, this `WebPage` object will not yet have called its own [`WebPage#open`](#webpage-open) method yet and thus does not yet know its requested URL ([`WebPage#url`](#webpage-url)). Therefore, the most common purpose for utilizing a `WebPage#onPageCreated` callback is to decorate the page (e.g. hook up callbacks, etc.).

Example:

page.onPageCreated = function(newPage) {
    console.log('A new child page was created! Its requested URL is not yet available, though.');
    // Decorate
    newPage.onClosing = function(closingPage) {
        console.log('A child page is closing: ' + closingPage.url);
    };
};
#### `onPrompt` #### **Introduced:** PhantomJS 1.6 This callback is invoked when there is a JavaScript `prompt` on the web page. The arguments passed to the callback are the string for the message (`msg`) and the default value (`defaultVal`) for the prompt answer. The return value of the callback handler should be a string.

Example:

page.onPrompt = function(msg, defaultVal) {
    if (msg === "What's your name?") {
        return 'PhantomJS';
    }
    return defaultVal;
};
#### `onResourceRequested` #### **Introduced:** PhantomJS 1.2 This callback is invoked when the page requests a resource. The first argument to the callback is the `requestData` metadata object. The second argument is the `networkRequest` object itself.

Example:

page.onResourceRequested = function(requestData, networkRequest) {
    console.log('Request (#' + requestData.id + '): ' + JSON.stringify(requestData));
};

The requestData metadata object contains these properties:

  • id: the number of the requested resource
  • method: http method
  • url: the URL of the requested resource
  • time: Date object containing the date of the request
  • headers: list of http headers

The networkRequest object contains these functions:

  • abort(): aborts the current network request. Aborting the current network request will invoke (onResourceError) callback.
  • changeUrl(url): changes the current URL of the network request.
#### `onResourceReceived` #### **Introduced:** PhantomJS 1.2 This callback is invoked when the a resource requested by the page is received. The only argument to the callback is the `response` metadata object.

If the resource is large and sent by the server in multiple chunks, onResourceReceived will be invoked for every chunk received by PhantomJS.

Example:

page.onResourceReceived = function(response) {
    console.log('Response (#' + response.id + ', stage "' + response.stage + '"): ' + JSON.stringify(response));
};

The response metadata object contains these properties:

  • id: the number of the requested resource
  • url: the URL of the requested resource
  • time: Date object containing the date of the response
  • headers: list of http headers
  • bodySize: size of the received content decompressed (entire content or chunk content)
  • contentType: the content type if specified
  • redirectURL: if there is a redirection, the redirected URL
  • stage: "start", "end" (FIXME: other value for intermediate chunk?)
  • status: http status code. ex: 200
  • statusText: http status text. ex: OK
#### `onUrlChanged` #### **Introduced:** PhantomJS 1.6 This callback is invoked when the URL changes, e.g. as it navigates away from the current URL. The only argument to the callback is the new `targetUrl` string.

Example:

page.onUrlChanged = function(targetUrl) {
    console.log('New URL: ' + targetUrl);
};

To retrieve the old URL, use the onLoadStarted callback.

#### `onResourceError` #### **Introduced:** PhantomJS 1.9 This callback is invoked when a web page was unable to load resource. The only argument to the callback is the `resourceError` metadata object.

Example:

page.onResourceError = function(resourceError) {
    console.log('Unable to load resource (URL:' + resourceError.url + ')');
    console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};

The resourceError metadata object contains these properties:

  • url: the resource url
  • errorCode: the error code
  • errorString: the error description
### Callbacks triggers ###

These function call callbacks. Used for tests...

#### `closing(page)` #### #### `initialized()` #### #### `javaScriptAlertSent(message)` #### #### `javaScriptConsoleMessageSent(message)` #### #### `loadFinished(status)` #### #### `loadStarted()` #### #### `navigationRequested(url, navigationType, navigationLocked, isMainFrame)` #### #### `rawPageCreated(page)` #### #### `resourceReceived(request)` #### #### `resourceRequested(resource)` #### #### `resourceError(resource)` #### #### `urlChanged(url)` ####