Tag Archives: Github

“selfhelp” – a self-upgrading Node.js application

I have a strange little project I’ve been working on over the last few weeks. It’s an example app I wrote using Node.js which is capable of self-upgrading itself to new versions. Thus you could use it as the basis of a cross-platform application with a browser based UI like SABnzbd+, the Plex Media Server, Couch Potato, and Sick Beard. All of which work on different operating systems (Mac OS X, Windows, and Linux) and which offer the same UI across all of them. So, this isn’t really intended for use on servers as much as it is intended for use on desktop machines so you can build apps using Node.js and whatever front-end technologies you happen to fancy (my particular flavor is AngularJS, though there is none in the example application).

I got it to where it works well on Mac OS X so I thought I’d write about it and maybe someone else would find it interesting enough to see if they could add a Windows batch file to it, maybe test it on Linux, or see if it suits a project they have been wanting to build. It’s called “selfhelp” and it’s available over on Github:

https://github.com/JohnMunsch/selfhelp

About these ads

A post-mortem on my first AngularJS project

Before I started my current employer down the road to AngularJS I decided to do a small (but complete) project using it just to see what it felt like. I had a colleague from my previous job who needed a website at precisely this point in time when I needed a project to do. It was small, self-contained, downloaded all of the data it needed at the time it initialized (so I wouldn’t have to start using AJAX with AngularJS and come up with a service layer when he didn’t already have one in place). In other words, it was almost like it had been designed for what I needed to learn.

It was to quote prices for custom t-shirts and it had some fairly complicated calculations it needed to do based upon shirt cost, shirt color, number of colors printed front and back, quantity of shirts, and surcharges for large shirts. Here’s the finished UI:

The interface as the user first sees it.

The interface as the user first sees it.

His original design called for buttons the user clicked to get a quote generated and to clear out a quote when the user wanted to get a new one. I wanted to see if I could use AngularJS to generate two versions of the same website using the same controller; one would have the buttons of the original design, the other would simply update all of the prices in real-time as the user selected colors, sizes, etc.

When I was done I had a couple of functions and flags the “quote button” version of the site used that the real-time update version of the page didn’t need but otherwise the same controller worked quite happily with two different versions of the UI (the original and my design). Needless to say, the real-time quote updates version of the site was much less clunky to use and is the only version of the source code I’ve made available on Github. My colleague (who also provided me with the web design) preferred it as well.

Prices and the quantity discounts update in real-time as the user changes colors, printing colors front and back, quantities, etc.

Prices and the quantity discounts update in real-time as the user changes colors, printing colors front and back, quantities, etc.

If you want to download the source code to an AngularJS app that isn’t another To-Do List or something to pull down Twitter tweets then feel free to check out this project here: https://github.com/JohnMunsch/airquotes

Now for the retrospective part of the blog. Surprisingly, there aren’t a huge number of things about the code that stand out as glaring mistakes almost five months later, despite spending hundreds of hours working with AngularJS since. Given how much I’ve learned in other parts of the framework, I think that speaks well to how much I could learn in a short time to get the project done and done fairly well. But that’s not to say that it’s perfect. Three changes I could pinpoint off the top of my head were:

  1. All of the shirt data and pricing data were just dumped as JSON into a file and used as global variables by the controller I built. Now I know that I could put them into an AngularJS service and inject them into the controller. That would be cleaner, but you won’t see it that way in the current code.
  2. I need to do another view to demonstrate how the user could flip over to a catalog of shirts in order to pick a different type of short-sleeved shirt, long-sleeved shirt, crop-top, etc. and then that would change the route to pick a different shirt. The routing for a selected shirt is in place, but the picking page isn’t. The fellow I was working with said he could provide that, but I think my example would be better if I went ahead and put one in.
  3. I do a lot of calculations and sub-calculations to bfigure the price and to figure the price at different price-break levels for the display. That code should really be unit tested. I actually did something about this recently, read on for details.

So I recently returned to the project with an eye to fixing a few things and the largest change I made was to use it to figure out how to do both unit tests and figure out how to know how much of my code was covered by the tests. The coverage report was, let’s just say highly motivating, when there were only a few tests in place so I spent a few hours writing a simple suite of tests to get me to 100% coverage.

So, if you’re interested, I can show you what was involved in getting unit tests and a coverage report added to an existing AngularJS project. First, if you haven’t already installed Node.js onto your machine, you should do so from the big green install button over here. Then run:

