Search

2/08/2012

在 git 的 pre-commit hook 裡面檢查 console.log

在 git 的 pre-commit hook 裡面檢查 console.log

在 .git/hooks/pre-commit 中加入以下內容,並 chmod +x .git/hooks/pre-commit。

#!/bin/sh
has_console_log=$(git diff --cached | ack '^\+\s*console\.log\(.*\)')

if [ "$has_console_log" != "" ]
then
echo "ERROR: You have console.log in your commit. Remove them."
exit 1
fi

A Moment of Clarity in the Pursuit of Happiness

A Moment of Clarity in the Pursuit of Happiness

The realization is that my happiness is something that is in my control to create control, something that I can create for myself and manage. What it means and how it works, are still a little hazy for me, but the idea is there, I feel it in my bones.

I’ve recently started reading Flow by Mihaly Csikszentmihalyi, a book which analyzes years of research into happiness. Here’s the quote that captures the thesis:

What I “discovered” was that happiness is not something that happens. It is not the result of good fortune or random chance. It is not something that money can buy or power command. It does not depend on outside events, but, rather, on how we interpret them. Happiness, in fact, is a condition that must be prepared for, cultivated, and defended privately by each person. People who learn to control inner experience will be able to determine the quality of their lives, which is as close as any of us can come to being happy.

The implication being, the quality of your live (and thus, your happiness), is a choice. It’s something that you decide you want, and something you create for yourself.

Here’s another quote from an article I just recently read called Top five regrets of the dying that supported the same argument:

Many did not realise until the end that happiness is a choice. They had stayed stuck in old patterns and habits. The so-called ‘comfort’ of familiarity overflowed into their emotions, as well as their physical lives. Fear of change had them pretending to others, and to their selves, that they were content, when deep within, they longed to laugh properly and have silliness in their life again.

Steve Jobs also shared a similar sentiment during his famed Stanford speech:

And since then, for the past 33 years, I have looked in the mirror every morning and asked myself, if today were the last day of my life, would I want to do what I am about to do today?

I’m trying to internalize this concept and make it a part of who I am. My identity and my thoughts are my own to have, control, and share. Happiness is a mindset for me to create. I find this newfound control over my life comforting since it means I can stop passing the buck and sulking in any form of unhappiness.

A final thought: On average, you have 78 years total to live. The first 18-20 are spent learning, which leaves 58. Spending 2 years doing something you don’t enjoy is a full 3.4% of your life. What are you getting back for that investment? Money? What are you going to do with that money that will be worth the non-refundable 3.4% of your life? An extra room in your house?

Web Dev .NET: Differences Between jQuery .bind() vs .live() vs .delegate() vs .on()

Web Dev .NET: Differences Between jQuery .bind() vs .live() vs .delegate() vs .on()

Using the Bind Method

The .bind() method registers the type of event and an event handler directly to the DOM element in question. This method has been around the longest and in it's day it was a nice abstraction around the various cross-browser issues that existed. This method is still very handy when wiring-up event handlers, but there are various performance concerns as are listed below.

The .bind() method will attach the event handler to all of the anchors that are matched! That is not good. Not only is that expensive to implicitly iterate over all of those items to attach an event handler, but it is also wasteful since it is the same event handler over and over again.

/* The .bind() method attaches the event handler directly to the DOM
element in question ( "#members li a" ). The .click() method is
just a shorthand way to write the .bind() method. */

$( "#members li a" ).bind( "click", function( e ) {} );
$( "#members li a" ).click( function( e ) {} );

Pros
This methods works across various browser implementations.
It is pretty easy and quick to wire-up event handlers.
The shorthand methods (.click(), .hover(), etc...) make it even easier to wire-up event handlers.
For a simple ID selector, using .bind() not only wires-up quickly, but also when the event fires the event handler is invoked almost immediately.

Cons
The method attaches the same event handler to every matched element in the selection.
It doesn't work for elements added dynamically that matches the same selector.
There are performance concerns when dealing with a large selection.
The attachment is done upfront which can have performance issues on page load.

Using the Live Method

