X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=editor.coffee;h=9b4ad4f5eae8490343cdbe21ad4b9fb6620aff31;hb=7933708e8875761cdaaa5c2fd746ad4b8aa7ce3a;hp=870c61bb6b91fb21b111b805509e99085fb3724d;hpb=dac5189783f7b082e0baf790c859aae9f28c5412;p=peach-html5-editor.git diff --git a/editor.coffee b/editor.coffee index 870c61b..9b4ad4f 100644 --- a/editor.coffee +++ b/editor.coffee @@ -197,6 +197,8 @@ outer_css = (args) -> ret += 'body {' ret += 'margin: 0;' ret += 'padding: 0;' + ret += 'color: black;' + ret += 'background: white;' ret += '}' ret += '#wrap1 {' ret += "border: #{occupy 1}px solid black;" @@ -242,23 +244,19 @@ outer_css = (args) -> ret += '}' ret += '#cursor {' ret += 'position: absolute;' - ret += 'height: 1em;' # FIXME adjust for hight of text ret += 'width: 2px;' - ret += 'background: #444;' - ret += '-webkit-animation: blink 1s linear infinite;' - ret += 'animation: blink 1s linear infinite;' + ret += 'background: linear-gradient(0deg, rgba(0,0,0,1), rgba(255,255,255,1), rgba(0,0,0,1), rgba(255,255,255,1), rgba(0,0,0,1), rgba(255,255,255,1), rgba(0,0,0,1), rgba(255,255,255,1), rgba(0,0,0,1));' + ret += 'background-size: 200% 200%;' + ret += '-webkit-animation: blink 1s linear normal infinite;' + ret += 'animation: blink 1s linear normal infinite;' ret += '}' ret += '@-webkit-keyframes blink {' - ret += '0% { background-color: rgba(0,0,0,0.7); }' - ret += '50% { background-color: rgba(0,0,0,0.7); }' - ret += '50.001% { background-color: rgba(255,255,255,0.7); }' - ret += '100% { background-color: rgba(255,255,255,0.7); }' + ret += '0%{background-position:0% 0%}' + ret += '100%{background-position:0% -100%}' ret += '}' - ret += '@keyframes blink {' - ret += '0% { background-color: rgba(0,0,0,0.7); }' - ret += '50% { background-color: rgba(0,0,0,0.7); }' - ret += '50.001% { background-color: rgba(255,255,255,0.7); }' - ret += '100% { background-color: rgba(255,255,255,0.7); }' + ret += '@keyframes blink { ' + ret += '0%{background-position:0% 0%}' + ret += '100%{background-position:0% -100%}' ret += '}' ret += '.ann_box {' ret += 'z-index: 5;' @@ -390,13 +388,15 @@ find_prev_cursor_position = (tree, n, i) -> if prev_xyh.x < orig_xyh.x or prev_xyh.y < orig_xyh.y return [n, prev_i] return [n, i - 1] - found_prev = n? + found_prev = null found = null traverse_tree tree, (node) -> if node.type is 'text' + unless n? + found = node + return true if node is n - if found_prev? - found = found_prev + found = found_prev # null if n is the first text node return true found_prev = node return false @@ -611,9 +611,9 @@ class PeachHTML5Editor constructor: (in_el, options) -> @options = options ? {} @in_el = in_el - @tree = [] + @tree = null @matting = [] - @inited = false # when iframes have loaded + @init_1_called = false # when iframes have loaded @outer_iframe # iframe to hold editor @outer_idoc # "document" object for @outer_iframe @wrap2 = null # scrollbar is on this @@ -624,6 +624,7 @@ class PeachHTML5Editor @cursor_visible = false @poll_for_blur_timeout = null @iframe_offset = null + @iframe_height = null opt_fragment = @options.fragment ? true @parser_opts = {} if opt_fragment @@ -641,10 +642,12 @@ class PeachHTML5Editor @outer_idoc.head.appendChild icss @iframe = domify @outer_idoc, iframe: sandbox: 'allow-same-origin allow-scripts' @iframe.onload = => - @init() - setTimeout (=> @init() unless @inited), 200 # firefox never fires this onload + @init_1() + timeout 200, => # firefox never fires this onload + @init_1() unless @init_1_called @outer_idoc.body.appendChild( domify @outer_idoc, div: id: 'wrap1', children: [ + domify @outer_idoc, div: style: "position: absolute; top: 0; left: 1px; font-size: 10px", children: [ domify @outer_idoc, text: "Peach HTML5 Editor" ] @wrap2 = domify @outer_idoc, div: id: 'wrap2', children: [ domify @outer_idoc, div: id: 'wrap3', children: [ @iframe @@ -664,8 +667,23 @@ class PeachHTML5Editor @outer_iframe.setAttribute 'style', outer_iframe_style css = outer_css w: outer_bounds.w, h: outer_bounds.h outer_wrap.appendChild @outer_iframe - init: -> # called by @iframe's onload (or timeout on firefox) + init_1: -> # @iframe has loaded (but not it's css) @idoc = @iframe.contentDocument + @init_1_called = true + # chromium doesn't resolve relative urls as though they were at the same domain + # so add a tag + @idoc.head.appendChild domify @idoc, base: href: this_url_sans_path() + # don't let @iframe have scrollbars + @idoc.head.appendChild domify @idoc, style: children: [domify @idoc, text: "body { overflow: hidden; }"] + # load css file + if @options.css_file + istyle = domify @idoc, link: rel: 'stylesheet', href: @options.css_file + istyle.onload = => + @init_2() + @idoc.head.appendChild istyle + else + @init_2() + init_2: -> # @iframe and it's css file(s) are ready @overlay.onclick = (e) => @have_focus() return event_return e, @onclick e @@ -681,14 +699,7 @@ class PeachHTML5Editor @outer_idoc.body.onkeypress = (e) => @have_focus() return event_return e, @onkeypress e - # chromium doesn't resolve relative urls as though they were at the same domain - # so add a tag - @idoc.head.appendChild domify @idoc, base: href: this_url_sans_path() - if @options.css_file - # TODO test this - @idoc.head.appendChild domify @idoc, link: rel: 'stylesheet', type: 'text/css', href: @options.css_file @load_html @in_el.value - @inited = true if @options.on_init? @options.on_init() overlay_event_to_inner_xy: (e) -> @@ -730,6 +741,47 @@ class PeachHTML5Editor break return false when KEY_UP + if @cursor? + new_cursor = @cursor + old_loc = cursor_to_xyh new_cursor[0], new_cursor[1] + new_loc = x: old_loc.x, y: old_loc.y + while new_loc.y >= old_loc.y + new_cursor = find_prev_cursor_position @tree, new_cursor[0], new_cursor[1] + return false unless new_cursor? + new_loc = cursor_to_xyh new_cursor[0], new_cursor[1] + if new_cursor? + # now we're above + if new_loc.x <= old_loc.x + @move_cursor new_cursor + return false + target_y = new_loc.y + # search leftward, until we find the closest position + while new_loc.x > old_loc.x and new_loc.y is target_y + prev_loc = new_loc + prev_cursor = new_cursor + new_cursor = find_prev_cursor_position @tree, new_cursor[0], new_cursor[1] + break unless new_cursor? + new_loc = cursor_to_xyh new_cursor[0], new_cursor[1] + # move cursor to prev_cursor or new_cursor + if new_cursor? + if new_loc.y is target_y + # both valid, and on the same line, use closest + if (old_loc.x - new_loc.x) < (prev_loc.x - old_loc.x) + @move_cursor new_cursor + else + @move_cursor prev_cursor + else + # new_cursor on wrong line, use prev_cursor + @move_cursor prev_cursor + else + # can't go any further prev, use prev_cursor + @move_cursor prev_cursor + else + # move cursor to first position in document + new_cursor = find_prev_cursor_position @tree + if new_cursor? + @move_cursor new_cursor + break return false when KEY_RIGHT if @cursor? @@ -737,11 +789,11 @@ class PeachHTML5Editor if new_cursor? @move_cursor new_cursor else - for c in @tree - new_cursor = find_prev_cursor_position @tree, c, -1 - if new_cursor? - @move_cursor new_cursor - break + # move cursor to first position in document + new_cursor = find_prev_cursor_position @tree + if new_cursor? + @move_cursor new_cursor + break return false when KEY_DOWN return false @@ -813,8 +865,15 @@ class PeachHTML5Editor @in_el.value = @pretty_html @tree @in_el.onchange = => @load_html @in_el.value - @iframe.style.height = "0" - @iframe.style.height = "#{@idoc.body.scrollHeight}px" + @adjust_iframe_height() + adjust_iframe_height: -> + h = parseInt(@idoc.body.scrollHeight, 10) + if @iframe_height isnt h + @iframe_height = h + s = @wrap2.scrollTop + @iframe.style.height = "0" + @iframe.style.height = "#{h}px" + @wrap2.scrollTop = s kill_cursor: -> # remove it, forget where it was if @cursor_visible @cursor_el.parentNode.removeChild @cursor_el