6月にエントリーシートの下書き作成用エディタをつくった。
ES Draft
http://naoyashiga.github.io/ES_Draft/
行数カウンターを設置しているが、それの数え方がうまくいかない。行数をカウントして、テキストエリアのサイズを可変にするようにしていた。しかしうまく可変されないバグがあった。
修正前
当初は次のようにしていた。
行数 = テキストエリアの文字数 / テキストエリアのカラム数(1行に入力できる文字数)
問題は2つあった。
問題1
改行文字を考慮していなかった。改行ばかりのテキストを入力すると、行数が少なくカウントされて、可変にならない。
問題2
テキストエリアのカラム数(1行に入力できる文字数)が一定ではない。ひらがな、英語で文字数が変わるのでどうしようもない。だから行数を正しくカウントできない。
//テキストエリアの縦を可変にする $("textarea").bind("keyup",function(){ var id = $(this).attr("id"); var cur = this; //テキストエリアの文字数を計算 改行文字を消去 var value = $(this).val().replace(/\n/g,""); //編集中のテキストエリアの行数を計算 var row = Math.max(Math.floor(value.length / cur.cols),1); //行数の初期値を設定 if(id == "title")var init_row = TITLE_ROWS; else var init_row = DRAFT_ROWS; if(row > init_row) $(this).attr("rows",row); else $(this).attr("rows",init_row); });
修正後
今回は問題1だけを直した。 改行文字の数をカウントして、テキストエリアの行数の初期値を超えたら、行数を足すことにした。
ここで修正前のコードを見る。
//タイトル行数の初期値 String型 var TITLE_ROWS = $("#title").attr("rows"); //ドラフト行数の初期値 String型 var DRAFT_ROWS = $("#draft").attr("rows"); //~途中省略~ if(row > init_row) $(this).attr("rows",row); else $(this).attr("rows",init_row);
初期値それぞれは、テキストエリアの属性「rows」を取得してるのでStringである。その語、テキストエリアを可変にするために、「rows」を設定し直している。jQueryにおいてattr()の第2引数はStringで正しく動いていた。
修正後のコードは次のようにした。あとで改行文字数を足すかもしれないので、属性「rows」の値をIntegerで取得した。
//タイトル行数の初期値 Integer var TITLE_ROWS = parseInt($("#title").attr("rows")); //ドラフト行数の初期値 Integer var DRAFT_ROWS = parseInt($("#draft").attr("rows")); //~途中省略~ if(row + len > init_row) $(this).attr("rows",row + len); else $(this).attr("rows",init_row);
これをStringとIntegerを混合させて、セットすると次のようになる。ここからjQueryのattr()の第2引数の計算で使われるIntegerは自動的にStringに型変換された後、計算されるようだ。
var str = "100"; var num = 1; $(this).attr("rows",str + num); console.log($(this).attr("rows")); //出力結果:1001
ちなみにStringをIntegerに直す方法として「+」をつけるやり方があるみたいだ。
参考:JavaScript イディオム集http://nmi.jp/archives/488
var str = "100"; var num = 1; $(this).attr("rows",+str + num);//str→+str console.log($(this).attr("rows")); //出力結果:101
最終的に修正したコードは次のようになった。
//テキストエリアの縦を可変にする $("textarea").bind("keyup",function(){ var id = $(this).attr("id"); var cur = this; //改行文字数 var len = 0; if($(this).val().match(/\n/g)){ //改行の個数+1行目 len = $(this).val().match(/\n/g).length + 1; } //テキストエリアの文字数を計算 var value = $(this).val().replace(/\n/g,""); //編集中のテキストエリアの行数を計算 var row = Math.max(Math.floor(value.length / cur.cols),1); //行数の初期値を設定 if(id == "title")var init_row = TITLE_ROWS; else if(id == "draft")var init_row = DRAFT_ROWS; if(row + len > init_row) $(this).attr("rows",row + len); else $(this).attr("rows",init_row); });
結果
問題1は解決できたので、より正しく可変されるようになった。しかし問題2が解決していないために、ソースコードのような改行ばかりのテキストをペーストした場合、テキストエリアが必要以上に長くなってしまう。どうにか解決できないものか。