[Javascript] Something about pinch gestures

Image Credit

pinch-gesture

最近一直在研究如何在 Browser 上支援 Mac touchpad 的 Pinch 手勢,所以有一些心得想要記錄一下。

3rd party libraries

一開始的想法就覺得這種事情應該有什麼 3rd party 套件有支援了,只要簡單的把 event 和現有的程式接上就可以了。不過找了一陣子後,實在是沒有找到什麼好東西,通常大家推的都是 Hammer.js,不過其實這個 library 是專門設計給 mobile app 使用的,看了一下程式碼發現是組合 touch 相關的 event 後再經過數學運算後提供客製化的 gesture event 像是 pinchpan … 之類的。

不過這個和我的使用情境不太一樣,因為 gesture 相關的 event 只有在 mobile 的 browser 上才會存在,因此只能再找找別的方法。

Solutions

之後很幸運的找到了 Chromium 開發者們的討論串,主要在討論的內容就是要如何把 touchpad 上的 pinch 手勢透過 wheel 這個 event 傳出去!那個討論串主要的重點就是在於 2014 年五月之後,Chromium 開發者們上了一個 patch,讓前端開發者可以透過正規的 wheel event (對了,wheelmousewheel 有點不太一樣,前者才是大家公認的標準,後者則是非標準,只有少部分的 browser 有支援,要注意一下)去偵測 pinch gesture 的觸發。當 wheel event 是透過 pinch 觸發的話,那傳進來的 event 的 ctrlKey 這個屬性則會被設成 true,所以開發者們就可以用這個值來做判斷。

而在我們公司裡,因為我們要監聽這個手勢的發生做客製化的視覺處理,而且我們不希望 Mac 上預設的 zoom in / zoom out 還被觸發,所以要記得透過 event.preventDefault() 來避免 Browser 做 zoom in / zoom out 的動作。

Limitations

當然世界沒這麼美好,所以我最後還是整理了一些目前的限制(以後說不定就沒這個問題)

  • Safari
    1. 目前我手上最新的 Safari 9.0.x 版(Mac OS X 10.11.x)是沒辦法透過上面的方法來偵測手勢及取消預設的 zoom in / zoom out 觸發。
    2. 好消息是在未來的 Safari 9.1.x 版後,他們提供了新的 gesture event 讓開發者們可以去偵測手勢,不過這個版本目前也還沒釋出所以也沒辦法測試,如果官方文件沒有唬爛的話那就應該是可以支援,只是這個 event 目前應該也是 Safari only 的客製化 event 就是了,會不會變成 standard 也不知道。
  • Chrome
    1. 在 2014 年五月後的 Chrome 就支援上述做法來偵測 pinch 手勢了!(我很想查 Chrome 的版本號只是不知道怎麼找,如果有人知道那個 patch 實際被 land 到哪個版本的話,請和我說一下)
    2. 個人 Chrome 48+ 實測是 ok 的。
  • IE / Edge
    1. 如果討論串上的資訊正確的話,那 IE / Edge 應該和 Chrome 一樣有支援 ctrlKey 可以讓開發者去做偵測。
  • Firefox
    1. 無解 …
  • Electron
    1. 我有測試過 Electron 0.36.x+,因為他的核心也是 Chromium,所以這個做法也是可以支援的!
    2. 如果你是用 <webview> 的方式來載入你的 web app 的話,那你特別需要先在 render view 的地方聽  wheel event 但是不需要做任何事(超怪,無法理解),這樣這個 wheel event 就會正確的被傳進你的 <webview>,然後你的 webview 裡面如果有實作 event.preventDefault() 的話,那預設的 zoom in / zoom out 行為就會被取消,這樣你就可以在 webview (也就是你的網站裡面處理這件事情就好)

References

附上所有我找到的有用資源如下:

  1. http://jsbin.com/qiyaseza/8/edit?html,css,js,output
  2. https://bugs.chromium.org/p/chromium/issues/detail?id=289887
  3. http://stackoverflow.com/questions/15416851/catching-mac-trackpad-zoom
  4. http://stackoverflow.com/questions/29929411/disable-pinch-zoom-in-webkit-or-electron
  5. https://gist.github.com/NekR/9a80ebe73573e11f0351

[Javascript] TwZip.js

twzip

Github Link

