BLACKBING PlayGround 紀錄一些生活或工作的雜事,偶爾會寫一些前端開發的心得

12一月/120

logger.js for switching production and development

發布於 BLACKBING

http://www.rickgeary.com/images/color/Logger.jpg

在開發時常常會需要用console來除錯或是檢查流程,但推到production上必須要將這些log清除,雖然console很好用,但適當的log可以輔助除錯,如果推到production就強制將console.log都從code裡頭移除也不一定是好事,因此常常會看到會有一個管理log的global  function,例如:

var log = function(s) {
    if (typeof console !== "undefined" && console !== null) {
          return console.log(s);
            }
};


不過這樣簡單的function就不夠彈性,結合大家的想法,希望這個logger至少能夠handle幾種情況

  • 可以直接呼叫Logger(‘foo’)
  • 也可以擁有console api 的功能,例如warn, info, group等等特殊功能
  • 快速切換production or dev環境
  • 就算有人不小心寫了console.log,只要我切換到production環境,就不會印任何東西
  • 萬惡的IE也要能運作正常,而不是強制關掉log(例如開啟開發人員工具還是可以看到log)

於是,Logger.js就誕生了,由於現在都用coffeeScript寫js(用了就回不去了),因此js是coffee產生出來的。也順便做了require.js的require版本,若在專案有用到require.js可以直接require。

雖然只是很簡單的code,不過對我來說很實用,跟大家分享。

Get the sourcecode(Github): Logger.js

實作上遇到幾個問題,原本構想是希望像jQuery一樣,可以直接呼叫,也可以呼叫function處理,例如:

$('#main')
$.ajax()
$.bind()


原本我以為要用覆寫prototype的方式來處理,繞了一大圈纔知道根本不用(真是暈了我),javascript原本就是「物件」導向,所有變數都可以是物件,因此function其實也是物件。犛清了這個觀念之後,實作就很容易了,首先宣告為function,接著再一一指派,大功告成。有興趣的就再研究Logger.js吧。乾杯。

Rock the code

31十月/110

國四無雙之下台一鞠躬

發布於 BLACKBING

URMAP的日子竟然匆匆過了四年,回想起來真是不可思議,在這兒,我學到不少東西,也是個很好發揮的地方,URMAP畢竟還是台灣少數的圖資應用廠商之一,舉凡LBS相關的服務、車隊系統、定址系統、導航系統、地圖API等等,都是台灣少數可以跟Google Map相抗衡的地方,研發團隊一直都很堅強,這也是我一直很樂此不疲的地方,在這裡有不定時的宅宅分享會,大家一起分享討論新的技術,看看是否可以應用在新的地方。

URMAP很特別,因為LBS的領域其實是有點專門的領域,能夠接觸到GIS相關的知識,這也是我一直很感興趣的地方,而各個領域都有很棒的同事在負責,我們用到的技術、創新服務也非常多,在這兒,真的是一個很好發揮的舞台。

時間過得非常快,四年好像一轉眼就過了,臨走前,我在宅宅分享會分享了最後一個主題:「Web Developer不可忽視的瀏覽器擴充元件」,主要是我認為隨著Google Chromium的發展,瀏覽器擴充元件會成為Web application中很重要的一環,除了web的know how,web Developer一定要知道browser extension可以做到什麼,或許也可以帶給網站一些有趣的應用。並且用我在閒暇之餘做過的Download FB album當作例子以及code review。

投影片請按此

投影片裡頭的特效是用HTML5 + CSS3來完成,由於時間有點趕,因此我沒測試過Firefox,所以只能用Chrome來開啟,另外由於公司投影機測試的解析度問題,所以也會有點小誤差。除了Extension的概念之外,其實我主要想分享的概念是「熱情」。

投影片裡頭的所有特效,除了slide的框架,其他都是自己寫出來的,看起來好像沒什麼,但是卻是花了很多時間在處理一些小細節,有同事問說:「為什麼要自己寫?也太閒了吧!」,我當時回答說:「因為爽」,不過其實我想分享的是一個「熱情」的精神,因為有熱情,你才會投入,哪怕是這個細節需要花你很多時間來做,事實上,所有的工作都是這樣的,「魔鬼藏在細節裡」,你不實做,永遠都不知道細節是什麼。

