aboutsummaryrefslogtreecommitdiffstats
path: root/iPhone/CordovaLib/Classes/CDVInAppBrowser.m
diff options
context:
space:
mode:
Diffstat (limited to 'iPhone/CordovaLib/Classes/CDVInAppBrowser.m')
-rwxr-xr-xiPhone/CordovaLib/Classes/CDVInAppBrowser.m370
1 files changed, 314 insertions, 56 deletions
diff --git a/iPhone/CordovaLib/Classes/CDVInAppBrowser.m b/iPhone/CordovaLib/Classes/CDVInAppBrowser.m
index 14671a5..b832e23 100755
--- a/iPhone/CordovaLib/Classes/CDVInAppBrowser.m
+++ b/iPhone/CordovaLib/Classes/CDVInAppBrowser.m
@@ -20,6 +20,7 @@
#import "CDVInAppBrowser.h"
#import "CDVPluginResult.h"
#import "CDVUserAgentUtil.h"
+#import "CDVJSON.h"
#define kInAppBrowserTargetSelf @"_self"
#define kInAppBrowserTargetSystem @"_system"
@@ -100,15 +101,19 @@
}
}
+
CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];
[self.inAppBrowserViewController showLocationBar:browserOptions.location];
-
+ [self.inAppBrowserViewController showToolBar:browserOptions.toolbar];
+ if (browserOptions.closebuttoncaption != nil) {
+ [self.inAppBrowserViewController setCloseButtonTitle:browserOptions.closebuttoncaption];
+ }
// Set Presentation Style
UIModalPresentationStyle presentationStyle = UIModalPresentationFullScreen; // default
if (browserOptions.presentationstyle != nil) {
- if ([browserOptions.presentationstyle isEqualToString:@"pagesheet"]) {
+ if ([[browserOptions.presentationstyle lowercaseString] isEqualToString:@"pagesheet"]) {
presentationStyle = UIModalPresentationPageSheet;
- } else if ([browserOptions.presentationstyle isEqualToString:@"formsheet"]) {
+ } else if ([[browserOptions.presentationstyle lowercaseString] isEqualToString:@"formsheet"]) {
presentationStyle = UIModalPresentationFormSheet;
}
}
@@ -117,14 +122,15 @@
// Set Transition Style
UIModalTransitionStyle transitionStyle = UIModalTransitionStyleCoverVertical; // default
if (browserOptions.transitionstyle != nil) {
- if ([browserOptions.transitionstyle isEqualToString:@"fliphorizontal"]) {
+ if ([[browserOptions.transitionstyle lowercaseString] isEqualToString:@"fliphorizontal"]) {
transitionStyle = UIModalTransitionStyleFlipHorizontal;
- } else if ([browserOptions.transitionstyle isEqualToString:@"crossdissolve"]) {
+ } else if ([[browserOptions.transitionstyle lowercaseString] isEqualToString:@"crossdissolve"]) {
transitionStyle = UIModalTransitionStyleCrossDissolve;
}
}
self.inAppBrowserViewController.modalTransitionStyle = transitionStyle;
+
// UIWebView options
self.inAppBrowserViewController.webView.scalesPageToFit = browserOptions.enableviewportscale;
self.inAppBrowserViewController.webView.mediaPlaybackRequiresUserAction = browserOptions.mediaplaybackrequiresuseraction;
@@ -133,13 +139,20 @@
self.inAppBrowserViewController.webView.keyboardDisplayRequiresUserAction = browserOptions.keyboarddisplayrequiresuseraction;
self.inAppBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering;
}
-
- if (self.viewController.modalViewController != self.inAppBrowserViewController) {
+
+ if (! browserOptions.hidden) {
+ if (self.viewController.modalViewController != self.inAppBrowserViewController) {
[self.viewController presentModalViewController:self.inAppBrowserViewController animated:YES];
+ }
}
[self.inAppBrowserViewController navigateTo:url];
}
+- (void)show:(CDVInvokedUrlCommand*)command
+{
+ [self.viewController presentModalViewController:self.inAppBrowserViewController animated:YES];
+}
+
- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
{
if ([self.commandDelegate URLIsWhitelisted:url]) {
@@ -159,24 +172,162 @@
}
}
-#pragma mark CDVInAppBrowserNavigationDelegate
+// This is a helper method for the inject{Script|Style}{Code|File} API calls, which
+// provides a consistent method for injecting JavaScript code into the document.
+//
+// If a wrapper string is supplied, then the source string will be JSON-encoded (adding
+// quotes) and wrapped using string formatting. (The wrapper string should have a single
+// '%@' marker).
+//
+// If no wrapper is supplied, then the source string is executed directly.
-- (void)browserLoadStart:(NSURL*)url
+- (void)injectDeferredObject:(NSString*)source withWrapper:(NSString*)jsWrapper
{
- if (self.callbackId != nil) {
+ if (!_injectedIframeBridge) {
+ _injectedIframeBridge = YES;
+ // Create an iframe bridge in the new document to communicate with the CDVInAppBrowserViewController
+ [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:@"(function(d){var e = _cdvIframeBridge = d.createElement('iframe');e.style.display='none';d.body.appendChild(e);})(document)"];
+ }
+
+ if (jsWrapper != nil) {
+ NSString* sourceArrayString = [@[source] JSONString];
+ if (sourceArrayString) {
+ NSString* sourceString = [sourceArrayString substringWithRange:NSMakeRange(1, [sourceArrayString length] - 2)];
+ NSString* jsToInject = [NSString stringWithFormat:jsWrapper, sourceString];
+ [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:jsToInject];
+ }
+ } else {
+ [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:source];
+ }
+}
+
+- (void)injectScriptCode:(CDVInvokedUrlCommand*)command
+{
+ NSString* jsWrapper = nil;
+
+ if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+ jsWrapper = [NSString stringWithFormat:@"_cdvIframeBridge.src='gap-iab://%@/'+window.escape(JSON.stringify([eval(%%@)]));", command.callbackId];
+ }
+ [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectScriptFile:(CDVInvokedUrlCommand*)command
+{
+ NSString* jsWrapper;
+
+ if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+ jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('script'); c.src = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+ } else {
+ jsWrapper = @"(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document)";
+ }
+ [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectStyleCode:(CDVInvokedUrlCommand*)command
+{
+ NSString* jsWrapper;
+
+ if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+ jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('style'); c.innerHTML = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+ } else {
+ jsWrapper = @"(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document)";
+ }
+ [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectStyleFile:(CDVInvokedUrlCommand*)command
+{
+ NSString* jsWrapper;
+
+ if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+ jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+ } else {
+ jsWrapper = @"(function(d) { var c = d.createElement('link'); c.rel='stylesheet', c.type='text/css'; c.href = %@; d.body.appendChild(c); })(document)";
+ }
+ [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+/**
+ * The iframe bridge provided for the InAppBrowser is capable of executing any oustanding callback belonging
+ * to the InAppBrowser plugin. Care has been taken that other callbacks cannot be triggered, and that no
+ * other code execution is possible.
+ *
+ * To trigger the bridge, the iframe (or any other resource) should attempt to load a url of the form:
+ *
+ * gap-iab://<callbackId>/<arguments>
+ *
+ * where <callbackId> is the string id of the callback to trigger (something like "InAppBrowser0123456789")
+ *
+ * If present, the path component of the special gap-iab:// url is expected to be a URL-escaped JSON-encoded
+ * value to pass to the callback. [NSURL path] should take care of the URL-unescaping, and a JSON_EXCEPTION
+ * is returned if the JSON is invalid.
+ */
+- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+ NSURL* url = request.URL;
+ BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
+
+ // See if the url uses the 'gap-iab' protocol. If so, the host should be the id of a callback to execute,
+ // and the path, if present, should be a JSON-encoded value to pass to the callback.
+ if ([[url scheme] isEqualToString:@"gap-iab"]) {
+ NSString* scriptCallbackId = [url host];
+ CDVPluginResult* pluginResult = nil;
+
+ if ([scriptCallbackId hasPrefix:@"InAppBrowser"]) {
+ NSString* scriptResult = [url path];
+ NSError* __autoreleasing error = nil;
+
+ // The message should be a JSON-encoded array of the result of the script which executed.
+ if ((scriptResult != nil) && ([scriptResult length] > 1)) {
+ scriptResult = [scriptResult substringFromIndex:1];
+ NSData* decodedResult = [NSJSONSerialization JSONObjectWithData:[scriptResult dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
+ if ((error == nil) && [decodedResult isKindOfClass:[NSArray class]]) {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:(NSArray*)decodedResult];
+ } else {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_JSON_EXCEPTION];
+ }
+ } else {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:@[]];
+ }
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:scriptCallbackId];
+ return NO;
+ }
+ } else if ((self.callbackId != nil) && isTopLevelNavigation) {
+ // Send a loadstart event for each top-level navigation (includes redirects).
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
- messageAsDictionary:@ {@"type":@"loadstart", @"url":[url absoluteString]}];
+ messageAsDictionary:@{@"type":@"loadstart", @"url":[url absoluteString]}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
}
+
+ return YES;
}
-- (void)browserLoadStop:(NSURL*)url
+- (void)webViewDidStartLoad:(UIWebView*)theWebView
+{
+ _injectedIframeBridge = NO;
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)theWebView
{
if (self.callbackId != nil) {
+ // TODO: It would be more useful to return the URL the page is actually on (e.g. if it's been redirected).
+ NSString* url = [self.inAppBrowserViewController.currentURL absoluteString];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
- messageAsDictionary:@ {@"type":@"loadstop", @"url":[url absoluteString]}];
+ messageAsDictionary:@{@"type":@"loadstop", @"url":url}];
+ [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+ }
+}
+
+- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+{
+ if (self.callbackId != nil) {
+ NSString* url = [self.inAppBrowserViewController.currentURL absoluteString];
+ CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
+ messageAsDictionary:@{@"type":@"loaderror", @"url":url, @"code": [NSNumber numberWithInt:error.code], @"message": error.localizedDescription}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
@@ -187,7 +338,7 @@
{
if (self.callbackId != nil) {
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
- messageAsDictionary:@ {@"type":@"exit"}];
+ messageAsDictionary:@{@"type":@"exit"}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
@@ -203,12 +354,15 @@
@implementation CDVInAppBrowserViewController
+@synthesize currentURL;
+
- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent
{
self = [super init];
if (self != nil) {
_userAgent = userAgent;
_prevUserAgent = prevUserAgent;
+ _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self];
[self createViews];
}
@@ -229,7 +383,7 @@
[self.view addSubview:self.webView];
[self.view sendSubviewToBack:self.webView];
- self.webView.delegate = self;
+ self.webView.delegate = _webViewDelegate;
self.webView.backgroundColor = [UIColor whiteColor];
self.webView.clearsContextBeforeDrawing = YES;
@@ -259,9 +413,6 @@
self.closeButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)];
self.closeButton.enabled = YES;
- self.closeButton.imageInsets = UIEdgeInsetsZero;
- self.closeButton.style = UIBarButtonItemStylePlain;
- self.closeButton.width = 32.000;
UIBarButtonItem* flexibleSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
@@ -325,32 +476,132 @@
[self.view addSubview:self.spinner];
}
+- (void)setCloseButtonTitle:(NSString*)title
+{
+ // the advantage of using UIBarButtonSystemItemDone is the system will localize it for you automatically
+ // but, if you want to set this yourself, knock yourself out (we can't set the title for a system Done button, so we have to create a new one)
+ self.closeButton = nil;
+ self.closeButton = [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStyleBordered target:self action:@selector(close)];
+ self.closeButton.enabled = YES;
+ self.closeButton.tintColor = [UIColor colorWithRed:60.0 / 255.0 green:136.0 / 255.0 blue:230.0 / 255.0 alpha:1];
+
+ NSMutableArray* items = [self.toolbar.items mutableCopy];
+ [items replaceObjectAtIndex:0 withObject:self.closeButton];
+ [self.toolbar setItems:items];
+}
+
- (void)showLocationBar:(BOOL)show
{
- CGRect addressLabelFrame = self.addressLabel.frame;
- BOOL locationBarVisible = (addressLabelFrame.size.height > 0);
+ CGRect locationbarFrame = self.addressLabel.frame;
+
+ BOOL toolbarVisible = !self.toolbar.hidden;
+
+ // prevent double show/hide
+ if (show == !(self.addressLabel.hidden)) {
+ return;
+ }
+
+ if (show) {
+ self.addressLabel.hidden = NO;
+
+ if (toolbarVisible) {
+ // toolBar at the bottom, leave as is
+ // put locationBar on top of the toolBar
+
+ CGRect webViewBounds = self.view.bounds;
+ webViewBounds.size.height -= FOOTER_HEIGHT;
+ self.webView.frame = webViewBounds;
+
+ locationbarFrame.origin.y = webViewBounds.size.height;
+ self.addressLabel.frame = locationbarFrame;
+ } else {
+ // no toolBar, so put locationBar at the bottom
+
+ CGRect webViewBounds = self.view.bounds;
+ webViewBounds.size.height -= LOCATIONBAR_HEIGHT;
+ self.webView.frame = webViewBounds;
+
+ locationbarFrame.origin.y = webViewBounds.size.height;
+ self.addressLabel.frame = locationbarFrame;
+ }
+ } else {
+ self.addressLabel.hidden = YES;
+
+ if (toolbarVisible) {
+ // locationBar is on top of toolBar, hide locationBar
+
+ // webView take up whole height less toolBar height
+ CGRect webViewBounds = self.view.bounds;
+ webViewBounds.size.height -= TOOLBAR_HEIGHT;
+ self.webView.frame = webViewBounds;
+ } else {
+ // no toolBar, expand webView to screen dimensions
+
+ CGRect webViewBounds = self.view.bounds;
+ self.webView.frame = webViewBounds;
+ }
+ }
+}
+
+- (void)showToolBar:(BOOL)show
+{
+ CGRect toolbarFrame = self.toolbar.frame;
+ CGRect locationbarFrame = self.addressLabel.frame;
+
+ BOOL locationbarVisible = !self.addressLabel.hidden;
// prevent double show/hide
- if (locationBarVisible == show) {
+ if (show == !(self.toolbar.hidden)) {
return;
}
if (show) {
- CGRect webViewBounds = self.view.bounds;
- webViewBounds.size.height -= FOOTER_HEIGHT;
- self.webView.frame = webViewBounds;
+ self.toolbar.hidden = NO;
+
+ if (locationbarVisible) {
+ // locationBar at the bottom, move locationBar up
+ // put toolBar at the bottom
+
+ CGRect webViewBounds = self.view.bounds;
+ webViewBounds.size.height -= FOOTER_HEIGHT;
+ self.webView.frame = webViewBounds;
+
+ locationbarFrame.origin.y = webViewBounds.size.height;
+ self.addressLabel.frame = locationbarFrame;
- CGRect addressLabelFrame = self.addressLabel.frame;
- addressLabelFrame.size.height = LOCATIONBAR_HEIGHT;
- self.addressLabel.frame = addressLabelFrame;
+ toolbarFrame.origin.y = (webViewBounds.size.height + LOCATIONBAR_HEIGHT);
+ self.toolbar.frame = toolbarFrame;
+ } else {
+ // no locationBar, so put toolBar at the bottom
+
+ CGRect webViewBounds = self.view.bounds;
+ webViewBounds.size.height -= TOOLBAR_HEIGHT;
+ self.webView.frame = webViewBounds;
+
+ toolbarFrame.origin.y = webViewBounds.size.height;
+ self.toolbar.frame = toolbarFrame;
+ }
} else {
- CGRect webViewBounds = self.view.bounds;
- webViewBounds.size.height -= TOOLBAR_HEIGHT;
- self.webView.frame = webViewBounds;
+ self.toolbar.hidden = YES;
- CGRect addressLabelFrame = self.addressLabel.frame;
- addressLabelFrame.size.height = 0;
- self.addressLabel.frame = addressLabelFrame;
+ if (locationbarVisible) {
+ // locationBar is on top of toolBar, hide toolBar
+ // put locationBar at the bottom
+
+ // webView take up whole height less locationBar height
+ CGRect webViewBounds = self.view.bounds;
+ webViewBounds.size.height -= LOCATIONBAR_HEIGHT;
+ self.webView.frame = webViewBounds;
+
+ // move locationBar down
+ locationbarFrame.origin.y = webViewBounds.size.height;
+ self.addressLabel.frame = locationbarFrame;
+ } else {
+ // no locationBar, expand webView to screen dimensions
+
+ CGRect webViewBounds = self.view.bounds;
+ self.webView.frame = webViewBounds;
+ }
}
}
@@ -376,6 +627,8 @@
[[self parentViewController] dismissModalViewControllerAnimated:YES];
}
+ self.currentURL = nil;
+
if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserExit)]) {
[self.navigationDelegate browserExit];
}
@@ -385,16 +638,14 @@
{
NSURLRequest* request = [NSURLRequest requestWithURL:url];
- _requestedURL = url;
-
if (_userAgentLockToken != 0) {
[self.webView loadRequest:request];
} else {
[CDVUserAgentUtil acquireLock:^(NSInteger lockToken) {
- _userAgentLockToken = lockToken;
- [CDVUserAgentUtil setUserAgent:_userAgent lockToken:lockToken];
- [self.webView loadRequest:request];
- }];
+ _userAgentLockToken = lockToken;
+ [CDVUserAgentUtil setUserAgent:_userAgent lockToken:lockToken];
+ [self.webView loadRequest:request];
+ }];
}
}
@@ -420,20 +671,24 @@
[self.spinner startAnimating];
- if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserLoadStart:)]) {
- NSURL* url = theWebView.request.URL;
- if (url == nil) {
- url = _requestedURL;
- }
- [self.navigationDelegate browserLoadStart:url];
+ return [self.navigationDelegate webViewDidStartLoad:theWebView];
+}
+
+- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+ BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
+
+ if (isTopLevelNavigation) {
+ self.currentURL = request.URL;
}
+ return [self.navigationDelegate webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
}
- (void)webViewDidFinishLoad:(UIWebView*)theWebView
{
// update url, stop spinner, update back/forward
- self.addressLabel.text = theWebView.request.URL.absoluteString;
+ self.addressLabel.text = [self.currentURL absoluteString];
self.backButton.enabled = theWebView.canGoBack;
self.forwardButton.enabled = theWebView.canGoForward;
@@ -450,15 +705,12 @@
// from it must pass through its white-list. This *does* break PDFs that
// contain links to other remote PDF/websites.
// More info at https://issues.apache.org/jira/browse/CB-2225
- BOOL isPDF = [@"true" isEqualToString:[theWebView stringByEvaluatingJavaScriptFromString:@"document.body==null"]];
+ BOOL isPDF = [@"true" isEqualToString :[theWebView stringByEvaluatingJavaScriptFromString:@"document.body==null"]];
if (isPDF) {
[CDVUserAgentUtil setUserAgent:_prevUserAgent lockToken:_userAgentLockToken];
}
- if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserLoadStop:)]) {
- NSURL* url = theWebView.request.URL;
- [self.navigationDelegate browserLoadStop:url];
- }
+ [self.navigationDelegate webViewDidFinishLoad:theWebView];
}
- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
@@ -471,6 +723,8 @@
[self.spinner stopAnimating];
self.addressLabel.text = @"Load Error";
+
+ [self.navigationDelegate webView:theWebView didFailLoadWithError:error];
}
#pragma mark CDVScreenOrientationDelegate
@@ -510,12 +764,15 @@
if (self = [super init]) {
// default values
self.location = YES;
+ self.toolbar = YES;
+ self.closebuttoncaption = nil;
self.enableviewportscale = NO;
self.mediaplaybackrequiresuseraction = NO;
self.allowinlinemediaplayback = NO;
self.keyboarddisplayrequiresuseraction = YES;
self.suppressesincrementalrendering = NO;
+ self.hidden = NO;
}
return self;
@@ -534,19 +791,20 @@
if ([keyvalue count] == 2) {
NSString* key = [[keyvalue objectAtIndex:0] lowercaseString];
- NSString* value = [[keyvalue objectAtIndex:1] lowercaseString];
+ NSString* value = [keyvalue objectAtIndex:1];
+ NSString* value_lc = [value lowercaseString];
- BOOL isBoolean = [value isEqualToString:@"yes"] || [value isEqualToString:@"no"];
+ BOOL isBoolean = [value_lc isEqualToString:@"yes"] || [value_lc isEqualToString:@"no"];
NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setAllowsFloats:YES];
- BOOL isNumber = [numberFormatter numberFromString:value] != nil;
+ BOOL isNumber = [numberFormatter numberFromString:value_lc] != nil;
// set the property according to the key name
if ([obj respondsToSelector:NSSelectorFromString(key)]) {
if (isNumber) {
- [obj setValue:[numberFormatter numberFromString:value] forKey:key];
+ [obj setValue:[numberFormatter numberFromString:value_lc] forKey:key];
} else if (isBoolean) {
- [obj setValue:[NSNumber numberWithBool:[value isEqualToString:@"yes"]] forKey:key];
+ [obj setValue:[NSNumber numberWithBool:[value_lc isEqualToString:@"yes"]] forKey:key];
} else {
[obj setValue:value forKey:key];
}