matchMedia to enable/disable script on viewport resize

I want to run a script dependant on the width of the viewport. I would like this to happen not just on page load but also if the browser is resized and the specified width is less/greater than.

Here’s an example of what I have: https://codepen.io/moy/pen/jOGGBwe

Ignore the UI for now …that’s a ‘work in progress’ and there are problems with it (another post coming soon, I’m sure)!

A min-width is used so when the viewport crosses that value, the code should run or stop running. In the example, if you load the page above/below the threshold. The desired result is achieved. However, if I load the page and shrink the viewport below 1080px wide, the script still runs - until I refresh the page.

If I load the page below 1080px, the script doesn’t load and when resizing the viewport to a value greater than the threshold, it kicks it. But again reducing the width doesn’t stop it running.

So I feel like I need an else maybe to prevent the script from running but I haven’t been able to get that to work. Or maybe the script needs a ‘name’ and only that is within the if/else statements to disable/able…

I’m well out of my comfort zone here so any advice will be greatly appreciated!

Isolated JS:

// Create a condition that targets viewports at least 1080px wide
const mediaQuery = window.matchMedia('(min-width: 1080px)')

function viewportChange(e) {
  // Check if the media query is true
  if (e.matches) {

$(document).ready(function() {

  var num_children = $('.split-loop__left').children().length;
  var child_height = $('.split-loop__right').height() / num_children;
  var half_way = num_children * child_height / 2;
  $(window).scrollTop(half_way);

  function crisscross() {
      
      var parent = $(".split-loop");//.first();
      var clone = $(parent).clone();
      
      var leftSide = $(clone).find('.split-loop__left');
      var rightSide = $(clone).find('.split-loop__right');

      if (window.scrollY > half_way ) {
          //We are scrolling up
          $(window).scrollTop(half_way - child_height);
          
          var firstLeft = $(leftSide).children().first();
          var lastRight = $(rightSide).children().last();
          
          lastRight.appendTo(leftSide);
          firstLeft.prependTo(rightSide);

      } else if (window.scrollY < half_way - child_height) {

          var lastLeft = $(leftSide).children().last();
          var firstRight = $(rightSide).children().first();
          
          $(window).scrollTop(half_way);
          lastLeft.appendTo(rightSide);
          firstRight.prependTo(leftSide);
      }

      $(leftSide).css('bottom', '-' + window.scrollY + 'px');
      $(rightSide).css('bottom', '-' + window.scrollY + 'px');

      $(parent).replaceWith(clone);        
  }
  
  $(window).scroll(crisscross);

});
}
}

// Register event listener
mediaQuery.addListener(viewportChange)

// Initial check
viewportChange(mediaQuery)

I think you just need to turn the scroll event off in the else statement.

e.g. Something like this if I remember my jquery :slight_smile:

     $(window).scroll(crisscross);
    } else {
      console.log("not matches");
      $(window).off("scroll");
    }
$(document).ready(function () {
  const mediaQuery = window.matchMedia("(min-width: 1080px)");

  function viewportChange(e) {
    // Check if the media query is true
    if (e.matches) {
      var num_children = $(".split-loop__left").children().length;
      var child_height = $(".split-loop__right").height() / num_children;
      var half_way = (num_children * child_height) / 2;
      $(window).scrollTop(half_way);

      function crisscross() {
        var parent = $(".split-loop"); //.first();
        var clone = $(parent).clone();

        var leftSide = $(clone).find(".split-loop__left");
        var rightSide = $(clone).find(".split-loop__right");

        if (window.scrollY > half_way) {
          //We are scrolling up
          $(window).scrollTop(half_way - child_height);

          var firstLeft = $(leftSide).children().first();
          var lastRight = $(rightSide).children().last();

          lastRight.appendTo(leftSide);
          firstLeft.prependTo(rightSide);
        } else if (window.scrollY < half_way - child_height) {
          var lastLeft = $(leftSide).children().last();
          var firstRight = $(rightSide).children().first();

          $(window).scrollTop(half_way);
          lastLeft.appendTo(rightSide);
          firstRight.prependTo(leftSide);
        }

        $(leftSide).css("bottom", "-" + window.scrollY + "px");
        $(rightSide).css("bottom", "-" + window.scrollY + "px");

        $(parent).replaceWith(clone);
      }

      $(window).scroll(crisscross);
    } else {
      console.log("not matches");
      $(window).off("scroll");
    }
  }

  // Register event listener
  mediaQuery.addListener(viewportChange);

  // Initial check
  viewportChange(mediaQuery);
});

I added the document ready around the whole thing as it doesn’t make sense to have it in the middle of the code.

I’m also guessing that perhaps the window scroll should have a handler name so that you can turn that handler off rather than all scroll events. It mat be as simple as this $(window).off("scroll",crisscross); but I’ll leave that for a JS guru to tidy up :slight_smile:

2 Likes

Thanks @PaulOB, that seems to have done the trick! :smiley:

I’m getting a ESLint error “Move function declaration to function body root.” which looks like it is in regards to function crisscross() { but other than that it all seems to work as expected.

The script within that is going to change a lot. Needs to be completely rewritten I think so no doubt there’ll be another post about that soon!

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.