Tuan Anh

container nerd. k8s || GTFO

Using GitHub issue tracker as comment system for your static blog

Ivan Zuzak wrote about it here. It’s actually a very cool idea. All you need is to create a new repo on GitHub, create an issue for the blog post you want to enable comment and set commentIssueId in your blog post. A JavaScript ajax call will pull comments from GitHub on page load.

If I were to enable comments on my blog, I would defenitely go this route. You already blog like a hacker, you should also comment like one.

I’ve also seen people using Discourse for their website’s comments. The downside is setting up a new VPS and install Discourse(an online discussion software) seems like overkill for this purpose. Also, Discourse is not exactly lightweight. In order to install Discourse, you need a VPS with minimum 1GB of RAM (at least that was when I last tried it). My VPS has mere 128MB of memory, not exactly a beasty machine. The reason I went with static blog is it’s very lightweight. Using Discourse kinda defeat the purpose now, doesn’t it?

If you don’t want to go through all the troubles, you can use Disqus instead.


Resume-driven developer

A resume-driven developer can’t seem to use the same technology, in the same way all over again. When assigned an easy task, he will find ways to over-engineering a solution that will make it less boring. He loves injecting new technology into the current project, often without any upfront with other developers (well, this could be very bad since it may introduces competing UI framework, multiples data access methods, repeated functionalities, etc..). And when asked about it, he wil talk for hours about how horrible the current code/framework in the existing project is.

Does all of that sound familiar to you? If yes, you’re definitely a resume-driven developer.

I have to confess I’m that guy. I’m easy attracted to shiny new, cool technology but I found it hard to find motivation to learn it properly. Working in an actual project helps me learn better with all the challenges and deadline.

Decide what’s the next bullet you want to put on your resume at the end of the project, be it new language, new framework or some responsibilities, request to take that part of the project and make them true.

Resume-driven in itself isn’t bad. It’s actually a sign of a passionate developer. As long as it makes sense to introduce it to the current project without adding too much complexity, it will work. Remember, your code is not for you to read alone. It’s your job to manage the complexity, not to create it.


Shower thought about movie recommedation

Once in awhile, when I see a movie that I like, I go to IMDB and find out who directed it; who are the main actor/actress; what are the others highly rated movies of that director, main actor/actress. Then I will go on systematically watching one film after another. Given that they are good enough to keep me going.

The result is decidedly mixed. It doesn’t always turn out to be good as I want but it works, to a degree.

The thing about movie is that it takes million of dollars to make and it involves many parties. It’s hard for the creator to make the movie the way they indended to make. And I guess it makes sense. Making movie is unlike writing a novel; at least not until technology evolves to make producing movies cheap enough to be an habit like writing novels.

When that happened, recommender system for movies will be a lot easier to implemented and more accurated.


Inline Google fonts to further reduce number of blocking CSS resources

Most major browsers have support for .woff font format for quite awhile now. The number is around 85%+ with IE8 is the most high profile exception. But … who actually cares about IE8 right! Chances are if you are reading my blog, you won’t be using it anyway 1.

Ok, I’m convinced. How do I download and use .woff fonts now?

There is a npm package called webfont-dl which will create a ready-to-use CSS file with .woff fonts inline and other font formats as well as fallback. Including it in your main stylesheet and you’re done. Maybe organize it in a /fonts/ folder and update the font links in the CSS. That’s it.

To install webfont-dl: (nodejs required)

npm install -g webfont-dl

To download the CSS and webfonts:

webfont-dl "http://fonts.googleapis.com/css?family=Crimson+Text:400,400italic|Raleway:500" \
  -o css/font.css
  1. I provide fallbacks for unsupported browser anyway. See how nice I am ;) 


How to burn a bootable ISO file to USB stick on OS X

This method works with *unix ISO files. If you want to create a bootable Windows USB, use Bootcamp Assistant instead.

OS X shipped with dd installed. It’s a little utility to copy/convert from an input (your ISO file) to another output (your USB stick). The process is fairly easy.

Plugin your USB stick. Find where your USB stick is mounted by looking at the name and the size. It looks like /dev/diskX.

diskutil list

