Pages

11/10/2014

Hong Kong address area code - AngularJS Version



今天承上一個今天分享一個了 Program 仔,就是可以自動分辨香港地址上的分區
那足足花了我整天時間,經常說讀 IT 的,三年不學新的就會被淘汰。幾年前通街都用jQuery,說盡他的好處。
一年多後,AngularJS就靜靜的冒起,到了現在,不少老外都推廣它的優勝之處。
那就不要浪費整天的時間,杜芬宅決定將其轉換成用AngularJS編寫。
又要不斷爬文了~~~
====================================================

Hong Kong Address Area Code

開發工具︰NotePad++
技術︰AngularJS, Ajax, JSON, PHP, HTML, CSS

版本編號︰2014-10-03(因為是當天完成的)
開發者︰杜芬宅
授權條款︰Apache License 2.0
===================================================================
事出必有因︰
===================================================================

背景

當然不是很閒沒事做,Google 時大部份的結果都只是單方面地說說 AngularJS 那好這好。
水過鴨背的介紹一下 AngularJS 的功能,今次就希望藉著那個案例。一邊廂是 jQuery,另一邊廂是 AngularJS。
看一看 jQuery 與 AngularJS 在開發時間上,開發難易度……有什麼分別

杜芬宅 是 AngularJS 新手,第一個小程式寫得不好請多多指教。
首先參考了幾篇文章,看完也認為不錯的,在此發享一下增加對 AngularJS 的認識。

你會留意到網頁也有使用 jQuery ,那純粹是想方便地使用 jQuery Selector
你可能同時又發現 layout 有點不同,因為轉用了 Bootstrap framework 而非 jQuery UI
===================================================================
良機 -→ 實幹 --→ ……
===================================================================

『嘣』出世了

由於時間的關係,Programming 就完成了
在此特別想提到,周圍爬文時,發現不少例子的寫法有點過時,強烈建議大家去看官網 https://angularjs.org/
及看大概六七個第三方的例子,官網首頁的例子比較貧乏 X_X

go to DEMO PAGE

jQuery 和 AngularJS 的不同思维模式

[文章引用]︰大置上分五點

  1. 先不要理會 UI 設計,應該用 DOM 去達成你的預期結果

    在jQuery的裡面,你會先設計好一個頁面,然後再讓它變成動態的。
    那就是問題所在,在開發後期,那會令到程式碼十分冗長︰難以閱讀、難以理解 邏輯 和 流程

    但是在AngularJS的世界中,先要構思整體架構,然後從零開始構建應用。
    而不是在現有的介面中,你要讓它做 ~!@#$%^ 就做,過了一會要多做幾樣,就再做幾樣
    你必須首先思考你到底要完成什麼功能,然後再開始動手,
    然後再開發你的應用,最後才去設計你的介面。

  2. 不要混合使用jQuery和AngularJS

    就是字面的意思,原文提到 大多數情況 只需要很少的 AngularJS 代碼就可以把 150-200 行 jQuery 代碼的功能完全取代。
    杜芬宅同意那並不是全部情況

    底線是:在解決問題的過程中,首先“Think in AngularJS”(以AnguarJS的方式去思考問題去解決);如果你想不到解決方案,請求助於社群;如果在嘗試了所有這些方法之後還找不到簡單的解決方案,然後再求助於jQuery。但是,絕對不要依賴jQuery,否則你永遠無法真正掌握AngularJS。
之後有點長氣,想深入了解請自行查閱。
杜芬宅反而想說說下圖︰

Data Binding in Classical Template Systems

Most templating systems bind data in only one direction: they merge template and model components together into a view. After the merge occurs, changes to the model or related sections of the view are NOT automatically reflected in the view. Worse, any changes that the user makes to the view are not reflected in the model. This means that the developer has to write code that constantly syncs the view with the model and the model with the view.

