如何使用JavaScript展开和折叠<div>?

103

我在我的网站上创建了一个列表。这个列表是通过foreach循环创建的,其中包含来自我的数据库的信息。每个项目都是一个容器,具有不同的部分,因此这不是像1、2、3...等这样的列表。我正在列出重复的带有信息的部分。在每个部分中,都有一个小节。一般的构建如下:

<div>
    <fieldset class="majorpoints" onclick="majorpointsexpand($(this).find('legend').innerHTML)">
    <legend class="majorpointslegend">Expand</legend>
    <div style="display:none" >
        <ul>
            <li></li>
            <li></li>
        </ul>
    </div>
</div>

所以,我正在尝试使用onclick="majorpointsexpand($(this).find('legend').innerHTML)"来调用函数。

我想要操作的div默认情况下是style="display:none",我想使用javascript来实现在单击时使其可见。

在这种情况下,"$(this).find('legend').innerHTML"尝试将"Expand"作为函数参数传递。

以下是javascript代码:

function majorpointsexpand(expand)
    {
        if (expand == "Expand")
            {
                document.write.$(this).find('div').style = "display:inherit";
                document.write.$(this).find('legend').innerHTML = "Collapse";
            }
        else
            {
                document.write.$(this).find('div').style = "display:none";
                document.write.$(this).find('legend').innerHTML = "Expand";
            }
    }

我几乎可以确定我的问题是语法问题,而且我对JavaScript的工作原理并不十分了解。

我已经通过以下方式将jQuery链接到文档中:

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>

<head></head>标签内。


3
我认为你想要实现的是一个手风琴效果 http://jqueryui.com/accordion/ - Marc
1
$this 是我试图表达的“与”函数所触发的 HTML 元素相关。 - Ryan Mortensen
1
@hungerpain - 我认为提问者可能是新手,只是忘记在 $(this) 周围加上括号。希望这可以帮到他。 - jamesmortensen
2
我认为你应该先更多地学习jQuery。显然,你不太了解jQuery和JavaScript之间的区别。 - tom10271
1
@aokaddaoc 你完全正确 ;) - Ryan Mortensen
显示剩余2条评论
13个回答

192

好的,你有两个选择:

  1. 使用 jQuery UI 的手风琴 - 它很好、易用且快速。在这里查看更多信息。
  2. 或者,如果你仍然想自己完成此任务,可以移除 fieldset元素(它在语义上并不正确),并自行创建结构。

以下是如何创建结构的方法。创建一个像这样的 HTML 结构:

<div class="container">
    <div class="header"><span>Expand</span>

    </div>
    <div class="content">
        <ul>
            <li>This is just some random content.</li>
            <li>This is just some random content.</li>
            <li>This is just some random content.</li>
            <li>This is just some random content.</li>
        </ul>
    </div>
</div>
通过以下CSS:(这是为了在页面加载时隐藏.content的元素。)

使用此CSS:(这是为了在页面加载时隐藏.content的元素。

.container .content {
    display: none;
    padding : 5px;
}

然后,使用jQuery为标题编写一个click事件。

$(".header").click(function () {

    $header = $(this);
    //getting the next element
    $content = $header.next();
    //open up the content needed - toggle the slide- if visible, slide up, if not slidedown.
    $content.slideToggle(500, function () {
        //execute this after slideToggle is done
        //change text of header based on visibility of content div
        $header.text(function () {
            //change text based on condition
            return $content.is(":visible") ? "Collapse" : "Expand";
        });
    });

});

这里有一个演示:http://jsfiddle.net/hungerpain/eK8X5/7/


10
如果页面上有多个DIV元素,+1将解决这个问题。换句话说,由于您针对的是单击标题内的内容,因此可以很好地扩展。 - jamesmortensen
2
fieldset字段不是必要的。我会删除它,只使用边框。这很好,因为它选择了与我点击的标题相关的div进行扩展,这非常重要,因为根据用户设置和其他因素,我可能有几个不同数量的列出的项目。 - Ryan Mortensen
2
@Unipartisandev 看看这个:http://jsfiddle.net/hungerpain/476Nq/ 完整的示例 :) - krishwader
我非常感激您的帮助。尽管这个特定的事情更多地是一个全有或全无的显示示例,但网站的其他部分无疑也需要使用手风琴。我仍然遇到问题。我的jQuery版本过时且无法加载。这已经解决了,但它仍然无法正常工作。我已经花了一个小时来调试它,我会睡一觉再看看。也许明天会有灵感。 - Ryan Mortensen
谢谢,对于多个div非常有效。我现在的问题是如何获得一个动态的展开/折叠标题,以获取来自div的第一个<span>,并制作一个标题,例如“展开-第1节:介绍”...但我还无法完全弄清楚。 - josh.thomson
显示剩余5条评论

22

你觉得怎么样:

jQuery:

$('.majorpoints').click(function(){
    $(this).find('.hider').toggle();
});

HTML

<div>
  <fieldset class="majorpoints">
    <legend class="majorpointslegend">Expand</legend>
    <div class="hider" style="display:none" >
        <ul>
            <li>cccc</li>
            <li></li>
        </ul>
    </div>
</div>

Fiddle

这样做将点击事件绑定到了 .majorpoints 类,您无需每次在 HTML 中编写它。


嗨raam86,我会更进一步地使用类而不是ID在div上进行.find。如果提问者在页面上有几个这样的fieldset,他将想要针对与单击的特定fieldset相关的隐藏器进行定位。希望这可以帮助! :)例如,您可以使用.closest获取对父div的引用,然后使用.find来定位具有class ="hider"的div。 - jamesmortensen
1
我知道现在是凌晨3点,但我刚刚注意到你在jsFiddle中仍在使用id。这可能会导致未定义的行为,因为W3C规范指出每个id应该是唯一的。如果你将hider更改为类,则可以更有效地避免其他浏览器中的错误或奇怪的、无法解释的行为。希望这能帮到你! - jamesmortensen
实际上应该是$('.majorpointslegend').click(function(){ $(this).parent().find('.hider').toggle(); });否则,当单击字段集中的任何位置时,它将折叠。 - Awatatah