To burn the bootable ISO to USB stick, issue the following command. Replace the ISO file name with the path to your ISO file and diskX with the value you noted at the previous step.

sudo dd if=xubuntu-14.10-desktop-amd64.iso of=/dev/diskX

Enter your password, wait for a little while. It may looks like it’s hanging but do not abort. It would take few minutes, depends on the size of the ISO file.

If you find dd too slow, you can try replace /dev/diskX with /dev/rdiskX and add bs=4m option.

sudo dd if=xubuntu-14.10-desktop-amd64.iso of=/dev/rdiskX bs=4m

Contexts is the perfect companion app for Amethyst

⌘-Tab for application switching is a real nuisance. It’s application-based instead of document-based. Example, you have two documents, opened in two windows of an app. ⌘-Tab onlys show 1 entry (the app itself) in the application switcher, which is annoying. You have no way of getting to the window of the document that you want. Instead you will have to right click on the app icon in the dock and select from there.

Contexts is a simple app that solves a lot of problems with builtin ⌘-Tab app switcher.

Switching apps with Contexts

Contexts overrides the system shortcut ⌘-Tab so it will just fit right in.

The usual workflow when you want to switch to an app goes like this: you press ⌘-Tab, take a look at the list and keep pressing Tab until you get to the application you want to switch to. It’s far from idea because you can’t jump straight to the app you want but keep holding ⌘-Tab while checking the list.

Contexts solve this problem by showing a small sidebar with badge number. All you have to do is to press + number1 to switch to the coresponding app.

Another problem is with the Finder app. When I need to open a new Finder window when there isn’t any opened. I will have to ⌘-Tab then Tab to it. Finder will be brought to front without any active window. I then have to press ⌘-N combination to open a new window. So much trouble for a simple operation. Contexts fixes this by openning a new window when there isn’t one.

Switching app by searching

Switching app by searching is by far my favorite feature.

Contexts allows you to search by pressing Ctrl+Space then type app name or document’s title. This is a much improvement over the builtin application switcher. I can now switch app without the need to hold ⌘-Tab, which I found very tiresome.

contexts app os x

I only use ⌘-Tab to quickly switch back to the previous app because Contexts sorts apps by default that way.

Fin

I fell in love with Contexts sometimes ago. Then there was Amethyst. These two apps just complements each other perfectly, making managing app windows a breeze.

If you’ve never tried it, give it a shot. Once you do, you won’t go back. Guaranteed.

  1. I change the combination to Alt+number since it messes up with Chrome tab switching (⌘-number) shortcuts. 


Awesome maching learning

A curated list of awesome machine learning frameworks, libraries and software (by language). Inspired by awesome-php. Other awesome lists can be found in the awesome-awesomeness list.

Stumble upon this list when I was looking for some Julia’s libraries.

link bài gốc

Deferred font loading and using localStorage as cache

The idea is to lazy-load web fonts once everything else loaded completely, store them in localStorage to be used for subsequent pages. A cookie is used as a flag to check if the fonts are cached in localStorage.

