Thanks to some wonderful help here at stack exchange, I have built a comment section with a dropdown menu that adds comment_meta to the comments.
I currently have a working filter that uses GET
to trigger an if
statement to query based on this comment_meta info. The thing I don't like is that it refreshes the page each time you click a button. I'm looking for a way to filter without having the page refresh. I think I need Javascript for this.
I've set up two sets of buttons. The top row is my GET
buttons, which work, but refresh the page. The bottom row are my javascript
buttons. I can get them to filter the text WITHIN the comments, but I'd like them to filter the entire contents instead.
For instance, if you go to Madonna's page (https://staging3.recordcollectorsoftheworldunite.com/artist/madonna/), and scroll down to the comments, they don't even show up until you press 'show all'. Once you press "Show All" it looks right, but again when you filter, it only filters the comments.
I've added 3 photos to the bottom of this post.
-First photo is when the page loads, how all the comments are hidden- I'd like "ALL" to automatically be selected when the page loads. I tried <button class='button active'>
but that must not be the right way to say it.
-Second photo is when "SHOW ALL" is clicked
-Third photo is when "BUY" is clicked.
Here's my comments.php
<?php
comment_form();
if (have_comments()) : ?>
<div class="container">
<div class="btn-group flex">
<button type="button" onclick="window.location.href='<?php echo the_permalink();?>/?cmeta=ALL'">SHOW ALL</button>
<button type="button" onclick="window.location.href='<?php echo the_permalink();?>/?cmeta=BUY'">BUY</button>
<button type="button" onclick="window.location.href='<?php echo the_permalink();?>/?cmeta=SELL'">SELL</button>
<button type="button" onclick="window.location.href='<?php echo the_permalink();?>/?cmeta=TRADE'">TRADE</button>
<button type="button" onclick="window.location.href='<?php echo the_permalink();?>/?cmeta=TALK'">TALK</button>
</div>
</div>
<hr>
<div class="container">
<div class="btn-group flex">
<button class="button active" onclick="filterSelection('all')"> Show all</button>
<button class="button" onclick="filterSelection('BUY')"> BUY</button>
<button class="button" onclick="filterSelection('SELL')"> SELL</button>
<button class="button" onclick="filterSelection('TRADE')"> TRADE</button>
<button class="button" onclick="filterSelection('TALK')"> TALK</button>
</div>
</div>
<style>
.filterDiv {
display: none;
}
.show {
display: block;
}
.container {
margin-top: 20px;
overflow: hidden;
}
</style>
<script>
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
// Add the "show" class (display:block) to the filtered elements, and remove the "show" class from the elements that are not selected
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
// Show filtered elements
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {
element.className += " " + arr2[i];
}
}
}
// Hide elements that are not selected
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current control button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
</script>
<?php
if(isset($_GET['cmeta'])){
$commentmeta=$_GET['cmeta'];
if($commentmeta=='ALL'){
$wantto= get_comment_meta( $comment_id, 'wantto', true );
$args = array(
'post_id' => get_the_ID(),
);
}else{
$wantto= get_comment_meta( $comment_id, 'wantto', true );
$args = array(
'post_id' => get_the_ID(),
'meta_query' => array(
array(
'key' => 'wantto',
'value' => $commentmeta,
),
)
);
}
$comment_query = new WP_Comment_Query( $args );
$comments = $comment_query->comments;
echo '<ol class="post-comments">';
wp_list_comments(array(
'style' => 'ol',
'short_ping' => true,
));
echo $wantto;
echo '</ol>';
/* much simpler one to style probably
if ( $comments ) {
foreach ( $comments as $comment ) {
echo '<p>' . $comment->comment_content . '</p>';
}
} else {
echo 'No comments found.';
}
*/
}else{
$wantto= get_comment_meta( $comment_id, 'wantto', true );
echo '<ol class="post-comments">';
wp_list_comments(array(
'style' => 'ol',
'short_ping' => true,
));
echo $wantto;
echo '</ol>';
}
endif;
$comment_id=get_comment_ID();
echo $wantto;
?>
Here's the section from my functions.php
that adds the dropdown menu, and filters by type. I've added the filterDiv
tag in the second function of this part. Where I have it now only filters the text, I'd like it to filter the entire comment itself.
/*
* This will add the fields to the comment form
*/
function wpse406058_custom_comment_fields() {
echo '<p class="comment-form-wantto">';
echo '<label for="wantto">Tag your comment so other users can find your post.<br>I want to</label>';
echo '<select id="wantto" name="wantto" class="myclass">';
echo '<option value="---">---</option>';
echo '<option value="BUY">BUY</option>';
echo '<option value="SELL">SELL</option>';
echo '<option value="TRADE">TRADE</option>';
echo '<option value="TALK">TALK</option>';
echo '</select>';
}
add_action( 'comment_form_logged_in_after', 'wpse406058_custom_comment_fields' );
add_action( 'comment_form_after_fields', 'wpse406058_custom_comment_fields' );
/*
* This will field value as comment meta
*/
function wpse406058_save_custom_field($comment_id) {
if ( isset($_POST['wantto']) && !empty($_POST['wantto']) ) {
$wantto = sanitize_text_field($_POST['wantto']);
update_comment_meta( $comment_id, 'wantto', $wantto );
}
}
add_action( 'comment_post', 'wpse406058_save_custom_field' );
function wpse406058_display_comment_meta( $comment_text ) {
$wantto = get_comment_meta( get_comment_ID(), 'wantto', true );
if ( isset($wantto) && !empty($wantto) ) {
$wanttotext = '<p class="wantosec">I want to ' . esc_html($wantto) . '</p>';
?><div class="filterDiv <?php echo $wantto;?>"><?php
$comment_text = $wanttotext . $comment_text;
}
echo '<div class="container">';
return $comment_text;
echo '</div>';
echo '</div>';
}
add_filter( 'comment_text', 'wpse406058_display_comment_meta' );
<div>
instead of the content, either by modifying the selector or using JS DOM traversal. If you'd like to modify the markup generated for comments, you could pass thecallback
argument towp_list_comments()