星期二, 2月 26, 2013

[3C] 購買筆電心得,極不推薦崑碁資訊


  最近採購筆電,因為有朋友崑碁資訊就想說做個面子在哪邊採購, 沒想到其服務態度讓人一整個無法接受, 我直接把我的投訴信件貼出來讓大家看. 以便大家之後再採購筆記型電腦可以作為一個參考.


您好崑碁資訊

我是禮拜天在貴公司購買 Lenovo Y500的顧客,而這次的購買體驗讓我非常的失望.
首先,我也是資訊工作從事人員, 面對客戶我永遠秉持著專業態度,並且以我的專業為傲.

可是這次購買經驗,我完全感受不出貴公司從事人員的專業以及敬業精神.

有兩件事情我會隨時會掌握住就是客戶的時程以及對客戶的承諾.
以及不把客戶當作玩具耍的心態.
而這次購買經驗, 我完全感受不出專業度, 首先連最基本的交貨時程都都無法確切掌握.

我可以理解由於Lenovo原廠維修問題, 所以機器晚到.(我也並非因此而憤怒)
可是好幾次我聯絡我的購買窗口的手機沒有一次聯絡成功.
而打貴公司的電話, 也是要碰運氣才有人接到才有人幫忙轉.
而我主動詢問時間的結果(幾乎都是我主動詢問才會有回電), 往往得到的時間也都很不明確.

第一次是禮拜一下午 3, 4點.
第二次是禮拜一 8, 9點.
之後延期到禮拜二下午 3, 4點.
之後延期到禮拜二下午 8, 9點.
最後我決定要退訂了才跟我有一個比較明確的時間. 禮拜二下午 7點30.

而當我抵達那邊取貨時, 取貨的人員似乎根本不知道我的貨品在何處.
打了一堆電話跑了一堆地方才把我的貨品從某個地方搬下來.

而最後當我已經要脫離這場購買經驗噩夢之後, 貴公司的收納小姐打來說:
他發票金額打錯, 請問我能不能走回去跟他換發票.(好像因為月底了吧有點趕).
那請問一下有考慮上班時間來我公司跟我拿發票麼?

請尊重客戶的時間時程以及不要把客戶當作玩具耍. 這是我的結論.
我要求兩件事情, 第一 - 把我拆下來的8GB記憶體歸還給我, 這是我應該取回來的元件.
第二我要求金額 1000新台幣或等值的電子產品賠償, 老實說賠償不大.
我只是希望相關人士記住, 請尊重客戶, 尊重自己的工作.


星期一, 2月 25, 2013

[JavaScript] Drag and Drop implementation - Drop

  上一篇我們介紹 Drag and Drop的 Drag, 現在我們來實作看看Drop.的困難點會在哪邊呢? 我們就來討論看看.

  Drag and Drop操作主要分做三部, mouseDown, mouseMove 以及 mouseUp. 而 Drag則複雜的在前面兩個 (Down 跟Move). 所以 Drop自然就在 mouseUp囉!

  我本來一度很天真的以為有辦法透過 onMouseUp(event) 的 event取得 drop區域的物件. 結果實作才知道, 這 event指的是我們操作的 draggable物件. 所以要取得 drop區域這邊其實是要經過計算的, 才能算出我們到底有沒有丟到到我們想要的區域.
  下面是範例, 請大家點擊 edit on 點開來看會比較完整.

Check out this Pen!

  我們在一開始宣告一個變數存放 dropArea, 而在onMouseUp這邊我們增加了了判斷. 判斷拖拉的物件是不是有落在掉落的此在範圍的 offsetWidth跟 offsetHeight裏面.

  這個 Drag and Drop的範例的重點我大致擷取如下.

  • 三個步驟
    • onMouseDown
    • onMouseMove
    • onMouseUp
  • onMouseDown: 取得滑鼠點擊物件的偏移量 ( mouseOffset 不然移動時候設定位置會錯位)
  • onMouseMove
    • 將拖拉物件 display設定為 absolute.
    • {x,y} = 滑鼠位置-滑鼠點擊物件偏移量
    • 滑鼠位置.x = event.clientX + document.body.scrollLeft - document.body.clientLeft
    • 滑鼠位置.y = event.clientY + document.body.scrollTop  - document.body.clientTop 
  • onMouseUp:
    • 利用物件的 offsetWidth跟 offsetHeight計算是否落在 drop區域.
  當然 Drag and Drop作法很多種. 只是趁這次探討這問題的同時提出一種做法而已.


星期五, 2月 22, 2013

[JavaScript] Drag and Drop implementation - Drag

  之前有人問過我, 如果沒有 jQuery或是 YUI的函式庫, 要你實作一個拖拉的效果 (Drag and Drop)的效果,你會怎麼做? 好的問題比好的答案更為難得, 雖然時間有點久了我還是找時間自己思考了一下我會怎樣做.

  先從下面三個行為來思考, 首先就是要算出滑鼠的位置.這邊真的就是一門數學大工程了.
Ref.1 瀏覽器的各位置寬度屬性
  
  雖然有點這範例圖示瀏覽器版本舊了, 不過很多概念都還是可以使用的.


  • onMouseDown: 將滑鼠點擊的物件取出.
  • onMouseMove
    • 設定滑鼠 style為 absolute.
    • 計算滑鼠位置: mousePosition - mouseOffset
      • x: (event.clientX + document.body.scrollLeft - document.body.clientLeft) - mouseOffset.x
      • y: event.clientY + document.body.scrollTop  - document.body.clientTop  - mouseOffset.y
      • mouseOffset: 設定物件為滑鼠的點擊後經過運算的位置 (請參考下方原始碼)
      • 因為沒人知道使用者會點在物件的哪個位置上, 所以這邊要稍微計算一下.(使用offsetLeft跟 offsetTop做運算.)
  • onMouseUp: 取消滑鼠物件,設定為NULL.
  這是 Drag的作法, 還有 Drop的做法待續.
