I am trying to toggle a div with an arrow; this is the code I have so far:
$('.hide-show').hide();
$('.toggle-year').on('click', function() {
$(this).html($(this).text().substr(0, 4) == 'Hide' ? '▼' : 'Hide ▲');
$('.hide-show').toggle('slow');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="javascript:void(0)" class="toggle-year">▼</a>
<div class="hide-show">
Content comes here
</div>
This example works fine but needs the text Hide
to change the arrow back to downwards. How can I strip out the text Hide
(so arrows only?)
The easiest way is to remove all the text that you don't want, and then just compare whether the text is currently-equal to either the up, or down, arrow:
// hides the text to be hidden on page-load:
$('.hide-show').hide();
// selects all elements matching the supplied CSS selector
// and binds the anonymous function of the on() method
// as the event-handler for the 'click' event:
$('.toggle-year').on('click', function() {
$(this).text(function(_, currentText) {
// _ is the index of the current element amongst
// all the elements retrieved in the jQuery collection;
// currentText is a reference to the current textContent
// of the current element from the jQuery collection.
// here we use a conditional operator to update the
// text of the current element. If the currentText is
// equal to '▼' then we change it to '▲' and if it
// is not equal to '▼' then we set it to '▼':
return currentText == "▼" ? "▲" : "▼";
});
// and then we toggle the visibility of the hidden
// element(s):
$('.hide-show').toggle('slow');
});
/* we're using a <button> instead of an <a> as we're not
navigating to a new area of the website, so here we're
styling it to appear similar to an <a> (assuming that's
your preference): */
button.toggle-year {
border: 0;
background-color: inherit;
text-decoration: underline;
color: #00f;
outline: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- as mentioned in the CSS, above, because we're not using
the element for navigation but instead for functionality,
I've replaced the <a> with a <button>: -->
<button class="toggle-year">▼</button>
<div class="hide-show">
Content comes here
</div>
Anything that can be achieved with jQuery can, of course, be similarly achieved by native JavaScript; with that in mind the following shows one means by which plain JavaScript might be used instead:
// I cache a reference to the document as 'D' because I'm lazy and don't want
// to type 'document' more than I have to:
const D = document,
// here we define the toggleVisibility function, using Arrow function syntax
// since we don't really need a reference to 'this', and we get an indirect
// access via the Event Object passed from EventTarget.addEventListener()
// function later:
toggleVisibility = (e) => {
// e.target is the element that initiated the click action (in this
// instance e.currentTarget would also have worked):
const clicked = e.target,
// caching a reference to the current textContent of that clicked
// element:
text = clicked.textContent,
// caching a reference to the element(s) that we intend to show/hide:
elementsToHide = D.querySelectorAll('.hide-show'),
// we're using this test in two places, so cache the result of the
// comparison/assessment:
shouldChange = text == '▼';
// iterating over the collection of elements we found earlier, using
// NodeList.protoype.forEach():
elementsToHide.forEach(
// again using an Arrow function syntax:
(el) => {
// if the shouldChange variable is true/truthy (in this case it's
// Boolean true, but it would also work with truthy/falsey values)
// we change the display of the current Node in the NodeList to
// 'block', otherwise if shouldChange is false then we set the
// display to 'none' in order to hide it:
el.style.display = shouldChange ? 'block' : 'none';
// here if shouldChange is true we update the text-content to
// '▲', otherwise we change it to '▼':
clicked.textContent = shouldChange ? '▲' : '▼';
});
},
// here we retrieve the <button> elements with the class-name of 'toggle-year':
toggleButtons = D.querySelectorAll('button.toggle-year');
// and then use NodeList.prototype.forEach() to iterate over that collection:
toggleButtons.forEach(
// again, we use Arrow syntax and bind the toggleVisibility() function (but
// do note the deliberate lack of parentheses below) as the event-handler for
// the 'click' event:
(button) => button.addEventListener('click', toggleVisibility)
);
button.toggle-year {
border: 0;
background-color: inherit;
text-decoration: underline;
color: #00f;
outline: 0;
}
.hide-show {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="toggle-year">▼</button>
<div class="hide-show">
Content comes here
</div>
References: