Angular UI-Grid with SASS

Do a lot of AngularJS these days. As my readers know, I do a lot with data grids. Looking for feature rich data grids, written in Angular, that support Bootstrap styling, I long ago went with Angular UI-Grid.

But, one down side to UI-Grid is that the source code uses LESS for it's style sheets. Don't get me wrong, I do like LESS, but I've come to find SASS to be a little better to work with when overriding core variables at compile time. But in UI-GRID? Alas, no SASS.

So, what did I do? I ported the LESS to SASS. Over in my GitHub projects you'll find the new ui-grid-sass project, where I took all of the LESS in UI-Grid and did my best to give a one for one retool for SASS. It's also in the npm registry, so you can easily add it to your project.

Now, my mad SASS skillz are...ok. I've tried to cover everything, but I'm not perfect. So, if you're a SASS ninja, and have some interest, please feel free to contribute.

Node Angular Template

More for myself than anything, I created a base application template and put it up on GitHub. Feel free to fork it, and contributions are welcome. Here's what it has out of the box:

  • AngularJS 1.5
  • UI-Router
  • Bootstrap (LESS compiled)
  • Gulp Build
    • Lint
    • Transpile (ES6 -> ES5 with Babel)
    • Browserify
    • LESS
    • JS and CSS concatenation and minification
    • JS and CSS file versioning
    • and More!
  • JavaScript Unit Testing with Jasmine
  • Simple Node Server Script
  • Sample (Simple) AngularJS App with State Routing

I just needed something as a base to start other projects off of, so I threw this together as a starting point. You need Bower and NodeJS to get started, but all of the instructions are on the GitHub Page. Use it for your own projects, a quick look at AngularJS with ES6, or a sample of writing Gulp tasks.

All feedback encouraged and welcome.

2014 in Review: A Year of Learning

2014 has been an outstanding year for me, in many ways, but perhaps one of the most important things (besides my family) has been continuing to do what I love. I'm passionate about development, and constantly working to learn new things. This is important for any developer, as our world changes so quickly today. New standards, new languages, new frameworks, it's a consistent onslaught of new ideas, and impossible to learn each and every one, but important to get exposure none-the-less.

The early part of the year I was still maintaining a large legacy application. We were in the final stages of migrating some very old pieces of the application into new framework architecture (FW/1) along with a new look (based on Bootstrap 3). When you're working on legacy applications, there are rarely opportunities to dive in to new things, so that project was a nice nudge to explore areas previously untouched. Back in April, though, I took on a new position that had me doing nothing but non-stop new product development. Not only was this a great switch, but the particular tasks I was given had me working with technologies with which I had little or no exposure, and often without a team peer who could mentor me, as many of the technologies were new for the company as well.

Historically, I'm a server-side programmer. But, over the last several years, I've spent a great deal of time honing my client-side skills. I'm no master, by any means, but I've consistently improved my front-end work over that time, and 2014 built upon that considerably as well.

One area I could get some mentoring in was AngularJS. This was a big shift for me, and while I am still learning more and more every day, it has been an exciting change up for me. Angular is extremely powerful and flexible, taking some hard things and making them dead simple (to be fair, it makes some simple things hard too ;) ). Angular is one of those items I wished I had spent more time with a year or so back, because in hind-sight it could have saved me hundreds of hours of work. I'm really looking forward to working more with Angular.

From a software craftsmanship standpoint, I also had to dive in to a slew of technologies to assist in my day-to-day development. I now use Vagrant to spin up my local dev environment, which is a godsend. One quick command line entry, and I'm up and running with a fully configured environment. I went from playing around with NodeJS to working with it day in and day out, writing my own plugins (or tweaking existing ones), and to using (and writing/tweaking) both Grunt and Gulp task runners for various automation and build tasks. To take something as "source" and convert it to "app" with a simple command line entry is the shiznit. How many hours did I waste building my own sprites, and compiling LESS in some app? Now it happens at the touch of a few keys.

