Thursday, August 31, 2017

Javascript touch events

Javascript has the following touch events:
  • touchstart
  • touchmove
  • touchend
  • touchenter
  • touchleave
  • touchcancel
We usually use the following code snippet to detect touch event support

if ('ontouchstart' in window) {
  /* browser with Touch Events
     running on touch-capable device */

if (('ontouchstart' in window) ||
     (navigator.maxTouchPoints > 0) ||
     (navigator.msMaxTouchPoints > 0)) {
      /* browser with either Touch Events or Pointer Events (from Microsoft, outdated)
         running on touch-capable device */

To support both touch-capable device and desktop mouse input, we can listen to both touch event and click event, something like below

blah.addEventListener('touchend', function(e) {
  /* prevent delay and simulated mouse events */
blah.addEventListener('click', someFunction);

If we need all touch events handling for Mobile web, suggest to check out some open source libraries, like jQuery Mobile, hammerjs, or jQuery-Touch-Events.

Wednesday, August 30, 2017

nginx proxy_pass 502 Bad gateway

I use proxy_pass to proxy local API requests to our dev servers, something like


All of a sudden, it stops working with a "502 Bad Gateway" error in browser DevTool network. However I can access directly using web browser.

It is obvious that nginx upstream fails for some reason. I googled a lot, and most discussions are relating to nginx configuration. However, I didn't change anything to nginx configuration before it stops working. Something happened on api server side?

Yes, our api server turned off TLSv1.0 due to security concern. I checked my local nginx and openssl versions, and realized we have 2 options:
1. Upgrade openssl version
2. Rollback api server changes to allow TLSv1.0

$ /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.0.15

$ openssl version -a
OpenSSL 0.9.8zh 14 Jan 2016
built on: Jan 23 2017
platform: darwin64-x86_64-llvm
options:  bn(64,64) md2(int) rc4(ptr,char) des(idx,cisc,16,int) blowfish(idx)
compiler: -arch x86_64 -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -O3 -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DMD32_REG_T=int -DOPENSSL_NO_IDEA -DOPENSSL_PIC -DOPENSSL_THREADS -DZLIB -mmacosx-version-min=10.6
OPENSSLDIR: "/System/Library/OpenSSL"

How to enable TLSv1.2 in Nignx?

ssl_protocols TLSv1.2 TLSv1.1 TLSv1;

ssl_prefer_server_ciphers on;

Tuesday, August 29, 2017 website goes live

我们使用Google site很快搭建了一个书法网站来介绍华风书社,非常好用,从框架到版面,大概也就1-2个小时的时间,唯一的问题是存储空间有限,手机访问支持不好,在这个mobile first的时代,感觉有点落伍。我们不想去购买G Suite, 所以就将就了。然后去Godaddy买了个域名,配了下DNS就可以访问 华风书社 (

推广网站倒是个头痛的事情,除了传统的SEO优化外,可能最直接的方法就是购买Google AdWords了,但这个每天都要支出的,所以目前不太适合。我们还是看看其他方法,比如多写些blog, 多发布些商家信息,多加些外链。

定搜索关键词也是个头疼的事情,如果有明确的方向或者明确的竞争对手就好些,不然自己就要揣摩用户查找的习惯。我们书社的目的是在旧金山湾区推广书法,教授书法,所以目前定下来的关键词是:湾区 书法。 一个是地点信息,一个是主题,书法学习,书法老师,书法讲座,书法探讨,传统书法等等都有这个主语。



Monday, August 28, 2017

Regexp Lookahead vs Lookbehind

Lookahead means look forwards (to the right)
If the regex is x(?=insert_regex_here), which is positive look ahead, that means "find an x that is followed by insert_regex_here".

If the regex is x(?!insert_regex_here), which is negative look ahead, that means "find an x that is not followed by insert_regex_here".

Lookbehind means look backwards (to the left)
If the regex is (?<=insert_regex_here)x, which is positive look behind, that means "find an x that is preceded by insert_regex_here".

If the regex is (?<!insert_regex_here)x, which is negative look behind, that means "find an x not preceded by insert_regex_here"

The above (?=   (?!   (?<=   (?<! etc are Perl regex syntax - the syntax might be slightly different depending on your flavour of regex. You can also use to play around these two concepts in RegExp.

Tuesday, August 22, 2017

2017 IRA and 401k Contribution Limit

A 403(b) is a retirement plan offered by certain public institutions and tax-exempt organizations.

A 401(k) plan is the tax-qualified, defined-contribution pension account defined in subsection 401(k) of the Internal Revenue Code.

A 457 plan is a type of nonqualified, tax advantaged deferred-compensation retirement plan that is available for governmental and certain non-governmental employers in the United States.

A traditional IRA is a way to save for retirement that gives you tax advantages. Contributions you make to a traditional IRA may be fully or partially deductible, depending on your circumstances, and Generally, amounts in your traditional IRA (including earnings and gains) are not taxed until distributed.

A Roth IRA (individual retirement account) is a retirement plan under US law that is generally not taxed, provided certain conditions are met.

A SIMPLE IRA plan (Savings Incentive Match PLan for Employees) allows employees and employers to contribute to traditional IRAs set up for employees. It is ideally suited as a start-up retirement savings plan for small employers not currently sponsoring a retirement plan.

A SIMPLE 401K plan is a subset of the 401(k) plan. Just like the SIMPLE IRA plan, this is a plan just for you: the small business owner with 100 or fewer employees.

Friday, August 11, 2017

Javascript Keyboard events

Events & event values
There are keydown, keypress, and keyup events. For most keys, browser dispatches a sequence of key events like this:

  • When the key is first depressed, the keydown event is sent.
  • If the key is not a modifier key, the keypress event is sent.
  • When the user releases the key, the keyup event is sent.
In the event object, event.which, event.keyCode and event.charCode are more relating to Javascript programming. 

There is some online testing tool for these keyboard events, for instance

Using this kind of tool, we can quickly detect the keyCode, which, charCode values from keydown, keypress and keyup events.

Cross browser compatibility
However, different browsers might return different keyCode for same character. For instance, IE/Edge browser returns 229 but Chrome/Firefox returns 50 keyCode from keydown event. If we look at below comparison figure, same browser returns different keyCode value from different keyboard events.  One example here is: keypress event, for same @ char, chrome returns 64 keyCode, but Firefox returns 0 keyCode.

Fortunately, jQuery normalize browser difference for keyCode etc. Further more, jQuery recommends event.which over event.keyCode and event.charCode keyboard events.

The event.which property normalizes event.keyCode and event.charCode. It is recommended to watch event.which for keyboard key input. 

event.which also normalizes button presses (mousedown and mouseupevents), reporting 1 for left button, 2 for middle, and 3 for right. Use event.which instead of event.button.

MDN (Mozilla Developer Network) has the following note:

In a keypress event, the Unicode value of the key pressed is stored in either the keyCode or charCode property, never both. If the key pressed generates a character (e.g. 'a'), charCode is set to the code of that character, respecting the letter case. (i.e. charCode takes into account whether the shift key is held down). Otherwise, the code of the pressed key is stored in keyCode. charCode is never set in the keydown and keyup events. In these cases, keyCode is set instead. gives more details regarding keyboard events compatibility landscape across different browsers.

Different Keyboard Layouts
Same character might have different keyCode when using foreign keyboard layouts

Stackoverflow gives some simple solution as below for different keyboard layouts compatiblity:

Use onkeypress to ascertain the correct character code for the key that was pressed. In the event handler, check the event.which and event.keyCode properties:
function whichKey(evt) {
    alert(String.fromCharCode(evt.which || evt.keyCode));

KeyboardEvent.key to the rescue?
Model browsers start to support KeyboardEvent.key which should be used to replace charCode etc. 
The definition of 'KeyboardEvent.key' is in  "Document Object Model (DOM) Level 3 Events Specification" Working Draft (as of August 2017).
Apart from Android browsers, IE11/Edge, other modern browsers have support event.key.

Explore event.key if your web app doesn't need to support legacy browsers.
Use event.which, event.keyCode, and event.charCode wisely in different keyboard events.