X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=editor.coffee;h=faa2e3f25462bb44211107f980e8a9b88de31dd9;hb=dc0f845531025a04b5e3a541d1ba8c98fc96b1b4;hp=b608e6ba2747cb54cdb7fdd3a9b313aed33dc5b1;hpb=c8370edb3147dad5c8921f6dd4509a3c94658e0c;p=peach-html5-editor.git diff --git a/editor.coffee b/editor.coffee index b608e6b..faa2e3f 100644 --- a/editor.coffee +++ b/editor.coffee @@ -15,9 +15,12 @@ # along with this program. If not, see . # encode text so it can be safely placed inside an html attribute +enc_attr_regex = new RegExp '(&)|(")|(\u00A0)', 'g' enc_attr = (txt) -> - # FIXME implement - return txt + return txt.replace enc_attr_regex, (match, amp, quote) -> + return '&' if (amp) + return '"' if (quote) + return ' ' void_elements = { area: true @@ -40,43 +43,151 @@ dom_to_html = (dom) -> ret = '' for el in dom switch el.type - when wheic_parser.TYPE_TAG + when peach_parser.TYPE_TAG ret += '<' + el.name attr_keys = [] for k of el.attrs - attr_keys.push k - attr_keys.sort() + attr_keys.unshift k + #attr_keys.sort() for k in attr_keys - ret += " #{k}=\"#{enc_attr el.attrs[k]}\"" + ret += " #{k}" + if el.attrs[k].length > 0 + ret += "=\"#{enc_attr el.attrs[k]}\"" ret += '>' - unless ret.name in void_elements + unless void_elements[el.name] if el.children.length ret += dom_to_html el.children ret += "" - when wheic_parser.TYPE_TEXT + when peach_parser.TYPE_TEXT ret += el.text - when wheic_parser.TYPE_COMMENT + when peach_parser.TYPE_COMMENT ret += "" - when wheic_parser.TYPE_DOCTYPE + when peach_parser.TYPE_DOCTYPE ret += " 0 ret += " \"#{el.public_identifier}\"" if el.system_identifier? and el.system_identifier.length > 0 ret += " \"#{el.system_identifier}\"" + ret += ">\n" return ret +domify = (h) -> + for tag, attrs of h + if tag is 'text' + return document.createTextNode attrs + el = document.createElement tag + for k, v of attrs + if k is 'children' + for child in v + el.appendChild child + else + el.setAttribute k, v + return el + +css = '' +css += 'div#peach_editor_cursor {' +css += 'display: inline-block;' +css += 'height: 1em;' +css += 'width: 2px;' +css += 'margin-left: -1px;' +css += 'margin-right: -1px;' +css += 'background: #000;' +css += '-webkit-animation: 1s blink step-end infinite;' +css += 'animation: 1s blink step-end infinite;' +css += '}' +css += '@-webkit-keyframes "blink" {' +css += 'from, to { background: #000; }' +css += '50% { background: transparent; }' +css += '}' +css += '@keyframes "blink" {' +css += 'from, to { background: #000; }' +css += '50% { background: transparent; }' +css += '}' + +# key codes: +KEY_LEFT = 37 +KEY_UP = 38 +KEY_RIGHT = 39 +KEY_DOWN = 40 +KEY_BACKSPACE = 8 # <-- +KEY_DELETE = 46 # --> +KEY_END = 35 +KEY_ENTER = 13 +KEY_ESCAPE = 27 +KEY_HOME = 36 +KEY_INSERT = 45 +KEY_PAGE_UP = 33 +KEY_PAGE_DOWN = 34 +KEY_TAB = 9 + wysiwyg = (el, options = {}) -> opt_fragment = options.fragment ? true parser_opts = {} if opt_fragment parser_opts.fragment = 'body' - editor_instance = dom: wheic_parser.parse(el.value, parser_opts) - # el.value = dom_to_html dom + editor_instance = { + dom: [] + iframe: document.createElement('iframe') + load_html: (html) -> + @dom = peach_parser.parse html, parser_opts + as_html = peach.dom_to_html @dom + as_html = as_html.substr(0, 5) + '' + as_html.substr(5) + @iframe.contentDocument.body.innerHTML = as_html + } + el.parentNode.appendChild editor_instance.iframe + idoc = editor_instance.iframe.contentDocument + 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 + '39': KEY_RIGHT + '40': KEY_DOWN + '35': KEY_END + '8': KEY_BACKSPACE + '46': KEY_DELETE + '13': KEY_ENTER + '27': KEY_ESCAPE + '36': KEY_HOME + '45': KEY_INSERT + '33': KEY_PAGE_UP + '34': KEY_PAGE_DOWN + '9': KEY_TAB + + idoc.body.onkeyup = (e) -> + return false if ignore_key_codes[e.keyCode]? + return false if control_key_codes[e.keyCode]? + idoc.body.onkeydown = (e) -> + return false if ignore_key_codes[e.keyCode]? + return false if control_key_codes[e.keyCode]? + idoc.body.onkeypress = (e) -> + return if e.ctrlKey + return false if ignore_key_codes[e.keyCode]? + # in firefox, keyCode is only set for non-typing keys + if e.keyCode isnt KEY_BACKSPACE # so this is fine + return false if control_key_codes[e.keyCode]? + char = e.charCode ? e.keyCode + el.value += String.fromCharCode char + editor_instance.load_html el.value + return false + if options.stylesheet # TODO test this + istyle = idoc.createElement 'style' + istyle.setAttribute 'src', options.stylesheet + idoc.head.appendChild istyle + icss = idoc.createElement 'style' + icss.appendChild idoc.createTextNode css + idoc.head.appendChild icss + editor_instance.load_html el.value return editor_instance -window.wheic = { +window.peach = { wysiwyg: wysiwyg dom_to_html: dom_to_html } -# test in browser: wheic(document.getElementsByTagName('textarea')[0]) +# test in browser: peach.wysiwyg(document.getElementsByTagName('textarea')[0])