Then there are the deep areas that some project might take you. I had to dust off year's old AS3 skills to refactor a Flash based mic recorder. There was some extreme study into cross-browser client-side event handling. Iron.io has a terrific product for queuing up remote service containers for running small, process intensive jobs in concurrency without taxing your application's resources. That lead into studies in Ruby, shell scripting, and Debian package deployment (not in any sort of order), as well as spinning up NodeJS http servers with Express.

Did you know that you could write automated testing of browser behavior by using a headless page renderer like PhantomJS? Load a page, perform some actions, and record your findings, it really is incredibly powerful. It also has some hidden 'issues' to contend with as well, but it's well worth looking into, as the unit testing applications are excellent. Then you might change direction and checkout everything there is to know about Aspect Ratio. It's something you should know more about, when thinking about resizing images or video.

(Did I also mention that I went from Windows to Mac, on my desktop, and Windows to Linux, on my dev server? Best moves I ever made!)

Speaking of video, I got the opportunity to go beyond the basics with ffmpeg's video transcoding. For those unfamiliar with the process, you write a command line entry defining what you want. Basically it's one command with 200+ possible flags in thousands of possible combinations, and no clear documentation, by any one source, on how to get exactly what you want (read: a lot of reading and a lot of trial and error).

If that had been all of it, it would have been a lot, but then I really got to have fun, and got to rewrite a Chrome Extension. Now, I had the advantage that we already had an extension, but I was tasked with heavily expanding on it's capabilities, and it's been a blast. Going from something relatively simple to something much more complex is always a challenge, but doing so when you don't fully grasp the tech at hand is even more challenging. Google has created a brilliant triple tier architecture for interfacing the browser 'chrome' with the pages inside them, and developing advanced extensions with injected page applications has a lot of twists and turns along the way. I've learned enough along the way that I'm considering writing a presention on this process for the upcoming conference season.

So, in retrospect, I went from maintaining a large legacy system to doing cutting edge custom development, learning something new each and every day. Awesome! Now, the downside to this sort of process is that you lose valuable productivity time getting through the learning curve. It's difficult to make hard estimates on tasks that no one else has done before, and measuring success is taken in baby steps. But the upside is that you are constantly engaged, constantly motivated, and those skills will eventually translate into better products down the road. Products that won't incur that same learning curve (not to mention the new ideas that can come from exposure to so many different technologies). I can't claim mastery of any of it, yet, but did gain a solid foundation in most of it, and it just makes me hungry for more.

So, if I have one wish for 2015 for you, dear reader, as well as myself, it is only that you continue to learn every day. Maybe not to the levels described above (for I am a bit of a lunatic), but at least take the chance to branch out into one new area of development in the coming year.

The New Armaggedon? Or Web Developer Boon?

OK, so it's a little link baiting, but... ZDNet has just posted an article about Your perilous future on Windows XP. Basically, Microsoft will stop supporting XP on April 8, 2014. This means no more security patches, no more malware checks, and no more holes plugged in Internet Explorers 6 & 7.

Wait...What?

Yes, there are still people using Internet Explorer 6 & 7. Why? There are large organizations (public and private sector both) that invested a lot of time, money and resources to put XP on their desktops to begin with. They then wasted even more money developing browser based applications that only ran in those browsers.

So, here's what's going to happen. MS will EOL XP, and IE 6 & 7 with it. (Definitely 6, and hopefully 7...). The day the last patches are released, new zero day exploits will come out that will never be patched. After the initial pandemonium, organizations who have not upgraded from XP will either A) upgrade right away, or B) start using Firefox or Chrome. Many of them would also start spending mad resources to upgrade their application code to work in browsers other than Internet Explorer.

Where this is going to be felt first, hardest, and likely the slowest to respond, will be within the finance and government sectors. These are the areas that should be the most secure, but are also the tightest on the purse strings. It will probably take some major intrusions, crimes, and data loss before they finally begin to respond appropriately. Even then, it will probably take an Act of Congress, which means it'll be even longer.

The upside is that contracts for web developers should skyrocket, come April or May of 2014. If you are highly skilled in HTML, CSS, and JavaScript, and can work quickly and reliably, you should be in high demand.

