MEAN Stack Part Five – Introduction to the Angular Model

Angular is described by Goolge as MVW (Model View Whatever), so I guess there are purists who debate whether this is true MVC (C=Controller) but this is only a fairly small app, for a but of fun and to demonstrate the awesome power of the MEAN Stack.

So far we have rather overloading the Controller class and now a whole bunch of this logic has been moved to the Model:

air-de-david:portfolio-2014 davidpitts$ grep -i activityEntryModel www/public/controllers/activityAnalysisController.js 
    $scope.activityEntry = activityEntryModel;
    $scope.addTo = activityEntryModel.addTo;

So looking at this new activityEntryModel function/class:

air-de-david:portfolio-2014 davidpitts$ cat www/public/models/activityEntryModel.js 
var activityEntryModel = (function () {
    var i = 0,
        singularOrPlural = function (items, text) {
            return (items > 1) ? text + "s" : text;
        },
        getHours,
        getMinutes;

    getHours = function () {
        var toReturn = [];

        for (i = 0; i <= 18; i = i + 1) {
            toReturn.push({
                value: i,
                text: i + singularOrPlural(i, " hour")
            });
        }

        return toReturn;
    }

    getMinutes = function () {
        var toReturn = [];

        for (i = 0; i <= 50; i = i + 10) {
            toReturn.push({
                value: i,
                text: i + singularOrPlural(i, " minute")
            });
        }

        return toReturn;
    }

    this.defaults = {
        hours: getHours(),
        minutes: getMinutes(),
        metRates: [
            {
                value: 0.9,
                text: "Sleeping"
            },
            {
                value: 1,
                text: "Meditating or lounging around"
            },
    ...
            {
                value: 12.5,
                text: "Exercising very hard at the gym"
            }
        ]
    };

    this.hours = this.defaults.hours[0];
    this.minutes = this.defaults.minutes[0];
    this.metRate = this.defaults.metRates[0];

    // todo: try to refactor this function as add(member).to(collection)
    this.addTo = function (collection, toAdd) {
        collection.push({
            "metRate": toAdd.metRate,
            "hours": toAdd.hours,
            "minutes": toAdd.minutes
        });

        return collection;
    };

    return this;
}());

So the heart of our model is collection of exercise rate and times captured by the addTo funtion.
Note we have loaded are example data into defaults, rather than having this hardcoded in the frontend html (i.e. views/activityAnalysis.html)

vagrant@m202vm:/vagrant/portfolio-2014$ grep -B10 -A10 activityEntry.defaults  www/public/views/activityAnalysis.html 
...
    <div class="well">
        <fieldset class="form-group">
            <legend>Activity</legend>
            <p>In a typical day, fill in your activity levels and types</p>
            <select ng-model="activityEntry.metRate" 
                class="form-control" 
                ng-options="metRate.text for metRate in activityEntry.defaults.metRates">
            </select>
        </fieldset>

        <fieldset class="form-group form-inline">
            <legend>Duration</legend>
            <select ng-model="activityEntry.hours" 
                class="form-control col-xs-2 col-sm-2 col-lg-2" 
                ng-options="hours.text for hours in activityEntry.defaults.hours">
            </select>

            <select ng-model="activityEntry.minutes" 
                class="form-control col-xs-2 col-sm-2 col-lg-2" 
                ng-options="minutes.text for minutes in activityEntry.defaults.minutes">
            </select>
        </fieldset>

...

There are clearly some further enhancements requirements needed here i.e. to calculate calories and record the weight (kg/lb).

Mean Stack Part Four – tweaking the layout with some new Angular directives/classes

