-
-
Save mralexgray/1525568 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FROM: http://svn.cocoasourcecode.com/SkinnableApp/AppController.m | |
// | |
// AppController.m | |
// SkinnableApp | |
// | |
// Created by Matt Gemmell on 24/02/2008. | |
// Copyright 2008 Magic Aubergine. All rights reserved. | |
// | |
#import "AppController.h" | |
@implementation AppController | |
#pragma mark Setup | |
- (void)awakeFromNib | |
{ | |
// Set us up as the delegate of the webView for relevant events. | |
[webView setDrawsBackground:NO]; | |
[webView setUIDelegate:self]; | |
[webView setFrameLoadDelegate:self]; | |
[webView setEditingDelegate:self]; | |
// Configure webView to let JavaScript talk to this object. | |
[[webView windowScriptObject] setValue:self forKey:@"AppController"]; // can be any unique name you want | |
/* | |
Notes: | |
1. In JavaScript, you can now talk to this object using "window.AppController". | |
2. You must explicitly allow methods to be called from JavaScript; | |
See the +isSelectorExcludedFromWebScript: method below for an example. | |
3. The method on this class which we call from JavaScript is -showMessage: | |
To call it from JavaScript, we use window.AppController.showMessage_() <-- NOTE colon becomes underscore! | |
For more on method-name translation, see: | |
http://developer.apple.com/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html# | |
*/ | |
// Load the HTML content. | |
NSString *resourcesPath = [[NSBundle mainBundle] resourcePath]; | |
NSString *htmlPath = [resourcesPath stringByAppendingString:@"/index.html"]; | |
[[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]]]; | |
// Set up the themes chooser. | |
[themeChooser removeAllItems]; | |
NSArray *themes = [[NSBundle mainBundle] pathsForResourcesOfType:@"css" inDirectory:nil]; | |
for (NSString *theme in themes) { | |
// Get theme name without file-extension | |
NSString *themeName = [theme lastPathComponent]; | |
NSRange dotRange = [themeName rangeOfString:@"."]; | |
if (dotRange.location != NSNotFound) { | |
themeName = [themeName substringToIndex:dotRange.location]; | |
} | |
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:themeName | |
action:@selector(changeTheme:) | |
keyEquivalent:@""]; | |
[menuItem setTarget:self]; | |
[menuItem setRepresentedObject:[theme lastPathComponent]]; | |
if ([themeName isEqualToString:@"Default"]) { | |
[menuItem setState:NSOnState]; | |
} | |
[[themeChooser menu] addItem:menuItem]; | |
[menuItem release]; | |
} | |
} | |
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector | |
{ | |
// For security, you must explicitly allow a selector to be called from JavaScript. | |
if (aSelector == @selector(showMessage:)) { | |
return NO; // i.e. showMessage: is NOT _excluded_ from scripting, so it can be called. | |
} | |
return YES; // disallow everything else | |
} | |
#pragma mark WebView delegate methods | |
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame | |
{ | |
// This is a WebView Frame Load Delegate method. | |
// The HTML document just loaded, so we'll grab the current content of | |
// the 'contentTitle' H1 tag, and put it in the titleText NSTextField. | |
// This code shows you how to get a value from the HTML document. | |
DOMDocument *myDOMDocument = [[webView mainFrame] DOMDocument]; | |
DOMElement *contentTitle = [myDOMDocument getElementById:@"contentTitle"]; | |
[titleText setStringValue:[[contentTitle firstChild] nodeValue]]; | |
} | |
- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element | |
defaultMenuItems:(NSArray *)defaultMenuItems | |
{ | |
// This is a WebView UI Delegate method. | |
return nil; // disable contextual menu for the webView | |
} | |
- (BOOL)webView:(WebView *)webView shouldChangeSelectedDOMRange:(DOMRange *)currentRange | |
toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity | |
stillSelecting:(BOOL)flag | |
{ | |
// This is a WebView Editing Delegate method. | |
return NO; // prevent selection of content | |
} | |
#pragma mark IBActions | |
- (IBAction)changeTheme:(id)sender | |
{ | |
// The user just chose a theme in the NSPopUpButton, so we replace the HTML | |
// document's CSS file using JavaScript. This is a simple way to support | |
// dynamically loaded CSS themes. | |
WebScriptObject *scriptObject = [webView windowScriptObject]; | |
NSString *theme = [[themeChooser selectedItem] representedObject]; | |
NSString *script = [NSString stringWithFormat:@"document.getElementById('ss').href = '%@'", theme]; | |
[scriptObject evaluateWebScript:script]; | |
} | |
- (IBAction)addContent:(id)sender | |
{ | |
// The user just clicked the Add Content NSButton, so we'll add a new P tag | |
// to the HTML, with some default content. This shows you how to add content | |
// into an HTML document without reloading the page. | |
DOMDocument *myDOMDocument = [[webView mainFrame] DOMDocument]; | |
DOMElement *paraBlock = [myDOMDocument getElementById:@"main_content"]; | |
DOMElement *newPara = [myDOMDocument createElement:@"p"]; | |
DOMText *newText = [myDOMDocument createTextNode:@"Some new content"]; | |
[newPara appendChild:newText]; | |
[paraBlock appendChild:newPara]; | |
} | |
- (IBAction)setTitle:(id)sender { | |
// The user clicked the Set Title button, so we'll take whatever text is in | |
// the titleText NSTextField and replace the current content of the 'contentTitle' | |
// H1 tag in the HTML with the new text. This shows you how to replace some HTML | |
// content with new content. | |
DOMDocument *myDOMDocument = [[webView mainFrame] DOMDocument]; | |
DOMText *newText = [myDOMDocument createTextNode:[titleText stringValue]]; | |
DOMElement *contentTitle = [myDOMDocument getElementById:@"contentTitle"]; | |
[contentTitle replaceChild:newText oldChild:[contentTitle firstChild]]; | |
} | |
- (void)showMessage:(NSString *)message | |
{ | |
// This method is called from the JavaScript "onClick" handler of the INPUT element | |
// in the HTML. This shows you how to have HTML form elements call Cocoa methods. | |
NSRunAlertPanel(@"Message from JavaScript", message, nil, nil, nil); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment