Javascript 为什么我的内容可编辑插入符号在Chrome中跳到了最后? 脚本

Javascript 为什么我的内容可编辑插入符号在Chrome中跳到了最后? 脚本,javascript,html,google-chrome,contenteditable,Javascript,Html,Google Chrome,Contenteditable,我有一个contenteditable区域,在这个区域中我可能有一些包含一些文本。其思想是,这些span元素将表示无法编辑的样式文本,但可以通过按backspace键从区域中删除 问题 光标位置是这里的大问题。如果删除其中一个元素,光标将跳到的末尾。更有趣的是,如果您在光标处于“末尾”时键入一些文本,则文本的位置很好。。。然后,如果您删除新键入的文本,光标将向后跳 我准备了一把小提琴来演示这一点我只需要在Chrome中使用它,其他浏览器要么暂时不关心,要么已经有了解决办法。(另请注意,准备好的提

我有一个contenteditable
区域,在这个区域中我可能有一些
包含一些文本。其思想是,这些span元素将表示无法编辑的样式文本,但可以通过按backspace键从
区域中删除

问题 光标位置是这里的大问题。如果删除其中一个
元素,光标将跳到
的末尾。更有趣的是,如果您在光标处于“末尾”时键入一些文本,则文本的位置很好。。。然后,如果您删除新键入的文本,光标将向后跳

我准备了一把小提琴来演示这一点我只需要在Chrome中使用它,其他浏览器要么暂时不关心,要么已经有了解决办法。(另请注意,准备好的提琴仅用铬制作,以证明这一点)。



小提琴指令:Chrome版本39.0.2171.95 m(64位)也以32位复制

  • 单击进入
    区域
  • 输入“123”
  • 退格“3”退格“2”退格“1”

  • 相关细节 对此进行了广泛的研究,我遇到了许多相似的问题,但借用相关的解决方案并没有证明是我所追求的银弹。我还发现了Chrome项目的问题,这些问题似乎针对上述问题(可能不是以确切的方式),可以在下面查看

  • 我找到的最接近SO的解决方案是。此解决方案的思想是放置
    &zwnj
    元素后面的code>字符,但是如果我现在想删除我的
    ,我会删除
    &zwnj。。。强制我的光标跳到末尾,通过在“初始删除键笔划”中不删除我的
    ,提供了一种奇怪的UI体验

    问题:
    有没有人经历过这个问题并找到了解决办法?我欢迎任何可能的解决方案,即使是JS hacky。我逐渐了解到,利用
    contenteditable
    带来了一系列困难,但这似乎是我目前剩下的最后一个困难。

    我找到了一种黑客方法,用一些JQuery解决了
    结尾处光标行为不当的初始问题。我基本上是在
    内容的末尾插入一个空的
    ,以便光标“锁定”到
    内容。这个标签对我来说很有用,因为在将它们与普通文本进行退格时,由于覆盖了
    font-style:normal
    (请参见fiddle),最终用户没有UI差异,而且我还需要一些不同于
    的东西来插入

    我对这种解决方法并不特别兴奋,尤其是选择
    ,因为我没有找到更好的选择,我仍然欢迎更好的解决方案——如果有的话!。我计划继续努力,希望也能找到箭头键,但幸运的是,我只是被小提琴中的这个小故障困扰,而不是我的代码


    (仅限铬)

    
    项目
    项目
    项目
    
    函数hackCursor(){
    返回$('#main:last child')。获取(0)。标记名=='SPAN'?
    $(“#主跨度:最后一个孩子”)。在(“”)之后:
    虚假的;
    }
    $(函数(){
    hackCursor();
    $('#main').bind({
    “keyup”:函数(e){
    hackCursor();
    }
    })
    });
    
    因此,我对您的方法有了一个稍微清晰的实现,它依赖于更新
    contenteditable
    字段时触发的事件。IE不支持此事件,但不管怎样,
    contenteditable
    在IE中似乎非常不可靠

    它基本上在标记为
    contenteditable=“false”
    的每个元素周围注入元素。它可能是在初始加载时完成的,而不仅仅是在
    input
    事件上,但我认为您可能有办法向区域注入更多
    span
    ,因此
    input
    应该考虑到这一点

    限制包括箭头键周围的一些奇怪行为,正如您所看到的。我看到的大部分情况是,当您在跨距中向后移动时,光标会保持其正确的位置,但当您向前移动时,光标不会保持其正确的位置

    Javascript

    $('#main').on('input', function() {
        var first = true;
        $(this).contents().each(function(){
            if ($(this).is('[contenteditable=false]')) {
                $("<i class='wrapper'/>").insertAfter(this);
                if (first) {
                    $("<i class='wrapper'/>").insertBefore(this);
                    first = false   
                }
            }
        });
    }).trigger('input');
    

    问题是
    contenteditable
    元素是
    div
    ,默认情况下是
    display:block
    。这就是导致插入符号位置问题的原因。这可以通过使最外层的
    div
    不可编辑并添加一个新的可编辑
    div
    来解决,它将被视为
    内联块

    新的HTML将在外部HTML内部有一个新的
    div
    (在末尾有相应的结束标记):

    为了更好地看到插入符号位于
    span
    元素之间,我还为CSS中的
    div.main span
    规则添加了
    margin:2px
    ,但这不是防止问题中报告的插入符号跳转问题所必需的

    这是一本书


    正如您开始发现的那样,
    contenteditable
    在不同浏览器中处理不一致。几年前,我开始从事一个项目(在浏览器XML编辑器中),我认为
    contenteditable
    会让一切变得更简单。然后在开发应用程序时,我很快发现自己接管了我认为
    contenteditable
    将免费提供给我的功能。今天,
    contenteditable
    给我的唯一好处是它打开了我想要编辑的元素的键盘事件。其他一切,包括插入符号移动和插入符号显示,都是由自定义代码管理的。

    我不知道为什么会发生这种情况,但我觉得这与
    的大小有关,所以
    function hackCursor() {    
        return $('#main :last-child').get(0).tagName === 'SPAN' ? 
            $('#main span:last-child').after('<i style="font-style: normal"></i>') : 
            false;
    }
    
    $(function(){
    
        hackCursor();
    
        $('#main').bind({
            'keyup': function(e) {
                hackCursor();
            }
        })
    });
    
    $('#main').on('input', function() {
        var first = true;
        $(this).contents().each(function(){
            if ($(this).is('[contenteditable=false]')) {
                $("<i class='wrapper'/>").insertAfter(this);
                if (first) {
                    $("<i class='wrapper'/>").insertBefore(this);
                    first = false   
                }
            }
        });
    }).trigger('input');
    
    div.main {
        width: 400px;
        height: 250px;
        border: solid 1px black;
    }
    
    div.main span {
        width:40px;
        background-color: red;
        border-radius: 5px;
        color: white;
        cursor: pointer;
    }
    
    i.wrapper {
        font-style: normal;
    }
    
    <div id="main" class="main"><div id="editable" contenteditable="true">...
    
    div#editable {
        display: inline-block;
    }