Skip to content

Commit

Permalink
fix: 修复移动端编辑模式双击光标位置不正确的问题 (#11516)
Browse files Browse the repository at this point in the history
  • Loading branch information
2betop authored Jan 21, 2025
1 parent 3539ef8 commit 4cf711d
Showing 1 changed file with 35 additions and 18 deletions.
53 changes: 35 additions & 18 deletions packages/amis-editor-core/src/inlineEdit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ function startPlainTextEdit({
elem.focus();

let caretRange = event
? getMouseEventCaretRange(event)
? getMouseEventCaretRange(event, elem)
: createRangeAtTheEnd(elem);

// Set a timer to allow the selection to happen and the dust settle first
setTimeout(function () {
selectRange(caretRange);
selectRange(caretRange, elem);
}, 10);
}

Expand Down Expand Up @@ -188,12 +188,12 @@ async function startRichTextEdit({
origin = editor.html.get();

let caretRange = event
? getMouseEventCaretRange(event)
? getMouseEventCaretRange(event, elem)
: createRangeAtTheEnd(elem);

// Set a timer to allow the selection to happen and the dust settle first
setTimeout(function () {
selectRange(caretRange);
selectRange(caretRange, elem);
}, 10);
}
);
Expand All @@ -206,7 +206,7 @@ async function startRichTextEdit({
* @returns {Range} 创建的Range对象
*/
function createRangeAtTheEnd(elem: HTMLElement) {
const range = document.createRange();
const range = elem.ownerDocument.createRange();
range.selectNodeContents(elem);
range.collapse(false);
return range;
Expand All @@ -219,35 +219,49 @@ function createRangeAtTheEnd(elem: HTMLElement) {
* @param {MouseEvent} evt - 鼠标事件对象
* @returns {Range} 光标位置的Range对象
*/
function getMouseEventCaretRange(evt: MouseEvent) {
function getMouseEventCaretRange(evt: MouseEvent, elem: HTMLElement) {
let range,
x = evt.clientX,
y = evt.clientY;

const target = evt.target as HTMLElement;
const doc = elem.ownerDocument;

if (target.ownerDocument !== doc) {
// 如果点击事件来自iframe外部,需要调整坐标
const iframe = doc.defaultView?.frameElement as HTMLIFrameElement;

if (iframe) {
const rect = iframe.getBoundingClientRect();
x -= rect.left;
y -= rect.top;
}
}

// Try the simple IE way first
if ((document.body as any).createTextRange) {
range = (document.body as any).createTextRange();
if ((doc.body as any).createTextRange) {
range = (doc.body as any).createTextRange();
range.moveToPoint(x, y);
} else if (typeof document.createRange != 'undefined') {
} else if (typeof doc.createRange != 'undefined') {
// Try Mozilla's rangeOffset and rangeParent properties,
// which are exactly what we want
if (typeof (evt as any).rangeParent != 'undefined') {
range = document.createRange();
range = doc.createRange();
range.setStart((evt as any).rangeParent, (evt as any).rangeOffset);
range.collapse(true);
}

// Try the standards-based way next
else if ((document as any).caretPositionFromPoint) {
let pos: any = (document as any).caretPositionFromPoint(x, y);
range = document.createRange();
else if ((doc as any).caretPositionFromPoint) {
let pos: any = (doc as any).caretPositionFromPoint(x, y);
range = doc.createRange();
range.setStart(pos.offsetNode, pos.offset);
range.collapse(true);
}

// Next, the WebKit way
else if (document.caretRangeFromPoint) {
range = document.caretRangeFromPoint(x, y);
else if (doc.caretRangeFromPoint) {
range = doc.caretRangeFromPoint(x, y);
}
}

Expand All @@ -259,12 +273,15 @@ function getMouseEventCaretRange(evt: MouseEvent) {
* 支持IE和标准浏览器两种方式
* @param {Range} range - 要选中的Range对象
*/
function selectRange(range: any) {
function selectRange(range: any, elem: HTMLElement) {
const doc = elem.ownerDocument;
const win = doc.defaultView || (doc as any).parentWindow;

if (range) {
if (typeof range.select != 'undefined') {
range.select();
} else if (typeof window.getSelection != 'undefined') {
let sel: any = window.getSelection();
} else if (typeof win.getSelection != 'undefined') {
let sel: any = win.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
Expand Down

0 comments on commit 4cf711d

Please sign in to comment.