JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
clean up finding x,y for cursor
authorJason Woofenden <jason@jasonwoof.com>
Mon, 22 Feb 2016 04:07:34 +0000 (23:07 -0500)
committerJason Woofenden <jason@jasonwoof.com>
Mon, 22 Feb 2016 04:07:34 +0000 (23:07 -0500)
editor.coffee
editor_tests_compiled.html

index defecba..d4c0379 100644 (file)
@@ -19,13 +19,17 @@ TYPE_TEXT = peach_parser.TYPE_TEXT
 TYPE_COMMENT = peach_parser.TYPE_COMMENT
 TYPE_DOCTYPE = peach_parser.TYPE_DOCTYPE
 
-get_el_offset = (el) ->
+get_el_bounds = (el) ->
        rect = el.getBoundingClientRect()
        doc = el.ownerDocument.documentElement
        win = el.ownerDocument.defaultView
+       y_fix = win.pageYOffset - doc.clientTop
+       x_fix = win.pageXOffset - doc.clientLeft
        return {
-               top: rect.top + win.pageYOffset - doc.clientTop
-               left: rect.left + win.pageXOffset - doc.clientLeft
+               x: rect.left + x_fix
+               y: rect.top + y_fix
+               w: rect.width ? (rect.right - rect.left)
+               h: rect.height ? (rect.top - rect.bottom)
        }
 
 # figure out the top/left coordinates of where the cursor should be if it's at
@@ -36,31 +40,50 @@ get_el_offset = (el) ->
 cursor_to_loc = (n, i) ->
        span = domify span: style: "height: 1em; border-left: 1px solid black; margin-left: -1px"
        parent = n.el.parentNode
-       if i is 0
-               # cursor at start of text
-               parent.insertBefore span, n.el
-               ret = get_el_offset span
-               span.parentNode.removeChild span
-               return ret
-       else if i is n.text.length
-               # cursor at end of text
-               parent.insertBefore span, n.el.nextSibling
-               ret = get_el_offset span
-               span.parentNode.removeChild span
-               return ret
-       # cursor in middle of text
-       # split the text node
-       t0 = n.el.ownerDocument.createTextNode n.text.substr 0, i
-       t1 = n.el.ownerDocument.createTextNode n.text.substr i
-       parent.insertBefore t0, n.el
-       parent.insertBefore span, n.el
-       parent.insertBefore t1, n.el
-       parent.removeChild n.el
-       ret = get_el_offset span
-       parent.insertBefore n.el, t0
-       parent.removeChild t0
-       parent.removeChild span
-       parent.removeChild t1
+       els = []
+       txts = []
+       plus_width = false
+       if n.text.length < 2
+               bounds = get_el_offset n.el
+               if i is 1
+                       plus_width = true
+       else
+               if i is 0 # cursor at start of text
+                       check_i = 0
+                       txts.push n.text.substr 0, 1
+                       txts.push n.text.substr 1
+               else if i is n.text.length # cursor at end of text
+                       check_i = 1
+                       plus_width = true
+                       txts.push n.text.substr 0, n.text.length - 1
+                       txts.push n.text.substr n.text.length - 1
+               else
+                       check_i = 1
+                       txts.push n.text.substr 0, i
+                       txts.push n.text.substr i, 1
+                       txts.push n.text.substr i + 1
+               for txt, txt_i in txts
+                       el = n.el.ownerDocument.createTextNode txt
+                       if txt_i is check_i
+                               span = n.el.ownerDocument.createElement 'span'
+                               span.appendChild el
+                               el = span
+                       els.push el
+                       parent.insertBefore el, n.el
+               parent.removeChild n.el
+               bounds = get_el_bounds els[check_i]
+               parent.insertBefore n.el, els[0]
+               for el in els
+                       parent.removeChild el
+       ret = top: bounds.y, left: bounds.x
+       if plus_width
+               ret.left += bounds.w
+       # fudge case where bounds are BS because we're on non-significant whitespace
+       if i > 0
+               first = cursor_to_loc n, 0
+               if ret.left <= first.left
+                       # no need for a loop here, because recursion
+                       ret = cursor_to_loc n, i - 1
        return ret
 
 # TODO
index ec7fdb8..3a156f8 100644 (file)
@@ -15,7 +15,7 @@
        <h1>Peach HTML5 Editor test page (compiled version)</h1>
        <p>This version of the editor test page requires that you've compiled all the source files. (Just run <code>make</code>).</p>
        <form action="#" method="get">
-       <p>In:<br><textarea rows="9" cols="22" name="in" id="in">&lt;p&gt;Normal &lt;strong&gt;Bold &lt;em&gt; Italic+Bold&lt;/strong&gt; Italic&lt;/em&gt; Normal&lt;/p&gt;</textarea></p>
+       <p>In:<br><textarea rows="9" cols="22" name="in" id="in">&lt;p&gt;Normal     aoehu aoethu aotheu naoht usaoheuntao uthao euha onetuh aote usnaohe unaoh eutha oeuh  &lt;strong&gt;Bold &lt;em&gt; Italic+Bold&lt;/strong&gt; Italic&lt;/em&gt; Normal&lt;/p&gt;&lt;div&gt;I'm in a div&lt;/div&gt;&lt;div&gt;I'm in a div&lt;/div&gt;</textarea></p>
        <p><input id="button" type="submit" value="loading..." disabled></p>
        </form>
        <script src="parser.js"></script>