While the solutions above enabled me to put something together that worked in the case where the classes were being added via body_class(), I had another situation where none of them worked at all because the classes were being added by JavaScript.
Additionally I only needed to remove the classes on specific pages and could not do this by modifying or overriding the JS without potentially impacting other pages.
To solve this I added the following to the functions.php of the child theme...
<?php
// remove body classes not added through the wp body_class() function
// jQuery solution
function cbc_manage_body_classes() {
$to_remove = '';
if (is_shop()) { $to_remove .= 'class_one class_two'; }
if ( ! empty($to_remove)) {
?>
<script type="text/javascript">
jQuery(document).ready(function(){ jQuery("body").removeClass('<?php echo $to_remove; ?>'); });
</script>
<?php
}
}
add_action('wp_footer','cbc_manage_body_classes', 99);
The above jQuery solution worked perfectly for my use case. For those who need/want a JavaScript only solution, I put this together...
<?php
// remove body classes not added through the wp body_class() function
// Javascript only solution
function cbc_manage_body_classes() {
$to_remove = '';
if (is_shop()) { $to_remove .= 'class_one class_two'; }
if ( ! empty($to_remove)) {
?>
<script type="text/javascript">
window.onload = function() {
// inspiration from: https://stackoverflow.com/questions/784012/javascript-equivalent-of-phps-in-array
function cbcInArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) { if(haystack[i] == needle) return true; }
return false;
}
// inspiration from: https://stackoverflow.com/questions/13505253/how-to-remove-the-class-in-javascript
function cbcRemoveClass( elem, name ) {
var classlist = elem.className.split( /\s/ ),
namelist = name.split( /\s/ ),
newlist = [],
idx = 0;
for ( ; idx < classlist.length; idx++ ) {
if ( ! cbcInArray(classlist[ idx ], namelist) ) { newlist.push( classlist[ idx ] ); }
}
elem.className = newlist.join(" ");
return true;
}
cbcRemoveClass(document.getElementsByTagName("body")[0], '<?php echo $to_remove; ?>');
};
</script>
<?php
}
}
add_action('wp_footer','cbc_manage_body_classes', 99);
?>
And for the sake of sharing, here is what I put together for the body_class() use case using the ideas of those who posted before me.
The main difference with this code VS the posted snips is that this code enables whitelisting and blacklisting at the same time.
In the case I built this for I needed to restrict the body classes to a specific set globally and then remove others on specific pages.
<?php
//inpsired by: https://wordpress.stackexchange.com/questions/15850/remove-classes-from-body-class
function cbc_body_class_filter( $wp_classes, $extra_classes ) {
// merge $wp_classes and $extra_classes so all classes are subjected to the filtering
$classes = array_merge( $wp_classes, (array) $extra_classes );
// init list(s) of classes (not)allowed
$whitelist = $blacklist = array();
// block/remove body classes on wc shop page
// this block can be repeated for different pages
if (is_shop()) { // is_page('PAGE SLUG/NAME/ID')) {
$blacklisted = array('class-one', 'class-two');
$blacklist = array_merge($blacklist, $blacklisted);
}
// filter the body classes through the lists
// by filtering the whitelist first we can create a "master" whitelist and then remove other classes on a page by page basis
if ( ! empty($whitelist)) { $classes = array_intersect( $classes, $whitelist ); }
if ( ! empty($blacklist)) { $classes = array_diff( $classes, $blacklist ); }
return $classes;
}
add_filter( 'body_class', 'cbc_body_class_filter', 99, 2 );
?>