Now, will all of this come to pass? I don't know. That's what it looks like in theory. They all though Y2K was the end too, and it wasn't. I do think that this is a much bigger threat, on the grand scale of things. Guess we'll just have to wait and see...

Skinning Bootstrap Tabs

Bootstrap is the number one downloaded project on GitHub today. A small, lightweight framework for layout, Bootstrap is a combination of CSS, HTML format, and JavaScript that allows one to create very dynamic, responsive web sites and applications. This isn't a new concept, being the same sort of thing that jQueryUI and Ext JS are conceptually designed for. Each has their merits, and differences. Those libraries primarily utilize JavaScript for designing and configuring layouts and components, whereas Bootstrap focuses primarily on HTML and CSS (and a small JS file for event handling) for building these things.

One of the things that sets Bootstrap apart is the ease with which one can "skin" the library. Bootstrap uses LESS for building it's CSS files. LESS allows you to define variables and functions, that are then utilized in style declarations. Once compiled, those variables and functions are parsed in the definitions, to create your CSS. By changing a few variables, you can completely change the look and feel of your application.

In this example, I'm going to change the default Bootstrap tab display. When you see the default Bootstrap tabs, they aren't always easily identified as a tabbed interface, until you mouse over a tab. My clients have become used to the contrast provided by the layouts of the other libraries I've mentioned, having seen those interfaces time and again. Here, we'll update the Bootstrap tabs so that they appear more like those used by jQueryUI.

Basic File Structure

I, personally, don't like to change a libraries files. Even though you can do so, I find it better to create an "override" file that will add or change a definition. That way, if I update that library I'm not trying to find and replicate my changes. First, I start off by organizing my assets. I personally like to separate my CSS from my images from my scripts. I also like to create sub-folders under each, to further organize my assets for easy change, management, and retrieval. From Bootstrap's Getting Started page, I downloaded both the basic download, as well as the "source" download. I moved the .less files out of the css folder in the "source" distribution, placing them in /assets/css/bootstrap. I then moved the .js files out of the js folder in the "basic" distribution, placing them in /assets/js/bootstrap. Last, I took the .png files, out of the img folder in either distro, and put them in to the /assets/img/bootstrap folder. The last thing I'm going to do is create a new sub-folder to the css folder, titled core. Within this folder I'm going to create three files: core.less, overrides.less, and variables.less.

Getting started with LESS

We're going to start off by doing something really simple. First I told you that I didn't want to change the core Bootstrap files, but instead create "overrides". Since we changed the basic file structure of the Bootstrap distro, the first thing we'll need to do is correct the pathing to the image sprites. What we're going to do, rather than including the Bootstrap css directly, is create our own "core" file. "Core" needs to include Bootstrap, and then our overrides. We do this by adding the following lines to our core.less.

view plain print about
1@import "../bootstrap/bootstrap.less";
2
3@import "overrides.less";

These statements will include these two files, when core.less is compiled. If you go back and look at bootstrap.less, you will see that it is nothing but import statements as well.We want to create variables that we might need to reuse elsewhere. This is the general purpose of our variables.less file. If we open Bootstrap's variables.less file (/assets/css/bootstrap), we can search through it and find two specific variables: @iconSpritePath, and @iconWhiteSpritePath. Copy and paste these two lines into our variables.less file, then adjust their paths to coincide with our new file locations.

view plain print about
1// Sprite icons path
2@iconSpritePath: "/assets/img/bootstrap/glyphicons-halflings.png";
3@iconWhiteSpritePath: "/assets/img/bootstrap/glyphicons-halflings-white.png";

Finally, we need to use these updated variables in our overrides.less file, to override the proper style declarations. First we add the import statement that includes our variables.less file. Then, we find the declarations, in the sprites.less file (/assets/css/bootstrap), that currently define these paths (you can search for the variable names). Copy and paste these two declarations into our overrides.less file, and then take out all of the definition items except for those that define the background images. Our override only needs to "override" the background image paths, keeping everthing else.

