jquery jQueryで文字数により表示幅を変える

2013年4月17日

コードなどを記述する pre 要素の overflow を auto にしている時、1行の文字数が多い場合マウスオーバーすると幅が自動的に広がるようにする。

このサイト(例)の場合、google-code-prettify を使ってコードの記述部分をシンタックスハイライトするようにしていて、行番号を表示する場合は、番号リスト(ol)で出力され、そうでない場合は、span 要素で出力されている。(「WordPressのショートコードでシンタックスハイライト」)

行番号を表示しない場合は、span 要素だけで出力されているため、各行を検出することができないので、行番号を表示しているものを対象とする。(何かいい方法が思いつかないので、取り合えずは全て行番号を表示するようにする。)

各行の幅は、当初は以下のように各行の文字数から幅を算出しようとしたが、半角や全角、空白やタブなどでの個々の幅を算出が困難なので変更。

  1. $('#contents pre.prettyprint').hover(
  2. function() {
  3. var that = $(this);
  4. var li$ = that.find('li'); //li 要素のラップ集合
  5. var maxCount = 0;
  6. li$.each(function() { //各行の文字数をカウントし最大数を取得
  7. maxCount = Math.max(maxCount, $(this).text().length);
  8. });
  9. var prettyprint_maxwidth = maxCount * 10; //最大文字数から行の幅を推測(かなりアバウト)
  10. ...

行番号を表示する場合は、番号リスト(ol)で出力され、各行(li 要素)はテキストの内容が、複数の span 要素で出力されている。

  1. <div class="prettifydiv">
  2. <pre class="prettyprint linenums prettyprinted" style="">
  3. <ol class="linenums">
  4. <li class="L0">
  5. <li class="L1">
  6. <span class="pln">jQuery</span>
  7. <span class="pun">(</span>
  8. <span class="pln">document</span>
  9. <span class="pun">).</span>
  10. ...
  11. </li>
  12. <li class="L2">...</li>
  13. <li class="L3">...</li>
  14. </ol>
  15. </pre>
  16. </div>

そこで、各行の幅はその行に含まれる各 span 要素の幅の合計として算出してその最大値を取得。

幅の最大値が基準の値(*)より大きい場合は、幅をjQuery のアニメーションメソッドを使用して拡大。

(*) pre 要素内の ol 要素などのマージンやパディングを考慮して決定。 pre 要素の幅の値よりは小さくなっている。

この例では、コードを記述してある pre 要素には「prettyprint」というクラスが指定してある。

  1.  

jQuery(document).ready(function($) {
//シンタックスハイライト部分の幅の調整
var prettyprint_width = $(‘#contents pre.prettyprint’).width(); //シンタックスハイライト部分の幅
var expandWidth = 840; //拡大する際のシンタックスハイライト部分の幅の値
$(‘#contents pre.prettyprint’).hover(
function() {
var prettyprint_comparison_width = 590; //比較の基準とする幅(*)
var that = $(this);
var li$ = that.find(‘li’); //’li’要素のラップ集合
var maxWidth = 0; //各行の幅の最大値を初期化
li$.each(function() { //各行に含まれる’span’要素の幅を合計し、その最大値を取得する
var spanWidth = 0; //各’span’要素の幅の合計値を初期化
$(this).find(‘span’).each(function() {
spanWidth += $(this).width();
});
maxWidth = Math.max(maxWidth, spanWidth);
});
if(prettyprint_comparison_width < maxWidth) { //各行の幅の最大値が比較の基準とする幅の値より大きければexpandWidth(840)まで拡大 that.not(":animated").css({whiteSpace: 'pre-wrap', position: 'relative', zIndex: 10}).animate({width: expandWidth}, 100); }else{ return; } }, function() { if($(this).width() == expandWidth) { //シンタックスハイライト部分の幅が拡大されていれば元に戻す $(this).css({whiteSpace: 'pre'}).animate({width: prettyprint_width}, 100); } }); }); [/code] (追記:2013/7/7) Firefox の最新バージョン(22.0)になってから、マウスアウトする際に、今までは元の幅に自動的に戻っていたのに、戻らなくなった。他のブラウザ(IE, Chrome, Safari)では問題がない。 [code] function() { if($(this).width() == expandWidth) { //シンタックスハイライト部分の幅が拡大されていれば元に戻す $(this).css({whiteSpace: 'pre'}).animate({width: prettyprint_width}, 100); } }); [/code] の部分を以下のように変更(条件を削除)すると元の幅に自動的にもどるようになった。 [code] function() { $(this).css({whiteSpace: 'pre'}).animate({width: prettyprint_width}, 100); }); [/code] 関連情報:「jQuery で作成した機能が Firefox の最新バージョンで機能しない