2008-12-30 27 views
13

Tôi đang làm việc trên trình chỉnh sửa trong trình duyệt trong một số textarea. Tôi đã bắt đầu tìm kiếm một số thông tin về giao dịch với lựa chọn textarea và tìm thấy this jQuery plugin, fieldSelection thực hiện một số thao tác đơn giản.Hiểu điều gì xảy ra với lựa chọn văn bản bằng JavaScript

Tuy nhiên, nó không giải thích những gì đang xảy ra.

Tôi muốn hiểu thêm về lựa chọn vùng văn bản trong JavaScript, tốt nhất là với mô tả cả hai kịch bản trước DOM3 và sau DOM30.

Trả lời

10

Bắt đầu với PPK introduction to ranges. Kết nối nhà phát triển Mozilla có thông tin trên W3C selections. Microsoft có hệ thống của họ documented on MSDN. Một số thủ thuật khác có thể được tìm thấy in the answers here.

Ngoài các giao diện không tương thích, bạn sẽ rất vui khi biết rằng có thêm bất kỳ sự cố nào xảy ra với các nút textarea. Nếu tôi nhớ chính xác chúng hoạt động như bất kỳ nút nào khác khi bạn chọn chúng trong IE, nhưng trong các trình duyệt khác chúng có phạm vi lựa chọn độc lập được hiển thị thông qua các thuộc tính .selectionEnd.selectionStart trên nút.

Ngoài ra, bạn thực sự nên xem .contentEdiable làm phương tiện để chỉnh sửa nội dung trực tiếp. Từ bản phát hành Firefox3, điều này hiện được hỗ trợ bởi tất cả các trình duyệt.

+0

Cảm ơn Borgar! Tôi chưa bao giờ nghe nói về contentEditable trước đây. Tôi sẽ làm quen với bài đăng vội vàng đó! – brad

29
function get_selection(the_id) 
{ 
    var e = document.getElementById(the_id); 

    //Mozilla and DOM 3.0 
    if('selectionStart' in e) 
    { 
     var l = e.selectionEnd - e.selectionStart; 
     return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) }; 
    } 
    //IE 
    else if(document.selection) 
    { 
     e.focus(); 
     var r = document.selection.createRange(); 
     var tr = e.createTextRange(); 
     var tr2 = tr.duplicate(); 
     tr2.moveToBookmark(r.getBookmark()); 
     tr.setEndPoint('EndToStart',tr2); 
     if (r == null || tr == null) return { start: e.value.length, end: e.value.length, length: 0, text: '' }; 
     var text_part = r.text.replace(/[\r\n]/g,'.'); //for some reason IE doesn't always count the \n and \r in the length 
     var text_whole = e.value.replace(/[\r\n]/g,'.'); 
     var the_start = text_whole.indexOf(text_part,tr.text.length); 
     return { start: the_start, end: the_start + text_part.length, length: text_part.length, text: r.text }; 
    } 
    //Browser not supported 
    else return { start: e.value.length, end: e.value.length, length: 0, text: '' }; 
} 

function replace_selection(the_id,replace_str) 
{ 
    var e = document.getElementById(the_id); 
    selection = get_selection(the_id); 
    var start_pos = selection.start; 
    var end_pos = start_pos + replace_str.length; 
    e.value = e.value.substr(0, start_pos) + replace_str + e.value.substr(selection.end, e.value.length); 
    set_selection(the_id,start_pos,end_pos); 
    return {start: start_pos, end: end_pos, length: replace_str.length, text: replace_str}; 
} 

function set_selection(the_id,start_pos,end_pos) 
{ 
    var e = document.getElementById(the_id); 

    //Mozilla and DOM 3.0 
    if('selectionStart' in e) 
    { 
     e.focus(); 
     e.selectionStart = start_pos; 
     e.selectionEnd = end_pos; 
    } 
    //IE 
    else if(document.selection) 
    { 
     e.focus(); 
     var tr = e.createTextRange(); 

     //Fix IE from counting the newline characters as two seperate characters 
     var stop_it = start_pos; 
     for (i=0; i < stop_it; i++) if(e.value[i].search(/[\r\n]/) != -1) start_pos = start_pos - .5; 
     stop_it = end_pos; 
     for (i=0; i < stop_it; i++) if(e.value[i].search(/[\r\n]/) != -1) end_pos = end_pos - .5; 

     tr.moveEnd('textedit',-1); 
     tr.moveStart('character',start_pos); 
     tr.moveEnd('character',end_pos - start_pos); 
     tr.select(); 
    } 
    return get_selection(the_id); 
} 

function wrap_selection(the_id, left_str, right_str, sel_offset, sel_length) 
{ 
    var the_sel_text = get_selection(the_id).text; 
    var selection = replace_selection(the_id, left_str + the_sel_text + right_str); 
    if(sel_offset !== undefined && sel_length !== undefined) selection = set_selection(the_id, selection.start + sel_offset, selection.start + sel_offset + sel_length); 
    else if(the_sel_text == '') selection = set_selection(the_id, selection.start + left_str.length, selection.start + left_str.length); 
    return selection; 
} 
+1

