中級プログラマの自宅でPHP ブログ

自宅用ポータルシステム「MyHome Portal」をオープンソースで公開。MyHome Portalの説明とエンハンス情報。

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);