2008-09-24 23 views
7

Tôi gặp sự cố không bình thường với tài liệu IE có contentEditable được đặt thành true. Gọi select() trên một phạm vi được đặt ở cuối của một nút văn bản ngay trước một phần tử khối làm cho việc lựa chọn được dịch chuyển sang đúng một ký tự và xuất hiện ở nơi nó không nên. Tôi đã gửi một lỗi cho Microsoft chống lại IE8. Nếu bạn có thể, hãy bỏ phiếu cho vấn đề này để nó có thể được sửa.Phương thức chọn lựa TextRange của IE không hoạt động đúng cách

https://connect.microsoft.com/IE/feedback/ViewFeedback.aspx?FeedbackID=390995

Tôi đã viết một trường hợp thử nghiệm để chứng minh hiệu lực:

<html> 
    <body> 
    <iframe id="editable"> 
     <html> 
     <body> 
      <div id="test"> 
      Click to the right of this line -&gt; 
      <p id="par">Block Element</p> 
      </div> 
     </body> 
     </html> 
    </iframe> 
    <input id="mytrigger" type="button" value="Then Click here to Save and Restore" /> 
    <script type="text/javascript"> 
     window.onload = function() { 
      var iframe = document.getElementById('editable'); 
      var doc = iframe.contentDocument || iframe.contentWindow.document; 

      // An IFRAME without a source points to a blank document. Here we'll 
      // copy the content we stored in between the IFRAME tags into that 
      // document. It's a hack to allow us to use only one HTML file for this 
      // test. 
      doc.body.innerHTML = iframe.textContent || iframe.innerHTML; 

      // Marke the IFRAME as an editable document 
      if (doc.body.contentEditable) { 
       doc.body.contentEditable = true; 
      } else { 
       var mydoc = doc; 
       doc.designMode = 'On'; 
      } 

      // A function to demonstrate the bug. 
      var myhandler = function() { 
       // Step 1 Get the current selection 
       var selection = doc.selection || iframe.contentWindow.getSelection(); 
       var range = selection.createRange ? selection.createRange() : selection.getRangeAt(0); 

       // Step 2 Restore the selection 
       if (range.select) { 
        range.select(); 
       } else { 
        selection.removeAllRanges(); 
        selection.addRange(range); 
        doc.body.focus(); 
       } 
      } 

      // Set up the button to perform the test code. 
      var button = document.getElementById('mytrigger'); 
      if (button.addEventListener) { 
       button.addEventListener('click', myhandler, false); 
      } else { 
       button.attachEvent('onclick', myhandler); 
      } 
      } 
    </script> 
    </body> 
</html> 

Vấn đề là tiếp xúc trong các chức năng myhandler. Đây là tất cả những gì tôi đang làm, không có Bước 3 ở giữa lưu và khôi phục lựa chọn, và con trỏ di chuyển. Nó dường như không xảy ra trừ khi vùng chọn trống (ví dụ: tôi có một con trỏ nhấp nháy, nhưng không có văn bản), và nó dường như chỉ xảy ra bất cứ khi nào con trỏ ở cuối nút văn bản ngay trước nút khối.

Dường như phạm vi vẫn ở đúng vị trí (nếu tôi gọi parentElement trên phạm vi trả về div), nhưng nếu tôi nhận được dải ô mới từ vùng chọn hiện tại, phạm vi mới nằm trong thẻ đoạn, và đó là parentElement của nó.

Làm cách nào để giải quyết vấn đề này và liên tục lưu và khôi phục lựa chọn trong trình khám phá internet?

+0

Đã dành chút thời gian cho vấn đề này, tôi đã thuyết phục một cách hợp lý rằng không có cách nào để đặt dấu mũ ở cuối nút văn bản ngay trước phần tử khối. –

Trả lời

12

Tôi đã tìm ra một vài phương pháp để xử lý các phạm vi IE như thế này. Nếu tất cả những gì bạn muốn làm là lưu con trỏ ở đâu, và sau đó khôi phục nó, bạn có thể sử dụng phương pháp dánHTML để chèn một khoảng trống ở vị trí hiện tại của con trỏ, và sau đó sử dụng phương thức moveToElementText để đặt nó vào vị trí hiện tại của con trỏ. trở lại ở vị trí đó một lần nữa:

// Save position of cursor 
range.pasteHTML('<span id="caret"></span>') 

... 

// Create new cursor and put it in the old position 
var caretSpan = iframe.contentWindow.document.getElementById("caret"); 
var selection = iframe.contentWindow.document.selection; 
newRange = selection.createRange(); 
newRange.moveToElementText(caretSpan); 

Ngoài ra, bạn có thể đếm có bao nhiêu nhân vật đứng trước vị trí con trỏ hiện tại và lưu số đó:

var selection = iframe.contentWindow.document.selection; 
var range = selection.createRange().duplicate(); 
range.moveStart('sentence', -1000000); 
var cursorPosition = range.text.length; 

để khôi phục lại con trỏ, bạn đặt nó vào đầu và sau đó di chuyển nó số chara cters:

var newRange = selection.createRange(); 
newRange.move('sentence', -1000000); 
newRange.move('character', cursorPosition); 

Hy vọng điều này sẽ hữu ích.

0

