【问题标题】:Javascript: dynamic accordion content fetched from dynamically generated IDJavascript:从动态生成的 ID 中获取的动态手风琴内容
【发布时间】:2017-10-17 21:32:11
【问题描述】:

我目前正在开发一种更复杂的手风琴。手风琴应该有 4 个按钮(第 0-3 节)和单独的内容(lorem ipsum 0-3)。通过单击“第 0 部分”,它应该显示“lorem ipsum 0”。通过单击“第 1 节”,内容“lorem ipsum 0”将替换为“lorem ipsum 1”。

最终的网站将有未知数量的行,每行包含 4 个手风琴。这意味着,脚本必须是动态的。

我的方法是使用 JS 生成 ID,为每个面板设置此属性,然后再次调用它们以使手风琴工作。但我只能调用所有内容(如JSFiddle)或循环中的最后一个。

如何在不丢失布局的情况下显示/替换每个手风琴的内容?

也许有更好的方法来实现这一点?

HTML:

<div class="row">

  <div class="three columns">
    <button class="accordion">Section 0</button>
  </div>  

  <div class="three columns">
    <button class="accordion">Section 1</button>
  </div>  

  <div class="three columns">
    <button class="accordion">Section 2</button>
  </div>    

  <div class="three columns">
    <button class="accordion">Section 3</button>
  </div>  

</div>  

<div class="row">
  <div class="twelve columns">
    <div class="panel">
      <p>Lorem ipsum 0...</p>
    </div>
  </div>
  <div class="twelve columns">
    <div class="panel">
      <p>Lorem ipsum 1...</p>
    </div>
  </div>
  <div class="twelve columns">
    <div class="panel">
      <p>Lorem ipsum 2...</p>
    </div>
  </div>
  <div class="twelve columns">
    <div class="panel">
      <p>Lorem ipsum 3...</p>
    </div>
  </div>
</div>

JS:

var acc = document.getElementsByClassName("accordion");
for (var i = 0; i < acc.length; i++) {
    acc[i].onclick = function() {
        this.classList.toggle("active");

        var writeID = document.getElementsByClassName("panel");
        for (var y = 0; y < writeID.length; y++) {
            var newID = "demo-"+y;
            writeID[y].setAttribute("id", newID);

            var panel = document.getElementById(newID);

            if (panel.style.maxHeight){
                panel.style.maxHeight = null;
            } else {
                panel.style.maxHeight = panel.scrollHeight + "px";
            } 
        }
    }
}

我还创建了一个JSFiddle

感谢任何帮助!

干杯' 最大

编辑:我真的很感激这里的任何帮助。我试图用闭包和 forEach 解决这个问题,但没有成功。如果我必须澄清以上任何内容,我很乐意回答任何问题。

这是代码的当前状态。它给了我所有的内容,但我只想为每个手风琴得到一个:

var acc = document.getElementsByClassName("accordion");
for (var i = 0; i < acc.length; i++) {
  acc[i].onclick = function() {
    this.classList.toggle("active");

      for (var i = 0; i < acc.length; i++) {
        var panel = document.getElementById("demo-"+i);
        if (panel.style.maxHeight){
          panel.style.maxHeight = null;
        } else {
          panel.style.maxHeight = panel.scrollHeight + "px";
        }   
      };  
  }
}

或者换句话说,我试图以一种动态的方式实现这一目标

var acc = document.getElementsByClassName("accordion");

acc[0].onclick = function() {
  this.classList.toggle("active");
  var panel = document.getElementById("demo-0");
  if (panel.style.maxHeight){
    panel.style.maxHeight = null;
  } else {
    panel.style.maxHeight = panel.scrollHeight + "px";
  }    
}

acc[1].onclick = function() {
  this.classList.toggle("active");
  var panel = document.getElementById("demo-1");
  if (panel.style.maxHeight){
    panel.style.maxHeight = null;
  } else {
    panel.style.maxHeight = panel.scrollHeight + "px";
  }    
} 

【问题讨论】:

  • 在给出我的方法之前,让我试着理解你的问题!每个按钮的内容会是动态的吗,我想它会是,对吧?按钮也一样?
  • 是的,内容将是动态的。它可以是文本或图像。这些按钮将遵循某种模式,因此它们将具有固定的名称(如示例中所示)。
  • 我现在阅读了很多关于 javascript 循环附件的内容,但仍然无法弄清楚。有人来寻求帮助吗?谢谢!

标签: javascript html css accordion


【解决方案1】:

您可以使用节号 (data-section=3) 为按钮添加自定义属性,并使用该属性打开包含正确数据的正确面板

var data = ["lorem ipsum ipsum", "lorem lorem lorem", "blah blah blah"];
formatData(data);

