textarea文字列をタグで囲んだ後のカーソル表示
MyHome PortalのVer.3.11で、textareaへのタグ&アイコン挿入を改善しました。
textareaへのタグ&アイコン挿入には、
「textareaの選択範囲を取得し、前後に文字列を挿入する」
http://archiva.jp/web/javascript/getRange_in_textarea.html
のJavaScriptを使わせてもらっていましたが、タグ&アイコン挿入後に、カーソル(キャレット)が、textareaから出てしまったりしていました。タグ&アイコン挿入後も、カーソル(キャレット)がtextarea内に残るように、修正しました。カーソル(キャレット)が挿入タグの後ろに表示されるようにしました。
IEの場合、選択文字列をタグで囲んだ時には、挿入後のカーソル位置を決めるため、選択位置前の改行コードや、選択範囲内の改行コードの数を数える必要があるようです。
IEの場合、文字列を囲むのではなく、アイコン挿入など単に文字列挿入の場合、元のロジックでは行末と行頭の区別を付けることが出来ず、行頭にアイコン挿入が出来なかったので、シンプルに
var selection = document.selection.createRange();
selection.text = tag1 + tag2 + selection.text;
で、処理するようにしました。
これらにより、全体的に継ぎ接ぎ的なロジックになってしまいました。根本的にロジックを見直せば、もっとスッキリすると思われますが、とりあえず、これにてリリースしました。
以下に、修正版のJavaScriptソースを添付しておきます。
-------------------------------
function encloseTextArea(tag1, tag2, obj) {
var target = document.getElementById(obj);
var pos = getAreaRange(target);
if (isIE && (tag2 == '' || pos.start == pos.end)) {
target.focus();
var selection = document.selection.createRange();
selection.text = tag1 + tag2 + selection.text;
return;
}
var val = target.value;
var range = val.slice(pos.start, pos.end);
var beforeNode = val.slice(0, pos.start);
var afterNode = val.slice(pos.end);
var insertNode;
if (range || pos.start != pos.end) {
insertNode = tag1 + range + tag2 ;
target.value = beforeNode + insertNode + afterNode;
} else if (pos.start == pos.end) {
insertNode = tag1 + tag2;
target.value = beforeNode + insertNode + afterNode;
}
target.focus();
if (isIE) {
r = target.createTextRange();
if (retmatch = beforeNode.match(/\r\n/g)) {
retnum = retmatch.length;
} else {
retnum = 0;
}
if (range) {
if (retmatch = range.match(/\r\n/g)) {
retnum += retmatch.length;
}
}
r.move('character', pos.end + tag1.length + tag2.length - retnum);
r.select();
} else {
var newpos = pos.end + tag1.length + tag2.length;
target.setSelectionRange(newpos, newpos);
}
}
function getAreaRange(obj) {
var pos = new Object();
if (isIE) {
obj.focus();
var range = document.selection.createRange();
var clone = range.duplicate();
clone.moveToElementText(obj);
clone.setEndPoint('EndToEnd', range);
pos.start = clone.text.length - range.text.length;
pos.end = clone.text.length - range.text.length + range.text.length;
} else if(window.getSelection()) {
pos.start = obj.selectionStart;
pos.end = obj.selectionEnd;
}
return pos;
}
var isIE = (navigator.appName.toLowerCase().indexOf('internet explorer')+1?1:0);