Javascript [non-]内容可编辑HTML5元素上的键盘事件

Javascript [non-]内容可编辑HTML5元素上的键盘事件,javascript,jquery,linux,html,contenteditable,Javascript,Jquery,Linux,Html,Contenteditable,我正在编写(自由软件,alpha-stage,与定制GCC的领域特定语言相关)。它被用作一个专门的web服务器,我希望它成为我正在设计的某些DSL的语法导向编辑器。我说的是承诺,如果这很重要的话。您可以将其作为/monimelt-Dweb运行,运行-W localhost.localdomain:8086,然后在浏览器中打开 我正在发射(通过文件webroot/microedit.html) 现在,我希望类的每个对一些键盘(也许还有鼠标)事件敏感。但是,contenteditable元素可以通过

我正在编写(自由软件,alpha-stage,与定制GCC的领域特定语言相关)。它被用作一个专门的web服务器,我希望它成为我正在设计的某些DSL的语法导向编辑器。我说的是承诺,如果这很重要的话。您可以将其作为
/monimelt-Dweb运行,运行-W localhost.localdomain:8086
,然后在浏览器中打开

我正在发射(通过文件
webroot/microedit.html

现在,我希望类
的每个
对一些键盘(也许还有鼠标)事件敏感。但是,
contenteditable
元素可以通过许多用户操作进行编辑(我甚至不知道这类用户操作的完整列表是什么……)并且我只希望这些span元素对定义的和受限的按键集作出响应(字母数字和空格)并且不能被用户更改,否则(例如,没有标点符号、没有“剪切”、没有“粘贴”、没有退格、没有制表符等)

是否有
contenteditable='true'
元素可以获取并响应的事件(或用户操作)的完整列表

如何禁用大多数事件或用户操作(在键盘和鼠标上)并仅对某些(定义良好的)键盘事件作出反应?

显然,非可编辑内容的
元素中的
元素无法获得任何键盘用户操作(因为它无法获得焦点)

我只针对最新的HTML5浏览器,如Firefox38或42,或Chrome47等。。。在Debian/Linux/x86-64上,如果这很重要的话(所以我真的不关心IE9)

PS.是一个相关的问题,但不是同一个问题

PS2:找到了博客页面。让我几乎哭了。。。还可以阅读关于(的文章)。另请参见关于和草稿的W3C草稿内部文档。W3C的两项工作都在进行中。W3C TR on(2015年11月)仍然是一份工作草案。另请参见(在Chrome 46和Firefox 42或43 beta中表现不同)

PS3:也许
contenteditable
毕竟是个坏主意。我(遗憾地)正在考虑使用
画布
(a la)并用手写javascript进行所有编辑和绘图


增编: (2015年11月26日)

通过与一些Mozilla人士私下讨论,我了解到:

  • 杂乱无章(因此我宁愿避免),在Firefox中也不再有效(例如,即使是最近的测试版Firefox也不知道
    contenteditable='events',
    ,请参阅)

  • 非常重要

  • 一个普通的
    (或
    )可以通过给它一个
    tabindex
    属性来设置焦点

  • API可能很有用(但有一些最新的)

所以我可能不需要
内容可编辑

您可以这样做:

function validateInput(usrAct){
  swich(usrAct){
    case "paste":
    // do something when pasted
    break;
    case "keydown":
    // dosomething on keydown
    break;
    default:
    //do something on default
    break;
  }
}

document.querySelectorAll('.momitemref_cl').addEventListener('input', function(e){
  validateInput(e.type)
}, false);

首先,
HTMLElements
在您将其
contentEditableElements
属性设置为
true
时变为
contentEditableElements

现在,执行IMO解析的最佳方法是侦听并检查元素的
textContent

s.addEventListener('input',validate,false);
功能验证(evt){
var badValues=['bad','content'];
var span=这个;
badValues.forEach(函数(v){
if(span.textContent.indexOf(v)>-1){
//那太糟糕了,钥匙
span.textContent=span.textContent.split(v).join(“”);
}
});
};
Hello
编辑: (仅处理所述类的跨距。还处理这样的情况,即可以从另一个跨距返回到上一个跨距并删除它。合并了@AWolff的思想,用于切换焦点上的contenteditable属性)

总体思路与前一版本相同

小提琴:

片段:

var div=document.getElementById('microedit_id'),
span=document.querySelectorAll('#microedit_id.momtItemRef_cl'),
命令=[“粘贴”、“剪切”],
//白名单是按键事件的按键代码
白名单=[{'range':true,'start':'97','end':'122},//小写
{'range':true,'start':'65','end':'90'},//大写
{'range':true,'start':'48','end':'57'}//数字
], 
//specialkeys是按键关闭事件的按键代码
specialKeys=[8,9,13,46]//退格、制表符、输入、删除
;
div.addEventListener('keydown',把手外,假);
[].forEach.call(跨度,函数(跨度){
span.setAttribute('contenteditable',true);
setAttribute('tabindex','-1');
span.添加的事件监听器('focus',handleFocus,false);
span.增补列表(“模糊”,把手模糊,错误);
commands.forEach(函数(cmd){
span.addEventListener(cmd,函数(e){
e、 preventDefault();返回false;
});
});
span.添加的监听器('keypress',handlePress,false);
span.addEventListener('keydown',handleDown,false);
});
函数handleFocus(e){div.setAttribute('contenteditable',false);}
函数handleBlur(e){div.setAttribute('contenteditable',true);}
功能手柄(e){
允许的var=false,key=e.keyCode;
白名单.forEach(函数(范围){

如果(键&&(键!='')和(range.start这段代码可能就是你想要的,使
span.momtItemRef\u cl
元素可聚焦但不可选项卡化,并且设置为
contenteditable
。但是当我在chrome上测试它时,
contenteditable
在任何属性
contenteditable
设置为
true
的容器中,不要触发任何键盘事件。所以技巧可能是聚焦,将任何容器设置为不可编辑(并切换回模糊)

参见示例:(keypress和keydown事件都是绑定的,用于处理keypress或keydown无法处理的特定情况
    <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> 
function validateInput(usrAct){
  swich(usrAct){
    case "paste":
    // do something when pasted
    break;
    case "keydown":
    // dosomething on keydown
    break;
    default:
    //do something on default
    break;
  }
}

document.querySelectorAll('.momitemref_cl').addEventListener('input', function(e){
  validateInput(e.type)
}, false);
<div class="momitemref_cl" contenteditable="true">Foo Bar</div>
<input class="not-momitemref_cl"/>
<input class="momitemref_cl"/>
document.querySelectorAll('.momitemref_cl').forEach((el) => {
    el.addEventListener('keydown', validateInput);
    el.addEventListener('cut', e => e.preventDefault());
    el.addEventListener('copy', e => e.preventDefault());
    el.addEventListener('paste', e => e.preventDefault());
});

function validateInput(userAction) {
    console.log(userAction);
    if (userAction.ctrlKey) {
        userAction.preventDefault();
        return false;
    }
    let code = (userAction.keyCode ? userAction.keyCode : userAction.which);
    if ((48 <= code && code <= 57 && !userAction.shiftKey) || (65 <= code && code <= 90) || (97 <= code && code <= 122) || code === 32) {
        console.log(`Allowing keypress with code: ${code}`);
        return true;
    }
    console.log(`Preventing keypress with code: ${code}`);
    userAction.preventDefault();
    return false;
}