之前看過一篇文章:「什麼是重要的」,裡頭講到幾句話另我深有感觸:

  1. 追寻这些新技术,很容易让人有种走在技术前沿很牛逼的虚荣感。
  2. 以为走在前沿,其实只是凑个热闹,迟早成为舞台下的观众。
  3. 对于武林高手,内功最重要。招式套路,只能街头赚个掌声。
  4. 对于程序员,真正的核心竞争力是基本功。
  5. 永远不要舍本逐末,否则你学的新东西越多,被淘汰的可能性反而越大。

事實上,我認為中國大陸的前端技術能力非常堅強,已經不輸給國外的技術了,我常常找資料都找到大陸的技術博客,雖然大陸clone的文化還是有,但他們就是有能力做出一個一模一樣的技術,這不是也令人刮目相看?

總歸一句話,熱情才會創造出更有趣的應用,否則技術永遠只是死的,Programer 最有價值的地方就在於,能夠發揮創意並且實做出來,最怕的就是在看某個應用,然後說:「哦~這個不就是XX再加上OO,這我之前也想過」,那麼,你有實做出來嗎?在WEB當道的時代,創意已經不值錢了,值錢的是,將他實做出來。

「熱情,才能成就你自己」。共勉之。

分類於: Life 沒有回覆
7十月/114

Download FB album (for high resolution pictures)

發布於 BLACKBING

Download_FB_new_feature之前做了這個下載照片的小工具Download FB album,說真的,我沒想到會有這麼多人下載,雖然是chrome Extension,但隨著Chrome瀏覽器成長的快速,使用者與開發者也成長的非常快速,代表只要你的產品有碰到使用者,是真的能夠有這個市場,而且在chrome Web Store也已經有付費機制,也就是說你能夠透過web strore來跟使用者收取費用,讓開發人員更有興趣來Rock the World。

話說回來,Download FB album的目的只是要下載整個相簿的照片,而原本的概念也僅僅只是要替換縮圖與原圖的URL而已,然而,發佈之後才發現很多人反應沒辦法下載原始大小的圖檔,於是我再檢查是否可以取到相對應的原始大小圖檔,但結論是沒辦法,就連每一張圖片的高解析尺寸,FB都是重新發request來取得,而且包含html一起回來,這代表FB為了防止抓圖機器人大量抓圖(指)而採行的策略,於是我雙手一攤,那我就沒辦法囉~各位使用者,Sorry~(逃~)

但在這期間,我收到好幾個使用者直接寄信來反應是否可以提供下載高解析度照片,並且很認真的跟我討論實做的方法,大部分使用者一開始都提到只要改一個字元而已,仔細討論之後才發現真的沒那麼簡單,所以最後都不了了之。但隨著使用者下載的次數越來越多(目前已經38000以上人次下載),我的責任感卻增加了,於是我開始很認真的思考我該如何取得high resolution的圖片。歸納出以下結論:

21九月/110

批量AJAX query 系統(友邁科技定址程式)

發布於 BLACKBING

友邁科技多筆地址輸出系統

重寫舊系統

URMAP有一個很實用的系統「地址轉經緯度」,可以parse 台灣的地址,轉成WGS84 經緯度或TWD97座標,並且API化,可以使用AJAX的方式來做查詢,會將地址做正規劃,查詢到最靠近的點。由於是HTTP的方式,因此很容易實做,就算要做批次的查詢,只要會寫程式都可以很快速的做出批量做座標轉換。然而對於某些公司而言,他們不想要為了這個功能而花時間寫程式,希望能夠提供直接做查詢的使用方式,於是早期就有一套轉換系統,用JAVA撰寫之後包成jar檔,直接在windows或linux下command line,指定讀取的file,就會輸出成指定的CSV檔案。由於大家也懶,因此這樣的程式就流傳下來,連自己都覺得這樣的方式很不方便,而且每次都要指定參數,操作方式並不是很友善。後來看到node.js event io的概念才有IO存取的概念,類似像這種批量查詢的需求,一般來說都是以同步的概念下去執行,也就是一個查詢完成之後再做下一個查詢,查詢一百次、一千次就要同步的等待每一個request完成。有沒有辦法讓查詢更快?可以用多執行緒來解決,無奈程式不好寫,除錯不容易,因此一直沒有實做。

