1

I'm kinda new to JavaScript overall, and I've made a script by myself which is supposed to add classes to other classes on click.

Now the problem I have is that the code is supposed to work for the mobile view only (under 800px width) which works well, but when I resize the window to something above, after using the script it is still active.

Script:

$(document).ready(function() { 
    if ($(window).width() <=800 ) {
        $('.mobileNavButton').click(function() {
            $('.mainNav').toggleClass('active');
            $('.mobileNavButton').toggleClass('active');
        });
        $('.hasDropdown').click(function() {
            $('.dropdown').toggle('slide');
            $('.dropdown').toggleClass('active');
            $('.hasDropdown').toggleClass('rotate');
        });
        $('.hasSubDropdown').click(function() {
            $('.subDropdown').toggle('slide');
            $('.subDropdown').toggleClass('active');
            $('.hasSubDropdown').toggleClass('rotate');
        });
    }
});

You guys all helped me out a lot! Thanks!

Richard R
  • 75
  • 1
  • 1
  • 9
  • Use media queries instead. – SLaks Apr 06 '16 at 14:31
  • I'd like to point out that this is probably a non-issue. People on mobile won't be resizing anything. – 4castle Apr 06 '16 at 14:36
  • 1
    You could try placing `if ($(window).width() <=800 )` condition within `click` handlers, place calls to `.toggleClass()` within `if` statement ? – guest271314 Apr 06 '16 at 14:39
  • @4castle Yeah, I thought so too.. But then I tested it on a tablet. If I switch to landscape, I am above those 800px and then things don't work out like I want them to. – Richard R Apr 06 '16 at 14:41
  • @James Ahh, good point! Carry on :) – 4castle Apr 06 '16 at 14:42
  • Probably, [What is the best way to detect a mobile device in jQuery?](http://stackoverflow.com/questions/3514784/what-is-the-best-way-to-detect-a-mobile-device-in-jquery) it would help you to check mobile view. – hmd Apr 06 '16 at 14:44

3 Answers3

2
 $(document).on('click', 'body.mobile .mobileNavButton', function() {
    $('.mainNav').toggleClass('active');
    $('.mobileNavButton').toggleClass('active');
});

$(document).on('click', 'body.mobile .hasDropdown', function() {
   $('.dropdown').toggle('slide');
    $('.dropdown').toggleClass('active');
    $('.hasDropdown').toggleClass('rotate');
});

$(document).on('click', 'body.mobile .hasSubDropdown', function() {
    $('.subDropdown').toggle('slide');
    $('.subDropdown').toggleClass('active');
    $('.hasSubDropdown').toggleClass('rotate');
});

$(window).resize(function(e) {
    if ($(window).width() <= 800) {
        $('body').addClass('mobile');
    }
    else {
        $('body').removeClass('mobile');
    }
});

$(document).ready(function(){
  $(window).resize(); // call once for good measure!
});

https://jsfiddle.net/3okzr4z4/ Drag the window around and see the text change.

This is probably the most reliable quick solution, though I hesitate to give it since it might be beyond what you've learned so far. But the thing is, you avoid calling the .off() function if something isn't .on, and you also avoid having to tediously rebind and unbind function calls every moment the window is resized. You also avoid needing to place if conditions in every block.

Binding need only be done once.

What's happening is: Since we bind to the document, it checks against the selector that is our second argument when we get a click. So if the selector matches 'body.mobile .mobileNavButton', it executes the function.

On the window resize event, we add or remove the 'mobile' class from the body, that way the functions only run if the elements are children of 'body.mobile'. (We call it once when the script first runs for good measure)

Caveats

Although, if you REALLY want to make sure it's mobile, and not just a small screen, you will need more extensive checks than just $(window).width(); If this is relevant to you, check out this:

What is the best way to detect a mobile device in jQuery?

(Also, come on guys, you can't use media queries in jQuery lol)

Community
  • 1
  • 1
aaronofleonard
  • 2,448
  • 14
  • 22
  • With this solution, it makes it really easy to use `.mobile` in the CSS. No media query headaches and super readable CSS! – 4castle Apr 06 '16 at 14:47
  • I really really like this one! But sadly the function repeats one more time after each resize, if you know what I mean. – Richard R Apr 07 '16 at 06:48
  • To which function are you referring that repeats one more time? :) – aaronofleonard Apr 07 '16 at 14:09
  • @Amleonard Well, I'm not good at explaining stuff.. but I'll try :P When I use your code, and I resize the window, the code pretty much adds the function one more time.. so if I click the button, it opens the navigation. If I then resize the window and click the button again, it closes the menu and then opens it again. Do you know what I mean? – Richard R Apr 07 '16 at 14:28
1

Try placing if condition within click handlers, .toggleClass() calls within if statement

    var check  = function() {
      return $(window).width() <=800
    }

    $('.mobileNavButton').click(function() {
         if (check()) {
           $('.mainNav').toggleClass('active');
           $('.mobileNavButton').toggleClass('active');
         }
     });
     $('.hasDropdown').click(function() {
         if (check()) {
           $('.dropdown').toggle('slide');
           $('.dropdown').toggleClass('active');
           $('.hasDropdown').toggleClass('rotate');
         }
     });
     $('.hasSubDropdown').click(function() {
         if (check()) {
           $('.subDropdown').toggle('slide');
           $('.subDropdown').toggleClass('active');
           $('.hasSubDropdown').toggleClass('rotate');
         }
     });
guest271314
  • 1
  • 10
  • 82
  • 156
0

You can handle the window resize event : (but for this kind of behavior you should use css media queries )

Update : limit calls on resize

var resizeTimer;
$(window).resize(function(e) {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(function() {
        if ($(window).width() <= 800) {
            $('.mobileNavButton').click(function() {
                $('.mainNav').toggleClass('active');
                $('.mobileNavButton').toggleClass('active');
            });
            $('.hasDropdown').click(function() {
                $('.dropdown').toggle('slide');
                $('.dropdown').toggleClass('active');
                $('.hasDropdown').toggleClass('rotate');
            });
            $('.hasSubDropdown').click(function() {
                $('.subDropdown').toggle('slide');
                $('.subDropdown').toggleClass('active');
                $('.hasSubDropdown').toggleClass('rotate');
            });
        } else {
            $('.hasDropdown').off("click");
            $('.hasSubDropdown').off("click");
            $('.mobileNavButton').off("click");
        }
    },250);
});
Quentin Roger
  • 5,985
  • 2
  • 21
  • 35