ここから本文です

他ページから指定したタブへダイレクトリンクする方法を探しています。

light08sunさん

2013/7/218:48:32

他ページから指定したタブへダイレクトリンクする方法を探しています。

jQueryで下記URLのタブメニューを実装しております。
http://web-box.jp/kyoto/tab.html

タブのコンテンツは非表示で設定しており、
タブをクリックするとコンテンツが表示されます。

他ページ(index.html)から指定したタブ(tab.html#panel1)へ
ダイレクトリンクする方法があれば教えて頂けないでしょうか。

他のQ&Aなどを調べて試してみたのですが
javascript初心者で自己解決できず、こちらで質問させていただきました。

すみませんが、どうぞよろしくお願いいたします。

閲覧数:
5,524
回答数:
2
お礼:
500枚

違反報告

ベストアンサーに選ばれた回答

arc_coeurlさん

編集あり2013/7/315:54:07

ブラウザは HTML のソースコードを上から順に解釈していきます。
解釈しながら、例えば <script> タグが現れたら、そのスクリプトを解釈して実行します。

続けて HTML ソースを解釈して、例えば <img> タグがあれば画像を読み込んで表示して、ということを行い、 </html> まで読み込むと HTML の中身が全て構築されます。

(1) HTMLを解釈する(している途中)
(2) HTMLの中身が全て構築される(DOMツリーが完成する)
(3) 画像などの読込中のものが全て読み終わる(load イベントが発火する)

(3) まで終えると、ページの読み込みが完了した、ということになります。
「タブボタンをクリックしたら...」と JavaScript に jQuery を用いて記述していますが、この <script> タグは、 <body> よりも手前に書いています。

つまり、このスクリプトが実行される (1) のタイミングでは、タブボタンを参照することができません。
このため、 jQuery の機能を用いて、「(2) が終わったら処理をする」という書き方になっています。

========================================
// ここは (1) のタイミングで実行される
$(function(){
// この function() {} の中は (2) が終わったら実行される
});
// ここは (1) のタイミングで実行される
========================================

さて、本題に移ります。
タブやコンテンツを操作したいので、 (2) が終わった後に実行したいです。
ということで $(function() { ... }) と書き、 ... の部分にやりたいことを書きます。

他ページからハッシュフラグメント( # 記号)付きの URL で遷移してきた場合や、ページ内リンクで #付きの URL へ遷移した場合、そのページでは location.hash という変数(プロパティ)を参照することで、ハッシュの値が取得できます。

ハッシュの値を取得して、対応するタブのコンテンツを show することで、目的を達成できそうです。

========================================
//通常記述
$(function(){

var activePanelId = $("#tab .active a").attr("href");

$("#tab .panel > div:not(" + activePanelId + ")").hide();
$("#tab > ul li a").click(function(){
$("#tab .panel").show();
$("#tab > ul li.active").removeClass("active");
$("#tab .panel > div").hide();
$(this).parent("li").addClass("active");
$($(this).attr("href")).fadeIn(500);
return false;
});

// ここから
var hash = location.hash;
hash = (hash.match(/^#panel\d+$/) || [])[0];
var $tab = $("#tab > ul li a").filter("[href=" + hash +"]");
if ($tab.length > 0) {
$tab.eq(0).click();
}
// ここまで
})
========================================

この例では hash で指定された panel のコンテンツを表示するのではなく、その panel に対応するタブをクリックしたことにしています(その結果コンテンツが表示されます)。

目的の $tab が見つかれば、という意味で $tab.length のような if 文を書いていますが、 jQuery オブジェクトは自身の length が 0 でもメソッドを呼べるので、 if 文を書かずに $tab.eq(0).click() をいきなり実行してしまっても目的を達成できます(もし #panel99 のような URL の場合でも、何も起きないだけです)。

なお、 auau0 さんのような記述でも実現できますが、 jQuery の $() 関数に location.hash など、ユーザが入力できる値を直接入れてしまうと、ユーザが任意の JavaScript を実行できてしまう XSS という脆弱性を作ってしまう恐れがあります。
$() という関数の機能が豊富すぎるのですね(これは jQuery 1.9 以降で改善されています)。

今回の場合は jQuery 1.8.2 を用いていてハッシュフラグメント(#)ごと $() に入れているため XSS は生じないようですが、それでも危険そうな記述は避けることが好ましいです。( # から始まる $() の動作は jQuery 1.6.3 で改善されています。)

安全にするためには、 $() に入れる値を
hash = (hash.match(/^#panel\d+$/) || [])[0];
のようにして、想定しない文字列の場合は hash に渡さないようにするか、

$(location.hash) の代わりに、
$('body').find(location.hash) や、$('div').filter(location.hash) のように、
より目的に特化した関数を使うことが考えられます。

長くなりましたが、少しでも理解が深まれば幸いです。

質問した人からのコメント

2013/7/8 11:30:52

上記の方法でダイレクトリンクすることが出来ました!

丁寧な解説で初心者の私でも理解できたので、本当に助かりました。
location.hash による XSS についても大変勉強になりました。
ありがとうございます!

ベストアンサー以外の回答

1〜1件/1件中

auau0さん

編集あり2013/7/223:02:50

これを追記するとどうかな。
$(function(){
if(location.hash.substring(0,6) == "#panel"){
$("#tab .panel").show();
$(location.hash).show();
}
})
=====================
追記
おーおー、確かに。
firefoxだと、tab.html#panel<img src=a onerror=document.write(1)>
てのでHTML書き換えもできてしまいました。(IE10では何も起こらずでしたが。)攻撃者に細工されたURLで、XSSの温床でまずいですね、と。

あわせて知りたい

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問や知恵ノートは選択されたID/ニックネームのMy知恵袋で確認できます。