Clinet端的檔案輸入與輸出

於是我用node.js來實做這種批次查詢功能,利用Event IO的概念來實做,的確可以很快速的做回應,但通常要批量轉換的地址資料都會很大,若在本機執行還沒什麼大問題,但若做成web系統,就還要讓使用者上傳、解析文件等等,非常麻煩,因此這樣的方式也不理想。最後我把腦筋動到HTML5 FileReader,稍微試了一下,可以讓使用者選擇檔案,並直接透過javascript來讀取檔案內容,parse正確資料之後就可以在client端做AJAX批次的查詢。然而有輸入,就要有輸出,html5 FileWriter API幾乎沒有瀏覽器實做,因此Writer無法使用,不過我找到兩種方式來做文字檔的輸出:

  1. 另開新檔:http://stackoverflow.com/questions/6464828/cross-browser-save-as-txt
    這種方式利用瀏覽器開啟檔案的方式來實做,但IE系列不支援,若資料單純且可以排除IE,可以用這種方式來做,非常簡單。
  2. Downloadify
    則是用flash來實做另存檔案,使用上也不難。
萬事具備,只欠Coding。那就來實做吧。由於是內部系統,因此就不放連結上來了,要付費才可以使用喔(毆飛~)。

javascript根本就是天生拿來做這種事情的,不費吹灰之力就完成了批次輸出系統,由於是用非同步的ajax來做查詢,因此同時發出ajax查詢之後等待回傳結果,而查詢的效能也非常的快,完全取決於server端給不給力的傳回資料。用說的實在是不過隱,分享片段的程式來瞧瞧。

試用連結

友邁科技多筆定址輸出系統,歡迎企業有大量需求申請使用。

讀取檔案

//讀取檔案
function read() {
    var files = $('#filesInput')[0].files;
    if (!files.length) {
        alert('請輸入');
    }
    var file = files[0];
    var fileName = file.fileName;
    var fileSize = file.fileSize;
    var info = ['檔案名稱:' + file.fileName, '檔案大小:' + (file.fileSize / 1024) + 'k'];
    if (file.lastModifiedDate) {
        info.push('最近修改日期:' + file.lastModifiedDate.toLocaleDateString());
    }
    var infoHTML = info.join('&nbsp;<br>');
    $('#d2-info').html(infoHTML);

    var reader = new FileReader();
    reader.onload = function() {
        $('#d2-content').text(reader.result);
        $('#d2').dialog('open');
    };
    var encoding = $('#encoding option:selected').text();
    reader.readAsText(file, encoding);

}

匯出成CSV

//匯出成CSV
function exportCSV() {
    //    console.log('export');
    var data = [];
    for (var i = 0; i < addressCallback.length; i++) {
        var line = [];
        var addressLine = addressCallback[i];
        line.push(addressLine.address);
        line.push(addressLine.formal_address);
        line.push(addressLine.city);
        line.push(addressLine.area);
        line.push(addressLine.longitude);
        line.push(addressLine.latitude);
        line.push(addressLine.xcoor);
        line.push(addressLine.ycoor);
        line.push(addressLine.level);
        line.push(addressLine.position_result);
        data.push(line.join(','));
    }
    var exportData = data.join('\n');
    //var newDoc = window.open( "data:application/x-download;charset=utf-8,"  , 'address_export.csv', '', '');
    //newDoc.document.write(data);
    Downloadify.create('downloadify', {
        filename: function() {
            var ts = +new Date();
            return 'address_export' + ts + '.csv';
        },
        data: function() {
            return exportData;
        },
        onError: function() {
            alert('You must put something in the File Contents or there will be nothing to save!');
        },
        transparent: false,
        swf: './downloadify/downloadify.swf',
        downloadImage: './CSV.64.png',
        width: 64,
        height: 64,
        transparent: true,
        append: false
    });
    $('#downloadify').show();
}

心得

