コードなどを記述する pre 要素の overflow を auto にしている時、1行の文字数が多い場合マウスオーバーすると幅が自動的に広がるようにする。
このサイト(例)の場合、google-code-prettify を使ってコードの記述部分をシンタックスハイライトするようにしていて、行番号を表示する場合は、番号リスト(ol)で出力され、そうでない場合は、span 要素で出力されている。(「WordPressのショートコードでシンタックスハイライト」)
行番号を表示しない場合は、span 要素だけで出力されているため、各行を検出することができないので、行番号を表示しているものを対象とする。(何かいい方法が思いつかないので、取り合えずは全て行番号を表示するようにする。)
各行の幅は、当初は以下のように各行の文字数から幅を算出しようとしたが、半角や全角、空白やタブなどでの個々の幅を算出が困難なので変更。
$('#contents pre.prettyprint').hover( function() { var that = $(this); var li$ = that.find('li'); //li 要素のラップ集合 var maxCount = 0; li$.each(function() { //各行の文字数をカウントし最大数を取得 maxCount = Math.max(maxCount, $(this).text().length); }); var prettyprint_maxwidth = maxCount * 10; //最大文字数から行の幅を推測(かなりアバウト) ...
行番号を表示する場合は、番号リスト(ol)で出力され、各行(li 要素)はテキストの内容が、複数の span 要素で出力されている。
<div class="prettifydiv"> <pre class="prettyprint linenums prettyprinted" style=""> <ol class="linenums"> <li class="L0"> <li class="L1"> <span class="pln">jQuery</span> <span class="pun">(</span> <span class="pln">document</span> <span class="pun">).</span> ... </li> <li class="L2">...</li> <li class="L3">...</li> </ol> </pre> </div>
そこで、各行の幅はその行に含まれる各 span 要素の幅の合計として算出してその最大値を取得。
幅の最大値が基準の値(*)より大きい場合は、幅をjQuery のアニメーションメソッドを使用して拡大。
(*) pre 要素内の ol 要素などのマージンやパディングを考慮して決定。 pre 要素の幅の値よりは小さくなっている。
この例では、コードを記述してある pre 要素には「prettyprint」というクラスが指定してある。
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 の最新バージョンで機能しない」