Mon 14 April 2014

Popup windows are extremely annoying hence most modern browsers block them, agreeably so. That being said one use of popup windows is when doing OAuth. Showing the OAuth authorization dialog in a popup window as not to confuse the user.

If there is a better or different way please comment below.

All the code can be found at angular-popup.

Here is how I solved it using a simple express 4 application and the accompanying AngularJS.

The express code is very simple it just creates two routes. The root/index route renders the view to bootstrap the angular application.

The angular app has one default route / with its controller set to PopupCtrl. In the template popup.html using ng-click we call the function bound on the $scope called showPopup. This is the code for PopupCtrl;

Read the inline comments;

popupApp.controller('PopupCtrl', ['$scope', '$window', '$interval', function PopupCtrl($scope, $window, $interval) {
  'use strict';

  // assign the current $scope to $window so that the popup window can access it
  $window.$scope = $scope;


  $scope.showPopup = function showPopup(){
    // center the popup window
    var left = screen.width/2 - 200
        , top = screen.height/2 - 250
        , popup = $window.open('/popup', '', "top=" + top + ",left=" + left + ",width=400,height=500")
        , interval = 1000;

    // create an ever increasing interval to check a certain global value getting assigned in the popup
    var i = $interval(function(){
      interval += 500;
      try {

        // value is the user_id returned from paypal
        if (popup.value){
          $interval.cancel(i);
          popup.close();
        }
      } catch(e){
        console.error(e);
      }
    }, interval);

  }
}]);

We tell the popup to load up the /popup URL which our express app will render the server side jade template.

extends layout

block content
    <h1>I'm a popup</h1>

    script.
        setTimeout(function(){
            window.opener.$scope.says = 'teapot'; 
            window.value = true;
        }, 2000);

The template above is simple enough. All it does is after two seconds assing to window.value to indicate to the $interval that the popup has done something important. The popup also assigns a value to window.opener.$scope which is the $scope that was assigned in PopupCtrl.

As we have used ng-model in the default routes template a we will see the text teapot appear in the text input.

Hope this makes sense.

Mon 20 January 2014

Install

Im sure you know know how to install packages but here is the command for the sake of completeness

npm install sequelize async

The first migration

First initilize the migrations structure

sequelize --init

Then create the initial migration, but dont edit this file as we will use it create the SequelizeMeta table.

sequelize -c initial

Create another migration

sequelize -c create-tables

Dump the database

Now dump your database without the data. With mysqldump

mysqldump -d --compact --compatible=mysql323 ${dbname}|egrep -v "(^SET|^/\*\!)".

We need to remove the lines beginning or containing SET

Save this dump to the migrations folder and name it initial.sql

Edit the last migration that was created to look like;

var async = require('async')
  , fs = require('fs');

module.exports = {
  up: function(migration, DataTypes, done) {
    var db = migration.migrator.sequelize;

    async.waterfall([
      function(cb){
        fs.readFile(__dirname + '/initial.sql', function(err, data){
          if (err) throw err;
          cb(null, data.toString());
        });
      },

      function(initialSchema, cb){
        // need to split on ';' to get the individual CREATE TABLE sql
        // as db.query can execute on query at a time
        var tables = initialSchema.split(';');

        function createTable(tableSql, doneCreate){
          db.query(tableSql).complete(doneCreate);
        }

        async.each(tables, createTable, cb);
      }
    ], done);
  },

  down: function(migration, DataTypes, done) {
    migration.showAllTables().success(function(tableNames){

      // Dont drop the SequelizeMeta table 
      var tables = tableNames.filter(function(name){
        return name.toLowerCase() !== 'sequelizemeta';
      });

      function dropTable(tableName, cb){
        migration.dropTable(tableName).complete(cb);
      }

      async.each(tables, dropTable, done);
    });
  }
}

Please explain

On the migrations up function we use async.waterfall to orchestrate a the async calls;

  • read in the initial.sql file
  • need to split the initial.sql and retrieve each CREATE TABLE queries as db.query can execute on query at a time
  • using async.each run each of these queries

On the migrations down function we just remove all tables that is not the SequelizeMeta table. For some reason migration.dropAllTables() remove this table and messes up the migrations. Not sure if this is the correct behavior.

Hope this helps

Mon 30 December 2013

Thanks for reading. This will be my first ever review of a fountain pen. I hope it is usefull in helping you decide to either buy this version of the Ambition or not.

The Faber-Castell Ambition Pearwood is not my first fountain pen but it is one of the expensive ones that I've bought recently. In Australia this pen costs around $200-$150 but online on ebay or cultpens you can get it at a cheaper price. It also comes with a Faber-Castell branded converter so you dont need to buy one.

It's been in my daily usage and at the moment inked with Iroshizuku Yama-guri. When I first bought it I had it inked with Diamine Oxblood as I like to colour match the body of the fountain pen with the ink.

The Nib

The Ambition Pearwood has a Stainless steel medium nib and writes smoothly. You can also get nibs in fine, extra-fine, medium or broad. The medium nib is a bit more on the thicker side compared to other nibs but this also provides a really nice shading and line variation.

