Reputation: 3
This code works fine when there're classes for toggle function only but when I add classes for other function, it fails to toggle. I found out if there's a space besides a "toggle class"(like "button-10ac "), it fails. I have no idea what's wrong. Please help!
Here's my HTML code
<div class="button-01a in">button1</div>
<div class="button-05i out">button2</div>
<div class="button-10ac ">button3</div>
<div class="button-01a info-01a in" style="display:none;">info1</div>
<div class="button-05i info-05i in" style="display:none;">info2</div>
<div class="button-10ac info-10ac out" style="display:none;">info3</div>
and JavaScript/jQuery code
$("[class^=button-]").click(function(){
if($('.info-'+ this.className.match(/(\w+)+$/)[0]).is(':visible')){
$('.info-'+ this.className.match(/(\w+)+$/)[0]).hide()
}
else{
$("[class*='info-']").hide();
$('.info-'+ this.className.match(/(\w+)+$/)[0]).show()
}
})
JSFiddle: Link
Upvotes: 0
Views: 49
Reputation: 129
The first problem is, that the regular expression is matching for a word character sequence, which MUST end at the end of the line and in this case also the end of the string. This is known by observing the last character of the regular expression, $
.
See for more information about $
in regular expressions: https://stackoverflow.com/a/13912609/4132642.
Working code:
$("[class^=button-]").click(function(){
let classNameRegex = /button-(\w*)/;
let classNamePart = this.className.match(classNameRegex)[1];
if($('.info-'+ classNamePart).is(':visible')){
$('.info-'+ classNamePart).hide()
}
else{
$("[class*='info-']").hide();
$('.info-'+ classNamePart).show()
}
})
Upvotes: 0
Reputation: 1074385
I think you're trying to use those first three divs to toggle the other divs so only one is showing at a time. Instead of using complicated partial class matching, I'd use a single class to identify the buttons, another single class to identify the targets, and then an additional class to differentiate the targets, probably with a data-*
attribute on the button indicating which one it should toggle:
$(".button").on("click", function() {
var cls = "." + $(this).attr("data-toggle");
$(".info:not(" + cls + ")").hide();
$(".info" + cls).show();
});
<div class="button in" data-toggle="x01a">button1</div>
<div class="button out" data-toggle="x05i">button2</div>
<div class="button" data-toggle="x10ac">button3</div>
<div class="info x01a in" style="display:none;">info1</div>
<div class="info x05i in" style="display:none;">info2</div>
<div class="info x10ac out" style="display:none;">info3</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Note that I added an x
in front of 01a
and such, so that I could use a class selector. (A class name in a class selector can't start with an unescaped digit; we could escape the digit, but it's simpler just to add the x
.)
But if you're stuck with those existing classes:
// WARNING: Fragile! If you change the markup so that the button-xyz
// class isn't the *first* in the attribute, this
// fails!
$("div[class^=button]")
// Filter out the targets
.filter(function() {
return !/(?:^| )info-[^ ]+(?:$| )/.test(this.className);
})
.on("click", function() {
var cls = "info-" + this.className.match(/(?:^| )button-([^ ]+)(?:$| )/)[1];
if (cls) {
$("div[class^=button][class*=info]:not([class*=" + cls + "]").hide();
$("div[class^=button][class*=" + cls + "]").show();
}
});
<div class="button-01a in">button1</div>
<div class="button-05i out">button2</div>
<div class="button-10ac ">button3</div>
<div class="button-01a info-01a in" style="display:none;">info1</div>
<div class="button-05i info-05i in" style="display:none;">info2</div>
<div class="button-10ac info-10ac out" style="display:none;">info3</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
...but I wouldn't do it that way. :-)
Upvotes: 1