sudo npm install -g karma

The sudo won’t be necessary on Windows systems but on Mac OS X and Linux you’ll want it because we’re trying to install Karma, our unit test runner, globally so you can use it from any of your projects. Once you’ve done this once, you shouldn’t have to do it for each project.

npm install karma-coverage --save-dev

This gives us a Karma component which can check the percentage of our code which our tests reach. It’s uses the Istanbul project and it will show you at the line level exactly which lines are getting hit by your unit tests. The –save-dev adds it to the dev-dependencies part of your package.json file so npm knows it’s only a development dependency and not a runtime dependency.

bower install angular-mocks --save-dev

They’re different tools but both bower and npm recognize the –save-dev flag and use it the same way. In this case angular-mocks becomes a development dependency in your bower.json file. It will help us when we’re building our unit tests for AngularJS code.

karma init

The installation parts are done, now it’s time to add unit testing to a particular project. This will get Karma to ask you a series of questions and generate a configuration file. With a few tweaks to that file you’ll be ready to run unit tests and get code coverage information for your tests.

Karma init options.

Karma init options.

This screenshot shows me setting up a configuration file the same way I set up mine for this project. I picked Jasmine for writing the tests (other choices are Mocha and QUnit), I don’t use RequireJS, and you’ll notice it gave me an error message for no matching JavaScript files. That happened in this case because I was doing this test run in an empty directory, you wouldn’t see that normally.

If you actually open up the config file Karma generated at this point you’ll find it pretty easy to read. It has nice comments so you can tell where it wants you to put library files, the files you want to test, the browsers in which you want to test, etc.

You’re going to make two edits to the file at this point to get some things we want in there. This should be a one-time thing again.

There’s a files array part way down the page. Make sure you add the path to the angular-mocks.js in there.

And you’ll need to add a preprocessors section like you see below so the code coverage tool knows exactly which source it’s checking for test coverage and add ‘coverage’ to the list of reporters to turn on the coverage checker.

preprocessors: { 'app/scripts/**/*.js': 'coverage' },
reporters: ['progress', 'coverage'],

Note: If you use the latest angular-generator together with the latest Yeoman it seems like the generator now creates a Karma config file (karma.conf.js) and installs the angular-mocks so you can skip those two steps for your new project if you’re using Yeoman to generate it.

Finally there’s the writing of the tests themselves and the checking your coverage to see where else you need to craft tests.

To kick off this process, run “karma start” at the command line and Karma should now kick into gear, start up the browser or browsers you wanted your tests to run in, and start watching all of your source files for changes. This is super handy because you can save a change to a source file or a test file, Karma will notice that and rerun your tests so you get immediate feedback on whether everything is passing or not.

When I had only one test completed, this is what the coverage report looked like. Look for it in a subdirectory under the coverage directory after you've run some tests through Karma.

When I had only one test completed, this is what the coverage report looked like. Look for it in a subdirectory under the coverage directory after you’ve run some tests through Karma.

I’m not going to give instructions on writing Jasmine tests or even the specifics of writing them for AngularJS. There’s good examples for Jasmine on their website and I have to confess that most of the tests I’ve written so far focused on testing JavaScript rather than AngularJS specific items like services and directives. So I still have some learning yet to do. But for basic tests, if you look at the test/spec/airquoteSpec.js you can see 20+ tests I wrote for my code to achieve complete coverage of my main.js file.

With tests written for all the code in main.js there's lots of green and 100% coverage indicators at the top of the page.

With tests written for all the code in main.js there’s lots of green and 100% coverage indicators at the top of the page.

Good luck, I hope some of my code is helpful to you in your own projects, and feel free to ask questions about any of it.

AngularJS Services and Promises

Promises, Deferred, Futures

Call it what you will, promises are another mechanism for dealing with the asynchronous nature of some things you’ll do within JavaScript. For example, calling remote services, timers, animations completing, etc. In each case you could just have a callback, but what if you wanted to attach several callbacks to the completion or failure of a single asynchronous job? That’s difficult with callbacks, but promises make it easy.

Promises make it easy to tie together several asynchronous actions and treat them as one. This makes it easy to react only when all have completed or one of them had a problem. This is a much better solution than the nesting of callbacks you often see done in JavaScript code. Nested callbacks are often written in a way that forces requests to be made serially when they could be executed in parallel and perform better as a result.

