UIWebview文字选中高亮


原文1:http://zframework.ph/how-to-search-a-string-inside-uiwebview/

原文2:http://zframework.ph/how-to-mark-or-get-the-highlighted-string-ins/


How To Search And Highlight A String Inside UIWebView

UIWebView displays contents as a normal websites do but it doesn’t allow us to access its contents directly. So we have to use JAVASCRIPT in order to do that.

UIWebView has a method that can access any javascript implementations within your UIWebView (stringByEvaluatingJavaScriptFromString).

Since we need to use a Javascript, we need to add a javascript file to do this task. Download the javascript and html file here. Extract the zip file once you finished downloading it.

You’ll see a javascript file (UIWebViewSearch.js) and html file (index.html) there.

What are these files anyway?

Start with the javascript file (UIWebViewSearch.js).

This javascript file consist of a variable to count the number of result a string is found.

var uiWebview_SearchResultCount = 0;

And functions to highlight a string and removing all string highlights.

  • function uiWebview_HighlightAllOccurencesOfStringForElement(element,keyword) – Search a string inside the HTML element.
  • function uiWebview_HighlightAllOccurencesOfString(keyword) - Highlight all string occurences inside all elements of HTML file.
  • function uiWebview_RemoveAllHighlightsForElement(element)- Remove all string highlights inside an elements of HTML file.
  • function uiWebview_RemoveAllHighlights()- Remove all string highlights inside all elements of HTML file.

The HTML file index.html, had a sample web content there to try on searching strings within our UIWebView.

Let’s Do This!

This tutorial project is using a UISearchBar for string input and UIWebView to display web contents. Let’s do this.

1. Create an XCode project named (WebViewStringSearch) as a single view applciation or view based application if your using the older XCode IDE.

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)/…/UIWebViewSearch.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 UIWebViewSearch.js by selecting it and click the minus (-) button.

Add UIWebViewSearch.js to the COPY BUNDLE RESOURCES by clicking the plus (+) button and select the javascript fileSee Below screen-shot.

Remove js file from Compile Sources.

Screen_shot_2011-10-18_at_6

Add js file to the Copy Bundle Resources.

Screen_shot_2011-10-18_at_6

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 <UISearchBarDelegate>{
    UIWebView *_webView;
}

 

@property(nonatomic, retain) IBOutlet UIWebView *webView;

 

- (NSInteger)highlightAllOccurencesOfString:(NSString*)str;
- (void)removeAllHighlights;

 

@end

We have a UISearchBar delegate there to enable search bar delegate methods.

We also have a variable _webView as outlet reference of UIWebView that you will add to your XIB file later on and declare it as property.

We also have two methods here used to highlight and remove the highlight of string.

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

@synthesize webView = _webView;

Add this method:

/*
 Search A string inside UIWebView with the use of the javascript function
 */
- (NSInteger)highlightAllOccurencesOfString:(NSString*)str
{
    // The JS File   
    NSString *filePath  = [[NSBundle mainBundle] pathForResource:@”UIWebViewSearch” ofType:@”js” inDirectory:@”"];
    NSData *fileData    = [NSData dataWithContentsOfFile:filePath];
    NSString *jsString  = [[NSMutableString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];
    [_webView stringByEvaluatingJavaScriptFromString:jsString];
    [jsString release];

    // The JS Function
    NSString *startSearch   = [NSString stringWithFormat:@"uiWebview_HighlightAllOccurencesOfString('%@')",str];
    [_webView stringByEvaluatingJavaScriptFromString:startSearch];

    // Search Occurence Count
    // uiWebview_SearchResultCount – is a javascript var
    NSString *result        = [_webView stringByEvaluatingJavaScriptFromString:@"uiWebview_SearchResultCount"];
    return [result integerValue];
}

Above code will call the javascript file and execute the function to highlight a string inside webview web content.

Add this method:

/*
 Removes all highlighted string searched before
 */
- (void)removeAllHighlights
{
    // calls the javascript function to remove html highlights
    [_webView stringByEvaluatingJavaScriptFromString:@"uiWebview_RemoveAllHighlights()"];
}

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

Add add this search bar delegate method:

#pragma mark – UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {

 

    [self removeAllHighlights];

    int resultCount = [self highlightAllOccurencesOfString:searchBar.text];

 

    // If no occurences of string, show alert message
    if (resultCount <= 0) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”Hey!” 
                                                        message:[NSString stringWithFormat:@"No results found for string: %@", searchBar.text]
                                                       delegate:nil 
                                              cancelButtonTitle:@”Ok” 
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }

    // remove kkeyboard
    [searchBar resignFirstResponder];
}

Above code is called when you tap the SEARCH button in the keyboard popup of UISearchBar. Then we remove highlights first before highlighting all string occurences and check if there are any occurences, if not then display an alert and remove the keyboard.

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 release];
    _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];
}

Above code will load the HTML file index.html file to our webview by the time our view is loaded.

6. Now, add the UIWebView and UISearchBar components to your XIB file (ViewController.XIB). Then link UIWebView outlet and UISearchBar delegate to its owner. See screen-shot below.

link UIWebView outlet reference:

Screen_shot_2011-10-18_at_7

Links UISearchBar delegate to owner:

Screen_shot_2011-10-18_at_7

Compile and Run!

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

Screen_shot_2011-10-18_at_7

The Code Please!

You can download the full source code here.


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,4characters, a total of 5 characters. 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.

Screen_shot_2011-11-04_at_1

 

Add js file to the Copy Bundle Resources.

Screen_shot_2011-11-04_at_1

 

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:

Screen_shot_2011-11-04_at_1

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

Screen_shot_2011-11-04_at_1

:

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.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值