最近因為 Hax4 有 project 需要用到台灣郵遞區號,所以就花了一點時間做了一個簡單的 js (jQuery) plugin – TwZip.js。不過身為一個前端工程師當然想把事情都留在前端處理就好,因此當初在設計這個 plugin 的時候就打算把所有的資料都放在前端,然後以 lazyload 的方式把資料載進來而不需要後端的支援(超懶)。

而說到資料,TwZip.js 的資料是從中華郵政全球資訊網下載來的,然後簡單寫了一個 makefile 搭配 node.js 自動產生數百個鄉鎮市區的 metadata 供前端使用。

這邊要提一個我一直被卡住的白痴問題(OS 老師當初應該把我當掉),因為原本我的設計是三層式架構(像是 台北市/信義區/信義路),但是這會造成資料過度碎片化的問題。之所以會這樣是因為在 file system 裡面最小單位的 block or Cluster 有一個最小容量,像我電腦就是 4 KB,所以如果資料小於 4KB 就還是以 4KB 計,因此這個三層式設計最後就產生出 16X MB 的資料(因為產生出太多 metadata 了)… 整個比原本的專案大上好幾十倍呀 …

為了解決這個問題,最後就改成兩層式架構(像是 台北市/信義區,也因為層數變少的關係所以最後就變成約 4 MB 的資料了,整個就是皆大歡喜。

還記得以前的前輩曾經教過我在寫程式的時候要先把 API 想好,確定使用者使用的介面再開始寫細節,透過這樣的決定來讓整個專案照著預期的方向前進才是比較好的,這樣才可以提前知道這個設計上的缺陷及問題,算是又多了一點體悟吧!

儘管如此,目前這個 plugin 還只能算是一個 prototype ,未來應該會再把 zipcode 的資訊透過 callback 傳回去。其他的功能就再說吧。

DogFooding ++

[Node.js] Difference between module.exports and exports

Image Credit

This simplified Chinese blog tells the details about the difference between module.exports and exports.

The most surprising part of the difference is that you can not use them together at the same time. (I know no one would use it in this way, because you have to make sure the coding style is the same anywhere.)

After testing, if you use these two ways to export modules, defined methods or properties in exports will be discarded directly and only export the ones defined in module.exports.

So I think the best practice here is to use module.exports instead of exports to define your stuffs.

Read More on : Here

[Javascript] performance issues when appending in DOM tree

Image Credit

According to John Resig’s blog, you can see that there is 2x-3x performance better when using fragments.

Take his code for example :

https://gist.github.com/EragonJ/6111312.js

If you use original append to append divs one by one, then you will see the blink on the screen especially when you are going to append a huge list. But, when using fragments, it is another kind of structure to hold these temporary divs and will be appended to the target all together at the same time.

So if one day you have to deal with massive DOM manipulation problems without 3rd party libraries’ help, remember to use it.

Cheeers 😛

Read More on : http://ejohn.org/blog/dom-documentfragments/

[Javascript] Build your own Trip with Trip.js

Image Credit

Demo : http://eragonj.github.io/Trip.js/
Repository : https://github.com/EragonJ/Trip.js

太久沒寫網誌了,所以想說來寫一篇最近比較值得記錄的事情,那就是 Trip.js

什麼是 Trip.js ? 一言以敝之就是「Trip.js is a useful plugin that can help you customize a tutorial trip easily. ( Based on jQuery )」,通常對於 landing page 或是一些需要做  step by step 指導的網站,都會需要這類型的 plugin 來幫助 developer 快速上手,做出需要的效果 ,而剛好之前在公司的時候有類似的需求,所以我就在其他時間自己先行開發了 Trip.js 的初始版,然後分享在網路上。

就目前看來感覺效果還蠻出眾的(在 hackernews & github 上都有一些回響),雖然市面上還有很多類似的 plugin,但是東西是自己寫的那種感覺就是很不一樣,有興趣的 developer 不妨參考一下吧 😛

[Javascript] Some good/bad parts learned from Chrome Extension

Image Credit

Just update my FBBK from version 1.0 to 1.2.1 and think there are some nice features/designs to be noted about Chrome extension.

  1. chrome.storage API

    When using manifest 1, we have to set up a background page  as middleware to communicate between content scripts and localStorage ( used to store users’ selected options ) because the localStorage used in content scripts will be referred to the page localStorage instead of extension localStorage.In this way, developers have to make build up a fake background page to transfer data. But this problem has been solved by chrome.storage API. With this API, we can easily set/get data for content scripts without the help of background page.Better than that, this API can also synchronize data from local to the cloud to solve problems when users using different computers. The most awesome part is that the API would automatically fallback to store data in local if the internet connection breaks !
  2. chrome.i18n API

    It is really important to i18n your extensions/apps if you want to reach the global market ( users ). For FBBK 1.2.0+, I just implemented two locales ( en / zh ). I really like the design that Chrome can automatically detect the right locale to be used  and even falls back to default locale.This API is really smart enough for basic projects but can’t meet more complicated needs. Take FBBK for example, There are many models with i18n needs ( to describe models’ usage, intro … blah ). Because Chrome doesn’t support a good way for me to get the current locale ( can use predefined variable like @@ui_locale in CSS but not in JS  ) , I have to proxy the models descriptions to  use chrome.i18n.getMessage() to get the right locale and match the right message.json ( see the above figure ).

    This is how I do in FBBK :

    https://gist.github.com/4259985.js?file=gistfile1.js

    If you have better ideas to extract models with i18n json, plz comment to let me know !

That’s it ! Have fun on developing chrome extension 😉

[Javascript] Facebook Blocker (FBBK) Still Rocks On

Check : FBBK 的主介紹頁

改變

也許有點老梗,但是最近因為情緒低落,想要參考學徒模式的作法,回到自己的舒適圈,試著找回一些原本稱之為熱情的東西。

其實也是這麼的剛好,因為 Chrome 在版本號 >= 18 後會逐漸遺棄 Manifest V1 的部份實作,提供了更多方便好用的 API 在 Manifest V2(例如說 Content-Script 在 Manifest V1 時,存取 LocalStorage 的限制需要透過 background page 的幫助),其實我覺得是種陰謀啦,畢竟 Extensions 就和 Apps 多如牛毛,所以透過這種手段還可以順便幹掉那些沒在更新的 Extensions … 😄

以下是從  Google 那邊擷取的時程說明:

  1. 2013 Q1

    • The Web Store will remove manifest version 1 items from the wall, search results, and category pages.
    • Notice emails will be sent to all developers with manifest version 1 items still in the store reminding them that these items will be unpublished and providing update instructions.
  2. 2013 Q2

    • The Web Store will unpublish all manifest version 1 items.
    • Final notice emails will be sent to developers with manifest version 1 items still in the Web Store.
    • Chrome will continue to load and run installed manifest version 1 items.
  3. 2013 Q3

    • Chrome will stop loading or running manifest version 1 items.

動機

除此之外,還差一些讓我捲起袖子實作的動機 … 想著想著,我就想到我在使用 Facebook 長久以來的困擾,那就是這個:

沒錯,就是那個該死的「Seen」,這個 Feature 真的是我最痛恨的一點,有的時候就是想假裝沒有看到某個人的留言,但是 Facebook 卻會在特定的情況下 Trigger 「讓別人知道你已經看過留言的事件」,這種行為我真的沒辦法接受 … 隱私這種東西在這個設計之下幾乎是蕩然無存呀!

所以我就參考了一些文章還有 Chrome Extension Request 的機制,為 FBBK 加上全新的 Unseen Feature,可以參考選項設定的擷圖:

結果

經過幾位好友的友情測試之後,Unseen 運作的非常良好,終於可以(和別人站在不同的起跑點了) 在聊天的時候暫時找回那一點點曾經屬於自己的隱私了 xD。

以上就是這一次 FBBK 的更新,歡迎大家提供 feedback !

 

立馬安裝 Facebook Blocker – FBBK Chrome Extension

Updated on 2012/08/11,目前審核通過!

P.S. 其實這一篇是 2012/08/07 的時候就寫好了… 但是因為 Chrome Extension 在做版本更新的時候出了一點問題,所以這個版本的更新要等待工人智慧審核通過之後才會發佈,囧。

原本是想要等更新通過再發這一篇文章的啦,但是因為不知道要等多久(可靠消息指出會到兩三天),所以就先放出這個消息來啦!過幾天會把 FBBK 的更新消息統一到一個 Page ,這樣相關的資訊就可以在那邊一目了然啦!

Thanks All ~ FBBK Still Rocks on !