X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=editor.coffee;h=636bf193266ebc2a7d126ca6e90baf0b93a9c269;hb=8ef2ac71a968742051ccec0b4f20dad33e609602;hp=9e2154460af8520701db0c3dbc707e688cf7f6c6;hpb=3b0ea1cf0431211db79091277e2dec49f2c1bbd3;p=peach-html5-editor.git diff --git a/editor.coffee b/editor.coffee index 9e21544..636bf19 100644 --- a/editor.coffee +++ b/editor.coffee @@ -664,7 +664,8 @@ class PeachHTML5Editor constructor: (in_el, options) -> @options = options ? {} @in_el = in_el - @tree = null + @tree = null # array of Nodes, all editable content + @tree_parent = null # @tree is this.children. .el might === @idoc.body @matting = [] @init_1_called = false # when iframes have loaded @outer_iframe # iframe to hold editor @@ -922,16 +923,7 @@ class PeachHTML5Editor @move_cursor new_cursor return false when KEY_BACKSPACE - return false unless @cursor? - return false unless @cursor.i > 0 - @remove_character @cursor.n, @cursor.i - 1 - @adjust_whitespace_style @cursor.n - @changed() - new_cursor = new_cursor_position n: @cursor.n, i: @cursor.i - 1 - if new_cursor? - @move_cursor new_cursor - else - @kill_cursor() + @on_key_backspace e return false when KEY_DELETE return false unless @cursor? @@ -990,12 +982,12 @@ class PeachHTML5Editor return unless cur_block.parent? cur_block = cur_block.parent # find array to insert new element into - if cur_block.parent?.el? - parent_el = cur_block.parent.el - pc = cur_block.parent.children - else + if cur_block.parent is @tree_parent # top-level parent_el = @idoc.body pc = @tree + else + parent_el = cur_block.parent.el + pc = cur_block.parent.children # find index of current block in its parent for n, i in pc break if n is cur_block @@ -1013,10 +1005,65 @@ class PeachHTML5Editor new_node.el = domify @idoc, p: style: 'white-space: pre-wrap', children: [new_text.el] pc.splice i, 0, new_node parent_el.insertBefore new_node.el, before + @changed() new_cursor = new_cursor_position n: new_text, i: 0 throw 'bork bork' unless new_cursor? @move_cursor new_cursor # TODO move content past cursor into this new block + on_key_backspace: (e) -> + return false unless @cursor? + if @is_lone_space @cursor.n # false if it's not in a tag + if @cursor.i is 1 + # don't delete the space, because then it would collapse + # instead leave a space after the cursor + new_cursor = new_cursor_position n: @cursor.n, i: 0 + if new_cursor? + @move_cursor new_cursor + else + @kill_cursor() + else + parent = @cursor.n.parent + new_cursor = find_prev_cursor_position @tree, @cursor + if new_cursor? + if new_cursor.n is @cursor.n or new_cursor.n is parent + new_cursor = null + tag = @cursor.n.parent + if tag is @tree_parent + console.log "top-level text not supported" # FIXME + return false + for n, i in tag.parent.children + if n is tag + tag.parent.el.removeChild tag.el + tag.parent.children.splice i, 1 + break + @changed() + if new_cursor? + # re-check, in case it moved or is invalid now + new_cursor = new_cursor_position n: new_cursor.n, i: new_cursor.i + if new_cursor? + @move_cursor new_cursor + return + new_cursor = first_cursor_position @tree + if new_cursor? + @move_cursor new_cursor + else + @kill_cursor + return + else if @cursor.i is 0 + console.log 'not implemented yet' + # TODO if block, merge parent into prev + # TODO if inline, delete char from prev text node + return false + else + # TODO handle case of removing last char + @remove_character @cursor.n, @cursor.i - 1 + @adjust_whitespace_style @cursor.n + @changed() + new_cursor = new_cursor_position n: @cursor.n, i: @cursor.i - 1 + if new_cursor? + @move_cursor new_cursor + else + @kill_cursor() clear_dom: -> # remove all the editable content (and cursor, overlays, etc) while @idoc.body.childNodes.length @idoc.body.removeChild @idoc.body.childNodes[0] @@ -1024,8 +1071,12 @@ class PeachHTML5Editor return load_html: (html) -> @tree = peach_parser.parse html, @parser_opts + if !@tree[0]?.parent + @tree = peach_parser.parse '

', @parser_opts + @tree_parent = @tree[0]?.parent + @tree_parent.el = @idoc.body @clear_dom() - instantiate_tree @tree, @idoc.body + instantiate_tree @tree, @tree_parent.el tree_dedup_space @tree @changed() changed: -> @@ -1104,27 +1155,36 @@ class PeachHTML5Editor if needle is n.attrs.style.substr n.attrs.style.length - needle n.attrs.style = n.attrs.style.substr 0, n.attrs.style.length - needle n.el.setAttribute n.attrs.style + # true if n is text node with just a space in it, and the only child of a tag + is_lone_space: (n, i) -> + return false unless n.type is 'text' + return false unless n.text is ' ' + return false if n.parent is @tree_parent + if n.parent.children.length is 1 + if n.parent.children[0] is n + # n is only child + return true + return false + # detect special case: typing before a space that's the only thing in a block/doc + # reason: enter key creates blocks with just a space in them + insert_should_replace: (n, i) -> + return false unless i is 0 + return false unless n.text is ' ' + return true if n.parent is @tree_parent + if n.parent.children.length is 1 + if n.parent.children[0] is n + # n is only child + return true + return false # after calling this, you MUST call changed() and adjust_whitespace_style() insert_character: (n, i, char) -> + return if @cursor.n.parent is @tree_parent # FIXME implement text nodes at top level parent = @cursor.n.parent - return unless parent - return unless parent.el? # insert the character - if i is 0 - # special case: typing before a space that's the only thing in a block/doc - # reason: enter key creates blocks with just a space in them - special_case = false - if n.text is ' ' - if n.parent?.el? - if n.parent.children.length is 1 - if n.parent.children[0] is n - special_case = true - else - special_case = true - if special_case - n.text = char - else - n.text = char + n.text + if @insert_should_replace n, i + n.text = char + else if i is 0 + n.text = char + n.text else if i is n.text.length # replace the space n.text += char @@ -1195,7 +1255,7 @@ class PeachHTML5Editor return unless n? prev_bounds = x: 0, y: 0, w: 0, h: 0 alpha = 0.1 - while n?.el? + while n?.el? and n isnt @tree_parent if n.type is 'text' n = n.parent continue