Guiding The Geek In You
Restangular is a powerful, third-party AngularJS module designed to greatly simplify REST communication by abstracting specific transactional code from your application code. Restangular APIs offer a uniform approach to handling HTTP methods, as well as deliver results in a tidy Promise object while freeing developers from the need to use specific URLs. Configure Restangular at one end to wrestle with external APIs, and at the other to enjoy accessing data in a simple Promise-based fashion.
Installing Restangular is well-covered by the mgonto/restangular repo readme, but in summary is easy as:
bower install restangular
or
npm install restangular
Once installed, inject ‘restangular’ into your app as you would any third-party resource:
angular.module('yummyFruit', [ 'yummyFruit.services', 'restangular' ]);
At first blush, configuring Restangular may seem daunting. The vast number of methods, and the equally vast number of ways to use them, can quickly make any “starter” Restangular project into a casserole of configuration mish mash. Therefore, the most sensible approach for configuring Restangular in a single API base URL scenario is by starting with the application config method:
.config(function(RestangularProvider) { RestangularProvider.setBaseUrl('https://api.tropical.com'); });
Restangular will now use https://api.tropical.com
as the base URL for all API calls. Injecting Restangular as a dependency into your service(s) and configuring your API endpoints is simply a matter of:
angular.module('yummyFruit.services') .service('FruitService', function(Restangular) { var FruitService = this, fruits = Restangular.all('/fruits'); FruitService.getFruit = function() { return fruits.one('/').get(); }; });
The configuration detailed above works great in a single API scenario. However, most sophisticated web applications lean heavily upon multiple APIs, each with their own unique access requirements. Therefore, a more robust solution is required.
In a well-modularized application, global services should be contained within their own folder. To further improve modularity, I like using a separate file to create a global Service module. As it turns out, this file – _services.js
– is an ideal place to configure Restangular to use multiple API base URLs.
angular.module('yummyFruit.services', []) .factory("TropicalRestangularApi", ["Restangular", function(restangular) { return restangular.withConfig(function(RestangularConfigurer) { RestangularConfigurer.setBaseUrl("https://api.tropical.com"); }); }]) .factory("BerryRestangularApi", ["Restangular", function(restangular) { return restangular.withConfig(function(RestangularConfigurer) { RestangularConfigurer.setBaseUrl("https://api.berries.com"); }); }]);
Each factory is a self-encapsulated, Restangular instance, each featuring a unique base URL. Additionally, the factories are centrally located, affording easy reference for all team members. Exposure to the Restangular API factories is easily arranged via dependency injection:
angular.module('yummyFruit.services') .service('FruitService', ['Restangular', 'BerryRestangularApi', function(Restangular, BerryRestangularApi) { var berryFruitApiBase = BerryRestangularApi.all('/api'); }]);
Application services within the services module can now use one, some, or all the individual APIs at will, and without any more configuration necessary.
If you found this post useful, please share it on Twitter, Reddit, or your other favorite social media outlet! Questions? Hit me up on Twitter @jasonlunsford or leave your question in the comments below.
Thanks for reading!
Compass In Hand has been dormant for a long time, but starting today we are back in business! New content is around the corner. In fact we are kicking off with a new mini-series called “Mini-Wins”, bite-sized solutions to issues common in AngularJS based web application development. But be warned! These solutions are by no means “perfect” – many better fixes and smoother techniques almost certainly exist. That said these Mini-Wins are battle tested and work great for me, and may hopefully help you too.
Most importantly, I would also like to formally announce the next iteration of the Lunsford clan has joined us! Please say hello to our son, Nolan Grant Lunsford!
Thanks for reading! Please find me on Twitter or leave your comment down below.
Building an AngularJS application using partial views and supported by a Node.js / ExpressJS back-end is doable with a little effort.
Two methods exist for creating modules in AngularJS. I prefer the setter method. Note below we are injecting dependencies on our external controller and ngRoute. Both of these items source from external JS files, so don’t forget to attach them within your index.html.
angular.module('myApp', [ 'ngRoute', 'myApp.controllers' ]).
Pro Tip: Ensure the angular.js version matches angular-route.js! Download them both at the same time from code.angularjs.org.
$locationProvider allows access to .html5mode(), a piece of Angular magic that ensures URLs look like regular URLs in modern browsers, and hash-bangs in older ones. Neat trick! Keep these two caveats in mind when configuring a Node.js / ExpressJS installation:
config(function ($routeProvider, $locationProvider) { $routeProvider. when('/', { templateUrl: 'partials/home', controller: 'HomeController' }). when('/pizza', { template: 'I Love Pizza!' }). otherwise({ redirectTo: '/' }); $locationProvider.html5Mode(true); });
Standard configuration from the Angular perspective thus far. The controller is also super basic – just stubbed out for later use:
angular.module('myApp.controllers', []). controller('HomeController', function ($scope) { });
Configuring Node.js correctly (via the ExpressJS framework) is tricky. However, thanks to btford’s excellent seed project (available on github) I refined this:
var express = require('express'), routes = require('./routes'), http = require('http'), path = require('path'); var app = module.exports = express(); app.engine('html', require('ejs').renderFile); app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'html'); app.use(express.logger('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(app.router); if (app.get('env') === 'development') { app.use(express.errorHandler()); }
Pro Tip: Make sure this line:
app.use(express.static(path.join(__dirname, 'public')));
comes before this line:
app.use(app.router);
Order matters! We need Node.js to serve the static page request before passing the request to a route handler. This way AngularJS $routeProvider works as it should.
app.get('/', routes.index); app.get('/partials/:name', routes.partials); app.get('*', routes.index);
The code above is the connective tissue between AngularJS and Node.js. First, note the references to routes.index. They point to index.js, the JS file containing the specific routing information about the three potential GETS. The first and third lines will route all traffic to the index page, and line two routes requests to the partials directory (rendering any partials found within). Line three in particular is important, as this catch-all is vital for enabling html5mode in our AngularJS configuration.
Index.js:
exports.index = function(req, res){ res.render('index'); }; exports.partials = function (req, res) { var name = req.params.name; res.render('partials/' + name); };
And finally, to kick off our Node.js server:
http.createServer(app).listen(app.get('port'), function () { console.log('Server listening on port ' + app.get('port')); });
The entire Node.js configuration file:
/********************* * Module dependencies *********************/ var express = require('express'), routes = require('./routes'), http = require('http'), path = require('path'); var app = module.exports = express(); app.engine('html', require('ejs').renderFile); /*************** * Configuration ***************/ // all environments app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'html'); app.use(express.logger('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(app.router); // development only if (app.get('env') === 'development') { app.use(express.errorHandler()); } /******** * Routes ********/ // serve index and view partials app.get('/', routes.index); app.get('/partials/:name', routes.partials); // redirect all others to the index (HTML5 history) app.get('*', routes.index); /************** * Start Server **************/ http.createServer(app).listen(app.get('port'), function () { console.log('Server listening on port ' + app.get('port')); });
Awesome, an environment which supports AngularJS, runs Node.js / ExpressJS! All that’s missing now is the View.
If you are like me you prefer your HTML as pure as the driven snow. By default Express does not make this possible, as it requires the use of Jade, an HTML Template technology. Fortunately, Embedded JavaScript (ejs) is an easy replacement for Jade, affording us the luxury of a powerful framework and clean markup. Download and install ejs as you would any other node plug-in:
npm install ejs
That’s all folks. Comments, questions? I would love to hear from you. Don’t be shy, and…
Thanks for reading!
Happy New Year! It has been a few weeks since my last post. My sabbatical was refreshing and productive. I finished my first major AngularJS project, which I am excited to start writing about, and of course took some much-needed down time. I hope your end of year festivities were equally pleasant.
This year I have a diverse topic list in store for CompassInHand that I hope will be as interesting to you as it is educational to me. Technology is amazing. There is no end to what can be learned. My hope is that I can give back some of what others are teaching me.
As mentioned, I released my first application written purely in the “Angular way”: Our XBOX 360 Library (OX360L)! If you are interested in checking out the code, please visit the project git repo.
Loyal readers will note: prior to my holiday sabbatical my posting interval was about once per week. Unfortunately I rarely had enough time to do the research, understand the technology, and write a quality post about it within the single week. Therefore my new posting interval will be about twice per month. The additional week will be a tremendous help and should make for tighter posts with more code examples.
While no release date exists yet, this year you can expect CompassInHand to undergo a big face lift. With the help of my good friend (and new father!) Trian Koutoufaris a new WordPress theme is slowly taking shape – including an actual site logo! Stay tuned.
Finally, I plan to begin supporting RSS feeds. This is not a big technical challenge, just an administrative oversight I never considered before. Whether this feature is useful will be up to you guys – please, comment and let me know!
Lots of things!
Over the next several posts I will be discussing some of the many (many, many) lessons I learned while building OX360L. Some of these lesson topics may include:
Looking past Angular / OXB360L, other post topics coming in the next several months will include:
Finally, I have another project getting ready to spin up. Look for hints and mentions as meaningful progress is made. Hopefully it can be useful for all of you who go to lunch with coworkers.
Thanks for reading!
Happy Post-Thanksgiving weekend everyone!
This week I begin a non-sequential series of posts describing my experiences writing plugins for the jQuery library. My idea is to cover the evolution of one – or a small set of – plugins from version 1.0 to “launch”, where launch in this case means promotioning my plugins within the massive ecosystem of the jQuery universe as loudly as possible!
The opportunity to write the first plugin for this series – Primer Carousel – came as a result of a well-designed coding challenge I recently completed. The source for this challenge is available via my public git repo here. As always your opinion is welcome; please leave your comments below or send a pull request on github.
(function ( $ ) { $.fn.primerCarousel = function( options ) { }; }( jQuery ));
The first step in writing a plugin is remembering the global namespace. Functions structured in the above format are known as Immediately-Invoked Function Expressions (IIFEs). Using the format here is essentially defensive. We want to use the $ character, but we also must be polite citizens and cooperate with other JS libraries who love the $ character. The solution: pass the function jQuery and name the parameter $, which satisfies both requirements. Perhaps the most important purpose of a IIFE, however, is that it allows private variables accessible only within the function itself.
By using .fn() object we are extending the methods made available to the jQuery object to include our plugin (which becomes just another method). Developers can therefore attach the .primerCarousel() method to any appropriate block element. Additionally, notice the use of “options”? This object contains whatever user defined settings have been made available. In version 1.0 of Primer Carousel we offer one setting, rotation speed.
var globlalOps = $.extend( {}, $.fn.natCarousel.defaults, options ); var filmStripWidth = 0; var thumbNailCount = 1; var $filmStrip = $(".filmStrip"); var $focusArrow = $("#focusArrow"); var $filmStripCollection = $(".filmStrip").find("div"); var $smallImageCollection = $(".smallPictureRow").find("img"); var widthOfLargeImage = $filmStripCollection.width(); var widthOfSmallImages = $smallImageCollection.width(); var thumbNailArraySize = $smallImageCollection.length;
I prefer defining all of my variables up top. I know other developers prefer a “define where you use” technique – so go with what you know. There are a couple of important things to call out here. First, by using an empty object as the first passed parameter to the $.extend() method we ensure the custom defaults object is not overridden by the options object. Instead a third object is created by joining the two others.
Next, Primer Carousel relies on existing markup to function properly. This design choice speaks to a larger question: is it better to ask developers to implement a specific HTML structure for your plugin, or give the plugin a root container and rely on it to generate the HTML it needs? Obviously the later option is the most common – and from a reusability standpoint the most sensible. However, dealing with assets provided by the developer (images, for example), and operating within unique markup constraints means coding a robust evaluation system capable of detecting dimensions, calculating asymmetrical widths, and so forth. This version of Primer Carousel assumes symmetrical image width – a luxury afforded only in a test bed. Look for more robust environment evaluation logic in version 2.
// Initialize timer variable var rotateTimer; // Prepare film strip element containing the large image slides $filmStripCollection.each(function() { var $this = $( this ); filmStripWidth += $(this).width(); }); $filmStrip.width(filmStripWidth); // Carousel Control - Manual $smallImageCollection.on("click", advanceFilmStrip); // Carousel Control - Automatic rotateTimerStart(); // Pause carouseling on roll-over this.on("mouseover", function() { rotateTimerClear(); }).on("mouseleave", function() { rotateTimerStart(); }); // Initialize, Set, and Clear Interval function rotateTimerInit() { advanceFilmStrip(thumbNailCount); // basic position counter ( thumbNailCount < 3 ) ? thumbNailCount++ : thumbNailCount = 0; } function rotateTimerStart() { if ( typeof globlalOps.speed !== "number" ) { globlalOps.speed = 4000; } rotateTimer = setInterval(rotateTimerInit, globlalOps.speed); } function rotateTimerClear() { clearInterval(rotateTimer); }
You may notice the heavy reliance upon the setInterval() and clearInterval() functionality in this section? These two methods are extremely helpful when creating automated behavior. Consider wrapping them in functions to improve overall code DRY-ness, and in my opinion three timer functions work the best – initialization, start, and clear.
Also, functions defined within a IIFE formatted plugin are truly private. Returning anything back to the calling script requires return – which Primer Carousel does not need. However, if your plugin needs to be chainable then something must be returned.
function advanceFilmStrip(thumbIndex) { // two use cases: the thumbnail clicked or function fired automatically if ( typeof thumbIndex === "object" ) { var $this = $( this ); var thumbPosition = $smallImageCollection.index(this); var smallImageLeftMargin = $this.css("marginLeft"); } else { var thumbPosition = thumbIndex; var smallImageLeftMargin = $smallImageCollection.eq(thumbIndex).css("marginLeft"); } // Convert px measurement to an integer smallImageLeftMargin = (smallImageLeftMargin.replace("px","")) * 1; // Calculate current position var filmStripPosition = widthOfLargeImage * thumbPosition * -1; var focusArrowPosition = (widthOfSmallImages + smallImageLeftMargin) * thumbPosition; // move the images $filmStrip.css("left",filmStripPosition+"px"); $focusArrow.css("left",focusArrowPosition+"px"); }
The secret sauce is all right here. You probably noticed the typeof check made on the incoming parameter? This is done because of the dual use cases in which advanceFilmStrip is called. In my opinion this is a mistake, I should only ever need to accommodate for a single parameter type (in this case, object or integer).
$.fn.natCarousel.defaults = { speed:4000 };
Being kind in this case means saving developers the effort of hunting through our source code to find where we configure our default plugin options. This object should contain the entire range of all available options – version 2 of Primer Carousel will have several more, including spin direction, animation, and on-screen controls.
In my opinion, just because your plugin CAN do something does not mean it must – nor does it mean those functions must be documented for the end user. Think carefully about what features users will want and refine accordingly. Also, use conventions! Primer Carousel’s speed setting accepts an integer, and passes (with error checking, naturally) that value directly to the setInterval method. Abstract settings like “fast” or “ultra slow” simply add an additional layer of complexity. The goal is to make developers want to use our plugins because they work exactly as expected, reliably, and with a minimal education required. Keep it simple!
Thanks for reading!
Sometimes the hardest part about a project is sitting down to organize your environment before you begin. Sure, you probably have several, maybe hundreds, of pieces of functional code stashed in your git repo or squirreled away in different folders on your hard drive, but starting a brand new project? Ugh! Enter the project sandbox.
Project sandboxes are templates designed for easy duplication that allow you to quickly create an ideal project environment. Pre-configured folder structures and file names optimized to your liking make launching a new project as easy as duplicating a template and making a tweak to the new project’s server config file.
Similar to regular sandboxes – also known as development servers – project sandboxes isolate projects to a well-defined structure, preventing code pollution. The key difference is Sandboxes are usually designed for developing within an existing code base protected by a code repository. Project sandboxes, however, exist only to help start new and potentially disposable development in a reliable way.
Regarding naming schemes: the word of the day is CONSISTENCY. Name your project sandbox files anything you like and commit to your scheme. When you find a better naming method (and you will), retrofit your project sandbox right away – don’t put it off! Using consistent file names will build strong mental associations that help you decide where to put certain code.
My project sandbox files:
Some file stubs (files that exist without any content) I like keeping handy to handle RWD needs, or to load AMD formatted scripts, respectively:
Flexibility in terms of a project sandbox means keeping a variety of battle tested and carefully vetted resources at your finger tips, not all of which you may need for every project. Some resources should be configured to load by default, while others (like frameworks) are kept out of the loading stack.
Some of my core resources:
General Tools
Asynchronous Resource Loaders
JS MVC Frameworks
JS Libraries
Should you use a CDN or keep your toolkit stored locally? I prefer using local files. Staying local removes a layer of potential complexity (not relying on a file that probably stays the same), improves performance, and keeps resource files readily available for dissection. That said, CDNs are extremely valuable in many other situations.
However, using local resources means you must manually keep your project sandbox current. Get into the habit of watching for updates, reading release notes, and making informed decisions about updating your resources. Broken and dull tools are even worse than no tool at all!
Folder organization depends largely on your web server and middle tier language of choice. Discussing the best ways to organize folders for different servers and languages could be a cool topic for another day.
Since I use Node.js my project sandbox folder structure is pretty simple, as demonstrated below.
Of course, this is only a start! Your project sandbox can be tailored in any way you see fit and will change over time. The important lessons are: make one, keep it consistent, keep it current.
Good luck, and please comment with any suggestions. And as always, thank you for reading!
Special Note: Congratulations to the AngularJS team on their 1.2.0 release! New features, better security, more stability. Read more about it on the AngularJS blog.
Before we continue I would like to quickly mention how important a good sandbox is for the rapid building and breaking of educational code. In an upcoming post I plan to cover how I configure my sandbox. For now I recommend attaching the excellent CSS framework Bootstrap to your project index.html files to take advantage of pre-constructed classes that will make your rendered markup – tables in particular – easier to read.
Note these are View snippets – in order for these Bootstrap classes to work you must initialize the parent containers with their own Bootstrap classes. Again, more on this in a future post.
<div ng-app="myApp"> <div ng-controller="AvengersCtrl"> <table class="table table-striped table-bordered"> <tr ng-repeat="actor in avengers.cast"> <td>{{actor.name}}</td> <td>{{actor.character}}</td> </tr> </table> </div> </div>
Did you notice?
ng-repeat="actor in avengers.cast"
The ng-repeat directive is an example of angular magic; a small directive that drives iterations through data sets without needing extensive pre-configuration. Sweet!
// Initialize App var myApp = angular.module('myApp', []); // Create the Service myApp.factory('Avengers', function() { var Avengers = {}; Avengers.cast = [ { name: "Robert Downey Jr.", character: "Tony Stark / Iron Man" } // rest of the cast added here, more entries = bigger table ]; return Avengers; }); // Define the Controller function AvengersCtrl($scope, Avengers) { $scope.avengers = Avengers; }
Adding a Search filter, for the entire table or for a single column, only requires a small change to the View.
<input type="text" class="form-control" ng-model="search.$">
Using the dollar sign “$” refers to all available fields and is perfect for a table-wide search:
ng-model="search.$"
Replace the dollar sign “$” with “name” to limit searching to the name field:
ng-model="search.name"
Finally, enable search by adding the following:
<tr ng-repeat="actor in avengers.cast | filter:search">
In addition to outputting markup, each ng-repeat loop iteration can also be piped through a filter, as I’ve done in this example. Pattern matching is just one example; many other filters are available for even more advanced output manipulation. Refer to the AngularJS docs for more information on this awesome feature!
Huge credit for my continuing AngularJS education goes directly to egghead.io. Their awesome video library and associated sample code, most of which is FREE, is an incredible addition to the community. Thanks in particular to John Lindquist for explaining these concepts so clearly.
Thanks for reading.
A few nights ago over coffee at the local Starbucks I enjoyed one of those moments we as web developers secretly love: a full throttle conversation about ideal, multi-tiered web applications. As we broke down tiers and discussed their relationships, we considered different scenarios: what if the user is on a mobile device? What if their connection speed sucks? What if the site they are using has a million controls?
In fact, what if the website looked and needed to behave like a regular application? Would a massive collection of ad hoc jQuery event handlers, Ajax calls / RESTful services and finely crafted HTML be enough? Maybe. But a better solution exists. Enter the framework.
A framework is a specialized type of library. For programming languages, a library is a collection of behaviors (think: functionality) written in terms of the language, that can be called by using a well-defined interface. Libraries are meant to be used by multiple programs or in multiple areas of a single program, largely because they encapsulate commonly used functionality set apart from the program’s actual code. This makes writing complicated code somewhat easier, as repetitive / complex chores have already been solved and are only a friendly method call away.
A library is passive. Developers must write their code using that library’s interface to get anything out of it. Thus an entire program can be written never using a library’s treasure trove of functionality, even if available the whole time. Not so with frameworks.
Like the libraries from whence they came (poetically anyway), frameworks are a collection of functionality written in terms of the language they support. Frameworks are portable, meaning they too can be reused in multiple projects written in their given language. However, unlike a library, frameworks are bossy. Using a framework correctly means subscribing to how the framework developers view application organization and development. Let that sink in for a moment. Within a framework, your program no longer directs traffic. The framework becomes the traffic cop, and your program the exotic sports car (or three row SUV, which ever you prefer).
Frameworks share four attributes that set them apart from libraries. Where libraries are accessed as needed, frameworks work on the Hollywood Principle, aka “Don’t call us, we’ll call you.” The framework takes care of business and calls your program when it’s show time. The fancy term for this behavior is inversion of control. Second, a framework must have a default behavior, meaning once installed and properly configured, it has to do something useful right out of the box (typically a “hello world”). Next, they must afford some way for developers to extend their functionality, either by overriding default behavior or by creating new behavior within the internal guidelines. Finally, framework internals are considered off-limits. Extend all you want, look under the hood, show it off to your friends, but don’t touch anything inside. Modify the magic and you void the warranty.
During my research I looked at many languages. Each of these languages had at least one framework written for them. So, while a statement like “all languages have frameworks” would probably get me in trouble, I think it is safe to say frameworks have benefits that are tough to ignore, no matter the language. Here are a few popular languages and their corresponding web frameworks:
PHP: CodeIgniter, Zend
Ruby: Padrino, Rails, Sinatra
Java: Grails, Play
Python: Django, Zope2
JavaScript: AngularJS, Ember.js, Backbone
Node.js: Express, geddy, Meteor
In fact, frameworks are so helpful they are even used in CSS. Examples include:
Bootstrap
Foundation 3
Skeleton
Frameworks are not for everybody. Some are better than others in any given situation. Frameworks can have tough learning curves, particularly for the novice developer. The unusual usage demands and seemingly arbitrary control flow may seem senseless until well understood. Framework use can also lead to code bloat by adding unnecessary functionality and inspiring work arounds written by developers unfamiliar with the framework’s complexity. Speaking of complexity, take a look under the covers and marvel at the magic. Pre-implementation study and research is sincerely recommended!
These are real concerns you should absolutely consider. However, frameworks also bring a feast to the table. As well-tested and typically open source application scaffolding, frameworks can help separate concerns in extremely reliable ways, decreasing code spaghetti. In fact code quality is often amplified when developers follow usage rules and color inside the lines. Although structured, frameworks are extensible when necessary – while still cutting development time by taking care of common tasks (just like any other library). Finally, over the long-term the framework becomes invisible, improving project delivery time and code reusability.
Thanks for reading, and happy frameworking!
The conventional approach to detecting screen resolution with JavaScript using RWD requires you to duplicate break points within your actual code and consequently having to maintain them in two different places. Very annoying. Using a flag embedded in each of your CSS break points is a much simpler approach because they can be programmatically accessed. Multiple flag techniques exist, but in this blog post I will discuss my personal favorite, the pseudo-element flag, invented in 2012 by Jeremy Keith and the readers of his blog adactio.
Pseudo-elements exist in an odd realm. Technically they are not part of the DOM, so they cannot be accessed via traditional selectors nor participate in regular DOM flow. Pseudo-elements, and their cousins, pseudo-classes, are CSS constructions that afford some interesting presentation options. We have all used pseudo-classes before, such as :hover, :focus, and :first-child. Pseudo-elements are used in a very similar way, but not quite as often.
The relationship between real elements and their pseudo-element counterparts:
Image Source: Nicolas Gallagher, blog entry Multiple Backgrounds and Borders with CSS 2.1 (original image revised by me to remove some copy not topical to this blog entry, and to trim it down to size).
In fact, pseudo-elements are not new – CSS1 introduced :first-line and :first-letter. CSS2 saw the arrival of :before and :after, and CSS3 has introduced the newest member of the team, ::selection. As a quick side note, CSS3 spec suggests we use double colons (::) when using pseudo-elements, to differentiate them from pseudo-classes, which use the single colon (:). However backward compatibility within browsers ensures the single colon works for both cases, and from a practical standpoint it’s probably best to still use the single colon for now.
The :before and :after pseudo-elements, having been around for many years, are in fact backward compatible all the way to IE8 (not that modern Android or iPhone users care – but it’s still good to know). The caveat however is that the HTML5 document type declaration must be used, or IE8 will poop the bed and forget everything it learned.
While other techniques probably exist, the way I implement pseudo-element flags is to differentiate one at each break point. Therefore, the values contained within each set of CSS rules for each independent flag remain constant. For this reason I like to attach the flag to a relatively safe, static element, the body itself.
body:after{ }
As CSS constructs pseudo-elements enjoy CSS rules not available to conventional DOM objects. One in particular is in fact the secret in our secret sauce:
body:after{
content:"mobile";
}
To ensure the content is not actually displayed we’ll add the final piece:
body:after{
content:"mobile";
display:none;
}
Okay so, if a pseudo-element is not part of the actual DOM, how can we access it – or more to the point, the CSS rules defined for it? The answer:
window.getComputedStyle()
This sweet method returns the CSS styles applied to an element and the corresponding pseudo-elements, after the browser has finished applying them. Nifty right?
function whatIsMySize() { return window.getComputedStyle(document.body,':after').getPropertyValue('content'); }
Now you have access to the value of the content property of your pseudo-element. Nice!
Last note: Firefox (maybe others, I haven’t tested them all) will return an extra set of quotes if your content value was a string. So, in the example above, Firefox would return:
""mobile""
Thus for conditionals I like to use:
var checkMySize = whatIsMySize();
if ( checkMySize.indexOf("mobile") != -1 ) { // off to the races }
Thanks for reading!
Invented by Trygve Reenskaug, who originally called it the “Thing-Model-View-Editor” way back in 1979 (read all about it), the MVC design pattern has been a staple in software design since it appeared in the Smalltalk-80 class library.
Discussing software design patterns exceeds this post by light years, as does the interior magic of MVC (and siblings such as MVP, and MVVM, and so on). However, let’s cover a couple quick concepts in as non-boring-as-hell way as possible.
The MVC design pattern is focuses on “separation of concerns”. Meaning, software built using this design pattern is composed of pieces belonging to one of three main areas:
For example, when the user interacts with the software by changing the contents of the first name field, the controller handles the user input and changes the state of the model (which is responsible for storing that name somewhere). The controller does not directly tell the view “hey, the user changed the first name and I asked the model to save the information.” Instead the view is observing changes made to the model, and when those changes require a refresh of what the user actually observes on-screen – that refresh happens.
This is simplifying a more in-depth process – but hopefully you can appreciate how each piece has a unique role to play, and that the unity of these roles forms a very tight and reliable pattern for software design.
Absolutely! JavaScript has been in circulation for years. As a language made available via almost every browser it has penetrated into a vast assortment of devices. While the wise programmer will Progressive(ly) Enhance their sites – you never know whether JS is disabled, after all – it’s a safe assumption JavaScript will be available.
Of course raw JavaScript is rarely used anymore in a de-facto sense. While there are obvious speed and precision benefits to hand-coding JS, libraries (and the ocean of plug-ins available there-in) and frameworks take JavaScript development into entirely new realms. Frameworks in particular bring a virtue to the JavaScript ecosystem that have made complex single page development practical.
Understand: when you use a framework your code rests upon and within it. There are rules that should be followed, and coloring outside the lines is discouraged – and can sometimes be disastrous. So choose your coloring book with care.
A quality code base and an appropriate feature list. Will the framework do what you need it to do? Do you understand what’s happening under the hood?
Has the framework been endorsed by big companies? Implementation is a great sign of endorsement – do your research, who’s using this framework?
Are other developers actively supporting the framework? How many? Are the builds coming out fast and furious? Stability is good, commitment to growth over time is even better.
Documentation is vital! A big advantage to a JS MVC framework like Backbone is the sheer number of educational resources available to the developer.
Frameworks exist on an “opinionated” scale. Some, like AngularJS and Ember.js, are tremendously opinionated and will, via convention and scaffolding, handle many basic duties on behalf of the developer. These duties can include standardized file and URL structures. Un-opinionated frameworks like Backbone leave file and URL structuring up to the developer, sometimes frameworks even ask the developer to figure out their own routing and data storage solutions.
How interoperable is this framework? If you want to gently insert pieces of a framework into your existing code base, will the framework tolerate it? Backbone is happily inserted where ever you squeeze it. AngularJS is also friendly, but prefers some control – for example AngularJS prefers (but in no way requires) its built-in jqLite over jQuery, mostly because jqLite makes unit testing easier. Ember.js, however, demands total domination. It wants to control the entire page at run time.
Consider your target audience and the devices they likely use. Now, look at the file size of your framework including all dependencies. Realize that fully featured frameworks like Ember.js come equipped with built in solutions and typically only requires a single dependency, handlebars.js. Backbone, on the other hand, despite how lightweight and un-opinionated it is, needs underscore.js and jQuery (for desktops) and / or zepto.js (for mobile) to run. These requirements add weight.
Finally, avoid the insanity caused by YAFS (Yet Another Framework Syndrome) by downloading and using the amazing TodoMVC. TodoMVC is a collection of many of the leading JS MVC frameworks and assigns a single task to each: render a handy little To-Do List application. The UI is friendly and identical between each implementation. All of the code is exposed and ready for analysis. WooHoo!
Consider the problems solved by a framework:
Now consider the pain a framework implementation will bring:
Lastly, keep in mind that implementing single page applications is the core strength of the JS MVC. Therefore, if your project is a basic web page application a framework might be an over-engineered solution. I say “might” because some frameworks, like Backbone, can usefully solve common issues even in these traditional applications.
Awesome! Go download the framework and the dependencies, then load them into your Hello World project template, just like you would a JS library. Or, if you prefer and the option is available, use the CDN made available by the framework community.
After the World has been Hello’ed adequately, study the TodoMVC implementation of your framework. Peel back the covers, read the comments, study the hell out of the source and do your best to understand what is going on. You may come to rely on the awesome magic Ember.js, AngularJS, or your MVC of choice provides – but first do your best to understand it!
Finally, start your own project. In upcoming posts I will be discussing my project, including which framework I use and why. Stay tuned, and thanks for reading!