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