简体   繁体   English

如何一次只显示一个div?

[英]How to show only one div at the time?

I've got three sections, inside of which there are two divs.我有三个部分,其中有两个 div。 Inside the first one I have a button and after clicking it I should have the next one opened.在第一个里面我有一个按钮,点击它后我应该打开下一个。 However, only one div should be visible at the time (so when you click the next one, previous one should be closed).但是,此时应该只有一个 div 可见(因此当您单击下一个时,应关闭前一个)。 And I've got this functionality, but after clicking on the button again - it doesn't close the corresponding div.我有这个功能,但再次点击按钮后 - 它不会关闭相应的 div。

I set up an example of my problem on codepen:我在 codepen 上设置了我的问题示例:

https://codepen.io/hubertstrawa/pen/abOwWMJ
<section>
  <div class="product">
    <span class="btn">Show more</span>
    <p>Lorem ipsum</p>
  </div>
  <div class="product-more displayNone">
    Test
  </div>
</section>
$('.btn').click(function(e) {

  // only one div to be shown but can't be closed as well.
  $('.product-more').each(function(i, v) {
  $(this).removeClass('displayBlock');
  $(this).addClass('displayNone');
  })

  if ($(e.target).parent().next().hasClass('displayNone')) {
    $(e.target).parent().next().removeClass('displayNone');
    $(e.target).parent().next().addClass('displayBlock');
  } else {
    $(e.target).parent().next().removeClass('displayBlock');
    $(e.target).parent().next().addClass('displayNone');
  }

});

Any ideas how can I make it work?任何想法我怎样才能使它工作?

Thank you谢谢

Change a .is-open on a parent element .更改父元素上的.is-open

<section class="product is-open">    <!-- is-open toggled by JS -->
    <div class="product-more"></div> <!-- handle children styles using CSS -->
</section>
                 .product-more { display: none; }  /* default */
.product.is-open .product-more { display: block; } /* when ancestor is .is-open*/

Use delegateTarget inside the .on() method to get back the .product delegator element内部使用delegateTarget .on()方法来取回.product委托元素

 const $product = $('.product'); // Collect all current products $product.on('click', '.btn', function(e) { const $thisProd = $(e.delegateTarget); // The .product delegator $product.not($thisProd).removeClass('is-open'); // Handle all (but not this) $thisProd.toggleClass('is-open'); // Handle current });
 /* QuickReset */ * {margin: 0; box-sizing: border-box;} .product { background-color: #ededed; width: 400px; margin: 0 auto; margin-bottom: 1rem; } .product-title { position: relative; padding: 1rem; } .product .btn { position: absolute; bottom: 0; right: 0; padding: .7rem; background-color: cyan; cursor: pointer; } .product-more { width: 100%; padding: 1rem; background-color: cyan; display: none; /* by default */ } .product.is-open .product-more { display: block; }
 <section class="product"> <div class="product-title"> <p>Lorem ipsum</p> <span class="btn">Show more</span> </div> <div class="product-more">Test</div> </section> <section class="product"> <div class="product-title"> <p>Lorem ipsum</p> <span class="btn">Show more</span> </div> <div class="product-more">Test</div> </section> <section class="product"> <div class="product-title"> <p>Lorem ipsum</p> <span class="btn">Show more</span> </div> <div class="product-more">Test</div> </section> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

This is preferred, since it lets you change HTML and CSS, and not worry any more about JavaScript - whilst by using .prev() , .next() or .parent() (like the other answers suggest) JS is just waiting for you to change the markup - to break.这是首选,因为它可以让您更改 HTML 和 CSS,而不必再担心 JavaScript - 而通过使用.prev().next().parent() (就像其他答案建议的那样)JS 只是在等待你改变标记 - 打破。

  • No need to traverse back and forth your selectors.无需来回遍历选择器。
  • No need for .displayNone and .displayBlock on the product-more element. product-more元素上不需要.displayNone.displayBlock

Handling dynamic .product处理动态.product

if your .product are dynamic elements, here's another solution to the above concept:如果您的.product是动态元素,这里是上述概念的另一种解决方案:

 $('.allProducts').on('click', '.btn', function(e) { const $product = $(e.delegateTarget).find('.product'); // Get all .product const $thisProd = $(this).closest('.product'); // The closest .product ancestor $product.not($thisProd).removeClass('is-open'); // Handle all (but not this) $thisProd.toggleClass('is-open'); // Handle current });
 /* QuickReset */ * {margin: 0; box-sizing: border-box;} .product { background-color: #ededed; width: 400px; margin: 0 auto; margin-bottom: 1rem; } .product-title { position: relative; padding: 1rem; } .product .btn { position: absolute; bottom: 0; right: 0; padding: .7rem; background-color: cyan; cursor: pointer; } .product-more { width: 100%; padding: 1rem; background-color: cyan; display: none; /* by default */ } .product.is-open .product-more { display: block; }
 <div class="allProducts"> <section class="product"> <div class="product-title"> <p>Lorem ipsum</p> <span class="btn">Show more</span> </div> <div class="product-more">Test</div> </section> <section class="product"> <div class="product-title"> <p>Lorem ipsum</p> <span class="btn">Show more</span> </div> <div class="product-more">Test</div> </section> <section class="product"> <div class="product-title"> <p>Lorem ipsum</p> <span class="btn">Show more</span> </div> <div class="product-more">Test</div> </section> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

You are hiding all the product-more sections when clicking any btn button, and then, trying to show/hide the product-more section associated with the clicked button.单击任何btn按钮时,您正在隐藏所有product-more部分,然后尝试显示/隐藏与单击的按钮关联的product-more部分。

So, when the section product-more is already shown and you click its btn button what happens is that you first hide the associated section and then your code checks if it is not visible and then shows its again.因此,当product-more部分已经显示并且您单击它的btn按钮时,发生的情况是您首先隐藏关联的部分,然后您的代码检查它是否不可见,然后再次显示它。

One possible solution is to discard the associated product-more section when hiding.一种可能的解决方案是在隐藏时丢弃相关的product-more部分。 Also, as div s are shown by default, you don't need the displayBlock class.此外,由于默认显示div ,因此您不需要displayBlock类。

$('.btn').click(function(e) {
    var $current = $(e.target).parent().next('.product-more');

    // Hide all sections that are not the one associated to the current button.
    $('.product-more').not($current).addClass('displayNone');

    // Show or hide current section.
    $current.toggleClass('displayNone');
});

You can use the toggleClass it will detect your class and change it to another.您可以使用toggleClass它将检测您的类并将其更改为另一个类。

In your each function you just need to set all items to be hide and then it will toggle classes for current item.在您的 each 函数中,您只需要将所有项目设置为隐藏,然后它将切换当前项目的类。

Codepen代码笔

https://codepen.io/nasser-ali-karimi/pen/rNVwwLy?editors=1010 https://codepen.io/nasser-ali-karimi/pen/rNVwwLy?editors=1010

$('.btn').click(function(e) {

  // only one div to be shown but can't be closed as well.
  $('.product-more').each(function(i, v) {
    $(this).removeClass('displayBlock');
    $(this).addClass('displayNone');
  })
 $(e.target).parent().next().toggleClass('displayNone displayBlock');

});

A shorter version using jQuery would be using hide() and toggle():使用 jQuery 的较短版本将使用hide()toggle():

 $('.btn').click(function(e) { var more = $(e.target).parent().next() ; $('.product-more').not(more).hide(); $(e.target).parent().next().toggle(); });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM