JSタブ切替え応用編 —他ページから直接タブにアクセスする—

/web/javascript

Note: この記事は、3年以上前に書かれています。Webの進化は速い!情報の正確性は自己責任で判断してください。

他ページからそれぞれのタブにリンクすることってできますか?

—タブ切替をサクッと実装, くりはらさんのコメント

確かに便利そうなので、やってみました。ページ内リンクと同じように「なんたら.html#Contents」とかってURLでアクセスできます。意外と簡単~。サンプルは以下の画像から。

サンプルを確認する

考え方

  1. tab.dive = function(){
  2. var hash = window.location.hash;
  3. hash = hash.split("?");
  4. hash = hash[0].split("#");
  5.  
  6. if(hash[1] == 'page2') tab.showpage(tab.setup.tabs[1]);
  7. if(hash[1] == 'page3') tab.showpage(tab.setup.tabs[2]);
  8. if(hash[1] == 'page4') tab.showpage(tab.setup.tabs[3]);
  9. if(hash[1] == 'page5') tab.showpage(tab.setup.tabs[4]);
  10. }

URLの「#」以下の部分は「location.hash」で取得できます(2行目)。#以下はID名。
そこからロード時に対応するページを開くよう「tab.showpage()」と関連付けてやれば良い(6行目以降)。

追加部分

上記のままでも動作しますが、いちおパッケージ化してみましょうか。下記のコードを「tab」オブジェクトに追加します。

  1. dive: function(){
  2. var hash = window.location.hash;
  3. hash = hash.split("?");
  4. hash = hash[0].split("#");
  5.  
  6. var tabs = this.setup.tabs;
  7. var pages = this.setup.pages;
  8. for(i=0; i<pages.length; i++) {
  9. if(pages[i] == document.getElementById(hash[1])) this.showpage(tabs[i]);
  10. }
  11. }

で、「tab.init()」でセットアップしてから「tab.dive()」を呼び出してやれば良い。tab.dive()はURLからID名を抜き出し、そこから取得したオブジェクトと先に設定したページオブジェクトを比較して、一致すればそのページを開く。

