JavaScript将鼠标位置转换为选择范围 [英] JavaScript convert mouse position to selection range

查看:140
本文介绍了JavaScript将鼠标位置转换为选择范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想能够将当前鼠标位置转换为一个范围,特别是在CKEditor中。

I would like to be able to convert the current mouse position to a range, in CKEditor in particular.

CKEditor提供了根据范围设置光标的API:

The CKEditor provides an API for setting the cursor according to a range:

var ranges = new CKEDITOR.dom.range( editor.document );
editor.getSelection().selectRanges( [ ranges ] );

由于CKEditor提供此API,因此可以通过删除此要求来简化问题,

Since CKEditor provides this API, the problem may be simplified by removing this requirement and just find a way to produce the range from the mouse coordinates over a div containing various HTML elements.

但是,这并不等于将鼠标坐标转换为文本区域中的光标位置,因为textareas具有固定的列宽和行高,其中CKEditor通过iframe呈现HTML。

However, this is not the same as converting a mouse coordinate into the cursor position in a textarea since textareas have fixed column widths and row heights where the CKEditor renders HTML through an iframe.

基于,看起来这个范围可以应用于元素。

Based on this, it looks like the range may be applied to elements.

如何找出最接近当前鼠标位置的开始/结束范围?

How would you figure out the start/end range which is closest to the current mouse position?

编辑:
一个例子, ckeditor API来选择mouseup事件上的一个范围。

An example of how one might use the ckeditor API to select a range on the mouseup event.

editor.document.on('mouseup', function(e) {
    this.focus();
    var node = e.data.$.target;

    var range = new CKEDITOR.dom.range( this.document );
    range.setStart(new CKEDITOR.dom.node(node), 0);
    range.collapse();

    var ranges = [];
    ranges.push(range);
    this.getSelection().selectRanges( ranges );
});

上述示例的问题是事件目标节点(e.data。$。target)仅针对节点(例如HTML,BODY或IMG)而不是针对文本节点触发。即使是这样,这些节点表示文本块,不支持将光标设置为该文本块中鼠标的位置。

The problem with the above example is that the event target node (e.data.$.target) is only firing for nodes such as HTML, BODY, or IMG but not for text nodes. Even if it did, these nodes represent chunks of text which wouldn't support setting the cursor to the position of the mouse within that chunk of text.

推荐答案

您在尝试做的是在浏览器中很难。我不熟悉ckeditor特别,但常规的javascript允许你选择使用范围的文本,所以我不认为它添加任何特殊的。您必须找到包含该点击的浏览器元素,然后在所点击的元素中找到该字符。

What you're trying to do is really hard in a browser. I'm not familar with ckeditor in particular, but regular javascript allows you to select text using a range so I don't think it's adding anything special. You have to find the browser element that contains the click, then find the character within the element that was clicked.

检测浏览器元素是一件容易的事:您需要在每个元素上注册你的处理程序,或者使用事件的目标字段。有很多信息,在这里,请问一个更具体的问题stackoverflow如果这是你遇到麻烦。

Detecting the browser element is the easy bit: you need to either register your handler on every element, or use the event's target field. There is lots of info on this out there, ask a more specific question on stackoverflow if that's what you're having trouble with.

一旦你有了你需要的元素找出元素中的哪个字符被点击,然后创建一个适当的范围将光标放在那里。作为你链接到声明,浏览器的变化,这使得这真的很难。此网页有点过时,但对范围有很好的讨论: http://www.quirksmode。 org / dom / range_intro.html

Once you have the element you need to find out which character within the element was clicked, then create an appropriate range to put the cursor there. As the post you linked to stated, browser variations make this really hard. This page is a bit dated, but has a good discussion of ranges: http://www.quirksmode.org/dom/range_intro.html

范围无法告诉您在网页上的位置,因此您必须使用其他技术

Ranges can't tell you their positions on the page, so you'll have to use another technique to find out what bit of text was clicked.

我从来没有在javascript中看到这个完整的解决方案。几年前,我在一个,但我没有想出一个答案,我很高兴(一些真正困难的情况下)。我使用的方法是一个可怕的黑客:插入跨度到文本中,然后使用它们执行二分搜索,直到找到包含鼠标单击的最小可能跨度。间距不会更改布局,因此您可以使用span的position_x / y属性来找出它们包含的点击。

I've never seen a complete solution to this in javascript. A few years ago I worked on one but I didn't come up with an answer I was happy with (some really hard edge cases). The approach I used was a horrible hack: insert spans into the text then use them to perform binary search until you find the smallest possible span containing the mouse click. Spans don't change the layout, so you can use the span's position_x/y properties to find out they contain the click.

例如。假设您在节点中有以下文本:

E.g. suppose you have the following text in a node:

<p>Here is some paragraph text.</p>

我们知道点击在这个段落的某个地方。将段落分成两半:

We know the click was somewhere in this paragraph. Split the paragraph in half with a span:

<p><span>Here is some p</span>aragraph text.</p>

如果span包含点击坐标,则继续二分搜索,否则搜索下半部分。

If the span contains the click coordinates, continue binary search in that half, otherwise search the second half.

这适用于单行,但如果文本跨越多行,则必须先找到换行符,否则跨度可能重叠。你还必须制定出当点击不在任何文本,但在元素---例如在段落的最后一行的结尾时,做什么。

This works great for single lines, but if the text spans multiple lines you have to first find line breaks, or the spans can overlap. You also have to work out what to do when the click wasn't on any text but was in the element --- past the end of the last line in a paragraph for example.

因为我在这个浏览器上工作得更快。他们现在可能足够快,现在添加s在每个字符周围,然后围绕每两个字符等,以创建一个二叉树很容易搜索。你可以尝试这种方法 - 这将使得更容易找出你正在处理的行。

Since I worked on this browsers have got a lot faster. They're probably fast enough now to add s around each character, then around each two characters etc to create a binary tree which is easy to search. You could try this approach - it would make it much easier to work out which line you're working on.

TL; DR这是一个真正困难的问题,如果有是一个答案,它可能不值得你的时间来想出来。

TL;DR this is a really hard problem and if there is an answer, it might not be worth your time to come up with it.

这篇关于JavaScript将鼠标位置转换为选择范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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