Promises can simplify code in another way because a promise which has already resolved and one which has yet to resolve are treated are both used in exactly the same way.

Promises in AngularJS

AngularJS offers promises via a service called $q. It is modeled after a promise library called (not surprisingly) Q. You’ll see promises returned from several of AngularJS’s services, including $http (for service calls), $timeout, and $route (though I admit I’m not sure how it’s being used in the latter case).

AngularJS even has support for promises being assigned directly to $scope variables. So you can take the promise you get back from a remote service call and assign it directly to a variable knowing that when the service call finally returns, the variable will be updated and any binding attached to the variable will redisplay. That’s significantly easier than other frameworks I’ve used in the past.

Service Calls

I thought I’d give three examples of calling a service with $http and show how the promise it returns may be used directly, and examples of how caching and aggregation can be made easier thanks to promises.

For these examples I’m just calling the OpenKeyval service to store and retrieve some JSON data. It’s simple, it’s free, and I know I can count on any code I give you being able to access it without any special API key.

Source code for all of the following and more is here: https://github.com/JohnMunsch/AngularJSExamples, in particular look at the app/scripts/controllers/promises.js and app/view/promises.html to see the code specific to these examples.

Click here to see all of the following as running examples on Github

    • Example 1: Store and retrieve some values. Promises returned from $http are assigned directly to $scope variables and AngularJS dereferences them automatically.
    • Example 2: Make multiple calls to different services aggregating the results of all the calls and merging the results into a single returned value.
    • Example 3: A common pattern for services is to be able to satisfy requests from a local cache when appropriate. Promises can make that an easy upgrade for an existing service.

A Shortcoming

$q is not as full featured as Q is. That’s not surprising because AngularJS is only trying to provide as much functionality as it needs without requiring you to load up another library. AngularJS does the same kind of thing when it comes to jQuery. It has a minimal subset of functionality built in (called jQLite) that it uses if jQuery wasn’t loaded prior to loading AngularJS.

However, this is where things suddenly differ. If you do load jQuery prior to loading AngularJS then it won’t use it’s own built in version, but will instead use the more full-featured jQuery implementation. However, as far as I know, loading up the Q library or jQuery before you load up AngularJS doesn’t cause AngularJS to use Q promises or jQuery Deferred objects instead of its own subset implementation. That seems to me like an oversight or shortcoming to their implementation.

Nevertheless, I hope I’ve shown with the examples above that you can still do some really interesting things even with the limited set of functionality $q provides.

Follow Up

After a few weeks I realized that something I didn’t really cover is how assigning a promise to a variable in $scope can hinder access of that same variable in the controller. For example, if you do something like this:

$scope.someValue = $http.get(someURL);

You’ve assigned a promise to the variable and from the standpoint of code in your view, nothing really changed. You can still do {{someValue.someSubValue}} and act blissfully unaware that someValue is a promise rather than a JavaScript object. But, try the same thing from the controller code and you’ll have all kinds of problems. $scope.someValue.someSubValue isn’t anything you can access in the controller because $scope.someValue is actually a promise and will always stay a promise, even once it’s resolved. The only thing that changes once it’s resolved is that any .then() function you call on it will immediately call the closure you pass into it with the value the promise now caches. Thus you will forever more have to use it within the controller like so:

$scope.someValue.then(function (value) { $log.info(value.someSubValue); });

If you have some values you’re getting via AJAX calls or via some other mechanism that returns a promise and you need to access them as much or more from a controller as from view code then only assign the resolved value into the scope and not the promise. For example:

$http.get(someURL).then(function (value) { $scope.someValue = value; });

In that case you’re waiting until the promise resolves and only assigning the final returned value into the scope. Now both the view code and the controller can directly access $scope.someValue.someSubValue freely.

Reference

Changeable vector graphics with SVG and AngularJS

I’ve long been a fan of using SVG (Scalable Vector Graphics) to do images that I can change easily on the fly. When I say “long been a fan” I mean that when I first started doing it I hand wrote some SVG as XML to show a donation bar we needed for GameDev.net and I had a program that would change the amount thus far donated on the bar and run it through an early version of the Java Batik library to spit out a JPEG file we could put on the website. It was crude, but it sure beat making a new graphic two or three times a day.

