YUI を使ったアコーディオンメニュー

YUI を使ってアコーディオンメニューを実装するサンプルはいくつかあるけど、どうやってるのか知りたかったので自分でも作ってみた。

参考までに、最近見つけたものをいくつか。

どんなことをするか

  • ページを読み込んだ時に、アコーディオンのコンテンツを隠す
  • メニューをクリックした時にアコーディオンのコンテンツを表示する (開いてれば閉じる)

使い方

  • Yahoo UI Library の YAHOO, Dom, Event, Animation ユーティリティが必要
  • 対象となるコンテンツ全体を ‘accordion’ という class 名のタグで囲む
  • メニューのラベルは ‘ac-label’ という class 名と、ユニークな id を付ける
  • アコーディオンのコンテンツは ‘ac-content’ という class 名にし、id はラベルの id プラス ’-conent’ にする
  • ac-content には ‘overflow: hidden;’ というスタイルを適用する
  • 対象となるコンテンツの親となるエレメントの id を引数にして、関数を実行する

HTML

<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8 />
    <title>Accordion Widget</title>
    <style type="text/css">
    .ac-content {
        overflow: hidden;
    }
    </style>
</head>
<body id="bd">
<div class="accordion">
    <h2 id="accordion1" class="ac-label">Accordion 1</h2>
    <p id="accordion1-content" class="ac-content">
    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus
    </p>

    <h2 id="accordion2" class="ac-label">Accordion 2</h2>
    <p id="accordion2-content" class="ac-content">
    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus
    </p>
</div>

<!-- Combo-handled YUI JS files: -->
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.8.0r4/build/yahoo-dom-event/yahoo-dom-event.js&2.8.0r4/build/animation/animation-min.js"></script>
<script type="text/javascript" src="yui-accordion.js"></script>
<script type="text/javascript">
//<![CDATA[
YAHOO.util.Event.onDOMReady(
    var logger    = new YAHOO.widget.LogReader(null, {
        height: "20em",
        width:  "20em",
        top:    "0px",
        right:  "0px"
    });

    var myWidget  = YAHOO.myWidget;
    var accordion = myWidget.accordion("bd");
});
//]]>
</script>

</body>
</html>

yui-accordion.js

YAHOO.namespace("myWidget");

/**
 * accordion widget
 * @require yahoo, dom, event, animation, logger (optional)
 * @param  {string} RootNodeId of accordion object
 * @return {object} Accordion object
 */
YAHOO.myWidget.accordion = function(sRootNodeId){
    var Anim  = YAHOO.util.Anim,
        Dom   = YAHOO.util.Dom,
        Event = YAHOO.util.Event;

    var aAccordionEl = Dom.getElementsByClassName("accordion", "div", sRootNodeId);
    YAHOO.log(aAccordionEl.length + " accordion elements found");

    /**
     * toggle accordion menu
     * @param {object} Event (click)
     * @param {string} AccordionId (of the element)
     */
    var toggle = function(oEvent, sAccordionId){
        YAHOO.log("toggle function called for '" + this.firstChild.data + "' with [" + oEvent + ", " + sAccordionId + "]");

        if ( oAccordion[sAccordionId]["state"] === "expanded" ) {
            collapse(sAccordionId);

        } else if ( oAccordion[sAccordionId]["state"] === "collapsed" ) {
            expand(sAccordionId);
        }
    };

    /**
     * expand accordion contents
     * @param {string} AccordionId
     */
    var expand = function(sAccordionId){
        YAHOO.log("expand accordion contents of " + sAccordionId);
        oAccordion[sAccordionId]["expand"].animate();
        oAccordion[sAccordionId]["state"] = "expanded";
    };

    /**
     * collapse accordion contents
     * @param {string} AccordionId
     */
    var collapse = function(sAccordionId){
        YAHOO.log("collapse accordion contents of " + sAccordionId);
        oAccordion[sAccordionId]["collapse"].animate();
        oAccordion[sAccordionId]["state"] = "collapsed";
    };

    var oAccordion = {};
    for (var i=0, l=aAccordionEl.length; i<l; i++) {
        var aAcLabelEl = Dom.getElementsByClassName("ac-label", null, aAccordionEl[i]);

        for (var j=0, len=aAcLabelEl.length; j<len; j++) {
            var oAcLabel        = aAcLabelEl[j];
            var sAcId           = oAcLabel.id;
            var sAcContentId    = sAcId + "-content";
            var oAcContent      = document.getElementById(sAcContentId);

            // define animation
            var oAcAnimExpand   = new YAHOO.util.Anim(sAcContentId, {
                height: {
                    from: 0,
                    to: oAcContent.offsetHeight
                }
            }, 0.25, YAHOO.util.Easing.easeOut);
            var oAcAnimCollapse = new YAHOO.util.Anim(sAcContentId, {
                height: { to: 0 }
            }, 0.25, YAHOO.util.Easing.easeOut);

            oAccordion[sAcId] = {
                "content":  oAcContent,
                "expand":   oAcAnimExpand,
                "collapse": oAcAnimCollapse
            };

            Event.addListener(oAcLabel, "click", toggle, sAcId);
            YAHOO.log("click event is assigned to accordion #" + (j+1) + ": " + oAcLabel);
            collapse(sAcId); // close accordion contents
        }
    }

    return oAccordion;
};
Advertisements
YUI を使ったアコーディオンメニュー