The .live() method uses the concept of event delegation to perform it's so called "magic". The way you call .live() looks just like how you might call .bind(), which is very convenient. However, under the covers this method works much different. The .live method attaches the event handler to the root level document along with the associated selector and event information. By registering this information on the document it allows one event handler to be used for all events that have bubbled (a.k.a. delegated, propagated) up to it. Once an event has bubbled up to the document jQuery looks at the selector/event metadata to determine which handler it should invoke, if any. This extra work has some impact on performance at the point of user interaction, but the initial register process is fairly speedy.

The good thing about this code as compared to the .bind() example above is that it is only attaching the event handler once to the document instead of multiple times. This not only is faster, but less wasteful, however, there are many problems with using this method and they are outlined below.

Pros
There is only one event handler registered instead of the numerous event handlers that could have been registered with the .bind() method.
The upgrade path from .bind() to .live() is very small. All you have to do is replace "bind" to "live".
Elements dynamically added to the DOM that match the selector magically work because the real information was registered on the document.
You can wire-up event handlers before the document ready event helping you utilize possibly unused time.

/* The .live() method attaches the event handler to the root level
document along with the associated selector and event information
( "#members li a" & "click" ) */

$( "#members li a" ).live( "click", function( e ) {} );

Cons
This method is deprecated as of jQuery 1.7 and you should start phasing out it's use in your code.
Chaining is not properly supported using this method.
The selection that is made is basically thrown away since it is only used to register the event handler on the document.
Using event.stopPropagation() is no longer helpful because the event has already delegated all the way up to the document.
Since all selector/event information is attached to the document once an event does occur jQuery has match through it's large metadata store using the matchesSelector method to determine which event handler to invoke, if any.
Your events always delegate all the way up to the document. This can affect performance if your DOM is deep.

Using the Delegate Method

The .delegate() method behaves in a similar fashion to the .live() method, but instead of attaching the selector/event information to the document, you can choose where it is anchored. Just like the .live() method, this technique uses event delegation to work correctly.

If you skipped over the explanation of the .live() method you might want to go back up and read it as I described some of the internal logic that happen.

The .delegate() method is very powerful. The above code will attach the event handler to the unordered list ("#members") along with the selector/event information. This is much more efficient than the .live() method that always attaches the information to the document. In addition a lot of other problematic issues were resolved by introducing the .delegate() method. See the following outline for a detailed list.

/* The .delegate() method behaves in a similar fashion to the .live()
method, but instead of attaching the event handler to the document,
you can choose where it is anchored ( "#members" ). The selector
and event information ( "li a" & "click" ) will be attached to the
"#members" element. */

$( "#members" ).delegate( "li a", "click", function( e ) {} );

Pros
You have the option of choosing where to attach the selector/event information.
The selection isn't actually performed up front, but is only used to register onto the root element.
Chaining is supported correctly.
jQuery still needs to iterate over the selector/event data to determine a match, but since you can choose where the root is the amount of data to sort through can be much smaller.
Since this technique uses event delegation, it can work with dynamically added elements to the DOM where the selectors match.
As long as you delegate against the document you can also wire-up event handlers before the document ready event.

Cons
Changing from a .bind() to a .delegate() method isn't as straight forward.
There is still the concern of jQuery having to figure out, using the matchesSelector method, which event handler to invoke based on the selector/event information stored at the root element. However, the metadata stored at the root element should be considerably smaller compared to using the .live() method.

Using the On Method

Did you know that the jQuery .bind(), .live(), and .delegate() methods are just one line pass throughs to the new jQuery 1.7 .on() method? The same is true of the .unbind(), .die(), and .undelegate() methods. The following code snippet is taken from the jQuery 1.7.1 codebase in GitHub...


// ... more code ...

bind: function( types, data, fn ) {
return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
return this.off( types, null, fn );
},

live: function( types, data, fn ) {
jQuery( this.context ).on( types, this.selector, data, fn );
return this;
},
die: function( types, fn ) {
jQuery( this.context ).off( types, this.selector || "**", fn );
return this;
},

delegate: function( selector, types, data, fn ) {
return this.on( types, selector, data, fn );
},
undelegate: function( selector, types, fn ) {
return arguments.length == 1 ?
this.off( selector, "**" ) :
this.off( types, selector, fn );
},

// ... more code ...

With that in mind, the usage of the new .on() method looks something like the following...

