如何使用JavaScript一次只允许打开1个可折叠的

sczxawaw  于 2023-03-21  发布在  Java
关注(0)|答案(3)|浏览(145)

我在网页的右边有一个列表,有4个按钮,当点击一个按钮时,就会显示它的相关内容;这是通过JavaScript实现的。EventListener运行一个函数来切换类“active”。
按钮HTML元素还有一个onclick = myFunciton(),它链接到JS以隐藏右箭头图标。

我想设置为一次只能打开其中一个内容版块,如何实现?

以下是我的HTML代码:

<div class="container-fluid">
    <div class="sec2">
      <h1>A 44-letter alphabet.</h1>
      <h1>A phonetically consistent language.</h1>
      <h1>A determined teacher you can count on.</h1>
    </div>
    <div class="sec3">
      <ul class="sec2drop">
        <li>
          <button onclick="myFunction()" class="collapsible" id="colly1">
            Prepare for a language exam
            <i class="fa fa-caret-right" id="arrow0"></i>
          </button>
          <div class="content">
            <p>
              A hundred different reasons, one perfect outcome. Maybe you
              were born to Hungarian parents abroad, and decided to take a
              Hungarian language exam to replace one of your high school
              leaving exams.
            </p>
            <p>
              Maybe you're going to be an exchange student in Hungary or
              work there for some time. I'm happy to prepare you in video
              call sessions, both with verbal and written training.
            </p>
          </div>
        </li>
        <li>
          <button onclick="myFunction()" class="collapsible" id="colly2">
            Hungarian for kids
            <i class="fa fa-caret-right" id="arrow1"></i>
          </button>
          <div class="content">
            <p>
              Many Hungarians living abroad would like to teach their
              linguistics or national heritage. I will tailor online
              sessions for your child that suites their and your needs the
              best.
            </p>
            <p>
              You decide if you would like to supervise or participate in
              the lesson. Generally, children under 8 require parental or
              older sibling presence.
            </p>
          </div>
        </li>
        <li>
          <button onclick="myFunction()" class="collapsible" id="colly3">
            Take on a challenge
            <i class="fa fa-caret-right" id="arrow2"></i>
          </button>
          <div class="content">
            <p>
              Whether you spontaneously decided to learn one of the hardest
              languages in the world, or you want to reconnect with your
              Hungarian heritage, I will guide you along the way. Are you a
              newbie or an advanced learner? Would you like specific types
              of homework in between lessons? I will adapt to your needs.
            </p>
          </div>
        </li>
        <li>
          <button onclick="myFunction()" class="collapsible" id="colly4">
            Translation services
            <i class="fa fa-caret-right" id="arrow3"></i>
          </button>
          <div class="content">
            <p>
              English to Hungarian or Hungarian to English. You can book my
              written translation services and choose the package most
              suitable to you.
            </p>
          </div>
        </li>
      </ul>
    </div>
  </div>

以下是我的CSS代码:

/* Style the button that is used to open and close the collapsible content */
.collapsible {
  background-color: transparent;
  cursor: pointer;
  padding: 18px;
  margin-left: 10px;
  border: none;
  font-size: 15px;
  width: 100%;
  display: flex;
  justify-content: space-between;
}

/* Style the collapsible content. Note: hidden by default */
.content {
  padding: 0px 18px;
  display: none;
  overflow: hidden;
  background-color: wheat;
}

以下是我的JavaScript代码:

var coll = document.getElementsByClassName("collapsible");
var i;

for (i = 0; i < coll.length; i++) {
  coll[i].addEventListener("click", function () {
    this.classList.toggle("active");
    var content = this.nextElementSibling;
    if (content.style.display === "block") {
      content.style.display = "none";
    } else {
      content.style.display = "block";
    }
  });
}

function myFunction() {
  for (y = 0; y < 4; y++) {
    var x = document.getElementById(`arrow${y}`);
    if (x.style.display === "none") {
      x.style.display = "block";
    } else {
      x.style.display = "none";
    }
  }
}
mfuanj7w

mfuanj7w1#

你可以通过折叠所有的活动元素来实现这一点。检查collapseAll()函数。

var coll = document.getElementsByClassName("collapsible");
var i;

for (i = 0; i < coll.length; i++) {
  coll[i].addEventListener("click", function() {

    collapseAll()

    this.classList.toggle("active");
    var content = this.nextElementSibling;
    if (content.style.display === "block") {
      content.style.display = "none";
    } else {
      content.style.display = "block";
    }
  });
}

function collapseAll() {
  var activeElements = document.querySelectorAll(".collapsible.active")
  for (j = 0; j < activeElements.length; j++) {
    activeElements[j].classList.toggle("active")
    activeElements[j].nextElementSibling.style.display = "none";
  }
}

function myFunction() {
  for (y = 0; y < 4; y++) {
    var x = document.getElementById(`arrow${y}`);
    if (x.style.display === "none") {
      x.style.display = "block";
    } else {
      x.style.display = "none";
    }
  }
}
.collapsible {
  background-color: transparent;
  cursor: pointer;
  padding: 18px;
  margin-left: 10px;
  border: none;
  font-size: 15px;
  width: 100%;
  display: flex;
  justify-content: space-between;
}

