[FxOS] Settings App – Dialog v.s. Panel

fxos

In Settings app, we have two different concepts – one is Dialog while the other one is Panel. The main difference between them is how they are presented. From UX spec, if we need users to do some actions and then submit, normally they will be presented with Dialog with cancel and submit button. While for Panel, it is just a simple view that focuses on presenting data and basically you can notice that there is always a “<“ backward arrow in the header that can help you navigate back to previous panel.

63BF65E7-D01A-4934-B67B-D396E067C044

Wifi Auth Dialog

C2C748FE-3B37-4CF1-A0B4-C96DE1767C15

Wifi Panel

If you are going to create a dialog, here comes some notes that you need to be aware of at first. Let’s use Wifi Auth Dialog for example :

[Setup]

  1. You have to register one section element in Setting’s index.html.
    1. <section is=”wifi-auth” role=”region” id=”wifi-auth” class=”dialog”></section>
    2. remember, you need to add one extra dialog class to make sure the section can be applied with right CSS style
  2. Remember to add one more link element in index.html to make sure related sub-document will be loaded.
    1. <link rel=”import” href=”/elements/wifi_auth.html”>
  3. And then, you can follow scripts under settings/js/panels/* to make sure all dialog needed codes can be loaded.

Take settings/js/panels/wifi_auth/panel.js for example, for Dialog, there are some special API you can use and something that you need to know.

  1. In order to pass data back to caller, you can use onCancel and onSubmit function with resolved data. By doing so, caller can use DialogService.show(‘panelId’).then(function(result) {}); to get needed data.
  2. And also, if you want to programmatically cancel or submit, after Bug 1166495 is landed, you can use this.cancel() and this.submit() to achieve this.

For Panel, you can follow [Setup] part above without adding extra class and everything is done ! Based on our design, they share the same interface and there is no much difference between them, just make sure you won’t use onSubmit(), onCancel() and Dialog related API described above, then you are good !

[FxOs] Inter App Communication

之前投了一篇稿在 Mozilla TW 的謀智台客,主要是在探討 FxOS 如何透過 IAC 在 App 間溝通資料,廢話不多說,請看:

iac

在開發 App 的時候,我們有時候需要在App之間傳遞資訊,而今天我們要介紹的主角就是新引入的 WebAPI: IAC (Inter App Communication),有了這個好東西,我們就可以輕易的在 App 間傳遞訊息,以下就用筆者遇到的例子來說明吧:

User story

當使用者拿到 Firefox OS 手機,第一次開機的時候,會自動先開啓 FTU (First Time Use) App 作導覽。當導覽進行到最後一步的時候,會看到這個畫面,可以按下「Home」鍵回到主畫面。

ftu-mobile-627x1024

而在 Firefox OS 平板上,最後一步的導覽畫面會是這樣,但是改透過由螢幕下方往上滑動的手勢回到主畫面:

ftu-tablet-1024x640

大家可能還不是很明白為什麼這個 User Story 下面要使用 IAC,讓我解釋一下。因為在手機剛啟動的時候,我們的 FTU 是一個獨立的 App,而這個 App 是被 System App 所呼叫起來的,兩個 App 之間如果需要溝通,就需要透過 IAC 來傳遞資料。

之所以 FTU App 需要跟 System App 做溝通,是因為「使用者在 FTU 導覽過程中,是無法按 Home 鍵離開的」,但很不巧的這個需求在 Firefox OS 平台是 Tablet 的時候反而變成是一種限制,怎麼說呢,因為對 Tablet 來說,我們並沒有實體的 Home 鍵,因此「Swipe 向上的手勢」就被我們定義成「使用者按 Home 鍵」,但是在先前 Mobile 的需求下,使用者在 FTU 是不允許按 Home 鍵的!!因此這就產生了一個問題,我要怎麼判別使用者現在的情境是:

  1. Tablet 使用者
  2. FTU 已經導覽到最後一步
  3. 使用者可以透過螢幕下方往上滑動的手勢(等同按 Home 鍵)離開 FTU App

這個時候…我們就需要 IAC 的幫助!

IAC , we need your help

這邊要解釋一下 FTU App、System App 及 IAC 的角色。

FTU App 的功用主要是在教導使用者如何初始設定 FxOS 及透過 step by step 的教學來了解如何使用 FxOS 的裝置,所以他可以知道使用者目前的 step 到哪個階段了。

System App 在這裡的功用是在處理使用者按下 Home 鍵時要處理的事情,他只知道目前使用者是不是按下 Home 鍵(在 Tablet 就是 Swipe 向上的手勢),然後依照各個平台做相對應的事情。

而 IAC 的角色就是 FTU App 及 System App 溝通的橋樑,因為 System App 不知道目前 FTU App 是不是到了最後一步,所以自然就無法解除阻擋 Home 鍵這件事情,所以在這個 User Story 下,當使用者來到最後一個 Step 的時候(而且是在 Tablet 的平台),FTU App 就會透過 IAC 和 System App 溝通,然後請求 System App 可以讓我們以透過 Swipe 向上的手勢(等同按 Home 鍵)離開 FTU App。

在 Gaia 我是這麼做的:

In FTU App :

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

從程式碼中可以看到我們透過 app 實體去連接一個 keyword(在這個例子中就是 ftucomms),FTU App 跟 System App 之間就是透過這個 keyword 來當做識別並透過 port 來溝通,我們只需要把東西通通塞進 port.postMessage 做雞精就對了!

聰明的你可能會問,所以 App 只需要隨便用個 keyword 就可以連結並傳東西嗎?當然不行,接收訊息的 App (傳送訊息的不需要)還需要去它的 manifest.webapp 設定如下:

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

這樣子我們 System App 就可以接收來自 FTU App 的訊息了!在 System App 只要我們確定傳送進來的 message 是我們當初預期的 ‘done’ 就可以放行讓使用者可以透過 Swipe 向上的手勢離開 FTU App 了!

不過你可能又會問我要怎麼讓 System App 來接這個訊息呢,這是個好問題。如果你需要透過 IAC 來做資料傳遞的時候,你需要使用 mozSetMessageHandler 來掛載相對應的 Handler。

下面是 IAC 的基本使用方法:

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

但是要注意的是因為這個 API 只會執行最後一個掛上去的 Handler,所以當你一個 App 要做多組 IAC 資訊傳遞的時候就需要自己做額外的處理。

但在寫程式的時候沒注意到件事情,所以當時 Music App 的另一個 contributor – Jim Porter 同時也自己在 System App 建立了一個 Handler,而我的 Handler 又是在他建立之前建立的,因此所有我 FTU 有關的 Handler 不會執行到,因為通通都被它的 Handler 蓋過去了。

所以為了讓後面的人不要發生這個問題,之後就和 Jim Porter 討論出一個 IACHanlder,每個 App 只要引入這段 javascript ,我們就會自動幫他建好一個共用的 Handler,所有的資料都是這個 Handler 統一管理,然後以一個固定的 naming 用 Custom Event 的方式傳播出去,讓有需要的人可以自己接 Event。(有興趣了解實作的人可以看這裡

所以最後 System App 只要用這樣簡單一行程式碼就可以接 Event 然後做解除限制的動作了:

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

是不是很簡單呢!希望這篇能夠幫助到也需要使用 IAC 的開發者朋友哦 🙂

參考資料: Inter App Communication wiki 文件

[FxOS] Deep into Template.js

Image Credit

fxos

因為最近開始接觸很多 FxOS 核心的程式碼,所以發現了很多精鍊的程式碼,其中有一個很有趣的是 Template.js。

市面上有一大堆 Template engine,基本的功能該有的都有,幾乎都大同小異。但是 FxOS 自己的 Template 卻相當吸引我的注意,因為他才短短的一百多行就實作了一個 Template engine 該做的所有事情(這邊只討論 Search then Replace,不考慮 inline logic )而且有一個很關鍵的事情,就是他巧妙的解決了 Template 存在性的問題。

通常一般 Front-end 的 Template engine 都有一個問題,那就是要把 Template 存在哪裡?

Way 1 – by myself

愛用 jQuery 的我通常都是這樣做的:一開始先透過 selector 把 template 載入(一般都會 cache 住,只是我這個範例沒有特別寫這一段),而這個 template 本身會搭配一個 hide 的 class 避免一開始頁面在 render 的時候會被使用者看到,最後利用 sub-selector 把相對應的地方換成新值,最後再拿掉 hide class 並塞到 DOM tree 內。

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

恩,整體看起來好像還不賴,整個 code 簡單好懂,也做了 template cache(我沒特別寫,但是通常都會被我 cache 到某個 Controller 下),後續維護也只需要加上相對應的 selector 然後替換值就好了。

Way 2 – by Handlebars.js

雖然 Way 1 已經很好了,但是有時候需要 toggle hide class 其實還蠻麻煩的,能不能不要把 CSS 和 Template 扯在一起?有了這個想法後,我就開始到處尋找可能的做法,最後找到了 Handlebars.js,他巧妙的利用 Script tag 做到這件事情:

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

它的作法是去改變 script tag 的 type,你可以看 w3c 上面的說明,只要 browser 看不懂 script type 的話,它一致都會把它 render 成 text,又因為 script tag 本身就不會被 render 出來,所以就達到把 template 藏起來的效果,最後只要搭配 selector 去把它拉出來然後替換值就可以了。

Way 3 – by Template.js in FxOS

雖然 Way2 感覺起來好像不錯,但是利用 script type 這種 hack 的方式感覺有點不是這麼優雅,因為 Template 的東西本來就不該存活在script tag 內,到底還有沒有別的辦法來做到這件事情呢?

有,我在 Template.js 找到了。

http://gist-it.appspot.com/https://github.com/mozilla-b2g/gaia/blob/0a0dcb5a12d70ccd07edfd7c1392cdbf24f6febc/shared/js/template.js?slice=41:53

從程式碼我們可以發現他會一直去尋找所有的 sibling 直到找到整個註解,在 HTML 裡面,註解就是 <!– –>,所以一開始很巧妙的,我們的 template 就是被註解起來的,也就不會被使用者看到內容,也因為一開始就看不見,所以我們就根本不需要去做 CSS 的視覺欺騙,整個就是把 nodeType 利用到極致,使用先天的特性漂亮的解決了這個問題,也就產生了這個 Template.js 。

很有趣吧,有興趣的人可以去看 Template.js 作者 Rick 的 Github,其他的就讓我們留到下次再來分享吧 😛

[Hack] 2012 – Node.js Knockout

Image Credit

這是我第一次參加 Hackathon,雖然平常也沒什麼特別在寫 Node.js,頂多只有用 Express.js 試著架一些小東西來玩玩而已,不過還是憑著一股衝勁和 @bu 以 hahahaha ( hax4 ) 的名義參賽。說真的,我們也只有特別約出來吃一次飯,然後討論看看有什麼有趣的東西可以做,就在一陣東刪西減之後得到了一個明確的主題,那就是要做一個可以「動態捕捉使用者在網站上的各種行為」的外掛,同時還可以把資料記錄下來再做一個重播的動作,讓 Host 知道用戶在使用網站時的各種行為(目前是記錄 Click 和 mousemove 兩種)。

而我們的作品就是 Capturer !

很開心的就是這個 Idea 被大家所認同,所以最後得到第二名的成績!這一切都要感謝強者我隊友強大的後端實作能力,我只負責前端的行為記錄、呈現還有和後端溝通,還有研究 nodejitsu deploy 的一些細節而已,整個就是微不足道的小廢角。

廢話不多說,我真正想講的是這次 Hackathon 教我的東西:

很多時候,我們都眼高手低並空談著許多名為夢想的東西,同時卻又因為現實的工作的壓迫壓力而抹滅掉熱情,所以這種時候透過比賽這種強制手段來逼自己成長與學習了,一個兩天的比賽換來一個作品的 prototype ,同時也測試著這個團隊的合作能力,整個就是 Target-driven(動機導向) 的開發模式呀。

最後,Capturer 的使用方式還有介紹就麻煩到 神人的 Blog 去看啦,我們會努力在明年讓這個系統上線的,加油 !!

 

[Note] Mongodb – tiny and elegant database

Image Credit  :  1 , 2

最近在開發一個分享書籍資訊的服務,因為想要試著單靠 JavaScript 去征服這個世界,所以我就選定了以下的開發環境及工具:

  • Node.js ( server side javascript )
  • Express.js ( web framework based on Node.js )
  • MongoDB

因為書藉的資訊在這個服務中沒有太大的關聯性,同時我也懶得搞一個複雜的資料庫出來,所以在大量的 Survey 後,我發現 MongoDB 很適合當這個服務的資料庫後端 。

使用原因

所謂事出必有因,我特別列出幾個它吸引我的原因如下:

  1. JSON-style documents
    Document 在 MongoDB 裡的名詞定義就是一組一組的資料集合,而它有一個很棒的特色,就是所有的 Document 都是以 JSON 的風格存儲 ,所以在存儲資料的時候可以很方便的統一格式。
  2. Dynamic Schema
    我們在操作資料庫的時候可以不用操心 Schema 的問題,因為 Collection (等同於 RDBMS 中的 Table)的 Schema 是在你存入 Document 的時候依其型態決定的,所以還可以做到同一個 Collection 的 Document 有不同的資料型態(雖然這通常不會是我們允許的情況,但是做的到)。
  3. Easy Querying
    在操作 MongoDB 的時候,我們可以不用和一堆複雜的 SQL 語法打交道(如: CREATE TABLE / ALTER TABLE …),而是透過多個 Query Object 來存取資料,所以這對於熟悉 JavaScript 的開發者來說,真的是很直覺的操作方式。

善用 Modules

而在開發服務的時候,為了找到好用的 Node Modules 來操作 MongoDB,我就到處在 npm 尋找可行的 MongoDB modules,但是幾本上都不方便使用,光是原生的 MongoDB-native 也因為要寫一堆 callback function 而被我打槍…

就在萬念具灰的時候,我發現了一個名為「Mongolian」的 Module。

比較 Modules 差異

不用一段 Source Code 很難明確的點出 MongoDB-native 和 Mongolian 的落差,所以先來看一段 VCR(註解在程式碼裡):

https://gist.github.com/2957876.js

如果你還看不出 MongoDB-native 的 callback 大軍的話,那再看另一段從官方範例中完整取出的 VCR:

https://gist.github.com/2957935.js

這真的是太噁心了,我實在是沒有辦法使用這一串 callback 海來操作資料庫,所以我最後選用了還在這個還在開發階段中的 Mongolian,不單單只是因為操作簡單,還因為它完整的提供了和 MongoDB shell 一樣的操作流程,這對開發者來說真的是好事呀,這就是所謂的一魚兩吃!

Mongolian DeadBeef is an awesome Mongo DB node.js driver that attempts to closely approximate the mongodb shell.

而使用方式就不詳述了,因為這個去看 Document 還有 Example 甚至是多玩幾次 MongoDB shell 就會了,就請自己多方嘗試吧。

BSON ObjectId

我還要特別記錄一下這個叫做 ObjectId 的東西,如果你仔細去印出存在於 Collection 中的 Document 的話,你會發現每一組 Document 都會有一個 _id 的欄位存放著 ObjectId,原先我單單以為這只不過是一個類似 unique id 的機制,可以讓你明確的區分出各個 Document ,結果我錯了,因為他還有更深層的含意在背後。

BSON ObjectId 是一個大小為 12 bytes 的資料型態,從下表可以看出他每個資料區段所代表的意義。經過我的研究後發現,後三個資料區段主要是在提供 ObjectId 的獨特性以避免 Collision 的情況發生,所以其實並沒有太大的實質意義,真正特別的是 time 那個資料區段。

TimeStamp. This is a unix style timestamp. It is a signed int representing the number of seconds before or after January 1st 1970 (UTC).

WTF,他們聰明到把 Timestamp 藏在一個原本只是為了 Uniqueness (唯一性) 而存在的欄位,不僅因為 Timestamp 本身就具有唯一性,還具有實質上的意義呀!如果我們的 Document 存的是使用者的個人資訊,那你的 ObjectId 本身就代表著這個使用者創立帳號的時間,你就不需要再另外設計一個多餘的欄位來做這件事情,你只要這樣做就可以得到這個資訊:

o.getTimestamp() // ISODate("2012-06-20T03:40:58Z")

是不是很驚人?對我來說,真正驚人的是它背後的設計理念,這就像是 reCaptcha 為 Captcha 附予附加意義一樣,讓原本的惱人的 Captcha 驗証行為變成利用眾人的智慧去辨識無法辨別的古書,改變了原本被視為理所當然的事物,同時也附予其更深層的意義。

這才是所謂的「創新」,在你附予那些被視為理所當然的事物更深層意義之後。

以上就是這次的記錄,下次我們再來更深入了解 MongoDB 吧!

[Memo] 6lurk part – musicAnalysis

最近專題已經到了最後階段了,儘管如此,一天的工作量還是來到了12個小時左右。不過最令人開心的莫過於花兩天密集的Hacking把音樂回饋機制給實作出來了,說實在的自己自從暑假經歷兩個月的前端洗禮之後,至少變得比較了解「一點點」Javascript及jQuery了,也比較有能力可以做出符合自己期望的東西。

第一次用 javascript+Youtube javascript API + jQuery做出一個音樂播放器,而基本的輪播、單曲重播、上下曲切換…等功能都有了,只是歌曲的部分是我們分析使用者在Plurk上面的情緒後(星期一到星期日),利用自訂好的類別搭配 last.fm API 來得到該類別下當紅流行的top20首歌曲資訊,然後我們再從Youtube上面抓到最相關(因為它們串流檔這麼多,所以我們只找最相關的那一個)的影音串流回來,最後組成我們播放的卡帶,就可以任君挑選啦!

也許大家會覺得這種類型的網站不是很多嗎?那我們為什麼還要再做一個類似的應用?當然是有原因的,因為並沒有一個網站(可能是我不知道),會依照他的用戶提供量身訂做的音樂,而我們一來使用最接近使用者的社交資料來當做分析的來源,二來是利用一些統計上的分類來把我們量化過的分數幫使用者做一個情緒上的分類並提供相關的歌曲,如此一來當然能夠給予使用者最貼近當下情緒的音樂啦。

而我們團員自行測試後發現,其實我們自己都有類似的需求,因為時常都不知道要聽什麼歌,只是希望能夠像聽廣播一樣打開就可以聽到歌,然後不想聽的時候關掉就好,是一種心境上的自由,也不要有太大的負擔,這樣子不是很好嗎?在這邊我要和大家介紹一個啟發我很大的網站StreamDrag,它也是一個利用Youtube為資料來源的音樂播放網站,它有一個很棒的哲學(Philosophy),也很貼近我們設計的理念,在這邊引用這段話來為整篇文章做個結語。

Music amazes, music creates emotions and music pushes emotions.Music is the language of the world and thats why it should be available wherever you are. Therefore our biggest aim is to make music available wherever it is possible as simple as possible and to create new, innovative ways of listening.

[News] Google Maps, Like YouTube, Get Instantized

原文 From TechCrunch

From techCrunch

「Gmail Instant」也許真的很有用,但什麼是Google下一個目標?「Google Calendar Instant?」還是「Google Image Search Instant?」好吧,這些設計也許真的也很有用。事實上,這真的很難想像即使是即時化服務也不會讓Google從中獲得少許利益。

啟發於Google Instant的服務及 Feross Aboukhadijeh 這名工程師因為製作了「Youtube Instant」的實驗性質的網站而得到Youtbue工作機會的故事,美國阿拉巴馬州籍的開發者- Michael Hart 使用 Javascript Library – jQuery 及 Google Maps API 打造出了一個輕巧好用而且會更新全世界各地資料的「Google Maps Instant」。而就和故事中的Feross一樣,Hart也剛好也正在尋找工作:P。

依 Michael Hart 的說法,這個即時化的介面會即時地預測你想前往的地方並產生秀出即時搜尋結果,而他所設計的這個服務則是花了4小時及193次的改版才打造出來的(他目前也正努力和Google Maps 上的圖標有關的問題,及使用iPhone或Andorid手機瀏覽時的一些功能)但是雖然可以使用 Google Maps Instant 來查詢你正要去哪裡是一件很酷的事情,但是我不認為Google Maps Instant能夠和Youtube Instant有一樣的機緣就是了:P。

【評】

Instant這個想法其實並不新穎,也有很多實作的例子,最常看到的例子就是使用者在註冊時的密碼強度測試,如下圖:

所以這個東西實作並不困難,網路上都有許多的例子都可以用Ajax的方式來達到這個目標,那既然如此,到底是難在哪裡?難就難在他搜尋的資料量太大,而非同步互動的時間相對卻要縮短,而且秀出的結果還要依使用者們的習慣依序排出。要做到如此困難的事情除了在演算法要下大量的功夫之外,還需要許多方面的支援才做的到。

僅管如此,Instant在UI上是一個很重要的互動模式,能夠即時讓使用者了解到目前的Query是不是會產生預期的結果,雖然在背景下增加了一些Query的次數,不過對於具有強大財力背景的Google來說,如何讓使用者開心才是最重要的事吧:P

[Hax4] Rainbow

測試頁面:在這、專案資訊:在這

這幾天因為心血來潮,想說來練習一下pure javascript,所以就都不用jQuery來做事情(雖然最後還是有用,不過我只用來做特效而已XD)。這個Idea其實是源於我以前做的一個很爛的liu-translator,它只能單方面做字根對字的轉換,所以就想說利用Ajax的概念來實作一個線上的IME,因此我就去找了之前Luke的網蝦米來研究他的UI介面。

研究了一下後就開始著手動工整個JS的架構,邊看深入淺出Ajax邊試著實作他說的一些思惟,像是要怎麼寫的很MVC,所以就開始學著把程式切成粗略的「資料」、「模組」、「樣式」三類,雖然之間還是有些耦合性,但是比較以前的我,這次的實作算是很成功的分離了。

之後又想到行易公司的練習嘸蝦米的打字程式一直沒有跨平台,只支援該死的M$,所以為何不幫他們設計一個Cross Platform的Web Application?反正只要解決Cross Browser的問題就可以了,雖然我在Cross Browser這條路上只是一個剛入門的新手,但總比Cross Platform好多了吧…因此就把分離完的架構再修改,改成有點像是遊戲的小程式。

原本已經接近完工的狀態了,但是Bu因為是「大新倉頡」的愛好者,所以就給個建議要我加入的其字根對應表,去擴充可支援的輸入法,就又經過了一場編碼和正規表達式的戰爭後,終於把切換輸入法的功能也加上了,這完全要歸因於先前的MVC架構,讓我能夠在很短的時間完成這個動作。

最後一個也是最重要的啦,為了提高遊戲性,我設計了一段可以自動去抓使用者給定URL的頁面回來,把該頁面上所有符合UTF-8繁體中文的字全部抓下來當成題目,這又比起以前行易公司設計的那些題目多了一些趣味。多了這個設計,你還可以邊看Yahoo!奇摩新聞邊練打字咧!!

附上程式截圖:




§2010/05/13 補上程式的Demo連結,原來我都沒有放出來= = ,舊的在這,新的在這
§2011/02/05 更新連結、圖片、介紹。