A smallish update today to (see http://ebabel.eu/ and https://github.com/ebabel-eu/portfolio-2014/) today… enhancing the layout via AngularJS.

Moving forward with the angular app, there were quite alot of useful help details crowding out the real functionality. This background info and the example calculation is now hiding behind a button/overlay:

	<div overlay="myOverlay">
	    <h4 class="overlay-title">How to calculate your calories burning</h4>    
	    <p>
	        Calculate calories burnt by the formula:<br>
	        calories burnt = MET * Weight in Kg * Time (in Hours)
	    </p>
	    <p>
	        For example, if you exercise for 30 mins in the gym with a MET of about 8.0:<br>
	        8.0*76*(30/60) = 304 calories
	    </p>

	    <p>
	        However during an 8 hours period of sleeping:
	        0.9*76*8 =  547 calories
	    </p>

	    <p toggle="off" bubble target="myOverlay">
	        <span class="btn btn-primary">Got it</span>
	    </p>  
	</div>

	<p toggle="on" bubble target="myOverlay" class="info-button pull-right">
	    <span class="btn btn-primary"><i class="fa fa-info-circle"></i> Help</span>
	</p>  

i.e. here we are using the Angular overlay directive which can be toggled off and on via a button.

Next we have made some layout changes, including using class=”well” (which Angular uses from the Twitter bootstrap)

	<form role="form" ng-controller='activityAnalysisCtrl'>

	    <h2>Estimate the rate at which you burn calories</h2>
	    <p>Enter enough activities to describe your <em>typical day</em>.</p>
	    <p>This will help you work out <em>how many calories</em> you should be <em>eating</em> based on how many you are <em>burning</em>.</p>

	    <div class="well">
	        <fieldset class="form-inline">
	            <legend>Enter your weight ({{dailyExercise.weight}})</legend>
	            <input type="number" min="30" ng-model="dailyExercise.weight" 
	                class="form-control col-xs-2 col-sm-2 col-lg-2" placeholder="Weight">

	            <label>
	                <input type="radio" value="1" ng-model="dailyExercise.weightType"
	                    class="radio-inline"> Kg
	            </label>
	            <label>
	                <input type="radio" value="0.454" ng-model="dailyExercise.weightType"
	                    class="radio-inline"> Lb
	            </label>
	        </fieldset>
	    </div>

	    <table ng-show="dailyExercise.activityEntries.length > 0" class="table">
	        <thead>
	            <tr>
	                <th>Activity Rate (MET)</th>
	                <th>Duration (hh:mm)</th>
	            </tr>
	        </thead>
	        <tbody>
	            <tr ng-repeat="entry in dailyExercise.activityEntries" ng-class="{even: $even, odd: $odd}">
	                <td>{{entry.metRate}}</td>
	                <td>{{entry.hours}}:{{entry.minutes}}</td>
	            </tr>
	        </tbody>
	        <tfoot>
	            <tr>
	                <th>MET for a day</th>
	                <th>Hours to fill in</th>
	            </tr>
	            <tr>
	                <td>..calculation..</td>
	                <td>24 - ..total..</td>
	            </tr>
	        </tfoot>
	    </table>

	    <div class="well">
	        <fieldset class="form-group">
	            <legend>Activity</legend>
	            <p>In a typical day, fill in your activity levels and types</p>
	            <select ng-model="activityEntry.metRate" class="form-control">
	                <option value="0.9">0.9 ... Asleep</option>
	                <option value="1.0">1.0 ... Meditation, Weekend Lyin :)  </option>
	                <option value="1.75">1.75 ... Read a book/film, sitting at computer</option>
	                <option value="2.5">2.5 ... Housework, gentle walk</option>
	                <option value="3.0">3.0 Yoga</option>
	                <option value="3.5">3.5 Gentle cycling</option>
	                <option value="4.0">4.0 Brisk walking</option>
	                <option value="5.5">5.5 Cycling fast and sex ;)</option>
	                <option value="6.0">6.0 Wresling</option>
	                <option value="7.5">7.5 Light cardio training: light cross trainer, jogging, cycling hard ...</option>
	                <option value="10.0">10.0 Hard cardio training: hard cross trainer, running ...</option>
	                <option value="12.5">12.5 Very hard cardio training: very hard cross trainer, running ...</option>
	            </select>
	        </fieldset>

	        <fieldset class="form-group form-inline">
	            <legend>Duration</legend>
	            <select ng-model="activityEntry.hours" 
	                class="form-control col-xs-2 col-sm-2 col-lg-2">
	                <option value="0">0 hours</option>
	                <option value="1">1 hours</option>
	                <option value="2">2 hours</option>
	                <option value="3">3 hours</option>
	                <option value="4">4 hours</option>
	                <option value="5">5 hours</option>
	                <option value="6">6 hours</option>
	                <option value="7">7 hours</option>
	                <option value="8">8 hours</option>
	                <option value="9">9 hours</option>
	                <option value="10">10 hours</option>
	                <option value="11">11 hours</option>
	                <option value="12">12 hours</option>
	                <option value="13">13 hours</option>
	                <option value="14">14 hours</option>
	                <option value="15">15 hours</option>
	                <option value="16">16 hours</option>
	                <option value="17">17 hours</option>
	                <option value="18">18 hours</option>
	            </select>
	            <select ng-model="activityEntry.minutes" 
	                class="form-control col-xs-2 col-sm-2 col-lg-2">
	                <option value="0">0 minutes</option>
	                <option value="10">10 minutes</option>
	                <option value="20">20 minutes</option>
	                <option value="30">30 minutes</option>
	                <option value="40">40 minutes</option>
	                <option value="50">50 minutes</option>
	            </select>
	        </fieldset>

	        <button ng-click="addEntry(activityEntry)" 
	            class="btn btn-primary btn-lg"
	            rel="tooltip" 
	            title="Add activities until you total 24 hours">
	            <i class="fa fa-plus-circle"></i>
	            Add an activity
	        </button>
	    </div>
	</form>