面倒ならtab.init()の最後でtab.dive()を呼び出すようにしても良いね。以下のようになる。

  1. var tab = {
  2. init: function(){
  3. var tabs = this.setup.tabs;
  4. var pages = this.setup.pages;
  5.  
  6. for(i=0; i<pages.length; i++) {
  7. if(i !== 0) pages[i].style.display = 'none';
  8. tabs[i].onclick = function(){ tab.showpage(this); return false; };
  9. }
  10. this.dive();
  11. },
  12.  
  13. ... goodness ...

こうすれば起動部分のスクリプトは前回とまったく同じなので、本体を入れ替えるだけで済む。どないでしょ?

memo: ちなみに前回の記事で起動部分を<body>内に置くように勧めたのは、onloadで起動するとロード時に一瞬だけタブが展開されて見えるから。onloadイベントが読み込み完了時に実行されるモノだからですね。

関連記事

Note: スパム対策が面倒なので、コメント投稿を廃止しました。以前のコメントは残します。
ご意見・ご要望はtwitter@sigwygかはてブコメントにて。

26 Comments

くりはら wrote:
ありがとうございます。ページ内リンクのタブ切り替えは色々調べるとあったのですが、他ページからどうしてもリンクを張りたくて・・・すごく便利です。自分でもあれこれ試してだめだったので感激です。活用させていただきます。 2007–11–12 06:55
Sig. wrote:
お役に立てて良かったです。「他ページからリンクを張る」てアイディアは確かに凄く面白いので、こちらとしてもやりがいありました。ぜひ使ってやってください^^b 2007–11–13 12:58
t_dragon_2000 wrote:
page1とかに、IFRAMEを入れたいのですが、可能ですか?やってはみたものの、スクリプトエラーがでてしまって使えないのです。 2007–11–24 20:55
Sig. wrote:
う~、失敗。
コメントの改行が吹っ飛んじゃいました。ごめんなさいっ!


それはともかくt_dragon_200さん、こんにちわ。
たとえば...

<div id="page4">
<iframe src="http://archiva.jp/" width="100%"></iframe>
</div>

...とか、単純に <iframe id="page4"> とかでも問題なくできました。
もちょっと情報Plz! 2007–11–26 15:14
Y2T wrote:
いつも参考にさせて頂いております。
この「他ページから直接タブにアクセスする」を利用させて頂いているのですが、どうしてもうまくできない点があるので、
教えて頂ければ幸いです。
/=============================================================================
・分からない点
①同ページ内でのリンクジャンプがうまくいかない
(例:http://sample.com/index.html#page1内にある#page2へのリンクにうまく飛べない)

②#page2にあるname属性に直接ジャンプしたい
(例:http://sample.com/index.html#page2にある#sampleなどのリンクへジャンプできるようにしたい)
==============================================================================/
上記の事象が改善できず、試行錯誤しております。
お忙しいとは思いますが、ご返答頂ければ幸いです。 2008–09–23 13:13
Sig. wrote:
やーこんにちわ。
ようやく仕事が落ち着いたので回答をば!

タブ内にページ内リンク移動したいとのこと。ちょいと整理しましょうか。
 1.タブ切替JSを使っていてもページ内移動はできる。
 2.表示部分の「#deeplink」などへの移動はできる。
 3.非表示タブ内への移動は「飛び先が存在しない」 ←display:noneしているため

Y2Tさんの「分からない点1」が
「http://sample.com/index.html#page1」内で
「#page2」へのリンクを押したときに「タブが展開しない」という意味であれば、
これは tab.div() の実行がページ読み込み時だからです。
ページ内リンクでは再読み込みしないので、手動で開いてやる必要がありますね。

Y2Tさんの「分からない点2」が
「展開したタブの中の指定ポイントに移動したい」という意味であれば、
タブを展開した上で、指定位置までスクロールする必要がありますね。

幾つか方法は考えられますが... 言ってることは合ってるかな? 2008–10–02 04:46
Y2T wrote:
どうもこんばんわ!
お急がしいなかご回答頂き本当にありがとうございます。
大変参考になる意見でしたので、その意見を踏まえてもう一度作成し、いじってみます!
力不足な私に貴重なアドバイスをありがとうございました。
archiva様にて紹介される記事は大変参考になるものが多いので興味深く読ませて頂いております。
今後もサイト運営がんばって下さい! 2008–10–02 22:08
Anonymous wrote:
はじめまして。
いつも見させていただいてます。
中でもこのタブ切り替えは大変参考になりました。ありがとうございます。
そこで質問なのですが、
タブの中にタブをつくる・・・ことは可能なのでしょうか。
javascript初心者なので、いろいろ試行錯誤しているのですが
どうしてもできません。
状況としては、javascriptがoffになっている様な形(タブをクリックしてもページ下へジャンプするだけ)です。
ソースはarchivaさんのソースをほぼそのまま使用させていただいておりますm(_ _)m
もしできるのであれば、ヒント等教えていただけると大変助かります。
よろしくお願いします。。 2008–11–19 21:23
Sig. wrote:
ども、おまたせしました!
タブ内のタブですか。結論から言うと、できます。

考慮すべき点は2つ。
 1.tab.setup.tabs および tab.setup.pages の登録
 2.クリック時に全てのタブを消してしまう → タブ内タブでのクリックで親タブも消える

まず1の登録ですが、基本的にリスト形式で渡せば認識してくれます。
ただしgetElementsByTagName()が返すのは配列「ではなく」、「配列のようなオブジェクト」なので、
複数のタブを登録したい場合には結合するのが難しくなります。

var tabs1 = document.getElementById('tab1').getElementsByTagName('li');
var tabs2 = document.getElementById('tab2').getElementsByTagName('li');
tab.setup.tabs = tabs1.concat(tabs2);

...ではエラーになると言うこと。
スマートな方法は思いつきませんでしたが、ちょっと泥臭く

tab.setup.tabs = [
tabs1[0],
tabs1[1],
tabs1[2],
tabs1[3],
tabs1[4],
tabs2[0],
tabs2[1],
tabs2[2],
tabs2[3],
tabs2[4]
];

...とでもすればできます。
あとは2の切替ですが、これはtab.showpage()内のIF分岐でどうにかできます。
少なくとも俺はできました。頑張ってください^^b 2008–11–23 23:11
toshi wrote:
こんにちわ。
タブ内タブについてご質問させて頂いたものです。。
ご多忙中かと存じますが、早速のご返答ありがとうございました。

あれからいろいろやってみたのですが・・・すみません。どうしてもできなくて(^-^;)

ご指摘頂いた点の2番はなんとなく理解できたのですが、1番のイメージがわからなくて。。。
>var tabs1 = document.getElementById('tab1').getElementsByTagName('li');
>var tabs2 = document.getElementById('tab2').getElementsByTagName('li');
>tab.setup.tabs = tabs1.concat(tabs2);

この部分に関しましては、なんとなくわかりました。外タブと内タブをそれぞれ宣言し、配列として結合しているってことですよね。。?
(間違ってたら恥ずかしいです(^^;)..)
ただし、それではだめで、

// ※page1~5が外タブ、page6,7,8が内タブ(page1内)の場合※
tab.setup = {
tabs = [ tabs1[0], tabs1[1], tabs1[2], tabs1[3], tabs1[4], tabs2[0], tabs2[1], tabs2[2] ]
pages:[ document.getElementById('page1'),
           ・
           ・
      document.getElementById('page8')
    ]
}
tab.init();

と、このようにするということなのでしょうか。。??
お時間があるときでかまわないです。いつかご返答いただければ幸いです。
どうかよろしくお願いします。 2008–11–27 16:44
Sig. wrote:
> 配列として結合しているってことですよね。。?
配列として結合しようとしているのだけど、getElementsByTagName()が返すのは配列ではないのでconcat()は使用できない、というのが正確かな。これができればスマートなんですけどねー。

...で、toshiさんが出している方法で動かないのは、単純に文法エラーですね。基本的には合っていますよ。「オブジェクトリテラル」でググってみてください。 2008–12–01 06:16
toshi wrote:
お返事ありがとうございます。

なるほど。「オブジェクトリテラル」という名の書式なんですね。
ググってみて、何箇所か修正をしたら・・・できました。

今回のことでまた一つ勉強になりました。
本当にどうもありがとうございました。m(_ _)mペコリ 2008–12–01 12:04
minako wrote:
はじめまして。

色々お勉強させていただいております。

1つご質問なんですが、
タブを別のタブに切り替え、リロードすると最初のタブに戻ってしまいます。
リロードしても、リロード前のタブ情報を保持するにはどうすればよろしいでしょうか?

タブページの中の本文中にテキストリンクがあるのですが、そのリンク先に飛んでから再び元のタブページへ戻るとタブの一番初めに設定されているページに戻ってしまってうので使い勝手が悪くなってます。

firefoxではリロードしてもリロード前のタブのページのままなのですが、IEだと最初に設定したタブのページに戻ってしまいます。

もしよろしければ解決方法をご教授願います! 2009–02–06 12:15
minako wrote:
ごめんなさい!質問の内容が間違ってましたので訂正します。

リロードで初期化されるのは当たり前ですよね。

戻るボタンでタブページに戻って来たときに、初期化されない方法を教えていただきたいのです。
よろしくお願い致します。 2009–02–06 12:45
Sig. wrote:
こんちわ!
そですねー履歴の表示方法はブラウザやCMSによって違うのでなんとも言えないのですが、展開情報をCookieに保存しておけば可能かもしれません。

Cookieのget/setは以下の記事が参考になるかも。できたら教えてくださいねー^^b
http://archiva.jp/web/javascript/cookie-memo.html
http://archiva.jp/web/javascript/save_preset.html 2009–02–06 23:48
a kobayasi wrote:
はじめまして。とても参考になりありがとうございました。初心者ですが、しつもんがあります。呼び出し先のファイルのhead部分に「考え方」のソースの先頭部分を「function dive(){」と変えて配置し、tab.int()のあとでdive()と書き、呼び出し元のファイルから、「なんちゃら.htm#page2」 でリンク呼び出ししたら、エラーもなく動いたみたいですが、このやり方で正しいのでしょうか。それとこれをwebsiteで使いたいのですが、使ってよろしいでしょうか。
以上、よろしくお願いします。 2009–03–27 01:15
Sig. wrote:
ども、はじめまして!
意図したとおりに動いたなら、とりあえず問題ないでしょう。
コードの改変・利用は自由です。どうぞ使い倒してやってください。
ま、コメントにでもURL書いて貰えたら嬉しいですけどね! 2009–03–28 04:00
jmondo wrote:
 始めまして。超初心者ですので勉強させていただいています。「他ページから直接タブにアクセスする」をダウンロードして色々ためしていたらタブで表示される部分にページ収まらない文章いれると、他のページからアクセスすると表示部分がスクロールされてしまい。タブが見えない状態なるのですが、これはどのようにすればタイトル、タブを表示するようにできるのでしょうか
わかりづらい文章で申し訳ありません。よろしくお願いします。 2009–07–06 20:29
Sig. wrote:
>jmondoさん

あーなるほど。
これはですね、スクリプトとしてはURLから「#」以後の文字列を取得してるだけで
スクロール自体はスクリプト起動前に「ページリンクとして」既にされているのです。
なので方法としては、

1. 「location.hash」でなく「location.search」で取得する
2. タブ展開後に別の関数を起動して任意の位置まで再びスクロールする

...の、いずれかになると思います。

前者の場合には「tab.dive」の2〜3行目を
var hash = window.location.search;
hash = hash.split("=");
...のようにした上で、「./tab-menu2.html?page=page5」のような呼び出し方になると思います。

後者の場合は「tab.dive」の最後にscroll()メソッドでも追加して任意の位置まで。
以下の記事が参考になるかと

http://archiva.jp/web/javascript/smooth_scroll.html 2009–07–06 22:51
jmondo wrote:
早々のご返事ありがとうございます。両方ともうまくいきませんでした。もう少し勉強してから再チャレンジしたいと思います。 2009–07–07 11:51
Sig. wrote:
少なくとも1番の方法で僕は動作検証済みなので、
巧くいかなかったとしたら他の部分だと思いますよー
Firebugのログをまめに見とくと良いでしょう。 2009–07–07 15:20
jmondo wrote:
本当に早いご返答に感謝一杯です。1番の方法でうまくいきました。よくわからずにやっていますので
hash = hash[0].split("#");を残したままでいました。
2番の方法でやったみましたら、一瞬設定位置にスクロールしますがまた元に戻ってしまいました。たぶんスクロールさせるタイミングが
悪いのだと思います。これからも時々のぞかせていただき勉強していきたいと思います。よろしくお願いします。 2009–07–08 00:48
gano wrote:
始めまして、javascript始めたばかりなので、内容見ても自分で改造できないので質問させていただきます。
他の人が質問されているようなのですが答えが

///////////////////////////////////////////////////////////////////////////
「http://sample.com/index.html#page1」内で
「#page2」へのリンクを押したときに「タブが展開しない」という意味であれば、
これは tab.div() の実行がページ読み込み時だからです。
ページ内リンクでは再読み込みしないので、手動で開いてやる必要がありますね。
///////////////////////////////////////////////////////////////////////////

どうやって内部リンクを再読み込みさせればよいのでしょうか? 2009–07–24 09:10
Sig.. wrote:
サンプルで tab.dive() は tab.init() の中で実行されており、
tab.init() はページ読み込み時に一回実行されているだけなので、
タブ内のリンクのクリックではJavascriptが実行されません。

「手動で開いてやる」てのは任意のリンクにonclickイベントを追加してやるとかで
「tab.dive() を動かしてやってください」という意味です。

これ以上は言いませんよ?
せめて理解する努力はしてください... 2009–07–28 02:31
gano wrote:
返答ありがとうございました。
ほんとに何もわからないのでヒントを頼りにいろいろやってみます。 2009–08–03 00:02
Sig.. wrote:
僕のスクリプトに関する説明は歓迎しますが、
きりがないので、コメント欄にてJavaScript初級講座をするつもりはありません。
もうちょい具体的な質問なら答えようがあります。
頑張ってください。 2009–08–03 13:52