今天來介紹一下 新的版面配置模組 Flexbox

Flexbox 的存在是為了讓大家設計更複雜的網頁配置,而他最實用的地方在:

  1. 即使各種螢幕和瀏覽器視窗大小不同或改變時,元素的位置大小仍然保持一致。
  2. Flexbox 可以減少對浮動的依賴,要讓浮動的元素保持正確的位置或大小處理實在是一個令人頭痛的問題。
對於不論是 前端或是網頁設計師來說 真的是一個好消息。



Flex Container 的屬性有下列幾種:

flex-direction ( 指定在容器內子元素的配置方向 )
  • row ( 預設 ) : 子元素會以來源文件宣告順序由(左至右)的排列方式顯示。
  • row-reverse : 和 row 一樣的排列方式,可是方向。
  • column : 子元素會以來源文件宣告順序由(上至下)的排列方式顯示。
  • column-reverse : 和 column 一樣,可是方向相反。
範例 : flex-direction : column;


justify-content ( 指定在容器內子元素的配置位置 )
    • flex-start ( 預設 )
    • flex-end
    • center
    • space-between
    • space-around
    範例 : justify-content :cetner ;



    *這邊要稍微解釋一下 flex-start,flex-end,center,space-between,space-around 的配置位置。(借用國外大大的圖)





    align-items ( 和 justify-content 呼應的屬性 指定在容器內子元素的相對於側軸的配置位置 )
    • flex-start ( 預設 )
    • flex-end
    • center
    • baseline
    • stretch
    範例:align-items:center ;

    *再次解釋一下 flex-start,flex-end,center,space-between,space-around 的配置位置。(再次借用國外大大的圖 XD)






    flex-wrap ( 指定子元素根據容器中的空間換行或成多欄 )
    • nowrap ( 預設 ) : 子元素不換行。
    • wrap:子元素會換行顯示。
    • wrap-reverse : 子元素會換行顯示
    範例 :flex-wrap : wrap ;


    align-content ( 會更改 flex-wrap 的行為,與 align-items 相似,請參考上面 )
    • stretch
    • flex-start
    • flex-end
    • center
    • space-between
    • space-around


    flex-flow ( 是 flex-direction 和 flex-wrap的縮寫 )
    • flex-flow : [flex-direction] [flex-wrap]


    Flex Items 的屬性有下列幾種:

    order ( 顧名思義就是用來調整 子元素的順序 )

    範例 :


    margin (相信大家對 margin:auto ; 的用法相當熟悉,不過在 Flexbox 的 margin 確可以做出另大家期待已久的 真 - 垂直置中 !!!!)

    範例 :


    align-self (側軸對齊,會覆蓋父元素 align-items 的值,他的屬性與 align-items 一樣 請參考上面)


    flex (彈性元素)

    • flex : [ number ]
    • flex : initial  (在有剩餘空間下不會有任何變化)
    • flex : auto (根據主軸自動伸縮佔用剩餘空間)
    • flex : none  (任何情況都不會伸縮)
    範例 1: 第一個子元素佔用 1/2 空間 , 剩下兩個子元素各佔 1/4 的剩餘空間。


    範例 2:將每個子元素設置為1,剩餘空間就會平均分配。




    結論 :

    用 Flexbox 來配置版面看起來思考的方法要不太一樣,但也因為他很強大,相信會是未來用作規劃版面的趨勢。

    參考資料 (http://www.w3.org/TR/2012/WD-css3-flexbox-20120322/)







    Evernote API + Evernote  == Application's Online Storage !?

    如果您正在開發應用服務, 需要穩定的資料儲存空間, 以及跨平台讀取資料的需求,
    或許 Evernote 是一個不錯的選擇 !! 因為...
    • 資料存放在Client端無法備份, 自己架Server又需付出額外成本
    • Evernote 提供了相當豐富的 API, 可以讓開發者透過API 存取在Evernote Cloud 上使用者所存放的資料
    • 透過 Evernote 跨平台的同步機制, 又可讓資訊自動同步到各個裝置

    本篇文章是敘述如何透過 Evernote API 取代應用程式所需的後端服務
    Client 端的APP 則以 Evernote SDK for iOS
    為範例 https://github.com/evernote/evernote-sdk-ios.git


    初期設定


    A. 申請一個Evernote APP, 獲得 Consumer Key and Consumer Secret

    B. 申請一個Evernote Sandbox Server的帳號, 接下來APP測試都先指定到 Sandbox

    C. Client端設定 ( Evernote SDK for iOS )
    - Evernote Session 建立
    - Evernote Login
    - Check Login Status

    存取資料


    Evernote 的資料存取方式, 如下圖所示, 最上層是Notebook (如資料夾) 存放著多個Note
    我們可以假設 Notebook = Table , 而 Note = Record 而進行資料儲存

    A. 新增Notebook ( Crate a Table )

    B. 新增Note ( Insert a Record )

    除了 Evernote 的 Note 基本欄位可使用, 我們也可以使用 Resource, Resource Attributes 去存放更多我們想要的資訊, 如圖片, 網頁文件, XML等
    參考文件連結 : http://dev.evernote.com/documentation/reference/Types.html#Struct_Note

    進階功能


    A. 內容縮圖
    Evernote會針對每一個Note文件都會進行縮圖, 即使文件裡存有圖片, 也會一併產生一個圖檔
    對有些需要顯示縮圖的APP來說十分方便
    但是該圖檔並不是Public的, 需要每次 Request

    B. 搜尋文件
    可以透過Evernote 強大的搜尋引擎, 針對Note裡面的文字進行 Keyword 搜尋
    或是透過文件的Tag, 直接搜尋某些Note
    搜尋Filter 說明 : http://dev.evernote.com/documentation/reference/NoteStore.html#Struct_NoteFilter
    C. 文件排序
    Evernote 也提供了一些方式針對搜尋結果進行排序, 如Crate Time, 相關性, Title, 修改頻率等
    參考文件 : NoteSortOrder

    結論


    Evernote提供了非常強大且實用的後端服務, 透過Evernote API, 我們可以新增, 修改, 搜尋, 縮圖...等
    當然除此之外, 由於該文件儲存在 Evernote 的 Cloud, 這些資料還會因Evernote的同步機制,
    同步到您的各個Evernote Client 如手機, 電腦等
    若您不想再自己Host Server 做Database, Search Engine....
    利用Evernote的Cloud做後端的Database, 或許也是不錯的選擇 !

    前陣子剛好需要串金流,原本考慮台灣著名的紅藍綠(紅陽藍新綠界),但後來考量到後續可能會需要跨國、發票、稅務等問題,最後還是選擇 PayPal。

    Paypal是個相當強大的金流服務系統,開放的API,相當完整的文件,以及眾多的 3-party或官方的SDK,只是還是一句老話,好的系統是演化來的,也因此很容易造成歷史包袱(誤)。

    如果有去查過 Paypal的相關 source可能會常常看到 IPN(Instant Payment Notification),以及 PDT(Payment Data Transfer),兩種各有不同的需求,但我們所需要的就只是「線上信用卡付費」,只有一種商品一種售價,收費方式也不僅限於信用卡,另提供轉帳服務,在這種狀況下如果要花時間下去串完整的金流C/P值有點低,還好PayPal有提供更簡單的方式「Buy Now Buttons」。

    產生Buy Now Buttons簡單來說有三種方式,以下會再針對這三種方式特別來說明

    Paypal網站產生
    (※可能會因為Paypal網站改版而UI位置調整)
    step 1.註冊Paypal(註冊流程不再多加敘述,只是記得別選"個人")


    step 2.點選「個人檔案」


    step 3.點選「更新」


    step 4.「建立新按鈕」


    step 5.建立按鈕詳細訊息(以下為三步驟同時展開,其中比較重要部分已圈選起來)


    step 6.複製HTML貼到網站中或Email給會員,右邊為此HTML貼上後顯示效果



    URL 產生
    使用URL產生上方Button的功能,也就是直接連至付費頁面,Sample如下
    https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=herschelgomez@xyzzyu.com&item_name=Hot Sauce-12+oz.+Bottle&item_number=12345&amount=5%2e95&currency_code=USD

    較為重要如下,可依照個人需求而改變
    • business=herschelgomez@xyzzyu.com -> 需要匯入的Paypal帳戶名稱
    • item_name=Hot Sauce-12+oz.+Bottle -> 商品名稱
    • item_number=12345 -> 商品編號
    • amount=5%2e95 -> 售價
    • currency_code=USD -> 貨幣代號


    HTML 產生
    使用HTML自行產生付費按鈕,其中"YOUR_"開頭的部份就是需要填入的內容


    相關連結
    Paypal官方網站 - http://www.paypal.com
    Paypal Developer - https://www.x.com/developers/paypal




    Realtime 又名即時性,在這個資訊爆炸的時代尤其重要。為什麼會這麼說呢?因為海量資訊的產生,使得人們對於冗長的事物失去了耐心,取而代之的是「快且精準」的需求,而這個層面不僅僅只於閱讀,更衍伸到 UX( User Experience 又稱使用者體驗 )的領域去。

    其中最經典的例子,莫過於 Mike Krieger (Co-Founder of Instagram)對於 Instagram mobile app 上傳流程的設計:


    這個改變看似簡單,但其背後卻存在著更多細節需要實作,在做進一步討論之前,我們就先估且稱這個改變叫做「前端欺騙(Front-End Cheating)」吧。

    以剛剛的流程為例,在後端的設計就可能需要額外設計一個 Image Pool 來暫存這些無人認領的照片孤兒,直到該使用者「完成了整個上傳流程」才會把這張照片指定給他。而對前端來說,就必須捨棄原本的流程,從「拍照→濾鏡→填寫資訊→上傳→結束」改變成「拍照→濾鏡→上傳→填寫資訊→使用一個 identifier 告訴 backend 更新照片資訊→結束」。

    不過,以上只是最理想的假設,因為現實生活中還多了許多變數,特別是在 3G 網路的不穩定性還有 app 與 desktop program 設計上的差異,使得上傳的流程不如以往的順利及穩定,造成許多中斷及錯誤的可能,所以在 Error Handling 的部分還要做額外的處理。

    對 Instagram 來說,它還需要再設想幾個情境:
    1. 使用者已經上傳完照片,卻在最後一個時刻按下 Cancel 鍵取消了所有動作,那該怎麼辦?
    2. 當「前端欺騙」後,卻從 backend 發現先前的上傳失敗,那該怎麼辦?
    以情境 1 為例,舊流程是完全不會有這個問題(因為根本沒有辦法讓你中途取消),但是在新流程卻發生了,不過解法也很簡單,就是透過 identifier 告訴後端,從 Image Pool 幹掉這張照片就好了。

    而情境 2 就比較麻煩,雖然新舊流程都需要處理上傳失敗的 UI 設計,但是對新流程來說,我們還要特別處理掉原本因為「前端欺騙」所留下的 UI ,又多了一個要考慮的細節。

    除了 Instagram 這個經典上傳照片的例子外,還有一個更常看到的就是 Facebook Like。

    對 Facebook 來說,他們處理的是更海量的資料(從別人文章得到的數據是一天約 27 億個 Like),所以更需要這種「前端欺騙」的動作來滿足使用者,而 Like 就是一個很好的例子。對使用者來說,Like 是一種 … 該怎麼說,是一種食之無味卻又棄之可惜的東西,他的出現讓資料庫又塞了更多無用的資訊(27 億個 Like per day ),但是卻又可以為不想發言的使用者傳達「我有看過了」、「很棒」…  的意義。

    這種類型的資料特別適合透過「前端欺騙」的方式來處理,怎麼說呢?因為你可能只是當下想表示一種「認同」,但是資料的正確與否你就不會特別在意,舉 Michael Jackson 在 Facebook 上隨便一則 Post ,就會出現像是「You and 177,449 others like this.」的字眼,但是你真的會很在意 others 是哪些人嗎?通常不會,因為你真正在意的,通常是「你」和「你朋友」而已,其他陌生人 Like 與否相對就沒有這麼重要了。如果真的這麼重要,Facebook 也有做分頁載入(以 Infinite Scroll 的方式實作)的機制,你頂多看前一兩百個陌生臉孔也就不想再看下去了,遑論是那第 177,447 人呢?

    所以就我個人的觀點來說,Realtime 意指的「即時」並不是資料傳輸的即時,而是對於 UX 的即時反饋。而文章標題所謂的衝擊,則是人們對於這一個領域的重視,一個被眾人遺忘已久的枝微末節。


    當大家寫好程式,準備打包安裝檔或者佈署至Server時,通常都怎麼做?

        10多年前,筆者還在研究所打工寫專案時,都是透過壓縮軟體(WinRAR或WinZip),壓縮成一個一個的zip檔,然後再copy至server。

        後來開始工作後,接觸版本控制軟體,如Microsoft VSS或SVN後,就改成直接到Server Check out最新版本的程式。以上兩種傳統方法都很簡單也很方便,但其實有更好的選擇 - Build System

    何謂Build System? Google以下幾種關鍵字就可以大致了解。
    "Build Automation"
    "Build System" 

    一般的Build System通常都包含以下以個步驟: (wikipedia:http://en.wikipedia.org/wiki/Build_automation)

    1. 編譯原始碼
    2. 打包編譯後的結果
    3. 進行測試 (通常指的是Unit Test)
    4. 佈署到上線的機器
    5. 製作版本說明文件


        以上這幾個步驟都是參考,不一定要全部做完才是build system. 以筆者創業團隊而言,並沒有這麼多時間去製作自動產生的release note,而且build完之後,也不能直接上線,必須要至測試機器進行測試,確定沒有太大的bug,才進行佈署(deployment)。

        雖然了解什麼是build system,但為什麼要做這件事情?創業光是想出idea,快速開發出來,隨時想改就改,哪有時間去做啥build system?在此提一些個人的看法:

    • 其實做一個build script只需要不到半天的時間,但卻可以重複使用。
    • 以往程式有一些環境變數,例如測試資料庫跟正式資料庫的IP不同,但不想寫死在程式裡面
    • Server有Javascript跟CSS的程式,需要做minify,但又不想開發時就做,這樣很難Debug. (做過的人就能體會)
    • 程式碼coding convention檢查。一人開發就算了,但如果有兩三個同伴一起開發,總是要先談好coding的風格。但是透過code review檢查又太浪費時間,code review應該是要抓出更有意義的問題才對。
    • 打包的目錄結構跟寫程式的目錄結構可能是不同的 
    • 隨時都可以rollback到某一個版本,尤其是流量大的網站


        以上僅列出一些常遇到的問題,但build system可不只這些,例如compile code時,要先執行一些指令,或者執行單元測試前,需要restore DB,這些都是可以透過build system來做到。

    本篇分享後段,會分享一個小小的build script,也是我們正在使用的build script. 

        大致了解Build System之後,那怎麼開始呢?當然是先選擇build tool來實作囉!以下是筆者接觸過的程式語言跟可以用的build tool. 

    • Java: 當然就是推薦Ant這套廣為使用的Build Tool. 很多其他程式的build tool都是模仿Ant而生出來的。(Ant: http://ant.apache.org/)
    • Net:早期.Net並沒有很好的Build System,筆者使用過NAnt,但比起Java的Ant而言,陽春許多。後來選擇有GUI介面的FinalBuilder。FinalBuilder可以想像就是有GUI介面的Ant,也提供Server版本。非常的好用!NAnt: http://nant.sourceforge.net/ 或 FinalBuilder: http://www.finalbuilder.com/
    • PHP+Linux:筆者這一兩年從Windows陣營轉至Linux平台,目前有幾項產品也是透過PHP+Linux開發,基於對Ant的認識,所以也採用了系出同門的Phing(模仿Ant,但是有更多PHP相關的Task)。(Phing: http://www.phing.info/)

    以下介紹的就是Phing Build Tool的觀念,Ant或者NAnt都是相同的觀念。
    NewImage
    圖1: Ant,NAnt,Phing基本觀念

        Ant, NAnt, Phing等的Build Tool都是基於Build.xml來設計流程。如圖1,在一個Build.xml中,可以有很多Target(或者稱執行區塊)。每一個Target可以獨立存在與獨立執行。舉例來說,"取得最新程式碼"或"單元測試"就可以是一個Target。
        而Target裡面就可以設定各種不同的Task(任務),例如,刪除檔案,重新命名檔案等。當設計完build.xml之後,就可以透過Ant, NAnt, Phing來執行此build.xml.

        以下是以團隊其中一個服務的build.xml當範例(有些不適合秀出來的流程,就拿掉了,請見諒)。由於這是符合我們的需求,不見得適用每一個專案。但歡迎大家提出問題來討論。

    先來看看這個build.xml的架構
         NewImage

    在<project>包起來的所有節點,就是build.xml的主體。先來介紹一些基本的Tag。

    • <project> : 宣告整個build.xml,包含了名字,預設的Target,還有執行的目錄。預設的Target是指執行build.xml而沒有指定target的話,那預設會執行哪一個Target. 
    • <property> : 可以想像成build.xml的global variable (全域變數)。可以寫死常數,若宣告override=true,則可透過執行時,由外在的指令傳遞進來。
    • <target>: 每一個的Target(執行區塊),就是我們真正需要設計的地方。它包含了name, description與depends. 什麼是depends?顧名思義,就是要倚賴哪一個target先執行。透過depends就可以串起每一個不同的執行區塊與執行順序。


    這個build.xml有6個target,接下來逐一介紹裡面的內容,也順便介紹一些常用的task.


    • Clean Target: 主要將一些暫存檔案刪除 (請參考上圖)
      • <delete> : 這就是圖1提到的Task。在這個Target使用<delete>將暫存檔案或一些中間產物給刪除。

    • Init Target: 準備開始進行build的程序,可以看到這個target depends在clean上,所以執行init之前,會先執行clean。(請參考上圖)
      • <echo> : 就是echo,可以把message印出來,這是非常重要的,尤其是需要build比較久的系統,透過echo的設計,可以清楚的知道目前build的進度。筆者有時候也會透過echo來做build.xml的debug. 
      • <mkdir> : 應該看名字就知道是建立目錄
      • ${build} : 這是什麼東西?這就是在build.xml中變數的寫法。在property中有定義了這一個變數,當要使用它時,就可以透過這個格式來使用。

    • Build Target: 真正進行Build的Target,也是最重要的。(細節參考上圖)
      • <exec> : 這是執行外在指令的寫法。由於筆者團隊是使用SVN做程式碼版本管理,所以透過<exec> check out (簽出)最新的程式碼。當然,Phing也提供內建的版本控制task,但因為我們使用EC2的 server,是透過private key登入,目前Phing的Task不支援,所以只好透過Command做。
      • <phplint>: 這個專案使用PHP程式,所以透過PHPLint這個工具做程式碼語法檢查。這需要比較久的時間,若是希望快一點的人,可以略過這一步。
      • <version> : 這是個特別的Task,基本上我們採用的版本號碼跟一般open source相同。也就是[大版本.小版本.build號碼]。當設定releasetype="Bugfix"時,那會在version.txt中遞增最後一個build number. 筆者就是透過這個Task來進行版本號碼的遞增的。當然還有其他的作法,例如將版本號碼check-in至版本控制server,然後再不停的update跟check-in。
      • <foreach> : 在build.xml中,也可以類似寫程式一般,使用For-Each的邏輯。由於團隊有三種開發環境,Dev+ Testing+ Production,所以必須要做出不同環境的build. 這也是Build對團隊最大的幫助。因為不同的環境有許多不同的設定。
      • <property name="phases" value="prod,test" />,在phases中,設定了prod跟test, 所以<foreach>會執行兩次,並且把prod跟test帶入"phase"這個參數。由於Dev就是每一個開發者自己的環境,所以就不用特別作一個build了。

    • Phase_Build : 剛剛提到的ForEach,會執行兩次phase_build (test跟prod) (細節參考上圖)
      • <property file="${temp_src}/deployment/${phase}/${phase}.properties"/>:由於每個環境都有一些不同的設定,所以讀外部property檔案。這邊比較特別的是,property檔案中的key會自動變成build.xml中的變數,方便後續使用。
      • <copy> : 準備開始copy檔案,一邊copy檔案,也一邊進行一些變數的修改。例如,修改CDN的網址,修改DB的URL,修改Facebook API Key等等。
      • <JsMin> : 為了前端的performance,我們將所有的Javascript進行minify。不過後來我們採用另外一套更好的解法,之後再與大家分享。
      • <delete> : 刪除一些不必要的檔案

    • Dist與Phase_dist: 準備好各個環境的檔案後,就準備打包了。為什麼取名dist? 這只是慣例,沒有特別理由。(細節參考上圖)
      • <foreach> : 一樣進行兩種不同環境的的打包。由於之前Target已經宣告過phase變數,這邊直接使用即可。
      • <mkdir> : 準備打包的目錄
      • <tar>: 透過Tar的指令來打包檔案。這邊可以看到每一個tgz檔案,都會帶有版本號碼。執行完這一個task之後,就可以成功產生出build files了。


    底下就是產生出來的build file. 可以看到每個build都帶有版本號碼。
    NewImage 

        既然透過Phing或Ant可以做出Build,那可不可以也進行自動化佈署?當然是可以,筆者也透過Phing來進行多台Server的同時佈署,至於如何做?那就留待下一篇文章了!

    若各位有使用上的經驗或者問題,也歡迎提出來一起討論!謝謝!

    下載本文章的build.xml: https://docs.google.com/open?id=0Bx_RyouzvSXHb05iZm5xR0VuZE0