X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=editor.coffee;h=66d1dfedcaa62042c2d17a2982b3fab7fcf6a567;hb=fb81209e78ff39a5469ee9217b35d4edf94a21d5;hp=92fc1e03e0fbd11aa17c1105265a4af5496b7a87;hpb=d415d52813ae2ee5c19bb2fd183de1f6158f6d13;p=peach-html5-editor.git diff --git a/editor.coffee b/editor.coffee index 92fc1e0..66d1dfe 100644 --- a/editor.coffee +++ b/editor.coffee @@ -18,8 +18,13 @@ overlay_padding = 10 timeout = (ms, cb) -> return setTimeout cb, ms +next_frame = (cb) -> + if (window.requestAnimationFrame?) + window.requestAnimationFrame cb + else + timeout 16, cb -# xml 1.0 says: +# xml 1.0 spec, chromium and firefox accept these, plus lots of unicode chars valid_attr_regex = new RegExp '^[a-zA-Z_:][-a-zA-Z0-9_:.]*$' # html5 spec is much more lax, but chromium won't let me make at attribute with the name "4" js_attr_regex = new RegExp '^[oO][nN].' @@ -248,10 +253,22 @@ outer_css = (args) -> ret += 'font-size: 8px;' ret += 'white-space: pre;' ret += 'background: rgba(255,255,255,0.4);' + ret += '-ms-user-select: none;' + ret += '-webkit-user-select: none;' + ret += '-moz-user-select: none;' + ret += 'user-select: none;' ret += '}' return ret -# key codes: + +ignore_key_codes = + '18': true # alt + '20': true # capslock + '17': true # ctrl + '144': true # numlock + '16': true # shift + '91': true # windows "start" key +# key codes: (valid on keydown, not keypress) KEY_LEFT = 37 KEY_UP = 38 KEY_RIGHT = 39 @@ -266,14 +283,6 @@ KEY_INSERT = 45 KEY_PAGE_UP = 33 KEY_PAGE_DOWN = 34 KEY_TAB = 9 - -ignore_key_codes = - '18': true # alt - '20': true # capslock - '17': true # ctrl - '144': true # numlock - '16': true # shift - '91': true # windows "start" key control_key_codes = # we react to these, but they aren't typing '37': KEY_LEFT '38': KEY_UP @@ -593,6 +602,7 @@ class PeachHTML5Editor @cursor = null @cursor_el = null @cursor_visible = false + @poll_for_blur_timeout = null @iframe_offset = null opt_fragment = @options.fragment ? true @parser_opts = {} @@ -637,14 +647,19 @@ class PeachHTML5Editor init: -> # called by @iframe's onload (or timeout on firefox) @idoc = @iframe.contentDocument @overlay.onclick = (e) => + @have_focus() return event_return e, @onclick e @overlay.ondoubleclick = (e) => + @have_focus() return event_return e, @ondoubleclick e @outer_idoc.body.onkeyup = (e) => + @have_focus() return event_return e, @onkeyup e @outer_idoc.body.onkeydown = (e) => + @have_focus() return event_return e, @onkeydown e @outer_idoc.body.onkeypress = (e) => + @have_focus() return event_return e, @onkeypress e if @options.stylesheet # TODO test this @@ -665,6 +680,8 @@ class PeachHTML5Editor new_cursor = find_loc_cursor_position @tree, xy if new_cursor? @move_cursor new_cursor + else + @kill_cursor() return false ondoubleclick: (e) -> return false @@ -740,7 +757,7 @@ class PeachHTML5Editor onkeypress: (e) -> return if e.ctrlKey return false if ignore_key_codes[e.keyCode]? - return false if control_key_codes[e.keyCode]? # handled in keydown + # return false if control_key_codes[e.keyCode]? # handled in keydown char = e.charCode ? e.keyCode if char and @cursor? char = String.fromCharCode char @@ -845,12 +862,14 @@ class PeachHTML5Editor display = cs['display'] position = cs['position'] float = cs['float'] + visibility = cs['visibility'] else cs = @iframe.contentWindow.getComputedStyle(n.el, null) whitespace = cs.getPropertyValue 'white-space' display = cs.getPropertyValue 'display' position = cs.getPropertyValue 'position' float = cs.getPropertyValue 'float' + visibility = cs.getPropertyValue 'visibility' if n.name is 'textarea' inner_flags.pre_ish = true else @@ -866,7 +885,11 @@ class PeachHTML5Editor if 'display' is 'none' in_flow = false else - in_flow = true + switch visibility + when 'hidden', 'collapse' + in_flow = false + else # visible + in_flow = true switch display when 'inline', 'none' inner_flags.block = false @@ -936,6 +959,21 @@ class PeachHTML5Editor if prev_in_flow_is_block or parent_flags.block ret += "\n#{indent.substr 4}" return ret + onblur: -> + @kill_cursor() + have_focus: -> + @editor_is_focused = true + @poll_for_blur() + poll_for_blur: -> + return if @poll_for_blur_timeout? # already polling + @poll_for_blur_timeout = timeout 150, => + next_frame => # pause polling when browser knows we're not active/visible/etc. + @poll_for_blur_timeout = null + if document.activeElement is @outer_iframe + @poll_for_blur() + else + @editor_is_focused = false + @onblur() window.peach_html5_editor = (args...) -> return new PeachHTML5Editor args...