我正在使用textarea
内的浏览器内编辑器。我已经开始寻找处理textarea
选择的一些信息,并发现this jQuery plugin, fieldSelection做了一些简单的操作。了解如何使用JavaScript选择textarea
但是,它没有解释发生了什么。
我想了解更多关于textarea选择的JavaScript,最好是描述DOM3之前和DOM30之后的场景。
我正在使用textarea
内的浏览器内编辑器。我已经开始寻找处理textarea
选择的一些信息,并发现this jQuery plugin, fieldSelection做了一些简单的操作。了解如何使用JavaScript选择textarea
但是,它没有解释发生了什么。
我想了解更多关于textarea选择的JavaScript,最好是描述DOM3之前和DOM30之后的场景。
从PPK的introduction to ranges开始。 Mozilla开发者连接有关于W3C selections的信息。微软有他们的系统documented on MSDN。一些更多的技巧可以发现in the answers here。
除了不兼容的接口之外,您会很高兴知道textarea
节点还有额外的奇怪之处。如果我没有记错的话,当你在IE中选择它们时,它们的行为与其他节点相同,但在其他浏览器中,它们有一个独立的选择范围,通过节点上的.selectionEnd
和.selectionStart
属性公开。
此外,你应该真的看看.contentEdiable
作为一种手段来编辑生活的东西。从Firefox3发布以来,所有浏览器都支持这一功能。
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;
}
在我看到这个问题的所有解决方案中,这是唯一一个为我工作的解决方案。 – 2011-08-10 23:15:14
您应该将元素作为参数而不是ID,这使得它更加灵活。否则辉煌!非常感谢您提供其他人/网站未能提供的见解。 – Sam 2011-09-29 19:06:05
我唯一可以补充的是,它似乎(并没有真正尝试它),这应该滚动一直向上滚动,只要你处理内容。一个EAY的补救办法是换行不
e.value =
行两行复制和恢复scrollTop的,就像这样:
var rememberScrollTop = e.scrollTop;
e.value = .... (same as in user357565 snippet)
e.scrollTop = rememberScrollTop;
我刚刚通过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));
我希望有人认为它有用!
谢谢Borgar!我从来没有听说过contentEditable之前。我会很快熟悉它! – brad 2009-01-05 19:28:30