inner_padding = args.inner_padding ? overlay_padding
frame_width = args.frame_width ? inner_padding
# TODO editor controls height...
- shrink = (px) ->
- w -= 2 * px
- h -= 2 * px
- return px
+ occupy = (left, top = left, right = left, bottom = top) ->
+ w -= left + right
+ h -= top + bottom
+ return Math.max(left, top, right, bottom)
ret = ''
ret += 'body {'
ret += 'margin: 0;'
ret += 'padding: 0;'
ret += '}'
ret += '#wrap1 {'
- ret += "border: #{shrink 1}px solid black;"
- ret += "padding: #{shrink frame_width}px;"
+ ret += "border: #{occupy 1}px solid black;"
+ ret += "padding: #{occupy frame_width}px;"
ret += '}'
ret += '#wrap2 {'
- ret += "border: #{shrink 1}px solid black;"
- ret += "padding: #{shrink inner_padding}px;"
+ ret += "border: #{occupy 1}px solid black;"
+ ret += "padding: #{occupy inner_padding}px;"
+ ret += "padding-right: #{inner_padding + occupy 0, 0, 15, 0}px;" # for scroll bar
+ ret += "width: #{w}px;"
+ ret += "height: #{h}px;"
+ ret += 'overflow-x: hidden;'
+ ret += 'overflow-y: scroll;'
ret += '}'
ret += '#wrap3 {'
ret += 'position: relative;'
+ ret += "width: #{w}px;"
+ ret += "min-height: #{h}px;"
ret += '}'
ret += 'iframe {'
ret += 'box-sizing: border-box;'
ret += 'border: none;'
ret += 'padding: 0;'
ret += "width: #{w}px;"
- ret += "height: #{h}px;"
+ #ret += "height: #{h}px;" # height auto-set when content set/changed
ret += '}'
ret += '#overlay {'
ret += 'position: absolute;'
'9': KEY_TAB
instantiate_tree = (tree, parent) ->
- for c in tree
+ remove = []
+ for c, i in tree
switch c.type
when TYPE_TEXT
c.el = parent.ownerDocument.createTextNode c.text
parent.appendChild c.el
when TYPE_TAG
+ if c.name in ['script', 'object', 'iframe', 'link']
+ # TODO put placeholders instead
+ remove.unshift i
# TODO create in correct namespace
c.el = parent.ownerDocument.createElement c.name
for k, v of c.attrs
parent.appendChild c.el
if c.children.length
instantiate_tree c.children, c.el
+ for i in remove
+ tree.splice i, 1
traverse_tree = (tree, state, cb) ->
for c in tree
@iframe = domify @outer_idoc, iframe: {}
@iframe.onload = =>
@init()
+ setTimeout (=> @init()), 200 # firefox never fires this onload
@outer_idoc.body.appendChild(
domify @outer_idoc, div: id: 'wrap1', children: [
domify @outer_idoc, div: id: 'wrap2', children: [
@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
+ init: -> # called by @iframe's onload (or timeout on firefox)
+ return if @initialized # ignore timeout for non-broken browsers
@idoc = @iframe.contentDocument
@overlay.onclick = (e) =>
return @onclick e
@in_el.value = dom_to_html @tree
@in_el.onchange = =>
@load_html @in_el.value
+ @iframe.style.height = "0"
+ @iframe.style.height = "#{@idoc.body.scrollHeight}px"
kill_cursor: -> # remove it, forget where it was
if @cursor_visible
@cursor_el.parentNode.removeChild @cursor_el