Search code examples
jqueryjquery-isotopetoggleclass

Toggle multiple classes with prevAll(), nextAll(), slice(), and duplicate classes... better way?


Ultimately, I am creating a grid that is made up of squares whereby when a user hovers over a square it and a set number of squares around it are zoomed.

Currently, I'm using isotrope.js to lay it out in a grid (Will have to change to custom layout later) and toggling the multiple classes by using prevAll and nextAll plus several slices.

There are 5 sizes of squares in all. 25px base, 200px for active, 100px, 75px, and 50px, with the end result being squares organized around the active largest to smallest (eventually).

For now I've got the right divs doing the right thing in terms of swapping classes, but it seems like there's probably a better way.

UPDATED: JSFiddle with js updates from rdubya: http://jsfiddle.net/gtf8xh61/

Here was my original js:

  $( function() {

  var $container = $('.isotope').isotope({
    itemSelector: '.item',

  });

  $('.item').click(function() {

    $( this ).toggleClass('zoom200');
    $( this ).prev().toggleClass('zoom100');
    $( this ).prevAll().slice(5, 8).toggleClass('zoom100');
    $( this ).prevAll().slice(11, 12).toggleClass('zoom75');
    $( this ).prevAll().slice(15, 16).toggleClass('zoom75b');
    $( this ).prevAll().slice(1, 5).toggleClass('zoom50');
    $( this ).prevAll().slice(8, 10).toggleClass('zoom50b');
    $( this ).prevAll().slice(19, 22).toggleClass('zoom50c');
    $( this ).prevAll().slice(12, 15).toggleClass('zoom50d');
    $( this ).next().toggleClass('zoom100');
    $( this ).nextAll().slice(5, 8).toggleClass('zoom100');
    $( this ).nextAll().slice(11, 12).toggleClass('zoom75');
    $( this ).nextAll().slice(15, 16).toggleClass('zoom75b');
    $( this ).nextAll().slice(1, 5).toggleClass('zoom50');
    $( this ).nextAll().slice(8, 10).toggleClass('zoom50b');
    $( this ).nextAll().slice(19, 22).toggleClass('zoom50c');
    $( this ).nextAll().slice(12, 15).toggleClass('zoom50d');
    $container.isotope('layout')
  });

});

Solution

  • If you post your html I can try to come up with another solution for the logic (if there is one), but until then, you can clean up the current js with the following:

    $( function() {
    
      var $container = $('.isotope').isotope({
        itemSelector: '.item'
      });
    
      $('.item').click(function() {
        var $this = $(this),
            $following = $this.nextAll(),
            $preceding = $this.prevAll();
    
        $this.toggleClass('zoom200');
    
        $this.prev().toggleClass('zoom100');
        $preceding.slice(5, 8).toggleClass('zoom100');
        $preceding.slice(11, 12).toggleClass('zoom75');
        $preceding.slice(15, 16).toggleClass('zoom75b');
        $preceding.slice(1, 5).toggleClass('zoom50');
        $preceding.slice(8, 10).toggleClass('zoom50b');
        $preceding.slice(19, 22).toggleClass('zoom50c');
        $preceding.slice(12, 15).toggleClass('zoom50d');
    
        $this.next().toggleClass('zoom100');
        $following.slice(5, 8).toggleClass('zoom100');
        $following.slice(11, 12).toggleClass('zoom75');
        $following.slice(15, 16).toggleClass('zoom75b');
        $following.slice(1, 5).toggleClass('zoom50');
        $following.slice(8, 10).toggleClass('zoom50b');
        $following.slice(19, 22).toggleClass('zoom50c');
        $following.slice(12, 15).toggleClass('zoom50d');
    
        $container.isotope('layout')
      });
    
    });
    

    This will reduce the number of new objects created and speed up the execution.

    UPDATE: I'm not able to come up with a better solution logically, but here is another possible solution that will reduce some duplication and make it easier to maintain if you don't have a need for the preceding and following siblings to have different classes applied:

    $(function () {
    
        var $container = $('.isotope').isotope({
            itemSelector: '.item'
        });
    
        var CLASSES = [
            { start: 0, end: 1, name: 'zoom100'},
            { start: 1, end: 5, name: 'zoom50'},
            { start: 5, end: 8, name: 'zoom100'},
            { start: 8, end: 10, name: 'zoom50b'},
            { start: 11, end: 12, name: 'zoom75'},
            { start: 12, end: 15, name: 'zoom50d'},
            { start: 15, end: 16, name: 'zoom75b'},
            { start: 19, end: 22, name: 'zoom50c'}
        ];
    
        $('.item').click(function () {
            var $this = $(this),
                $following = $this.nextAll(),
                $preceding = $this.prevAll();
    
            for(var i = 0; i < CLASSES.length; i++) {
                $preceding.slice(CLASSES[i].start, CLASSES[i].end).toggleClass(CLASSES[i].name);
                $following.slice(CLASSES[i].start, CLASSES[i].end).toggleClass(CLASSES[i].name);
            }
    
            $this.toggleClass('zoom200');
            $container.isotope('layout')
        });
    
    });