LoginSignup
5
2

More than 3 years have passed since last update.

同じファイルでページをタブ化する(リロードしても直前の状態保持)

Posted at

概要

  • 登録されているデータをリスト表示する必要があった
  • 権限は管理者と一般で分かれているのに同じページで表示
  • スパゲティコードをほぐすと時間がかかるためその状態で管理者と一般をタブで分けたかった
  • タブ1,タブ2とある場合、タブ2でリロードするとタブ1に戻る
  • localStorageを使ってページ状態を保持するようにした
  • そのままでは一瞬だけタブ1が表示されるのでdisplay: none;にした

お詫び

  • タブ化の情報はたくさんあったのですがリロード後も同じタブを表示したり、一瞬でも直前のタブを表示しない状態にする情報が無かったので書いてみました
  • このためコードが入り乱れているので汚いです、ご了承ください

ポイント

  • タブ情報の保存にlocalStorageを使う
  • spliceを使って不要な情報の削除
  • diplay: none;を使って擬似的にそのタブがリロードされたように見せかける

HTML

<!-- タブそのもの -->
<ul id="tabs">
  <li><a href="#tab=tabs1" id="tabs1" name="tab1">管理者</a></li>  
  <li><a href="#tab=tabs2" id="tabs2" name="tab2">一般</a></li>
</ul>
<!-- 以下は各タブのコンテンツ -->
<div id="tabContent">
  <div id="tab1">
    hogehoge
  </div>
  <div id="tab2">
    hogehoge2
  </div>
</div>

css

  • タブにマウスカーソルonで色が変わるようにしている
  • アクティブ状態(選択された状態)だと色が変わるようにしている
  • 例えばtab1の状態からtab2をクリックするとtab2が色が濃くなり、tab1は薄くなる
#tabs {
  list-style-type: none; 
  padding-left: 0px;
  margin-bottom: 0px;
  height: 30px;
  overflow: hidden;
  width: 100%;
}

#tabs li {
  float: left;
}

#tabs a {
  position: relative;
  float: left;
  background: #c9f3c6;
  color: #000000;
  height: 25px;
  width: 200px;
  margin-right: 5px;
  padding-top: 5px;
  text-align: center;
  font-weight: bold;
  line-height: 25px;
  margin-bottom: 0px;
  text-decoration: none;
}

#tabs a.current {
  background: #0fb800;
  color: #ffffff;
}

#tabs a:hover,
#tabs a:hover::after,
#tabs a:focus,
#tabs a:focus::after {
  background: #0fb800;
  color: #ffffff;
}

#tabContent {
  position: relative;
  z-index: 2;
}

#tab1 {
  display: none;
}

#tab2 {
  display: none;
}

JavaScript(JQuery)


// 選択されたtabを取得する関数(hrefの=以降を取得->tabs1, tab2)
function parseHashBangArgs(aURL) {
  var tab = aURL.slice(aURL.indexOf('=') + 1);
  return tab;
}

// 今回は2タブだったので配列の内容を決め打ち
// 表示、非表示のコンテンツを決めるのに使う
function createTabsArray() {
  var tabs = ['#tab1', '#tab2'];
  return tabs;
}

// 選択「前」のタブ情報を非表示化するのに必要
// 例えば現在がtab1で遷移後がtab2の場合、tab2をクリックしたらtab1を消すということを実現したい
// tab2を選択した瞬間、tab2の情報が上記の配列から消えるので#tab1が残る。この#tab1に対してfadeOut()をかけることで不要なタブ情報を瞬時に非表示化できる
function switchContent(selectedConte) {
  var tabs = createTabsArray();
  var tab = '#' + selectedConte;
  for (i=0; i<tabs.length; i++) {  //delete not current content
    if (tabs[i] == tab ) {
      tabs.splice(i, 1);
    }
  }
  return tabs;
}


// リロード時
$(function() {
  // リロード前に保存されたタブIDを取得(初回アクセス時は未保存なので2つのタブともに選択されていない状態)
  var currentTab = localStorage.getItem('current');
  if (currentTab) {
    // 毎回リロード時に選択されているとするclassのcurrentを削除しlocalStorageの情報を元に再付与している(ちょっと非効率かも)
    $('li a').removeClass('current');
    var tabli = currentTab.replace(/tab/, 'tabs');
    $('#' + tabli).addClass('current');
    var tabs = switchContent(currentTab);
    // currentクラスを持つコンテンツは表示、そうじゃないのは非表示にしている
    // fadeを使う理由は無いので表示時間を0にするならshowを使えば良いかも知れない
    $('#tabContent' + ' ' + '#' + currentTab).fadeIn(0);
    $('#tabContent' + ' ' + tabs).fadeOut(0);
  } else {
    $('#tabContent' + ' ' + '#tab1').fadeIn(0);
  }
});

// タブのクリック時
// タブを選択すると選択したタブのhrefからどのタブが選択されたかを取得
// リロード同様に一度すべての選択状態を解除してから再付与
// 最後にlocalStorageに選択したタブの情報を保存
$('#tabs li a').click(function() {
  delMsg();
  var url = $(this).attr('href');
  var selectedTab = parseHashBangArgs(url);
  var selectedConte = selectedTab.replace(/tabs/, 'tab');
  if (selectedTab) {
    $('li a').removeClass('current');
    $('#' + selectedTab).addClass('current');
    var tabs = switchContent(selectedConte);
    $('#tabContent' + ' ' + '#' + selectedConte).fadeIn(0);
    $('#tabContent' + ' ' + tabs).fadeOut(0);
    localStorage.setItem('current', selectedConte);
  }
});
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2