view plain print about
1@import "variables.less";
2
3/* Icon Sprite Path Overrides */
4[class^="icon-"],
5[class*=" icon-"] {
6 background-image: url("@{iconSpritePath}");
7}
8
9/* White icons with optional class, or on hover/focus/active states of certain elements */
10.icon-white,
11.nav-pills >
.active > a > [class^="icon-"],
12.nav-pills > .active > a > [class*=" icon-"],
13.nav-list > .active > a > [class^="icon-"],
14.nav-list > .active > a > [class*=" icon-"],
15.navbar-inverse .nav > .active > a > [class^="icon-"],
16.navbar-inverse .nav > .active > a > [class*=" icon-"],
17.dropdown-menu > li > a:hover > [class^="icon-"],
18.dropdown-menu > li > a:focus > [class^="icon-"],
19.dropdown-menu > li > a:hover > [class*=" icon-"],
20.dropdown-menu > li > a:focus > [class*=" icon-"],
21.dropdown-menu > .active > a > [class^="icon-"],
22.dropdown-menu > .active > a > [class*=" icon-"],
23.dropdown-submenu:hover > a > [class^="icon-"],
24.dropdown-submenu:focus > a > [class^="icon-"],
25.dropdown-submenu:hover > a > [class*=" icon-"],
26.dropdown-submenu:focus > a > [class*=" icon-"] {
27 background-image: url("@{iconWhiteSpritePath}");
28}

Ok, now that you have the mechanics out of the way, all you need to do is compile your file. If you use a dynamic server side language (ColdFusion for instance), then you might be using an asset management framework that will automatically compile LESS files for you at runtime (I like cfStatic). But, you can always get a standalone compiler that will process your files manually. There are many freeware programs available on the web. I Googled "Windows LESS compiler", and came up with WinLess. I was able to plugin the folder name, select my core.less file (you only need to compile the one, as it includes the rest), and hit "compile" to get my core.css file created.

I unselected the Minify option, so that could see the underlying result in an easy to read format. For production code, I suggest having a minified and unminified version, using the unminified for debugging purposes. If you check your new, unminified core.css file, you can go all the way to the bottom and see your two overriding style declarations, verifying that they now reflect the updated sprite paths.

Creating Tabs

OK, we have the basics out of the way. Now lets make some tabs. First, lets write up an index.html that will be prepared for Bootstrap, using our new all-in-one css file.

view plain print about
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <title>Bootstrap Themed Nav</title>
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <meta name="description" content="">
8 <meta name="author" content="">
9 <link href="assets/css/core/core.css" rel="stylesheet">
10 <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
11 <!--[if lt IE 9]>
12 <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
13 <![endif]-->

14 </head>
15 <body>
16 <div class="container">
17
18 </div>
19 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
20 <script src="assets/js/bootstrap/bootstrap.min.js"></script>
21 </body>
22</html>

The next thing we need is the proper markup to create a tabbed interface within Bootstrap.

view plain print about
1<ul id="myTab" class="nav nav-tabs">
2 <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
3 <li><a data-toggle="tab" href="#profile">Profile</a></li>
4 <li><a data-toggle="tab" href="#tab3">Tab3</a></li>
5 <li><a data-toggle="tab" href="#tab4">Tab 4</a></li>
6</ul>
7<div id="myTabContent" class="tab-content">
8 <div id="home" class="tab-pane fade active in">
9 ...
10 </div>
11 <div id="profile" class="tab-pane fade">
12 ...
13 </div>
14 <div id="tab3" class="tab-pane fade">
15 ...
16 </div>
17 <div id="tab4" class="tab-pane fade">
18 ...
19 </div>
20</div>

This produces a basic Bootstrap tabbed interface. No additional JavaScript is required here, the base bootstrap.js will handle all the basic event binding necessary for a fully functional interface. But, as you can see, there's not much in the way of contrast, identifying tab separation, nor is your tabbed interface really separated from the rest of your page. What's needed now is to create that contrast and separation.

Skinning Tabs

We'll look to jQueryUI's tab representation, as a guide for how we wish ours to look. We won't get an exact match, but we can get really close. First, let's start with the new stuff. jQueryUI's tab sets have a border around the entire interface, separating the tabs from the rest of page flow. Bootstrap doesn't have this, so we'll make it. We'll add a new div around the nav-tabs unordered list and tab-conent div, and give it a class: nav-tabs-container. Next, we'll add a style declaration to our overrides.less file.