/* Style the collapsible content. Note: hidden by default */

.content {
  padding: 0px 18px;
  display: none;
  overflow: hidden;
  background-color: wheat;
}
<div class="container-fluid">
  <div class="sec2">
    <h1>A 44-letter alphabet.</h1>
    <h1>A phonetically consistent language.</h1>
    <h1>A determined teacher you can count on.</h1>
  </div>
  <div class="sec3">
    <ul class="sec2drop">
      <li>
        <button onclick="myFunction()" class="collapsible" id="colly1">
          Prepare for a language exam
          <i class="fa fa-caret-right" id="arrow0"></i>
        </button>
        <div class="content">
          <p>
            A hundred different reasons, one perfect outcome. Maybe you were born to Hungarian parents abroad, and decided to take a Hungarian language exam to replace one of your high school leaving exams.
          </p>
          <p>
            Maybe you're going to be an exchange student in Hungary or work there for some time. I'm happy to prepare you in video call sessions, both with verbal and written training.
          </p>
        </div>
      </li>
      <li>
        <button onclick="myFunction()" class="collapsible" id="colly2">
          Hungarian for kids
          <i class="fa fa-caret-right" id="arrow1"></i>
        </button>
        <div class="content">
          <p>
            Many Hungarians living abroad would like to teach their linguistics or national heritage. I will tailor online sessions for your child that suites their and your needs the best.
          </p>
          <p>
            You decide if you would like to supervise or participate in the lesson. Generally, children under 8 require parental or older sibling presence.
          </p>
        </div>
      </li>
      <li>
        <button onclick="myFunction()" class="collapsible" id="colly3">
          Take on a challenge
          <i class="fa fa-caret-right" id="arrow2"></i>
        </button>
        <div class="content">
          <p>
            Whether you spontaneously decided to learn one of the hardest languages in the world, or you want to reconnect with your Hungarian heritage, I will guide you along the way. Are you a newbie or an advanced learner? Would you like specific types of homework
            in between lessons? I will adapt to your needs.
          </p>
        </div>
      </li>
      <li>
        <button onclick="myFunction()" class="collapsible" id="colly4">
          Translation services
          <i class="fa fa-caret-right" id="arrow3"></i>
        </button>
        <div class="content">
          <p>
            English to Hungarian or Hungarian to English. You can book my written translation services and choose the package most suitable to you.
          </p>
        </div>
      </li>
    </ul>
  </div>
</div>
8cdiaqws

8cdiaqws2#

您的网站非常适合使用The Details disclosure element
<details><summary>元素已经包含了一个'open'/'close'机制,因此不需要用Javascript创建:

  • 当用户单击关闭的<details>元素的<summary>元素时,该机制会将 *boolean属性 * open添加到<details>元素中,并显示<summary>下面的内容。在连续单击时,该属性会被删除,详细信息再次关闭,隐藏内容。
  • 公开的详细信息(.content)* 保持打开 *,直到用户再次关闭它们。

由于您希望一次只打开一个.content项目,因此需要简单的Javascript功能来关闭已打开的<details>,然后在用户单击时打开下一个项目。
在代码片段中,我将.sec3的内容更改为与<details><summary>一起使用,并添加了前面提到的简单Javascript来切换.content的可见性。我删除了您的 FontAwesome 图标,并使 “Prepare for a language exam”summaryFontAwesome 一起使用,而其他三个细节使用HTML默认的插入符号。这样您就可以看到差异并选择保留哪一个。“准备语言考试” 还展示了如何在需要时嵌套<details><summary>

代码片段已注解,且应不言自明:

var currentDetail; // reference to current [open] details

// Attach a listener to each .main-detail <summary>
// Beware: nested details stay [open] in the back even if main details is closed

document.querySelectorAll('.main-detail>summary').forEach(el => {

    // This event triggers before <details> 'toggle' event
    el.addEventListener("click", event => {

        // Get reference to closest parent .main-detail
        const closest = event.currentTarget.closest('.main-detail');

        // Remember:
        // the HTML mechanism automatically adds the [open] atttribute
        // upon user click, we don't have to do it ourselves...

        if (closest.open) { // About to trigger 'toggle'...
            currentDetail = null; // all main details closed
        }

        else { // Not null and different main details
            if ((currentDetail) && (currentDetail != closest)) {
                // close current open main details first
                currentDetail.removeAttribute('open');
             };
             // Save newly opened main details
             currentDetail = closest;
        }
        // ...NOW the toggle takes place
    });
});
details .content {
  padding: 0 1rem;
  overflow: hidden;
  background-color: wheat;
}

/******************/
/* Some eye-candy */
/******************/
.main-detail[open] {
    border-top   : 1px solid Gray;
    border-bottom: 1px solid Gray;
    margin: 0.5rem 0;
}
.main-detail[open]>summary   { padding: 0.5em 0; font-weight: bold }

.main-detail details         { font-style: italic } /* nested details */
details details:last-of-type { padding-bottom: 0.5rem }