Accordion menu with YUI

There are some according widget with YUI, but I created very simple accordion menu widget
for myself to know how to implement it with YUI.

For your reference, I list some accordion widgets that I found laterly.

What’s the script doing

  • When a page load, it collapses accordion contents.
  • When you click a label of accordion, it expands its content (collapse if it’s expanded.)

How to use

  • It requires YAHOO, Dom, Event and Animation utility of Yahoo UI Library.
  • You need to wrap target contents with class name ‘accordion’.
  • Label of accordion must have class name ‘ac-label’ and its own id.
  • Accordion contents must have class name ‘ac-content’ and the id must be id of ac-label + ’-content’.
  • You need to specify css ‘overflow: hidden;’ to ac-content.
  • Execute the function with root node id. It look for target elements under the specified node.

HTML

<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8 />
    <title>Accordion Widget</title>
    <style type="text/css">
    .ac-content {
        overflow: hidden;
    }
    </style>
</head>
<body id="bd">
<div class="accordion">
    <h2 id="accordion1" class="ac-label">Accordion 1</h2>
    <p id="accordion1-content" class="ac-content">
    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus
    </p>

    <h2 id="accordion2" class="ac-label">Accordion 2</h2>
    <p id="accordion2-content" class="ac-content">
    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus
    </p>
</div>

<!-- Combo-handled YUI JS files: -->
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.8.0r4/build/yahoo-dom-event/yahoo-dom-event.js&2.8.0r4/build/animation/animation-min.js"></script>
<script type="text/javascript" src="yui-accordion.js"></script>
<script type="text/javascript">
//<![CDATA[
YAHOO.util.Event.onDOMReady(
    var logger    = new YAHOO.widget.LogReader(null, {
        height: "20em",
        width:  "20em",
        top:    "0px",
        right:  "0px"
    });

    var myWidget  = YAHOO.myWidget;
    var accordion = myWidget.accordion("bd");
});
//]]>
</script>

</body>
</html>

yui-accordion.js

YAHOO.namespace("myWidget");

/**
 * accordion widget
 * @require yahoo, dom, event, animation, logger (optional)
 * @param  {string} RootNodeId of accordion object
 * @return {object} Accordion object
 */
YAHOO.myWidget.accordion = function(sRootNodeId){
    var Anim  = YAHOO.util.Anim,
        Dom   = YAHOO.util.Dom,
        Event = YAHOO.util.Event;

    var aAccordionEl = Dom.getElementsByClassName("accordion", "div", sRootNodeId);
    YAHOO.log(aAccordionEl.length + " accordion elements found");

    /**
     * toggle accordion menu
     * @param {object} Event (click)
     * @param {string} AccordionId (of the element)
     */
    var toggle = function(oEvent, sAccordionId){
        YAHOO.log("toggle function called for '" + this.firstChild.data + "' with [" + oEvent + ", " + sAccordionId + "]");

        if ( oAccordion[sAccordionId]["state"] === "expanded" ) {
            collapse(sAccordionId);

        } else if ( oAccordion[sAccordionId]["state"] === "collapsed" ) {
            expand(sAccordionId);
        }
    };

    /**
     * expand accordion contents
     * @param {string} AccordionId
     */
    var expand = function(sAccordionId){
        YAHOO.log("expand accordion contents of " + sAccordionId);
        oAccordion[sAccordionId]["expand"].animate();
        oAccordion[sAccordionId]["state"] = "expanded";
    };

    /**
     * collapse accordion contents
     * @param {string} AccordionId
     */
    var collapse = function(sAccordionId){
        YAHOO.log("collapse accordion contents of " + sAccordionId);
        oAccordion[sAccordionId]["collapse"].animate();
        oAccordion[sAccordionId]["state"] = "collapsed";
    };

    var oAccordion = {};
    for (var i=0, l=aAccordionEl.length; i<l; i++) {
        var aAcLabelEl = Dom.getElementsByClassName("ac-label", null, aAccordionEl[i]);

        for (var j=0, len=aAcLabelEl.length; j<len; j++) {
            var oAcLabel        = aAcLabelEl[j];
            var sAcId           = oAcLabel.id;
            var sAcContentId    = sAcId + "-content";
            var oAcContent      = document.getElementById(sAcContentId);

            // define animation
            var oAcAnimExpand   = new YAHOO.util.Anim(sAcContentId, {
                height: { 
                    from: 0, 
                    to: oAcContent.offsetHeight
                }
            }, 0.25, YAHOO.util.Easing.easeOut);
            var oAcAnimCollapse = new YAHOO.util.Anim(sAcContentId, {
                height: { to: 0 }
            }, 0.25, YAHOO.util.Easing.easeOut);

            oAccordion[sAcId] = {
                "content":  oAcContent,
                "expand":   oAcAnimExpand,
                "collapse": oAcAnimCollapse
            };

            Event.addListener(oAcLabel, "click", toggle, sAcId);
            YAHOO.log("click event is assigned to accordion #" + (j+1) + ": " + oAcLabel);
            collapse(sAcId); // close accordion contents
        }
    }

    return oAccordion;
};
Accordion menu with YUI