在杜宅芬從前某個開發項目中,
Template 是一些HTML,Model是PHP,View是Browser的結果
HTML 的web page透過ajax call PHP,return的可能是XML / JSON,再用 jQuery 分拆return 的東東顯示出來
往往在合併後,可能資料經使用者有改動,同時又要傳回server。
便要再編寫另一段程式,取回值(例如︰$("#dataContainer").val()) , 再併湊一起送出。
如果PHP 傳回的值會不時變改,可能就要定時定侯再去抓一次DATA

Data Binding in Angular Templates

Angular templates work differently. First the template (which is the uncompiled HTML along with any additional markup or directives) is compiled on the browser. The compilation step produces a live view. Any changes to the view are immediately reflected in the model, and any changes in the model are propagated to the view. The model is the single-source-of-truth for the application state, greatly simplifying the programming model for the developer. You can think of the view as simply an instant projection of your model. Because the view is just a projection of the model, the controller is completely separated from the view and unaware of it. This makes testing a snap because it is easy to test your controller in isolation without the view and the related DOM/browser dependency.

Template 是一些HTML,Model是Javascript(不,正確來說應該是AngularJS),View是Browser的結果
Angular templates有點不同,在 Browser 上 compile 後,任何view上的變動都會對Model有影響,
同時 Model 有變更亦會在View上自動反影出來。

那就是 Angular 經常強調,很自豪的 Two-way Data Binding (雙向的資料綁定),那令我想起已經被遺棄的 knockout,也有幾分相似

Start with AngularJS

官方提供了清晰易明的 Free Course Video,由淺至深講解。

Level 1.1 大綱

  1. ng-app (Module)
  2. ng-controller
  3. Expressions {{ xxx }}
  4. ng-repeat
  5. ng-show

Level 2.1 大綱

  1. filer
  2. formatting with filters
  3. ng-src
  4. ng-click
  5. ng-init
  6. ng-class

Program Flow and Logic

兩個『小』程式,都是在僅有的時間擠出來。腦中想到什麼就做什麼,jQuery、AngularJS 功能上有少許差異乃屬正常現象。 [Current Dictionary] Tab
網頁載入後會自動取字典檔(check-address-area.txt),解析和分拆後會將判別為四區域的地名分別顯示在此
字典檔 的原始內容則顯示在旁的Source Tab,如果字典檔抓取失敗會顯示( Get external JSON...Fail )。
失敗時會自動套用預設字典,預設字典只懂辨識十八區區名。

[Press your address here] Panel
在此輸入文字後過透過 AngularJS filter ,斬開每行取出地址最後一段用逗號分隔的部份。
每句實時地反影在 [Get the substring] Panel
此時如在最尾部份地址發現問題,請修改來源[Press your address here] Panel
因為 [Get the substring] Panel 是 Read only,檢查後無異可進入下一步。

[Custom address area code] section
確保正確無誤後可按下[Identify area code],系統(程式)會為地址自動指派 Area Code。
如果未能從字典定義檔中進對配對,會留下Selection Box讓使用者可以手動自行選取 Area Code
在此同時,按下[Identify area code]後,每逢手動選取 Area Code或在旁邊的文字欄位改變 Area Code,
[Area code identification] panel 都會同步並整合所有的 Area Code,當完成所有的Area Code的辨別工作, 使用者可自行複製[Area code identification] panel內容並貼到Excel儲存。

[Dictionary New Definition] section
按下[Identify area code]後,每逢手動指派 Area Code 時,程式如發現該地址並未定義在字典中時,
會將地址放入[Dictionary New Definition],辨別為新定義。

按下 [Refresh JSON Dictionary] 後,會檢查所有框框,如果某項地址並未記錄在字典時。
該項地址會出現在[Dictionary New Definition] Accordion 雙應的分區

New Json section
最後,完成所有指派工作後。如果新定義出現了,可進行更新字典程序,讓日後遇上相同地址,程式懂得自動指派Area Code。
如果你的Server 支援PHP,可按 [Update JSON Dictionary] button,新定義將會寫入字典檔案
如果你不知道什麼是PHP,不清楚你的電腦是否有上述功能,可按 [Refresh JSON Dictionary] button,新的定義碼將會生成在New JSON panel中。
請你複製新的定義碼,開啓check-address-area.txt,將check-address-area.txt的內容刪除並切換成新的定義碼。
注︰按下[Update JSON Dictionary] button 或 [Refresh JSON Dictionary] button 意味完成整過處理流程
按下後如想重新開始指派其它更多地址的Area Code,必須重新進入網頁或按F5 重新整理網頁。