/* [OPTIONAL] Custom FontAwesome 6 carets replacing default carets */
/*
    If you want to use Fontawesome for all carets,
    change all '#colly1' below to 'summary',
    otherwise remove below four rules entirely...
*/
#colly1        { display: flex; justify-content: space-between }
#colly1::after {
    font-family : "Font Awesome 6 Free";
    font-weight : 900;
    font-style  : normal;
    font-variant: normal;
    line-height : 1;
    text-rendering: auto;
    padding-left: 0.5rem;
}
details       > #colly1::after { content: "\f0da" } /* Caret right */
details[open] > #colly1::after { content: "\f0d7" } /* Caret down  */
/* end Fontawesome */

/*************/
/* Just demo */
/*************/
 /* * { outline: 1px dashed } /* for debugging */

*    { box-sizing: border-box }

body {
    margin: 0; padding: 1rem;
    background-image: url('https://picsum.photos/id/100/1920/1200');
    background-attachement: fixed;
    background-repeat: no-repeat;

    cursor: default;
}
summary { cursor: pointer } /* odd, this should be default */

/* Responsive behavior */
.container-fluid {
    display: flex; flex-flow: row wrap;
    gap: 2rem;
}
/* all sections */
.container-fluid > * {
    flex: 1; /* grow to fill assigned space */
    /* at least 20rem, but 100% when less available */
    min-width: min(20rem,100%);
}

.sec2 { flex: 8 } /* [OPTIONAL] space distribution */
.sec3 { flex: 2 }

.sec2 h1 { word-break: break-word; hyphens: auto }
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css" rel="stylesheet"/>

<div class="container-fluid">
    <div class="sec2">
        <h1>A 44-letter alphabet.</h1>
        <h1>A phonetically consistent language.</h1>
        <h1>A determined teacher you can count on.</h1>
    </div>

    <div class="sec3">
        <details class="main-detail">
            <summary id="colly1">Prepare for a language exam</summary>
            <div class="content">
                <p>
                    A hundred different reasons, one perfect outcome. Maybe you
                    were born to Hungarian parents abroad, and decided to take a
                    Hungarian language exam to replace one of your high school
                    leaving exams.
                </p>
                <p>
                    Maybe you're going to be an exchange student in Hungary or
                    work there for some time. I'm happy to prepare you in video
                    call sessions, both with verbal and written training.
                </p>
                <details>
                    <summary>nested details (not handled by JS)</summary>
                    <p>some nested collapsible info, stays [open], even when main details are closed...</p>
                    <ul>
                        <li>list item 1</li>
                        <li>list item 2</li>
                        <li>list item 3</li>
                    </ul>
                    <details>
                        <summary>even deeper nested details (dito)</summary>
                        <p>some nested collapsible info, stays [open], even when main details are closed...</p>
                        <ul>
                            <li>list item 4</li>
                            <li>list item 5</li>
                            <li>list item 6</li>
                        </ul>
                    </details>
                </details>
            </div>
        </details>

        <details class="main-detail">
            <summary id="colly2">Hungarian for kids</summary>
            <div class="content">
                <p>
                    Many Hungarians living abroad would like to teach their
                    linguistics or national heritage. I will tailor online
                    sessions for your child that suites their and your needs the
                    best.
                </p>
                <p>
                    You decide if you would like to supervise or participate in
                    the lesson. Generally, children under 8 require parental or
                    older sibling presence.
                </p>
            </div>
        </details>

        <details class="main-detail">
            <summary id="colly3">Take on a challenge</summary>
            <div class="content">
                <p>
                    Whether you spontaneously decided to learn one of the hardest
                    languages in the world, or you want to reconnect with your
                    Hungarian heritage, I will guide you along the way. Are you a
                    newbie or an advanced learner? Would you like specific types
                    of homework in between lessons? I will adapt to your needs.
                </p>
            </div>
        </details>

        <details class="main-detail">
            <summary id="colly4"> Translation services</summary>
            <div class="content">
                <p>
                    English to Hungarian or Hungarian to English. You can book my
                    written translation services and choose the package most
                    suitable to you.
                </p>
            </div>
        </details>
    </div>
</div>
r8uurelv

r8uurelv3#

使用inline event listeners可能不是最好的主意。这里有一个最小的例子,使用event delegation,data-attributes来识别需要展开的内容,并使用css类来激活要展开的元素。

document.addEventListener(`click`, handle);

function handle(evt) {
  if (evt.target.dataset.unfold) {
    // hide currently activated (if applicable)
    document.querySelector(`.collapsible.active`)
      ?.classList.remove(`active`);
    // activate from button data attribute
    return document.querySelector(`#${evt.target.dataset.unfold}`)
      .classList.add(`active`);
  }
}
.collapsible {
  display: none;
}

.collapsible.active {
  display: block;
}
<button data-unfold="firstDiv">First</button>
<button data-unfold="secondDiv">Second</button>

<div id="firstDiv" class="collapsible">The first div</div>
<div id="secondDiv" class="collapsible">The second div</div>

相关问题