值得一提的是,利用jQuery.getScript的方式比jQuery.ajax的方式要快,我想是用getScript的方式來直接執行javascript更快速。同樣的概念我想可以應用在所有需要批量輸入輸出的系統上,只要打開browser,不需要安裝任何東西,也不需要上傳檔案到server端處理,完全透過client端解決所有的事情,javascript的應用真是越來越廣泛了,有需要使用這個好用的系統請洽友邁科技客服 ,會有親切的小姐跟您聯絡XD。
15九月/110

繼續保持又笨又餓

發布於 BLACKBING

stay hungry, stay foolish前陣子一些因緣際會的關係,讓我有機會跟miiicasaAwoo深入的聊天,看到他的努力與成就,深深地佩服不已,多跟高手切磋,果然會有更深的體悟,並瞭解自己的渺小。回頭看看自己走進資訊這條路也走了好幾年,工作之後的這幾年,讓我的經驗值增加不少,不敢說自己多有成就,但至少在這條路上,我還抱持著一股熱血想要為這個領域付出心血。「分享才是王道」。在這個領域上,分享的精神在網路上蔓延開來,有多少次我想分享的動力,是因為我在網路上遍尋不到(或是自己腦殘不知道怎麼找)平常取用於網路資源,偶爾也該貢獻一下,這樣的精神,讓我在Awoo與他的團隊身上找到令人感動且熱血沸騰的血液。

其實技術本身是不值錢的,技術一定需要實踐與應用才會彰顯他的價值,然而工作中,有時後會遇到某些人,也許技術能力很強,但卻很容易對某些人因為不懂得某些技術而嗤之以鼻,例如:「拜託,什麼時代了還在用Table切版」、「某國立大學的連相對路徑和絕對路徑都搞不懂?」。事實上「聞道有先後,術業有專攻」,你會這些知識,也許只是因為你活在這個時代罷了,你敢保證你會得這些技術,到了十年後還會再用嗎?沒有人能保證。事實上很多技術只是「知道」或「不知道」而已,就像食譜,為什麼師父很在意食譜被偷走,因為某個配方被偷走就會被模仿開來。(除了日本人很注重的「用心」沒辦法偷走之外)但技術這種東西,你知道了,沒有應用、沒有分享是不會有價值的。programer的價值不在於懂多少,而是在於解決問題的能力,當遇到問題時是否能找到最合適的方法來解決。

前陣子看到一個很棒的小故事:出自哪我已經忘了,上網搜尋到處都是轉貼,我想來源已經不可考了,所幸直接貼上了:

話說有二個和尚,他們分別在相鄰的二座山上的廟裡。

這二座山之間有一條溪於是這二個和尚,每天都會在同一時間下山去溪邊挑水,久而久之,他們便成為好朋友了。就這樣,時間在每天挑水中,不知不覺己經過了五年。

突然有一天,左邊這座山的和尚沒有下山挑水 ,右邊那座山的和尚心想:「他大概睡過頭了。」便不以為意。

哪知第二天,左邊這座山的和尚,還是沒有下山挑水,第三天也一樣,過了一個星期,還是一樣直到過了一個月,右邊那座山的和尚,終於受不了了。

他心想:「我的朋友可能生病了,我要過去拜訪他,「看看能幫上什麼忙。」

於是他便爬上了左邊這座山, 去探望他的老朋友等他到達左邊這座山的廟,看到他的老友之後,大吃一驚 因為他的老友,正在廟前打太極拳,一點也不像一個月沒喝水的人。

他好奇地問:「你巳經一個月,沒有下山挑水了,難道你可以不用喝水嗎?」

左邊這座山的和尚說:「來來來,我帶你去看。」 於是,他帶著右邊那座山的和尚走到廟的後院指著一口井說:「這五年來,我每天做完功課後,都會抽空挖這口井。即使有時很忙,能挖多少就算多少。

如今,終於讓我挖出井水,我就不必再下山挑水,我可以有更多時間,練我喜歡的太極拳。」

看完這個故事很有感觸,其實各行各業,都需要保持著這樣的心態,為自己的未來而努力,每天為自己的井多挖深一點,哪怕有一天,你就可以挖出井水;與其每天都在抱怨懷才不遇、工作無聊,不如換個心態,轉個心境讓自己隨時都為了下一步而準備。我常常在深夜裡,還在為某個問題而思考、搜尋,或者survey新的技術,工作固然重要,撥點時間保持自己的頭腦運轉也是很重要的。除了思考工作遇到的問題之外,從日常生活中找出想解決的事情,保持熱忱,保持實做的力量,將會是無比的競爭力。

