JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
check for visibility:hidden/collapsed too
[peach-html5-editor.git] / editor.coffee
index 8bc72ef..66d1dfe 100644 (file)
 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_:.]*$'
@@ -248,6 +253,10 @@ 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
 
@@ -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
@@ -847,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
@@ -868,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
@@ -938,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...