Trong tất cả các giải pháp tôi đã thấy cho vấn đề này, đây là giải pháp duy nhất đang hoạt động cho tôi. –

+1

bạn nên lấy các phần tử làm tham số thay vì ID, làm cho nó linh hoạt hơn rất nhiều. Nếu không rực rỡ! Cảm ơn bạn rất nhiều vì thông tin chi tiết về những người/trang web khác không cung cấp được. – Sam

+0

Chức năng đẹp; chúng rất dễ thích ứng với nhu cầu của tôi. Có một lỗi mặc dù sẽ bắt IE 6 & 7. Trong hàm set_selection bạn có "e.value [i]". Điều này sẽ được thay đổi thành "e.value.charAt (i)". Xem: http://stackoverflow.com/questions/5943726/string-charatx-or-stringx – ChrisD

1

điều duy nhất tôi có thể thêm là dường như (không cố tình thử nghiệm) rằng thao tác này sẽ cuộn hết lên bất cứ khi nào bạn tập hợp nội dung. một phương thuốc eay là để bọc đường mà không

e.value = 

với hai dòng để sao chép và khôi phục scrollTop, như vậy:

var rememberScrollTop = e.scrollTop; 
e.value = .... (same as in user357565 snippet) 
e.scrollTop = rememberScrollTop; 
5

Tôi vừa mới thông qua các giải pháp được trình bày bởi user357565, và recoded cho jQuery sử dụng trực tiếp:

(function ($) { 
    $.fn.get_selection = function() { 
    var e = this.get(0); 
    //Mozilla and DOM 3.0 
    if('selectionStart' in e) { 
     var l = e.selectionEnd - e.selectionStart; 
     return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) }; 
    } 
    else if(document.selection) { //IE 
     e.focus(); 
     var r = document.selection.createRange(); 
     var tr = e.createTextRange(); 
     var tr2 = tr.duplicate(); 
     tr2.moveToBookmark(r.getBookmark()); 
     tr.setEndPoint('EndToStart',tr2); 
     if (r == null || tr == null) return { start: e.value.length, end: e.value.length, length: 0, text: '' }; 
     var text_part = r.text.replace(/[\r\n]/g,'.'); //for some reason IE doesn't always count the \n and \r in length 
     var text_whole = e.value.replace(/[\r\n]/g,'.'); 
     var the_start = text_whole.indexOf(text_part,tr.text.length); 
     return { start: the_start, end: the_start + text_part.length, length: text_part.length, text: r.text }; 
    } 
    //Browser not supported 
    else return { start: e.value.length, end: e.value.length, length: 0, text: '' }; 
    }; 

    $.fn.set_selection = function (start_pos,end_pos) { 
    var e = this.get(0); 
    //Mozilla and DOM 3.0 
    if('selectionStart' in e) { 
     e.focus(); 
     e.selectionStart = start_pos; 
     e.selectionEnd = end_pos; 
    } 
    else if (document.selection) { //IE 
     e.focus(); 
     var tr = e.createTextRange(); 

     //Fix IE from counting the newline characters as two seperate characters 
     var stop_it = start_pos; 
     for (i=0; i < stop_it; i++) if(e.value[i].search(/[\r\n]/) != -1) start_pos = start_pos - .5; 
     stop_it = end_pos; 
     for (i=0; i < stop_it; i++) if(e.value[i].search(/[\r\n]/) != -1) end_pos = end_pos - .5; 

     tr.moveEnd('textedit',-1); 
     tr.moveStart('character',start_pos); 
     tr.moveEnd('character',end_pos - start_pos); 
     tr.select(); 
    } 
    return this.get_selection(); 
    }; 

    $.fn.replace_selection = function (replace_str) { 
    var e = this.get(0); 
    selection = this.get_selection(); 
    var start_pos = selection.start; 
    var end_pos = start_pos + replace_str.length; 
    e.value = e.value.substr(0, start_pos) + replace_str + e.value.substr(selection.end, e.value.length); 
    this.set_selection(start_pos,end_pos); 
    return {start: start_pos, end: end_pos, length: replace_str.length, text: replace_str}; 
    }; 

    $.fn.wrap_selection = function (left_str, right_str, sel_offset, sel_length) { 
    var the_sel_text = this.get_selection().text; 
    var selection = this.replace_selection(left_str + the_sel_text + right_str); 
    if(sel_offset !== undefined && sel_length !== undefined) 
     selection = this.set_selection(selection.start + sel_offset, selection.start + sel_offset + sel_length); 
    else if(the_sel_text == '') 
     selection = this.set_selection(selection.start + left_str.length, selection.start + left_str.length); 
    return selection; 
    }; 
}(jQuery)); 

Tôi hy vọng ai đó thấy nó hữu ích!

+0

Cảm ơn người đàn ông! sử dụng mã của bạn và sửa đổi nó một số tài khoản cho chuyển đổi wrapper vv Bạn muốn tôi bao gồm lưu ý/liên kết với bạn? – Dominik

+0

Cảm ơn nhưng không cần thiết. –

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