Years later things have gotten a lot easier. Modern browsers have advanced to the point where you can include an SVG image in the page as easily as referring to them in an img tag like so, <img src=”something.svg”/>, or just dumping some SVG code straight into the middle of the HTML for your page like this <svg>…lots of vector graphics…</svg>. And editing? Why would you edit by hand anymore when Adobe Illustrator can generate SVG files of your drawings for you, or if you have no budget for such nice tools, Inkscape does a pretty good job and costs nothing.

So it occurred to me the other day that it would be interesting to see if I could use AngularJS and its ability to rewrite HTML on the fly and combine that with SVG in the browser to rewrite SVG on the fly. The answer is, it not only works, it’s downright easy to do so. I’ve provided a couple of different examples to show just how easy it is to so.

Example 1: Have a SVG graphic where I change text within the graphic automatically because it’s tied to a value in an AngularJS model.

Getting an image to start with was pretty easy. I went to The Noun Project and grabbed an icon of the sun I liked. It was provided by an unknown author in this case. The icon came in SVG format so all I did with it in Inkscape was add a little color and some text that showed the temperature. Then I saved that as a “Plain SVG” file rather than an “Inkscape SVG” file. It might have worked as well with the latter but I didn’t want any surprises.

Inkscape editing SVG icon

I then popped over to an HTML file I had generated and imported it with an image link like this:

<img alt="" src="images/sunshine_plus_temp.svg" />

I then hand edited the SVG file and found where the text for the temperature and replaced it with an AngularJS model variable reference. So:

<tspan sodipodi:role="line" id="tspan4542" x="97.124313" y="52.063747">87°</tspan>

became:

<tspan sodipodi:role="line" id="tspan4542" x="97.124313" y="52.063747">{{temp}}°</tspan>

The <img> way of loading the SVG had to change because AngularJS wasn’t going to replace a variable inside an image for me. So I simply pasted the contents of the sunshine_plus_temp.svg right into the middle of a page already setup for AngularJS and put the temp variable into my $scope. It worked like a charm. With an input field tied to the model variable, as I typed, the SVG graphic was automatically updated with the new value.

My final touch was to externalize the SVG file. Nobody wants to edit an HTML file with half a dozen or more embedded lumps of SVG in there. It could quickly turn into an unreadable mess. And, as I already observed, <img> won’t work either. Ah, but AngularJS jumps to the fore again because it has it’s ng-include directive. All I had to do was this:

<span ng-include="'images/sunshine_plus_temp.svg'"></span>

and AngularJS was including the image where I needed it and binding the variable to the model for real-time update. Here’s the final version of the code I came up with for my first example, note the second set of quotes inside the ng-include to tell it not to interpret the string inside there, it’s just a string to use directly:

  <div>
    <p>Example 1: Text updated on the fly in an SVG graphic via AngularJS.</p>
    <span ng-include="'images/sunshine_plus_temp.svg'"></span>
  </div>
  <label>Temperature</label> <input type="text" ng-model="temp"/>

It’s worth noting that Inkscape is still perfectly capable of editing the SVG file even after the change I made and I guess I could have just made the change within Inkscape in the first place and never bothered opening up the file to manually change it with a text editor.

Inkscape editing modified SVG icon

Example 2: Have an SVG graphic that incorporates an image (just because it’s vector doesn’t mean it has to be all vector, SVG is great with images too) and use AngularJS to swap out the images on the fly.

We don’t really need a second example here, the first one showed pretty much everything but I wanted to show how easily images incorporate into SVG and help you achieve results that would be much much harder to do with other techniques. In this example I took a slides icon by Diego Naive, from The Noun Project, overlaid an image on top of it, and then overlaid a glossy reflection on top of half the slide, just to show that the image is fully incorporated by the graphic and can easily be rotated, have graphics on top of it, underneath it, etc. Stuff that would require a lot of work to do with many other techniques.

Again, I tested it out and edited the final SVG file to add a variable reference, in this case to {{slide_image}} instead of the specific file reference that I had added with Inkscape. This time, I will say that it does not edit nearly as well in Inkscape after the edit because it doesn’t know where to find an image named “{{slide_image}}”. Within the Inkscape editor you just see an error box where the image should be. Not perfect, but not debilitating either.

Here’s a page with links to both examples and to the Github repository with all the code for both: http://johnmunsch.github.io/AngularJSExamples/