Friedrich Ewald My Personal Website

Posts


  • Lunch manager with angularJS & nodeJS

    Some days ago I created a simple script just to try out some new techniques with angularJS in combination with nodeJS. The idea was to create a lunch manager where people can sign up for a specific day, that they are in for lunch at a specific time. There should be no complex signup since I was not expecting any spam or similar behavior. I had the idea of realising this script with a minimal footprint so that it is easy to deploy and easy to run on any Linux based server. This leads to the idea of creating a one pager with most of the Javascript files hosted on a CDN and only the absolute minimum should be hosted on my server. ##Setting up the front-end As a front-end I chose the responsive bootstrap framework from Twitter. The dynamic part should be realized with angular. The whole website is only one controller, called FoodCtrl.

    <body ng-controller="FoodCtrl as f">
    
    For this controller I wrote the following angular module which basically takes the user input, if the name is longer than two characters, submits it to the server and fetches every two seconds the list from the server. With this procedure it is ensured, that the list if the users is always up to date and the user does not have to refresh the website to see if new users have signed up.
    angular.module('foodApp', [])
      .controller('FoodCtrl', ['$http', function($http) {
        var food = this;
        food.alreadyIn = false;
        food.pendingRequest = false;
        food.name = '';
        food.namesList = [];
    
        food.signup = function(time) {
          food.pendingRequest = true;
          $http.post('/lunch/signup', {name: food.name, time: time})
            .then(function (response) {
              console.log(response);
              notie.alert(1, 'Success, you\'re in for today, ' + food.name + '!', 1.5);
              food.alreadyIn = true;
              food.pendingRequest = false;
            }, function (response) {
              notie.alert(3, 'Error ' + response.status, 5);
              food.pendingRequest = false;
            });
        };
        fetch_updates($http, food, 0, false);
        refetch_updates($http, food, 0);
      }])
      .directive('person', function() {
        return {
          template: '{ {n.name}}@{ {n.time}}'
        };
      });
    
    With a click on the signup button, an ajax request via the integrated angular $http service is made consisting of the name and the time. For the complete source code you can check out the git repository I set up. ##Difficulties While creating the app I had some difficulties stopping the flickering effect which happens to all angularJS apps which do not use externally loaded templates. This effect happens because the browser renders first the complete HTML document with the whole DOM and after that (if you load angular just before the closing body-tag) angular, which processes the HTML document with it’s own renderer. To avoid this, one can use the angular directive ng-cloak on any HTML tag which should be hidden at first because it contains i.e. if-expressions which are evaluated later. Adding only ng-cloak alone is only half of the solution because angular adds CSS tags to all elements with this directive. But since angular is loaded just before the closing body tag, hiding of the elements is executed often too late in time. Especially, the slower the computer, the more important it is to hide these elements just from the beginning. As a workaround I chose the following approach. Just add a style in the head part which hides ng-cloak and this style is removed later automatically by angular:
    <style type="text/css">
      [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
        display: none !important;
      }
    </style>
    
    Another difficulty which I had to solve was the update of the person list. There are basically three strategies on how to get an up-to-date list of the participants: long polling, WebSockets and periodic AJAX requests. Since long-polling looks more like a hack to me and WebSockets would need the set up of another server, I decided to use continuous AJAX requests, to enable a synchronization with all the connected clients. The script, which updates the list looks like this:
    function fetch_updates($http, food, errorCounter, recursive) {
        console.log('fetching names...');
        $http.get('/lunch/people.json')
          .then(function(response) {
            if(food.namesList.length < response.data.length && recursive) {
              notie.alert(4, 'Someone else signed up!', 1.5);
            }
            food.namesList = response.data;
            if (recursive) {
              refetch_updates($http, food, 0);
            }
          },
          function(response) {
            notie.alert(3, 'Error while fetching other people', 2);
            refetch_updates($http, food, errorCounter + 1)
          });
      };
    
      function refetch_updates($http, food, errorCounter) {
        if (errorCounter < 5) {
          var timeout = (errorCounter + 1) * 2000;
          console.log(timeout);
          setTimeout(function () {
            fetch_updates($http, food, errorCounter, true);
          }, timeout);
        }
        else {
          notie.confirm('Error loading data. Do you want to retry?', 'Yes', 'No', function () {
            refetch_updates($http, food, 0);
          });
        }
      }
    
    The method refetch_updates checks the errorCounter. If it is below 5, it calls fetch_updates after a timeout of the error count times two seconds. The method fetch_updates calls refetch_updates again. If the request fails more than five times, the user is asked, if he wants to continue fetching updates or not. If yes, the errorCounter is reset to zero and the recursive call begins again. The advantage of this method is, that I didn’t have to implement any other server than the existing nodeJS express server. ##Conclusion From the idea to the working script it took me about two hours, if I substract the setup time of nodeJS and Apache, which only serves as a proxy this time. If you want to download the whole project, you can check out my git repository.

  • Installing nodeJS and setting up an alias

    Under Ubuntu 14, installing nodejs is relatively easy. At first one needs to to the obvious sudo apt-get update followed by a sudo apt-get install nodejs With this two easy steps you have a nodejs installation on your system which you could easily check with node -v. If the installation was successful, this command prints the current installed nodejs version. In my case this was the version v0.10.25 which is a bit outdated but could be sufficient if you do not plan to serve files or sites over the internet. In this case you should install the latest version from nodejs.org directly because of some severe security issues with the older versions. In my case it was not done with installing node because the directory, where nodejs was installed to nor was in the PATH neither there was a symlink to nodejs. For some reason, some programs rely on node, others rely on nodejs. So the goal was to use the same program for each command and also make it available in the PATH to access it directly. After asking stackoverflow, I was proposed to create an alias in the .bashrc file like this:

    alias nodejs='/usr/bin/nodejs'
    
    Conclusion: Do not change the path, change the bash profile as the path easily can break since it depends on the order of the different folders.

  • Playing with git hooks

    Git scm offers a very interesting technique, called hooks. A hook is basically a trigger which is fired after the specific event occurs. If you create a new git repository with git init the folder .git/hooks with a couple of sample shell scripts is created. I personally use a hook to automate the deployment process of this website. After a commit is made, I automatically run a jekyll build and then copy the newly created site to the server. My current post-commit script looks like the following, simple but effective:

    #!/bin/bash
    jekyll build
    scp -r _site/* user@host:/home/user/html/
    
    ##Update 2015-12-11 I slightly changed the deploy script to only update changed files because I realized that the time to update the homepage will increase with every posting. For this reason I had to use rsync. Now the scripts looks as follows:
    #!/bin/bash
    jekyll build
    rsync --update --progress -r _site/* user@host:/home/user/html/
    
    The easiest way to synchronize over SSH is with a certificate.

  • First experiments with Jekyll

    Today, I’m trying out how to build this website with jekyll. With jekyll one can easily write markdown and yml files and create static pages from it. The advantages are obvious. No problems with scripts and security issues since all the files are HTML5, CSS and only a bit of Javascript. Also there is no need for complex server configuration or any high server speed. A simple webspace with FTP or SSH access is enough.

Page: 28 of 28 Next