Call external JS file based on "media screen" value

22,908

Solution 1

You can't do that directly using Javascript <script> tags. Media queries are used in linked CSS files or inline CSS styles. A basic example:

<link rel="stylesheet" media="screen and (min-width: 900px)" href="desktop.css"/>
<link rel="stylesheet" media="screen and (min-width: 571px)" href="tablet.css"/>
<link rel="stylesheet" media="screen and (max-width: 570px)" href="mobile.css"/>

Or directly in your stylesheets:

@media screen and (max-width: 599px) {
  #mobile {
     display: block;
  }
}

However, you can use an external asset loader/media query library to do this (require.js, modernizr.js, enquire.js and others), In this case, I'm setting an example using enquire.js, as I think it's very effective and doesn't require jQuery by default:

Full example

1) Include enquire.js (available here):

<script type="text/javascript" src="/js/enquire.js"></script>

2) Create a load function - to load JS files:

<script type="text/javascript">

// This loads JS files in the head element
    function loadJS(url)
    {
        // adding the script tag to the head
       var head = document.getElementsByTagName('head')[0];
       var script = document.createElement('script');
       script.type = 'text/javascript';
       script.src = url;

       // fire the loading
       head.appendChild(script);
    }

</script>

3) Fire enquire.js and listen for media query changes (both on-load and on-resize):

<script type="text/javascript">

    enquire.register("screen and (max-width: 599px)", {
        match : function() {
            // Load a mobile JS file
            loadJS('mobile.js');
        }
    }).listen();


    enquire.register("screen and (min-width: 600px) and (max-width: 899px)", {
        match : function() {
            // Load a tablet JS file
            loadJS('tablet.js');
            //console.log('tablet loaded');
        }
    }).listen();


    enquire.register("screen and (min-width: 900px)", {
        match : function() {
            // Load a desktop JS file
            loadJS('desktop.js');
            //console.log('desktop loaded');
        }
    }).listen();
</script>


Putting it all together

Using a simple HTML page with enquire.js loaded from an external file:

<html>
<head>

<script type="text/javascript" src="/enquire.js"></script>

<script type="text/javascript">

// This loads JS files in the head element
    function loadJS(url)
    {
        // adding the script tag to the head
       var head = document.getElementsByTagName('head')[0];
       var script = document.createElement('script');
       script.type = 'text/javascript';
       script.src = url;

       // fire the loading
       head.appendChild(script);
    }

</script>

<style>

    body {
      font-family: arial;
    }
    h1 {
      font-size: 50pt;
    }

    #mobile {
      display: none;
    }
    #tablet {
      display: none;
    }
    #desktop {
      display: none;
    }

    @media screen and (max-width: 599px) {
        #mobile {
            display: block;
        }
    }

    @media screen and (min-width: 600px) and (max-width: 899px) {
        #tablet {
            display: block;
        }
    }

    @media screen and (min-width: 900px) {
        #desktop {
            display: block;
        }
    }   

</style>

</head>
<body>

    <div id="desktop">
        <h1>Desktop</h1>
    </div>

    <div id="tablet">
        <h1>Tablet</h1>
    </div>

    <div id="mobile">
        <h1>Mobile</h1>
    </div>

    <script type="text/javascript">

        enquire.register("screen and (max-width: 599px)", {
            match : function() {
                // Load a JS file
                loadJS('mobile.js');
            }
        }).listen();


        enquire.register("screen and (min-width: 600px) and (max-width: 899px)", {
            match : function() {
                loadJS('tablet.js');
                //console.log('tablet loaded');
            }
        }).listen();


        enquire.register("screen and (min-width: 900px)", {
            match : function() {
                loadJS('desktop.js');
                //console.log('desktop loaded');
            }
        }).listen();

    </script>
</body>
</html>

In addition to loading JS files, you could create a CSS loader too, which would work in the same way (conditionally), but that defeats the object of using @media in CSS. It's worth reading the usage explanations for enquire.js, as it can do a lot more than I've illustrated here.

Caveat: Nothing above uses jQuery, but you could take advantage of some of the functions it offers; loading scripts for example - or executing other functions that you need to.

Solution 2

Why not just load in a script conditionally?

(function() {
    if( window.innerWidth > 600 ) {
        var theScript = document.createElement('script');
            theScript.type = 'text/javascript';
            theScript.src = 'js/menu-collapser.js';

        var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(theScript, s);
    }
})();

Or better yet, only execute the code if the window.innerWidth > 600 ? Anyway, there are a lot of solutions you can use.

Solution 3

media is not a valid attribute for <script>, check it here.

So you should detect media types by manually than load the script dynamically.

There is a plug-in for css media detection in javascript, you can use it.

<script type="text/javascript" src="js/mediatypechecker.js"></script>

$(function() {
    if(IsMediaType('screen') > 0 && parseInt(screen.width) < 599) {
        $.getSscript("js/menu-collapser.js");
    }
});
Share:
22,908
Mark
Author by

Mark

Updated on July 09, 2022

Comments

  • Mark
    Mark almost 2 years

    I'm trying this but it is not working:

    <html>
    <head>
    <script src="js/menu-collapser.js" type="text/javascript" media="media screen and (max-width: 599px)"></script>
    </head>
    ...
    </html>
    

    //menu-collapser.js :

    jQuery(document).ready(function($){
        $('.main-navigation li ul').hide();
        $('.main-navigation li').has('ul').click(function() {
            $(this).children().toggle();
        });
    });
    

    Do you have an idea on how to do this in the right way? The script work if used directly in the header with the tags.

  • Mark
    Mark about 11 years
    Hi, thanks for your complete explaination. I'm tryin to follow your suggestions but it's not easy for me. Do i have to download require.js/modernizr.js, include them in the head and then use your second code in the body? Because it doesn't seems to work...
  • Mark
    Mark about 11 years
    you are amazing, thanks for your help. unfortunatly i can't get it to work! :( if you are so kind to take a look at my code, i've simplified it and pasted here: pastebin.com/HkviLP9H
  • nickhar
    nickhar about 11 years
    @l736k There doesn't seem anything wrong with your code - It works in Chrome/Safari, but what does menu-collapser.js do!?
  • Mark
    Mark about 11 years
    menù collapser contains the jQuery script i've posted in the initial question...it should collapse the subpages of the menù in the mobile version of the theme. there might be some other problems as the jQuery code i have USED to works if typed directly into the body but now doesn't work anymore...and i can't understand why! you can see the live site at this URL if you want to have a better idea (try resizing the browser and you'll see the menù that changes under 599px): is.gd/6ju6a1
  • Mark
    Mark about 11 years
    actually, i geti it back to work but it ignore the screen dimensions...the script works also if the browser >599px...so in the full width version the menu have troubles...
  • jq beginner
    jq beginner almost 10 years
    would you please check this question, nickhar? it's about the same script: stackoverflow.com/questions/24969807/…
  • JTG
    JTG almost 9 years
    enquire.js version 2.0.0 no longer uses the listen() call, for any interested parties.