There are something to note:

  • If visitors disable cookie, this method will backfire as the webfont will be reloaded everytime visitors go to a different page.

  • localStorage is slower than browser cache (So i heard).

  • A browser that supports localStorage is required, which mean IE8+, Firefox, Opera and Chrome.

  • On first load, the page will be flashed a bit after finish loading web fonts. This happened because the web fonts finish loading and are re-applied onto the page. Because of this particular reason, I refuse to use this method to lazy-load web fonts. I just hate it seeing it flashed. I’m a sucker for this kind of detail.

  (function () {
    "use strict";
    // once cached, the css file is stored on the client forever unless
    // the URL below is changed. Any change will invalidate the cache
    var css_href = './index_files/web-fonts.css';
    // a simple event handler wrapper
    function on(el, ev, callback) {
      if (el.addEventListener) {
        el.addEventListener(ev, callback, false);
      } else if (el.attachEvent) {
        el.attachEvent("on" + ev, callback);
      }
    }
    
    // if we have the fonts in localStorage or if we've cached them using the native batrowser cache
    if ((window.localStorage && localStorage.font_css_cache) || document.cookie.indexOf('font_css_cache') > -1){
      // just use the cached version
      injectFontsStylesheet();
    } else {
     // otherwise, don't block the loading of the page; wait until it's done.
      on(window, "load", injectFontsStylesheet);
    }
    
    // quick way to determine whether a css file has been cached locally
    function fileIsCached(href) {
      return window.localStorage && localStorage.font_css_cache && (localStorage.font_css_cache_file === href);
    }

    // time to get the actual css file
    function injectFontsStylesheet() {
     // if this is an older browser
      if (!window.localStorage || !window.XMLHttpRequest) {
        var stylesheet = document.createElement('link');
        stylesheet.href = css_href;
        stylesheet.rel = 'stylesheet';
        stylesheet.type = 'text/css';
        document.getElementsByTagName('head')[0].appendChild(stylesheet);
        // just use the native browser cache
        // this requires a good expires header on the server
        document.cookie = "font_css_cache";
      
      // if this isn't an old browser
      } else {
         // use the cached version if we already have it
        if (fileIsCached(css_href)) {
          injectRawStyle(localStorage.font_css_cache);
        // otherwise, load it with ajax
        } else {
          var xhr = new XMLHttpRequest();
          xhr.open("GET", css_href, true);
          // cater for IE8 which does not support addEventListener or attachEvent on XMLHttpRequest
          xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
              // once we have the content, quickly inject the css rules
              injectRawStyle(xhr.responseText);
              // and cache the text content for further use
              // notice that this overwrites anything that might have already been previously cached
              localStorage.font_css_cache = xhr.responseText;
              localStorage.font_css_cache_file = css_href;
            }
          };
          xhr.send();
        }
      }
    }

    // this is the simple utitily that injects the cached or loaded css text
    function injectRawStyle(text) {
      var style = document.createElement('style');
      // cater for IE8 which doesn't support style.innerHTML
      style.setAttribute("type", "text/css");
      if (style.styleSheet) {
          style.styleSheet.cssText = text;
      } else {
          style.innerHTML = text;
      }
      document.getElementsByTagName('head')[0].appendChild(style);
    }

  }());

I did not write this code. This bit was taken from Smashing Magazine - source.


nodejs: callback vs promise

http://www.slideshare.net/wookieb/callbacks-promises-generators-asynchronous-javascript

The problem

Consider the code snippet below:

var x = doSomething();
typeof x === 'undefined'; // true

The second statement will not wait for the first one to complete, hence result in true in the second statement.

When it comes to dealing with asynchronous in nodejs, we usually come down to 2 most popular options: callback and promise.

Callback

Callback is widely used but when we need 3 or more operations going in sequence, things are going to get ugly. Consider the following code snippet.

var doSomething = function(arg1, arg2, cb_fn) {
  var sum = arg1 + arg2;
  cb_fn(sum);
};

// usage
doSomething(10,20, console.log);

That is just one function with callback. Imagine this with 4 levels of callback. Welcome to CALLBACK HELL!!

var func_1 = function(cb) {
  func_2(function(err, result) {
    if (err) { cb(err); return; }

    func_3(result, function(err, result) {
      if (err) { cb(error); return; }

      // WE NEED TO GO DEEPER
    });
  });
}

Promise

What is a promise?

The core idea behind promises is that a promise represents the result of an asynchronous operation. A promise is in one of three different states:

  • pending - The initial state of a promise.
  • fulfilled - The state of a promise representing a successful operation.
  • rejected - The state of a promise representing a failed operation.

Once a promise is fulfilled or rejected, it is immutable (i.e. it can never change again).

The most complete library for promise on Nodejs is Q.


How to fix `Logon failed for login 'username' due to trigger execution` error with mssql

I recently tumbled upon an error when trying to connect to SQL Server in nodejs using mssql package.

Logon failed for login 'username' due to trigger execution

I have no problem connecting to a dev db server of mine, probably due to I don’t have any restriction/security setup on it. I only got this when connecting to a production server.

Problem lies in the default driver tedious used by mssql. Changing to tds fixes the problem.

I don’t actually understand the problem behind this so if anyone knows, please help explain it to me.