webpackJsonp([0xb78ada27efd3],{361:function(e,t){e.exports={data:{markdownRemark:{html:'

\n \n \n \n \n \n

\n

What Is AngularJS

\n

AngularJS is a MVW (Model/View/Whatever) JavaScript framework that extends HTML through additional markup and produces more expressive and readable code. Its packed feature set make it a firm favourite for anyone developing SPAs or complex JavaScript based front ends.

\n

Why AngularJS

\n

Declarative User Interface

\n

Through the use of AngularJS directives, filters and expressions we can build more declarative UIs. This means we don\'t have to get bogged down with how to bend and shape the DOM of a html template view to our will. We can just declare what we want and where. This not only reduces development time but also leaves us with clean, intuitive code.

\n

2-Way Data Binding

\n

The whole MVW or MVVM (Model/View/View-Model) approach that AngularJS is well known for is possible due to it\'s View-Model or Scope as it is referred to in these parts. An application\'s scope sits between its view and its controller. From one side the controller can add variables and functions to the scope which can in turn be used by (bound to) the view. Okay, so not that impressive right? However AngularJS can also bind the view, or to be more specific HTML form fields back to the scope. What does this mean? Live Preview baby! Any changes made to the model by the view will be seen by the controller. And vice versa, any changes made to the model by the controller will be immediately visible in the view. This means the scope model is considered the single source of truth.

\n

Performance

\n

One of the big advantages of the above is that it is all achieved without a page reload anywhere to be seen. After the initial page load of an AngularJS application, any changes to the view (model data, partial views, etc) are performed automatically. How does it do that you ask? You might imagine that AngularJS loads the DOM as a string and parses it, updating as it goes then returning the updated string back to the browser to reload the DOM. This wouldn\'t be very efficient however as every small change would require the whole DOM to be updated, again and again. What actually happens is that the AngularJS Compiler service traverses the actual DOM looking for directives and expressions and then links these elements to the scope. It achieves this by registering listeners to the elements and placing watches on the scope. Anything changes in either the view or the scope, the other is updated instantly without a complete reload of the DOM. End result? A very responsive, fast application.

\n

Dependency Injection And Testing

\n

An age old problem of testing lies with the dependencies of our code. If dependencies, such as a call to an API, are declared directly within the code itself, tests will forced to use the very same (and possibly production) API call. The problem here is that our tests need to use consistent data input so that the outcome of our code can be correctly predicted. In our example, using a call to a live API could provide data that has been modified between tests and so taint the expected outcome. We can of course mock the service with our own pre-set and consistent data (like a fixture), but how can we tell our code to switch services when testing? The easiest way of managing this is to inject the required service into our code module as a dependency. The code can then utilise whichever service we supply and so provide the flexibility we need. This approach doesn\'t only help with testing, it also makes our code infinitely more re-usable.

\n

Thankfully, AngularJS was built with testing and the Separation Of Concerns (SoC) principal in mind from the outset and implements dependency injection throughout. Everything from components such as services, directives and filters to controllers and even module config can receive an array of dependencies to be injected. Nice!

\n

...Oh And It Plays Nicely With jQuery

\n

AngularJS comes with a lite version of jQuery aptly called jqLite built in. So if you are a fan of jQuery selectors for example, you can continue to use these within your AngularJS code. Should you discover you need to use a full blown version of jQuery, just make sure it is loaded before AngularJS and it will be used instead of jqLite.

\n

Getting Started

\n

Download or link to the CDN of the latest version of AngularJS (1.3.8 at the time of writing) in our html template (index.html):

\n
<!DOCTYPE html>\n<html> \n<head>\n\t<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>\n</head>\n<body>\n...\n</body>\n</html>\n
\n

Modules

\n

In keeping with SoC, AngularJS applications are built in a modular fashion to promote code re-use and more maintainable and easily testable code.

\n

Let\'s create an example AngularJS application module (app.js):

\n
var app = angular.module( \'myApp\', [] );\n
\n

The first argument is the name of the module. The second is an array of dependencies to be injected (of which we don\'t have any in this basic example).

\n

Now we include the module file in our html template:

\n
<head>\n\t...\n\t<script type="text/javascript" src="app.js"></script>\n\t...\n</head>\n
\n

And finally we need to bootstrap the application using our very first built-in directive ng-app (more on directives later):

\n
<html ng-app="myApp">\n...\n</html>\n
\n

Let\'s Meet The AngularJS Family

\n

Expressions

\n

AngularJS allows us to bind JavaScript-like expressions directly into a html template. The expressions can perform numerical and string operations or can refer to a variable/model within the scope.

\n
<p>1 + 2 = {{ 1 + 2 }}</p>  \n  \n<p>Hello {{ customer.firstName }}</p>\n
\n

Controllers

\n

An application\'s business logic is defined within its controllers. We can define our application\'s behaviour here as well as set the initial state of the controller\'s new child scope.

\n

First we need to create a controller and attach it to our application module (app) using the controller() method. The first argument is where we define the name of the controller and the second is the controller\'s constructor function (along with its dependencies):

\n
var app = angular.module( \'myApp\', [] );  \n  \napp.controller( \'CustomerController\', [ \'$scope\', function( $scope ) {  \n  \n\t$scope.customer = {\n\t\tfirstName: \'Peter\',\n\t\tlastName: \'Parker\',\n\t\tphoto: \'pparker.jpg\',\n\t\tisMember: true\n\t};  \n  \n}]);\n
\n

As you can see above, we have also initialised a \'customer\' object within the controller\'s scope. In real world examples of course this sort of data would probably be provided by an API service (injected as a dependency of the controller) rather than hard coded like this.

\n

Also note that whilst we are adding our controller to the same file as the module here (app.js), you can and probably should define your controllers in separate files (to be covered in a later article).

\n

Now to access our controller\'s scope (and all the values, objects and methods etc. associated with it) from within a html template, we must attach the controller to some relevant html element using another of the AngularJS built-in directives:

\n
...\n<div ng-controller="CustomerController">\n\t<p>Dear {{ customer.firstName }} {{ customer.lastName }},</p>\n</div>\n...\n
\n

Note that we can only access the controller\'s scope from within the bound element. If we tried to place {{ customer.firstName }} anywhere outside of the div bound to the CustomerController, it would be ignored.

\n

Built-in Directives

\n

As we have already seen earlier, AngularJS comes ready to roll with built-in directives. These directives allow us to extend standard HTML to help us build web applications. All AngularJS built-in directives use the namespace \'ng\' at the start i.e. ngApp, ngController, etc. (note the camelCase here). However, when we use the directives in html the camelCase is substituted for hyphenation i.e. ng-app, ng-controller, etc.

\n

Below is a selection of some of the most commonly used directives:

\n

ng-app
Used to auto-bootstrap an AngularJS application and also defines the root element of the application by whichever element the directive is placed on (usually <html> or <body>).

\n
<html ng-app="myApp">\n
\n

ng-controller
As we saw earlier, this directive is used to attach an existing AngularJS controller to a element within the html template. Remember, the controller\'s scope will only be available within the element that it is bound to.

\n
<div ng-controller="CustomerController">\n...\n</div>\n
\n

ng-show / ng-hide / ng-if
All three of these directives accept an expression to be evaluated. The first two are self explanatory i.e. they will show or hide whatever element they are attached to if their expression evaluates to true. The ng-if directive is similar to these but with one main difference. Whilst ng-show and ng-hide merely use CSS to show/hide the element, ng-if actually removes the element (and its contents) from the DOM if its expression evaluates to false and recreates it if true.

\n
<div ng-if="customer.isMember">\n...\n</div>  \n  \n<div ng-hide="!customer.isMember">\n...\n</div>\n
\n

ng-click
Attaches a click handler to an element. When the bound element is clicked, the method passed to the handler is run. The method must of course first be defined in the controller and added to the scope.

\n
app.controller( \'CustomerController\', [ \'$scope\', function($scope) {  \n  \n\t$scope.updateCustomer = function() {\n\t\t...\n\t\tsome code to save the customer changes back to the API\n\t\t...\n\t};  \n  \n}]);\n
\n
<button ng-click="updateCustomer()">Save Changes</button>\n
\n

ng-src
The problem with dynamically setting the source of an <img> element is that the data in the scope won\'t be available for the browser to pre-load as AngularJS hasn\'t parsed the DOM yet. AngularJS provides a solution with the ng-src directive. As the <img> will initially have no src, no attempt will be made to pre-load. Once the DOM has been parsed, AngularJS can set the src.

\n

Won\'t work (well it might but only after an additional request):

\n
<img src="http://www.example.com/photos/{{ customer.photo }}" />\n
\n

Will work:

\n
<img ng-src="http://www.example.com/photos/{{ customer.photo }}" />\n
\n

ng-repeat
So far so good, but ng-repeat steps up the excitement levels! No? Just me then. This powerful directive lets us iterate over a collection of items, such as an array of objects, applying a template to each item. In other words, a big time saver.

\n

Let\'s say we have an array of fruit objects in a controller:

\n
$scope.fruits = [\n        {\n            name: \'Bananas\',\n            stock: 5\n        },\n        {\n            name: \'Apples\',\n            stock: 2\n        },\n        {\n            name: \'Oranges\',\n            stock: 3\n        }\n];\n
\n

Now we want to list those healthy snacks out in a html template along with the current stock level:

\n
<ul>\n\t<li ng-repeat="fruit in fruits">{{ fruit.name }} ({{ fruit.stock }})</li>\n</ul>\n
\n

Yep that\'s it! I told you it was cool. We attach the ng-repeat directive to the element we wish to replicate for every item, for example the <li> element. Each item in the fruits array from our controller scope is assigned its own scope, in this case named fruit. We can then insert our AngularJS expressions to place our data where required.

\n

Outputs:

\n\n

Filters

\n

Once again AngularJS gets us started with a bunch of built-in filters that allow us to create subsets of, limit, order or format the output of an expression. They are preceded by the | symbol (to pipe our data through the filter) followed by the filter component name. This is then followed by a : and any filter arguments.

\n
{{ expression | filter:arguments }}\n
\n

Here is a selection of a few of them:

\n

currency
Format the expression to a currency with the provided symbol:

\n
{{ 1234 | currency:"&pound;" }}\n
\n

Outputs: £1,234.00

\n

date
Formats the expression (a date object, or milliseconds for example) to the provided date format:

\n
{{ 1420070401000 | date:"dd/MM/yyyy HH:mm:ss" }}\n
\n

Outputs: 01/01/2015 00:00:01

\n

filter
Creates and returns a subset array from the provided filter expression array (such as an array of objects used in a ng-repeat) based on the expression argument (a string, a pattern object or a predicate function). Let\'s use our earlier ng-repeat example and apply a couple of different filters.

\n

String example:

\n
<ul>\n\t<li ng-repeat="fruit in fruits | filter:\'an\'">{{ fruit.name }} ({{ fruit.stock }})</li>\n</ul>\n
\n

Outputs:

\n\n

Pattern Object example:

\n
<ul>\n\t<li ng-repeat="fruit in fruits | filter:{ name:\'es\', stock:3 }">{{ fruit.name }} ({{ fruit.stock }})</li>\n</ul>\n
\n

Outputs:

\n\n

Predicate Function example (requires the function to be defined in the controller\'s scope):

\n
$scope.filterByLowStock = function(fruit) {\n\treturn fruit.stock < 5;\n};\n
\n
<ul>\n\t<li ng-repeat="fruit in fruits | filter:filterByLowStock">{{fruit.name}} ({{fruit.stock}})</li>\n</ul>\n
\n

Outputs:

\n\n

Custom
Once you get the hang of the built-in offerings, have a go at creating your own custom filter.

\n

Forms & Models

\n

There was a significant omission from the earlier introduction to AngularJS built-in directives by the name of ng-model. This directive is the final piece in the 2 Way Data Binding puzzle and let\'s us bind html form fields to a model defined in the controller\'s scope. Assuming we use the earlier defined CustomerController, let\'s take a look at a basic example:

\n
<p>Customer name: {{customer.firstName}} {{customer.lastName}}</p>  \n  \n<form>\n\t<input type="text" ng-model="customer.firstName" />\n\t<input type="text" ng-model="customer.lastName" />\n</form>\n
\n

As you can see we have used ng-model to bind a couple of input fields to properties of our customer object. We are also displaying these properties above to illustrate the live preview. Now if we change either of the input field values (note the default value is set from the existing initialised model), this will update the model (customer object) in the scope which will in turn update the view and display our changes above.

\n

Note that there is no data retention at this stage. A refresh of the page and we are back where we started. This would require a function to be defined in the controller that saves our changes back to data source such as an API. Check out the ng-click example above for how we might go about this.

\n

Wrap Up

\n

Hopefully you now have a good understanding of the what, why and the beginnings of the how of AngularJS and feel inspired to have a go yourself. Tweet me up and let me know how you get on.

\n

I have planned a bunch of follow up articles to delve further into AngularJS so check back soon.

',frontmatter:{teaser:"With the popularity of Single Page Applications (SPA) and AngularJS as the 'go to' JavaScript framework of choice, here we cover the what, why and an introduction to the how of AngularJS.",date:"29 December 2014",path:"/blog/angularjs-essentials",title:"AngularJS: The Essentials"}}},pathContext:{prev:{html:'

\n \n \n \n \n \n

\n

Data Types

\n

JavaScript is a loosely typed language which means a variable\'s value defines its type. JavaScript has 7 data types grouped as follows:

\n

Primary / Primitive (Have no properties and are immutable)

\n\n

Composite / Reference (Are objects so have properties and are mutable)

\n\n

Special (Classed as primary / primitive but with no corresponding object constructor)

\n\n

Certain operations will cause the JavaScript interpreter to coerce a variable\'s type to allow it to complete the requested operation without causing an exception. For example adding a number or a boolean to a string will convert the former variable to a string too (and concatenate the two). Adding a boolean to a number will convert the boolean to a number before adding the values together.

\n

Also note that whilst the primitive types are not objects (unless instantiated with the new keyword, see below), they still have properties/methods available to them from their corresponding object constructor. This is because JavaScript temporarily creates an object wrapper whilst it accesses/performs the requested property/method. This object is immediately destroyed afterwards which explains why you can\'t access a property that you just added to a primitive, it\'s gone already!

\n

Built-In Objects

\n

Everything in JavaScript except primitive values are objects. Note that objects in JavaScript are addressed by reference which means assigning an object to the value of another variable does NOT make a copy of the object. It merely creates another pointer to the same object.

\n

String

\n

Instantiation

\n
\'string\', "string", String(thing), new String(thing)
\n

Properties

\n
length
\n

Methods (most common)

\n
charAt(index), indexOf(needle), match(regexp), replace(needle|regexp, newNeedle), search(needle|regexp), slice(start, exclusiveEnd), split(delimiter|regexp,limit), substr(start, inclusiveEnd), substring(start, exclusiveEnd), toLowerCase(), toUpperCase, trim(), valueOf()
\n

Number

\n

Instantiation

\n
new Number(value)
\n

Methods (most common)

\n
toFixed(decimals), toPrecision(length), toString(), valueOf()
\n

Boolean

\n

Instantiation

\n
new Boolean(value)
\n

Methods

\n
toString(), valueOf()
\n

Date

\n

Instantiation

\n
new Date(milliseconds|dateString|year, month, date[, hours[, minutes[, seconds[, milliseconds]]]])
\n

Methods

\n
get|set + UTC + Date|Day|FullYear|Hours|Milliseconds|Minutes|Month|Seconds|Time + (),
to + Date|GMT|ISO|LocaleDate|LocaleTime|Locale|Time|UTC + String(),
toJSON(), now(), parse(dateString), valueOf(),
UTC(year, month[, date[, hours[, minutes[, seconds[, milliseconds]]]]])
\n

Math

\n

Instantiation

\n

Math objects don\'t need to be instantiated and so can just be used with the required property or method directly.

\n

Methods (most common)

\n
abs(x), ceil(x), floor(x), max(x, ...), min(x, ...), pow(base, exponent), random(), round(x), sqrt(x)
\n

RegExp

\n

Instantiation

\n
/pattern/modifiers, new RegExp(pattern, modifiers)
\n

Methods (most common)

\n
exec(string), test(string)
\n

Also note that the String object\'s match(), replace(), search() and split() methods all accept RegExp patterns as arguments. Learn more about JavaScript regular expressions.

\n

Array

\n

JavaScript arrays are classed as objects except with a numerical index (rather than names/strings). As objects, they can contain mixed collections of data types including objects, functions and other arrays.

\n

Instantiation

\n
[element0, ...], new Array(element0 , ...|arrayLength)
\n

Properties

\n
length (number of elements)
\n

Methods (most common)

\n
concat(array2, ...), indexOf(needle), isArray(object), join(separator), shift(), pop(), unshift(item1, ...), push(item1, ...), sort(), reverse(), slice(start, exclusiveEnd), splice(index, numToRemove, itemToAdd1, ...), valueOf()
\n

Object

\n

Objects contain name:value pairs. The names must be a string (they can be numbers or reserved words but must be enclosed in quotes). The values can be of any data type including arrays, functions (methods) and other objects.

\n

Instantiation

\n
{name: value, ...}, new Object(value)
\n

Properties

\n
Whatever you define
\n

Methods (most common)

\n
Whatever you define, hasOwnProperty(name), propertyIsEnumerable(name), toString(), valueOf()
\n

Function

\n

Functions can be created as a declared function or as a function expression and can be assigned to a variable or object property (as a method). Function expressions can be created without a name as an anonymous function expression. They can even invoke themselves (self-invoked/self-executing/immediately-invoked function expression) as in run automatically on script load. All functions, regardless of how they are created can receive arguments via parameters. When invoked (or called), functions execute the code/procedure contained within. Functions often return a computed value back to the caller of the function. This return value can also be another nested function as in the module pattern. Yes, functions can be nested too (see closures below).

\n

Declaration/Creation

\n
function functionName(param1, ...) { code }, new Function(param1, ..., code), var functionName = function (param1, ...) { code }, functionName: function (param1, ...) { code }, (function (param1, ...) { code })()
\n

Properties

\n
length (number of parameters expected), arguments (.length, [i])
\n

Invocation

\n
functionName(arg1, ...), objectName.functionName(arg1, ...), new functionName(arg1, ...), (function (arg1, ...) { code })()
\n

Closures

\n

Closures allow us to create and access more secure, private variables within functions. Perfect for function factories, they also make it possible to persist an outer function\'s declared variables and arguments from within the inner function to be returned by the factory.

\n
function makeMyCar( car ) {\n\tcount = 0;\n\treturn function( colour ) {\n\t\tcount++;\n\t\tconsole.log( "You are #" + count + " in the " + car + " queue. Your chosen colour is " + colour + ".");\n\t};\n}  \n  \nvar fiestaFactory = makeMyCar( "Fiesta" );\nfiestaFactory( "Goblin Green" ); // You are #1 in the Fiesta queue. Your chosen colour is Goblin Green.  \n  \nvar bentleyFactory = makeMyCar( "Bentley" );\nbentleyFactory( "Posh Purple" ); // You are #1 in the Bentley queue. Your chosen colour is Posh Purple.  \n  \nfiestaFactory( "Perky Pink" ); // You are #2 in the Fiesta queue. Your chosen colour is Perky Pink.\n
\n

Hoisting

\n

JavaScript will automatically hoist all variable and function declarations to the top of the current scope, regardless of where they were declared in the script. Note that initialisations of variables and functions expressions will not be hoisted.

\n
console.log( x ); // undefined (the variable definition of x has been hoisted but not initialised yet)\nvar x = 123;\nconsole.log( x ); // 123 (now the variable x has been initialised)\n
\n

Strict Mode

\n

If we want to enforce a stricter environment and provide more error/exception information, we can tell browsers to compile in strict mode by placing the following either at the top of the script (global setting for the whole script) or within a function (local setting).

\n
"use strict mode"\n
\n

Strict mode enforces a boatload of restrictions such as preventing the use of undeclared variables, duplication of object and function parameters and assigning values to non-writable object properties.

\n

JavaScript Reference

\n

Here are some handy places to find a detailed reference for JavaScript:

\n', id:"/home/geoff/www/cornerpiece/geoffford.co.uk/src/pages/blog/07-01-2015-javascript-cheat-sheet/index.md absPath of file >>> MarkdownRemark",frontmatter:{date:"2015-01-07T19:16:22Z",path:"/blog/javascript-cheat-sheet",title:"JavaScript Cheat Sheet"}},next:{html:'

\n \n \n \n \n \n

\n

Welcome to the second post in my Responsive Web Design series. If you haven't already, check out the first post on the essentials of responsive web design.

\n

When responsive web design first came on the scene, most of us were still caught up designing for desktop and mobile separately. At first it might have seemed that we no longer needed our mobile websites anymore as we could now just scale down our desktop sites. A few max-width media queries here and there and we were good to go. It quickly became apparent however that this approach alone was not enough.

\n

The suggestion of a mobile first design approach actually precedes that of responsive web design. Luke Wroblewski first coined the term back in his November 2009 blog post, unsurprisingly named Mobile First. This was later followed up by a book in the A Book Apart series. Luke had observed the huge growth in mobile internet access pushed on by the rapidly growing adoption of smartphones. This indicated that not only should we be prepared for this growth, but we should embrace it wholeheartedly and turn our usual design approach on its head. The fact that mobile websites were designed for devices with limited screen real estate and unreliable bandwidth meant they had to be focused, uncluttered and light. What desktop website wouldn't benefit from some of that lean goodness?

\n
\n

"So when a team designs mobile first, the end result is an experience focused on the key tasks users want to accomplish without the extraneous detours and general interface debris that litter today's desktop-accessed Web sites. That's good user experience and good for business."

\n
\n

In addition, mobile browsers opened up more possibilities than your standard desktop browser with location via GPS, cameras, NFC (Near Field Communications), etc. Whilst support for these features has been patchy, it has improved with every new release.

\n

What does this have to do with responsive web design?

\n

Everything Luke brought to our attention about the benefits of thinking 'Mobile First' fit like a glove with the goal of responsive web design, one website to rule them all. It had been difficult to decide where all these desktop page elements (clutter) were going to fit on our small smartphone screens. And what about our navigation, hover effects, images, etc? Desktop websites that had been given the responsive overhaul were still too heavy and not always thought out very well. Navigation was frequently bunched so close together that you couldn't always hit the desired target. Some also relied on hover effects to indicate their presence and/or state which left visitors bemused.

\n

A clean slate

\n

So let's start out fresh! With a limited amount of space available, we have to get ruthless and cut out the crud. This part of the approach goes hand in hand with another known as 'Content First' which stresses not only uncluttered, leaner content, but also the priority of content over other elements like navigation. Who wants to scroll down through all of your navigation links to find what they actually came to see ... your content!

\n

Let's assume you have now binned any unnecessary page elements and are ready to tackle the primary site navigation. Whether left or right handed, most people use their thumb when operating a phone with one hand. It therefore stands to reason that your navigation should be placed at the bottom of the screen. Having said that, smartphones are getting bigger all the time so single handed operation may not be possible for those with smaller hands. Let's play along for now though and place our navigation at the end of our content (Note this also means it isn't getting in the way of our all important content). We are also going to make sure that each navigation item allows enough space for our chubby fingers to prevent any unexpected behaviour.

\n
        ...\n\t\t<section class="site-content">\n            <div class="wrapper clearfix">\n                <section class="main">\n\t\t\t\t...\n\t\t\t\tYour content here\n\t\t\t\t...\n                </section>\n                <nav id="site-nav">\n                    <a name="nav"></a>\n                    <ul class="nav-list">\n                        <li><a href="/">Home</a></li>\n                        <li><a href="/about">About</a></li>\n                        <li><a href="/blog">Blog</a></li>\n                    </ul>\n                </nav>\n            </div>\n        </section>\n        <footer class="site-footer">\n\t\t...\n
\n
#site-nav {\n  display: block;\n  width: 100%;\n}\n.nav-list {\n  display: block;\n  list-style-type: none;\n  padding: 0;\n  margin: 0;\n  width: 100%;\n}\n.nav-list li {\n  display: block;\n  width: 100%;\n}\n.nav-list li a {\n  display: block;\n  padding: 0 1em;\n  text-align: right;\n  font-size: 1.4em;\n  line-height: 2.4em;\n  height: 2.4em;\n  white-space: nowrap;\n}\n
\n

This is a good start but hang on, doesn't this mean we now have to scroll all the way through our content to get to the nav? Well, yes it does. So let's make that a little easier by putting a subtle but obvious link at the top of the page that will whisk us down to our navigation. The most common form for this link is the faithful 'hamburger' link. I use an icon font this but you can use SVG or just an image if you want. The first two are preferable as they scale well.

\n
        <header class="site-header">\n            <div class="wrapper">\n                <a href="/" id="header-logo">Your SVG/Icon/Image Logo Here</a>\n                <a href="#nav" id="site-nav-toggle" class="icon-alone">Your SVG/Icon/Image Hamburger Here</a>\n            </div>\n        </header>\n
\n
#site-nav-toggle {\n  float: right;\n  margin: 10px 10px 0px 0px;\n  border: 0;\n  outline: none;\n  font-size: 22px;\n  line-height: 22px;\n}\n
\n
\n \n \n Navigation moved to the end of the content\n \n \n
\n

Great stuff, looking good. Content is up front and center where it should be and our main navigation is out of the way but easily accessible. It turns out however that not everyone is a fan of this approach and can get confused when they suddenly find themselves at the bottom of the page after clicking on our hamburger button. This is especially obvious if you don't have many navigation items as they don't fill the screen and so the bottom of your content is visible above. We need some help.

\n

A tale of two strategies

\n
\n \n \n Graceful Degradation VS Progressive Enhancement\n \n \n
\n

As far back as 2003, two men (Steve Champeon and Nick Finck) were challenging what had for almost 10 years prior been an accepted strategy for delivering content - Graceful Degradation. The original idea was that when certain 'newer' features were not recognised by older browsers, the important content would still be visible, whilst the 'extras' would gracefully disappear without making a scene. This could be achieved for example by browser (and version) specific style sheets through various hacks. Unfortunately this wasn't as ideal as it sounds. Firstly designers rarely looked back beyond the previous version of a given browser which left all the users of older versions with a suboptimal experience. Also these webpages were cluttered with elements that were utterly useless to these older browsers and just added unnecessary weight.

\n

Their proposition - Progressive Enhancement - suggested turning the old approach on its head (sound familiar?) and starting out with the basic content. We could then, where the required support was available, add the bells and whistles to our base. That way everyone could be happy, from the most basic content experience up to the fully featured, 'throw everything at it' version.

\n

In its most basic form, progressive enhancement refers to a base of semantically marked up content, which can then be enhanced by separate CSS styling where supported. The content can then be further enhanced by JavaScript (again where supported), maybe by including additional content via an AJAX call.

\n

Today there are many libraries and techniques that help us to check for support of all sorts of features including the CSS3 and HTML5 palettes. In some cases we can even add those features to non supporting browsers with some black magic known as polyfills.

\n

Plugging the gap

\n

Whilst progressive enhancement tells us to include features only where support is available, another approach is to add that missing support, normally via JavaScript. Remy Sharp was the first to coin the term 'Polyfill' when trying to describe something that adds an API to a browser that doesn't already have native support.

\n

Here are a few polyfills that I use regularly:

\n\n

Enhanced navigation

\n

Earlier we created our mobile first navigation that sits at the bottom of the screen for browsers that don't support JavaScript. For those that do, we can move the navigation back up top and enhance it with a nice show/hide effect (with a little help from jQuery) behind our hamburger button.

\n
$(document).ready(function() {\n\t$('#site-nav').insertAfter('.site-header').css('display','none');\n\t$('#site-nav-toggle').attr('href','#').click(function(e) {\n\t\t$('#site-nav').slideToggle("fast");\n\t\te.preventDefault();\n\t});\n});\n
\n
\n \n \n Navigation moved back to the top\n \n \n
\n

Let's take things a step further and change our navigation at different break points so we get a more traditional navigation menu in larger viewports. I have tried to achieve this without the help of JavaScript.

\n
@media screen and (min-width: 50em) {\n  // Position the navigation block top right\n  #site-nav {\n    display: block;\n    position: absolute;\n    top: -65px;\n    right: 0px;\n    bottom: auto;\n    left: auto;\n    width: auto;\n  }\n  // Display navigation items inline\n  .nav-list {\n    float: right;\n    width: auto;\n    background: none;\n    border-bottom: none;\n  }\n  .nav-list > li {\n    width: auto;\n    float: left;\n    display: inline;\n    border: none;\n  }\n  .nav-list > li > a {\n    background: none;\n    float: left;\n    text-align: center;\n    font-size: 1.4em;\n    line-height: 1.4em;\n    padding: 0;\n    margin-left: 1.6em;\n    margin-top: -10px;\n  }\n  // Hide the hamburger button\n  #site-nav-toggle {\n    visibility: hidden;\n  }\n}\n
\n

We have a small problem now that if JavaScript is enabled, the earlier code would have already moved our navigation block to a different location and we would get unexpected results from our CSS media queries. Ideally we want to move our navigation block back when the above media query matches. Using an awesome little library called enquire.js, we can replicate our CSS media queries and trigger our enhancements at specific break points. Let's replace the earlier JavaScript with the following:

\n
// Move navigation block for smaller viewports and move back when match lost (larger viewports)\nenquire.register("screen and (max-width: 49.9em)", {\n\tmatch : function() {\n\t\t$('#site-nav').insertAfter('.site-header').css('display','none');\n\t\t$('#site-nav-toggle').attr('href','#').click(function(e) {\n\t\t\t$('#site-nav').slideToggle("fast");\n\t\t\te.preventDefault();\n\t\t});\n\t},\n\tunmatch : function() {\n\t\t$('#site-nav').insertAfter('.main').css('display','block');\n\t\t$('#site-nav-toggle').off('click');\n\t}\n});\n// Display navigation block for larger viewports and hide when match lost (smaller viewports)\nenquire.register("screen and (min-width: 50em)", {\n\tmatch : function() {\n\t\t$('#site-nav').css('display','block');\n\t\tmenu.init();\n\t},\n\tunmatch : function() {\n\t\tmenu.destroy();\n\t\t$('#site-nav').css('display','none');\n\t}\n});\n
\n
\n \n \n Navigation on larger viewports\n \n \n
\n

I couldn't discuss progressive enhancement and not mention one of the best tools in the box. Modernizr allows you to test for specific CSS3 and HTML5 feature support. It then adds CSS class names to the html element to show which tested features are supported. You can then precede your own class names with the Modernizr ones to ensure your styles are only applied when that feature is supported. Maybe I will cover this in another article, but please do check it out.

\n

So there you have it, a base navigation that is optimised for mobile first, then progressively enhanced with CSS and JavaScript. The same principles can and should of course be applied to other aspects of your design. And you can take the whole progressive enhancement idea much further with dynamically loaded page elements via Ajax etc. Let's allow everyone to enjoy their encounter with your website regardless of browser or device and access your content in an appropriate way.

',id:"/home/geoff/www/cornerpiece/geoffford.co.uk/src/pages/blog/08-03-2014-responsive-web-design-mobile-first-and-progressive-enhancement/index.md absPath of file >>> MarkdownRemark",frontmatter:{date:"2014-03-08T05:18:12Z",path:"/blog/responsive-web-design-mobile-first-and-progressive-enhancement",title:"Responsive Web Design: Mobile First & Progressive Enhancement"}}}}}}); //# sourceMappingURL=path---blog-angularjs-essentials-0b3e08764e4a41b89b61.js.map