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

时间:2010-05-16 17:10:01

标签: javascript contenteditable

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

  1. 我有2个div( div1 div2
  2. div1 =不可编辑的div
  3. div2 = contenteditable div
  4. 两个div包含完全相同的内容
  5. 当用户点击 div1 时,它会被隐藏, div2 会出现在确切位置,用户可以修改
  6. 问题:我希望插入符号在div2上的确切位置显示为div1

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

    有什么办法吗?

    谢谢 -

6 个答案:

答案 0 :(得分:7)

简短回答:你不能

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

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

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

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

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

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

你可以,基本上你需要在你的第一个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);
});

现在只需要get / set caret方法:)

编辑&gt;这是我自己的,(live demo

        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);
        }

答案 3 :(得分:0)

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

答案 4 :(得分:0)

当你点击一个元素时,会创建一个长度为零的Selection对象(从element.getSelection()获取它,其中element是所讨论的div)。该对象的focusOffset会让你知道你点击了那个div中的第74个字符(这是Adrien所说的在不同的答案中是不可能的)。

答案 5 :(得分:0)

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