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 [_frameView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
00154
00155 _scrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
00156 [_scrollView setAutohidesScrollers:YES];
00157 [_scrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
00158 [_scrollView setDocumentView:_frameView];
00159
00160 _frameView._DOMElement.appendChild(_iframe);
00161
00162 [self _setScrollMode:_scrollMode];
00163
00164 [self addSubview:_scrollView];
00165 }
00166
00167
00168 - (void)setFrameSize:(CPSize)aSize
00169 {
00170 [super setFrameSize:aSize];
00171 [self _resizeWebFrame];
00172 }
00173
00174 - (BOOL)_resizeWebFrame
00175 {
00176 if (_scrollMode === CPWebViewScrollAppKit)
00177 {
00178 if (_scrollSize)
00179 {
00180 [_frameView setFrameSize:_scrollSize];
00181 }
00182 else
00183 {
00184 [_frameView setFrameSize:[_scrollView contentSize]];
00185
00186
00187 var win = null;
00188 try { win = [self DOMWindow]; } catch (e) {}
00189
00190 if (win && win.document)
00191 {
00192 var width = win.document.body.scrollWidth,
00193 height = win.document.body.scrollHeight;
00194
00195 _iframe.setAttribute("width", width);
00196 _iframe.setAttribute("height", height);
00197
00198 [_frameView setFrameSize:CGSizeMake(width, height)];
00199 }
00200 else
00201 {
00202 CPLog.warn("using default size 800*1600");
00203
00204 [_frameView setFrameSize:CGSizeMake(800, 1600)];
00205 }
00206 }
00207 }
00208 }
00209
00210 - (void)setScrollMode:(int)aScrollMode
00211 {
00212 if (_scrollMode == aScrollMode)
00213 return;
00214
00215 [self _setScrollMode:aScrollMode];
00216 }
00217
00218 - (void)_setScrollMode:(int)aScrollMode
00219 {
00220 _scrollMode = aScrollMode;
00221
00222 _ignoreLoadStart = YES;
00223 _ignoreLoadEnd = YES;
00224
00225 var parent = _iframe.parentNode;
00226 parent.removeChild(_iframe);
00227
00228 if (_scrollMode === CPWebViewScrollAppKit)
00229 {
00230 [_scrollView setHasHorizontalScroller:YES];
00231 [_scrollView setHasVerticalScroller:YES];
00232
00233 _iframe.setAttribute("scrolling", "no");
00234 }
00235 else
00236 {
00237 [_scrollView setHasHorizontalScroller:NO];
00238 [_scrollView setHasVerticalScroller:NO];
00239
00240 _iframe.setAttribute("scrolling", "auto");
00241
00242 [_frameView setFrameSize:[_scrollView bounds].size];
00243 }
00244
00245 parent.appendChild(_iframe);
00246 }
00247
00248 - (void)loadHTMLString:(CPString)aString
00249 {
00250 [self loadHTMLString:aString baseURL:nil];
00251 }
00252
00253 - (void)loadHTMLString:(CPString)aString baseURL:(CPURL)URL
00254 {
00255
00256
00257 [self _setScrollMode:CPWebViewScrollAppKit];
00258
00259 [self _startedLoading];
00260
00261 _ignoreLoadStart = YES;
00262 _ignoreLoadEnd = NO;
00263
00264 _url = null;
00265 _html = aString;
00266
00267 [self _load];
00268 }
00269
00270 - (void)_loadMainFrameURL
00271 {
00272 [self _setScrollMode:CPWebViewScrollNative];
00273
00274 [self _startedLoading];
00275
00276 _ignoreLoadStart = YES;
00277 _ignoreLoadEnd = NO;
00278
00279 _url = _mainFrameURL;
00280 _html = null;
00281
00282 [self _load];
00283 }
00284
00285 - (void)_load
00286 {
00287 if (_url)
00288 {
00289 _iframe.src = _url;
00290 }
00291 else if (_html)
00292 {
00293
00294 _iframe.src = "";
00295
00296
00297 window.setTimeout(function() {
00298 var win = [self DOMWindow];
00299
00300 win.document.write(_html);
00301
00302 window.setTimeout(_loadCallback, 1);
00303 }, 0);
00304 }
00305 }
00306
00307 - (void)_startedLoading
00308 {
00309 [[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressStartedNotification object:self];
00310
00311 if ([_frameLoadDelegate respondsToSelector:@selector(webView:didStartProvisionalLoadForFrame:)])
00312 [_frameLoadDelegate webView:self didStartProvisionalLoadForFrame:nil];
00313 }
00314
00315 - (void)_finishedLoading
00316 {
00317 [self _resizeWebFrame];
00318
00319 [[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self];
00320
00321 if ([_frameLoadDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)])
00322 [_frameLoadDelegate webView:self didFinishLoadForFrame:nil];
00323 }
00324
00325 - (CPString)mainFrameURL
00326 {
00327 return _mainFrameURL;
00328 }
00329
00330 - (void)setMainFrameURL:(CPString)URLString
00331 {
00332 if (_mainFrameURL)
00333 [_backwardStack addObject:_mainFrameURL];
00334 _mainFrameURL = URLString;
00335 [_forwardStack removeAllObjects];
00336
00337 [self _loadMainFrameURL];
00338 }
00339
00340 - (BOOL)goBack
00341 {
00342 if (_backwardStack.length > 0)
00343 {
00344 if (_mainFrameURL)
00345 [_forwardStack addObject:_mainFrameURL];
00346 _mainFrameURL = [_backwardStack lastObject];
00347 [_backwardStack removeLastObject];
00348
00349 [self _loadMainFrameURL];
00350
00351 return YES;
00352 }
00353 return NO;
00354 }
00355
00356 - (BOOL)goForward
00357 {
00358 if (_forwardStack.length > 0)
00359 {
00360 if (_mainFrameURL)
00361 [_backwardStack addObject:_mainFrameURL];
00362 _mainFrameURL = [_forwardStack lastObject];
00363 [_forwardStack removeLastObject];
00364
00365 [self _loadMainFrameURL];
00366
00367 return YES;
00368 }
00369 return NO;
00370 }
00371
00372 - (BOOL)canGoBack
00373 {
00374 return (_backwardStack.length > 0);
00375 }
00376
00377 - (BOOL)canGoForward
00378 {
00379 return (_forwardStack.length > 0);
00380 }
00381
00382 - (WebBackForwardList)backForwardList
00383 {
00384
00385 return { back: _backwardStack, forward: _forwardStack };
00386 }
00387
00388 - (void)close
00389 {
00390 _iframe.parentNode.removeChild(_iframe);
00391 }
00392
00393 - (DOMWindow)DOMWindow
00394 {
00395 return (_iframe.contentDocument && _iframe.contentDocument.defaultView) || _iframe.contentWindow;
00396 }
00397
00398 - (CPWebScriptObject)windowScriptObject
00399 {
00400 var win = [self DOMWindow];
00401 if (!_wso || win != [_wso window])
00402 {
00403 if (win)
00404 _wso = [[CPWebScriptObject alloc] initWithWindow:win];
00405 else
00406 _wso = nil;
00407 }
00408 return _wso;
00409 }
00410
00411 - (CPString)stringByEvaluatingJavaScriptFromString:(CPString)script
00412 {
00413 var result = [self objectByEvaluatingJavaScriptFromString:script];
00414 return result ? String(result) : nil;
00415 }
00416
00417 - (JSObject)objectByEvaluatingJavaScriptFromString:(CPString)script
00418 {
00419 return [[self windowScriptObject] evaluateWebScript:script];
00420 }
00421
00422 - (DOMCSSStyleDeclaration)computedStyleForElement:(DOMElement)element pseudoElement:(CPString)pseudoElement
00423 {
00424 var win = [[self windowScriptObject] window];
00425 if (win)
00426 {
00427
00428 return win.document.defaultView.getComputedStyle(element, pseudoElement);
00429 }
00430 return nil;
00431 }
00432
00433
00434
00435 - (BOOL)drawsBackground
00436 {
00437 return _iframe.style.backgroundColor != "";
00438 }
00439
00440 - (void)setDrawsBackground:(BOOL)drawsBackround
00441 {
00442 _iframe.style.backgroundColor = drawsBackround ? "white" : "";
00443 }
00444
00445
00446
00447
00448
00449 - (IBAction)takeStringURLFrom:(id)sender
00450 {
00451 [self setMainFrameURL:[sender stringValue]];
00452 }
00453
00454 - (IBAction)goBack:(id)sender
00455 {
00456 [self goBack];
00457 }
00458
00459 - (IBAction)goForward:(id)sender
00460 {
00461 [self goForward];
00462 }
00463
00464 - (IBAction)stopLoading:(id)sender
00465 {
00466
00467 }
00468
00469 - (IBAction)reload:(id)sender
00470 {
00471 [self _loadMainFrameURL];
00472 }
00473
00474 - (IBAction)print:(id)sender
00475 {
00476 try
00477 {
00478 [self DOMWindow].print();
00479 }
00480 catch (e)
00481 {
00482 alert('Please click the webpage and select "Print" from the "File" menu');
00483 }
00484 }
00485
00486
00487
00488
00489
00490
00491 - (id)downloadDelegate
00492 {
00493 return _downloadDelegate;
00494 }
00495 - (void)setDownloadDelegate:(id)anObject
00496 {
00497 _downloadDelegate = anObject;
00498 }
00499 - (id)frameLoadDelegate
00500 {
00501 return _frameLoadDelegate;
00502 }
00503 - (void)setFrameLoadDelegate:(id)anObject
00504 {
00505 _frameLoadDelegate = anObject;
00506 }
00507 - (id)policyDelegate
00508 {
00509 return _policyDelegate;
00510 }
00511 - (void)setPolicyDelegate:(id)anObject
00512 {
00513 _policyDelegate = anObject;
00514 }
00515 - (id)resourceLoadDelegate
00516 {
00517 return _resourceLoadDelegate;
00518 }
00519 - (void)setResourceLoadDelegate:(id)anObject
00520 {
00521 _resourceLoadDelegate = anObject;
00522 }
00523 - (id)UIDelegate
00524 {
00525 return _UIDelegate;
00526 }
00527 - (void)setUIDelegate:(id)anObject
00528 {
00529 _UIDelegate = anObject;
00530 }
00531
00532 @end
00533
00534
00535 @implementation CPWebScriptObject : CPObject
00536 {
00537 Window _window;
00538 }
00539
00540 - (id)initWithWindow:(Window)aWindow
00541 {
00542 if (self = [super init])
00543 {
00544 _window = aWindow;
00545 }
00546 return self;
00547 }
00548
00549 - (id)callWebScriptMethod:(CPString)methodName withArguments:(CPArray)args
00550 {
00551
00552 if (typeof _window[methodName] == "function")
00553 {
00554 try {
00555 return _window[methodName].apply(args);
00556 } catch (e) {
00557 }
00558 }
00559 return undefined;
00560 }
00561
00562 - (id)evaluateWebScript:(CPString)script
00563 {
00564 try {
00565 return _window.eval(script);
00566 } catch (e) {
00567 }
00568 return undefined;
00569 }
00570
00571 - (Window)window
00572 {
00573 return _window;
00574 }
00575
00576 @end
00577
00578
00579 @implementation CPWebView (CPCoding)
00580
00586 - (id)initWithCoder:(CPCoder)aCoder
00587 {
00588 self = [super initWithCoder:aCoder];
00589
00590 if (self)
00591 {
00592
00593 _mainFrameURL = nil;
00594 _backwardStack = [];
00595 _forwardStack = [];
00596 _scrollMode = CPWebViewScrollNative;
00597
00598 #if PLATFORM(DOM)
00599 [self _initDOMWithFrame:[self frame]];
00600 #endif
00601
00602 [self setBackgroundColor:[CPColor whiteColor]];
00603 }
00604
00605 return self;
00606 }
00607
00612 - (void)encodeWithCoder:(CPCoder)aCoder
00613 {
00614 var actualSubviews = _subviews;
00615 _subviews = [];
00616 [super encodeWithCoder:aCoder];
00617 _subviews = actualSubviews;
00618 }
00619
00620 @end