JavaScript Object Literal and jQuery $(classes)

138 views Asked by At

I have an object that contains a list of browser widths

breakpoints {
    smallMobile: 0, 
    mobile: 480, 
    tablet: 672, 
    desktop: 868, 
    largeDesktop: 1050
}

I want to add a class to the body of the document based on whether the browser width falls between two values in the breakpoints object.

What I have so far

var key;

for (key in breakpoints) {
    if (breakpoints.hasOwnProperty(key))
        if (winWidth >= breakpoints[key]) {
            $('body').removeClass().addClass(key);
        } else {
            $('body').removeClass(key);
        }
    }
}

Now this works, however it also removes ALL classes from the body. Instead I would like to add only one class, and not have to remove anything unless the breakpoint no longer matches.

I'm sure there has to be a way. Any help would be appreciated :)

EDIT

Current output at various widths

>= 1050: <body class="smallMobile mobile tablet desktop largeDesktop">

>= 868: <body class="smallMobile mobile tablet desktop">

>= 672: <body class="smallMobile mobile tablet">

Ideal output

>= 1050: <body class="largeDesktop">

>= 868: <body class="desktop">

>= 672: <body class="tablet">

(For the record I use Media Queries, but I need access to classnames for an edge case)

5

There are 5 answers

5
somethinghere On BEST ANSWER

I've slightly modified your code and saved the class thats the highest applicable one. Then I remove every class and apply the applicable one.

// create a variable to store the only class you want to apply
var apply = "";
for (var key in breakpoints) {
    // keep overwriting the apply var if the new key is applicable
    if (winWidth >= breakpoints[key]) {
       apply = key;
    }
    // remove any existing classes with that keyname
    $('body').removeClass(key);
}
// add the key to the body as a class
$('body').addClass(apply);

Also, you can remove breakpoints.hasOwnProperty(key) as the for-loop only loops through keys that actually exist anyway, so you are doing an unnecessary check.

Update

At @juvian's note, I'll add a way to make sure that the order in which you make your object makes no difference:

var apply = "";
var check = 0;
for (var key in breakpoints) {
    // Also check if the value is higher than the last set value
    if (winWidth >= breakpoints[key] && breakpoints[key] >= check) {
        apply = key;
        check = breakpoints[key];
    }
    $('body').removeClass(key);
}
$('body').addClass(apply);
2
Prabu Raja On

It's because you're using removeClass() without any parameter in it.

If a class name is included as a parameter, then only that class will be removed from the set of matched elements. If no class names are specified in the parameter, all classes will be removed.

Source: http://api.jquery.com/removeClass/

So, you should find the right class to remove and then call this function with a param.

0
Tommi On

Consider to store your breakpoints in sorted array instead of map:

var dimensions = [];
for (var key in breakpoints) {
   dimensions.push({ name: key, width: breakpoints[key] })
}

dimensions.sort(function(a, b) { return b.width - a.width });

Now dimensions is

[
    {"name":"largeDesktop","width":1050},
    {"name":"desktop","width":868},
    {"name":"tablet","width":672},
    {"name":"mobile","width":480},
    {"name":"smallMobile","width":0}
]

Of course you can hardcode it in this structure and not grep/sort each time.

Finally, find highest width with

for (var i = 0; i < dimensions.length; i++) {
    if (winWidth >= dimensions[i].width) {
        $("body").addClass(dimensions[i].name);
        break;
    }
} 

However, if you want to create responsive layout, media queries is the way to go. Media queries also will take windows resize/orientation change events into account.

0
juvian On

Here is a way you can get the one that matches with the highest value:

var wid = 868;
var max = 0;
var size = null;

Object.keys(breakpoints).map(function(a){
    size = wid >= breakpoints[a] ? a : size;
    max = wid >= breakpoints[a] ? Math.max(max,breakpoints[a]) : max;
})
console.log(max, size) // 868, 'desktop'
0
Putra Soerya On

if you use .removeClass() without parameter then all class on selected element will remove as like prabu said, but if you want, i give some example so you will not confused how to remove class if window width less than breakpoints

var key;
for (key in breakpoints) { 
    if (breakpoints.hasOwnProperty(key)) {
        $("body").addClass(key);
        if (winWidth<breakpoints[key]) {
            $("body").removeClass(key);
        }
    }
}