Here is another album containing a few images of the Ambition. The notebook I used for the writing sample is the Monsiuer Fountain Pen friendly notebook. I find it hard to believe this notebook is marketed as such as with certain nibs & ink the feathering and ghosting is really noticeable.

Mon 07 October 2013

Introduction

Writing tests with Mocha is really fun and satisfying. Combined with should.js for expectations/assertions and mocking/stubbing with sinon.js I think it becomes very powerful test environment.

In this article I will show you how to get started with test mocking/stubbing by showing an example which stubs out the get method on mikeal/request. I also assume you are somewhat familiar with Node.js and have it installed.

Before we start create a directory and install the dependencies needed.

mkdir test_article; cd test_article
npm install mocha should sinon request async

GET some data

Here is a function that will get any users public GitHub profile from the GitHub API. We will use the awesome async module to help with the asyncronousness.

var request = require('request')
  , async   = require('async');

function getProfile(username, cb){
  async.waterfall([
    function(callback){
      request.get('https://api.github.com/users/' + username, function(err, response, body){
        if (err) return callback(err);
        callback(null, body);
      });
    }
  ], cb)
}

module.exports = getProfile;

getProfile('bulkan', function(result){
  console.log(result);
});

We require the two packages we need, then define a function which accepts the GitHub username & a callback function.

async.waterfall takes an array of functions as its argument then calls them one by one passing the values from that is passed to the callback to the next function. For more details read the official description here.

The first function in async.waterfall function list does a request to GitHub API passing the body to the next function. We dont have have another function so async.waterfall will call the callback we passed into getProfile with err and result as its argument. Its a good idea to read the official description of the waterfall function.

Last, we export our function as the module so we can use it later.

Tests taste better Mocha

To test the above code we can write a Mocha test assuming the above code is in a file named gh.js.

var getProfile = require('./gh');

describe('User Profile', function(){
  it('can get user profile', function(done){
    getProfile('bulkan', function(err, result){
      if(err) return done(err);

      // simple should.js assertion
      result.should.not.be.empty;
      done();
    });
  });
});

We can run the above test via the following line assuming the Mocha test is in a file named gh_test.js

./node_modules/.bin/mocha --require should --ui bdd gh_test.js

The problem with the this test is that each time we run it will do a HTTP GET to GitHub API which will slow the test. The more tests we add that do actual HTTP requests to will slow the tests even more. What we can do is we can mock out the request.

We can change the test code.

var request    = require('request')
  , sinon      = require('sinon')
  , getProfile = require('./gh');

describe('User Profile', function(){
  before(function(done){
    sinon
      .stub(request, 'get')
      .yields(null, null, JSON.stringify({login: "bulkan"}));
    done();
  });

  after(function(done){
    request.get.restore();
    done();
  });

  it('can get user profile', function(done){
    getProfile('bulkan', function(err, result){
      if(err) return done(err);
      request.get.called.should.be.equal(true);
      result.should.not.be.empty;
      done();
    });
  });
});

We add a before call that stubs out request.get.

The yields allows us to simulate the call to the callback that is passed to request.get. In this case we return null for err, null for the response and JSON string of a simple object.

The after call restores the default request.get method.

Our test case tests that request.get was called.

In Node.js require(..) loads modules once into a cache. As our test case runs first it will loads the request module first. We use the reference to the module to be able to stub methods on it. Later on when we load getProfile module it will do a require('request') call which will retrieve the module from the cache with the get method stubbed out.

I hope this example helps you in your testing.

Sun 18 August 2013

Twitter Bootstrap comes with a nice carousel for cycling through images. If you look at the html for the carousel you will notice that the images are loaded on page load. This is fine as long as it contains a few images but what happens if we have 11 jpg''s 500kb each ? One solution I have is to put the carousel in a modal and using jQuery to lazy load the carousel images.

In the following html we have a modal which contains a carousel which loads three images, when the page loads.


Full screen demo

We can add a bit of JavaScript and change the HTML markup to lazy load the carousel images when the modal is launched.


Full screen demo

In the HTML all that has changed is that a div was added that contains an image element that loads an animated GIF of an ajax-loader just above the carousel html and the src attributes on img elements were changed to data-src. This way the browser wont load the images on page load.

The JavaScript does a few things. First, it binds/listens to the show event on all divs with the modal class, finds the carousel within it and hidse it. Then for all image elements within the carousel div we look to see if it has a data-src attribute, if it does we create a Deferred instance.

Deferreds are a bit advanced topic but here they are used to make sure that the carousel is shown after all images are loaded, hence why the deferred instance is added to an array.

After this, the JavaScript binds/listens to the load event on the img element. In this case it uses the resolved function on the deferred instance p as the callback function. This means that once the image is loaded by the browser, the deferred is marked as resolved/done.

To load the image, the src attribute is set to the value of data-src and data-src is set to an empty value so that this process isnt repeated again if the modal is closed and re-opened later.

The last bit of code is to wait until all of our deferred instances are done. This is done by the $.when.apply call. apply is used here as an array needs to be passed as the argument to $.when. In the callback function, we hide the ajax-loader and fadeIn the carousel.

Thats it. Hope this helps. Read the following deferred.promise docs for more information on the API.