我正在编写MELT监视器 (免费软件,alpha阶段,与GCC MELT域特定语言相关以定制GCC)。 它使用libonion作为一个专门的Web服务器,我希望它成为我正在devise的一些DSL的语法指导编辑器。 如果有问题的话我说的是提交97d60053 。 你可以运行./monimelt -Dweb,run -W localhost.localdomain:8086
然后在浏览器中打开http://localhost.localdomain:8086 / microedit.html 。
我正在发射(通过文件的webroot/microedit.html
)
<h1>Micro Editing Monimelt</h1> <div id='microedit_id' contenteditable='true'>*</div> <hr/>
那么一些AJAX #micredit_id
就是用包含类似于以下内容的东西来填充#micredit_id
元素:
<dd class='statval_cl' data-forattr='notice'> ▵ <span class='momnode_cl'>*<span class='momconn_cl'> <span class='momitemref_cl'>comment</span></span> (“<span class='momstring_cl'>some simple notice</span>” <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>
现在,我希望类momitemref_cl
每个<span>
对某些键盘(也许是鼠标)事件敏感。 然而,可以通过许多用户操作(我甚至不理解这些用户操作的整个列表是什么…)来编辑可contenteditable
元素,而我只希望这些span元素能够响应定义和限制的按键 (字母数字和空格键 ) ,否则不能被用户修改 (例如没有标点符号,没有“剪切”,没有“粘贴”,没有退格键 ,没有标签等)。
是否有contenteditable='true'
元素可以获取和正在做出反应的事件(或用户操作)的完整列表?
如何禁用大部分这些事件或用户操作 (在键盘和鼠标上) , 只对一些 (定义明确的) 键盘事件 作出反应 ?
显然,一个非contenteditable
元素中的<span>
元素不能得到任何键盘用户操作(因为它不能获得焦点)…
我只针对最近的HTML5浏览器,如Firefox 38或42,或Chrome 47等…在Debian / Linux / x86-64(如此重要)(所以我真的不关心IE9)
PS。 这是一个相关的问题,但不是一回事。
PS2:发现为什么contenteditable
是可怕的博客页面。 让我差点哭了…还读了关于在浏览器的Javascript ( CodeMirror )中伪造一个可编辑的控件 。 另请参阅W3C关于编辑讲解员和编辑活动草案的内部文件草案。 W3C的两件事情都在进行中。 关于UI事件的 W3C TR仍然是(2015年11月)的工作草案。 另请参阅http://jsfiddle.net/8j6jea6p/ (在Chrome 46和Firefox 42或43 beta中的行为不同)
PS3:也许一个contenteditable
是一个坏主意。 我(可悲的是)考虑使用canvas
(àla carota ),并通过手写的JavaScript做所有的编辑和绘图…
(2015年11月26 日 )
通过与一些Mozilla人私下讨论,我了解到:
contenteditable
是凌乱的(所以我宁愿避免它),并不再在Firefox中工作太多(例如,即使是最近的testing版Firefox也不知道contenteditable='events'
,请参阅nsGenericHTMLElement.h
文件 )
事件冒泡和捕获事情很重要
一个普通的<div>
(或<span>
)可以通过给它一个tabindex
属性来进行聚焦
文本select API可能是有用的(但有一些最近的错误 )
所以我可能不需要contenteditable
你可以这样做:
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').addEventlistner('input', function(e){ validateInput(e.type) }, false);
这个片段可能是你正在寻找的,使span.momitemref_cl
元素可以聚焦,但不可tabbable和设置contenteditable
。 但是,当我在chrome上测试它时, contenteditable
属性contenteditable
设置为true
任何容器内,不要触发任何键盘事件。 所以技巧可能是关注于将任何容器设置为不可编辑(并切换回模糊)。
看例如: (keypress和keydown事件都绑定处理一些特定的情况下,按键或keydown将不会触发特定的键)
注: 你似乎动态地填充DIV的内容,你可以委托它或绑定事件(&设置tabindex属性,如果改变它在HTML标记不解决方案)一旦Ajax请求已经完成。
$('#microedit_id .momitemref_cl').attr('tabindex', -1).prop('contenteditable', true).on('focusin focusout', function(e) { $(this).parents('[contenteditable]').prop('contenteditable', e.type === "focusout"); }).on('keypress keydown paste cut', function(e) { if (/[a-zA-Z0-9 ]/.test(String.fromCharCode(e.which))) return; return false; });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <h1>Micro Editing Monimelt</h1> <div id='microedit_id' contenteditable='true'> <dd class='statval_cl' data-forattr='notice'>▵ <span class='momnode_cl'>*<span class='momconn_cl'> <span class='momitemref_cl'>comment</span></span>(“<span class='momstring_cl'>some simple notice</span>” <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/>
首先, HTMLElements
在将contentEditable
属性设置为true
时变为contentEditableElements
。
现在,解析IMO的最好方法是监听inputEvent
并检查元素的textContent
:
s.addEventlistner('input', validate, false); function validate(evt) { var badValues = ['bad', 'content']; var span = this; badValues.forEach(function(v) { if (span.textContent.indexOf(v) > -1) { // that's bad m..key span.textContent = span.textContent.split(v).join(''); } }); };
<span id="s" contentEditable="true">Hello</span>
( 只处理所述类的跨度,也处理这种情况,你可以从另一个跨度返回到前一个跨度,并且可以删除它,并包含了@AWolff用于将contenteditable属性转换为焦点的想法 )
总体思路与前一版本保持一致。
小提琴: http : //jsfiddle.net/abhitalks/gb0mbwLu/
片段:
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.addEventlistner('keydown', handleFromOutside, false); [].forEach.call(spans, function(span) { span.setAttribute('contenteditable', true); span.setAttribute('tabindex', '-1'); span.addEventlistner('focus', handleFocus, false); span.addEventlistner('blur', handleBlur, false); commands.forEach(function(cmd) { span.addEventlistner(cmd, function(e) { e.preventDefault(); return false; }); }); span.addEventlistner('keypress', handlePress, false); span.addEventlistner('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 (prev || next) { if (node.className == 'momitemref_cl') { if (specialKeys.indexOf(key) >= 0) { e.preventDefault(); return false; } } } }
<h1>Micro Editing Monimelt</h1> <div id='microedit_id' contenteditable='true'> <dd class='statval_cl' data-forattr='notice'> ▵ <span class='momnode_cl'>*<span class='momconn_cl'> <span class='momitemref_cl'>comment</span></span> (“<span class='momstring_cl'>some simple notice</span>” <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/>