jQueryによる共通部品の読み込みとNavbarのアクティブ項目の変更

前の記事に引き続き、ビジュアル情報処理研究合宿のHPで使用したネタを書いていきたいと思います(たぶん、コレで最後)。

jQueryによる共通部品の読み込み

ヘッダーやフッター、メニューバーなどの共通部品を1つのページごとに実装することは保守管理の面であまりよい状態ではありません。

先輩によると昨年度のページではSSIを用いて共通部品を読み込んでいたそうですが、今年度はBootstrapに関連して全編JavaScriptもしくはjQueryでこれらを実現しようと思いました。とは言っても、やり方はめちゃくちゃ簡単です。

まず、共通部品を格納するブロック要素にidを割り当てます。

次に、この部分に挿入したいHTMLを別ファイルで作成しておきます。このファイルをjQuery側で開き、HTML上の指定idに対して読み込みます。

この1行だけで、当該id部分に別ファイルのHTMLが読み込まれるため、ヘッダーやフッターを1ファイルにしておけば、あとは適当な場所で読み込むだけで全て共通の内容でレンダリングされることとなります。簡単ですね!

ただし、ローカルファイルからの読み込みはChromeではクロスドメイン制限などによって実行されないため、起動オプション指定によってこれを解除するか、デバッグには他のブラウザを使用する必要があることに注意が必要です。

Navbarのアクティブ項目をページごとに切り替えたい

一方で、メニューは共通だけど先の記事におけるNavbarのように「アクティブにしたい項目がページごとに異なる」場合、共通部品の読み込みだけでは対応できません。何らかの形でアクティブにする項目を指定し、HTMLを変更する必要があります。

このため、今回のページ作成ではメニューバーの項目を動的に追加し、HTML側のdata属性で指定された項目をアクティブにしてリンク先を#に変更する処理を行うことで、部品自体を共通化しながらフレキシブルにアクティブ項目の変更を実現しています。

まず、HTMLのNavbar側にdata属性を追加しておきます。ここではdata-activeを指定し、activeで指定されたメニュー項目をアクティブにすることとします。

次に、Navbarのテンプレートファイルを先ほどと同じように読み込みます。この時、読み込み自体は先程と同じですが、読み込み完了後にNavbarの各項目を追加する関数(generateNavbar)を実行するようにハンドラを指定します。

また、この時のmenu.htmlを以下に示します。

ここで、NavbarContentに対して各liコンテンツを追加していきます。追加を行うのが先に指定したgenerateNavbar関数になります。

ここでは、各項目のクラス要素名(Type)、リンク名(Anchor)、リンク先(Href)をデータ構造として定義し、配列化します。配列化したデータをリンクにして追加していきますが、この時にHTML側で指定されたdata-activeの値と配列要素のインデックスが一致する場所のクラス要素をactive指定し、リンク先も#に変更しています。

これによって、配列要素のインデックスは既知である必要はありますがHTML側でdata要素を指定するだけでNavbarを共通化しながらも変更したい部分をすっきりと指定し変更することが可能となります。実際の挙動はこちらからご確認ください。

Bootstrap 3で等幅ナビゲーションバー(Navbar Justified)を実現する

背景

先月からビジュアル情報処理研究合宿のHPを作っていたのですが(完成版ページ)、最初にページデザインをお願いした後輩から上がってきたデザイン案では「ナビゲーションバーを幅いっぱいにして各項目を等幅で実装し、スマホ版では縦並びにする」ような形になっていました。

私のようなホリデーWebエンジニア(口悪く言えば「にわか」)は「とりあえずBootstrapあたりのコンポーネントライブラリを使ってサクッと出来るっしょ~www」的な希望的観測で実装していたのですが、いざNavbarを作って確認してみると…あれ?動かないぞ、と。

これのキモは、ナビゲーションバーの各li項目をulの幅いっぱいにして各項目の幅が同じになるようにulのクラス要素にnav-justified指定をする点。これを入れることで、デザイン案のようなナビゲーションバーができる、はずだった。

動きを見ると……なんだこのゴミ。等幅どころか画像載せる気力なくすぐらい崩れてやがる。

とりあえず、Bootstrapのガイドラインを見てみる。

Justified navbar nav links are currently not supported.

ファーwwwwwwwww

さーて、どうしてくれようか。

よく読むと、同じナビゲーションバーでもtabsとかpillsにすればjustifiedにはできるらしいことが分かり、とりあえず指定してみたけど、今度は配色をカスタムしたことが災いしてリンクテキストが読めない。これは弱った。どうしよう。

と思いながらとりあえずググッてみると、やっぱりハマってる人は多かったらしく、StackOverflowがすぐに引っかかった。ひとまず、floatを解除してやればいいみたいなので、自己定義CSSファイルに以下のような指定を追加。

とりあえずこれで等幅メニューにはなった。

無題

諸々の修正&dividerもどきの付加

でもこの状態でNavbar-Brandは邪魔だし、デザインで指定されている区切り(divider)が無い。それに、画面サイズが中途半端な時に2行に渡るようなli要素があるとactive指定したリンクが浮いたり、スマホ版メニューでも何故か左に寄っていたり。

無題

無題

2行になる時の対策がどうあがいても上手く行かなかったので、とりあえず「992px(col-md)」をメニュー切り替えのタイミングにすることと、モバイル版とデスクトップ版でボーダー指定を切り替えることで対応することに。さらに追記したCSSが以下の様な感じ。

最後のIE対策は、Chromeなどでは問題なかったんだけど1200pxら辺でテキストが2行になる問題がまた発生したので、とりあえずこの時はナビゲーションバーを折りたたまずにリンクテキストのフォントサイズを少し下げることで対応する形にしました。

その他は、デスクトップ版とモバイル版でNavbar-Brandの表示を切り替えたり、ボーダーの向きを変更するような指定を追加しています。モバイル版ではliをテーブル扱いにすることで、左に寄ったり項目が浮くような問題をクリアしています(ぶっちゃけ、汚いやり方な気がしますが)。

最後にvariables.lessでナビゲーションバーが折りたたまれるタイミングをscreen-md-minに変更し、完了です。

実際にご覧ください(トリビアの紹介風に)

そして出来たNavbarがこちら。
フルサイズ版
無題ちょっと小さい版無題モバイル版
無題

とりあえず、Bootstrap3でもJustifiedで、かつちゃんとボーダーが付いてレスポンシブなナビゲーションバーが作れましたとさ。めでたしめでたし。