Skip to content

Commit

Permalink
Implemented A anchor support.
Browse files Browse the repository at this point in the history
When encountering a <a name="anchor">text</a> this causes a DTAnchorAttribute to be added to the text. DTAttributedTextView now has a method to scroll to thusly named anchors.
  • Loading branch information
odrobnik committed Apr 21, 2012
1 parent 384f2d5 commit bcac407
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 6 deletions.
8 changes: 8 additions & 0 deletions Core/Source/DTAttributedTextView.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@


@property (nonatomic, unsafe_unretained) IBOutlet id <DTAttributedTextContentViewDelegate> textDelegate; @property (nonatomic, unsafe_unretained) IBOutlet id <DTAttributedTextContentViewDelegate> textDelegate;



/**
Scrolls the receiver to the anchor with the given name to the top.
@param anchorName The name of the href anchor.
@param animated `YES` if the movement should be animated.
*/
- (void)scrollToAnchorNamed:(NSString *)anchorName animated:(BOOL)animated;

@end @end
20 changes: 19 additions & 1 deletion Core/Source/DTAttributedTextView.m
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ - (Class)classForContentView
return [DTAttributedTextContentView class]; return [DTAttributedTextContentView class];
} }


#pragma mark External Methods
- (void)scrollToAnchorNamed:(NSString *)anchorName animated:(BOOL)animated
{
NSRange range = [self.contentView.attributedString rangeOfAnchorNamed:anchorName];

if (range.length != NSNotFound)
{
// get the line of the first index of the anchor range
DTCoreTextLayoutLine *line = [self.contentView.layoutFrame lineContainingIndex:range.location];

// make sure we don't scroll too far
CGFloat maxScrollPos = self.contentSize.height - self.bounds.size.height + self.contentInset.bottom + self.contentInset.top;
CGFloat scrollPos = MIN(line.frame.origin.y, maxScrollPos);

// scroll
[self setContentOffset:CGPointMake(0, scrollPos) animated:animated];
}
}

#pragma mark Notifications #pragma mark Notifications
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{ {
Expand All @@ -95,7 +114,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
} }
} }



#pragma mark Properties #pragma mark Properties
- (DTAttributedTextContentView *)contentView - (DTAttributedTextContentView *)contentView
{ {
Expand Down
1 change: 1 addition & 0 deletions Core/Source/DTCoreTextConstants.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extern NSString *DTDefaultStyleSheet;
extern NSString *DTTextListsAttribute; extern NSString *DTTextListsAttribute;
extern NSString *DTAttachmentParagraphSpacingAttribute; extern NSString *DTAttachmentParagraphSpacingAttribute;
extern NSString *DTLinkAttribute; extern NSString *DTLinkAttribute;
extern NSString *DTAnchorAttribute;
extern NSString *DTGUIDAttribute; extern NSString *DTGUIDAttribute;
extern NSString *DTHeaderLevelAttribute; extern NSString *DTHeaderLevelAttribute;
extern NSString *DTPreserveNewlinesAttribute; extern NSString *DTPreserveNewlinesAttribute;
Expand Down
1 change: 1 addition & 0 deletions Core/Source/DTCoreTextConstants.m
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
NSString *DTTextListsAttribute = @"DTTextLists"; NSString *DTTextListsAttribute = @"DTTextLists";
NSString *DTAttachmentParagraphSpacingAttribute = @"DTAttachmentParagraphSpacing"; NSString *DTAttachmentParagraphSpacingAttribute = @"DTAttachmentParagraphSpacing";
NSString *DTLinkAttribute = @"DTLink"; NSString *DTLinkAttribute = @"DTLink";
NSString *DTAnchorAttribute = @"DTAnchor";
NSString *DTGUIDAttribute = @"DTGUID"; NSString *DTGUIDAttribute = @"DTGUID";
NSString *DTHeaderLevelAttribute = @"DTHeaderLevel"; NSString *DTHeaderLevelAttribute = @"DTHeaderLevel";
NSString *DTPreserveNewlinesAttribute = @"DTPreserveNewlines"; NSString *DTPreserveNewlinesAttribute = @"DTPreserveNewlines";
Expand Down
4 changes: 4 additions & 0 deletions Core/Source/DTHTMLAttributedStringBuilder.m
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -419,6 +419,10 @@ - (void)_registerTagStartHandlers
} }


currentTag.link = link; currentTag.link = link;


// the name attribute of A becomes an anchor
currentTag.anchorName = [currentTag attributeForKey:@"name"];
}; };


[_tagStartHandlers setObject:[aBlock copy] forKey:@"a"]; [_tagStartHandlers setObject:[aBlock copy] forKey:@"a"];
Expand Down
1 change: 1 addition & 0 deletions Core/Source/DTHTMLElement.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ typedef enum
@property (nonatomic, copy) DTCoreTextParagraphStyle *paragraphStyle; @property (nonatomic, copy) DTCoreTextParagraphStyle *paragraphStyle;
@property (nonatomic, strong) DTTextAttachment *textAttachment; @property (nonatomic, strong) DTTextAttachment *textAttachment;
@property (nonatomic, copy) NSURL *link; @property (nonatomic, copy) NSURL *link;
@property (nonatomic, copy) NSString *anchorName;
@property (nonatomic, strong) DTColor *textColor; @property (nonatomic, strong) DTColor *textColor;
@property (nonatomic, strong) DTColor *backgroundColor; @property (nonatomic, strong) DTColor *backgroundColor;
@property (nonatomic, copy) NSString *tagName; @property (nonatomic, copy) NSString *tagName;
Expand Down
9 changes: 9 additions & 0 deletions Core/Source/DTHTMLElement.m
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ @implementation DTHTMLElement
DTTextAttachment *_textAttachment; DTTextAttachment *_textAttachment;
DTTextAttachmentVerticalAlignment _textAttachmentAlignment; DTTextAttachmentVerticalAlignment _textAttachmentAlignment;
NSURL *_link; NSURL *_link;
NSString *_anchorName;


