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 spec, chromium and firefox accept these, plus lots of unicode chars
valid_attr_regex = new RegExp '^[a-zA-Z_:][-a-zA-Z0-9_:.]*$'
@cursor = null
@cursor_el = null
@cursor_visible = false
+ @poll_for_blur_timeout = null
@iframe_offset = null
opt_fragment = @options.fragment ? true
@parser_opts = {}
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
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...