Home suc IMadeIt
IMadeIt

Javascript & XMLによる静的HTMLサイトでパンくずリストの作り方:How to make breadcrumb lists in static HTML pages by the Javascript & XML.

suc - IMadeIt

2008年 2月 15日(金曜日) 00:00

静的サイトにもっと『パンくず』を!!

 

『パンくず』とは

『パンくず』とはページ上部に表示されるナビゲーションのための簡易なリンクリストです。簡素で目立たないなものですが、ナビゲーションとしては非常に有効で、サイト全体のナビゲーションに一貫性の無い、事業部乱立、サイト制作発注先バラバラの大型のサイトなどは、『パンくず』無しでは、まさに森で迷ったヘンゼルとグレーテル状態となってしまうでしょう。

『パンくず』は「履歴型」と「階層型」に分類できます。「履歴型」の代表例はwikiで見られ、自分が閲覧してきたページを表示するものです。
「階層型」は現在見ているページが、そのサイトでどの位置に属しているかを線形で表示するもので上位カテゴリへの参照による現在位置の把握が目的となります。
一般的なサイトでどちらが良いかという問題に関しては、筆者は「階層型」が良いと思っています。「履歴型」は単に自分の見たページの『履歴パンくず』であり、ナビゲーションとは言えないからです。
wikiは投稿者が自由に記事を投稿するシステム上、サイト構造はマトリックス型になり整理されたたサイト構造を構成するのが不可能です。そのため「階層型」の動的なナビゲーションを生成するには手間がかかるでしょう。また、“関連する記事の閲覧”といった目的から考えても『履歴パンくず』の方が合理的である言えます。
尚、『履歴パンくず』は比較的簡単にcookieによって静的サイトへも実装可能だと思います。

そこで今回、「階層型」の『パンくずリスト』をhtmlによる静的サイトへ実装する方法に関して考察しました。
 

概要

多くのCMSでは『パンくず』(breadcrumbsやpathwayとも言います)を自動で生成してくれます。
これは非常に便利で、ユーザビリティ的にもGOODなナビゲーションと考えられていますが、静的HTMLで構築したサイトでは手動(要するに各々のページに個別に打ち込むこと)で設定することが常となります。

このあたりを少しでも自動化できないものかと考えて、色々と探しまわったのですが、、結局、イメージに近い物は見当たりませんでした。
そこで作ったのがこのスクリプトです。
『パンくず』の自動生成はファイルをphpにして・・・などという方法も考えられますが、『パンくず』ごときにファイルをphpにするのも何なんで、、
また、各ファイルのメタタグ等に情報を持たせて、と言う方法も少し考えましたが、ファイル自身に絶対的な位置情報を依存するのはサイト構造の変更時などに手間が発生すると考えられましたので、今回はJavascriptとXMLファイルを利用しました。(少しでもオブジェクト的に・・)
作ると言った程のものでは無いのですが、この程度の物が欲しかったのです。

考え方もスクリプトも非常に単純ですが、サイトのディレクトリ構造に左右されない自由度をもっています。
完全な自動化ではありませんが、個人的な制作経験から考えると、この程度の手間と自由度のトレードオフは許容範囲ではないかと思っています。
また、自動化すればするほどディレクトリの構造やファイル名、コンテンツ内容の影響を受けるために自由な『パンくず』の記述が出来なくなるために諦めました。

考え方は簡単で、各フォルダに『パンくず』生成のための情報を持ったXMLファイルを設置して各ページ(HTML)で読み込んで、『パンくず』を生成するといったものです。

特長

  • 自由度が高い
    • サイトのディレクトリ構造に左右されない
      ・・と言っても、できれば一致させた方が解り易いと思いますし、インフォメーションアーキテクチャ的にも◎だと思います。
    • リストの記述が自由
    • リンクの設定が自由

欠点

  • 各フォルダにXMLファイルを設置する必要がある
    まぁ、10のセクション、各々が10個のフォルダによってサイト構築した場合、100のXMLファイルを設置する必要がありますが、こういったディレクトリ構造は個人的には細かすぎて問題ありと思っていますので。実際には8セクション+若干のフォルダ数で20以下のXMLファイルが平均的な量ではないかと思います。

 

