forked from dgrijalva/gitx
-
Notifications
You must be signed in to change notification settings - Fork 76
/
Copy pathSearchWebView.m
130 lines (113 loc) · 4.45 KB
/
SearchWebView.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//
// SearchWebView.m
// GitX
//
// Created by German Laullon on 19/03/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "SearchWebView.h"
@implementation WebView (SearchWebView)
int resultCount=0;
DOMRange *result=nil;
- (int) resultCount {
return resultCount;
}
- (void)highlightAllOccurencesOfString:(NSString*)str inNode:(DOMNode *)_node
{
DOMDocument *document=[[self mainFrame] DOMDocument];
DOMNodeList *nodes=[_node childNodes];
DOMNode *node=[nodes item:0];
while(node!=nil){
if([node nodeType]==DOM_TEXT_NODE){
NSString *block;
if([[node nodeValue] rangeOfString:str options:NSCaseInsensitiveSearch].location!=NSNotFound){
NSScanner *scanner=[NSScanner scannerWithString:[node nodeValue]];
[scanner setCharactersToBeSkipped:nil];
[scanner setCaseSensitive:NO];
while([scanner scanUpToString:str intoString:&block]){
DOMNode *newNode=[document createTextNode:block];
[[node parentNode] appendChild:newNode];
while([scanner scanString:str intoString:&block]){
DOMElement *span=[document createElement:@"span"];
[span setAttribute:@"id" value:[NSString stringWithFormat:@"SWVHL_%d",resultCount++]];
[span setAttribute:@"class" value:@"SWVHL"];
newNode=[document createTextNode:block];
[span appendChild:newNode];
[[node parentNode] appendChild:span];
}
}
[[node parentNode] removeChild:node];
}
}else if([node nodeType]==DOM_ELEMENT_NODE){
[self highlightAllOccurencesOfString:str inNode:node];
}else{
DLog(@"--->%@",node);
}
node=[node nextSibling];
}
}
- (void)highlightAllOccurencesOfString:(NSString*)str update:(BOOL)update direction:(BOOL)forward
{
if([[[[self mainFrame] DOMDocument] documentElement] isKindOfClass:[DOMHTMLElement class]]){
DOMHTMLElement *dom=(DOMHTMLElement *)[[[self mainFrame] DOMDocument] documentElement];
if(update){
[self removeAllHighlights];
[self highlightAllOccurencesOfString:str inNode:dom];
}
if([self searchFor:str direction:forward caseSensitive:NO wrap:YES]){
result=[self selectedDOMRange];
}
}
}
- (void)search:(NSSearchField *)sender update:(BOOL)update grabFocus:(BOOL)grabFocus direction:(BOOL)forward
{
NSString *searchString = [sender stringValue];
DLog(@"searchString:%@",searchString);
NSRange searchFieldSelectedRange;
if (grabFocus) {
// Back-up the search field's caret position so we can restore it later
searchFieldSelectedRange = [[sender currentEditor] selectedRange];
}
if([searchString length]>0){
[self highlightAllOccurencesOfString:searchString update:update direction:forward];
if (grabFocus) {
// Bring the search field back in focus and restore its caret position
[[sender window] makeFirstResponder:sender];
[[sender currentEditor] setSelectedRange:searchFieldSelectedRange];
}
if(result!=nil) {
[self setSelectedDOMRange:result affinity:NSSelectionAffinityDownstream];
}
}else{
[self removeAllHighlights];
}
}
- (void)removeAllHighlights:(DOMNode *)_node
{
DOMNode *node=[_node firstChild];
while(node!=nil){
if ([node nodeType]==DOM_ELEMENT_NODE) {
if ([[(DOMElement *)node getAttribute:@"class"] isEqualToString:@"SWVHL"]) {
DOMNode *txt=[node firstChild];
DOMNode *parent=[node parentNode];
[node removeChild:txt];
[parent insertBefore:txt refChild:node];
[parent removeChild:node];
[parent normalize];
[self removeAllHighlights:parent];
}else{
[self removeAllHighlights:node];
}
}
node=[node nextSibling];
}
}
- (void)removeAllHighlights
{
resultCount = 0;
if([[[[self mainFrame] DOMDocument] documentElement] isKindOfClass:[DOMHTMLElement class]]){
DOMHTMLElement *dom=(DOMHTMLElement *)[[[self mainFrame] DOMDocument] documentElement];
[self removeAllHighlights:dom];
}
}
@end