00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import <AppKit/CPView.j>
00024
00025 #include "Platform/Platform.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 CPWebViewProgressStartedNotification = "CPWebViewProgressStartedNotification";
00038 CPWebViewProgressFinishedNotification = "CPWebViewProgressFinishedNotification";
00039
00040 CPWebViewScrollAppKit = 1;
00041 CPWebViewScrollNative = 2;
00042
00043
00044
00049 @implementation CPWebView : CPView
00050 {
00051 CPScrollView _scrollView;
00052 CPView _frameView;
00053
00054 IFrame _iframe;
00055 CPString _mainFrameURL;
00056 CPArray _backwardStack;
00057 CPArray _forwardStack;
00058
00059 BOOL _ignoreLoadStart;
00060 BOOL _ignoreLoadEnd;
00061
00062 id _downloadDelegate;
00063 id _frameLoadDelegate;
00064 id _policyDelegate;
00065 id _resourceLoadDelegate;
00066 id _UIDelegate;
00067
00068 CPWebScriptObject _wso;
00069
00070 CPString _url;
00071 CPString _html;
00072
00073 Function _loadCallback;
00074
00075 int _scrollMode;
00076 CGSize _scrollSize;
00077 }
00078
00079 - (id)initWithFrame:(CPRect)frameRect frameName:(CPString)frameName groupName:(CPString)groupName
00080 {
00081 if (self = [self initWithFrame:frameRect])
00082 {
00083 _iframe.name = frameName;
00084 }
00085 return self
00086 }
00087
00088 - (id)initWithFrame:(CPRect)aFrame
00089 {
00090 if (self = [super initWithFrame:aFrame])
00091 {
00092 _mainFrameURL = nil;
00093 _backwardStack = [];
00094 _forwardStack = [];
00095 _scrollMode = CPWebViewScrollNative;
00096
00097 [self _initDOMWithFrame:aFrame];
00098 }
00099
00100 return self;
00101 }
00102
00103 - (id)_initDOMWithFrame:(CPRect)aFrame
00104 {
00105 _ignoreLoadStart = YES;
00106 _ignoreLoadEnd = YES;
00107
00108 _iframe = document.createElement("iframe");
00109 _iframe.name = "iframe_" + Math.floor(Math.random()*10000);
00110 _iframe.style.width = "100%";
00111 _iframe.style.height = "100%";
00112 _iframe.style.borderWidth = "0px";
00113
00114 [self setDrawsBackground:YES];
00115
00116 _loadCallback = function() {
00117
00118 if (!_ignoreLoadStart)
00119 {
00120
00121 [self _startedLoading];
00122
00123 if (_mainFrameURL)
00124 [_backwardStack addObject:_mainFrameURL];
00125
00126
00127 _mainFrameURL = _iframe.src;
00128 _mainFrameURL = _iframe.src;
00129
00130
00131 [_forwardStack removeAllObjects];
00132 }
00133 else
00134 _ignoreLoadStart = NO;
00135
00136 if (!_ignoreLoadEnd)
00137 {
00138 [self _finishedLoading];
00139 }
00140 else
00141 _ignoreLoadEnd = NO;
00142
00143 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00144 }
00145
00146 if (_iframe.addEventListener)
00147 _iframe.addEventListener("load", _loadCallback, false);
00148 else if (_iframe.attachEvent)
00149 _iframe.attachEvent("onload", _loadCallback);
00150
00151
00152 _frameView = [[CPView alloc] initWithFrame:[self bounds]];
00153
00154 _scrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
00155 [_scrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
00156 [_scrollView setDocumentView:_frameView];
00157
00158 _frameView._DOMElement.appendChild(_iframe);
00159
00160 [self _setScrollMode:_scrollMode];
00161
00162 [self addSubview:_scrollView];
00163 }
00164
00165
00166 - (void)setFrameSize:(CPSize)aSize
00167 {
00168 [super setFrameSize:aSize];
00169
00170 [self _resizeWebFrame];
00171 }
00172
00173 - (BOOL)_resizeWebFrame
00174 {
00175 if (_scrollMode === CPWebViewScrollAppKit)
00176 {
00177 if (_scrollSize)
00178 {
00179 [_frameView setFrameSize:_scrollSize];
00180 }
00181 else
00182 {
00183 [_frameView setFrameSize:[_scrollView bounds].size];
00184
00185
00186 var win = null;
00187 try { win = [self DOMWindow]; } catch (e) {}
00188
00189 if (win && win.document)
00190 {
00191 var width = win.document.body.scrollWidth,
00192 height = win.document.body.scrollHeight;
00193
00194 _iframe.setAttribute("width", width);
00195 _iframe.setAttribute("height", height);
00196
00197 [_frameView setFrameSize:CGSizeMake(width, height)];
00198 }
00199 else
00200 {
00201 CPLog.warn("using default size 800*1600");
00202
00203 [_frameView setFrameSize:CGSizeMake(800, 1600)];
00204 }
00205 }
00206 }
00207 }
00208
00209 - (void)setScrollMode:(int)aScrollMode
00210 {
00211 if (_scrollMode == aScrollMode)
00212 return;
00213
00214 [self _setScrollMode:aScrollMode];
00215 }
00216
00217 - (void)_setScrollMode:(int)aScrollMode
00218 {
00219 _scrollMode = aScrollMode;
00220
00221 _ignoreLoadStart = YES;
00222 _ignoreLoadEnd = YES;
00223
00224 var parent = _iframe.parentNode;
00225 parent.removeChild(_iframe);
00226
00227 if (_scrollMode === CPWebViewScrollAppKit)
00228 {
00229 [_scrollView setHasHorizontalScroller:YES];
00230 [_scrollView setHasVerticalScroller:YES];
00231
00232 _iframe.setAttribute("scrolling", "no");
00233 }
00234 else
00235 {
00236 [_scrollView setHasHorizontalScroller:NO];
00237 [_scrollView setHasVerticalScroller:NO];
00238
00239 _iframe.setAttribute("scrolling", "auto");
00240
00241 [_frameView setFrameSize:[_scrollView bounds].size];
00242 }
00243
00244 parent.appendChild(_iframe);
00245 }
00246
00247 - (void)loadHTMLString:(CPString)aString
00248 {
00249 [self loadHTMLString:aString baseURL:nil];
00250 }
00251
00252 - (void)loadHTMLString:(CPString)aString baseURL:(CPURL)URL
00253 {
00254
00255
00256 [self _setScrollMode:CPWebViewScrollAppKit];
00257
00258 [self _startedLoading];
00259
00260 _ignoreLoadStart = YES;
00261 _ignoreLoadEnd = NO;
00262
00263 _url = null;
00264 _html = aString;
00265
00266 [self _load];
00267 }
00268
00269 - (void)_loadMainFrameURL
00270 {
00271 [self _setScrollMode:CPWebViewScrollNative];
00272
00273 [self _startedLoading];
00274
00275 _ignoreLoadStart = YES;
00276 _ignoreLoadEnd = NO;
00277
00278 _url = _mainFrameURL;
00279 _html = null;
00280
00281 [self _load];
00282 }
00283
00284 - (void)_load
00285 {
00286 if (_url)
00287 {
00288 _iframe.src = _url;
00289 }
00290 else if (_html)
00291 {
00292
00293 _iframe.src = "";
00294
00295
00296 window.setTimeout(function() {
00297 var win = [self DOMWindow];
00298
00299 win.document.write(_html);
00300
00301 window.setTimeout(_loadCallback, 1);
00302 }, 0);
00303 }
00304 }
00305
00306 - (void)_startedLoading
00307 {
00308 [[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressStartedNotification object:self];
00309
00310 if ([_frameLoadDelegate respondsToSelector:@selector(webView:didStartProvisionalLoadForFrame:)])
00311 [_frameLoadDelegate webView:self didStartProvisionalLoadForFrame:nil];
00312 }
00313
00314 - (void)_finishedLoading
00315 {
00316 [self _resizeWebFrame];
00317
00318 [[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self];
00319
00320 if ([_frameLoadDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)])
00321 [_frameLoadDelegate webView:self didFinishLoadForFrame:nil];
00322 }
00323
00324 - (CPString)mainFrameURL
00325 {
00326 return _mainFrameURL;
00327 }
00328
00329 - (void)setMainFrameURL:(CPString)URLString
00330 {
00331 if (_mainFrameURL)
00332 [_backwardStack addObject:_mainFrameURL];
00333 _mainFrameURL = URLString;
00334 [_forwardStack removeAllObjects];
00335
00336 [self _loadMainFrameURL];
00337 }
00338
00339 - (BOOL)goBack
00340 {
00341 if (_backwardStack.length > 0)
00342 {
00343 if (_mainFrameURL)
00344 [_forwardStack addObject:_mainFrameURL];
00345 _mainFrameURL = [_backwardStack lastObject];
00346 [_backwardStack removeLastObject];
00347
00348 [self _loadMainFrameURL];
00349
00350 return YES;
00351 }
00352 return NO;
00353 }
00354
00355 - (BOOL)goForward
00356 {
00357 if (_forwardStack.length > 0)
00358 {
00359 if (_mainFrameURL)
00360 [_backwardStack addObject:_mainFrameURL];
00361 _mainFrameURL = [_forwardStack lastObject];
00362 [_forwardStack removeLastObject];
00363
00364 [self _loadMainFrameURL];
00365
00366 return YES;
00367 }
00368 return NO;
00369 }
00370
00371 - (BOOL)canGoBack
00372 {
00373 return (_backwardStack.length > 0);
00374 }
00375
00376 - (BOOL)canGoForward
00377 {
00378 return (_forwardStack.length > 0);
00379 }
00380
00381 - (WebBackForwardList)backForwardList
00382 {
00383
00384 return { back: _backwardStack, forward: _forwardStack };
00385 }
00386
00387 - (void)close
00388 {
00389 _iframe.parentNode.removeChild(_iframe);
00390 }
00391
00392 - (DOMWindow)DOMWindow
00393 {
00394 return (_iframe.contentDocument && _iframe.contentDocument.defaultView) || _iframe.contentWindow;
00395 }
00396
00397 - (CPWebScriptObject)windowScriptObject
00398 {
00399 var win = [self DOMWindow];
00400 if (!_wso || win != [_wso window])
00401 {
00402 if (win)
00403 _wso = [[CPWebScriptObject alloc] initWithWindow:win];
00404 else
00405 _wso = nil;
00406 }
00407 return _wso;
00408 }
00409
00410 - (CPString)stringByEvaluatingJavaScriptFromString:(CPString)script
00411 {
00412 var result = [self objectByEvaluatingJavaScriptFromString:script];
00413 return result ? String(result) : nil;
00414 }
00415
00416 - (JSObject)objectByEvaluatingJavaScriptFromString:(CPString)script
00417 {
00418 return [[self windowScriptObject] evaluateWebScript:script];
00419 }
00420
00421 - (DOMCSSStyleDeclaration)computedStyleForElement:(DOMElement)element pseudoElement:(CPString)pseudoElement
00422 {
00423 var win = [[self windowScriptObject] window];
00424 if (win)
00425 {
00426
00427 return win.document.defaultView.getComputedStyle(element, pseudoElement);
00428 }
00429 return nil;
00430 }
00431
00432
00433
00434 - (BOOL)drawsBackground
00435 {
00436 return _iframe.style.backgroundColor != "";
00437 }
00438
00439 - (void)setDrawsBackground:(BOOL)drawsBackround
00440 {
00441 _iframe.style.backgroundColor = drawsBackround ? "white" : "";
00442 }
00443
00444
00445
00446
00447
00448 - (IBAction)takeStringURLFrom:(id)sender
00449 {
00450 [self setMainFrameURL:[sender stringValue]];
00451 }
00452
00453 - (IBAction)goBack:(id)sender
00454 {
00455 [self goBack];
00456 }
00457
00458 - (IBAction)goForward:(id)sender
00459 {
00460 [self goForward];
00461 }
00462
00463 - (IBAction)stopLoading:(id)sender
00464 {
00465
00466 }
00467
00468 - (IBAction)reload:(id)sender
00469 {
00470 [self _loadMainFrameURL];
00471 }
00472
00473 - (IBAction)print:(id)sender
00474 {
00475 try
00476 {
00477 [self DOMWindow].print();
00478 }
00479 catch (e)
00480 {
00481 alert('Please click the webpage and select "Print" from the "File" menu');
00482 }
00483 }
00484
00485
00486
00487
00488
00489
00490 - (id)downloadDelegate
00491 {
00492 return _downloadDelegate;
00493 }
00494 - (void)setDownloadDelegate:(id)anObject
00495 {
00496 _downloadDelegate = anObject;
00497 }
00498 - (id)frameLoadDelegate
00499 {
00500 return _frameLoadDelegate;
00501 }
00502 - (void)setFrameLoadDelegate:(id)anObject
00503 {
00504 _frameLoadDelegate = anObject;
00505 }
00506 - (id)policyDelegate
00507 {
00508 return _policyDelegate;
00509 }
00510 - (void)setPolicyDelegate:(id)anObject
00511 {
00512 _policyDelegate = anObject;
00513 }
00514 - (id)resourceLoadDelegate
00515 {
00516 return _resourceLoadDelegate;
00517 }
00518 - (void)setResourceLoadDelegate:(id)anObject
00519 {
00520 _resourceLoadDelegate = anObject;
00521 }
00522 - (id)UIDelegate
00523 {
00524 return _UIDelegate;
00525 }
00526 - (void)setUIDelegate:(id)anObject
00527 {
00528 _UIDelegate = anObject;
00529 }
00530
00531 @end
00532
00533
00534 @implementation CPWebScriptObject : CPObject
00535 {
00536 Window _window;
00537 }
00538
00539 - (id)initWithWindow:(Window)aWindow
00540 {
00541 if (self = [super init])
00542 {
00543 _window = aWindow;
00544 }
00545 return self;
00546 }
00547
00548 - (id)callWebScriptMethod:(CPString)methodName withArguments:(CPArray)args
00549 {
00550
00551 if (typeof _window[methodName] == "function")
00552 {
00553 try {
00554 return _window[methodName].apply(args);
00555 } catch (e) {
00556 }
00557 }
00558 return undefined;
00559 }
00560
00561 - (id)evaluateWebScript:(CPString)script
00562 {
00563 try {
00564 return _window.eval(script);
00565 } catch (e) {
00566 }
00567 return undefined;
00568 }
00569
00570 - (Window)window
00571 {
00572 return _window;
00573 }
00574
00575 @end
00576
00577
00578 @implementation CPWebView (CPCoding)
00579
00585 - (id)initWithCoder:(CPCoder)aCoder
00586 {
00587 self = [super initWithCoder:aCoder];
00588
00589 if (self)
00590 {
00591
00592 _mainFrameURL = nil;
00593 _backwardStack = [];
00594 _forwardStack = [];
00595 _scrollMode = CPWebViewScrollNative;
00596
00597 #if PLATFORM(DOM)
00598 [self _initDOMWithFrame:[self frame]];
00599 #endif
00600
00601 [self setBackgroundColor:[CPColor whiteColor]];
00602 }
00603
00604 return self;
00605 }
00606
00611 - (void)encodeWithCoder:(CPCoder)aCoder
00612 {
00613 var actualSubviews = _subviews;
00614 _subviews = [];
00615 [super encodeWithCoder:aCoder];
00616 _subviews = actualSubviews;
00617 }
00618
00619 @end