How To Mark Or Get The Highlighted String Inside UIWebView

Before we go over with this tutorial, I would like to thank everyone for reading my posts, for asking questions and for giving suggestions. Because of that, I will continue writing tutorials that might help other developers get rid of headaches and frustrations.

This tutorial is a follow up tutorial from my previous post. Someone find it simple yet helpful and ohers have questions if it is possible to mark/stylize and get those strings inside UIWebView that are selected or highlighted. So I created this tutorial to support that question.

Let's get started!

Since we are still manipulating UIWebView, we need to gain access to its contents. In order to do this, we have to use Javascripts.

With Javascript, we can access UIWebViews contents like normal browsers do.

In this tutorial, we will use UIWebViews method (stringByEvaluatingJavaScriptFromString) to access javascript files and execute its functions.

Download the javascript and html file here. After downloading the zip file, extract the file and you should have two files (HighlightedString.js and index.html).

What are these files?

The html file (index.html) handles the UIWebView content.

That javascript file (HighlightedString.js) handles all the job of getting or marking highlighted strings inside UIWebView.

Inside that javascript file, we have variable to store the selected text.

var selectedText = "";

We also have a function to get the highlighted strings.

function getHighlightedString() {
    var text        = window.getSelection();
    selectedText    = text.anchorNode.textContent.substr(text.anchorOffset, text.focusOffset - text.anchorOffset);

}

This function above will access the window and perform the getSelection() operation to access of UIWebViews contents.

Then, we parse UIWebView's contents using the anchorOffset and focusOffset.

  • anchorOffset() - returns the first index position of the highlighted strings. For example if my UIWebView has content "My name is Zaldy", and you highlighted Zaldy. You're anchorOffset is 11 which is the character "Z". Because it counts all characters from the beginning of the content as index 0.
  • focusOffset() - returns the last index position of the highlighted strings. With the latter example, our focusOffset is 15 which refers to the last character of the highlighted string,  the character "y".

Now, in order to acquire the highlighted strings, we parse the UIWebView contents and scan the content using the operation text.anchorNode.textContent.substr(int startingIndex, int length). This operation takes two paramters, the first one is the starting position of the character to parse, the second one is the length of the string to end the parsing.

So if our UIWebView has content "My name is Zaldy" and we have anchorOffset() = 11 with focusOffset() = 15. Our string length would be 15 - 11 = 4. Remember that 4 means we have 0,1,2,3,4 characters, a total of 5characters. The parser now scan's the content from index 11 with string length 4, so it will end scanning to character "y".

Hope that sounds clear to you guys.

Another function is to stylize/mark any highlighted string inside UIWebView content.

function stylizeHighlightedString() {
    
    var range               = window.getSelection().getRangeAt(0);
    var selectionContents   = range.extractContents();
    var span                = document.createElement("span");
    
    span.appendChild(selectionContents);
    
    span.setAttribute("class","uiWebviewHighlight");
    span.style.backgroundColor  = "black";
    span.style.color            = "white";
    
    range.insertNode(span);
}

That function above captures the range of our selection and put a <span> element before the first character of the highlighted string and put the </span> after the last character of the highlighted string. After that, we add a class attribute named "uiWebviewHighlight" with defined style backgroundColor to black and font color style to white. Then insert the changes to the highlighted strings and update the UIWebView content.

Note: You can always change the colors of marker's background and text.

We also have a function to remove all highlights. This function is also used on my previous post to mark/highlight a searched string.

// helper function, recursively removes the highlights in elements and their childs
function uiWebview_RemoveAllHighlightsForElement(element) {
    if (element) {
        if (element.nodeType == 1) {
            if (element.getAttribute("class") == "uiWebviewHighlight") {
                var text = element.removeChild(element.firstChild);
                element.parentNode.insertBefore(text,element);
                element.parentNode.removeChild(element);
                return true;
            } else {
                var normalize = false;
                for (var i=element.childNodes.length-1; i>=0; i--) {
                    if (uiWebview_RemoveAllHighlightsForElement(element.childNodes[i])) {
                        normalize = true;
                    }
                }
                if (normalize) {
                    element.normalize();
                }
            }
        }
    }
    return false;
}

That function above recursively removes all element occurence that has class attribute named "uiWebviewHighlight". This will remove all marks/highlights defined to that class attribute.

.Let's do this!

This tutorial project is using an iOS5 SDK with Storyboards and ARC.

1. Create an XCode project named (WebViewHighlight) as a single view applciation. Check the Use Of Storyboard and the Use of Automatic Reference Counting.

2. Add the javascript and html file to your XCode.

3. Note: once you have added a javascript file to your XCode. XCode will displays a warning:

warning: no rule to process file '$(PROJECT_DIR)/.../HighlightedString.js' of type sourcecode.javascript for architecture i386

This happens because it compiles a javascript file and will find it weird. So that our XCode will not compile our javascript file, go to your TARGET and select the BUILD PHASES tab and expand the COMPILE SOURCES then  remove the HighlightedString.js by selecting it and click the minus (-) button.

Add HighlightedString.js to the COPY BUNDLE RESOURCES by clicking the plus (+) button and select the jabascript fileSee below screen-shot.

Remove js file from Compile Sources.

Add js file to the Copy Bundle Resources.

This will add the javascript file to your project's bundle resources without compiling it.