Check out this Pen!


[Reference] 
[Ref.1] Browser client X scrollLeft client left
[Ref.2] Event对象的5种坐标


星期四, 2月 21, 2013

[CSS] how to use white-space

  最近在玩這 css屬性: white-space, 相信很多人在用的時候常常都是一知半解在玩他. 不過瞭解原理跟定義之後其實是蠻簡單的屬性. white-space有六個 property values, inherit是繼承父元件屬性值就不另外介紹, 下面跟各位一一就定義說明一下.

  • normal: 連續的空白將會被合併為一個, 文字在容器內會合理的換行.
  • nowrap: 連續的空白將會被合併為一個, 文字直到遇到 <br> 標籤才會換行.
  • pre: 空白將會被保留, 換行符號 (line break)也會呈現. 效果類似 HTML的 <pre> 這個標籤.
  • pre-wrap: 空白將會保留, 在容器內文字也會合理換行, 遇到換行符號 (line break)也會換行.
  • pre-line: 連續的空白將會會合併為一個, 在容器內文字也會合理換行, 遇到換行符號 (line break)也會換行.
  下面我實做了這幾個案例, 各位可以觀察 第一句子後面的 Vestibulum這邊空白字元跟換行的情況, 就比較知道white-space的實際運作情況. 可以點擊右上角 Edit on CodePen連結顯示完整程式碼.

Check out this Pen!

星期二, 2月 05, 2013

[JS] keyCode for KeyDown, KeyPress and KeyUp

  之前就一直蠻困惑這問題的, 這次索性做個例子解釋一下原因.首先還是從最基本原理先解釋一下. 為求看得清楚,我這邊就使用 KeyDown, KeyPress 跟KeyUp 大小寫區分.

  • KeyDown: 鍵盤按鍵按下去所觸發事件, 若一直按著, 就一直觸發. (合理! 因為一直按著字就一直出來.)
  • KeyPress: 鍵盤按鍵按下去所觸發事件, 順序是先 KeyDown 然後再觸發 KeyPress.
  • KeyUp: 放開鍵盤按鍵時候觸發事件.
  下面是我使用 YUI所建立的範例, 若執行可以很簡單看出來 KeyDown, KeyPress所回傳的 key code是不同的.
  而 KeyPress的 key code就是按鍵的 ASCII值. 而我們使用Shift去切換大小寫對KeyPress的key code有影響, 但是對 KeyDown沒影響 (以大寫的 key code為主).

  • KeyCode範例

Check out this Pen!


  附註一點我試做了若持續按著鍵盤觸發, 擷取 KeyDown跟 KeyPress先後順序的記錄下來看, 發現其先後順序並非交錯執行( KeyDown-> KeyPress-> KeyDown-> KeyPress), 這是要注意的地方.


星期五, 2月 01, 2013

[JavaScript][OO] this object memo

  最近在跟Josehpj (啊嗚)討論 JavaScript的 Object Oriented 時候討論到 this 物件, 啊嗚有提到一段話,我直接引用如下:
JavaScript 在語言本身、模擬物件導向的開發中,this 都是很清楚的代表一個 instance。

把 this 搞複雜的原因,其實是瀏覽器特有的 DOM API。
像是 DOM Event、或像是 window.XMLHttpRequest 這樣的全域方法。
this 在對應的處理函式中都不會是所預期 instance。
這也是為什麼在 Y.on 或 Y.io 都有提供設定 context 的參數。
或者得自己去使用 call 或 apply 取執行 Handler、讓 Handler 正確處理。

如果今天開發的是沒有瀏覽器的 JavaScript,例如 Node.js,
this 通常是不會造成太大的困擾的 :)

  再說程式之前我先名詞解釋一下: "context", 何謂 context, 中譯最接近的意思就是上下文, 前後文. 常常我們看到一個句子會不太懂他的由來的時候, 若知道他的上下文, 我們很快就可以知道他的涵義.

  這邏輯推到變數也是一樣, 看到一個變數我們可能不太知道意義的話, 若能知道他的上下文, 大概就比較知道他到底是誰使用他了, 而下面例子當中所舉的的 this, 就是上面說的 context(上下文). 以程式舉例, 我後面有標 (1) (2) (3) 註解:
 on: {
   viewload: function () { 
      api = this;
      api.get(node).
         one('form').on('submit', _handleSubmit, api); 
      // (1).api is the context
    }
 }
 _handleSubmit = function (event) {
   var _api = this; //(2) this is api from (1) context
   _api.get(node).all('input');

   _enableForm.call(_api, arg1, arg2); 
   //(3.1) this _api is context
   _enableForm.apply(_api, [arg1, arg2]); 
   //(3.2) this _api is context
 }
  上述的範例說當一個模組在頁面載入完成要執行的 function call (on viewload). 當按下 Submit 按鈕送出之後相對應的handler (_handleSubmit) 會處理相對應的動作.

submit是 event的名字,  _handleSubmit是 callback funciton, 而第三個參數就是context了.

  而 (3.1) , (3.2)則是 JavaScript常拿來執行函式的方式.

  下方例子則是特別情況, 假設我有個物件 _api有 confirm的方法( 類似於 JavaScript的 confirm), 傳入message, 以及 callback. 而此時callback有需要 _api當其 context.則此時可以使用YUI的 Y.bind.


_api.confirm(message, callback); 
//callback will need _api as context
_api.confirm(message, Y.bind(callback. _api)); 
//callback will need _api as context

這次的 JavaScript this之旅真是學到不少東西啊!