mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 21:17:03 +00:00
818 lines
20 KiB
Plaintext
818 lines
20 KiB
Plaintext
/*
|
|
* CPWebView.j
|
|
* AppKit
|
|
*
|
|
* Created by Thomas Robinson.
|
|
* Copyright 2008, 280 North, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
@import "CPView.j"
|
|
@import "CPScrollView.j"
|
|
|
|
|
|
// FIXME: implement these where possible:
|
|
/*
|
|
CPWebViewDidBeginEditingNotification = "CPWebViewDidBeginEditingNotification";
|
|
CPWebViewDidChangeNotification = "CPWebViewDidChangeNotification";
|
|
CPWebViewDidChangeSelectionNotification = "CPWebViewDidChangeSelectionNotification";
|
|
CPWebViewDidChangeTypingStyleNotification = "CPWebViewDidChangeTypingStyleNotification";
|
|
CPWebViewDidEndEditingNotification = "CPWebViewDidEndEditingNotification";
|
|
CPWebViewProgressEstimateChangedNotification = "CPWebViewProgressEstimateChangedNotification";
|
|
*/
|
|
CPWebViewProgressStartedNotification = "CPWebViewProgressStartedNotification";
|
|
CPWebViewProgressFinishedNotification = "CPWebViewProgressFinishedNotification";
|
|
|
|
CPWebViewScrollAppKit = 1;
|
|
CPWebViewScrollNative = 2;
|
|
|
|
// FIXME: somehow make CPWebView work with CPScrollView instead of native scrollbars (is this even possible?)
|
|
|
|
/*!
|
|
@ingroup appkit
|
|
|
|
@class CPWebView
|
|
|
|
CPWebView is a class which allows you to display arbitrary HTML or embed a
|
|
webpage inside your application.
|
|
|
|
It's important to note that the same origin policy applies to this view.
|
|
That is, if the web page being displayed is not located in the same origin
|
|
(protocol, domain, and port) as the application, you will have limited
|
|
control over the view and no access to its contents.
|
|
*/
|
|
|
|
@implementation CPWebView : CPView
|
|
{
|
|
CPScrollView _scrollView;
|
|
CPView _frameView;
|
|
|
|
IFrame _iframe;
|
|
CPString _mainFrameURL;
|
|
CPArray _backwardStack;
|
|
CPArray _forwardStack;
|
|
|
|
BOOL _ignoreLoadStart;
|
|
BOOL _ignoreLoadEnd;
|
|
|
|
id _downloadDelegate;
|
|
id _frameLoadDelegate;
|
|
id _policyDelegate;
|
|
id _resourceLoadDelegate;
|
|
id _UIDelegate;
|
|
|
|
CPWebScriptObject _wso;
|
|
|
|
CPString _url;
|
|
CPString _html;
|
|
|
|
Function _loadCallback;
|
|
|
|
int _scrollMode;
|
|
CGSize _scrollSize;
|
|
|
|
int _loadHTMLStringTimer;
|
|
}
|
|
|
|
- (id)initWithFrame:(CPRect)frameRect frameName:(CPString)frameName groupName:(CPString)groupName
|
|
{
|
|
if (self = [self initWithFrame:frameRect])
|
|
{
|
|
_iframe.name = frameName;
|
|
}
|
|
return self
|
|
}
|
|
|
|
- (id)initWithFrame:(CPRect)aFrame
|
|
{
|
|
if (self = [super initWithFrame:aFrame])
|
|
{
|
|
_mainFrameURL = nil;
|
|
_backwardStack = [];
|
|
_forwardStack = [];
|
|
_scrollMode = CPWebViewScrollNative;
|
|
|
|
[self _initDOMWithFrame:aFrame];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (id)_initDOMWithFrame:(CPRect)aFrame
|
|
{
|
|
_ignoreLoadStart = YES;
|
|
_ignoreLoadEnd = YES;
|
|
|
|
_iframe = document.createElement("iframe");
|
|
_iframe.name = "iframe_" + FLOOR(RAND() * 10000);
|
|
_iframe.style.width = "100%";
|
|
_iframe.style.height = "100%";
|
|
_iframe.style.borderWidth = "0px";
|
|
_iframe.frameBorder = "0";
|
|
|
|
[self setDrawsBackground:YES];
|
|
|
|
_loadCallback = function() {
|
|
// HACK: this block handles the case where we don't know about loads initiated by the user clicking a link
|
|
if (!_ignoreLoadStart)
|
|
{
|
|
// post the start load notification
|
|
[self _startedLoading];
|
|
|
|
if (_mainFrameURL)
|
|
[_backwardStack addObject:_mainFrameURL];
|
|
|
|
// FIXME: this doesn't actually get the right URL for different domains. Not possible due to browser security restrictions.
|
|
_mainFrameURL = _iframe.src;
|
|
_mainFrameURL = _iframe.src;
|
|
|
|
// clear the forward
|
|
[_forwardStack removeAllObjects];
|
|
}
|
|
else
|
|
_ignoreLoadStart = NO;
|
|
|
|
if (!_ignoreLoadEnd)
|
|
{
|
|
[self _finishedLoading];
|
|
}
|
|
else
|
|
_ignoreLoadEnd = NO;
|
|
|
|
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
|
}
|
|
|
|
if (_iframe.addEventListener)
|
|
_iframe.addEventListener("load", _loadCallback, false);
|
|
else if (_iframe.attachEvent)
|
|
_iframe.attachEvent("onload", _loadCallback);
|
|
|
|
_frameView = [[CPView alloc] initWithFrame:[self bounds]];
|
|
[_frameView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
|
|
|
_scrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
|
|
[_scrollView setAutohidesScrollers:YES];
|
|
[_scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
|
[_scrollView setDocumentView:_frameView];
|
|
|
|
_frameView._DOMElement.appendChild(_iframe);
|
|
|
|
[self _setScrollMode:_scrollMode];
|
|
|
|
[self addSubview:_scrollView];
|
|
}
|
|
|
|
|
|
- (void)setFrameSize:(CPSize)aSize
|
|
{
|
|
[super setFrameSize:aSize];
|
|
[self _resizeWebFrame];
|
|
}
|
|
|
|
- (void)_attachScrollEventIfNecessary
|
|
{
|
|
if (_scrollMode !== CPWebViewScrollAppKit)
|
|
return;
|
|
|
|
var win = null;
|
|
try { win = [self DOMWindow]; } catch (e) {}
|
|
|
|
if (win && win.addEventListener)
|
|
{
|
|
var scrollEventHandler = function(anEvent)
|
|
{
|
|
var frameBounds = [self bounds],
|
|
frameCenter = CGPointMake(CGRectGetMidX(frameBounds), CGRectGetMidY(frameBounds)),
|
|
windowOrigin = [self convertPoint:frameCenter toView:nil],
|
|
globalOrigin = [[self window] convertBaseToBridge:windowOrigin];
|
|
|
|
anEvent._overrideLocation = globalOrigin;
|
|
[[[self window] platformWindow] scrollEvent:anEvent];
|
|
};
|
|
|
|
win.addEventListener("DOMMouseScroll", scrollEventHandler, false);
|
|
}
|
|
}
|
|
|
|
- (void)_resizeWebFrame
|
|
{
|
|
if (_scrollMode === CPWebViewScrollAppKit)
|
|
{
|
|
if (_scrollSize)
|
|
{
|
|
[_frameView setFrameSize:_scrollSize];
|
|
}
|
|
else
|
|
{
|
|
var visibleRect = [_frameView visibleRect];
|
|
[_frameView setFrameSize:CGSizeMake(CGRectGetMaxX(visibleRect), CGRectGetMaxY(visibleRect))];
|
|
|
|
// try to get the document size so we can correctly set the frame
|
|
var win = null;
|
|
try { win = [self DOMWindow]; } catch (e) {}
|
|
|
|
if (win && win.document && win.document.body)
|
|
{
|
|
var width = win.document.body.scrollWidth,
|
|
height = win.document.body.scrollHeight;
|
|
|
|
_iframe.setAttribute("width", width);
|
|
_iframe.setAttribute("height", height);
|
|
|
|
[_frameView setFrameSize:CGSizeMake(width, height)];
|
|
}
|
|
else
|
|
{
|
|
CPLog.warn("using default size 800*1600");
|
|
|
|
[_frameView setFrameSize:CGSizeMake(800, 1600)];
|
|
}
|
|
|
|
[_frameView scrollRectToVisible:visibleRect];
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Sets the scroll mode of the receiver. Valid options are
|
|
CPWebViewScrollAppKit and CPWebViewScrollNative.
|
|
*/
|
|
- (void)setScrollMode:(int)aScrollMode
|
|
{
|
|
if (_scrollMode == aScrollMode)
|
|
return;
|
|
|
|
[self _setScrollMode:aScrollMode];
|
|
}
|
|
|
|
- (void)_setScrollMode:(int)aScrollMode
|
|
{
|
|
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
|
_scrollMode = CPWebViewScrollNative;
|
|
else
|
|
_scrollMode = aScrollMode;
|
|
|
|
_ignoreLoadStart = YES;
|
|
_ignoreLoadEnd = YES;
|
|
|
|
var parent = _iframe.parentNode;
|
|
parent.removeChild(_iframe);
|
|
|
|
if (_scrollMode === CPWebViewScrollAppKit)
|
|
{
|
|
[_scrollView setHasHorizontalScroller:YES];
|
|
[_scrollView setHasVerticalScroller:YES];
|
|
|
|
_iframe.setAttribute("scrolling", "no");
|
|
}
|
|
else
|
|
{
|
|
[_scrollView setHasHorizontalScroller:NO];
|
|
[_scrollView setHasVerticalScroller:NO];
|
|
|
|
_iframe.setAttribute("scrolling", "auto");
|
|
|
|
[_frameView setFrameSize:[_scrollView bounds].size];
|
|
}
|
|
|
|
parent.appendChild(_iframe);
|
|
}
|
|
|
|
/*!
|
|
Loads a string of HTML into the webview.
|
|
|
|
@param CPString - The string to load.
|
|
*/
|
|
- (void)loadHTMLString:(CPString)aString
|
|
{
|
|
[self loadHTMLString:aString baseURL:nil];
|
|
}
|
|
|
|
/*!
|
|
Loads a string of HTML into the webview.
|
|
|
|
@param CPString - The string to load.
|
|
@param CPURL - The base url of the string. (not implemented)
|
|
*/
|
|
- (void)loadHTMLString:(CPString)aString baseURL:(CPURL)URL
|
|
{
|
|
// FIXME: do something with baseURL?
|
|
|
|
[self _setScrollMode:CPWebViewScrollAppKit];
|
|
|
|
[_frameView setFrameSize:[_scrollView contentSize]];
|
|
|
|
[self _startedLoading];
|
|
|
|
_ignoreLoadStart = YES;
|
|
_ignoreLoadEnd = NO;
|
|
|
|
_url = null;
|
|
_html = aString;
|
|
|
|
[self _load];
|
|
}
|
|
|
|
- (void)_loadMainFrameURL
|
|
{
|
|
[self _setScrollMode:CPWebViewScrollNative];
|
|
|
|
[self _startedLoading];
|
|
|
|
_ignoreLoadStart = YES;
|
|
_ignoreLoadEnd = NO;
|
|
|
|
_url = _mainFrameURL;
|
|
_html = null;
|
|
|
|
[self _load];
|
|
}
|
|
|
|
- (void)_load
|
|
{
|
|
if (_url)
|
|
{
|
|
_iframe.src = _url;
|
|
}
|
|
else if (_html)
|
|
{
|
|
// clear the iframe
|
|
_iframe.src = "";
|
|
|
|
if (_loadHTMLStringTimer !== nil)
|
|
{
|
|
window.clearTimeout(_loadHTMLStringTimer);
|
|
_loadHTMLStringTimer = nil;
|
|
}
|
|
|
|
// need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document
|
|
_loadHTMLStringTimer = window.setTimeout(function()
|
|
{
|
|
var win = [self DOMWindow];
|
|
|
|
if (win)
|
|
win.document.write(_html);
|
|
|
|
window.setTimeout(_loadCallback, 1);
|
|
}, 0);
|
|
}
|
|
}
|
|
|
|
- (void)_startedLoading
|
|
{
|
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressStartedNotification object:self];
|
|
|
|
if ([_frameLoadDelegate respondsToSelector:@selector(webView:didStartProvisionalLoadForFrame:)])
|
|
[_frameLoadDelegate webView:self didStartProvisionalLoadForFrame:nil]; // FIXME: give this a frame somehow?
|
|
}
|
|
|
|
- (void)_finishedLoading
|
|
{
|
|
[self _resizeWebFrame];
|
|
[self _attachScrollEventIfNecessary];
|
|
|
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self];
|
|
|
|
if ([_frameLoadDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)])
|
|
[_frameLoadDelegate webView:self didFinishLoadForFrame:nil]; // FIXME: give this a frame somehow?
|
|
}
|
|
|
|
/*!
|
|
Returns the URL of the main frame.
|
|
|
|
@return CPString - The URL of the main frame.
|
|
*/
|
|
- (CPString)mainFrameURL
|
|
{
|
|
return _mainFrameURL;
|
|
}
|
|
|
|
/*!
|
|
Sets the URL of the main frame.
|
|
|
|
@param CPString - the url to set.
|
|
*/
|
|
- (void)setMainFrameURL:(CPString)URLString
|
|
{
|
|
if (_mainFrameURL)
|
|
[_backwardStack addObject:_mainFrameURL];
|
|
_mainFrameURL = URLString;
|
|
[_forwardStack removeAllObjects];
|
|
|
|
[self _loadMainFrameURL];
|
|
}
|
|
|
|
/*!
|
|
Tells the webview to navigate to the previous page.
|
|
|
|
@return BOOL - YES if the receiver was able to go back, otherwise NO.
|
|
*/
|
|
- (BOOL)goBack
|
|
{
|
|
if (_backwardStack.length > 0)
|
|
{
|
|
if (_mainFrameURL)
|
|
[_forwardStack addObject:_mainFrameURL];
|
|
_mainFrameURL = [_backwardStack lastObject];
|
|
[_backwardStack removeLastObject];
|
|
|
|
[self _loadMainFrameURL];
|
|
|
|
return YES;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
/*!
|
|
Tells the receiver to go forward in page history.
|
|
|
|
@return - YES if the receiver was able to go forward, otherwise NO.
|
|
*/
|
|
- (BOOL)goForward
|
|
{
|
|
if (_forwardStack.length > 0)
|
|
{
|
|
if (_mainFrameURL)
|
|
[_backwardStack addObject:_mainFrameURL];
|
|
_mainFrameURL = [_forwardStack lastObject];
|
|
[_forwardStack removeLastObject];
|
|
|
|
[self _loadMainFrameURL];
|
|
|
|
return YES;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
/*!
|
|
Checks to see if the webview has a history stack you can navigate back
|
|
through.
|
|
|
|
@return BOOL - YES if the receiver can navigate backward through history, otherwise NO.
|
|
*/
|
|
- (BOOL)canGoBack
|
|
{
|
|
return (_backwardStack.length > 0);
|
|
}
|
|
|
|
/*!
|
|
Checks to see if the webview has a history stack you can navigate forward
|
|
through.
|
|
|
|
@return BOOL - YES if the receiver can navigate forward through history, otherwise NO.
|
|
*/
|
|
- (BOOL)canGoForward
|
|
{
|
|
return (_forwardStack.length > 0);
|
|
}
|
|
|
|
- (WebBackForwardList)backForwardList
|
|
{
|
|
// FIXME: return a real WebBackForwardList?
|
|
return { back: _backwardStack, forward: _forwardStack };
|
|
}
|
|
|
|
/*!
|
|
Closes the webview by unloading the webpage. The webview will no longer
|
|
respond to load requests or delegate methods once this is called.
|
|
*/
|
|
- (void)close
|
|
{
|
|
_iframe.parentNode.removeChild(_iframe);
|
|
}
|
|
|
|
/*!
|
|
Returns the window object of the webview.
|
|
|
|
@return DOMWindow - The window object.
|
|
*/
|
|
- (DOMWindow)DOMWindow
|
|
{
|
|
return (_iframe.contentDocument && _iframe.contentDocument.defaultView) || _iframe.contentWindow;
|
|
}
|
|
|
|
/*!
|
|
Returns the root Object of the webview as a CPWebScriptObject.
|
|
|
|
@return CPWebScriptObject - the Object of the webview.
|
|
*/
|
|
- (CPWebScriptObject)windowScriptObject
|
|
{
|
|
var win = [self DOMWindow];
|
|
if (!_wso || win != [_wso window])
|
|
{
|
|
if (win)
|
|
_wso = [[CPWebScriptObject alloc] initWithWindow:win];
|
|
else
|
|
_wso = nil;
|
|
}
|
|
return _wso;
|
|
}
|
|
|
|
/*!
|
|
Evaluates a javascript string in the webview and returns the result of
|
|
that evaluation as a string.
|
|
|
|
@param script - A string of javascript.
|
|
@return CPString - The result of the evaluation.
|
|
*/
|
|
- (CPString)stringByEvaluatingJavaScriptFromString:(CPString)script
|
|
{
|
|
var result = [self objectByEvaluatingJavaScriptFromString:script];
|
|
return result ? String(result) : nil;
|
|
}
|
|
|
|
/*!
|
|
Evaluates a string of javascript in the webview and returns the result.
|
|
|
|
@param script - A string of javascript.
|
|
@return JSObject - A JSObject resulting from the evaluation.
|
|
*/
|
|
- (JSObject)objectByEvaluatingJavaScriptFromString:(CPString)script
|
|
{
|
|
return [[self windowScriptObject] evaluateWebScript:script];
|
|
}
|
|
|
|
/*!
|
|
Gets the computed style for an element.
|
|
|
|
@param DOMElement - An Element.
|
|
@param pseudoElement - A pseudoElement.
|
|
@return DOMCSSStyleDeclaration - The computed style for an element.
|
|
*/
|
|
- (DOMCSSStyleDeclaration)computedStyleForElement:(DOMElement)element pseudoElement:(CPString)pseudoElement
|
|
{
|
|
var win = [[self windowScriptObject] window];
|
|
if (win)
|
|
{
|
|
// FIXME: IE version?
|
|
return win.document.defaultView.getComputedStyle(element, pseudoElement);
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
|
|
/*!
|
|
@return BOOL - YES if the webview draws its own background, otherwise NO.
|
|
*/
|
|
- (BOOL)drawsBackground
|
|
{
|
|
return _iframe.style.backgroundColor != "";
|
|
}
|
|
|
|
/*!
|
|
Sets whether the webview draws its own background.
|
|
|
|
@param BOOL - YES if the webview should draw its background, otherwise NO.
|
|
*/
|
|
- (void)setDrawsBackground:(BOOL)drawsBackround
|
|
{
|
|
_iframe.style.backgroundColor = drawsBackround ? "white" : "";
|
|
}
|
|
|
|
|
|
// IBActions
|
|
|
|
/*!
|
|
Used with the target/action mechanism to automatically set the webviews
|
|
mainFrameURL to the senders stringValue.
|
|
|
|
@param sender - the sender of the action. Should respond to -stringValue.
|
|
*/
|
|
- (@action)takeStringURLFrom:(id)sender
|
|
{
|
|
[self setMainFrameURL:[sender stringValue]];
|
|
}
|
|
|
|
/*!
|
|
Same as -goBack but takes a sender as a param.
|
|
|
|
@param sender - the sender of the action.
|
|
*/
|
|
- (@action)goBack:(id)sender
|
|
{
|
|
[self goBack];
|
|
}
|
|
|
|
/*!
|
|
Same as -goForward but takes a sender as a param.
|
|
|
|
@param sender - the sender of the action.
|
|
*/
|
|
- (@action)goForward:(id)sender
|
|
{
|
|
[self goForward];
|
|
}
|
|
|
|
/*!
|
|
Stops loading the webview. (not yet implemented)
|
|
|
|
@param sender - the sender of the action.
|
|
*/
|
|
- (@action)stopLoading:(id)sender
|
|
{
|
|
// FIXME: what to do?
|
|
}
|
|
|
|
/*!
|
|
Reloads the webview.
|
|
|
|
@param sender - the sender of the action.
|
|
*/
|
|
- (@action)reload:(id)sender
|
|
{
|
|
[self _loadMainFrameURL];
|
|
}
|
|
|
|
/*!
|
|
Tells the webview to print. If the webview is unable to print due to
|
|
browser restrictions the user is alerted to print from the file menu.
|
|
|
|
@param sender - the sender of the receiver.
|
|
*/
|
|
- (@action)print:(id)sender
|
|
{
|
|
try
|
|
{
|
|
[self DOMWindow].print();
|
|
}
|
|
catch (e)
|
|
{
|
|
alert('Please click the webpage and select "Print" from the "File" menu');
|
|
}
|
|
}
|
|
|
|
|
|
// Delegates:
|
|
|
|
// FIXME: implement more delegates, though most of these will likely never work with the iframe implementation
|
|
|
|
- (id)downloadDelegate
|
|
{
|
|
return _downloadDelegate;
|
|
}
|
|
- (void)setDownloadDelegate:(id)anObject
|
|
{
|
|
_downloadDelegate = anObject;
|
|
}
|
|
- (id)frameLoadDelegate
|
|
{
|
|
return _frameLoadDelegate;
|
|
}
|
|
- (void)setFrameLoadDelegate:(id)anObject
|
|
{
|
|
_frameLoadDelegate = anObject;
|
|
}
|
|
- (id)policyDelegate
|
|
{
|
|
return _policyDelegate;
|
|
}
|
|
- (void)setPolicyDelegate:(id)anObject
|
|
{
|
|
_policyDelegate = anObject;
|
|
}
|
|
- (id)resourceLoadDelegate
|
|
{
|
|
return _resourceLoadDelegate;
|
|
}
|
|
- (void)setResourceLoadDelegate:(id)anObject
|
|
{
|
|
_resourceLoadDelegate = anObject;
|
|
}
|
|
- (id)UIDelegate
|
|
{
|
|
return _UIDelegate;
|
|
}
|
|
- (void)setUIDelegate:(id)anObject
|
|
{
|
|
_UIDelegate = anObject;
|
|
}
|
|
|
|
@end
|
|
|
|
/*!
|
|
@class CPWebScriptObject
|
|
|
|
A CPWebScriptObject is an Objective-J wrapper around a scripting object.
|
|
*/
|
|
@implementation CPWebScriptObject : CPObject
|
|
{
|
|
Window _window;
|
|
}
|
|
|
|
/*!
|
|
Initializes the scripting object with the scripting Window object.
|
|
*/
|
|
- (id)initWithWindow:(Window)aWindow
|
|
{
|
|
if (self = [super init])
|
|
{
|
|
_window = aWindow;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
Call a method with arguments on the receiver.
|
|
|
|
@param methodName - The method that should be called.
|
|
@param args - An array of arguments to pass to the method call.
|
|
*/
|
|
- (id)callWebScriptMethod:(CPString)methodName withArguments:(CPArray)args
|
|
{
|
|
// Would using "with" be better here?
|
|
if (typeof _window[methodName] == "function")
|
|
{
|
|
try {
|
|
return _window[methodName].apply(args);
|
|
} catch (e) {
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
/*!
|
|
Evaluates a string of javascript and returns the result.
|
|
|
|
@param script - The script to run.
|
|
@return - The result of the evaluation, which may be 'undefined'.
|
|
*/
|
|
- (id)evaluateWebScript:(CPString)script
|
|
{
|
|
try {
|
|
return _window.eval(script);
|
|
} catch (e) {
|
|
// FIX ME: if we fail inside here, shouldn't we return an exception?
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
/*!
|
|
Returns the receivers Window object.
|
|
*/
|
|
- (Window)window
|
|
{
|
|
return _window;
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
@implementation CPWebView (CPCoding)
|
|
|
|
/*!
|
|
Initializes the web view from the data in a coder.
|
|
|
|
@param aCoder the coder from which to read the data
|
|
@return the initialized web view
|
|
*/
|
|
- (id)initWithCoder:(CPCoder)aCoder
|
|
{
|
|
self = [super initWithCoder:aCoder];
|
|
|
|
if (self)
|
|
{
|
|
// FIXME: encode/decode these?
|
|
_mainFrameURL = nil;
|
|
_backwardStack = [];
|
|
_forwardStack = [];
|
|
_scrollMode = CPWebViewScrollNative;
|
|
|
|
#if PLATFORM(DOM)
|
|
[self _initDOMWithFrame:[self frame]];
|
|
#endif
|
|
|
|
[self setBackgroundColor:[CPColor whiteColor]];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
Writes out the web view's instance information to a coder.
|
|
|
|
@param aCoder the coder to which to write the data
|
|
*/
|
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
|
{
|
|
var actualSubviews = _subviews;
|
|
_subviews = [];
|
|
[super encodeWithCoder:aCoder];
|
|
_subviews = actualSubviews;
|
|
}
|
|
|
|
@end
|