0

I'm trying to initialise isotope https://isotope.metafizzy.co/ in Wordpress so I can start filtering posts based on their categories. I think I'm missing some php in the <a href='#' data-filter='.".$term->slug."'>" . $term->name . "</a> section because when i click on the category it gives me a /# instead of filtering the categories. I'm really trying to achieve this filtering effect: https://nmbw.com.au/works-and-projects/

I'm new to this so any help would be really appreciated.

Here's what I have:

<?php
/**
 * Template Name: isotope
 *
 * Template for displaying a page without sidebar even if a sidebar widget is published.
 *
 * @package understrap
 */

get_header();
$container = get_theme_mod( 'understrap_container_type' );
?>

<ul id="filters">
    <li><a href="#" data-filter="*">All categories</a></li>
<?php
$terms = get_terms("category"); // get all categories, but you can use any taxonomy
$count = count($terms); //How many are they?
if ( $count > 0 ){  //If there are more than 0 terms
foreach ( $terms as $term ) {  //for each term:
echo "<li><a href='#' data-filter='.".$term->slug."'>" . $term->name . "</a></li>\n";
//create a list item with the current term slug for sorting, and name for label
}
}
?>
</ul>


<?php $the_query = new WP_Query( 'posts_per_page=9' ); //Check the WP_Query docs to see how you can limit which posts to display ?>
<?php if ( $the_query->have_posts() ) : ?>
    <div id="isotope-list">
    <?php while ( $the_query->have_posts() ) : $the_query->the_post();
$termsArray = get_the_terms( $post->ID, "category" );  //Get the terms for this particular item
$termsString = ""; //initialize the string that will contain the terms
foreach ( $termsArray as $term ) { // for each term
$termsString .= $term->slug.' '; //create a string that has all the slugs
}
?>
<div class="<?php echo $termsString; ?> item">
<h3><?php the_title(); ?></h3>
        <?php if ( has_post_thumbnail() ) {
                      the_post_thumbnail();
                } ?>
</div> <!-- end item -->
    <?php endwhile;  ?>
    </div> <!-- end isotope-list -->
<?php endif; ?>
<?php get_footer(); ?>

This is what I have in my functions.php file

function add_isotope() {
wp_register_script( 'isotope', get_template_directory_uri().'/js/libs/isotope.pkgd.min.js', array('jquery'),  true );
wp_register_script( 'isotope-init', get_template_directory_uri().'/js/isotope.js', array('jquery', 'isotope'),  true );
wp_register_script( 'isotope-custom', get_template_directory_uri().'/js/isotope-custom.js', array('jquery', 'isotope'),  true );
wp_register_style( 'isotope-css', get_stylesheet_directory_uri() . '/css/isotope.css' );

wp_enqueue_script('isotope-init');
wp_enqueue_style('isotope-css');
}

add_action( 'wp_enqueue_scripts', 'add_isotope' );  

This is in my isotope-custom.js file

jQuery(function ($) {

var $container = $('#isotope-list'); //The ID for the list with all the 
blog posts
$container.isotope({ //Isotope options, 'item' matches the class in the 
PHP
itemSelector : '.item', 
layoutMode : 'masonry'
});

//Add the class selected to the item that is clicked, and remove from 
the others
var $optionSets = $('#filters'),
$optionLinks = $optionSets.find('a');

$optionLinks.click(function(){
var $this = $(this);
// don't proceed if already selected
if ( $this.hasClass('selected') ) {
return false;
}
var $optionSet = $this.parents('#filters');
$optionSets.find('.selected').removeClass('selected');
$this.addClass('selected');

//When an item is clicked, sort the items.
var selector = $(this).attr('data-filter');
$container.isotope({ filter: selector });

return false;
});

});