/* The jQuery .bind(), .live(), and .delegate() methods are just one
line pass throughs to the new jQuery 1.7 .on() method */

// Bind
$( "#members li a" ).on( "click", function( e ) {} );
$( "#members li a" ).bind( "click", function( e ) {} );

// Live
$( document ).on( "click", "#members li a", function( e ) {} );
$( "#members li a" ).live( "click", function( e ) {} );

// Delegate
$( "#members" ).on( "click", "li a", function( e ) {} );
$( "#members" ).delegate( "li a", "click", function( e ) {} );


You'll notice that depending how I call the .on() method changes how it performs. You can consider the .on() method as being "overloaded" with different signatures, which in turn changes how the event binding is wired-up. The .on method bring a lot of consistency to the API and hopefully makes things slightly less confusing.

Pros
Brings uniformity to the various event binding methods.
Simplifies the jQuery code base and removes one level of redirection since the .bind(), .live(), and .delegate() call this method under the covers.
Still provides all the goodness of the .delegate() method, while still providing support for the .bind() method if you need it.

Cons
Brings confusion because the behavior changes based on how you call the method.


Conclusion (tl;dr)

If you have been confused about the various different types of event binding methods then don't worry, there has been a lot of history and evolvement in the API over time. There are many people that view these methods as magic, but once you uncover some of how they work it will help you understand how to better ode inside of your projects.

The biggest take aways from this article are that...
Using the .bind() method is very costly as it attaches the same event handler to every item matched in your selector.
You should stop using the .live() method as it is deprecated and has a lot of problems with it.
The .delegate() method gives a lot of "bang for your buck" when dealing with performance and reacting to dynamically added elements.
That the new .on() method is mostly syntax sugar that can mimic .bind(), .live(), or .delegate() depending on how you call it.
The new direction is to use the new .on method. Get familiar with the syntax and start using it on all your jQuery 1.7+ projects.

Tinycon - Favicon Alert Bubbles

Tinycon - Favicon Alert Bubbles

我的生日禮物 ◎王文華/撰...

我的生日禮物 ◎王文華/撰...

來源:網路流傳
每個人,在每個人生階段,都可以忙一百件事情,而因為在忙那些事情而從自己真正的人生中缺席。他可以告訴朋友:「我爸爸過世前那幾年我沒有陪他,因為我在忙這個、忙那個。」我相信每個人的講法都會合邏輯,大家聽完後不會有人罵你這個忘恩負義的東西。但人生最難的不是怎麼跟社會交代,而是怎麼面對自己。

爸爸在二○○○年的十二月十七日過世,兩年後的今天,我依然收到他送我的禮物。一九九八年十月,爸爸的左耳下突然腫了起來,起先覺得是牙周病,後來以為是耳鼻喉的問題,最後才懷疑是淋巴瘤。在此之前,爸爸一向是家中最健康的,煙酒不沾、早睡早起、一百七十五公分、七十公斤。

由於淋巴散佈全身的特性,淋巴瘤通常是不開刀、而用化學治療的。但爸爸為了根治,堅持開刀。七小時後被推出來,上半身都是血。由於麻藥未退,他在渾沌中微微眨著眼睛,根本認不出我們。醫生把切下來的淋巴結放在塑膠袋裡,舉得高高地跟我解釋。曾經健康的爸爸的一塊肉被割掉了,曾經健康的爸爸的一部分被放在裝三明治的塑膠袋裡。

手術後進行化學治療,爸爸總是一個人,從忠孝東路坐車到台大醫院,一副去逛公園的輕鬆模樣。打完了針,還若無其事地走到重慶南路吃三商巧福的牛肉麵。我勸他牛肉吃多了不好,他笑說吃肉長肉,我被割掉的那塊得趕快補回來。化療的針打進去兩周後,白血球降到最低,所有的副作用,包括疲倦、嘔吐等全面進攻,他仍然每周去驗血,像打高爾夫球一樣勤奮。

但這些並沒有得到回報,腫瘤復發,化療失敗,放射線治療開始。父親仍神采奕奕,相信放射線是他的秘密武器。一次他做完治療後,跑到明曜百貨shopping。

回家後我問他買了什麼,他高興地拿出來炫耀,好像剛剛買了一個Gucci皮包。

