Permalink
Browse files

Implemented A anchor support.

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 bcac40798944b6096b1465c3747b4e5963de1e90
@@ -23,4 +23,12 @@
@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
@@ -85,6 +85,25 @@ - (Class)classForContentView
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
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
@@ -95,7 +114,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
}
}
-
#pragma mark Properties
- (DTAttributedTextContentView *)contentView
{
@@ -30,6 +30,7 @@ extern NSString *DTDefaultStyleSheet;
extern NSString *DTTextListsAttribute;
extern NSString *DTAttachmentParagraphSpacingAttribute;
extern NSString *DTLinkAttribute;
+extern NSString *DTAnchorAttribute;
extern NSString *DTGUIDAttribute;
extern NSString *DTHeaderLevelAttribute;
extern NSString *DTPreserveNewlinesAttribute;
@@ -27,6 +27,7 @@
NSString *DTTextListsAttribute = @"DTTextLists";
NSString *DTAttachmentParagraphSpacingAttribute = @"DTAttachmentParagraphSpacing";
NSString *DTLinkAttribute = @"DTLink";
+NSString *DTAnchorAttribute = @"DTAnchor";
NSString *DTGUIDAttribute = @"DTGUID";
NSString *DTHeaderLevelAttribute = @"DTHeaderLevel";
NSString *DTPreserveNewlinesAttribute = @"DTPreserveNewlines";
@@ -419,6 +419,10 @@ - (void)_registerTagStartHandlers
}
currentTag.link = link;
+
+
+ // the name attribute of A becomes an anchor
+ currentTag.anchorName = [currentTag attributeForKey:@"name"];
};
[_tagStartHandlers setObject:[aBlock copy] forKey:@"a"];
@@ -41,6 +41,7 @@ typedef enum
@property (nonatomic, copy) DTCoreTextParagraphStyle *paragraphStyle;
@property (nonatomic, strong) DTTextAttachment *textAttachment;
@property (nonatomic, copy) NSURL *link;
+@property (nonatomic, copy) NSString *anchorName;
@property (nonatomic, strong) DTColor *textColor;
@property (nonatomic, strong) DTColor *backgroundColor;
@property (nonatomic, copy) NSString *tagName;
@@ -29,6 +29,7 @@ @implementation DTHTMLElement
DTTextAttachment *_textAttachment;
DTTextAttachmentVerticalAlignment _textAttachmentAlignment;
NSURL *_link;
+ NSString *_anchorName;
DTColor *_textColor;
DTColor *backgroundColor;
@@ -149,6 +150,12 @@ - (NSDictionary *)attributesDictionary
[tmpDict setObject:_linkGUID forKey:DTGUIDAttribute];
}
+ // add anchor
+ if (_anchorName)
+ {
+ [tmpDict setObject:_anchorName forKey:DTAnchorAttribute];
+ }
+
// add strikout if applicable
if (strikeOut)
{
@@ -899,6 +906,7 @@ - (id)copyWithZone:(NSZone *)zone
newObject.shadows = self.shadows;
newObject.link = self.link; // copy
+ newObject.anchorName = self.anchorName; // copy
newObject.linkGUID = _linkGUID; // transfer the GUID
newObject.preserveNewlines = self.preserveNewlines;
@@ -1010,6 +1018,7 @@ - (void)setLink:(NSURL *)link
@synthesize tagName;
@synthesize text;
@synthesize link = _link;
+@synthesize anchorName = _anchorName;
@synthesize underlineStyle;
@synthesize textAttachment = _textAttachment;
@synthesize tagContentInvisible;
@@ -65,9 +65,17 @@
- (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.
@@ -197,6 +197,21 @@ - (NSRange)rangeOfTextBlock:(DTTextBlock *)textBlock atIndex:(NSUInteger)locatio
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
@@ -1,3 +1,29 @@
-<p style="font-family:'Times New Roman';font-size:20px;">Hello</p>
-<p style="font-family:'Times New Roman';font-size:20px;"></p>
-<p style="font-family:'Times New Roman';font-size:20px;">World</p>
+<a href="#kapitel2">Go To Chapter2</a>
+<a name="kapitel1" href="#kapitel1">Kapitel 1</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>
+<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>
@@ -396,7 +396,26 @@ - (BOOL)attributedTextContentView:(DTAttributedTextContentView *)attributedTextC
- (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

0 comments on commit bcac407

Please sign in to comment.