繁体   English   中英

JavaScript'contenteditable' - 获取/设置插入位置

[英]JavaScript 'contenteditable' — Getting/Setting Caret Position

我已经阅读了几篇关于插入符号的帖子,但似乎都没有回答我的特定问题。

  1. 我有2个div( div1div2
  2. div1 =不可编辑的div
  3. div2 = contenteditable div
  4. 两个div包含完全相同的内容
  5. 当用户点击div1时 ,它会被隐藏, div2出现在确切的位置,用户可以编辑

问题 :我希望插入符号作为div1出现在div2上的确切位置

所以,我需要一些方法来读取用户点击div1的位置,然后当div2出现时将光标/插入符号放在同一位置,这样就是一组getCaretLocation(in_div_id)setCaretLocation(in_div_id)函数。

有办法吗?

谢谢 -

简答 :你做不到

答案很长 :你将面临的问题是你将能够获得div1上click事件的(x,y)坐标,但是任何实现的插入位置都要求你知道插入符号在内容中的位置(这是插入符号前面的字符数)。

要将(x,y)坐标转换为字符位置,您实际上需要知道之前有多少个字符(即,如果文本是ltr,则保留在当前行和上面的字符处)。

如果使用固定宽度字体,则可以简化问题:将(x,y)坐标映射到字符网格上的(线,列)坐标。

但是,您仍然面临不知道文本如何被包装的问题。 例如 :

------------------
|Lorem ipsum     |
|dolor sit amet  |
|consectetur     |
|adipiscing elit |
------------------

如果用户点击了dol中d ,你知道该字符是第二行的第一个,但是在不知道包装算法的情况下,你无法知道它是“Lorem ipsum dolor sit中的第13个字符...... ”。 并且无法保证这种包装算法在浏览器和平台之间是相同的。

现在,我想知道为什么你会首先使用2个不同的同步div 当用户点击(或悬停)时,仅使用一个div并将其内容设置为可编辑是不是更容易?

你可以,基本上你需要在你的第一个div上设置可编辑的临时内容以捕获插入符号位置

$('div1').hover(function()
{ $(this).attr('contenteditable','true');
},function()
{ $(this).removeAttr('contenteditable');
}).mouseup(function()
{   var t = $(this);
    // get caret position and remove content editable
    var caret = t.getCaret();
    t.removeAttr('contenteditable');
    // do your div switch stuff
    ...
    // and apply saved caret position
    $('div2').setCaret(caret);
});

现在只需要获取/设置插入符号方法:)

编辑>这是我自己的,( 现场演示

        getSelection:function($e)
        {   if(undefined === window.getSelection) return false;
            var range = window.getSelection().getRangeAt(0);

            function getTreeOffset($root,$node)
            {   if($node.parents($root).length === 0) return false; // is node child of root ?
                var tree = [], treesize = 0;
                while(1)
                {   if($node.is($root)) break;
                    var index, $parent = $node.parent();
                    index = $parent.contents().index($node);
                    if(index !== -1) { tree[treesize++] = index; } $node = $parent;
                };  return tree.reverse();
            }

            var start = getTreeOffset($e,$(range.startContainer));
            var end   = getTreeOffset($e,$(range.endContainer));

            if(start & end === false) return false;

            return {start:start,end:end,startOffset:range.startOffset,endOffset:range.endOffset};
        }, setSelection:function($e,s,win)
        {   $e.focus(); if(s === false) return; var sel = win.getSelection(); sel.removeAllRanges();

            function getNode($e,s)
            {   var node = $e;
                for( var n=0;n<s.length;n++ )
                {   var index = s[n]; if(index < 0) break;
                    node = node.contents(':eq('+index+')');
                }   return node.get(0);
            }

            var start = getNode($e,s.start), end = getNode($e,s.end), range = win.document.createRange();
            range.setStart(start,s.startOffset); range.setEnd(end,s.endOffset); sel.addRange(range);
        }

您可以在插入符号处插入一个小的span-element,获取其位置并将其删除。 对于跨浏览器范围和选择库,请参阅rangy

单击元素时,将创建一个长度为零的Selection对象(从element.getSelection()获取,其中element是有问题的div)。 该对象的focusOffset将告诉您单击该div中的第74个字符(这是Adrien所说的在不同答案中不可能的事情)。

读取文本中的插入位置,然后在编辑窗口中设置插入位置。

听起来你正在尝试进行内联编辑...你看过jeditable插件了吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM