Automatically open details element on ID call
I don't think you can open <details>
with CSS alone. But you can:
- Get the hash with
location.hash
. Possibly listen tohashchange
event. - Use
document.getElementById
to get the element. - Set its
open
property to true.
function openTarget() {
var hash = location.hash.substring(1);
if(hash) var details = document.getElementById(hash);
if(details && details.tagName.toLowerCase() === 'details') details.open = true;
}
window.addEventListener('hashchange', openTarget);
openTarget();
:target {
background: rgba(255, 255, 200, .7);
}
<details id="foo">Details <summary>Summary</summary></details>
<div><a href="#foo">#foo</a> <a href="#bar">#bar</a></div>
How to open details from link in another page
You cannot modify another page that is not active using Javascript. Javascript only runs on the active page and can modify the DOM of the active page. You will have to send the value to the next page.
HTML5 Session Storage to send data:
home.html
<script type="text/javascript">
window.onload = function() {
var a = document.getElementById("mylink");
a.onclick = function() {
localStorage.setItem("open", "true");
}
}
</script>
second_page.html
<script>
var val = localStorage.getItem("open");
if (val == "true") {
var b = document.getElementById("mydetails");
b.open = true;
b.style.color = "red";
localStorage.removeItem("open");
}
</script>
Expand details element when URL is called with specific hashes
It's a question of relaxing your check of the hash to allow more than just exactly "comments", but also "comment-111". I have assumed, as your HTML suggests, that your IDs are numeric.
//grab hash and its parts
let hash = location.hash.match(/^#(comment(s|-(\d+)))$/);
if (hash) {
//resolve to element
let el = document.getElementById(hash[1]);
if (el) {
//open comments - not sure what your .open property does
el.closest('#comments').open = true;
//if is hash to specific comment, go to it
if (hash[3]) location.href = '#'+hash[3];
}
}
How to expand details/summary when opening page with anchor inside nested details ?
also: gist, codepen
function MakeArrayOfAllPrefixes(str){
//console.log("MakeArrayOfAllPrefixes("+str+")");
var prefixes = [];
for (var i=1; i<=str.length; i++){
prefixes.push(str.substr(0,i));
}
console.log("MakeArrayOfAllPrefixes("+str+") -> returns [" + prefixes + "]");
return prefixes;
}
function SetOpenAttrForIdsAndPrefixes(ids, openAttrBool){
$('details').attr('open',false); // close all others first
console.log("SetOpenAttrForIds([" +ids+"], "+openAttrBool+")");
for (idindex in ids) {
var id = ids[idindex];
if (id != ""){
var prefixes = MakeArrayOfAllPrefixes(id);
for (prefixidx in prefixes) {
var prefix = prefixes[prefixidx];
if(openAttrBool==true) { operationstr="Opening"; } else { operationstr="Closing"};
console.log(operationstr+" <details id='#"+prefix+"'> with $('#"+prefix+").attr('open',"+openAttrBool+");");
$('#'+prefix).attr('open',openAttrBool);
}
}
}
}
function SetOpenAttrForIdsAndPrefixesFromLocationHash(){
var hashes = $(location).attr('hash').split('#');
SetOpenAttrForIdsAndPrefixes(hashes, true);
}
$(document).ready(function(){
SetOpenAttrForIdsAndPrefixesFromLocationHash();
if ("onhashchange" in window) {// does the browser support the hashchange event?
window.onhashchange = function () {
SetOpenAttrForIdsAndPrefixesFromLocationHash();
}
}
});
<p>
Opens details/summeries, all parths, using prefixes. Supports multiple anchors in url, example:
</p>
<ul>
<li><a href="#Q0A0#Q1A">#Q0A0#Q1A</a>,</li>
<li><a href="#Q0B#Q0C#Q1B#Q1C">#Q0B#Q0C#Q1A#Q1C</a>.</li>
</ul>
<p>
references:
<a href="https://webdesign.tutsplus.com/tutorials/explaining-the-details-and-summary-elements--cms-21999">1</a>,
<a href="https://stackoverflow.com/a/48258026/544721">2</a>,
<a href="https://stackoverflow.com/q/55308339/544721">3</a>,
<a href="https://stackoverflow.com/q/3552944/544721">4</a>,
<a href="https://stackoverflow.com/q/2161906/544721">5</a>.
</p>
<ul>
<li><details id="Q0"><summary>Q0</summary>
<ul>
<li><details id="Q0A"><summary>Q0A</summary>
<ul>
<li><details id="Q0A0"><summary>Q0A0</summary><a href="#Q0A0">Answer to Q0A0</a></details></li>
<li><details id="Q0A1"><summary>Q0A1</summary><a href="#Q0A1">Answer to Q0A1</a></details></li>
<li><details id="Q0A2"><summary>Q0A2</summary><a href="#Q0A2">Answer to Q0A2</a></details></li>
</ul>
</details>
</li>
<li><details id="Q0B"><summary>Q0B</summary><a href="#Q0B">Answer to Q0B</a></details></li>
<li><details id="Q0C"><summary>Q0C</summary><a href="#Q0C">Answer to Q0C</a></details></li>
</ul>
</details>
</li>
<li><details id="Q1"><summary>Q1</summary>
<ul>
<li><details id="Q1A"><summary>Q1A</summary><a href="#Q1A">Answer to Q1A</a></details></li>
<li><details id="Q1B"><summary>Q1B</summary><a href="#Q1B">Answer to Q1B</a></details></li>
<li><details id="Q1C"><summary>Q1C</summary><a href="#Q1C">Answer to Q1C</a></details></li>
</ul>
</details>
</li>
</ul>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hiding child elements inside an open details element
1. Is it "okay" / correct to hide child elements of an open details element
- Yes, there's nothing wrong with hiding an element inside a
details
element. - Actually, you may programmatically toggle the display of those hidden elements just like any other element in the page.
2. Should details
only have 1 child element, besides the summary
element?
- No, you are not limited to have only one element inside a
details
. - Also,
details
tags do not requiresummary
elements to be rendered correctly. Although it is recommended to have asummary
element in order to have your own label for thedetails
element, you can ditch thatsummary
element entirely and the browser will show its own placeholder/label (Chrome
show the text "Details" if adetails
tag doesn't contain asummary
). - In short, you can have as many elements inside a
details
but a maximum of 1summary
element.
With that being said, let's have a simple demo that illustrates the use of details
that, on its own, has a bunch of different elements. You can use the button to toggle the div
that is initially hidden:
const myDIV = document.getElementById('my-div'),
toggler = document.getElementById('toggler');
toggler.addEventListener('click', () => myDIV.classList.toggle('hidden'));
.hidden {
display: none;
}
/** just to make the demo visually appealing */
details {
border: 1px solid #aaa;
border-radius: 4px;
margin-top: 10px;
padding: .5em .5em 0;
}
summary {
font-weight: bold;
margin: -.5em -.5em 0;
padding: .5em;
cursor: pointer;
}
details[open] {
padding: .5em;
}
details[open] summary {
border-bottom: 1px solid #aaa;
margin-bottom: .5em;
}
<button id="toggler">Toggle Initially Hidden DIV</button>
<details open>
<summary>Some summary</summary>
<div>This content is display</div>
<div id="my-div" class="hidden">This content is NOT displayed and its display can be toggled</div>
<p>I have an image too!<img src="https://via.placeholder.com/150" style="display:block;margin: 10px auto 0" width="150"></p>
</details>
Is it possible to automatically declare thousands of variables in JavaScript?
This question is more of an architectural issue than a need for creating dynamic variables. Consider this example:
id
s are removed (existing class names used)- This pattern scales for
n
sentence instances - In
handleClick
, we toggle theopen
class on the clicked element, which lets us leverage the adjacent sibling selector viaCSS
- No need for a
close
class, since the absence of theopen
class represents the closed state.
let outerUL = document.querySelectorAll('.sentcontent')
function handleClick() {
this.classList.toggle('open');
}
outerUL.forEach(ul => {
ul.addEventListener('click', handleClick);
})
.sentcontent {
cursor: pointer;
}
.sentcontent.open + .infobox {
display: block;
}
.infobox {
background-color: #eee;
display: none;
padding: .25em .5em;
}
<ul class='sentcontent'>
<li class='number'>1.</li>
<li class='thesent'>Sent</li>
</ul>
<div class='infobox'>
<ul class='sentinfo'>
<li class='information'>Info</li>
<li class='infotext'><em>Info text</em></li>
</ul>
<ul class='sentinfo'>
<li class='information'>Line info</li>
<li class='line'>Line</li>
</ul>
</div>
<ul class='sentcontent'>
<li class='number'>2.</li>
<li class='thesent'>Sent</li>
</ul>
<div class='infobox'>
<ul class='sentinfo'>
<li class='information'>Info</li>
<li class='infotext'><em>Info text</em></li>
</ul>
<ul class='sentinfo'>
<li class='information'>Line info</li>
<li class='line'>Line</li>
</ul>
</div>
Detecting the opening or closing of a details element
You can use the toggle event:
var details = document.querySelector("details")
details.addEventListener("toggle", function() {
details.firstChild.textContent = "done"
})
<!doctype html>
<details>
<summary>toggle event</summary>
</details>
Related Topics
How to Move an Element That's on the Top to the Bottom in Responsive Design
Different CSS for Each Browser
Half Circle with CSS (Border, Outline Only)
Strip All HTML Tags Except Links
Why Does a Diamond with a Questionmark in It Appear in My HTML
How to Stop the Browser from Url-Encoding Form Values on Get
Changing the Text Selection Color Using CSS
How to Use the Same Meta Tag for Opengraph and Schema.Org
Link to a Section of a Webpage
Making a Paragraph in HTML Contain a Text from a File
How to Add Border to a Container with Transparent Gaps in Between
Do HTML5 Script Tag Need Type="Javascript"
If an HTML Form Has Two <Input Type="Submit"> Buttons, How to Know Which Got Clicked
Style and Script Tags in HTML Body... Why Not
Change Checkbox Check Image to Custom Image
CSS Display None and Opacity Animation with Keyframes Not Working