autoResizeを使ってみた
前回のTwitterライクな文字数カウンターを使うのは、テキストエリアが基本だろう。その場合に大量にテキストを書いた場合や、改行が多く含まれるテキストを入力するとテキストエリアが小さいとすべて表示することができなくなってしまう。最初から大きくとっておくと邪魔なので必要な時に大きくなって欲しいこともあるだろう。その要望に答えるのがautoResizeだ。
今回もjQueryのプラグインなので使い方は簡単で、以下の様な引数を渡すだけ。animateはこれを入れないとFireFoxで広がった瞬間にキャレットの位置がずれてしまった為入れた。
t.autoResize({ animateDuration : 300, extraSpace: 20, minHeight: 16, animate: { duration: 0, complete: function(){} } });
実装としてはオリジナルのテキストエリアにkeyup、change、pastイベントが来たら、cloneでテキストエリアを複製し、そのscrollTopを取得して、オリジナルのテキストエリアを広げるという物。この実装を見たときは「なるほど、賢い」と思った。IE7でも動くと書いてあったので動かしてみると確かに動く。これは便利と実際のアプリに組み込んで見たところ、IE7でフォームの値がわたらない問題が起こった。かなり(半日ぐらい)はまって色々調査したところ、IE7(?)のclone実装に問題があったようだ。手元にIE7の環境が無いので細かい調査が出来なかったのだが、どうやらIE7のcloneは作ったプロセスの間はオリジナルへのポインタとなっているらしい。cloneという関数名からは想像もできない挙動だが、シャローコピーと言った感じか。それだけなら良かったのかもしれないが、autoResizeはcloneしたテキストエリアの高さを算出する為にbodyにappendしているのだ。その時にidとかが被って変なことになるのを防ぐ為(?)にidとname属性をcloneしたテキストエリアから消しているのだ。結局IE7だとオリジナルへの参照なので、オリジナルのidとname属性を消すことになってしまい、パラメータが渡らなかったのではないと言う結論に至った。
そこでcreateClone関数の中でcloneしているところを関数化しIEのみ挙動を変えるようにした。cloneNodeではなく「新しく作ってコピー」に変えた。
function createTextAreaClone(el) { if (!$.browser.msie) return el.clone(); var txt = document.createElement('textarea'); txt.style.cssText = el[0].style.cssText; return $(txt).attr('class', el.attr('class')); }
作られたのも昔というのもあり若干バグが残っている。野良jQueryプラグインの怖さを味わった。仕事で使うならやはり実績があるプラグインがいいかもしれない。