2017年3月28日火曜日

テキストエリア内のカーソル行、列を取得・設定する

テキストエリア内でカーソルが何行目の何列目にあるのかを取得したり設定するためのサンプルを作成しました。

HTA専用(クロスブラウザにしようと思えばできることだけど、難解なのでHTAに特化することで少しでも分かり易くしたい)です。

試した限りでは意図した通りの動作になることを確認しましたが、正直なところ仕様を理解できているとは言えないので、もしかすると意図しない動作になってしまうケースがあるかもしれません。

以下ソース
<html>
<head>
<title>行番号</title>
<style type="text/css">
.max{width:100%;height:100%}
.bc{border-collapse:collapse}
.of-hidden{overflow:hidden}
</style>
</head>
<body class="of-hidden">
<table class="bc max">
<tr><td><textarea id=ta class=max wrap=off></textarea></td></tr>
<tr height=1><td>行:<input id=inp行> 列:<input id=inp列></td></tr>
</table>
</body>
<script>
resizeTo(400,400)
ta.onkeyup=ta.onkeydown=function(){
var obj=getテキストカーソル位置(this), str=this.value.slice(0,obj.start), arr=str.split('\n')
inp行.value = arr.length
inp列.value = arr[arr.length-1].length + 1
}
getテキストカーソル位置=function(elem){
// 左記URLのページを参照させていただきました。 http://d.hatena.ne.jp/nakazawaken1/20100125/p1
var rngSel=document.selection.createRange(), rngElem=document.body.createTextRange()
rngElem.moveToElementText(elem)
// rngSelより前の範囲を選択する(rngElemのEndをrngSelのStart位置に合わせる)
rngElem.setEndPoint('EndToStart', rngSel)
var f=function(rng){
var str=rng.text, str0=str
// 選択文字数が0でない間(前の範囲)
while(rng.compareEndPoints('StartToEnd', rng) != 0){
// 一文字ずつ範囲終了位置を前にずらしていく
rng.moveEnd('character', -1)
// ずらす前と後の文字列が異なる状態ならbreak
if(str0 != rng.text){break}
// ずらす前と後の値が同じ状態の間は改行を付け足していく。
str += '\r\n'
}
return str
}
var str前=f(rngElem), str選択=f(rngSel), start=str前.length, end=start + str選択.length
return {start:start, end:end}
// 以下の方法では選択範囲の末尾に改行文字がある場合、意図した通りの動作にならない。
/*
rngSel.moveStart('character', -this.value.length)
rngSel.moveEnd ('character', 1)
var reg=/\n/g, res=rSel.text.match(reg), 行, 列
if(res){
行 = res.length
列 = RegExp.rightContext.length - 1
}else{
行 = 0
列 = rSel.text.length - 1
}
inp行.value = 行
inp列.value = 列
*/
}
inp行.onchange = inp列.onchange = function(){
var 行=inp行.value, 列=inp列.value, arr=ta.value.split('\r\n'), rng=document.body.createTextRange()
行 = isFinite(行) ? 行 : 1
列 = isFinite(列) ? 列 : 1
ta.select()
rng.moveToElementText(ta)
rng.moveStart('character', arr.slice(0,行).join('\r\n').length - (行-1))
rng.moveStart('character', 列 - arr[行-1].length - 1)
while(rng.compareEndPoints('StartToEnd', rng) != 0){ rng.moveEnd('character',-1) }
rng.select()
}
</script>
</html>

0 件のコメント:

コメントを投稿