コード

フォルダに設置するXMLファイル(例)

<breadcrumbs>
<pathway>
<path>http://itami.info/testroom/samplepathway/</path>
    <name>ホーム</name>
   </pathway>
   <pathway>
<path>http://itami.info/testroom/samplepathway/about/</path>
<name>会社情報</name>
    </pathway>
<pathway>
<path>http://itami.info/testroom/samplepathway/about/access/</path>
<name>アクセスマップ</name>
    </pathway>
</breadcrumbs>

 

各ページで読み込むJavascript

window.onload = function XmlPathway()
{

// XmlPathway v1.2 20080320 by itami.info http://itami.info/
// XmlPathway.js is freely distributable under the terms of an MIT-style license.

/** config *******************************************************************/
    var xmlid         = "pathway";                // set id
    var pathXmlFile     = "_bc.xml";                // set xml file name
    var separater         = " &#187; ";        // set character as separater
    var currentPhrase     = "";        // set phrase for current page <-- toggle excludePhrase
    var excludePhrase     = "";        // set exclude phrase for current page <-- toggle currentPhrase
/*****************************************************************************/
    var path,name,string   ="";

    if (document.implementation && document.implementation.createDocument){
        xml_doc = document.implementation.createDocument("", "", null);
    }else if (window.ActiveXObject){
         xml_doc = new ActiveXObject("Microsoft.XMLDOM");
    }else{
    }

    xml_doc.async = false;
    xml_doc.load(pathXmlFile);

    var pathways = xml_doc.getElementsByTagName("pathway");
    for (var i = 0; i < pathways.length; i++) {
        path = pathways[i].getElementsByTagName("path")[0].firstChild.nodeValue;
        name = pathways[i].getElementsByTagName("name")[0].firstChild.nodeValue;
        string += "<a class='path' href=' " + path +"'>"+ name + "</a>" + separater;
    }
    currentTitle = document.title;

    if (currentPhrase != ""){
        string += currentPhrase;
    }else if (excludePhrase != ""){
        string += currentTitle.replace(excludePhrase ,"");
    }else {
        string += currentTitle;
    }

    document.getElementById(xmlid).innerHTML = string;
}

 

サンプル

『パンくず』の必要の無いページではJavascriptへのリンクを外してください。

 

ダウンロード

ファイルはutf-8版です。他の文字コードで使用する場合はXMLファイルに日本語が含まれていますので、HTML、XMLの文字コードは統一して下さい。
 


スクリプトは最低限の手続きのみで組んでいます。IE6,IE7,FF2,Opera.NNで動作確認していますが、safariでは動作しません。ご意見、改良点など是非お聞かせ下さい。

 

過去のコメント

 

コメント一覧

itamiさんのコメント

.innerHTMLの使い方に問題があったので、修正しました。
(動作テストをDOCTYPE無しで行っていたので、DOCTYPE宣言を行った場合、FFで『パンくず』が表示されませんでした。)
それに伴い、使用するidをconfig部で指定できるように変更しました。
 

itamiさんのコメント

20080321追記
少し改良しました。
以下を設定しない場合はパンくずの終端にはタイトルが使用されます。
var currentPhraseとvar excludePhraseはどちらか一方の設定のみ可能です。

var currentPhrase = ""; // 現在のページとして使用する文字列を設定します。
var excludePhrase = ""; // タイトルから指定した文字列削除します。

● currentPhraseの設定について
『パンくず』の終端を指定した文字列に統一します。

例: 未設定
       ホーム >> 会社情報 >> アクセスマップ >> ○×株式会社_地図

例: excludePhraseに "このページ" を設定
       ホーム >> 会社情報 >> アクセスマップ >> このページ

● excludePhraseの設定について
XmlPathway.jsでは『パンくず』の終端にタイトルタグ内の文字を使用することを前提としていますが、タイトルタグはSEOや検索エンジンへのリスティングを考慮して『サイト名+ページタイトル』などの設定が多く見られます。
この場合、生成される『パンくず』に余分な文字列(例えばサイト名)などが含まれてしまいますが、excludePhraseで指定することによって特定の文字列を削除できます。

