Reputation: 23
I have an unordered list like below :
<ul class='learningAreas'>
<li class="caret"><span><img src="/assets/img/rightarrow.png"> </span>Performance Art
<ul class='subjectRef'>
<li class="subject ACTIVE" id="PAADLB" data-status="ACTIVE"><a href="#" class="ACTIVE" title="PAADLB">(PAADLB) - Acting & Directing</a></li>
<li class="subject ACTIVE" id="PAATDY" data-status="ACTIVE"><a href="#" class="ACTIVE" title="PAATDY">(PAATDY) - Acting Design</a></li>
</ul>
</li>
<li class="caret"><span><img src="/assets/img/rightarrow.png"> </span>Visual Art
<ul class='subjectRef'>
<li class="subject ACTIVE" id="VA2DFAW" data-status="ACTIVE"><a href="#" class="ACTIVE" title="VA2DFAW">(VA2DFAW) - 2D Fine Art</a></li>
<li class="subject ACTIVE" id="VA2DMY" data-status="ACTIVE"><a href="#" class="ACTIVE" title="VA2DMY">(VA2DMY) - 2D Media</a></li>
</ul>
</li>
</ul>
The list items (Learning Areas) with class 'caret' expand/collapse into a sub-list depending on click.
I have a right arrow image in a span before the list item when a user clicks a "Learning Area" the arrow switches to a down arrow.
My problem is that when the user clicks a new "Learning Area" it should set the previous down arrow to a right arrow and the new "Learning Area" right arrow to a down arrow
The CSS works fine and I can click a "Learning Area" and the right arrow switches to a down arrow yet when I click another "Learning Area" the previously clicked arrow does not change.
My CSS is this
.rightArrow {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
display: inline-block;
}
.downArrow {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
display: inline-block;
}
My JQuery looks like this
$('ul.subjectRef').hide();
$("li > span").addClass("rightArrow");
$('.learningAreas > li').click(function(){
$('.caret').not(this).find(".subjectRef").hide();
$(this).find(".subjectRef").toggle();
$(this).find(".rightArrow").toggleClass("downArrow");
});
Where am I going wrong? I have tried .hasClass with .addClass and .removeClass but am just going around in circles. I somehow need to know what was the previously clicked item and change its arrows.
any help would be appreciated Thanks John
Upvotes: 2
Views: 85
Reputation: 13623
I made the following adjustments to your script:
$('.learningAreas > li').click(function() {
// use variables to cache our collections for performance and clarity
const clickedListElement = $(this);
const otherListElements = $('.caret').not(this);
// find the .subjectRef in the other list elements and hide it
otherListElements.find(".subjectRef").hide();
// find the .downArrow classed image in the other list elements and toggle the down arrow class
otherListElements.find(".downArrow").toggleClass("downArrow");
// toggle on the current list item
clickedListElement.find(".subjectRef").toggle();
clickedListElement.find(".rightArrow").toggleClass("downArrow");
});
You can see it in action below:
$('ul.subjectRef').hide();
$("li > span").addClass("rightArrow");
$('.learningAreas > li').click(function() {
// use variables to cache our collections for performance and clarity
const clickedListElement = $(this);
const otherListElements = $('.caret').not(this);
// find the .subjectRef in the other list elements and hide it
otherListElements.find(".subjectRef").hide();
// find the .downArrow classed image in the other list elements and toggle the down arrow class
otherListElements.find(".downArrow").toggleClass("downArrow");
// toggle on the current list item
clickedListElement.find(".subjectRef").toggle();
clickedListElement.find(".rightArrow").toggleClass("downArrow");
});
.rightArrow {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
display: inline-block;
}
.downArrow {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class='learningAreas'>
<li class="caret"><span><img src="https://i.imgur.com/APHeUQH.png"> </span>Performance Art
<ul class='subjectRef'>
<li class="subject ACTIVE" id="PAADLB" data-status="ACTIVE"><a href="#" class="ACTIVE" title="PAADLB">(PAADLB) - Acting & Directing</a></li>
<li class="subject ACTIVE" id="PAATDY" data-status="ACTIVE"><a href="#" class="ACTIVE" title="PAATDY">(PAATDY) - Acting Design</a></li>
</ul>
</li>
<li class="caret"><span><img src="https://i.imgur.com/APHeUQH.png"> </span>Visual Art
<ul class='subjectRef'>
<li class="subject ACTIVE" id="VA2DFAW" data-status="ACTIVE"><a href="#" class="ACTIVE" title="VA2DFAW">(VA2DFAW) - 2D Fine Art</a></li>
<li class="subject ACTIVE" id="VA2DMY" data-status="ACTIVE"><a href="#" class="ACTIVE" title="VA2DMY">(VA2DMY) - 2D Media</a></li>
</ul>
</li>
<li class="caret"><span><img src="https://i.imgur.com/APHeUQH.png"> </span>Performance Art
<ul class='subjectRef'>
<li class="subject ACTIVE" id="PAADLB" data-status="ACTIVE"><a href="#" class="ACTIVE" title="PAADLB">(PAADLB) - Acting & Directing</a></li>
<li class="subject ACTIVE" id="PAATDY" data-status="ACTIVE"><a href="#" class="ACTIVE" title="PAATDY">(PAATDY) - Acting Design</a></li>
</ul>
</li>
</ul>
This works, but you could probably extract some of this behavior into functions to structure it a bit better, if you think you might have more DOM pieces to shuffle around for each operation. As it is it will do a needless iteration on .otherListElements
when the user clicks the currently open item to toggle it.
Upvotes: 1