view plain print about
1/* Add a tab container class, for a border around the entire tabset */
2.nav-tabs-container {
3 padding: 3px;
4 border: 1px solid @grayLight;
5 .border-radius(4px);
6}

Here's what we're doing here. We gave the container a 3 pixel padding all the way around. We gave it a one pixel solid light gray border, using the color variable in Bootstrap's variables.less file. Last, we gave it rounded corners with a four pixel radius (for those browsers that support it) by calling on the .border-radius() LESS function that's defined in Bootstrap's mixins.less file.

Our next step is to see what makes jQueryUI's tab interface different. We make a list of the basic elements.

  • The tab bar (ul with a class of nav-tabs) has:
    • a one pixel gray border with rounded corners
    • padding on the left, top, and right of a few pixels
    • a gradient background of a gray that is darker than the tabs
  • The tabs (list item tags containing anchor tags) have:
    • active tab (li with a class of active) has:
      • a white background
      • a one pixel gray border with rounded corners
      • no bottom border
    • inactive tabs (li's without classes) have gray backgrounds, of a lighter gray than the nav-tabs
    • active and inactive tabs have text that is gray

At this point, our next step is to find the original Bootstrap declarations for tabs. These can be found in the navs.less file (/assets/css/bootstrap). Copy and paste these declarations into your overrides.less file. From here, it's a matter of removing lines that won't change, adjusting lines that meet your requirements, and adding any new code needed to finalize those requirements. I'm not going to go over every line of code, instead giving you the full set, but we'll hit the high parts. First, the code:

view plain print about
1/* Tab Theming Overrides */
2// TABS
3// ----
4
5/* Add a tab container class, for a border around the entire tabset */
6.nav-tabs-container {
7 padding: 3px;
8 border: 1px solid @grayLight;
9 .border-radius(4px);
10}
11
12// Give the tabs something to sit on
13.nav-tabs {
14 border: 1px solid @grayLight;
15 padding: 4px 3px 0 3px;
16 margin-bottom: 5px;
17 .border-radius(4px);
18 #gradient >
.vertical(@grayLighter, @grayLight);
19}
20
21// Actual tabs (as links)
22.nav-tabs > li > a {
23 line-height: 10px;
24 background-color: @grayLighter;
25 border: none;
26 outline: 0;
27 &:hover,
28 &:focus {
29 border-style: solid;
30 border-width: 1px 1px 0;
31 border-color: @grayLight @grayLight transparent;
32 }
33 &:link,
34 &:active,
35 &:visited,
36 &:hover,
37 &:focus {
38 color: @gray;
39 }
40}
41
42.nav-tabs > li:not(.active) > a {
43 &:hover,
44 &:focus {
45 padding: 7px 11px;
46 }
47}
48// Active state, and it's :hover/:focus to override normal :hover/:focus
49.nav-tabs > .active > a,
50.nav-tabs > .active > a:hover,
51.nav-tabs > .active > a:focus {
52 border-style: solid;
53 border-width: 1px 1px 0;
54 border-color: @grayLight @grayLight transparent;
55}

We mentioned earlier the use of variables within LESS. Throughout this block of code you will see multiple references to various colors identified in the base Bootstrap variables.less file. We also previously utilized the .border-radius() method from Bootstrap's mixins.less file. We use this again, within this block of code, as well as other mixin methods, such as the .vertical() method we're using in our gradient definition. It's a good idea to look at the mixins.less and variables.less, to get ideas as to what's available to you. You will also notice nested declarations (such as the link psuedo selectors) that will automatically build out with LESS.

That's it! I hope you found this post helpful and informative. Any feedback, please leave me a comment. Here's what I hope you'll takeaway from this post:

  • Bootstrap is a powerful layout framework
  • Bootstrap is easy to modify/skin by making minor modifications using LESS
  • LESS is a great way to create dynamic, adjustable CSS
  • LESS can be a lot of fun