JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
clean up finding x,y for cursor
[peach-html5-editor.git] / editor.coffee
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