Archives

Change Time Zone in Ubuntu Linux

All time zone files are located:

/usr/share/zoneinfo

Locate the timezone file name such as Asia/Hong_Kong:

Change the time zone as root:

echo 'Asia/Hong_Kong' > /etc/timezone 

Configure time zone data:

dpkg-reconfigure --frontend noninteractive tzdata

Sync clock:

ntpdate pool.ntp.org

CoffeeScript Inline Block Rule Toggling

Temporarily remove CoffeeLint restriction via the inline code:

1
2
3
4
5
6
# coffeelint: disable=max_line_length,no_implicit_parens
#
# A long comment that exceeds 80 chars per line. Lorem ipsum dolor sit amet, consectetur
# adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
#
# coffeelint: enable=max_line_length,no_implicit_parens

CoffeeScript Array of Objects

We frequently find ourselves need to define array of objects. In CoffeeScript we can write in the following way:

1
2
3
4
5
6
7
8
9
10
arr = [
{
name: 'foo'
pass: 'oof'
}
{
name: 'bar'
pass: 'rab'
}
]

Or another format is to insert a comma:

1
2
3
4
5
6
7
arr = [
name: 'foo'
pass: 'oof'
,
name: 'bar'
pass: 'rab'
]

In the spirit of CoffeeScript, we want to avoid using braces as much as possible. Therefore, the second method is preferred.

JavaScript parseInt(array) Only Converts the First Element

Converting from one type to another frequently causes bugs or unexpected result if you’re not careful. For example, when converting a string to an integer, we use the following function:

1
var num = parseInt(string, radix);

Accidentally, I used an array of numeric strings in place of string for conversion.

As stated in MDN parseInt:

If string is not a string, then it is converted to one. Leading whitespace in the string is ignored.

The array is converted to string.

If the array has only one element, then there won’t be any problem:

1
2
3
4
[10].toString()
> '10'
parseInt('10', 10)
> 10

But when there are more than one element, only the first element will be parsed:

1
2
3
4
[10, 5].toString()
> '10,5'
parseInt('10,5', 10)
> 10

Therefore, you have to be very careful when processing query parameter like:

1
?year=2013&year=2012

In many cases, it will be converted to:

1
year: ['2013', '2012']

After running through parseInt, it will result in 2013, might not be what you are looking for.

Set Your Goals

Understand that success is a byproduct of achieving your goals, and setting your
goals takes time and practice.

Steps:

  1. Define clear and measurable goals
  2. Work towards your goals everyday
  3. Track and measure your progress
1
2
3
4
5
6
7
8
9
10
11
12
13
14
types = ['personal', 'professional', 'habit']
durations = [
'lifetime', 'long term', 'short term',
'year', 'week', 'today'
]
goal =
title: 'Write a blog once a week'
body: 'Spend 1 or 2 hours each week, preferably on
Saturday, review the most important thing you have
learned in the past week, and blog about it.'
types: ['personal', 'habit']
tags: ['blog']
duration: 'short term'

Android 4.3 Jelly Bean

Jelly Bean

Finally jump back into the Google land in the mobile world. Here is what are
coming up:

  • Take a deep dive into the operating system
  • Explore every possible features in the hardware
  • Maximize the potential, including app development
  • Come up with a list of useful apps and their workflow

Share JavaScript Code between Browser (front-end) and Node (back-end)

One of the benefits coding in JavaScript is the ability to share code between
browser (front-end) and Node (back-end) environments.

To share code between two different environment, first need to understand what
are specific to browser and what are specific to Node. Shared code should be
agnostic to both environments.

In browser environment, there is an obvious one: window object. In Node
environment, there are a few objects that are not globally defined in browser:
global, process, module, exports and more, see global objects. All
these variables work, but exports is preferred.

1
console.log('Hi ' + (typeof window !== 'undefined' ? 'browser!' : 'Node!'));

Once environment is identified, then it is just the matter of writing style,
either browser style or Node style.

For example, writing in Node style by passing the exports as the parameter:

1
2
3
4
5
(function (exports) {
var foo = exports.foo = {};
// Node style code goes here.
}(typeof exports === 'undefined' ? this : exports));

By using browser style, here is an example from the annotated source code of
Underscore:

1
2
3
4
5
6
7
8
9
10
11
// Export the Underscore object for Node.js, with backwards-compatibility
// for the old require() API. If we're in the browser, add _ as a global
// object via a string identifier, for Closure Compiler "advanced" mode.
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {
root._ = _;
}

To make it easier without concerning the backward compatibility:

1
2
3
4
5
6
7
8
9
10
11
(function () {
var foo = {};
if (typeof exports !== 'undefined') {
exports.foo = foo;
} else {
this.foo = foo;
}
// Browser style code goes here.
}).call(this);

this is the same as window object in the browser environment.

1
2
3
(function (window) {
// Browser style code goes here.
}(this));

One more thing, writing in CoffeeScript is even better, because the compiled
code is already wrapped in closure, fewer indentation is needed.

1
2
3
4
5
6
7
foo = {}
if exports isnt 'undefined'
exports.foo = foo
else
this.foo = foo
# Browser style code goes here.

Compile to JavaScript by CoffeeScript 1.6.3:

1
2
3
4
5
6
7
8
9
10
11
12
(function() {
var foo;
foo = {};
if (exports !== 'undefined') {
exports.foo = foo;
} else {
this.foo = foo;
}
}).call(this);

Everything will be encapsulated inside the foo object.

Repeat Character Serveral Times in JavaScript

In Markdown, a header can be written as:

1
2
Header
======

This is a Setext-style headers, which are ‘underlined’ using equal signs (for
first-level headers) and dashes (for second-level headers)
. In order to
generate those underlined equal signs, a simple loop could be used to repeat
the character = several times. By the way, it is not necessary to have exact
number of the equal signs as the header length, but it just looks better. But
there is another way:

1
Array(heading.length + 1).join('=')

It is using the JavaScript Array global object to construct an empty Array
with the specified array length. Clever indeed!

Source Maps by UglifyJS 2 with New Prefix

Living on the bleeding edge means more to learn. I was learning about creating source maps by using UglifyJS. For some reason, the uncompressed JavaScript source codes were not able to load. After some diff with a working version from Source Maps 101, the problem is just resulting of one character difference. With newly updated UglifyJS v2.3.6, SourceMapping pragma has changed to //#:

//# sourceMappingURL=script.uglify.js.map

but my Chrome browser lags behind. It recognizes source maps as //@:

//@ sourceMappingURL=script.uglify.js.map

I did not use the latest or dev build, the current Chrome browser I am using is yet to support //#. What I really need is Chrome Canary. Unfortunately, it is not available for Linux :(.

Configure grunt-contrib-jshint options with multiple targets

When linting, different JSHint options are needed for front-end and back-end
JavaScript. We can specify different targets in grunt-contrib-jshint. But
there is something to be careful:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
jshint: {
// Task level options
options: {
jshintrc: './.jshintrc'
},
node: {
// Target level options
options: {
node: true
}
},
jquery: {
// Target level options
options: {
globals: {
jQuery: true
}
}
}
}

I thought the target level options will merge with the task level, but it does
not happen. Need to dig deeper to figure out why jshintrc option is not merged
with JSHint options. A quick fix is to load the JSHint JSON file directly:

1
2
3
4
5
6
7
8
9
10
jshint: {
// Task level options
options: grunt.file.readJSON('./.jshintrc'),
node: {
// Target level options
options: {
node: true
}
}
}

In this case, if jshint:node target was run, the merged options will be parsed
to JSHint.