是否有更简单的方法来制作这个可扩展的菜单?

时间:2014-04-13 13:39:41

标签: javascript html css

我想制作一个可扩展的菜单,包含三个或更多项目。单击其中一个项目时,它会展开以显示<ul>下面的display: hidden。 此外,我希望它的工作方式是,如果该菜单上的某个项目已经展开,如果我点击任何其他一个项目,它会在展开第二个项目之前收回第一个项目的内容(一个点击了。)

我的代码是this。我必须为我在那里的三个项目中的每个项目定义一个不同的toggle函数,再加上一个额外的switchAll函数来隐藏任何展开的项目,然后再继续展开一个新项目。

但是,这种解决方案似乎并不是最好的 是不是有更好的方法来定义一个可以处理所有这三个项目的函数?为此,我需要它来获取之前点击的项目,以便它可以了解哪些项目是否被扩展,以及相应采取的行动。
我猜这只能用两个函数完成,但我似乎无法弄清楚如何做到这一点。

另外,我想用Javascript实现这一点,而不是jQuery。

相关代码如下:

HTML:

<ul>
    <li><a href="#" onclick="toggle();">one</a>
        <ul id="menu">
            <li>sacd</li>
            <li>safsdf</li>
        </ul>
    </li>
    <li><a href="#" onclick="toggle1();">two</a>
        <ul id="menu2">
            <li>jlkfd</li>
            <li>ljsdf</li>
        </ul>
    </li>
        <li><a href="#" onclick="toggle2();">three</a>
        <ul id="menu3">
            <li>sfsdvbg gb</li>
            <li>asdavffds</li>
        </ul>
    </li>
</ul>

CSS:

#menu {
    display: none;
}

#menu2 {
    display : none;
}

#menu3 {
    display : none;
}

JS:

var hidden = true;
var hidden2 = true;
var hidden3 = true;

function switchAll(other1, other2) {
    other1.style.display = "none";
    other2.style.display = "none";
    hidden = true;
    hidden2 = true;
    hidden3 = true;
};

function toggle() {
    var menu = document.getElementById("menu");
    var menu2 = document.getElementById("menu2");
    var menu3 = document.getElementById("menu3");
    if(hidden) {
        switchAll(menu2, menu3);
        menu.style.display = "block";
        hidden = false;
    } else {
        menu.style.display = "none";
        hidden = true;
    };
};

function toggle1() {
    var menu = document.getElementById("menu");
    var menu2 = document.getElementById("menu2");
    var menu3 = document.getElementById("menu3");
    if(hidden2) {
        switchAll(menu, menu3);
        menu2.style.display = "block";
        hidden2 = false;
     } else {
        menu2.style.display = "none";
        hidden2 = true;
    };
};

function toggle2() {
    var menu = document.getElementById("menu");
    var menu2 = document.getElementById("menu2");
    var menu3 = document.getElementById("menu3");
    if(hidden3) {
        switchAll(menu, menu2);
        menu3.style.display = "block";
        hidden3 = false;
    } else {
        menu3.style.display = "none";
        hidden3 = true;
    };
};

4 个答案:

答案 0 :(得分:3)

如果我的第一个答案是复杂的,这里只是一个没有动画的css替代品。 JS。

<强> HTML

<ul class="box">
    <li id="a"><a href="#a">one</a>
        <ul>
            <li>sacd</li>
            <li>safsdf</li>
        </ul>
    </li>
    <li id="b"><a href="#b">two</a>
        <ul>
            <li>jlkfd</li>
            <li>ljsdf</li>
        </ul>
    </li>
    <li id="c"><a href="#c">three</a>
        <ul>
            <li>sfsdvbg gb</li>
            <li>asdavffds</li>
        </ul>
    </li>
</ul>

<强> CSS

.box>li>ul{
 display: none;
}
.box>li:target>ul{
 display:block;
}

<强>样本

http://jsfiddle.net/vvLu2/

没有javascript ...

答案 1 :(得分:1)

将当前展开的项目存储在变量中。

var current = null;
function toggle(element) {
    if(current === null) {
        // Show 'element'
        current = element;
    }
    else if(element === current) {
        // Hide 'current'
        current = null;
    }
    else {
        // Show 'element' and hide 'current'
        current = element;
    }
}

答案 2 :(得分:1)

我的JSFiddle在这里:http://jsfiddle.net/naokiota/38W8X/12/

