UIWebView で JavaScript confirm と prompt

iOS で、JavaScript  confirm と prompt をカスタマイズして機能させるには、

confirm は、runJavaScriptConfirmPanelWithMessage
prompt は、runJavaScriptTextInputPanelWithPrompt

で行う。

@implementation UIWebView (JavaScriptDialog)

static BOOL dialog_result = NO;

#pragma mark -------------- confirm ----------------

- (BOOL)webView:(UIWebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
{
    UIAlertView *dialog = [[UIAlertView alloc] initWithTitle:nil 
                                               message:message 
                                               delegate:self 
                                               cancelButtonTitle:@"キャンセル"
                                               otherButtonTitles:@"OK"
                                             , nil
                          ];
    [dialog show];
    while(dialog.hidden == NO && dialog.superview != nil)
        [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01f]];

    [dialog autorelease];
    return dialog_result;
}


#pragma mark -------------- prompt ----------------

-(NSString *)webView:(UIWebView *)sender runJavaScriptTextInputPanelWithPrompt:(NSString *)message 
         defaultText:(NSString *)defaultText initiatedByFrame:(WebFrame *)frame
{
    NSString *displaymessage = [NSString stringWithFormat:@"%@\n\n\n", message];
    UIAlertView *dialog = [[UIAlertView alloc] initWithTitle:nil
                                               message:displaymessage
                                               delegate:self
                                               cancelButtonTitle:@"キャンセル"
                                               otherButtonTitles:@"OK"
                                               , nil
                           ];
    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 50.0, 260.0, 25.0)];
    [textField setBackgroundColor:[UIColor whiteColor]];
    [textField setText:defaultText];
    [dialog addSubview:textField];
    [dialog show];
    while(dialog.hidden == NO && dialog.superview != nil)
        [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01f]];

    [dialog autorelease];
    if (dialog_result){
        return textField text];
    }else {
        return defaultText;
    }
}


#pragma mark ------- ダイアログボタン押した時のインデックスから真偽値に -----------

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (buttonIndex) {
      case 0:
            dialog_result = NO;
         break;
      case 1:
         dialog_result = YES;
         break;
   }
}

@end

prompt は、入力の描画がうまく配置されるように、メッセージを3行ぐらい改行しないとボタンと被ってしまう。


ダイアログ表示して while で待ってるのがダサい。

JavaScript の window.onbeforeunload をハンドリングしたいが、
iOS UIWebView では、見つからない。

shouldStartLoadWithRequest で、渡される引数の UIWebViewNavigationType が、UIWebViewNavigationTypeOther であるときに、UIAlertView を出す
方法では、あまりにも乱暴に思える。


enum {
UIWebViewNavigationTypeLinkClicked,
UIWebViewNavigationTypeFormSubmitted,
UIWebViewNavigationTypeBackForward,
UIWebViewNavigationTypeReload,
UIWebViewNavigationTypeFormResubmitted,
UIWebViewNavigationTypeOther
};