「因為現在脖子要照放射線,所以我特別去買了一件夾克,這樣以後穿衣服就不會碰到傷口。」傍晚七點,我們坐在客廳,我能聽到鄰居在看娛樂新聞,爸爸自信地說:「算命的曾經告訴我,我在七十歲之後還有一關要過,但一定過得去。過去之後,八十九十,就一帆風順了。」他閉上眼、欣慰地微笑。

一九九九年四月,爸爸生病半年之後,他中風了。

我們在急診室待了一個禮拜,與五十張鄰床只用綠色布簾相隔,我可以清楚地聽到別人急救和急救失敗的聲音。「前七天是關鍵期!跟他講話,你們要一直跟他講話。」我跟他講話,他聽得見卻不能回答。我換著尿布、清著尿袋、盯著儀器、徹夜獨白。「你記不記得小學時有一年中秋節你帶我去寶慶路的遠東百貨公司,我們一直逛到九點他們打烊才離開……」我開始和爸爸說話,才發現我從來沒有和他說過話。

爸爸回來了,我不知道他怎麼做到的,但他這硬氣的老小子,真的就回來了。帶著痲痺的半身,我們住進復健病房,腫瘤的治療不得不暫停。任何復健過的人和家人都知道,那是一個漫長、挫折、完全失去尊嚴的過程。你學著站,學著拿球,學著你三歲就會做的事,而就算如此,你還做不到。但他不在乎看起來可笑,穿著訂做的支架和皮鞋,每天在醫院長廊的窗前試著抬腳。

癌症或中風其中之一,就可以把有些人擊垮。但爸爸跟兩者纏鬥,卻始終意興風發。他甚至有興趣去探索秘方,命令我到中壢中正路上一名中醫處求藥,「我聽說他的藥吃個三次中風就會好!」復健、化療、求秘方,甚至這樣他還嫌不夠忙,常常幫我向女復健老師要電話,「她是台大畢業的,我告訴她,你也是台大的,這樣你們一定很速配。」

我還沒有機會跟復健師介紹自己,腫瘤又復發了。醫師不建議我們再做化療或放療,怕引起再次中風。「那你們就放棄囉?」我質問。

醫師說:「不是這麼講,不是這麼講……」

我知道我的質問無禮,但我只是希望有人能解釋這一年的邏輯。從小到大,我相信:只要我做好事,就會有回報。只要我夠努力,就可以得到我想要的東西。結果呢?那麼好的一個人、那麼努力地工作了一生、那麼健康地生活、那麼認真地治療、我們到最好的醫院、請最好的醫生、全家人給他最好的照顧,他自己這麼痛苦,結果是什麼?結果都是bullshit!

「還有最後一種方法,叫免疫療法。還在試驗階段,也是打針,健保不給付,一針一萬七。」

免疫療法失敗後,爸爸和我們都每下愈況。二○○○年六月,他再次中風,開始用呼吸器和咽喉管呼吸,也因此無法再講話。他瘦成一百六十五公分、五十公斤。床越來越大,他越來越往下塌。我們開始用文字交談,他左手不穩、字跡潦草,我們看不懂他的字,久了之後,他也不寫了。中風患者長期臥床,四小時要拍背抽痰一次。夜裡他硬生生地被我們叫醒,側身拍背。他的頭靠在我的大腿上,口水沾濕了我的褲子。拍完後大家回去睡覺,他通常再也睡不著。夜裡呼吸器運轉不順突然嗶嗶大叫,我們坐起來,黑暗中最明亮的是他孤單的眼睛。

一直到最後,當他臥床半年,身上插滿鼻胃管、咽喉管、心電圖、氧氣罩時,爸爸還是要活下去的。他躺在床上,斜看著病房緊閉的窗和窗上的冷氣機,眼睛會快速地一眨一眨,好像要變魔術,把那緊閉的窗打開。就算當走廊上醫生已經小聲地跟我們討論緊急時需不需要急救,而我們已經簽了不要的同意書時,他自己還是要活下去的。當我握著他的手,替他按摩時,他會不斷地點著我的手掌,像在打密碼似地說:「只要過了這一關,八十、九十,就一帆風順了。」

爸爸過世讓我學會三件事。