Above we are also using a table layout for “entry in dailyExercise.activityEntries”. There is also highlighting of odd and even rows:

this is using $even and $odd from Angular to determine oddness or evenness:

	            <tr ng-repeat="entry in dailyExercise.activityEntries" ng-class="{even: $even, odd: $odd}">

MEAN Stack Part Three – a quick look at the ngShow (conditional) and ngRepeat (loop) Angular directives

Updating http://ebabel.eu/ and https://github.com/ebabel-eu/portfolio-2014/ … to work with some Angular directives.

The following angular code snippet does two things: firstly it checks that we have at least one or more existing entries and secondly it loops over the results displaying the results in a table:

<ol ng-show="dailyExercise.activityEntries.length > 0">
    <div ng-repeat="entry in dailyExercise.activityEntries">
        <li>
            Activity Rate (MET) was {{entry.metRate}} for a duration of {{entry.hours}}:{{entry.minutes}}.
        </li>
    </div>
</ol>

Break this down the usage of ng-show directive:

ngShow
- directive in module ng
The ngShow directive shows or hides the given HTML element based on the expression provided to the ngShow attribute.

https://docs.angularjs.org/api/ng/directive/ngShow

our usage pretty straight forward, basically this is an Angular version of the traditional Conditional program flow logic (http://en.wikipedia.org/wiki/Comparison_of_programming_languages_(basic_instructions)#Conditional_statements)

While the use ng-repeat directive is also pretty straight forward:

ngRepeat
- directive in module ng
The ngRepeat directive instantiates a template once per item from a collection. Each template instance gets its own scope, where the given loop variable is set to the current collection item, and $index is set to the item index or key.

https://docs.angularjs.org/api/ng/directive/ngRepeat

Similar this Angular’s LOOP program control (http://en.wikipedia.org/wiki/Comparison_of_programming_languages_(basic_instructions)#Loop_statements).

It is worth noting that we are looping over “entry in dailyExercise.activityEntries” and the syntax to access the entry objects is via ‘double curly brackets’:

Activity Rate (MET) was {{entry.metRate}} for a duration of {{entry.hours}}:{{entry.minutes}}.

MEAN Stack Part Two – Getting Going with AngularJS!

Starting to touch angular today (see http://ebabel.eu/ and https://github.com/ebabel-eu/portfolio-2014/).

In my previous post I was looking at the initial project setup and config i.e. via the frontend and backend package managers (bower and npm respectively). We also reviewed RequireJS which was used to load all the frontend javascript libraries into the browser. Finally we also briefly went over ExpressJS which is the container app for our Angular code.

Most of our application logic is going to be handled via AngularJS, and in this post I want to cover the basic plumbing for the MVC model behind this AngularJS app.

Starting with index.html, within the head tags we are using the mobile friendly angular stylesheet:

vagrant@m202vm:/vagrant/portfolio-2014$ grep -i mobile www/public/index.html 
        <link rel="stylesheet" href="libraries/mobile-angular-ui/dist/css/mobile-angular-ui-base.min.css">
        <link rel="stylesheet" href="libraries/mobile-angular-ui/dist/css/mobile-angular-ui-desktop.min.css">

and within the body tags define the two main parts of this Angular application (1) the sidebar/menus and (2) the main application body/content:

vagrant@m202vm:/vagrant/portfolio-2014$ grep -A1000 body www/public/index.html 
    <body>
        <div class="sidebar sidebar-left" toggleable parent-active-class="sidebar-left-in" id="mainSidebar">
            <div class="scrollable">
                <div class="scrollable-content">
                    <div class="list-group" toggle="off" bubble target="mainSidebar">
                        <a class="list-group-item" href="#/">Home <i class="fa fa-chevron-right pull-right"></i></a>
                        <a class="list-group-item" href="#/angular-chart">Angular Chart <i class="fa fa-chevron-right pull-right"></i></a>
                        <a class="list-group-item" href="#/activity-analysis">Activity Analysis <i class="fa fa-chevron-right pull-right"></i></a>
                    </div>
                </div>
            </div>
        </div>
        <div class="app">
            <div class="navbar navbar-app navbar-absolute-top">
                <div class="navbar-brand navbar-brand-center" yield-to="title">
                    <span>Nadjib Amar</span>
                </div>
                <div class="btn-group pull-left">
                    <div ng-click="toggle('mainSidebar')" class="btn btn-navbar sidebar-toggle">
                        <i class="fa fa-bars"></i> Menu
                    </div>
                </div>
            </div>
            <div class="app-body scrollable">
                <ng-view class="app-content scrollable-content"></ng-view>
            </div>
        </div>
        <!-- data-main attribute tells require.js to load scripts/main.js after require.js loads. -->
        <script data-main="main" src="libraries/requirejs/require.js"></script>
    </body>
</html>

OK so getting back to the plumbing, in the menu we have 3 links/pages:

<a class="list-group-item" href="#/">Home <i class="fa fa-chevron-right pull-right"></i></a>
<a class="list-group-item" href="#/angular-chart">Angular Chart <i class="fa fa-chevron-right pull-right"></i></a>
<a class="list-group-item" href="#/activity-analysis">Activity Analysis <i class="fa fa-chevron-right pull-right"></i></a>

these are mapped to the relevant html Views by $routeProvider in bootstrap.js

vagrant@m202vm:/vagrant/portfolio-2014$ grep -B2 -A6 routeProvider www/public/bootstrap.js 

    var app = angular.module('app', ['ngRoute', 'mobile-angular-ui', 'googlechart'])
        .config(['$routeProvider', function ($routeProvider) {
            $routeProvider
                .when('/', {templateUrl: 'views/home.html'})
                .when('/angular-chart', {templateUrl: 'views/angular-chart.html'})
                .when('/activity-analysis', {templateUrl: 'views/activity-analysis.html'})
                .otherwise({redirectTo: '/'});
        }])
        .config(['$locationProvider', function ($locationProvider) {

this view inturn makes calls to it's Controller i.e. activityAnalysisCtrl:

vagrant@m202vm:/vagrant/portfolio-2014$ grep -A10 activityAnalysisCtrl www/public/views/activity-analysis.html 
            <div ng-controller='activityAnalysisCtrl'>

                <p>Please enter your weight: {{dailyExercise.weight}} {{dailyExercise.weightType}}</p>


                <input ng-model="dailyExercise.weight" type="number" step="1" min="30" label="weight" >

                <select ng-model="dailyExercise.weightType">
                    <option value="1">KG</option>
                    <option value="0.454">LB</option>
                </select>

The controller function is defined within controllers/activityAnalysis.js:

vagrant@m202vm:/vagrant/portfolio-2014$ grep activityAnalysisCtrl www/public/views/*
www/public/views/activity-analysis.html:            <div ng-controller='activityAnalysisCtrl'>
vagrant@m202vm:/vagrant/portfolio-2014$ grep activityAnalysisCtrl www/public/controllers/*
www/public/controllers/activityAnalysis.js:var activityAnalysisCtrl = function ($scope) {

There is also a mapping function within controllers/index.js:

vagrant@m202vm:/vagrant/portfolio-2014$ cat www/public/controllers/index.js 
/** attach controllers to this module 
 * if you get 'unknown {x}Provider' errors from angular, be sure they are
 * properly referenced in one of the module dependencies in the array.
 * below, you can see we bring in our services and constants modules 
 * which avails each controller of, for example, the `config` constants object.
 **/
define([
    './angularChart',
    './activityAnalysis'
], function () {});

For the moment the controller logic is fairly simple:

vagrant@m202vm:/vagrant/portfolio-2014$ cat www/public/controllers/activityAnalysis.js
// todo: refactor the scope of this controller to not be thrown like this in the global space.

var activityAnalysisCtrl = function ($scope) {

    // todo: refactor all this in a model.
    $scope.dailyExercise = {
        "weight": 76,
        "weightType": 1,
        "date": new Date(),
        "activityEntries": []
    };

    $scope.activityEntry = {
        "metRate": 0.9,
        "hours": 0,
        "minutes": 0
    };

    $scope.addEntry = function (activityEntry) {
        $scope.dailyExercise.activityEntries.push({
            "metRate": activityEntry.metRate,
            "hours": activityEntry.hours,
            "minutes": activityEntry.minutes
        });
    };

So we are really getting going with Angular now, but lots more to do :)

MEAN Stack Part One – Disecting a very simple Node.js, RequireJS, ExpressJS application

Disecting a very simple Node.js, RequireJS, ExpressJS applicaton

Javascript seem to have been the hot new language for several years now, the language itself is not really new but there are a lot of exciting frontend and backend projects using javascript.

Recently I have been building up my backend javascript kills via a number of Mongo University courses (highly recommended… although I am still slightly more comfortable programing in python than javascript).

I’m really curious about all the new frontend javascript libraries and frameworks, and as my partner is a very experienced javascript programmer, I have been having some training at home :)

Before we start, the prototype version of this project is using a single backend node.js package, which is express.js:

vagrant@angular:/vagrant/portfolio-2014$ cat package.json 
{
  "name": "portfolio-2014",
  "description": "Showcase of Nadjib Amar web work.",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "4.2.x"
  }
}

and in the front-end using the bower package manager, we are running with angular.js and require.js:

vagrant@angular:/vagrant/portfolio-2014$ cat bower.json 
{
  "name": "Portfolio 2014",
  "version": "0.0.1",
  "main": "www/public/index.html",
  "ignore": [
    "**/.*",
    "libs"
  ],
  "dependencies": {
    "angular": "1.2.x",
    "angular-route": "1.2.x",
    "requirejs": "2.1.x",
    "requirejs-domready": "2.0.x"
  }

I am not going to cover any details for npm install and bower install logs, but it is worth noting that running on Ubuntu 12.04, I had to use sudo for the ‘npm install’ but not for the ‘bower install’

Starting with a very simple get request to index.html

vagrant@angular:/vagrant/portfolio-2014$ cat www/public/index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">

        <title>Nadjib Amar, Front-end Developer in Amsterdam</title>
    </head>
    <body>

        <h1>Nadjib Amar, Front-end Developer in Amsterdam</h1>

        <nav>
            <div>
                <h2>Front-end programming</h2>
                Javascript
                HTML5
                CSS 3
            </div>

            <div>
                <h2>Backend programming</h2>
                NodeJS
            </div>

            <div>
                <h2>Databases</h2>
                MongoDB
                MySQL
                SQL Server
            </div>

            <div>
                <h2>Deployment environments</h2>
                NodeJS on Ubuntu
                Amazon Cloud
                Apache on Ubuntu
                Microsoft Cloud
            </div>

            <div>
                <h2>Javascript libraries</h2>
                AngularJS
                ExpressJS
            </div>

            <div>
                <h2>Websites I've worked on</h2>
            </div>

            <div>
                <h2>Development ideas</h2>
            </div>

            <div>
                
            </div>
        </nav>


        <ng-view></ng-view>

        <!-- data-main attribute tells require.js to load scripts/main.js after require.js loads. -->
        <script data-main="main" src="libraries/requirejs/require.js"></script>
    </body>
</html>

the most interesting part is the call to require.js passing in the data-main=”main” parameter.

Stepping through this simple node.js project, looking at the server logs for a simple “index.html” GET request

vagrant@angular:/vagrant/portfolio-2014$ node www/server.js 
Listening on port 8080.
GET /
GET /libraries/requirejs/require.js
GET /main.js
GET /bootstrap.js
GET /app.js
GET /libraries/angular/angular.min.js
GET /controllers/index.js
GET /libraries/angular-route/angular-route.min.js
GET /controllers/helloWorld.js
GET /libraries/requirejs-domready/domReady.js
GET /views/home.html
GET /libraries/angular/angular.min.js.map
GET /libraries/angular-route/angular-route.min.js.map

the server.js defines a basic express “app”:

vagrant@angular:/vagrant/portfolio-2014$ cat www/server.js 
(function () {
    'use strict';

    // Load dependencies.
    var express = require('express'),
        app = express();

    // Simple logger.
    app.use(function (req, res, next) {
        console.log('%s %s', req.method, req.url);
        next();
    });

    // Set generic headers used in all responses.
    app.use(function (req, res, next) {
        res.set({
            'X-Powered-By': 'eBabel',
            'Access-Control-Allow-Methods': 'GET, OPTIONS', // Allowed request methods.
            'Access-Control-Allow-Headers': 'X-Requested-With,content-type' // Allowed request headers.
        });
        next();
    });

    // Static file requests.
    app.use(express.static(__dirname + '/public'), {
        maxAge: 365    // Set an distant expiry date for all static assets.
    });

    // Start listening on a port.
    app.listen(8080);
    console.log('Listening on port 8080.');

However sbove you can see we are loading express via require which was loaded in the index.html (I had expected these to be loaded via server.js when the application starts, however the console logs show this was not the case)

Looking at the “GET requests” in the server logs (even further above), the first request is to GET ”/libraries/requirejs/require.js” i.e. when index.html is loaded:

vagrant@angular:/vagrant/portfolio-2014$ head www/public/libraries/requirejs/require.js 
/** vim: et:ts=4:sw=4:sts=4
 * @license RequireJS 2.1.14 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
 * Available via the MIT or new BSD license.
 * see: http://github.com/jrburke/requirejs for details
 */
//Not using strict: uneven strict support in browsers, #392, and causes
//problems with requirejs.exec()/transpiler plugins that may not be strict.
/*jslint regexp: true, nomen: true, sloppy: true */
/*global window, navigator, document, importScripts, setTimeout, opera */
var requirejs, require, define;
(function (global) {
    var req, s, head, baseElement, dataMain, src,
        interactiveScript, currentlyAddingScript, mainScript, subPath,
        version = '2.1.14',
...

We are using require.js to load all the javascript libraries we are going to use

vagrant@angular:/vagrant/portfolio-2014$ cat -n  www/public/libraries/requirejs/require.js|grep -A20 data-main
  1943	    //Look for a data-main script attribute, which could also adjust the baseUrl.
  1944	    if (isBrowser && !cfg.skipDataMain) {
  1945	        //Figure out baseUrl. Get it from the script tag with require.js in it.
  1946	        eachReverse(scripts(), function (script) {
  1947	            //Set the 'head' where we can append children by
  1948	            //using the script's parent.
  1949	            if (!head) {
  1950	                head = script.parentNode;
  1951	            }
  1952	
  1953	            //Look for a data-main attribute to set main script for the page
  1954	            //to load. If it is there, the path to data main becomes the
  1955	            //baseUrl, if it is not already set.
  1956	            dataMain = script.getAttribute('data-main');
  1957	            if (dataMain) {
  1958	                //Preserve dataMain in case it is a path (i.e. contains '?')
  1959	                mainScript = dataMain;
  1960	
  1961	                //Set final baseUrl if there is not already an explicit one.
  1962	                if (!cfg.baseUrl) {
  1963	                    //Pull off the directory of data-main for use as the
  1964	                    //baseUrl.
  1965	                    src = mainScript.split('/');
  1966	                    mainScript = src.pop();
  1967	                    subPath = src.length ? src.join('/')  + '/' : './';
  1968	
  1969	                    cfg.baseUrl = subPath;
  1970	                }
  1971	
  1972	                //Strip off any trailing .js since mainScript is now
  1973	                //like a module name.
  1974	                mainScript = mainScript.replace(jsSuffixRegExp, '');
  1975	
  1976	                 //If mainScript is still a path, fall back to dataMain
  1977	                if (req.jsExtRegExp.test(mainScript)) {
  1978	                    mainScript = dataMain;
  1979	                }
  1980	
  1981	                //Put the data-main script in the files to load.
  1982	                cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
  1983	
  1984	                return true;
  1985	            }
  1986	        });
  1987	    }

now in index.html we set data-main=”main”, so require is going to load the following script:

vagrant@angular:/vagrant/portfolio-2014$ cat www/public/main.js 
// Configure RequireJS
require.config({

    paths: {
        'angular': 'libraries/angular/angular.min',
        'angular-route': 'libraries/angular-route/angular-route.min',
        'domReady': 'libraries/requirejs-domready/domReady'
    },
    shim: {
        'angular': {
            exports: 'angular'
        },
        'angular-route': {
            deps: ['angular']
        }
    },
    deps: [
        // Kick start application. See bootstrap.js
        './bootstrap'
    ]

This gives the path to the angular libraries we will be using, although from the server logs it appears that deps is load next

^Cvagrant@angular:/vagrant/portfolio-2014$ node www/server.js 
Listening on port 8080.
GET /
GET /libraries/requirejs/require.js
GET /main.js
GET /bootstrap.js         << this gets loads next
GET /app.js
GET /libraries/angular/angular.min.js
GET /controllers/index.js
GET /libraries/angular-route/angular-route.min.js
GET /controllers/helloWorld.js
GET /libraries/requirejs-domready/domReady.js
GET /views/home.html
GET /libraries/angular/angular.min.js.map
GET /libraries/angular-route/angular-route.min.js.map

the other thing to note here is the reference to shim which allows us to define dependencies

“Ideally the scripts you load will be modules that are defined by calling define(). However, you may need to use some traditional/legacy “browser globals” scripts that do not express their dependencies via define(). For those, you can use the shim config. To properly express their dependencies.”

http://requirejs.org/docs/api.html

Anyway looking at bootstrap.js, this calls the RequireJS define function, passing an array of modules to be loaded and a callback function:

vagrant@angular:/vagrant/portfolio-2014$ cat www/public/bootstrap.js 
/**
 * bootstraps angular onto the window.document node
 * NOTE: the ng-app attribute should not be on the index.html when using ng.bootstrap
 */
define([
    'require',
    'angular',
    'angular-route',
    'app'
], function (require, ng) {
    'use strict';

    /*
     * place operations that need to initialize prior to app start here
     * using the `run` function on the top-level module
     */

    /* App Module */
    var app = angular.module('app', ['ngRoute'])
        .config(['$routeProvider', function ($routeProvider) {
            $routeProvider
                .when('/', {templateUrl: 'views/home.html'})
                .when('/front-end-developer-cv', {templateUrl: 'views/front-end-developer-cv.html'})
                .otherwise({redirectTo: '/'});
        }])
        .config(['$locationProvider', function ($locationProvider) {
            $locationProvider.html5Mode(false);
        }]);

    require(['domReady!'], function (document) {
        ng.bootstrap(document, ['app']);
    });
});

Here is a relevant snip from define()

vagrant@angular:/vagrant/portfolio-2014$ cat -n  www/public/libraries/requirejs/require.js|grep -B10 -A10 'define = function'
..
  1989	    /**
  1990	     * The function that handles definitions of modules. Differs from
  1991	     * require() in that a string for the module should be the first argument,
  1992	     * and the function to execute after dependencies are loaded should
  1993	     * return a value to define the module corresponding to the first argument's
  1994	     * name.
  1995	     */
  1996	    define = function (name, deps, callback) {
  1997	        var node, context;
  1998	
  1999	        //Allow for anonymous modules
  2000	        if (typeof name !== 'string') {
  2001	            //Adjust args appropriately
  2002	            callback = deps;
  2003	            deps = name;
  2004	            name = null;
  2005	        }
  2006	
...

Now RequireJS has done it’s work, we load our ExpressJS app.js code

vagrant@angular:/vagrant/portfolio-2014$ cat www/public/app.js 
(function () {
    'use strict';

    /**
     * loads sub modules and wraps them up into the main module
     * this should be used for top-level module definitions only
     */
    define([
        'angular',
        'angular-route',
        './controllers/index'
    ], function (angular) {
        'use strict';

        return angular.module('app', [
            'app.controllers',
            'ngRoute'
        ]);
    });

}());

This loading angular, angular-route and then controller/index

vagrant@angular:/vagrant/portfolio-2014$ cat www/public/controllers/index.js 
/** attach controllers to this module 
 * if you get 'unknown {x}Provider' errors from angular, be sure they are
 * properly referenced in one of the module dependencies in the array.
 * below, you can see we bring in our services and constants modules 
 * which avails each controller of, for example, the `config` constants object.
 **/
define([
    './helloWorld'
], function () {});

clearly this is still some work to be done here, to build out this web app ;)

Setting up ruby version manager and neography (rubyzip requires Ruby version >= 1.9.2)

I have been happily working with Ubuntu 12.04 running it via vagrant:

vagrant@neo4mind:/vagrant$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 12.04 LTS
Release:	12.04
Codename:	precise

today’s problem was that I needed a more up-to-date version of ruby:

vagrant@neo4mind:/vagrant$ sudo gem install neography
Fetching: excon-0.33.0.gem (100%)
Fetching: json-1.8.1.gem (100%)
Building native extensions.  This could take a while...
Fetching: os-0.9.6.gem (100%)
Fetching: rubyzip-1.1.4.gem (100%)
ERROR:  Error installing neography:
	rubyzip requires Ruby version >= 1.9.2.
vagrant@neo4mind:/vagrant$ ruby -v
ruby 1.8.7 (2012-02-08 patchlevel 358) [i686-linux]

the solution was rvm (ruby version manager)

\curl -L https://get.rvm.io | bash -s stable
exit     ##need to logoff and back in here
source ~/.rvm/scripts/rvm
rvm requirements
rvm install ruby
rvm use ruby --default
ruby -v

and now I can install neography

sudo gem install neography

AMS JavaScript MVC Meetup Dec 2013

Last week I went the JavaScript MVC Meetup and here I have written up my notes in the form of mind-map using neography (a ruby interface to Neo4j).

I appreciate that the links here are a reflection of my personal thoughts and observations and probably slightly choatic… but still I find mindmaps very useful and I am enjoying being able to generate them programatically!

So to the two presentations….

Peter Peerdeman gave a presentation of Restangular vs AngularJS… it was a very good presentation, with good audience interactions. Possibly the topic was a bit advanced for my more basic Javascript MVC knowledge, but still I got a lot out of it:

JavascriptMVC_Restangular

The 2nd presentation was Or Hiltch from AVG, sme really insight into how widespread their adoption of Javascript has already become: ‘everything which can be written in Javascript will eventually be written in Javascript’:

JavascriptMVC_AVG

The best quote of the evening was :

everything which can be written in Javascript will eventually be written in Javascript

Alex Gorbatchev’s WordPress SyntaxHighlighter

This is a great WordPress plugin : http://en.support.wordpress.com/code/posting-source-code/

The sample source code in my blog posts now has proper highlighting, for example:

@bottle.route('/')
def blog_index():

    cookie = bottle.request.get_cookie("session")

    username = sessions.get_username(cookie)

    # even if there is no logged in user, we can show the blog
    l = posts.get_posts(10)

    return bottle.template('blog_template', dict(myposts=l, username=username))

Unfortunately my existing blog posts all needed updating, I had used the following bash script:

http://wiki.ebabel.eu/index.php?title=Sed/syntax_high_lighter

Mongo University M101P and M102… more great MOOCs

I am working my way through and enjoying the Mongo University courses:

- M101P: MongoDB for Developers

This course will go over basic installation, JSON, schema design, querying, insertion of data, indexing and working with language drivers. We will also cover working in sharded and replicated environments. In the course, you will build a blogging platform, backed by MongoDB. Our code examples will be given in Python.

- M102: MongoDB for DBAs

Then you will learn about JSON and Mongo’s extensive query capabilities through the Mongo shell. We will cover importing, and exporting data into Mongo. After that, we cover replication and fault tolerance. Then it is on to scaling out with MongoDB, including indexing, performance tuning, monitoring, and sharding. Finally, we cover backups and recovery.

The courses are very well structured, about a year ago I did the Udacity CS101 to learn python to build a web crawler:

In this course you will learn key concepts in computer science and learn how to write your own computer programs in the context of building a web crawler.

David Evans is a Professor of Computer Science at the University of Virginia where he teaches computer science and leads research in computer security. He is the author of an introductory computer science textbook and has won Virginia’s highest award for university faculty. He has PhD, SM, and SB degrees from MIT.

Basically I really like the modern MOOC format (‘Massive Open Online Course’), and in this Mongo course is that the problem solving is the particularly well paced problems.

The following problem sounds pretty simple:

The students collection has 200 records

 
>db.students.count()
200

but the scores for each student are slightly awkwardly structured, with an array of dictionary elements:

> db.students.find({"_id" : 1},{scores:1}).pretty()
{
"_id" : 1,
"scores" : [
{
"type" : "exam",
"score" : 60.06045071030959
},
{
"type" : "quiz",
"score" : 52.79790691903873
},
{
"type" : "homework",
"score" : 71.76133439165544
},
{
"type" : "homework",
"score" : 34.85718117893772
}
]
}

are our task is to remove the homework documents with the lowest scores:

&gt; db.students.find({"_id" : 1},{scores:1}).pretty()
{
"_id" : 1,
"scores" : [
{
"score" : 60.06045071030959,
"type" : "exam"
},
{
"score" : 52.79790691903873,
"type" : "quiz"
},
{
"score" : 71.76133439165544,
"type" : "homework"
}
]
}

my solution was based on
1) loading the data:

for ids_scores_cursor in students.find():
   ids_scores_dict[ids_scores_cursor["_id"]]=ids_scores_cursor["scores"]

2) for each record I create a new_scores array:

for rec_id in ids_scores_dict:
   new_scores=[]
   min_homework=0

and work through the original scores list and load in relevant records…

3) update the students record with the new_scores

   db.students.update({'_id':rec_id},{'$set':{'scores': new_scores}},upsert=False, multi=False)

Working on MongoDB with NodeJS and Mongoose

I am starting a new project to build a new website / webservice for an Eritrean language dictionary with Nadjib.

We are going to use the MEAN stack … MongoDB, ExpressJS, AngularJS and NodeJS

My task is to work on the MongoDB – Mongoose side of the application.

I now have the very basics working:

http://wiki.ebabel.eu/index.php/MongoDB-Mongoose

This work is based on / summary of several very useful webpages.

Firstly to setup MongoDB on Ubuntu:

http://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/
https://www.digitalocean.com/community/articles/how-to-install-mongodb-on-ubuntu-12-04

Next getting Mongoose working:

http://blog.modulus.io/getting-started-with-mongoose

NB The npm install of express and mongoose was handled by Nadjib for me.