DTColor *_textColor; DTColor *_textColor;
DTColor *backgroundColor; DTColor *backgroundColor;
Expand Down Expand Up @@ -149,6 +150,12 @@ - (NSDictionary *)attributesDictionary
[tmpDict setObject:_linkGUID forKey:DTGUIDAttribute]; [tmpDict setObject:_linkGUID forKey:DTGUIDAttribute];
} }


// add anchor
if (_anchorName)
{
[tmpDict setObject:_anchorName forKey:DTAnchorAttribute];
}

// add strikout if applicable // add strikout if applicable
if (strikeOut) if (strikeOut)
{ {
Expand Down Expand Up @@ -899,6 +906,7 @@ - (id)copyWithZone:(NSZone *)zone
newObject.shadows = self.shadows; newObject.shadows = self.shadows;


newObject.link = self.link; // copy newObject.link = self.link; // copy
newObject.anchorName = self.anchorName; // copy
newObject.linkGUID = _linkGUID; // transfer the GUID newObject.linkGUID = _linkGUID; // transfer the GUID


newObject.preserveNewlines = self.preserveNewlines; newObject.preserveNewlines = self.preserveNewlines;
Expand Down Expand Up @@ -1010,6 +1018,7 @@ - (void)setLink:(NSURL *)link
@synthesize tagName; @synthesize tagName;
@synthesize text; @synthesize text;
@synthesize link = _link; @synthesize link = _link;
@synthesize anchorName = _anchorName;
@synthesize underlineStyle; @synthesize underlineStyle;
@synthesize textAttachment = _textAttachment; @synthesize textAttachment = _textAttachment;
@synthesize tagContentInvisible; @synthesize tagContentInvisible;
Expand Down
10 changes: 9 additions & 1 deletion Core/Source/NSAttributedString+DTCoreText.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -65,9 +65,17 @@
- (NSRange)rangeOfTextBlock:(DTTextBlock *)textBlock atIndex:(NSUInteger)location; - (NSRange)rangeOfTextBlock:(DTTextBlock *)textBlock atIndex:(NSUInteger)location;


/** /**
@name Converting to Other Representations Returns the range of the given href anchor.
@param list The text block.
@param anchorName The name of the anchor.
@returns The range of the given anchor.
*/ */
- (NSRange)rangeOfAnchorNamed:(NSString *)anchorName;


/**
@name Converting to Other Representations
*/


/** /**
Encodes the receiver into a generic HTML prepresentation. Encodes the receiver into a generic HTML prepresentation.
Expand Down
15 changes: 15 additions & 0 deletions Core/Source/NSAttributedString+DTCoreText.m
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -197,6 +197,21 @@ - (NSRange)rangeOfTextBlock:(DTTextBlock *)textBlock atIndex:(NSUInteger)locatio
return [self _rangeOfObject:textBlock inArrayBehindAttribute:DTTextBlocksAttribute atIndex:location]; return [self _rangeOfObject:textBlock inArrayBehindAttribute:DTTextBlocksAttribute atIndex:location];
} }


- (NSRange)rangeOfAnchorNamed:(NSString *)anchorName
{
__block NSRange foundRange = NSMakeRange(0, NSNotFound);

[self enumerateAttribute:DTAnchorAttribute inRange:NSMakeRange(0, [self length]) options:0 usingBlock:^(NSString *value, NSRange range, BOOL *stop) {
if ([value isEqualToString:anchorName])
{
*stop = YES;
foundRange = range;
}
}];

return foundRange;
}

#pragma mark HTML Encoding #pragma mark HTML Encoding




Expand Down
32 changes: 29 additions & 3 deletions Demo/Resources/CurrentTest.html
Original file line number Original file line Diff line number Diff line change
@@ -1,3 +1,29 @@
<p style="font-family:'Times New Roman';font-size:20px;">Hello</p> <a href="#kapitel2">Go To Chapter2</a>
<p style="font-family:'Times New Roman';font-size:20px;"></p> <a name="kapitel1" href="#kapitel1">Kapitel 1</a>
<p style="font-family:'Times New Roman';font-size:20px;">World</p> <p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<a name="kapitel2">Chapter2</a>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
21 changes: 20 additions & 1 deletion Demo/Source/DemoTextViewController.m
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -396,7 +396,26 @@ - (BOOL)attributedTextContentView:(DTAttributedTextContentView *)attributedTextC


- (void)linkPushed:(DTLinkButton *)button - (void)linkPushed:(DTLinkButton *)button
{ {
[[UIApplication sharedApplication] openURL:[button.URL absoluteURL]]; NSURL *URL = button.URL;

if ([[UIApplication sharedApplication] canOpenURL:[URL absoluteURL]])
{
[[UIApplication sharedApplication] openURL:[URL absoluteURL]];
}
else
{
if (![URL host] && ![URL path])
{

// possibly a local anchor link
NSString *fragment = [URL fragment];

if (fragment)
{
[_textView scrollToAnchorNamed:fragment animated:NO];
}
}
}
} }


- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
Expand Down

0 comments on commit bcac407

Please sign in to comment.