Prevent Events in ContentEditable

by abhitalks

HTML

<h1>Micro Editing Monimelt</h1>
<div id='microedit_id' contenteditable='true'>
    <dd class='statval_cl' data-forattr='notice'> &#9653;
    <span class='momnode_cl'>*<span class='momconn_cl'>
    <span class='momitemref_cl'>comment</span></span>
    (&#8220;<span class='momstring_cl'>some simple notice</span>&#8221;
     <span class='momnode_cl'>*<span class='momconn_cl'>
     <span class='momitemref_cl'>web_state</span></span>
     (<span class='momnumber_cl'>2</span>)</span>
     <span class='momitemval_cl'>hashset</span>
     <span class='momset_cl'>{<span class='momitemref_cl'>microedit</span>
     <span class='momitemref_cl'>the_agenda</span>}</span>
     <span class='momtuple_cl'>[<span class='momitemref_cl'>web_session</span>
     <span class='momitemref_cl empty_cl'>~</span>
     <span class='momitemref_cl'>the_system</span>]</span>)</span> ;</dd>     
</div>
<hr/>

CSS

span.momitemref_cl { background-color: yellow; }

JavaScript

var div = document.getElementById('microedit_id'), 
    spans = document.querySelectorAll('#microedit_id .momitemref_cl'), 
    commands = ['paste', 'cut'], 
    // whitelist is the keycodes for keypress event
    whitelist = [{'range': true, 'start': '97', 'end': '122'}, // lower-case
                 {'range': true, 'start': '65', 'end': '90'}, // upper-case
                 {'range': true, 'start': '48', 'end': '57' } // numbers
	], 
    // specialkeys is the keycodes for keydown event
    specialKeys = [8, 9, 13, 46] // backspace, tab, enter, delete
;
div.addEventListener('keydown', handleFromOutside, false);

[].forEach.call(spans, function(span) {
    span.setAttribute('contenteditable', true);
    span.setAttribute('tabindex', '-1');
    span.addEventListener('focus', handleFocus, false);
    span.addEventListener('blur', handleBlur, false);
    commands.forEach(function(cmd) {
        span.addEventListener(cmd, function(e) {
            e.preventDefault(); return false;
        });
    });
    span.addEventListener('keypress', handlePress, false);
    span.addEventListener('keydown', handleDown, false);
});

function handleFocus(e) { div.setAttribute('contenteditable', false); }
function handleBlur(e) { div.setAttribute('contenteditable', true); }

function handlePress(e) {
    var allowed = false, key = e.keyCode;
    whitelist.forEach(function(range) {
        if (key && (key != '') && (range.start <= key) && (key <= range.end)) {
            allowed = true;
        }
    });
    if (! allowed) { e.preventDefault(); return false; }
}

function handleDown(e) {
    var allowed = false, key = e.keyCode;
    specialKeys.forEach(function(spl) {
        if (key && (spl == key)) { e.preventDefault(); return false; }
    });
}

function handleFromOutside(e) {
    var key = e.keyCode, node = window.getSelection().anchorNode, prev, next;
    node = (node.nodeType == 3 ? node.parentNode : node)
    prev = node.previousSibling; next = node.nextSibling; 
    if...