爸爸過世後的這兩年,我學到三件事情。第一件叫「perspective」,或是「視野」,意思是看事情的角度,就是把事情放在整個人生中來衡量,因而判斷出它的輕重緩急。好比說小學時,我們把老師的話當聖旨,相信的程度超過相信父母。大學後,誰還會在乎老師怎麼說?因為看事情的角度不一樣了,事情真正的重要性就清楚了。在忠孝東路四段,你覺得每一個紅燈都很煩、每一次街頭分手都是世界末日,但從飛機上看,你肝腸寸斷的事情小得像鳥屎,少了你一個人世界並沒有什麼損失。

我的視野是爸爸給我的。我把自己過去、現在,和未來所有的挫折加起來,恐怕都比不上他在醫院的一天。如果他在腫瘤和中風的雙重煎熬下還要活下去,我碰到人生任何事情有什麼埋怨的權利?後來我常問自己:我年輕、健康、有野心、有名氣,但我真得像我爸爸那麼想活下去嗎?我把自己弄得很忙,表面上看起來很風光,但我真的在活著嗎?我比他幸運這麼多,但當有一天我的人生也開始兵敗如山倒時,過去的幸運是讓我軟弱,還是讓我想復活?

有了視野,我學到的第二件事是:搞清楚人生的優先順序。三十歲之前,我的人生只有自己。上大學後我從不在家,看到家人的頻率低於學校門口的校警。我成功地說服了我的良知,告訴爸媽也告訴自己:我不在家時是在追求自己的理想,實踐理想的目的是讓爸媽以我為傲。於是我畢業、當兵、留學、工作,去美國七年,回來時媽媽多了白髮,爸爸已經要進手術房。當我真正要認識爸爸時,他已經分身乏術。子欲養而親不待,我離家為了追求創意的人生,沒想到自己的人生卻掉進這個最俗不可耐的陷阱。

每個人,在每個人生階段,都可以忙一百件事情,而因為在忙那些事情而從自己真正的人生中缺席。他可以告訴朋友:「我爸爸過世前那幾年我沒有陪他,因為我在忙這個忙那個。」我相信每個人的講法都會合邏輯,大家聽完後不會有人罵你這個忘恩負義的東西。但人生最難的不是怎麼跟社會交代,而是怎麼面對自己。我永遠有時間去留學、住紐約、寫小說、「探索自己的心靈」,但認識父母,只剩下這幾年。爸爸走後,不用去醫院了,我有全部的時間來寫作,卻一個字都寫不出來。我的人生變成一碗剩飯,份量雖多我卻一點都沒有食慾。失去了可以分享成功的對象,再大的成功都只是隔靴搔癢。

我學到的第三件事是:承認自己的脆弱。爸爸什麼都沒做,只是一天晚上坐在陽台乘涼,然後摸到耳下的腫塊,碰!兩年內他老了二十歲。無時無刻,壞事發生在好人身上,你要如何從其中註釋出正面的意義?每一次空難都有兩百名罹難者,你要怎麼跟他們的家人說「這雖然是一個悲劇,但我們從其中學到了…」

悲劇中所能勉強歸納出來的唯一意義,就是人是如此脆弱,所以我們都應該「小看」自己。不管你多漂亮多成功,不管你多平凡多失落,都不用因此而膨脹自我。在無法理解的災難面前,我們一戳就破。

爸爸在二○○○年的十二月十七日過世,這一天剛好是我的生日。他撐到那一天,為了給我祝福。爸爸雖然不在了,但兩年來,以及以後的每一年,他都會給我三樣生日禮物。這三樣禮物的代價,是化療、放療、中風、急診、呼吸器、強心針、電腦斷層、磁振造影。他離開,我活過來,真正體會到:誕生,原來是一件這麼美麗的事。

turn.js - The page flip effect for HTML5

turn.js - The page flip effect for HTML5

2/06/2012

Google Chrome Developer Tools: 12 Tricks to Develop Quicker


1. short cut: command + option + I
2. use copy (document.title) to copy text to clipper board.
3. use clear() to clear console text
4. in any tab of chrome developer tool, use 'Esc' to turn on/off of Console
5. highlight element in the 'Elements' tab and use $0 to reference it in the 'Console' , $0 will reference to whatever element is currently selected