15

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

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

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

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

有什么办法吗?

谢谢 -

4

6 回答 6

8

简短的回答:你不能

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

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

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

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

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

如果用户点击dolor中的d,您会知道该字符是第 2 行的第 1 个字符,但如果不知道包装算法,您将无法知道它是“Lorem ipsum dolor sit... 中的第 13 个字符... ”。并且不能保证这样的包装算法在浏览器和平台之间是相同的。

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

于 2010-05-16T18:25:14.423 回答
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);
});

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

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

        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);
        }
于 2012-12-17T13:20:18.323 回答
1

您可以在插入符号处插入一个小跨度元素,获取它的位置,然后将其删除。有关跨浏览器范围和选择库,请参阅rangy

于 2011-02-01T09:11:52.103 回答
0

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

于 2010-05-17T00:49:43.830 回答
0

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

于 2013-12-19T11:24:45.537 回答
0

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

于 2012-06-15T13:43:28.223 回答