Chapter 4. Customizing to Your Unique Needs

In this chapter we'll be covering some of the extras provided by Modernizr that go beyond just feature detection, as well as customizing the library to suit your individual needs. Up to this point we've used the library as a development build. The development build includes all of the feature tests and library extras, which will be covered in a bit more detail as well. As a performance goal however, we want to keep any overhead as light as possible. We've lightened overhead (download size) significantly by reducing HTTP requests, when we converted some images to be purely CSS. Now we can go a step further and lighten the file size of the Modernizr library by building a custom version with only the features we need. This will allow the library to download as fast as possible and in turn enhance overall page performance. Here's what this chapter will be covering:

  • Custom building Modernizr for leaner overhead
  • Modernizr.load (YepNope JS) for conditionally loading
  • Loading polyfills and other conditional scripts
  • Shim media queries using Respond JS
  • Further reading and resources

Customizing Modernizr

In the examples from the previous chapter, we used the full development build of the library. This however isn't recommended for production sites because the full library would be rarely needed. It is better instead to reduce the overhead file size by custom building this library with only the feature tests that are needed.

This is very easy to do by using the custom build options on the Modernizr website. Simply select Production as the download option and choose the boxes for the features your application needs, click on Generate and you're off and running. It has even been minified for you. For the previous chapter, a custom build of the library would include the following tests

  • CSS3
    • @font-face
    • background-size
    • border-radius
    • box-shadow
    • hsla
    • multiple backgrounds
    • opacity
    • rgba
    • text-shadow
    • CSS Animations
    • CSS Generated Content
    • CSS Gradients
    • CSS Reflections
    • CSS 2D transforms
    • CSS Transitions
  • Extensibility
    • Modernizr.prefixed
    • Modernizr.testProp
    • Modernizr.testAllProps
    • Modernizr._domPrefixes
  • Extra
    • html5shiv
    • Modernizr.load
    • Add CSS Classes

The extensibility part isn't actually needed if all of your vendor prefixing was done manually or by a vendor prefix generator such as Prefixr, which we touched upon in the previous chapter. It's been left in the build. So, we can cover it in a bit more detail in this chapter as well. The other extensible includes are required by Modernizr.prefixed and will be auto selected for you upon custom build. However, as we have them it's a good chance to highlight one of the most useful methods, the addTest method.

The custom build of Modernizr weighs in at about 10 KB. Compare that with the full development build we used that weighed in at around 47 KB. This means that the development version was over four times the size needed to run the application in the previous chapter. The custom build tool looks as follows on Modernizr.com:

Customizing Modernizr

Why stress over kilobytes? Aren't they trivial when it comes to overhead? Now that applications are moving from the Web and expanding into almost every digital device imaginable, this makes a huge difference. By minimizing as much overhead as possible, not only does the site load as fast as it can, but also a room is made for other hungrier resources such as images. The extra 37 KB could be an entire CSS sprite.

The Modernizr.addTest plugin API

While we are on the topic of extending, Modernizr has a plugin API that you can use to extend the library and add in some of your own. For example, if you wanted to test whether Safari is running in a sort of web app mode called standalone on an iPhone, which is often the case for websites that have been bookmarked by adding to the device's home screen, you could do so by creating the following custom test:

//Add a test for Safari Mobile standalone mode.
Modernizr.addTest("standalone", window.navigator.standalone );

The second argument can either be passed as a function that returns a true or false result, or as we've done in the preceding example by passing in a property. This method is handy when not a lot of logic has to be applied and the result is a simple true or false statement. After running this function, Modernizr will now add either a standalone or no-standalone class to the page, as well as store this result along with the others.

Modernizr.load

Modernizr has a load method, also known as the popular YepNope JS conditional loading library. It is a hugely popular conditional loader for polyfills that is also capable of loading other resources including CSS files. Modernizr capitalizes on the capability of YepNope JS by packaging it under its hood under the method name of load.

This new test for standalone mode can now be used by Modernizr.load to conditionally load additional scripts. Let's say, for example, you wanted to load some special scripts when the browser is running as a web app. The new custom standalone test we created can be used to do this. In this next bit of code, our new test will be performed and a fictional webapp.js script will be loaded if the condition is true.

//Custom test for standalone mode.
Modernizr.addTest('standalone', window.navigator.standalone);
Modernizr.load({
  test: Modernizr.standalone,
  yep: 'webapp.js',
  complete: function () {
    console.log("Standalone was tested for and the conditional script was loaded if needed");
  }
});

The test we created is added and performed using Modernizr.addTest. Then Modernizr.load runs this test and if it passes, the yep script—a special webapp.js will be loaded. The last method, named complete, is also run after all of this has completed. The complete method will run regardless of the test passing or failing.