9
你可能想要查看这个简单的 JavaScript 方法,当点击链接时调用它,以使面板/ div 展开或折叠。
<script language="javascript"> 
function toggle(elementId) {
    var ele = document.getElementById(elementId);
    if(ele.style.display == "block") {
            ele.style.display = "none";
    }
    else {
        ele.style.display = "block";
    }
} 
</script>

你可以传递div ID,它将在“none”和“block”之间切换显示状态。 snip2code上的原始来源 - 如何折叠HTML中的div

7

这里有很多问题。

我已经为您设置了一个适用的fiddle:http://jsfiddle.net/w9kSU/

$('.majorpointslegend').click(function(){
    if($(this).text()=='Expand'){
        $('#mylist').show();
        $(this).text('Colapse');
    }else{
        $('#mylist').hide();
        $(this).text('Expand');
    }
});

7

首先,你的Javascript甚至没有使用jQuery。有几种方法可以解决这个问题。例如:

第一种方法,使用jQuery的toggle方法:

<div class="expandContent">
        <a href="#">Click Here to Display More Content</a>
 </div>
<div class="showMe" style="display:none">
        This content was hidden, but now shows up
</div>

<script>  
    $('.expandContent').click(function(){
        $('.showMe').toggle();
    });
</script>

jsFiddle: http://jsfiddle.net/pM3DF/

另一种方法是直接使用jQuery的show方法:

<div class="expandContent">
        <a href="#">Click Here to Display More Content</a>
 </div>
<div class="showMe" style="display:none">
        This content was hidden, but now shows up
</div>

<script>
    $('.expandContent').click(function(){
        $('.showMe').show();
    });
</script>

jsFiddle: http://jsfiddle.net/Q2wfM/

第三种方法是使用jQuery的slideToggle方法,它可以实现一些特效。例如$('#showMe').slideToggle('slow');,它会慢慢显示隐藏的div。


假设页面上有多个showMe元素怎么办?记住,他正在使用for循环来构建这些元素的列表,因此针对class="showMe"只会影响该元素的第一个实例。我的建议是参考所点击的showMe元素。那么这将是一个好的解决方案。希望这可以帮到你! :) - jamesmortensen
没错,但他使用循环来建立一个包含一系列<li>元素的列表,而不是 div。无论如何,他都可以使用元素 ID 来隐藏它。 - Michael Hawkins
你正在考虑子部分,却忘记了会有更多的这些。每个“section”都由“subsection”中的li元素填充。 “此列表是通过foreach循环创建的,该循环使用来自我的数据库的信息构建。每个项目都是具有不同部分的容器,因此这不是像1、2、3等一样的列表。我正在列出带有信息的重复部分。在每个部分中,都有一个子部分。”简而言之,他只是向您展示了一个部分,即使还会有更多。 - jamesmortensen

3

尝试使用jQuery。

  <div>
        <a href="#" class="majorpoints" onclick="majorpointsexpand(" + $('.majorpointslegend').html() + ")"/>
        <legend class="majorpointslegend">Expand</legend>
        <div id="data" style="display:none" >
            <ul>
                <li></li>
                <li></li>
            </ul>
        </div>
    </div>


function majorpointsexpand(expand)
    {
        if (expand == "Expand")
            {
                $('#data').css("display","inherit");
                $(".majorpointslegend").html("Collapse");
            }
        else
            {
                $('#data').css("display","none");
                $(".majorpointslegend").html("Expand");
            }
    }

3

这里有一个展示如何通过动画效果扩展职员列表并显示详细信息的示例。

