blue

fdScroller.js ちょこっと改良

  • Posted by: SOMA Hitoshi
  • November 18, 2008 3:22 PM
  • web

楽勝と思ったコード修正に落とし穴発覚。当初提示したコードではSafari、Google Chrome、Operaといったブラウザで期待どおりの動作をしませんでした。コードは再修正済み。再修正の詳細は記事の後段を参照ください。

 「続々・ページ内リンク(ID)にするするっと移動する」等の記事で紹介したfdScroller.jsだが、ほんの少しだけコードを書き足し、以前から気づいていた問題点を修正した。きっかけはDISQUSである。

 HTMLにJavaScriptのトリガーを持たせるさいのやり方として、アンカーに空のハッシュ「#」を設定する──で、「onclick="〜"」などとやる──手が古くからあるが、fdScroller.jsはとにかくドキュメント内のすべてのハッシュへのクリックを自身のプログラムへと引き取ってしまうから、そのようにして書かれたJavaScriptが動作しなくなってしまうのだった。
 同じくアンカーを使っても <a href="javascript:〜"> というふうに書くぶんにはだいじょうぶで、だからこれまでは──もっぱら自サイト内に置いて使うJavaScriptとバッティングするだけだったから──不具合を見つけるたびにそう書き換えて対処していた。
 が、DISQUSが吐くコードはこちらで書き換えることができない。で、DISQUSがこの空の「#」を多用しているのだった。

 というわけで、共存させるにはfdScroller.jsのほうを見直さなければならないのだが、よく考えたら非常に簡単な話だった。スクロールを起こさせる場合の条件にひとつ足し、ハッシュの値が1文字以上なければ動作しないようにすればいいわけである。

と言って一度修正版を提示したものの

 上記のように説明して提示した修正版のコードでは、まず、

  1.  var lnks = document.getElementsByTagName('a');
  2.   for(var i = 0, lnk; lnk = lnks[i]; i++) {
  3.   var lnkhash = lnk.hash;

として変数「lnkhash」にハッシュの値を代入したうえで、それが「1文字以上あれば〜」という部分を、はじめ次のように書いていた。

if (lnkhash.length > 0) { 処理 }

 Firefoxではこれで問題なく動作するものだから、単純なコードでもあるし、とくに疑うことなくこれを記事中に公開したのだったが、その後まずSafariで、これでは期待する動作をしない(つまり、<a href="#">のケースでこの判定が真になる)ことがわかった。

さて、ちゃんと検証してみると

 リンク先に「#」とだけ指定されたアンカーに対してその hash の値の length を取得した場合、Safari、Google Chrome、Operaでは「1」が、FirefoxとIEでは「0」が返ってくる。で、「#a」の場合にはどのブラウザも「2」となるのだった。Safari系のブラウザが一貫し「#」自身も含めた文字数を返してくるのに対し、Firefox系では、ハッシュが空(「#」)である場合にのみ例外的に、(「空」という意味でだろうか)「0」を返すのである。
 複雑なようだけれど、要はハッシュが空でない場合、どのブラウザでも length は「2以上」になるというわけで、つまりさきほどの条件文は、

if (lnkhash.length > 1) { 処理 }

とすればいいのだった。
 というわけで、以下が修正版の全文。

関連記事

トラックバック(1)

トラックバックURL: https://web-conte.com/blue/mt-tb.cgi/387

以下のリストにある記事は、当記事 " fdScroller.js ちょこっと改良 " を参照しています :

fdScroller.js ちょこっと改良 はじめまして、るりのんです。 共同でブログを書かせていただくにあたって、こちらへは自分が便利だと思ったWeb ...

2010年6月13日 22:59