phù hợp với nội dung, đặt dấu mũ ở cuối văn bản (trình duyệt chéo)


111

đầu ra trong Chrome :

<div id="content" contenteditable="true" style="border:1px solid #000;width:500px;height:40px;">
    hey
    <div>what's up?</div>
<div>
<button id="insert_caret"></button>

Tôi tin rằng trong FF nó sẽ giống như thế này:

hey
<br />
what's up?

và trong IE :

hey
<p>what's up?</p>

Thật không may, không có cách nào <br />hay ho để mọi trình duyệt chèn thẻ thay vì thẻ div hoặc p, hoặc ít nhất là tôi không thể tìm thấy bất cứ thứ gì trực tuyến.


MỌI LÚC NÀO, điều tôi đang cố gắng làm bây giờ là, khi tôi nhấn nút , tôi muốn dấu mũ được đặt ở cuối văn bản, vì vậy nó sẽ trông giống như sau:

hey
what's up?|

bất kỳ cách nào để làm điều này để nó hoạt động trong tất cả các trình duyệt ?

thí dụ:

$(document).ready(function()
{
    $('#insert_caret').click(function()
    {
        var ele = $('#content');
        var length = ele.html().length;

        ele.focus();

        //set caret -> end pos
     }
 }

Câu trả lời:


282

Chức năng sau sẽ thực hiện điều đó trong tất cả các trình duyệt chính:

function placeCaretAtEnd(el) {
    el.focus();
    if (typeof window.getSelection != "undefined"
            && typeof document.createRange != "undefined") {
        var range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (typeof document.body.createTextRange != "undefined") {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
    }
}

placeCaretAtEnd( document.querySelector('p') );
p{ padding:.5em; border:1px solid black; }
<p contentEditable>foo bar </p>

Việc đặt dấu mũ ở đầu gần như giống hệt nhau: nó chỉ yêu cầu thay đổi Boolean được truyền vào các lệnh gọi tới collapse(). Đây là một ví dụ tạo các hàm để đặt dấu mũ ở đầu và ở cuối:

function createCaretPlacer(atStart) {
    return function(el) {
        el.focus();
        if (typeof window.getSelection != "undefined"
                && typeof document.createRange != "undefined") {
            var range = document.createRange();
            range.selectNodeContents(el);
            range.collapse(atStart);
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (typeof document.body.createTextRange != "undefined") {
            var textRange = document.body.createTextRange();
            textRange.moveToElementText(el);
            textRange.collapse(atStart);
            textRange.select();
        }
    };
}

var placeCaretAtStart = createCaretPlacer(true);
var placeCaretAtEnd = createCaretPlacer(false);

Không hoạt động với Chrome vì createTextRange không phải là một hàm tiêu chuẩn. Xem stackoverflow.com/a/41743191/700206 .
whitneyland

@Lee: Nó hoạt động tốt trong Chrome, hỗ trợ window.getSelectiondocument.createRange. Các createTextRangechi nhánh là cho các phiên bản cũ của trình duyệt Internet Explorer.
Tim Down

tại thời điểm viết bài window.getSelectionnày không được hỗ trợ bởi 0,29% tất cả các trình duyệt (IE> 8). xem: caniuse.com/#search=window.getSelection
w.stoettinger

@TimDown này hoạt động. +1. Nhưng bạn cũng có thể giải thích mã bằng cách thêm ý kiến ​​được không? Sẽ rất tuyệt
shinobi

Có ai biết cách đặt dấu mũ ở cuối (sử dụng mã này) khi cố gắng nhắm mục tiêu phần tử iframe> body không? Phần tử body có editablecontent="true"...? placeCaretAtEnd(this);sẽ không hiệu quả với tôi.
RobbTe,

6

Thật không may, câu trả lời xuất sắc của Tim chỉ phù hợp với tôi khi đặt ở cuối, để đặt ở đầu, tôi phải sửa đổi nó một chút.

function setCaret(target, isStart) {
  const range = document.createRange();
  const sel = window.getSelection();
  if (isStart){
    const newText = document.createTextNode('');
    target.appendChild(newText);
    range.setStart(target.childNodes[0], 0);
  }
  else {
    range.selectNodeContents(target);
  }
  range.collapse(isStart);
  sel.removeAllRanges();
  sel.addRange(range);
  target.focus();
  target.select();
}

Không chắc chắn nếu focus()select()thực sự cần thiết.


Bạn cũng đã giới thiệu một thư viện bên ngoài. Nếu bạn không nghĩ rằng tập trung và chọn lọc là cần thiết, tại sao không nhận xét các dòng và kiểm tra nó?
dotnethaggis 19/07/17

Cảm ơn, đã xóa jquery. Tôi nhớ tôi đã có một số kết quả trái ngược nhau, tôi sẽ cố gắng cô lập chúng một lần nữa.
lờ mờ

1

Ví dụ (trực tiếp) này cho thấy một hàm đơn giản ngắn setCaretAtStartEnd, có hai đối số; Một nút (có thể chỉnh sửa) để đặt dấu mũ tại & một Boolean cho biết vị trí đặt nó (bắt đầu hoặc kết thúc của nút)

const editableElm = document.querySelector('[contenteditable]');

document.querySelectorAll('button').forEach((elm, idx) => 
  elm.addEventListener('click', () => {
    editableElm.focus()
    setCaretAtStartEnd(editableElm, idx) 
  })
)

function setCaretAtStartEnd( node, atEnd ){
  const sel = document.getSelection();
  node = node.firstChild;

  if( sel.rangeCount ){
      ['Start', 'End'].forEach(pos =>
        sel.getRangeAt(0)["set" + pos](node, atEnd ? node.length : 0)
      )
  }
}
[contenteditable]{ padding:5px; border:1px solid; }
<h1 contenteditable>Place the caret anywhere</h1>
<br>
<button>Move caret to start</button>
<button>Move caret to end</button>


-1

Nếu bạn đang sử dụng trình biên dịch google đóng, bạn có thể làm như sau (phần nào được đơn giản hóa từ câu trả lời của Tim):

function placeCaretAtEnd(el) {
    el.focus();
    range = goog.dom.Range.createFromNodeContents(el);
    range.collapse(false);
    range.select();
}

Đây là điều tương tự trong ClojureScript:

(defn place-caret-at-end [el] 
   (.focus el)
   (doto (.createFromNodeContents goog.dom.Range el)
         (.collapse false)
         .select))

Tôi đã thử nghiệm điều này trong Chrome, Safari và FireFox, không chắc về IE ...


1
range = goog.dom.Range.createFromNodeContents (el); goog.dom là gì?
Anh Tú

Điều này đã làm việc cho tôi. @ AnhTú: goog.dom là không gian tên được cung cấp bởi thư viện đóng.
David Beneš
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.