如何在javascript中单击文本时获取字符位置 [英] How to get character position when click on text in javascript

查看:95
本文介绍了如何在javascript中单击文本时获取字符位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个功能来点击文本时获取光标的位置,它只适用于等宽字符,这很好,但它显然不适用于像中文或日文更宽的字符。

I have this function to get position of the cursor when you click on the text, it only works for monospace characters which is fine, but it obviously don't work with characters that are wider like Chinese or Japanese ones.

    function get_char_pos(point) {
        var prompt_len = self.find('.prompt').text().length;
        var size = get_char_size();
        var width = size.width;
        var height = size.height;
        var offset = self.offset();
        var col = Math.floor((point.x - offset.left) / width);
        var row = Math.floor((point.y - offset.top) / height);
        var lines = get_splited_command_line(command);
        var try_pos;
        if (row > 0 && lines.length > 1) {
            try_pos = col + lines.slice(0, row).reduce(function(sum, line) {
                return sum + line.length;
            }, 0);
        } else {
            try_pos = col - prompt_len;
        }
        // tabs are 4 spaces and newline don't show up in results
        var text = command.replace(/\t/g, '\x00\x00\x00\x00').replace(/\n/, '');
        var before = text.slice(0, try_pos);
        var len = before.replace(/\x00{4}/g, '\t').replace(/\x00+/, '').length;
        return len > command.length ? command.length : len;
    }

我尝试使用wcwidth库创建一个函数(返回2表示更宽的字符和普通字母的1)但它不能正常工作,这是带演示的代码:

I've tried to create a function using wcwidth library (that return 2 for wider characters and 1 for normal letters) but it don't work quite right, here is the code with demo:

var self = $('pre');
var offset = self.offset();
var command = 'チトシタテイトチトシイスチトシタテイトチトシイスチトシタテイトチトシイス\nfoo bar baz\nfoo bar baz\nチトシタテイトチトシイ';
self.html(command);
function get_char_size() {
    var span = $('<span>&nbsp;</span>').appendTo(self);
    var rect = span[0].getBoundingClientRect();
    span.remove();
    return rect;
}
var length = wcwidth;
// mock
function get_splited_command_line(string) {
    return string.split('\n');
}
function get_char_pos(point) {
    var size = get_char_size();
    var width = size.width;
    var height = size.height;
    var offset = self.offset();
    var col_count = Math.floor((point.x - offset.left) / width);
    var row = Math.floor((point.y - offset.top) / height);
    var lines = get_splited_command_line(command);
    var line = lines[row];
    var col = 0;
    var i = col_count;
    while (i > 0) {
        i -= length(line[col]);
        col++;
    }
    var try_pos;
    if (row > 0 && lines.length > 1) {
        try_pos = col + lines.slice(0, row).reduce(function(sum, line) {
            return sum + length(line);
        }, 0);
    } else {
        try_pos = col;
    }
    // tabs are 4 spaces and newline don't show up in results
    var text = command.replace(/\t/g, '\x00\x00\x00\x00').replace(/\n/, '');
    var before = text.slice(0, try_pos);
    var len = before.replace(/\x00{4}/g, '\t').replace(/\x00+/, '').length;
    var command_len = command.length;
    return len > command_len ? command_len : len;
}
self.click(function(e) {
  var pos = get_char_pos({
      x: e.pageX,
      y: e.pageY
  });
  self.html(command.substring(0, pos-1) + '<span>' +
            command[pos] + '</span>' +
            command.substring(pos+1));
});

span {
  color: red;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/jcubic/leash/master/lib/wcwidth.js"></script>
<pre></pre>

我不能为每个字母使用跨度,因为我将文本拆分为3跨度,光标和光标之后。我也有可能或不在容器中的样式的跨度。

I can't use spans for each letter because I have the text split into 3 spans before, cursor and after the cursor. and I also have spans for styling that may be or not in the container.

任何帮助如何修复此功能是值得赞赏的。

Any help how to fix this function is appreciated.

解决方案

以下是基于@Will的代码,我在我的代码中使用了多个代码元素(由于某些原因,当你点击只有一个字符的元素时,chrome会出现问题,以防焦点不超过文本的长度):

Here is my code based on @Will that I've used in my code that work with multiple elements (for some reason chrome have issues when you click on element that have only one character, and just in case the focus is not more then the length of the text):

    function get_focus_offset() {
        var sel;
        if ((sel = window.getSelection()) && (sel.focusNode !== null)) {
            return sel.focusOffset;
        }
    }
    function get_char_pos(e) {
        var focus = get_focus_offset();
        if ($.isNumeric(focus)) {
            var node = $(e.target);
            // [role="presentation"] is my direct children that have
            // siblings that are other nodes with text
            var parent = node.closest('[role="presentation"]');
            var len = node.text().length;
            focus = len === 1 ? 0 : Math.min(focus, len);
            return focus + parent.prevUntil('.prompt').text_length() +
                node.prevAll().text_length();
        } else {
            return command.length;
        }
    }

更新:有如果你点击前半部分正确选择的字符点击问题,但是当你点击另一半时它选择下一个字符,所以我最终每个元素的方法有一个字符。

UPDATE: there is issue with clicking if you click on the first half the character it get selected correctly but when you click other half it select next character so I ended up with one character per element approach.

推荐答案

window.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('.charPosition').forEach(el => {
        let characters = el['innerText'].split('');
        el.innerHTML = '';
        characters.forEach(char => {
            let span = document.createElement('span');
            span.innerText = char;
            span.addEventListener('click', function () {
                let position = 0;
                let el = this;
                while (el.previousSibling !== null) {
                    position++;
                    el = el.previousSibling;
                }
                console.log(this.innerHTML + ':' + position);
            });
            el.appendChild(span);
        });
    });
});

<div class="charPosition">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>

这篇关于如何在javascript中单击文本时获取字符位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