例: 未設定
       ホーム >> 会社情報 >> アクセスマップ >> ○×株式会社_地図

例: excludePhraseに "○×株式会社_" を設定
       ホーム >> 会社情報 >> アクセスマップ >> 地図
 

メガネ女子さんのコメント

はじめまして。
貴殿のサンプルを拝見させていただき、ぜひ私も利用させていただきたい!と思っていたところです。
が、自宅に戻り、Firefox3で同じサンプルを拝見したところ、パンくずのところがうまく動いていないようでした(ページ遷移はしますが、パンくずのところが真っ白状態)。

どうにか動かないかと、自分でもソースを眺めてみたのですがダメでした(泣)
どうしたらよいのでしょうか…教えてください。
 

itamiさんのコメント

メガネ女子さん、こんにちは。

おかしいですね、、こちらでWin Firefox3.0及び3.01での動作を確認しているのですが。。
メガネ女子さんのPC環境などをもう少しお教え頂けますか。
 

メガネ女子さんのコメント

大変失礼いたしました。
本日、改めて確認しましたところ、バッチリ表示されておりました。大変申し訳ございません、私の確認ミスでした…。スミマセン。

頑張ってこれをShift-JISでできないものか挑戦中です…。なかなかうまくゆかないものですね(涙)
 

itamiさんのコメント

Shift-JISを含め、文字コードの変換はTerapadなどのエディタで開いて、文字コードを指定して保存するだけでOKだと思います。
お試し下さい。
 

メガネ女子さんのコメント

え?!ホントですか??
何から何まですみません。こんな素人女に助言いただいて
ありがとうございます。
m(_ _;)m
 

itamiさんのコメント

すみません、言葉足らずでした。
フォルダに設置するXMLファイルは文字コードがutf以外の場合は、文頭でXML宣言が必要です。

例:Shift_JISの場合
<?xml version='1.0' encoding='Shift_JIS'?>
 
 

隠しログインフォームの設定 by Dreamweaver

suc - IMadeIt

2007年 12月 15日(土曜日) 00:00

動作デモ

以下で紹介されている場所と同じ場所に設定していますので、ダブルクリックしてご確認下さい。

ダウンロード

設定方法
「メインの目次」、「個別のアイテム」などスキン編集により、mod_loginform.incは<%parsedinclude(mod_login.inc)%>として<body>直下に読み込みます。
loginbox.cssとloginbox.jsはヘッダ内でリンクします。
 

隠しログインフォームの設定

 Nucleusのブログでは管理領域へのログインフォームを常に表示している場合も多いのですが、企業サイトなどではログインフォームを常に表示する必要性はありません。
 不要なものを隠すことによって、サイトナビゲーションなどユーザビリティも向上し、少しばかりのセキュリティアップへもつながります。
 ページ上に表示されているログインフォームは、通常サイドバーにスキン変数<%loginform%>として記述されていますのでこの記述を削除すれば簡単に表示を消すことは可能です。しかしこの記述を削除した場合、ログインは/nucleusディレクトリにアクセスする必要が発生し、若干手間のかかるログイン方法となります。また、ページ面から該当記事を直接編集するといった便利さも失われてしまいます。
 そこで「Company」ではDreamweaverのビヘイビアに用意されている「エレメントの表示-非表示」を利用することによって、通常はログインフォームを隠しながら、隠しエリアをダブルクリックすることによって表示させる方法をとります。
 設定は他のスキンや将来的にも再利用可能なように読込ファイルとして作成します。

ログインフォームの表示と非表示の構造

  1. ログインのためのフォームが配置されているloginboxは不可視設定し、callLoginBox領域をダブルクリックすることによって表示される。
  2. loginbox内でダブルクリックしたらloginboxは閉じる。

 

設定の手順

以下はDreamweaverによる設定の手順を参考までに紹介しています。興味のある方はご覧下さい。
 

1)
 HTMLの構造は以下のとおりです。このHTMLを<body>タグの直下に配置します。

 


<div id="callLoginBox"></div>   
<div id="loginbox">
<dl>
<dt>Login</dt>
<dd><%loginform%></dd>
</dl>
</div>