賈伯斯告訴大家:「保持著又笨又餓吧」。Stay Hungry, Stay Foolish

分類於: Life 沒有回覆
2九月/110

那些年,回到過去特效文字

發布於 BLACKBING

jq.scrollEffectNumber demo

那些年最近好像賣得嚇嚇叫,不過我還是沒去看XD,而且這篇文章跟那些年沒有關係。。。

話說前幾天我跟我家女王去看「真愛挑日子」,導演用的是倒敘法,並且很強調時間的描述,有過去與未來時間的交錯,於是在劇中會不斷地出現時間,並且用滾動的時間代表時間往前或往後,比方說,從2001滾動到1963,從1966滾動到1970,而不是很普通的只是顯示現在時間是1963、1970。

這讓我手癢了,覺得一個小特效就可以讓生硬的描述變得生動起來,於是我就開始構思這個特效該怎麼在web上呈現。考慮到多位數的呈現而且還有效能的問題,我先不考慮直接用CSS來做定位,直接試試看用canvas的效果如何。

首先,數字只有0~9,要讓數字做循環的滾動並且無縫隙的接起來,我先準備一張圖片,這張圖片是從0~9再循環到0,之所以要循環到0,是因為要讓滾動時不會產生空隙,當然再計算時就需要take care一點。照慣例,廢話不多說,先來看看DEMO。

19八月/110

俄羅斯方塊with Canvas

發布於 BLACKBING

之前寫了一篇Tetris Game(javascript 俄羅斯方塊),在render頁面時用html字串的方式重新塞進畫面當中,雖然效能堪用,但若嘗試著將更新時間變短,就會很明顯看到效能的問題,尤其在IE上更加明顯,因此我將render的部份改用canvas來做,果然效能突飛猛進,而IE雖然不吃canvas,也可以透過explorercanvas project套件來做到,原本在IE 中 render HTML的效果有限,改成canvas來繪圖看起來好多了。往後在頁面的呈現效果,也許可以朝這個方向來解決。廢話少說,先看一下DEMO。

DEMO: http://blackbing.net/lab/Tetris/canvas.html 

你可以看到跟之前的方法呈現出來的效果一模一樣,差別在於render 的動態效果移到canvas上做了,看不出來嗎?讓我們來看剖面圖:

See? 看剖面圖應該比較清楚一點,底下的Grid,我還是用HTML來處理,會變動的只有在上面的Canvas圖層,每次畫面更新時,都是清掉重新繪製。用這樣的方法來提昇場景的更新,效能當然更快速。不過你可能會想,這樣程式要改多少?非常的少,我把修改的部份抓出來說明:

1. 加上explorercanvas

記得IE9以上就支援canvas囉 ,所以只要針對IE9以下來include即可。

<!--[if lt IE 9]>
<script src="excanvas.js" type="text/javascript"></script>
<![endif]-->

2. 初始化canvas

初始化的時候,用G_vmlCanvasManager來做IE的對應處理,就是執行excanvas的處理函式。

plineCanvas = document.createElement('canvas');
 if(!plineCanvas.getContext && typeof G_vmlCanvasManager!='undefined'){
  plineCanvas = G_vmlCanvasManager.initElement(plineCanvas);
}
 plineCanvas.width = blockXCount * blockWidth;
 plineCanvas.height = blockYCount * blockWidth;
 plineCanvas.style.cssText = 'position:absolute; z-index:10;';

 stageElm.append(plineCanvas);
 if(plineCanvas.getContext) {
  plineCtx = plineCanvas.getContext('2d');
  plineCtx.lineCap = 'round';
  plineCtx.lineJoin = 'round';
}

3. 重新繪製canvas

由於之前的架構還算單純,因此重新繪製場景的部份改成canvas繪製,處理起來也很簡單。只要使用fillRect就可以輕鬆繪製。

