I need to dynamically add an active class to a shortcode in wordpress based on the active number set in it’s parent shortcode.
The parent looks like this:
$active = 3;
$output .= "ntt".wpb_js_remove_wpautop($content);
The $content variable can technically consist of anything in between the shortcodes tags, but specifically, should include more child shortcodes (it’s a tabs shortcode so the parent is tabs and the children are tab).
What I need to do is parse $content
and replace the Nth ($active
variable) instance of [vc_tab
with [vc_tab active="true"
I realize there are better ways to design the shortcode to compensate for this but I am limited in what I can do because I am modifying Visual Composer to use Bootstrap tabs instead of jQuery and Bootstrap tabs need the active class on both the <li>
and the <div class="tab-pane">
elements but I don’t want the users to have to add an active number to the parent shortcode and an active true/false to the child as that will get confusing.
So far from googling I can only find replacing the first occurrence or all occurrences, not the Nth one.
Temporarily I am using jQuery to make the appropriate <div>
active but it results in an undesirable FOUC where there is no pane visible on load and then one pops into place when the jQuery runs.
$('.tabs-wrap').each(function(){
var activeTab = $(this).find('.tabbed li.active a').attr('href');
$(this).find(activeTab).addClass('active');
});
This is an interesting problem, and got me thinking if you really need a regex to do this.
My conclusion is that I don’t believe you do. All you need to do is find the occurrence of the
Nth
$needle
, and replace it with your replacement. This can be achieved through some simple string manipulation, as follows:Define some variables. Your input string, your
$active
index, the$needle
that we are looking for, and the$replace
ment that we will replace theNth
match with.Now, we need to make sure that there are enough
$needle
s in the$string
, otherwise we can’t do this replacement.Now, we know we can do the replacement. So let’s find the
$index
in the string where theNth
occurrence of$needle
ends:Now,
$index
is pointing here in the string:We can now do some simple
substr()
‘s to form the final string:So, we end up concatenating:
[vc_tab [vc_tab
[vc_tab active="true"
[vc_tab [vc_tab [vc_tab
This results in our final output:
Try it out in the demo!
I ‘m not familiar with the tools you mention so I can’t say if there is a better way to achieve the end goal, but you can replace the Nth occurrence of something using
preg_replace_callback
:See it in action.
This works by replacing each occurrence with itself unless the occurrence counter is equal to the target number.
Note that I have passed
$active
as the maximum number of occurrences to replace in order to get free performance increase; this will causepreg_replace_callback
to stop after$active
occurrences have been replaced (we know that all occurrences after that will be replaced by themselves, so there’s no point in going on).