我正在textarea. 我已经开始寻找一些有关处理textarea选择的信息,并找到了这个 jQuery 插件 fieldSelection,它可以进行一些简单的操作。
但是,它没有解释发生了什么。
我想更多地了解 JavaScript 中的 textarea 选择,最好是对 DOM3 前和 DOM30 后场景的描述。
我正在textarea. 我已经开始寻找一些有关处理textarea选择的信息,并找到了这个 jQuery 插件 fieldSelection,它可以进行一些简单的操作。
但是,它没有解释发生了什么。
我想更多地了解 JavaScript 中的 textarea 选择,最好是对 DOM3 前和 DOM30 后场景的描述。
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;
}
从 PPK对 range的介绍开始。Mozilla 开发人员连接有关于W3C 选择的信息。Microsoft在 MSDN 上记录了他们的系统。可以在此处的答案中找到更多技巧。
除了不兼容的接口之外,您会很高兴地知道textarea节点还有一些奇怪的地方。如果我没记错的话,当您在 IE 中选择它们时,它们的行为与任何其他节点一样,但在其他浏览器中,它们具有独立的选择范围,该范围通过节点上的.selectionEnd和.selectionStart属性公开。
此外,您真的应该将其.contentEditable视为一种实时编辑内容的方法。从 Firefox3 发布开始,现在所有浏览器都支持它。
我刚刚采用了 user357565 提出的解决方案,并重新编码以供 jQuery 直接使用:
(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));
我希望有人觉得它有用!
我唯一可以补充的是,似乎(没有实际尝试过)每当您操纵内容时,它都应该一直向上滚动。一个简单的补救措施是将行
e.value =
用两行来复制和恢复 scrollTop,如下所示:
var rememberScrollTop = e.scrollTop;
e.value = .... (same as in user357565 snippet)
e.scrollTop = rememberScrollTop;