2)
 CSSによりcallLoginBoxを設定します。最終的には非表示にしますが、設定中は場所や大きさを把握するために背景色を与えています。場所はposition: absolute;で絶対指定します。
 Dreamweaverであればマウスドラッグによる場所の移動も可能ですので、自分には覚え易く他の人には推測し難い場所を設定して下さい。


左に赤く見えるのが#callLoginBoxの設定です。


プロパティインスペクタの設定


設定したCSS


#callLoginBox {
    position: absolute;
    width: 20px;
    height: 20px;
    left: 0px;
    top: 120px;
    background-color: #CC0000; /*見えるように色付けしています。最終的には削除します*/
}

3)
CSSによりloginboxを設定します。場所はposition: absolute;で絶対指定しますが、z-indexは2を与え、表示された場合はcallLoginBoxよりも手前に配置されるように設定して初期値で非表示に設定します。


#loginboxの設定


プロパティインスペクタの設定


設定したCSS

#loginbox {
    position: absolute;
    z-index: 2;
    overflow: auto;
    visibility: hidden;
    top: 69px;
    left: -3px;
    border: 3px dotted #000000;
    padding: 15px;
    background-color: #33CC66;
}

4)
callLoginBoxに対するビヘイビアの設定
 HTMLソースからcallLoginBoxを選択し、ビヘイビアの「+」アイコンを押してドロップダウンリストから「エレメントの表示-非表示」を選びます。

ドロップダウンリスト
 

ダイアログボックスのエレメントにloginboxを選び、設定を「表示」にしてOKボタンを押します。

エレメントの表示-非表示ポップアップ
 

ビヘイビアパレットのイベントはonDblClickに変更します。これでcallLoginBoxをダブルクリックするとloginboxが表示されます。

ビヘイビアパレット
 

5)
 loginboxに対するビヘイビアの設定
 HTMLソースからloginboxを選択し、ビヘイビアの「+」アイコンを押してドロップダウンリストから「エレメントの表示-非表示」を選びます。

ドロップダウンリスト
 

ダイアログボックスのエレメントにloginboxを選び設定を「非表示」にしてOKボタンを押します。

エレメントの表示-非表示ポップアップ

 

ビヘイビアパレットのイベントはonDblClickに変更します。これでloginboxをダブルクリックするとloginboxが非表示になります。

ビヘイビアパレット
 

※callLoginBox、loginbox共イベントにダブルクリックを指定しているのは不用意なクリックによってフォームの表示/非表示が発生しないためです。
※Dreamweaverのバージョンなどによって手順や生成されるスクリプトに違いがあるかも知れませんのでご注意下さい。

完成した隠しログインフォームのモジュール化
 Dreamweaverのビヘイビアによって書き込まれた部分を切り出してmod_loginform.incとして保存します。また、動作に必要なjavascriptは<head>タグ内に記述されていますので、こちらも外部ファイルとして保存し、リンク使用します。


ビヘイビア設定後のHTMLコード


<div id="callLoginBox" ondblclick="MM_showHideLayers('loginbox','','show')"></div>   
<div id="loginbox" ondblclick="MM_showHideLayers('loginbox','','hide')">
<dl>
<dt>Login</dt>
<dd><%loginform%></dd>
</dl>
</div>

 


記述されたJavascript

// JavaScript Document
function MM_showHideLayers() { //v9.0
  var i,p,v,obj,args=MM_showHideLayers.arguments;
  for (i=0; i<(args.length-2); i+=3)
  with (document) if (getElementById && ((obj=getElementById(args[i]))!=null)) { v=args[i+2];
    if (obj.style) { obj=obj.style; v=(v=='show')?'visible':(v=='hide')?'hidden':v; }
    obj.visibility=v; }
}


mod_loginform.incは<%parsedinclude(mod_login.inc)%>として<body>直下に読み込みます。
loginbox.cssはヘッダ内でリンクします。
Javascriptはloginbox.jsとして保存し、こちらもヘッダ内でリンクします。
「メニュー」> 「挿入」> 「HTML」> 「スクリプトオブジェクト」> 「スクリプト」でJavascriptのリンクでリンク設定が可能です。


不可視の領域をダブルクリックすることによってログインフォームが現れます