Tuesday, August 30, 2016

2017, The Year of Catching Up

In 2015 I decided that this year, 2016, would be a year where I became more engaged with the development community by speaking at meetups and conferences. I've met my goals and am even working on my first book.

Although this has been a great year with experiences I'd never regret I'm also left feeling like I'm continually falling behind in my other pursuits. With four months and many obligations remaining in 2016 I've decided that next year, 2017, will be the Year of Catching Up.

In the past five years I've accumulated 20+ technical books that I've hardly touched (if I've even read at all!), close to 100 books of fiction that I've neglected in favor of career time (if alert) or Netflix time (if not), scores of video games that I've bought on a whim that I've never even installed. There are many social activities that I've begged off from in hopes that I'd use the time to add to my book or prepare for a conference.

With every title I purchase I wonder whether I'll ever catch up. Whether I'll be around to indulge whatever curiosity caused me to add an item to my collection. I hate feeling that way. I remember when I was younger (and considerably poorer) that every book I bought felt like a luxury. Every DVD was an indulgence. Now I make compulsive purchases that just sit around neglected.

I don't expect that I'll clear my stack in 2017 but I'd like to end the year feeling like I've made significant progress. I expect I'll also continue adding to that stack, but as long as I'm digging into the stack faster than I'm adding then I'll feel some level of accomplishment.

To that end in 2017 I will only be submitting to conferences on material that I've already presented. That means talks on refactoring Angular applications, explorations of RxJS, my Applesoft BASIC flashback talk, or my talk with Andy McConnell on building developer culture.

What if there is an exciting new framework in my future? What if I yearn to share my knowledge? The truth is there are many passionate people in my local community equally able to cover the same material. For me 2017 will be a year of cooling down a little bit, a year of catching up, and a year of contemplating what I really want to accomplish in the long run.

We in the tech field are lucky. If you miss one train there will be another shortly behind it. The technologies we need to master by 2020 haven't been invented yet. There's little to be lost in taking your time and focussing.

Tuesday, June 2, 2015

How to refactor names without an IDE

At my current client the IDE I'm using doesn't work very well with JavaScript. In fact, it can lock up the whole IDE if you even try certain types of refactoring.

Worse, I am restricted from installing another IDE (thanks, group policies!) However, I do have Cygwin

Here's my little find/replace script that only modifies files where the find :

$(find $DIR -type f -exec grep -q -l -E $GREP_RX {} \; -print0 | xargs -0 sed -b -i $SED_RX)


find $dir -type f
Find files in $DIR that are files (no directories)

-exec grep -q -l -E $GREP_RX {} \;
Execute a grep search for each found file and looking for the $FIND string, but only whole matching words. If match not found, exit quietly (-q), otherwise print the file name (-l).

-print 0 | xargs -0 sed -b -i $SEX_RX
Print the matching file names with no newline between them. Pipe this list of files to xargs and invoke sed to do an in-place find/replace, treating each file as a binary file so that line endings are not changed.

P.S., I had to run dos2unix on the script to get it to run in Cygwin.

Monday, June 1, 2015

AngularJS: How to stop a user from leaving a dirty form?

A colleague asked our dev group how an AngularJS app could be configured prompt a user before leaving an unsaved form.

One suggested approach was to use the run block and watch the $stateChangeStart event. The only problem with this is that the form is really only visible from the view and controller in which its defined.

I suggested writing a directive that could be added to the form element. This is what it looks like:

app.directive('formExitPrompt', function ($rootScope, $modal) {
  return {
    require: 'form',
    restrict: 'A',
    link: function (scope, el, attrs, formCtrl) {
      $rootScope.$on('$stateChangeStart', promptUser);
      function promptUser () {
        if (formCtrl.$dirty) {
          var modalInstance = ${
             * Modal configuration goes here! 

Here's a plunker with formExitPrompt in action.

Wednesday, January 15, 2014

grunt-connect adding an upload handler for testing

Just a snippet for adding an upload handler to a grunt-connect livereload instance for testing file uploads.
      livereload: {
        options: {
          open: true,
          base: [
            '<%= %>'
          middleware: function (connect, options) {
            var middlewares = [

              connect().use(connect.bodyParser({ uploadDir: '.tmp' })),

              // save a file to temp and send a JSON response with basic file stats
              connect().use('/upload', function(req, res, next) {

                // files properties
                // { key: value } of form properties
                res.setHeader('Content-Type', 'application/json');

                // response with basic file stats
                res.end(JSON.stringify({ 'size': req.files.file.size, 'path' : req.files.file.path, 'error' : null }));

            // add the static paths in options.base
            options.base.forEach(function (base) {

            return middlewares;