<html>
  <head>
    <style>
      .staff {            margin:10px 0;}
      .staff-block{       float: left; width:48%; padding-left: 10px; padding-bottom: 10px;}
      .staff-title{       font-family: Verdana, Tahoma, Arial, Serif; background-color: #1162c5; color: white; padding:4px; border: solid 1px #2e3d7a; border-top-left-radius:3px; border-top-right-radius: 6px; font-weight: bold;}
      .staff-name {       font-family: Myriad Web Pro; font-size: 11pt; line-height:30px; padding: 0 10px;}
      .staff-name:hover { background-color: silver !important; cursor: pointer;}
      .staff-section {    display:inline-block; padding-left: 10px;}
      .staff-desc {       font-family: Myriad Web Pro; height: 0px; padding: 3px; overflow:hidden; background-color:#def; display: block; border: solid 1px silver;}
      .staff-desc p {     text-align: justify; margin-top: 5px;}
      .staff-desc img {   margin: 5px 10px 5px 5px; float:left; height: 185px; }
    </style>
  </head>
<body>
<!-- START STAFF SECTION -->
<div class="staff">
  <div class="staff-block">
    <div  class="staff-title">Staff</div>
    <div class="staff-section">
        <div class="staff-name">Maria Beavis</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Maria earned a Bachelor of Commerce degree from McGill University in 2006 with concentrations in Finance and International Business. She has completed her wealth Management Essentials course with the Canadian Securities Institute and has worked in the industry since 2007.</p>
        </div>
        <div class="staff-name">Diana Smitt</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Diana joined the Diana Smitt Group to help contribute to its ongoing commitment to provide superior investement advice and exceptional service. She has a Bachelor of Commerce degree from the John Molson School of Business with a major in Finance and has been continuing her education by completing courses.</p>
        </div>
        <div class="staff-name">Mike Ford</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Mike: A graduate of École des hautes études commerciales (HEC Montreal), Guillaume holds the Chartered Investment Management designation (CIM). After having been active in the financial services industry for 4 years at a leading competitor he joined the Mike Ford Group.</p>
        </div>
    </div>
  </div>

  <div class="staff-block">
    <div  class="staff-title">Technical Advisors</div>
    <div class="staff-section">
        <div class="staff-name">TA Elvira Bett</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Elvira has completed her wealth Management Essentials course with the Canadian Securities Institute and has worked in the industry since 2007. Laura works directly with Caroline Hild, aiding in revising client portfolios, maintaining investment objectives, and executing client trades.</p>
        </div>
        <div class="staff-name">TA Sonya Rosman</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Sonya has a Bachelor of Commerce degree from the John Molson School of Business with a major in Finance and has been continuing her education by completing courses through the Canadian Securities Institute. She recently completed her Wealth Management Essentials course and became an Investment Associate.</p>
        </div>
        <div class="staff-name">TA Tim Herson</div>
        <div class="staff-desc">
          <p><img src="http://www.craigmarlatt.com/canada/images/security&defence/coulombe.jpg" />Tim joined his father&#8217;s group in order to continue advising affluent families in Quebec. He is currently President of the Mike Ford Professionals Association and a member of various other organisations.</p>
        </div>
    </div>
  </div>
</div>
<!-- STOP STAFF SECTION -->

<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

<script language="javascript"><!--
//<![CDATA[
$('.staff-name').hover(function() {
    $(this).toggleClass('hover');
});
var lastItem;
    $('.staff-name').click(function(currentItem) {
        var currentItem = $(this);
      if ($(this).next().height() == 0) {
          $(lastItem).css({'font-weight':'normal'});
          $(lastItem).next().animate({height: '0px'},400,'swing');
          $(this).css({'font-weight':'bold'});
          $(this).next().animate({height: '300px',opacity: 1},400,'swing');
      } else {
          $(this).css({'font-weight':'normal'});
          $(this).next().animate({height: '0px',opacity: 1},400,'swing');
      }
      lastItem = $(this);
    });
//]]>
--></script>

</body></html>

Fiddle


3

1
你好,欢迎来到 Stack Overflow!您应该展示一个例子,这样您的答案就更完整了。如果链接失效,您的答案仍将对未来的访问者有用。祝你好运! :) - jamesmortensen
你能否编辑并添加一个示例,或将其作为评论添加。谢谢。 - JGallardo

2

既然页面已经加载了jQuery,你可以删除onclick属性和majorpointsexpand函数。将以下脚本添加到页面底部或者最好是一个外部的.js文件中:

$(function(){

  $('.majorpointslegend').click(function(){
    $(this).next().toggle().text( $(this).is(':visible')?'Collapse':'Expand' );
  });

});

这个解决方案应该能与您的HTML代码配合使用,但并不是一个非常强大的答案。如果您更改了fieldset的布局,它可能会失效。我建议您在隐藏的div中添加一个class属性,例如class="majorpointsdetail",然后使用以下代码:

$(function(){

  $('.majorpoints').on('click', '.majorpointslegend', function(event){
    $(event.currentTarget).find('.majorpointsdetail').toggle();
    $(this).text( $(this).is(':visible')?'Collapse':'Expand' );
  });

});

注意:您的问题中没有闭合的</fieldset>标签,因此我假设隐藏的div位于fieldset内部。


你是正确的。有一个闭合的fieldset,但我在问题中错过了它。它紧接在内部</div>的闭合标签之后,在外部</div>的闭合标签之前。 - Ryan Mortensen

1
如果您使用了 data-role 可折叠功能,例如:
    <div id="selector" data-role="collapsible" data-collapsed="true">
    html......
    </div>

然后它将关闭扩展的div。
    $("#selector").collapsible().collapsible("collapse");   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接