Automatically close all the other <details> tags after opening a specific <details> tag

巧了我就是萌 提交于 2019-12-21 10:15:33

问题


Here is my code.

<details>
  <summary>1</summary>
  Demo 1
</details>

<details>
  <summary>2</summary>
  Demo 2
</details>

<details>
  <summary>3</summary>
  Demo 3
</details>

What I want to do is -- if the details of any single <details> tag is open and I open/view another <details> tag, then the earlier one should close/hide/minimize.

How can this be achieved?

I'm aware the <details> tag is not supported in IE or Edge.


回答1:


Another approach, slightly shorter, slightly more efficient, without dependencies, and without onclick attributes in the HTML.

// Fetch all the details element.
const details = document.querySelectorAll("details");

// Add the onclick listeners.
details.forEach((targetDetail) => {
  targetDetail.addEventListener("click", () => {
    // Close all the details that are not targetDetail.
    details.forEach((detail) => {
      if (detail !== targetDetail) {
        detail.removeAttribute("open");
      }
    });
  });
});
<details>
  <summary>1</summary>Demo 1
</details>

<details>
  <summary>2</summary>Demo 2
</details>

<details>
  <summary>3</summary>Demo 3
</details>



回答2:


Same concept, just a bit shorter.

$('details').click(function (event) {
    $('details').not(this).removeAttr("open");  
    });



回答3:


Whao, nobody answering about <details> <summary> are using toogle event ?

const All_Details = document.querySelectorAll('details');

All_Details.forEach(deet=>{
  deet.addEventListener('toggle', toggleOpenOneOnly)
})

function toggleOpenOneOnly(e) {
  if (this.open) {
    All_Details.forEach(deet=>{
      if (deet!=this && deet.open) deet.open = !open
    });
  }
}
<details>
  <summary>1</summary>
  Demo 1
</details>

<details>
  <summary>2</summary>
  Demo 2
</details>

<details>
  <summary>3</summary>
  Demo 3
</details>



回答4:


I have come up with a solution. Please correct me if this is a wrong approach.

I added an onclick event to all of the details tag and made a function thisindex(this) which returns the index of the clicked tag and the obtained index number is then passed to the another function closeAll() which minimizes/closes all the other open tags except for one whose index matches with what we obtained earlier.

Here is the code.

function thisindex(elm){
  var nodes = elm.parentNode.childNodes, node;
  var i = 0, count = i;
  while( (node=nodes.item(i++)) && node!=elm )
    if( node.nodeType==1 ) count++;
  return count;
}

function closeAll(index){
  var len = document.getElementsByTagName("details").length;

  for(var i=0; i<len; i++){
    if(i != index){
      document.getElementsByTagName("details")[i].removeAttribute("open");
    }
  }
}
<details onclick="closeAll(thisindex(this));">
  <summary>1</summary>Demo 1
</details>

<details onclick="closeAll(thisindex(this));">
  <summary>2</summary>Demo 2
</details>

<details onclick="closeAll(thisindex(this));">
  <summary>2</summary>Demo 3
</details>

Same with the help of jQuery

$(document).ready(function(){
  $('details').click(function (event) {
    var index = $('details').index(this);
    var len = $("details").length;
    for(var i=0; i<len; i++){
      if(i != index){
        $("details")[i].removeAttribute("open");
      }
    }
  });
});

Kindly suggest me a better approach if this not up to the mark.




回答5:


Modification for use with polyfill jquery-details.js [Edge]

  var isIE = /*@cc_on!@*/false || !!document.documentMode;
  var isEdge = !isIE && !!window.StyleMedia;
  const details = Array.from(document.querySelectorAll("details"));
  details.forEach((targetDetail) => {
    targetDetail.addEventListener("click", () => {
      details.forEach((detail) => {
        if (detail !== targetDetail) {
          if(isEdge) {
            detail.className = detail.className.replace(/\bopen\b/g,"");
            detail.open =  false;
            detail.querySelector("summary").setAttribute("aria-expanded","false");
            var chil = detail.querySelectorAll("details > *");
            for(var j = 0; j < chil.length; j++) {
              if(chil[j].tagName != "SUMMARY") {
                chil[j].style.display = "none";
              }
            }
          } else {
            detail.removeAttribute("open");
          }
        }
      });
    });
  });**strong text**


来源:https://stackoverflow.com/questions/16751345/automatically-close-all-the-other-details-tags-after-opening-a-specific-detai

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!