Issue
So lately I've been trying to make a "SHOW MORE" and "SHOW LESS" feature with embedded SVG.
The code seems to be working fine, although each time I add another button I have to create completly new function therefore I was wondering if you could help me optimize my code.
Currently it looks like this:
<!-- HTML CODE -->
<button id="hideShow" class="button slide-down">SHOW MORE
<svg id="showMoreSVG" width="13px" height="10px" viewBox="0 2 13 10">
<path id="showMorePATH" d="M 1 5 L 1 5 L 5 9 L 9 5 L 5 9"></path>
</svg>
</button>
// js code
var button = document.getElementById("hideShow");
var content = document.getElementById("more-text");
let text = button.innerHTML.replace("MORE", "LESS");
let textR = button.innerHTML.replace("LESS", "MORE");
button.onclick = function () {
if (content.className == "open") {
content.className = "";
document.getElementById("hideShow").innerHTML = textR;
document.getElementById("showMoreSVG").setAttribute("viewBox", "0 2 13 10");
document
.getElementById("showMorePATH")
.setAttribute("d", "M 1 5 L 1 5 L 5 9 L 9 5 L 5 9");
} else {
content.className = "open";
document.getElementById("hideShow").innerHTML = text;
document
.getElementById("showMoreSVG")
.setAttribute("viewBox", "0 -2 13 10");
document
.getElementById("showMorePATH")
.setAttribute("d", "M 1 5 L 1 5 L 5 1 L 9 5 L 5 1");
}
};
Result as img:
It works based on changing max-height property in css class that is different depending on size of text (some are smaller, some are larger). For example:
#more-text,
#more-text2 {
max-height: 0px;
overflow: hidden;
transition: max-height 0.7s ease;
}
#more-text.open {
max-height: 1600px;
transition: max-height 0.7s ease;
}
#more-text2.open {
max-height: 600px;
}
I know that the part of css code can be optimized with jQuery but I don't want to implement it on my website. Rather vanilla javascript or some npm package.
Also I do realize that content.className = "open";
is invalid way to change class, this is something I have on my todo list so please don't bother with that part.
Any help is much appreciated.
Solution
Here's a reusable way to do it (though I can't seem to test the SVG - I may have gotted the up/down confused). Basically you initialize all more/less buttons at once (in case there are more than one) and you structure your HTML so each more/less instance is in it's own container. Then you can use closest(selector) and querySelector(selector) to target the elements you want without using all those ID tags - the ID tags are usefull for somethings but in your case you were reusing them which is strictly forbidden. There's no need for them as you can see.
// js code
let buttons = document.querySelectorAll(".hideShow");
buttons.forEach(button => button.addEventListener('click', e => {
let content = e.target.closest('.hs-container').querySelector('.inner-content');
let closeme = content.classList.contains('open');
content.classList.toggle('open')
e.currentTarget.querySelector('span').innerText = closeme ? "SHOW MORE" : "SHOW LESS";
let att = closeme ? ["0 -2 13 10", "M 1 5 L 1 5 L 5 1 L 9 5 L 5 1"] : ["0 2 13 10", "M 1 5 L 1 5 L 5 9 L 9 5 L 5 9"];
e.currentTarget.querySelector('.icon').setAttribute('viewBox', att[0])
e.currentTarget.querySelector('.icon path').setAttribute('d', att[1])
}));
.inner-content {
max-height: 0px;
overflow: hidden;
transition: max-height 0.7s ease;
}
.open {
max-height: 1600px;
transition: max-height 0.7s ease;
}
svg.icon {
width: 13px;
height: 10px;
}
<div class='hs-container'>
<div class='inner-content'>Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah</div>
<button class="button slide-down hideShow"><span>SHOW MORE</span>
<svg class="icon" viewBox="0 2 13 10">
<path d="M 1 5 L 1 5 L 5 9 L 9 5 L 5 9"></path>
</svg>
</button>
</div>
Answered By - Kinglish
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.