Reputation:
I have a UIWebView with some basic html that acts as a simple editor.
// in initWithFrame: of UIView subclass.
_editorHTML = [@"<!doctype html>"
"<html>"
"<head>"
"<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"
"<style type=\"text/css\">"
"#content { font-family:Arial, Helvetica, sans-serif; font-size:1em; } "
"</style>"
"<script type=\"text/javascript\">"
"function load()"
"{"
" window.location.href = 'ready://' + document.body.offsetHeight;"
"}"
"</script>"
"</head>"
"<body id=\"bodyDiv\" onload=\"load()\">"
"<div id=\"content\" contenteditable=\"true\">%@</div>"
"</body>"
"</html>" retain];
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
_webView.delegate = self;
_webView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_webView.scrollView.bounces = NO;
[_webView loadHTMLString:[NSString stringWithFormat:_editorHTML, @""] baseURL:[NSURL fileURLWithPath:directory]];
- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
if (navigationType == UIWebViewNavigationTypeOther) {
if ([[url scheme] isEqualToString:@"ready"]) {
int height = (int)_webView.frame.size.height;
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.getElementById('content').style.minHeight = '%dpx'", height - WEBVIEW_DIVHEIGHT_OFFSET]];
return NO;
}
}
return YES;
}
So, how can I determine the cursor position in my div so I can update my scrollView to make sure that the content is visible above the UIKeyboard thus not having to make the user manually scroll to keep the text in view?
Upvotes: 4
Views: 5004
Reputation: 2027
This solution is an evolution of the accepted answer. Fixes the newLine issue in WebKit.
function getCaretClientPosition() {
var x = 0, y = 0;
var sel = window.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
var needsToWorkAroundNewlineBug = (range.startContainer.nodeName.toLowerCase() == 'p'
&& range.startOffset == 0);
if (needsToWorkAroundNewlineBug) {
x = range.startContainer.offsetLeft;
y = range.startContainer.offsetTop;
} else {
if (range.getClientRects) {
var rects = range.getClientRects();
if (rects.length > 0) {
x = rects[0].left;
y = rects[0].top;
}
}
}
}
return { x: x, y: y };
}
Upvotes: 1
Reputation: 1232
@timdown Interestingly enough, your script always returns 0,0 for the beginning of a line. The script from [question]: Coordinates of selected text in browser page does return the right Y value, though.
Repeated here for ease of searching:
function getSelectionCoords() {
var sel = document.selection, range;
var x = 0, y = 0;
if (sel) {
if (sel.type != "Control") {
range = sel.createRange();
range.collapse(true);
x = range.boundingLeft;
y = range.boundingTop;
}
} else if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
range = sel.getRangeAt(0).cloneRange();
if (range.getClientRects) {
range.collapse(true);
var rect = range.getClientRects()[0];
x = rect.left;
y = rect.top;
}
}
}
return { x: x, y: y };
}
Upvotes: 5
Reputation: 324567
You can get the selected range from the selection and use its getClientRects()
method.
Live demo: http://jsfiddle.net/timdown/xMEjD/
Code:
function getCaretClientPosition() {
var x = 0, y = 0;
var sel = window.getSelection();
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
if (range.getClientRects) {
var rects = range.getClientRects();
if (rects.length > 0) {
x = rects[0].left;
y = rects[0].top;
}
}
}
return { x: x, y: y };
}
Upvotes: 7