Here is my code.
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>
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.
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 = false
});
}
}
<details>
<summary>1</summary>
Demo 1
</details>
<details>
<summary>2</summary>
Demo 2
</details>
<details>
<summary>3</summary>
Demo 3
</details>
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**
Same concept, just a bit shorter.
$('details').click(function (event) {
$('details').not(this).removeAttr("open");
});
Yet another answer for those who don't want to use obsolete jQuery and those who loves functional javascript
[...document.getElementsByTagName("details")].forEach( (D,_,A) =>
D.addEventListener("toggle", E =>
D.open && A.forEach(d =>
d!=E.target && (d.open=false)
)
)
)
<details>
<summary>1</summary>Demo 1
</details>
<details>
<summary>2</summary>Demo 2
</details>
<details>
<summary>3</summary>Demo 3
</details>