X-Git-Url: https://jasonwoof.com/gitweb/?p=peach-html5-editor.git;a=blobdiff_plain;f=editor.coffee;h=dd39c6223016adc38779af63fb2652aa13fb31fb;hp=c78151a90cfa2dfd08487d75d63ae427b67e4ce2;hb=30aee05f9c37a3954f5f849823b2e84a304423ff;hpb=1a3115b9b75ed1f9a380b59c80d51fabdc811a2a diff --git a/editor.coffee b/editor.coffee index c78151a..dd39c62 100644 --- a/editor.coffee +++ b/editor.coffee @@ -559,21 +559,32 @@ tree_dedup_space = (tree) -> throw "how is this possible?" next_i -= 1 return 1 - whitespace_to_space = (undo) -> + replace_with_space = (undo) -> if undo cur.text = (cur.text.substr 0, cur_i) + removed_char + (cur.text.substr cur_i + 1) cur.el.textContent = cur.text else removed_char = cur.text.charAt(cur_i) - cur.text = (cur.text.substr 0, cur_i) + ' ' + (cur.text.substr cur_i + 1) - cur.el.textContent = cur.text + if removed_char isnt ' ' + cur.text = (cur.text.substr 0, cur_i) + ' ' + (cur.text.substr cur_i + 1) + cur.el.textContent = cur.text return 0 # return true if cur was removed from the dom (ie re-use same prev) operate = -> # cur definitately set # prev and/or next might be null, indicating the start/end of a display:block return false unless is_space_code cur.text.charCodeAt cur_i - fixers = [remove, whitespace_to_space] + fixers = [remove, replace_with_space] + # check for common case: single whitespace surrounded by non-whitespace chars + if prev? and next? + unless (is_space_code prev.text.charCodeAt prev_i) or (is_space_code next.text.charCodeAt next_i) + dbg = cur.text.charCodeAt cur_i + if cur.text.charAt(cur_i) is ' ' # perens required + # single space can't collapse, doesn't need fixin' + return false + else + # tab, newline, etc, can't collapse, but maybe should be replaced + fixers = [replace_with_space] bounds = text_range_bounds cur.el, cur_i, cur_i + 1 # consistent cases: # 1. zero rects returned by getClientRects() means collapsed space @@ -581,7 +592,8 @@ tree_dedup_space = (tree) -> return remove() # 2. width greater than zero means visible space if bounds.w > 0 - fixers.shift() # don't try removing + # has bounds, don't try removing + fixers = [replace_with_space] # now the weird edge cases... # # firefox and chromium both report zero width for characters at the end @@ -590,6 +602,11 @@ tree_dedup_space = (tree) -> # collapsed spaces via the range/bounds api, so... # # remove it from the dom, and if prev or next moves, put it back. + # + # this block (try changing it, put it back if something moves) is also + # used on collapsable whitespace characters besides space. In this case + # the character is replaced with a normal space character instead of + # removed if prev? and not prev_px? prev_px = new_cursor_position n: prev, i: prev_i if next? and not next_px? @@ -1077,6 +1094,13 @@ class PeachHTML5Editor @kill_cursor() return on_page_up_key: (e) -> + if @wrap2.scrollTop is 0 + return unless @cursor? + new_cursor = first_cursor_position @tree + if new_cursor? + if new_cursor.n isnt @cursor.n or new_cursor.i isnt @cursor.i + @move_cursor new_cursor + return if @cursor? screen_y = @cursor.y - @wrap2.scrollTop scroll_amount = @wrap2_height - breathing_room @@ -1084,10 +1108,17 @@ class PeachHTML5Editor if @cursor? @move_cursor_into_view screen_y + @wrap2.scrollTop on_page_down_key: (e) -> + lowest_scrollpos = @wrap2.scrollHeight - @wrap2_height + if @wrap2.scrollTop is lowest_scrollpos + return unless @cursor? + new_cursor = last_cursor_position @tree + if new_cursor? + if new_cursor.n isnt @cursor.n or new_cursor.i isnt @cursor.i + @move_cursor new_cursor + return if @cursor? screen_y = @cursor.y - @wrap2.scrollTop scroll_amount = @wrap2_height - breathing_room - lowest_scrollpos = @wrap2.scrollHeight - @wrap2_height @wrap2.scrollTop = Math.min lowest_scrollpos, @wrap2.scrollTop + scroll_amount if @cursor? @move_cursor_into_view screen_y + @wrap2.scrollTop @@ -1095,32 +1126,36 @@ class PeachHTML5Editor move_cursor_into_view: (y_target) -> return if y_target is @cursor.y was = @cursor - y_min = @wrap2.scrollTop + breathing_room - y_max = @wrap2.scrollTop + @wrap2_height - 2 * breathing_room + y_min = @wrap2.scrollTop + unless @wrap2.scrollTop is 0 + y_min += breathing_room + y_max = @wrap2.scrollTop + @wrap2_height + unless @wrap2.scrollTop is @wrap2.scrollHeight - @wrap2_height # downmost + y_max -= breathing_room y_target = Math.min y_target, y_max y_target = Math.max y_target, y_min if y_target < @cursor.y finder = find_up_cursor_position - far_enough = (a, b) -> - return a <= b + far_enough = (cur, target_y) -> + return cur.y + cur.h <= target_y else finder = find_down_cursor_position - far_enough = (a, b) -> - return a >= b + far_enough = (cur, y_target) -> + return cur.y >= y_target loop cur = finder @tree, was, @cursor_ideal_x break unless cur? - break if far_enough cur.y, y_target + break if far_enough cur, y_target was = cur if was is @cursor was = null if was? - if was.y > y_max + if was.y + was.h > y_max was = null else if was.y < y_min was = null if cur? - if cur.y > y_max + if cur.y + cur.h > y_max cur = null else if cur.y < y_min cur = null @@ -1128,7 +1163,7 @@ class PeachHTML5Editor # both valid, pick best if cur.y < y_min new_cursor = was - else if was.y > y_max + else if was.y + was.h > y_max new_cursor = cur else if cur.y - y_target < y_target - was.y new_cursor = cur