Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

intercept copy, paste, define popover in UIWebView

When we highlight a text in UIWebView usually the copy, paste, define.. etc appears. How can I intercept this so that when I choose copy I call some other method/do something else. Is this possible?

like image 517
adit Avatar asked Jan 11 '12 17:01

adit


1 Answers

You can simply override -copy:

- (void)copy:(id)sender
{
    // Do something else here
    return [super copy:sender];
}

Edit to answer your comment.

Define is a bit trickier, since it's private. However, you could implement your own method. Set up the UIMenuController with your desired items.

UIMenuItem *copyItem = [[UIMenuItem alloc] initWithTitle:@"Copy" 
                                                  action:@selector(myCopy:)];

UIMenuItem *defineItem = [[UIMenuItem alloc] initWithTitle:@"Define"
                                                    action:@selector(myDefine:)];

[[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:defineItem, copyItem, nil]];
[defineItem release];
[copyItem release];

Then you implement those methods.

As for define, it's way more complicated.. First, you need to check if the UIReferenceLibraryController has a definition, by overriding -canPerformAction:withSender:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{
    if (action == @selector(myDefine:)) {
        // Make sure we are on iOS5.x
        if (NSClassFromString(@"UIReferenceLibraryViewController")) {
            return [UIReferenceLibraryViewController dictionaryHasDefinitionForTerm:[webView selectedText]];
        }
    }
    // Implement other custom actions here
    return NO;
}

-selectedText is here a category on UIWebView:

- (NSString *)selectedText {
    return [self stringByEvaluatingJavaScriptFromString:@"window.getSelection().toString()"];
}

Then you need to implement myDefine:

- (void)myDefine:(UIMenuController *)menuController 
{    
    CGRect selectedWordFrame = [webView rectForSelectedText];

    UIReferenceLibraryViewController *dict = [[UIReferenceLibraryViewController alloc] initWithTerm:[webView selectedText]];
    UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:dict];
    [popover presentPopoverFromRect:selectedWordFrame
                             inView:webView
           permittedArrowDirections:UIPopoverArrowDirectionAny
                           animated:YES];
    [popover setDelegate:self];
    [dict release];
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController 
{
    [popoverController release];
}

Edit to answer you comment again

-rectForSelectedText is another custom category on UIWebView.

- (CGRect)rectForSelectedText {
    return CGRectFromString([self stringByEvaluatingJavaScriptFromString:@"getRectForSelectedWord()"]);
}

What it does is calling a javascript that returns a string that you can convert using CGRectFromString(), it looks something like this:

function getRectForSelectedWord() {
    var selection = window.getSelection();
    var range = selection.getRangeAt(0);
    var rect = range.getBoundingClientRect();
    return "{{" + rect.left + "," + rect.top + "}, {" + rect.width + "," + rect.height + "}}";
}

Check this page to learn how to inject javascript into UIWebView.

like image 55
hwaxxer Avatar answered Oct 19 '22 17:10

hwaxxer