function formatData(data) {
  data.forEach(function(text, index) {
    var buttonHTML = "<div class='three columns'>" +
      "<button class='accordion' data-section=" + index + ">Section " + index + "</button>" +
      "</div>";

    var accordionHTML = "<div class='twelve columns'>" +
      "<div id='panel" + index + "' class='panel'>" +
      "<p>" + text + "</p>" +
      "</div>" +
      "</div>";
    document.getElementById("buttonRow").insertAdjacentHTML('beforeend', buttonHTML);
    document.getElementById("panelRow").insertAdjacentHTML('beforeend', accordionHTML);
  })
  var acc = document.getElementsByClassName("accordion");
  for (var i = 0; i < acc.length; i++) {
    acc[i].onclick = function() {
      this.classList.toggle("active");
      var sectionNum = this.getAttribute("data-section");
      var currentPanel = document.getElementById("panel" + sectionNum);
      if (currentPanel.style.maxHeight) {
        currentPanel.style.maxHeight = null;
      } else {
        currentPanel.style.maxHeight = currentPanel.scrollHeight + "px";
      }
    }
  }
}
.democlass {
  color: red;
}

#demo-0 {
  color: red;
}

#demo-1 {
  color: blue;
}

#demo-2 {
  color: green;
}

#demo-3 {
  color: magenta;
}


/* Accordion
–––––––––––––––––––––––––––––––––––––––––––––––––– 
https://www.w3schools.com/howto/howto_js_accordion.asp
*/


/* Style the buttons that are used to open and close the accordion panel */

button.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  width: 100%;
  text-align: left;
  border: none;
  outline: none;
  transition: 0.4s;
}


/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */

button.accordion.active,
button.accordion:hover {
  background-color: #ccc;
}


/* Style the accordion panel. Note: hidden by default */

div.panel {
  padding: 0 18px;
  background-color: white;
  /*    display: none;
*/
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}

.container {
  position: relative;
  width: 100%;
  /*max-width: 1200px;*/
  margin: 0 auto;
  padding: 0 20px;
  box-sizing: border-box;
}

.column,
.columns {
  width: 100%;
  float: left;
  box-sizing: border-box;
}


/* For devices larger than 400px */

@media (min-width: 400px) {
  .container {
    width: 85%;
    padding: 0;
  }
}


/* For devices larger than 550px */

@media (min-width: 550px) {
  .container {
    width: 95%;
  }
  .column,
  .columns {
    margin-left: 4%;
  }
  .column:first-child,
  .columns:first-child {
    margin-left: 0;
  }
  .one.column,
  .one.columns {
    width: 4.66666666667%;
  }
  .two.columns {
    width: 13.3333333333%;
  }
  .three.columns {
    width: 22%;
  }
  .four.columns {
    width: 30.6666666667%;
  }
  .five.columns {
    width: 39.3333333333%;
  }
  .six.columns {
    width: 48%;
  }
  .seven.columns {
    width: 56.6666666667%;
  }
  .eight.columns {
    width: 65.3333333333%;
  }
  .nine.columns {
    width: 74.0%;
  }
  .ten.columns {
    width: 82.6666666667%;
  }
  .eleven.columns {
    width: 91.3333333333%;
  }
  .twelve.columns {
    width: 100%;
    margin-left: 0;
  }
  .one-third.column {
    width: 30.6666666667%;
  }
  .two-thirds.column {
    width: 65.3333333333%;
  }
  .one-half.column {
    width: 48%;
  }
  /* Offsets */
  .offset-by-one.column,
  .offset-by-one.columns {
    margin-left: 8.66666666667%;
  }
  .offset-by-two.column,
  .offset-by-two.columns {
    margin-left: 17.3333333333%;
  }
  .offset-by-three.column,
  .offset-by-three.columns {
    margin-left: 26%;
  }
  .offset-by-four.column,
  .offset-by-four.columns {
    margin-left: 34.6666666667%;
  }
  .offset-by-five.column,
  .offset-by-five.columns {
    margin-left: 43.3333333333%;
  }
  .offset-by-six.column,
  .offset-by-six.columns {
    margin-left: 52%;
  }
  .offset-by-seven.column,
  .offset-by-seven.columns {
    margin-left: 60.6666666667%;
  }
  .offset-by-eight.column,
  .offset-by-eight.columns {
    margin-left: 69.3333333333%;
  }
  .offset-by-nine.column,
  .offset-by-nine.columns {
    margin-left: 78.0%;
  }
  .offset-by-ten.column,
  .offset-by-ten.columns {
    margin-left: 86.6666666667%;
  }
  .offset-by-eleven.column,
  .offset-by-eleven.columns {
    margin-left: 95.3333333333%;
  }
  .offset-by-one-third.column,
  .offset-by-one-third.columns {
    margin-left: 34.6666666667%;
  }
  .offset-by-two-thirds.column,
  .offset-by-two-thirds.columns {
    margin-left: 69.3333333333%;
  }
  .offset-by-one-half.column,
  .offset-by-one-half.columns {
    margin-left: 52%;
  }
}
<div class="container">

  <div id="buttonRow" class="row">

  </div>

  <div id="panelRow" class="row">

  </div>

</div>
<!-- /container  -->

【讨论】:

  • 感谢您对该主题的看法。内容(lorem ipsum)需要是动态的并从 cms 中获取,所以我想这不会成功。还是谢谢你!
  • Max 我更新了答案,使您的数据更加动态。我把你的数据作为一个字符串数组,但你可以把它塑造成另一种类型的对象
  • 谢谢安德鲁!我最终用 jQuery 来做这件事——一个朋友帮我写了一些代码。感谢您的时间和精力
猜你喜欢
  • 2013-01-20
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 2015-03-07
相关资源
最近更新 更多