将事件位置映射到非文本字段中的文本位置

时间:2010-05-24 16:47:36

标签: javascript jquery

有没有办法在此元素上映射事件,例如点击事件

<div>Just normal text</div>

到包含文本中的位置(“你只是点击了第6个字符”,当点击'n'时)?

3 个答案:

答案 0 :(得分:1)

我不知道实现这一目标的任何方式,但我得到了一个可行的解决方案,虽然它很难看。

您可以将div文字的每个字母包含在一个简单的span元素中,并为每个字母添加唯一标识符。然后你会为那些span元素挂钩事件处理程序,而不是整个div,并根据你可以分辨出哪个字符的span id。

这一切都可以在JS中完成,但正如我所说,这不是理想的解决方案。

以下是示例(我已经在div中添加了test ID,因此我可以更轻松地找到它。

var letters = $('#test').text();
var spans = '';
for (var i = 0; i < letters.length; i++) {
    spans += '<span id="id' + i + '">' + letters[i] + '<span>';
}
$('#test').html(spans);

$('span[id^=id]').click(function() {
    alert('Clicked char: ' + (Number($(this).attr('id').substring(2)) + 1));
    return false;
});

您也可以试试我的demo

答案 1 :(得分:1)

不是这样;我想你必须在服务器端或使用JQuery将每个字符分成<span>元素。

答案 2 :(得分:0)

这是一种可能会起作用的hacky方式:它涉及暂时使文档可编辑并检查选择。它应该适用于Firefox 3 +,IE 6 +,最近的Safari和Chrome。

目前看来,我可以看到一些问题:

  • IE中的结果与其他浏览器不同:IE将整个包含元素的所有字符计算到插入符号,而其他浏览器在包含文本节点中提供偏移量,但你可以解决这个问题;
  • 在某些浏览器中,当前元素旁边会出现边框
  • 在Opera或Firefox 2中不起作用,并且文档可编辑
  • 其他UI故障的可能性:这是一个讨厌的黑客。

代码:

window.onload = function() {
    var mouseDownEl;

    document.onmousedown = function(evt) {
        evt = evt || window.event;
        var el = evt.target || evt.srcElement;
        if (evt.srcElement || !("contentEditable" in el)) {
            document.designMode = "on";
        } else {
            el.contentEditable = "true";
        }

        mouseDownEl = el;
    };

    document.onclick = function(evt) {
        evt = evt || window.event;
        var el = evt.target || evt.srcElement;
        if (el == mouseDownEl) {
            window.setTimeout(function() {
                var caretPos, range;
                if (typeof window.getSelection != "undefined") {
                    caretPos = window.getSelection().focusOffset;
                } else if (document.selection && document.selection.createRange) {
                    range = document.body.createTextRange();
                    range.moveToElementText(el);
                    range.collapse();
                    range.setEndPoint("EndToEnd", document.selection.createRange());
                    caretPos = range.text.length;
                }

                if (el.contentEditable == "true") {
                    el.contentEditable = "false";
                } else {
                    document.designMode = "off";
                }
                alert(caretPos);
            }, 1);
        } else {
            if (mouseDownEl.contentEditable == "true") {
                mouseDownEl.contentEditable = "false";
            } else {
                document.designMode = "off";
            }
        }
        mouseDownEl = null;
    };
};