这是简化功能的示例:

<强> HTML

    <ul>
        <li><a href="#" onclick="toggle(1);" >one</a>
            <ul class="submenu">
                <li>sacd</li>
                <li>safsdf</li>
            </ul>
        </li>
        <li><a href="#" onclick="toggle(2);" >two</a>
            <ul class="submenu">
                <li>jlkfd</li>
                <li>ljsdf</li>
            </ul>
        </li>
        <li><a href="#" onclick="toggle(3);" >three</a>
            <ul class="submenu">
                <li>sfsdvbg gb</li>
                <li>asdavffds</li>
            </ul>
        </li>
    </ul>

<强>的JavaScript

function toggle(n) {
    var menus = document.getElementsByClassName("submenu");
    for(var i=0;i<menus.length;i++){
        if((i == (n-1)) && (menus[i].style.display != "block")){
            menus[i].style.display = "block";
        }else{
            menus[i].style.display = "none";
        }
    } 
};

<强> CSS

.submenu {
    display: none;
}

希望这有帮助。

答案 3 :(得分:0)

是的,有一种更简单的/(更好的和动画的)方式来写这样的东西。

  1. 它是动画的
  2. 可以处理无限开关
  3. 不使用display none
  4. 不使用循环
  5. 只有一个eventhandler控制所有元素
  6. 您可以应用任何类型的风格
  7. 只需添加accordion
  8. 即可添加多个手风琴

    我前段时间编写了这段代码并对其进行了优化并对其进行了压缩。

    给我一​​些时间,我发布一个更易读的代码...因为我给你看了最终版本之一。

    它是一支手风琴。

    function h(e){
     var p='parentNode',a=e.target,b=a[p],f=48,u='px',y=b.firstChild==a?b[p]:y;
     !y.c||(y.c==b||(y.c.style.height=f+u,y.c.x=f)),
     y.c=y.c==b?null:b,
     a!=b.firstChild||(b.x=b.x>f?f:(f+b.childNodes[1].offsetHeight),
     b.style.height=b.x+u)
    }
    document.getElementById('container').addEventListener('click',h,false);
    

    <强>样本

    http://jsfiddle.net/YjCbM/1/

    这是另一个版本

    function handler(e){
     e=e||window.event;
     var target=e.target||e.srcElement;
     var action=target.dataset['action']||'no action';
     !(action=='toggle')||(target.childNodes[1].classList.toggle('show'));
     !target.dataset['url']||alert(target.dataset['url']);
    }
    var firstUL=document.getElementsByTagName('ul')[0];
    firstUL.addEventListener('click',handler,false);
    

    http://jsfiddle.net/Jj6FY/1/

    可读遗嘱(略有不同)

    这基本上是一个手风琴插件

    (function(D){
    function acsf(e){
     var a=e.target.parentNode,h;
     if(a.parentNode==this&&a.firstChild==e.target){
      if(this.c==a){
       this.c.style.height='';
       delete this.c
      }else{
       if(this.c){
        this.c.style.height=''
       }
       this.c=a;
       this.c.style.height=(a.firstChild.offsetHeight+
       this.c.childNodes[1].offsetHeight)+'px'
      }
     }
    }
     function acsinit(){
      var acs=D.getElementsByClassName('accordion'),acsl=acs.length;
      while(acsl--){
       acs[acsl].addEventListener('click',acsf,false);
      }
      window.removeEventListener('load',acsinit,false);
     }
     window.addEventListener('load',acsinit,false);
    })(document)
    

    动画的CSS。

    #container>div{
     width:512px;height:48px;overflow:hidden;
     -webkit-transition:all 300ms ease;
     background-color:rgba(0,0,0,0.5);
    }
    #container>div>div:nth-child(1){
     line-height:48px;text-align:center;
     background-color:rgba(0,0,0,0.5);
    }
    

    html结构

    <div id="container" class="accordion">
     <div>
      <div>Title</div>
      <div>description</div>
     </div>
     <div>
      <div>Title</div>
      <div>description</div>
     </div>
    </div>
    

    如果您希望能够关闭它们,那么您需要使用循环来检查它们是否被切换。

    类似的东西:

    function openAll(){
     var elements=container.childNodes,l=elements.length;
     while(l--){
      if(elements[l].classList.contains('hidden')){
       elements[l].classList.remove('hidden');
      }
     }
    }