Gần đây, tôi đã làm việc tại một trang web sử dụng Microsoft CMS với gói "MSIB +" của các điều khiển bao gồm trình soạn thảo WYSIWYG chạy trong Internet Explorer.

Tôi có vẻ nhớ một số nhận xét trong Javascript của trình chỉnh sửa phía máy khách được liên kết cụ thể với lỗi này trong IE và phương thức Range.Select().

Thật không may, tôi không làm việc ở đó nữa vì vậy tôi không thể truy cập các tệp Javascript, nhưng có lẽ bạn có thể tải chúng từ nơi khác?

Chúc may mắn

+0

Bạn có biết liệu trình soạn thảo WYSIWYG có tên không? Có thể làm cho việc tìm kiếm dễ dàng hơn ... –

+0

Tôi đã quản lý để có được một bản sao của gói MSIB +, nhưng tôi dường như không thể tìm thấy trình soạn thảo WYSIWYG bên trong. Tôi không chắc chắn nếu bản sao tôi có là lỗi thời, hoặc các biên tập viên thực sự là một phần của biên tập viên CMS ... –

1

Tôi đã có một chút của một đào & tiếc là không thể nhìn thấy một workaround ... Mặc dù có một điều tôi nhận thấy trong khi gỡ lỗi javascript, nó có vẻ như vấn đề là thực sự với phạm vi đối tượng chính nó thay vì với range.select() tiếp theo. Nếu bạn nhìn vào các giá trị trên đối tượng phạm vi selection.createRange() trả về, có đối tượng dom mẹ có thể chính xác, nhưng thông tin định vị đã đề cập đến đầu dòng tiếp theo (tức là offsetLeft/Top, boundingLeft/Top, v.v. sai rồi).

Dựa trên thông tin here, herehere, tôi nghĩ bạn không may mắn với IE vì bạn chỉ có quyền truy cập vào đối tượng TextRange của Microsoft, dường như đã bị hỏng. Từ thử nghiệm của tôi, bạn có thể di chuyển phạm vi xung quanh và định vị chính xác vị trí của nó, nhưng khi bạn làm như vậy, đối tượng dải ô sẽ tự động chuyển sang dòng tiếp theo ngay cả trước khi bạn cố gắng .select() nó. Ví dụ, bạn có thể thấy vấn đề bằng cách đặt mã này ở giữa của bạn Bước 1 & Bước 2:

if (range.boundingWidth == 0) 
{ 
    //looks like its already at the start of the next line down... 
    alert('default position: ' + range.offsetLeft + ', ' + range.offsetTop); 
    //lets move the start of the range one character back 
    //(i.e. select the last char on the line) 
    range.moveStart("character", -1); 
    //now the range looks good (except that its width will be one char); 
    alert('one char back: ' + range.offsetLeft + ', ' + range.offsetTop); 
    //calculate the true end of the line... 
    var left = range.offsetLeft + range.boundingWidth; 
    var top = range.offsetTop; 
    //now we can collapse back down to 0 width range 
    range.collapse(); 
    //the position looks right 
    alert('moving to: ' + left + ', ' + top); 
    //move there. 
    range.moveToPoint(left, top); 
    //oops... on the next line again... stupid IE. 
    alert('moved to: ' + range.offsetLeft + ', ' + range.offsetTop); 
} 

Vì vậy, tiếc là nó không giống như có cách nào để đảm bảo rằng phạm vi là ở chỗ phải khi bạn chọn lại.

Rõ ràng có những sửa chữa nhỏ để mã của bạn ở trên, bằng cách thay đổi Bước 2 nó thế này:

// Step 2 Restore the selection 
if (range.select) { 
    if (range.boundingWidth > 0) { 
     range.select(); 
    } 
} else { 
    selection.removeAllRanges(); 
    selection.addRange(range); 
    doc.body.focus(); 
} 

Nhưng có lẽ, bạn thực sự muốn làm điều gì đó giữa Bước 1 & Bước 2 trong thực tế của bạn trong đó bao gồm di chuyển lựa chọn, do đó cần phải thiết lập lại nó. Nhưng chỉ trong trường hợp. :)

Vì vậy, tốt nhất tôi có thể làm là đi & bỏ phiếu cho lỗi bạn đã tạo ... Hy vọng rằng họ sẽ sửa lỗi đó.

+0

Cảm ơn bạn đã xem. Tôi biết đó là một lỗi trong IE, tôi chỉ đang tìm một giải pháp an toàn vì tôi cần phải di chuyển vùng chọn xung quanh trước khi khôi phục nó. –

0

Có lẽ tôi hiểu sai, nhưng nếu tôi nhấp vào bên phải của dòng đầu tiên đó, con trỏ của tôi đã ngay lập tức xuất hiện ở đầu dòng thứ hai, vì vậy đó không phải là vấn đề TextRange, phải không?

Thêm loại tài liệu để trang thử nghiệm được hiển thị ở chế độ tiêu chuẩn thay vì sửa lỗi chế độ quirks cho tôi.

Và tôi không thể tái tạo chức năng myhandler của bạn, vì việc nhấn nút đó sẽ di chuyển tiêu điểm đến nút để tôi không thể nhìn thấy con trỏ nữa và không thể lấy lại. Tìm vị trí con trỏ trong một nội dung Chỉnh sửa khu vực seems to be a different problem altogether.

Các vấn đề liên quan