2012-07-11 33 views
0

我有以下html结构。当有人点击“切换”div我想添加一个隐藏类到内容div和分支ul兄弟姐妹。当再次点击时,我想删除它们。我可以编写点击事件,但我不知道如何从click事件引用嵌套的内容和分支。如何使用纯javascript创建嵌套树状打开/关闭按钮

<ul id="tree"> 
    <li class="leaf"> 
     <div class="switch"></div> 
     <div class="content"> 
      ... stuff 
     </div> 
     <ul class="branch"> 
      <li class="leaf"> 
       <div class="switch"></div> 
       <div class="content"> 
        ... stuff 
       </div> 
       <ul class="branch"> 
        <!-- Can be many layers deep --> 
       </ul> 
      </li> 
     </ul> 
    </li> 
    <li class="leaf"> 
     <div class="switch"></div> 
     <div class="content"> 
      ... stuff 
     </div> 
     <ul class="branch"> 
      <li class="leaf"> 
       <div class="switch"></div> 
       <div class="content"> 
        ... stuff 
       </div> 
       <ul class="branch"> 
        <!-- Can be many layers deep --> 
       </ul> 
      </li> 
     </ul> 
    </li> 
    <!-- Can be many more of these --> 
</ul> 

的Javascript

var Library = (function() { 
    "use strict"; 


    /** 
    * Create click events for all classes passed in. 
    * 
    * This is used by newer browsers that have getElementsByClassName. 
    * 
    * @param {array} class_names The class names to attatch click events to. 
    * @param {function} The callback to handle the click event. 
    * 
    * @return void 
    */ 
    var classNameClick = function(class_names, clickEvent) { 
     for(var i = 0; i < class_names.length; i++) { 
      var elements = document.getElementsByClassName(class_names[i]); 
      for(var j = 0; j < elements.length; j++) { 
       elements[j].onclick = clickEvent; 
      } 
     } 
    }; 

    /** 
    * Loops through all DOM elements to find classes to attatch click events to. 
    * 
    * This is used by older browsers that don't have getElementsByClassName 
    * 
    * @param {array} class_names The class names to attatch click events to. 
    * @param {function} The callback to handle the click event. 
    * 
    * @return void 
    */ 
    var classTagClick = function(class_names, clickEvent) { 
     var elements = document.getElementsByTagName("*"); 
     for(var i = 0; i < elements.length; i++) { 
      var element = elements[i]; 
      for(var j = 0; j < class_names.length; j++) { 
       if(element.className.indexOf(class_names[j]) >= 0) { 
        element.onclick = function() { 
         clickEvent(); 
        } 
       } 
      } 
     } 
    }; 

    return { 

     /** 
     * Loops through all DOM elements to find classes to attatch click events to. 
     * 
     * @param {array} class_names The class names to attatch click events to. 
     * @param {function} The callback to handle the click event. 
     * 
     * @return void 
     */ 
     classClick : function(class_names, clickEvent) { 
      if (typeof document.getElementsByClassName !== "undefined") { 
       classNameClick(class_names, clickEvent); 
      } else { 
       classTagClick(class_names, clickEvent); 
      } 
     } 

    }; 
}()); 

var Tree = (function() { 
    "use strict"; 

    return { 

     construct : function() { 

      Library.classClick("switch", function() { 
       // Not sure how to reference the relevant content and branch class here. 
      }); 

     } 
    }; 
}()); 

window.onload = function() { 
    Tree.construct(); 
} 

我不能使用jQuery或其他库(这很容易与jQuery)。

+1

旁注:我会将该类添加到父李,而不是特定的子节点(兄弟姐妹)。这样你只有一个地方可以切换类(例如'node.parentNode')。 – Yoshi 2012-07-11 09:43:45

+0

@Yoshi那会隐藏开关,它将无法再次打开。内容和分支节点可以嵌套在一个div中,以使代码更有效率。 – SystemicPlural 2012-07-11 09:48:04

+1

为什么? 'li.open> .branch {display:block}'(例如)会使开关保持不动。这样你甚至可以根据状态设置开关的样式。 – Yoshi 2012-07-11 09:48:40

回答

1

我已经通过将以下两个类click事件

element.onclick = function() { 
    clickEvent.apply(this); 
} 

这将替换解决了这个this对象与被点击的DOM元素的单击事件功能。

然后我将以下内容添加到click事件中。

Library.classClick(["switch"], function() { 
    var leaf_node = this.parentNode; 
    var parent_class = leaf_node.className; 
    if (parent_class.indexOf(" closed") === -1) { 
     leaf_node.className += " closed"; 
    } else { 
     leaf_node.className = leaf_node.className.replace(" closed", ""); 
    } 
}); 

最后增加了以下的CSS

li.leaf.closed>。内容,li.leaf.closed> .branch { 显示:无; }