Modernizr.load, also known as YepNope JS, is known most famously for the conditional loading of polyfills. Let's go over an example of using this helpful method to conditionally load one of ur own.

Using polyfills

What exactly is a polyfill? Remy Sharp, who coined the term, defines a polyfill on his blog as follows:

A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. Flattening the API landscape if you will.

Paul Irish defines a polyfill as follows:

A shim that mimics a future API, providing fallback functionality to older browsers.

The etymology comes from a spackling paste named Polyfilla and best summed up the ideals of what was being accomplished when creating this functionality.

In the following test, we're going to use a built-in test for local storage and load a polyfill if that test result does not pass. In this example, we'll just test against the window property and not using Modernizr because that particular test wasn't included in our custom build. However, that is something that can be included in the library.

//Test for local storage and load a polyfill if needed.
Modernizr.load({
  test: window.localStorage,
  nope: 'storage.js', //Local storage is not supported, load polyfill
  complete: function () {
    console.log("local storage has been polyfilled if required");
  }
});

Using this code, we get something similar to the following screenshot:

Using polyfills

There are a large number of polyfills available to you on the Internet. A large list of polyfills can be found on the Modernizr Github at https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills.

How about we try this out in a web page and put it into practice? In a new HTML page, I'm going to make a quick and simple div element that will wrap an input text field and a button. Upon entering a value into the text field and then clicking on the button, that value will be saved in the browser's local storage. On page refresh, the saved value will be checked for and then added to the text field if it is found. I will be using the following HTML for the page:

<!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
  <meta charset="utf-8">
<!--  Force IE to use the latest version of its rendering engine -->
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <meta name="description" content="A Modernizr test page.">
  <link rel="stylesheet" href="styles.css">	
<script src="modernizr.custom.js"></script>
</head>
<body>
<h1>Local Storage Example</h1>
 <div id="localStorage">
 <input type="text" class="textinput"/><button>Save to Local Storage</button>
 </div>	
  <!-- JavaScript at the bottom for fast page loading -->
  <!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

In the styles.css file, we'll add the basic styles for the form using the following code snippet:

#localStorage{
  margin: 300px auto 0;
  width: 265px;
  background: #eee;
  padding: 20px;
}
/* Add a drop shadow */
.boxshadow #localStorage {
  -webkit-box-shadow: 0 0 2px 2px #ccc;
  box-shadow: 0 0 2px 2px #ccc;
}

Using this code, we get something similar to the following screenshot:

Using polyfills

As you will have already noticed it's a straightforward, bare bones text input and button wrapped by a div element. A stylesheet, jQuery, and JavaScript file are included similar to the naming conventions in the previous chapters. The script.js file is where all of the heavy lifting is going to happen. I am also going to wrap all of the JavaScript in a little bit of shorthand for the document ready method to ensure that the DOM will be loaded before running any of the JavaScript. I'm going to first add in the previous examples, the localStorage test, the standalone test, and the polyfill loading as seen in the following code snippet:

$(function(){
  //Test for localstorage and load a polyfill if needed.
  Modernizr.load({
    test: window.localStorage,
    nope: 'storage.js',
    complete: function () {
      localStorage.setItem("successfull save", "Saving to local storage now that it's safe");  
    }
  });
Modernizr.addTest( 'standalone', window.navigator.standalone );
  Modernizr.load({
    test: Modernizr.standalone,
    yep: 'specialjavascriptfunctions.js',
    complete: function () {
      console.log("Standalone was tested for, and the conditional script was loaded if needed");
    }
  });
});

If you view this new HTML page in the browser you'll see the console has logged the localStorage and the standalone complete messages.

Now, we can add the code that will handle localStorage input processing:

$(function(){ 
// ...previous code from Modernizr.load, Modernizr.addTest above
   //Cache the text input, and local storage into variables.
  var textVal = $('.textinput', '#localStorage'),
  var storedItem = localStorage.getItem("textvalue");
  //Check and see if anything has been stored
  //from the text input. Set the text input to have it's value.
  if( typeof storedItem === 'string' ){
    textVal.val( storedItem );
  }
  //Bind a function to the click event of
  //our button that saves the value into localstorage.
  //An alert is fired after this is done.
  $('button', '#localStorage').click(function(){
    localStorage.setItem( "textvalue", textVal.val() );
    alert("Saved into local storage!");	
  
  });
}); //end of code

With the code all in place, and the polyfill conditionally loaded, we can test our form. Once the value is saved an alert will appear, as shown in the following screenshot:

Using polyfills
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset