< window.onload を待たずに処理を開始する | CScript.exe で実行したいスクリプト >

January 6, 2010

続、目次フレームを自動生成する

あと、目次フレームを自動生成するの toc.js の諸々を修正しました。主な修正点はオブジェクトメンバの実装をリテラル記法にして見やすくしたのと、自動生成される ID の番号の階層がおかしかった点を改善しました。

あと、汎用性を考慮して初期化ハンドラを自動で登録しないようにしたのでwindow.onload を待たずに処理を開始するを使ってもいいかも。

<script type="text/javascript" src="loadlistener.js"></script>
<script type="text/javascript" src="toc.js"></script>
<script type="text/javascript">//<![CDATA[
    LoadListener.onload = function () { toc.create(); };
//]]></script>
var toc = function ()
{

    //
    // Node クラス
    //

    // コンストラクタ
    function Node (element, level, idprefix, sindex)
    {
        this.element = element;
        this.level = level;
        this.idprefix = idprefix;
        this.sindex = sindex;
        this.firstChild = null;
        this.nextSibling = null;

        if (element && !element.id)
            element.id = this.idprefix + "-" + this.sindex;
    }

    //
    // Node クラスの実装
    //

    // 子要素追加
    Node.prototype = {
        append: function (element, level)
            {
                if (this.nextSibling != null)
                {
                    this.nextSibling.append (element, level);
                    return;
                }
                var childId = this.idprefix;
                if (this.level > 0)
                    childId += "-" + this.sindex;

                switch (level - this.level)
                {
                case 0:
                    this.nextSibling = new Node (element, level, this.idprefix, this.sindex + 1);
                    break;

                case 1:
                    if (this.firstChild == null)
                        this.firstChild = new Node (element, level, childId, toc.baseIndex);
                    else
                        this.firstChild.append (element, level);
                    break;

                default:
                    if (this.firstChild == null)
                        this.firstChild = new Node (null, this.level + 1, childId, toc.baseIndex);
                    this.firstChild.append (element, level);
                    break;

                }
            },

        // 目次を作成する
        createIndex: function (listTagName)
            {
                var li = document.createElement ("li");
                if (this.element != null)
                {
                    var ancher = document.createElement ("a");
                    ancher.setAttribute ("href", "#" + this.element.id);
                    var text = document.createTextNode (this.element.textContent || this.element.innerText);
                    ancher.appendChild (text);
                    li.appendChild (ancher);
                }
                if (this.firstChild)
                {
                    var list = document.createElement (listTagName);
                    var node = this.firstChild;
                    while (node != null)
                    {
                        list.appendChild (node.createIndex (listTagName));
                        node = node.nextSibling;
                    }
                    li.appendChild (list);
                }
                return li;
            }
        };

    //
    // toc のプライベートメソッド
    //

    // 要素を走査して木構造を作る
    var scanElements = function (idprefix)
        {
            var elements = document.getElementsByTagName ("*");
            var root = new Node (null, 0, idprefix, 0);
            for (var i = 0; i < elements.length; i ++)
            {
                var element = elements [i];
                if (element.nodeName.match (/^h([1-9])$/i))
                {
                    var number = RegExp.$1 - 0;
                    root.append (element, number);
                }
            }
            return root;
        };

    // 木構造から目次を作る
    var createIndex = function (root, listTagName)
        {
            var list = document.createElement (listTagName);
            var node = root.firstChild;
            while (node != null)
            {
                list.appendChild (node.createIndex (listTagName));
                node = node.nextSibling;
            }
            return list;
        };

    //
    // toc オブジェクトを返す
    //
    
    return {
        listtag: "ul",
        tocId: "toc",
        defaultIdPrefix: "hedding",
        baseIndex: 1,

        create: function ()
            {
                var root = scanElements (this.defaultIdPrefix);
                var tocelem = document.createElement ("div");
                tocelem.id = this.tocId;
                tocelem.appendChild (createIndex (root, this.listtag));
                document.body.appendChild (tocelem);
            }
        }
} ();

トラックバック

このエントリーにトラックバック:
http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/2473

コメント

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?