//清除畫布
plineCtx.clearRect(0, 0, plineCanvas.width, plineCanvas.height);
for(var i=0; i<metrixLen; i++){
	var color = metrix[i].color;
	if(color){
		var ycount = Math.floor(i/_self.blockXCount);
		var y =  ycount * _self.blockWidth + 1;
		var x = Math.floor(i%_self.blockXCount) * _self.blockWidth +1;
		plineCtx.fillStyle = color; //設定塗滿顏色
		plineCtx.fillRect(x, y, _self.blockWidth-2, _self.blockWidth-2); //塗滿這個grid
		//stop condition
		if(ycount === 0 && metrix[i].stacked){
			stop = true;
		}
	}
}

canvas是個非常棒的東西,可以處理到一些更細節的部份,尤其針對動態的處理,繪製的效能比網頁render的效果好上太多,如果你的動態效果遇到效能瓶頸,嘗試著用canvas畫布來思考,也許會有更驚人的提昇。大家一起快快樂樂做網頁。ㄎㄎ~

17八月/112

javascript UTF-8 繁體中文筆劃排序 解決之道

發布於 BLACKBING

今天遇到一個客戶提出的需求,需要在前端做中文的筆劃排序,雖然已經跟客戶提出說UTF8很難做筆劃排序,但他們還是要求要依照筆劃來做排序。於是我就開始陷入編碼的世界而無法自拔(汗)。搜尋google大神的結果幾乎都是從資料庫端來解決,然而這次遇到的問題並不是單純將資料庫資料撈出來排序就可以搞定,而是要顯示在前端做動態的分群並且排序。因為實在是花了太多時間在找資料,而且大部分的解決方式都是N年前的解法,不適合現在的應用環境(UTF-8編碼),本篇文章是希望後續有人遇到類似的問題可以省點力氣,整理一些解決的方式。重點如下:
12八月/110

Auto play in Facebook Theater Mode

發布於 BLACKBING

Auto play in Facebook Theater Mode

Auto play in Facebook Theater Mode

家中的女王又來給我出題目了,這次的題目不算難,他想要在看朋友的FB相簿時自動播放,用chromeExtension可以很輕易的做到,有了之前開發的經驗,要做這種注入式攻擊增強功能算是小事一樁。雖然如此,還是紀錄一下開發心得。

1. 由於是Page Action,需要的資源如圖片等必須額外host,我不想為了這個小功能而要找host放圖片,因此我用Binary File to base64 encoder來將圖片轉成base64 直接嵌入。

2. 使用 getComputedStyle 來查找「真正的」計算樣式(computed style):

如果你只用Element 的style屬性來取得該Element設定,一定會吃鱉,因為style  屬性只包含該元素之inline樣式資訊,而不包含該元素的CSS階層樣式,因此你需要用 getComputedStyle來查找真正的style屬性。只是要注意的是這個方式不見得都能取得想要的資訊,例如:當元素不是絕對定位,透過computed style取得left 和top時,只會得到"auto",這是完全合法的CSS值,但這可能不是你要得結果。因此在使用時,必須要謹慎。另外一點需要注意的是IE並不存在這個用法,而是要使用currentStyle 來做查詢。不過我開發的平台在chrome,因此就可以忽略這個問題,大心。

 大概就是這樣啦~那麼,有任何bug請回報。
8八月/110

情人節APP

發布於 BLACKBING

  
今年情人節突發奇想的搞了個APP遊戲給我家女王玩,順便熟悉一下jQuery Mobile。先講一下這個遊戲的流程。

地點

這次的地點我選在離家近的中和環球購物中心,因為對我來說場勘也比較容易。哈哈。進去之後,營造出你已經踏入遊戲世界,請拿出你的通話裝置,遊戲即將開始。

掃描QR Code

下載遊戲程式,請事先檢查有沒有安裝掃QR code軟體。以及環境網路暢通。 2011 valentine qr

安裝APK

記得要是先將女王的Android手機的設定改成「允許接受未知的來源」,不然安裝時還要改來改去就糗大了。 2011 mode app icon

遊戲開始

大方的讓她知道這是一個遊戲,讓她有期待玩遊戲的感覺就好了,我則在旁充當技術指導員,以及故障排除XD,畢竟沒有人能保證寫出來的東西沒有bug 。