4. Update your ViewController header file (ViewController.h) with the code below.

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property(nonatomic, retain) IBOutlet UIWebView *webView;
- (IBAction)removeAllHighlights;
- (IBAction)markHighlightedString:(id)sender;
- (IBAction)getHighlightedString:(id)sender;
@end

We have an IBOutlet UIWebView variable and functions to mark, get and remove highlighted strings.

5. Update your @implementation file (ViewController.m).

Add these below @implementation.

{
    UIWebView *_webView;
}

@synthesize webView = _webView;

Add this method.

- (IBAction)markHighlightedString:(id)sender {
    
    // The JS File   
    NSString *filePath  = [[NSBundle mainBundle] pathForResource:@"HighlightedString" ofType:@"js" inDirectory:@""];
    NSData *fileData    = [NSData dataWithContentsOfFile:filePath];
    NSString *jsString  = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];
    [_webView stringByEvaluatingJavaScriptFromString:jsString];
    
    // The JS Function
    NSString *startSearch   = [NSString stringWithFormat:@"stylizeHighlightedString()"];
    [_webView stringByEvaluatingJavaScriptFromString:startSearch];
    
}

Above code will call the javascript file and execute the function to mark any highlighted strings inside your webview content.

Add this method.

- (IBAction)getHighlightedString:(id)sender {
    
    // The JS File   
    NSString *filePath  = [[NSBundle mainBundle] pathForResource:@"HighlightedString" ofType:@"js" inDirectory:@""];
    NSData *fileData    = [NSData dataWithContentsOfFile:filePath];
    NSString *jsString  = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];
    [_webView stringByEvaluatingJavaScriptFromString:jsString];
    
    // The JS Function
    NSString *startSearch   = [NSString stringWithFormat:@"getHighlightedString()"];
    [_webView stringByEvaluatingJavaScriptFromString:startSearch];
    
    NSString *selectedText   = [NSString stringWithFormat:@"selectedText"];
    NSString * highlightedString = [_webView stringByEvaluatingJavaScriptFromString:selectedText];
    
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Highlighted String" 
                                                    message:highlightedString
                                                   delegate:nil 
                                          cancelButtonTitle:@"Oh Yeah" 
                                          otherButtonTitles:nil];
    [alert show];
    //[alert release]; // not required anymore because of ARC
}

Above code will call the javascript file and execute the function to get any highlighted strings inside webview content and push an alert view.

Add this method.

- (IBAction)removeAllHighlights
{
    // calls the javascript function to remove html highlights
    [_webView stringByEvaluatingJavaScriptFromString:@"uiWebview_RemoveAllHighlights()"];
}

Above code will call the javascript function to remove string highlights.

Update your - (void)viewDidUnload with this code:

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    _webView = nil;
}

Update your - (void)viewDidLoad with this code:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // Load index.html to our webview
    NSString *urlAddress        = [[NSBundle mainBundle] pathForResource:@"index" 
                                                                  ofType:@"html"]; //you can also use PDF files
    NSURL *url                  = [NSURL fileURLWithPath:urlAddress];
    NSURLRequest *requestObj    = [NSURLRequest requestWithURL:url];
    [_webView loadRequest:requestObj];
    
    // Menu Controller
    UIMenuController *menuController = [UIMenuController sharedMenuController];
    UIMenuItem *getHighlightString = [[UIMenuItem alloc] initWithTitle: @"Get String" action: @selector(getHighlightString:)];
    UIMenuItem *markHighlightedString = [[UIMenuItem alloc] initWithTitle: @"Mark String" action: @selector(markHighlightedString:)];
    [menuController setMenuItems: [NSArray arrayWithObjects:getHighlightString, markHighlightedString, nil]];

}

Above code will load the HTML file index.html file to our webview by the time our view is loaded. There is a UIMenuController object added there as well, which will add two popup menu options when you highlight a string inside UIWebView with targets pointing to our IBAction methods. See screenshot below.

Screen_shot_2011-11-04_at_1

Add this method.

- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
{
    
    if (action == @selector(getHighlightString:)) {
        return YES;
    } else if (action == @selector(markHighlightedString:)) {
        return YES;
    }
    
    return NO;
}

Above code will disable other popup menu items and show our newly added popup menu items.

6. Now, add the UIWebView and UIButton components to your storyboard file (MainStoryboard.storyboard). Then link UIWebView outlet and UIButton actions . See screen-shot below.

link UIWebView outlet reference:

link UIButton action events (Do this also with the rest of the buttons Get Highlighted String and Remove Highlights to action events getHighlightedString: and removeAllHighlights)
:Compile and Run!

Go ahead, compile and run. You should see something like this:

Screen_shot_2011-11-04_at_1
Marking a highlighted string.

Screen_shot_2011-11-04_at_1
Get the highlighted string.

Screen_shot_2011-11-04_at_1
The Code Please!

You can download the full source code here.

Inside that javascript file, we have variable to store the selected text.


原帖地址:https://zaldzbugz.posterous.com/how-to-mark-or-get-the-highlighted-string-ins

COCA: http://www.cocoachina.com/bbs/read.php?tid=124376

cnblogs: http://www.cnblogs.com/lifuqing/archive/2012/04/16/2451838.html

發佈了6 篇原創文章 · 獲贊 2 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章