自說自話

回到那個部份,杜芬宅認為 AngularJS 是另一個層次的東西,不能單純地和 jQuery 作比較。
我們看看官方的自白

AngluarJS
What is AngluarJS (https://docs.angularjs.org/guide/introduction)
AngularJS is a structural framework for dynamic web apps. It lets you use HTML as your template language and lets you extend HTML's syntax to express your application's components clearly and succinctly. Angular's data binding and dependency injection eliminate much of the code you would otherwise have to write. And it all happens within the browser, making it an ideal partner with any server technology.

jQuery
What is jQuery? (http://jquery.com/)
jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript.
http://try.jquery.com/levels/1/sections/2

jQuery 正如 LOGO 的口號一樣,write less, do more (http://brand.jquery.org/logos/)
jQuery 的宗旨是 一件很複雜的事情只需很少的編碼 就可以完成,
一個最簡單的例子,假設要 Point to / get 一個 Element
var elementObject = document.getElementById("elementID");
var elementObject = $("#elementID");
後續例子


Click me!

真的是少了,我沒有騙你
/* Javascript version */
function getValue(){var x=document.getElementById("myHeader");alert(x.innerHTML)}

/* jQuery version */
$(function(){$("#elementID").click(function(){alert($(this).text())})});
還可以除去 onclick="getValue()",共節省29字元。
AngluarJS 是為著 動態 web apps 設計出來, web apps即是任何在瀏覽器上執行的程式。
不單單是資訊性的網頁,一個網頁遊戲可以算是一個Web app,一個網上聊天室可以說是一個Web app。

詳見 web app 定義
http://en.wikipedia.org/wiki/Web_application
http://webtrends.about.com/od/webapplications/a/web_application.htm

AngluarJS 以 HTML 為範本,其後使用者可自行 擴展更多的 HTML tags去製作你的 web apps。
令結構較加清晰簡潔,那個概念與 HTML5 有相似之處。
AngluarJS 同樣地能夠實現使用者自定義更多的 HTML 語法。
讓開發一個項目時結構得到規範,那與片中對 HTML5 的比喻有著異曲同工之妙。00:27 至 01:21


雖然 XHTML 同樣可以自定義語法,不過 AngluarJS 還伴隨了 Data binding 令功能可以更擴泛應用。
AngluarJS 的 data binding 和 dependency injection (那個未爬文不知是啥),能夠為開發者節省更多 Coding ,因為 AngluarJS 幫你處理了。
最後 AngluarJS 是在瀏覽器執行,不論背後伺服器的種類、建構技術都不受影響。

jQuery VS AngularJS

Compare functional requirement implementation

Function - Get the district (last part of the address)

A friendly behavior pops from my mind at once, I would not accept the user need to press a [confirm] button to let the program know that he/she just type/pase a list of addresses.
Because I'm that user, I would not like to click more one time so that I choose to coding more to handle this one.

The keyup event is sent to an element when the user releases a key on the keyboard.

The change event is sent to an element when its value changes. This event is limited to <input> elements, <textarea> boxes and <select> elements. For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus.

I use keyup to capture the keyboard action, I use change to handle the user paste content by mouse right click.
There was a limitation, the change only affects when the textarea loses focus, but still better than nothing.

用 jQuery 的 change 就可以每當Textarea內容變更時獨發,
用 jQuery 的 keyup 就可以當在Textarea時每逢有鍵盤放開按鍵時獨發,
用 keyup 持續監視鍵盤輸入, change 則是修補 如果只用 滑鼠貼上而沒有 keyup的狀況。
不過 change 用在textarea上必須out focus才有效果。
即是滑鼠貼上也要按其它地方/按TAB,總之要離開Textarea才有效果,有點美中不足。

首先建立一個Controller,用 model 和 bind 將資料綁定到兩個Textarea。
顯示地址最尾部份的使用一個format / filte,便可以對地址進行一些處理再顯示出來。

/* jQuery version */

$("#client-address").keyup(function () {
    var form = $(this).parents(".formEntry");
    form = form.find("#client-address").val();
    aKeyhWasType(form);
});
$("#client-address").change(function () {
    var form = $(this).parents(".formEntry");
    form = form.find("#client-address").val();
    aKeyhWasType(form);
});
function aKeyhWasType(form) {
    console.log(arguments.callee.name + " function start");
    getTheSubstring(form);
}
  
function getTheSubstring(text){
   text = text.trim();
   $("#custom-area-code-td").text("");
   $("#address-substring").val("");
   
   textInLine = text.split("\n");
   for(i=0; i < textInLine.length; i++){
        commaIndex = textInLine[i].lastIndexOf(",");
        
        var addressLastLine = textInLine[i].substring(commaIndex+1, textInLine[i].length);
        addressLastLine = addressLastLine.trim();
        $("#address-substring").val($("#address-substring").val()+addressLastLine+"\n");
   }
  });

/* AngulgarJS version */
// Controller customAddress
app.controller("customAddress", function($scope){
    $scope.customAddressText = "";
});

// split the customAddress,
// filter the last part address
app.filter('getAddressLastPart', function(CustomAddressLastPart) {
    return function(input) {
        // do some bounds checking here to ensure it has that index
        textInLine = input.split('\n');
        var _customAddressLastPart = "";
        for(i=0; i < textInLine.length; i++){
            commaIndex = textInLine[i].lastIndexOf(",");
            var addressLastLine = textInLine[i].substring(commaIndex+1, textInLine[i].length);
            addressLastLine = addressLastLine.trim();
            if(!addressLastLine)
                continue;
            _customAddressLastPart += addressLastLine + "\n";
        }
        _customAddressLastPart = _customAddressLastPart.trim();
        CustomAddressLastPart.setAddressList(_customAddressLastPart);
        return _customAddressLastPart;
    }
});

Function - Generate the customer area code UI

When the program getting each last part of the address, the last part will compare with the dictionary to try to matching a area code.
There was a DIV template hidden in the HTML code. Although jQuery allow create DOM, I wont put it in HTML in develop status.

clone means copy a UI template, which is include a textbox, selection box and one more textbox.
Put the address last part into first textbox, assign the matched area code to the last textbox if found.

appendTo the page, finally assign the matched area code to the selection box, because the change action only can affect to DOM, the change action must after the appendTo.

If the matched area code found, lock the selection box and textbox.
Hopes that reduce the items keep your focus.
After process all the last part address
Set the lock/unlock button behavior,
as above said that the program will lock the block if that last part address found, we need to provide a Undo to unlock the block if the program making misjudgment. Relatively, I give you lock again=.= hahaha.

add change trigger on selection box, last textbox, update the Area code identification textarea when the use change or assign the area code.
the trigger include to sync between the selection box and last textbox.
Finally, clear and refresh the Area code identification textarea.
At as current, some of last part address may be matched in dictionary, we found all the area code and paste on the Area code identification panel.

在分割每段地址最後部份時,會與 字典進行比對。
比對後會用clone 複製出一個框框,框框已隱藏在網頁內。 將地址最後部份、比對成功的代表 香港、九龍、新界、離島的字元 放進框框內、以及選取適當的下拉選項。
由於jQuery change只可以控制DOM,所以必須要將框框複製品 嵌入到網頁內。
然後再進行選取選單的動作。

本來原意是想減少用家需要關注的項目,如果成功從字典找到地址。
會自動鎖著整個框框,你不用擔心會誤改了地區。
不過為了讓人悔旗所以給你解鎖

為框框內用家可以改動的內容都加入觸發器,每有改動內容就觸發。
更新一次在 Area code identification 文字方塊內顯示的 area code。

一個網站 / 一個網頁 如果需要與使用者大量的互動, AngularJS 將會是你開發的 希望之光。
依靠著 AngularJS 的 Two-way Data Binding

No comments:

Post a Comment