This is in the isotope.js file `jQuery(function ($) {

 //set the container that isotope will be inside of in a var

 var container = document.querySelector('#isotope-list');

 //create empty var isotope

 var Isotope;

 // initialize Isotope after all images have loaded
 var $container = $('#isotope-list').imagesLoaded( function() {
 $container.isotope({
 // options
 });
 });




 var $container = $('#isotope-list'); //The ID for the list with all 
 the blog posts
 $container.isotope({ //Isotope options, 'item' matches the class in 
 the PHP
 itemSelector : '.item',
 layoutMode : 'masonry',
 isOriginLeft: false
 });
 var container = document.querySelector('#isotope-list');
 // init
 var iso = new Isotope( container, {
 // options
 itemSelector: '.item',

 });

 //Add the class selected to the item that is clicked, and remove from 
 the others
 var $optionSets = $('#filters'),
 $optionLinks = $optionSets.find('a');

  $optionLinks.click(function(){
  var $this = $(this);
  // don't proceed if already selected
  if ( $this.hasClass('selected') ) {
  return false;
  }
  var $optionSet = $this.parents('#filters');
  $optionSets.find('.selected').removeClass('selected');
  $this.addClass('selected');

  //When an item is clicked, sort the items.
  var selector = $(this).attr('data-filter');
  $container.isotope({ filter: selector });

  return false;
  });

  });

  jQuery( function($) {

  $('.isotope').isotope({
  itemSelector: '.item',
  masonry: {
  columnWidth: 100
  }
  });

  });`
4
  • Could you please elaborate why do you have a certain expectation about PHP output and what happens differently/unexpectedlyt? This is hard to follow for someone who isn’t familiar with Isotope specifics.
    – Rarst
    Commented Jul 6, 2017 at 8:24
  • Hi @Rarst what i assumed turned out to be wrong after running some tests. Isotope allows you to filter categories which is what I'm trying to achieve. Here's their website: isotope.metafizzy.co
    – Dnbl_
    Commented Jul 6, 2017 at 8:57
  • Can you add to your question the javascript code you're using for initialising isotope and also the javascript code for the filters links?
    – dbeja
    Commented Jul 6, 2017 at 14:26
  • Hi @dbeja i've just edited my initial post with what im using to initialise isotope
    – Dnbl_
    Commented Jul 9, 2017 at 11:58

1 Answer 1

0

Try to prevent the default behaviour of the click event using jQuery right from the beginning:

jQuery(function ($) {

var $container = $('#isotope-list'); //The ID for the list with all the 
blog posts
var $isotope = $container.isotope({ //Isotope options, 'item' matches the class in the 
PHP
itemSelector : '.item', 
layoutMode : 'masonry'
});

//Add the class selected to the item that is clicked, and remove from 
the others
var $optionSets = $('#filters'),
$optionLinks = $optionSets.find('a');

$optionLinks.click(function(e){
e.preventDefault();
var $this = $(this);
// don't proceed if already selected
if ( $this.hasClass('selected') ) {
return false;
}
var $optionSet = $this.parents('#filters');
$optionSets.find('.selected').removeClass('selected');
$this.addClass('selected');

//When an item is clicked, sort the items.
var selector = $(this).attr('data-filter');
$isotope.isotope({ filter: selector });

return false;
});

});
15
  • Thanks @dbeja, that seems to have initialised isotope properly but am now getting Uncaught TypeError: Isotope is not a constructor in my Chrome console
    – Dnbl_
    Commented Jul 9, 2017 at 12:48
  • I think it's because $container isn't a isotope element. What if on the top of your script you save the isotope to a new variable var isotope = $container.isotope... And then on the click event of the filter you use instead isotope.isotope...
    – dbeja
    Commented Jul 9, 2017 at 14:17
  • Thanks @dbeja. How would I go about doing that? I'm new to web dev! Thanks
    – Dnbl_
    Commented Jul 10, 2017 at 0:18
  • I edit my answer to include all your js code with both modifications (preventDefault and $isotope). See if it helps.
    – dbeja
    Commented Jul 10, 2017 at 6:20
  • Sorry I'm still a bit confused. I've put in that edited js code but I'm still getting the Uncaught TypeError: Isotope is not a constructor error
    – Dnbl_
    Commented Jul 10, 2017 at 9:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.