2012-12-06

SQL Server 分頁 (Paging) 的寫法

參考 [SQL Server]幾種分頁(Paging)寫法

2012-11-11

console.log fallback

上次遇到 console.log 在 IE 上的問題, stackoverflow  上有不錯的解法。
「console.log is only available after you have opened the Developer Tools」只能說花熱發...

練習打包成小工具 console_log_fallback.js
(function(){
  'use strict';
  var _scripts = document.getElementsByTagName('script');
  var _script = _scripts[_scripts.length-1];
  var _url = _script.src;
  var _qi = _url ? _url.indexOf('?') : -1;
  var alertStead = false;
  var i, param, params = _url.substr(_qi + 1).split('&');
  for (i = 0; i < params.length; i++) {
      param = params[i].split('=');
      if (param[0]=='alert' && parseInt(param[1])) {
          alertStead = true;
      }
  }

  if (typeof console === "undefined" || typeof console.log === "undefined") {
    console = {};
    if (alertStead) {
      console.log = function(msg) {
        alert(msg);
      };
    } else {
      console.log = function() {};
    }
  }
})();
使用以下方式時, 在 IE 可以用 alert 來替代 console.log 除錯:
<script src="console_log_fallback.js?alert=1" type="text/javascript"></script>

在 CodeIgniter 使用圖形驗證

◎方式一: 使用內建的 CAPTCHA Helper
   在使用手冊中, 建議用 DB 來記錄 captcha word; 個人是比較習慣使用 session 來記錄, 這樣可以省掉 DB 的操作。步驟:

1. 在 controller 類別的建構式中載入 CAPTCHA Helper 和 SESSION Class。
$this->load->library('session');
$this->load->helper('captcha');

2. 建立一個目錄用來暫存 captcha 圖片, 注意該目錄必須設定為 writeable。以下的範例是在 document root 建立名為 captcha 的目錄, 目錄裡的圖形檔過期後會自動被刪除。

3. 在 controller 類別中定義產生圖形的方法:
    private function captcha_img() 
    {
        $pool = '0123456789';
        $word = '';
        for ($i = 0; $i < 4; $i++){
            $word .= substr($pool, mt_rand(0, strlen($pool) -1), 1);
        }
        $this->session->set_userdata('captcha', $word);
        $vals = array(
            'word'  => $word,
            'img_path'  => './captcha/',
            'img_url'  => $this->data['baseURL'] . 'captcha/',
            'expiration' => 1200
            );
        $cap = create_captcha($vals);
        return $cap['image'];
    }
●   $word 為亂數產生的字串, 可以自訂產生的方式。
●   接著將 $word 值設定到 session 存起來, 以方便之後的比對。
●   $vals 為建立 captcha 時的設定:
   ○   word: 欲顯示的文字
   ○   img_path: 暫存圖形的目錄
   ○   img_url: 圖形目錄的 URL
   ○   expiration: 過期的時間, 單位為秒
●   $cap['image'] 會是包含圖片路徑的 <img> 標籤的字串

4. 比對驗證碼:
$this->input->post('captcha') == $this->session->userdata('captcha')

 CAPTCHA Helper 優點是使用起來方便, 不需額外安裝其它外掛; 缺點是較為陽春, 預設大小為 150 * 30, 外觀幾乎不能用設定方式更改。

Flash 開發效能檢測工具: TheMiner

一般常使用 Hi-ReS-Stats 來檢測 Flash 的效能, 可以看到簡單的 FPS 的記憶體使用情況。

剛剛無意間發現 TheMiner (舊名為 FlashPreloadProfiler), 試用了「非商業版」, 功能不少, 感覺還不錯。有非商業版就表示有商業版, 請自行閱讀其使用者條款 (有些功能商業版才提供)。


作者的 Blog 介紹: http://jpauclair.net/flashpreloadprofiler/
官網: http://www.sociodox.com/theminer/
安裝方式: http://www.sociodox.com/theminer/tutorial/tutorial_install.html

安裝方式建議使用第三種, 步驟:
1. 設定允許 TheMiner_zh-tw.swf 的全域安全性 (Flash Global Security Settings)
2. 在用戶家目錄設定 mm.cfg 檔, 在 Win 7 上的設定情況
PreloadSWF=PreloadSWF=C:\Users\用戶名稱\TheMiner_zh-tw.swf

在 Flash IDE 測試影片時, 就可以看到左上方的工具列了。

2012-11-10

用 jQuery Address 實現「深連結」

jQuery Address 提供所謂「深連結」(Deep linking) 的功能, 簡單講就是以 # 實現不換頁而標示 (或顯示) 網頁的部份內容。
套現在流行的「微」文化, 應該也可以稱為「微連結」吧 XD。

AS 開發者會覺得這東西很像 SWFAddress, 沒錯兩者目的是一樣的, 而且是同一家公司開發的優質兄弟產品。

jQuery Address 是顧名是 jQuery 的外掛, 使用起來相當方便。
官網: http://www.asual.com/jquery/address/
官方最能說明其功能的範例: http://www.asual.com/jquery/address/samples/api/

用 Highlight.js 美化網頁上的程式碼

Highlight.js 能讓網頁上的程式碼更容易閱讀, 支援數十種程式語言, 而且可以自動判斷程式語言, 無需指定。
缺點是, 程式碼若太短判斷可能不正確。
官網: http://softwaremaniacs.org/soft/highlight/en/
Demo: http://softwaremaniacs.org/media/soft/highlight/test.html
Download: http://softwaremaniacs.org/soft/highlight/en/download/
Github: https://github.com/isagalaev/highlight.js

使用方式, 請看 Github 上專案首頁的 readme.

2012-11-06

CKEditor 和 KCFinder 設定

FCKEditor 改版為 CKEditor 把上傳圖片拿掉了。若要有檔案上傳的功能,可以使用官方推出付費的 CKFinder、使用免費的 KCFinder,或自行編寫上傳功能。在此選用 KCFinder 設定。

配置方式可以參考這篇「如何配置 CKEditor 使用 KCFinder?

2012-10-07

網頁除錯: IE7 和 IE8

客戶反應網站使用 IE 瀏覽時, 發生若干問題。雖然對 IE 反感到了一個極致, 但問題還是得處理。安裝了測試環境 IE Tester , 預設提供 5.5 ~ 9 的版本, 是很方便的工具 (分頁有時很容易當掉)。
大致上是兩個因素造成問題:

  1. IE7 沒有提供 JSON 類別
  2. IE 的 event 可能不會從事件處理器丟出 (依版本而異)


2012-09-22

使用 console.log 測試 JavaScript 時

開發網頁 JavaScript, 我個人偏好使用 Google Chrome 的 console.log() 來除錯。但發佈時若沒有把 console.log() 註解掉, 在 IE 上就會發生悲劇, 產生 Error (使用的是 IE9)。離奇的是, 在 IE 使用開發者工具, console.log() 不會發生錯誤, 但切回一般模式就 GG 了... WTF。

2012-09-15

Microsoft HTTPAPI/2.0 佔用 80 port

安裝 SQL Server 2008 後, WAMP server 的 Apache 就無法啟用, 測試了一下發現是「Microsoft HTTPAPI/2.0」佔用的 port 80。Google 說是 SQL Server Reporting Services 佔用了, 只要把它停掉就可以放出 80 port。
在「控制台」→「系統管理工具」→「服務」裡停止「SQL Server Reporting Services」。

2012-09-14

MSSQL *.trc 追蹤檔處理

在這裡使用 SQL Server 2008 R2 評估版

使用 SQL Server Profiler 開啟第一個追蹤檔, 接著使用
「檔案」>「另存新檔」>「追蹤資料表」
連結 DB 之後輸入資料表名稱即可。

2012-09-02

測試 AIR 的 LoaderInfo.parentSandboxBridge 用法

最近遇到一個狀況, AIR App 要載入放在 applicationDirectory 以外的 swf 檔。某些 swf 運作正常, 但少部份無法正常執行。後來在官網找到了解決方式: AIR security / Scripting between content in different domains

2012-08-26

Adobe AIR 快速儲存 JPEG 或 PNG 圖檔


Flash 以往將點陣圖資料轉換為 JPEG 或 PNG 格式都是透過 as3corlib 裡的 API, 當點陣圖資料較大時, 轉換的速度明顯變慢。好消息是現在可以使用原生的轉換功能, 速度快許多。

請先參考 Flash CS6 新增 AIR SDK , 將 AIR SDK 新增 3.3 以上。

Flash Player 11.3, AIR 3.3 之後的版本, 在 BitmapData 類別新增了 encode() 方法。分別搭配 JPEGEncoderOptions, JPEGXREncoderOptions, PNGEncoderOptions 設定就可以快速將陣圖資料轉存為 JPEG 或 PNG 檔。

SQL 語法片段小記

個人使用的 SQL 語法幾乎都是最基本的, 以下記錄幾個最近使用 ActionScript 時用到的片段:

1. 如果某筆記錄已經存在, 則更新該記錄
var sql_xml:XML = <s>
 UPDATE "{TABLE_NAME}"
 SET {type}='{path}'
 WHERE sid=(
  SELECT sid FROM "{TABLE_NAME}"
  WHERE "year"={year} AND "month"={month} 
  AND "date"={date} AND "page"={page}
 );
 </s>;
2. 如果某筆記錄不存在, 則新增記錄
var sql_xml:XML = <s>
 INSERT INTO "{TABLE_NAME}" (year, month, date, page, {type})
 SELECT {year}, {month}, {date}, {page}, '{path}'
 WHERE NOT EXISTS (
  SELECT * FROM "{TABLE_NAME}" 
  WHERE "year"={year} AND "month"={month}
  AND "date"={date} AND "page"={page}
 );
 </s>;
2. 兩張表 "content" 和 "content_usage" 是以 INNER JOIN 的方式查詢。在變更 "content_usage" 而需要 "content" 的條件時
var sql_xml:XML = <s>
 UPDATE "content_usage"
 SET "open"=0, "open_date"=NULL
 WHERE EXISTS (
  SELECT * FROM "content"
  WHERE "cid"="content_usage"."cid" AND "lv" &gt;= {level}
 );
 </s>;

2012-08-23

Adobe AIR 的 SQLite 之 DATETIME 類型

一般 SQLite 的工具 (例如: Firefox plugin - SQLite Manager) 對其 DATETIME 資料類型, 裡面還是使用 TEXT 的方式處理, 以字串表示。

AIR 的 SQLite 引擎則是使用浮點數的表示方式, 貼心的地方是在讀取時會是 Date 物件。但是, 若以 AIR 去讀 DATETIME 類型 "2012-08-23 18:18:18" 這樣的文字格式, 將會無法顯示正確的日期; 若 SQLite Manager 去讀取 AIR 寫入的 DATETIME 類型 將會顯示浮點數。相互之間無法讀取。

解決的方式:

  1. 不使用 SQLite Manager, 使用 Lita 之類 AIR 寫成的工具。
  2. 若和其它程式語言合作開發時, 第一種方式就不方便了。可以將日期欄位設定為 TEXT 而不要使用 DATETIME, 如此一來以字串來處理就可以了。

2012-08-14

Flash Player 11 開始支援原生的 JSON

Flash Player 11.0 / AIR 3.0 開始支援原生的 JSON

屬預設套件 (default package) 的 JSON 類別, 方法同 JavaScript 的用法, 靜態方法使用 stringify() 和 parse()。注意: 在此並不是用 encode() 和 decode()。

2012-08-10

Sublime Text 2 設定 ActionScript 3 開發環境

Sublime 預設的 ActionScript 是支援 2.0。AS2 個人幾乎沒在寫了,以下的步驟是改成 AS3 的開發環境:

先在 Sublime Text 2 上安裝 Package Control

利用 Package Control 安裝 ActionScript 3 plugin。

  • 在 Mac 上按 command + shift + p
  • 輸入 "install", 選擇 "Package Control: install package"
  • 然後選 ActionScript 3 安裝

點選 Preferences > Browse Packages..., 開啟檔案管理員。

將 ActionScript 目錄裡的檔案移除 (或變更名稱)。

將 ActionScript 3 目錄裡的檔案拷貝到 ActionScript 目錄。

在 ActionScript 目錄, "ActionScript 3.tmLanguage" 改名為 "ActionScript.tmLanguage"。

利用 Package Control 移除 ActionScript 3 plugin。

  • 在 Mac 上按 command + shift + p
  • 輸入 "install", 選擇 "Package Control: remove package"
  • 然後選 ActionScript 3 移除

最後,依據原有的 .sublime-snippet 檔格式,去新增自己的 snippet。




2012-07-29

Eclipse 語系設定

參考自 "Eclipse 設定編輯畫面的語系 (解決中文亂碼問題)"


Eclipse 語系設定的優先權:

單一檔案的語系編碼 > Project 語系編碼 > Workspace 語系編碼

1) Workspace 語系編碼
  • 開啟 "偏好設定" (Preferences)
  • 左側選單 Generals -> Workspace
  • 右側 Text file encoding 設定

2) Project 語系編碼
  • 專案開啟後,選主選單 Project -> Properties
  • 左側選單點選 Resource
  • 右側 Text file encoding 設定

3) 單一檔案的語系編碼
  • 於 Package Explorer 面版,在文字檔上按右鍵
  • 於 彈跳出來的選單面版,點選 Properties
  • 左側選單點選 Resource
  • 右側 Text file encoding 設定
另外可依副檔名設定編碼:
  • 開啟 "偏好設定" (Preferences)
  • 左側選單 Generals -> Appearance -> Content types
  • 右側 Content types 欄選定文字檔類型
  • 右側 Default encoding 輸入編碼設定

2012-07-19

Publishing APK for Android with ANE included by using Flash CS6

Select Menu: "File > Publish Settings > ActionScript Settings"
Select Tab: "Library path"
Click icon button: "Add New Path"
Click icon button: "Browse to a Native Extension (ANE) file"

After browsing and selecting an ANE file, the file will be added in included files ( Checking "General" tab in "AIR for Android Settings"  ).

Publishing APK by using "AIR for Android Settings" panel, the ANE will be added in the APK file.

2012-07-18

AIR native extension for android (Java)

官方的教學文件裡有一篇 Developing native extensions for Adobe AIR, 裡面的教學算很詳盡, 但有些細節不太正確, 以下是個人初次試做的心得。

官方建議在 Flash Builder 4.6 上安裝 Android Developer Tools 並直接在上面開 3 個 projects: Android Application Project, Flex Library Project 和 Flex Mobile Project。
在 Flash Builder 開 Android Application Project 遇到的狀況:
1. 以系統管理員身分執行 Flash Builder 才能安裝 plug-in。
2. 只能安裝 Android Developer Tools, 無法安裝 Android NDK plugins (問題不明)。
3. 撰寫時要切換到 Java perspective (個人在 Flash Builder 上開 Android Application Project 有莫名的排斥 XD )。

個人是在 Eclipse 上做 Android Application Project 開發:
1. 建立專案時選 Android Application Project。
2. 取消勾選 "Create custom launcher icon", 勾選 "Make this project as a library"。
3. 選 BlankActivity ( Create Activity 應該可以取消)。
4. 將 FlashRuntimeExtensions.jar 加到 libraries 裡 ( 此 jar 位於 AIR SDK 的目錄裡, 如 C:\air_sdk_33\lib\android ) 。
5. 依劇規則撰寫類別檔之後, 我們要的 jar 檔會在 /bin 目錄裡自動生成。

Flex Library Project:
1. 在 Flash Builder 上建立 Flex Library Project。
2. 依規則撰寫類別檔之後, 我們要的 swc 檔會在 /bin 裡。
3. 如官方教學, 在專案的 /src 裡新增一個 extension.xml。例如:
<extension xmlns="http://ns.adobe.com/air/extension/3.1">
  <id>com.riarock.string</id>
  <versionNumber>1</versionNumber>
    <platforms>
      <platform name="Android-ARM">
        <applicationDeployment> 
          <nativeLibrary>shinderstringnative.jar</nativeLibrary>
          <initializer>com.riarock.shinderstringnative.extensions.ShinderStringExtension</initializer> 
      </applicationDeployment> 
    </platform>
  </platforms>
</extension>

打包成 .ane :
1. 將 Android Application Project 裡生成的 jar 檔, 放到專案的 /bin/native 目錄內。
2. 將 Flex Library Project 裡生成的 swc 檔解壓縮 (swc 其實也是 zip 格式), 將 library.swf 放到上一步的 /bin/native 目錄內 (避免打包時, 找不到 library.swf 的錯誤, 理論上打包時應該要自動解壓縮並放到 ane 檔裡才是)。
3. 如官方教學, 在 Flex Library Project 專案的 /src 內新增一個批次檔 package.bat (windows):
set adt_directory=C:\air_sdk_33\bin
set library_directory=C:\Users\shinder\Adobe Flash Builder 4.6\StringANEConnector
set native_directory=C:\Users\shinder\workspace\ShinderStringNative\bin\native

set signing_options=-storetype pkcs12 -keystore "C:\Users\shinder\Desktop\mycert_shinderlin_123456.p12"
set dest_ANE=ShinderString.ane
set extension_XML=%library_directory%\src\extension.xml
set library_SWC=%library_directory%\bin\StringANEConnector.swc

"%adt_directory%"\adt -package -tsa none %signing_options% -target ane "%dest_ANE%" "%extension_XML%" -swc "%library_SWC%" -platform Android-ARM -C "%native_directory%" .
4. 在 命令列中執行  package.bat, 就可以在相同的目錄看到 ane 檔了。
5. -tsa none 的參數可以避免打包時 "Could not generate timestamp" 的錯誤。

測試功能的專案:
1. 在 Flash Builder 上建立 Flex Mobile Project。
2. 在 Properties > Flex Build Path > Native Extensions 加入 ane 檔。
3. 在 Properties > Flex Build Packaging > Google Android > Native Extensions, 勾選 ANE 項目裡的 Package (就是發佈時要包含 ane 檔的內容)。
4. 按 Export Release Build 就可以生成 apk 檔了。

註1: jar, swc, apk 都是 zip 格式, 就可以用 7-zip 之類的工具就查看打包的內容。
註2: Permissions 應該是在 Flex Mobile Project 上設定, 而不是在 Android Application Project 上設定。

2012-07-01

ColorBox 在 IE 上無法正常顯示

夜路走多了, 也會遇到 IE 的 ...
現在網路的測試幾乎都是 Google Chrome 一路到底,IE 能不碰就不碰,但客戶還是很在意的。
用了 jQuery 的小外掛 ColorBox,如死不死在 IE 上就是不 work,網路上找到這篇,原來很多人都碰到了,心裡的訐譙也就少了一半。
我原本 DOCTYPE 開頭為:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
改成以下就 OK 了:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

2012-06-02

測試 AIR-Kinect

跟朋友借了 Kinect 偵測器用以 survey Adobe AIR 的應用。

朋友當初買的是 Xbox + Kinect 整組, 所以沒有附電源線 ( 電源+AUX-USB轉接 )。若是單買 Kinect     會附電源線。網路上電源線大概 360 NT, 原廠的大概 800 NT, 我直接跑去光華買, 問了好幾家才問到一家有賣, 還開價 450 NT, 想說懶得等就直接買了 QQ。

目前在 Windows 上測試還滿容易的, 先到 Kinect for windows 下載並安裝 SDK, Toolkit 應該可以不用安裝 (另一種方式是使用 OpenNI, 但我一直在 windows 7 32-bit 上裝不起來, 就不想試了)。

裝好 Kinect for Windows SDK 之後, 到 as3NUI 下載 airkinect-2-core, 並解壓縮。其中 bin/airkinect-2-core.swc 和 bin/airkinect-2-core-mssdk.ane 是我們會用到的兩個檔案。

as3NUI 建議使用 Flash Builder 4.6 (或其它 IDE ) 去開發, 在這兒有 Video 教學。以下是使用 Flash CS6 來測試的個人步驟:

  1. 建立一個專案目錄 kinect_01/ 。
  2. 以 Flash CS6 新建 AIR 檔案 kt_main01.fla 並存放在 kinect_01/ 裡。
  3. 將 airkinect-2-core.swc 和 airkinect-2-core-mssdk.ane 兩個檔案放到 kinect_01/ 裡。
  4. 在 kt_main01.fla 的「ActionScript設定」裡, 分別於「元件庫設定」加入 .swc 和 .ane 檔。
  5. 發佈時使用「Windows 安裝程式」不能使用「AIR套件」發佈。

以下程式參考 as3NUI 的範例,但寫在 fla 的第一影格:
import com.as3nui.nativeExtensions.air.kinect.Kinect;
import com.as3nui.nativeExtensions.air.kinect.KinectSettings;
import com.as3nui.nativeExtensions.air.kinect.events.CameraImageEvent;
import com.as3nui.nativeExtensions.air.kinect.data.User;
import com.as3nui.nativeExtensions.air.kinect.data.SkeletonJoint;
import com.as3nui.nativeExtensions.air.kinect.constants.CameraResolution;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.display.Graphics;

var kinect:Kinect;
var kinectSettings:KinectSettings;
var bmp:Bitmap;
var skeletonContainer:Sprite;

stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.nativeWindow.visible = true;

if(Kinect.isSupported()){
 bmp = new Bitmap;
 this.addChild( bmp );
 skeletonContainer = new Sprite;
 this.addChild( skeletonContainer );
 kinect = Kinect.getDevice();
 kinect.addEventListener(CameraImageEvent.DEPTH_IMAGE_UPDATE, depthImageUpdate);
 kinectSettings = new KinectSettings();
 kinectSettings.depthEnabled = true;
 kinectSettings.skeletonEnabled = true;
 kinectSettings.depthResolution = CameraResolution.RESOLUTION_640_480;
 kinect.start( kinectSettings );
 this.addEventListener(Event.ENTER_FRAME, myEnterFrame);
} else {
 trace('Kinect is not Supported!');
}

function myEnterFrame(event:Event):void {
 var user:User;
 var joint:SkeletonJoint;
 var gr:Graphics = skeletonContainer.graphics;
 gr.clear();
 for each( user in kinect.usersWithSkeleton) {
  joint = user.rightHand;
  gr.beginFill(0xFF0000);
  gr.drawCircle(joint.depthPosition.x, joint.depthPosition.y, 10);
  gr.endFill();
  joint = user.leftHand;
  gr.beginFill(0x0000FF);
  gr.drawCircle(joint.depthPosition.x, joint.depthPosition.y, 10);
  gr.endFill();
 }
}

function depthImageUpdate(event:CameraImageEvent):void {
 bmp.bitmapData = event.imageData;
}


2012-04-06

對 Dart 的一些看法


看了 What Is Dart, and Why Should You Care? 想記錄一下自己對 Dart 的想法。
Dart 是 Google 用來取代 JS (JavaScript) 所設計的程式語言。以 Google 這樣大的公司要支持一項技術,並沒有多大的困難。但對於目前瀏覽器群雄並起的情況下,我個人並不看好它的流行。

不看好的主因:

  1. 目前 Dart 並不是一項標準,也就是其它瀏覽器並沒有理由去實作它,就算是 Open Source 頂多也只能是個外掛。早期的 VBScript 是除了 JS 外的另一種選擇,但目前似乎很少人在前端使用 VBScript,原因是它只能在 IE 上執行。不過 Dart 是以取代 JS 之姿出現,改進了 JS 上的許多缺點,並不是 VBScript 可以相比的。
  2. 另外,JS 最近蓬勃發展,libs 多如牛毛,要前端開發者放棄好用的 libs (如 jQuery),除非有好的替代品,不然以目前如此年輕的 Dart 而言 libs 是無法跟 JS 相比的。


Dart 的優點:

  1. 新的程式語言,對開發人員而言,除了要熟悉語法,還必須熟稔語言的 API。Dart 是 C-like,全物件導向,語法比較貼近 ECMAScript 4;若有在開發 JS,Dart 的 API 看起來也應該很容易熟悉。
  2. Google 可以為 Dart 在 Chrome 建立讓人驚奇的功能。


目前我選擇 CoffeeScript 的原因是:

  1. 簡潔語法和物件導向的寫法 (或許有人不喜歡沒有 {} 並且要縮排的語法)。
  2. 編譯 (亦可解譯) 為 JavaScript,依然是寫 JS 用 JS 的 libs。


Yepnope.js 和 CoffeeScript 拆檔 (續)

繼上篇 Yepnope.js 和 CoffeeScript 拆檔 改良一下, 使用 CoffeeScript.load() 裡的 callBack 功能, 讓 *.coffee 可以依序載入並執行。另外, 設置了 isDeveloping 變數, 使得在開發的過程避免 *.coffee cache 的問題。

2012-04-05

Yepnope.js 和 CoffeeScript 拆檔

Yepnope.js 和 CoffeeScript 拆檔其實是兩回事。
Yepnope.js 和 RequireJS 提供類似的功能, 都是用來載入外部的 *.js 或 *.css。Yepnope.js 可以依條件而決定是否載入, 同時也可以確保我們要的執行順序, 感覺還不錯。
但 Yepnope.js 和 coffee-script.js 搭配時, 無法直接透過 Yepnope.js 載入 *.coffee 並執行; 而是在載入 coffee-script.js 後, 以 CoffeeScript.load() 分別載入 *.coffee 檔。
以下的範例又搭配 Backbone.js, 為了讓類別定義可以自由取用, 將類別名放在 window.myproj 物件下當做屬性。

CoffeeScript Loader Plugin

require-cs 是使用 RequireJS 的 CoffeeScript Loader Plugin。
其實就是把 RequireJS 和 coffee-script.js 的功能加在一起, 而在沒編譯的情況下可以引入 *.coffee 檔執行。
其 Demo 將 CoffeeScript 分成幾個檔案, 然而皆以 RequireJS 的 module 方式撰寫, 個人比較不喜歡。
RequireJS 其實廣受使用, 排斥 module 寫法純粹是個人喜惡 :P

2012-04-04

JavaScript ( AJAX ) 的跨網域存取

JavaScript 的跨網域存取是透過 XMLHttpRequest 物件。標準為 Cross-Origin Resource Sharing ( CORS ) , 參考資料為: XMLHttpRequest 執行 AJAX 跨網域存取
方式是在被存取的資源設定 HTTP Header 屬性 Access-Control-Allow-Origin, 其值設定為允許存取的網域, 或以 * 表示所有網域。
以下是個 PHP 的例子:
<?php
header("Access-Control-Allow-Origin: http://www.riarock.com");
?>
Hello JavaScript Cross Domain!

Backbone.js 的 Router

Backbone.Router 的主要功能是能夠在不刷新頁面的情況下, 變更 URL, 同時執行不同的功能。不論建立幾個 Router 物件, 要啟作用時都必須呼叫 Backbone.history.start()。

  • 屬性 routes: 用來設定 routes hash 對應的動作 ( actions, functions )。
  • 方法 initialize: 初始化呼叫, 自行定義。建立 Router 物件時若傳入 Object 物件, 讓物件會視為 routes 的設定。
  • 方法 route: 動態設定 routes hash 對應的動作。
  • 方法 navigate: 呼叫此方法以變更 URL。第一個參數為字串, 第二個參數為 Object 物件。Object 物件屬性 trigger 設定為 true 時, 表示要呼叫 route function。Object 物件屬性 replace設定為 true 時, 表示不留在 history 裡。

呼叫 Backbone.history.start() 時傳入的 Object 物件屬性可以有三個:

  • 屬性 pushState: 設定為 true 時表示使用 HTML5 的 pushState 功能, 將不會在 URL 使用 # , 這通常需要做後端 URL mapping 設定。
  • 屬性 root: 如果路徑不是 / 可以使用 root 設定。 
  • 屬性 silent: 如果不願在初始化時呼叫 route function, 把 silent 設定為 trrue。

在 IE 建議不要使用以上三個屬性設定... 囧。

2012-04-02

Backbone.js 的 View

在 Backbone.js, View 經常會和 Model 做關聯, 在這裡先排除 Model, 單純討論 View 的其它功能。

  • 屬性 el: 用來表示對應的頁面元素 (element), 其值為字串類型, 可以是標籤名稱或 id 名稱等 selector。
  • 屬性 tagName: 表示新 View 物件初始的標籤。
  • el 和 tagName 兩者為二選一設定。
  • 屬性 $el: 為對應 element 的 jQuery (或 Zepto) 物件。
  • 屬性 $(selector): 對應子元素的 jQuery (或 Zepto) 物件。
  • 屬性 events: 定義事件 (及事件來源) 對應事件處理的方法。常用的事件: click, dblclick, contextmenu, mouseover, mouseout。

  • 方法 initialize: 初始化的方法, 定義類別時定義。有別於 constructor, 在此不建議使用 constructor。建立 View 物件時, 傳入一個 Object 物件, 會將 Object 的屬性複製給 View 物件。
  • 方法 render: 物件成形的方法, 定義類別時定義。應回傳物件本身 (this)。
  • 方法 remove: 方便從 DOM 將 View 物件移除。同 $(view.el).remove()。
  • 方法 make: 方便由標籤名稱、屬性 (包成 Object )、內容字串, 建立 element。
  • 方法 delegateEvents: 設定事件 (及事件來源) 對應事件處理方法。通常只要定義屬性 events 即可完成自動設定, 而無需手動呼叫此方法。
  • 方法 undelegateEvents: 取消所有設定事件 (及事件來源) 對應事件處理方法。當要讓 View 物件失能, 或暫時從 DOM 移除時, 可以呼叫此方法。


2012-03-30

jsonTrace 小工具修正

jsonTrace 專案 (之前的介紹) 修正了臭蟲, 之前使用遞迴真是不智的選擇, 改成使用陣列, 不會有 stack overflow 的問題了。另外, 可以設定格式化的空白。README.md 有簡要的說明。
註: commit message 居然打錯字 =..=

2012-03-19

JRuby 1.6 同時支援 Ruby 1.8 和 1.9

JRuby 1.6.7 同時支援 Ruby 1.8.7 和 1.9.2
在 Windows 上安裝的方式:

  1. 解壓縮至 C:\ 為 C:\jruby-1.6.7
  2. 設定環境變數 JRUBY_HOME 為 C:\jruby-1.6.7
  3. 將 %JRUBY_HOME%\bin 加入環境變數 PATH 中
  4. 設定環境變數 JRUBY_OPTS 為 --1.9 可以切換為 Ruby 1.9.2 相當的功能。預設為 1.8.7。

命令列上輸入 jirb 開啟 irb 環境
命令列上輸入 jirb_swing 開啟視窗 irb 環境

2012-03-18

AS-PHP-talk 簡介

AS-PHP-talk 放到 github 後, 不知不覺已經過了一年 =..=, 突然想來寫個介紹。

這個專案的目的是為了讓 ActionScript 和 PHP 溝通有另一種較為簡單的選擇, 目前後端只有 PHP 的實作。 以往後端 ( 筆者較常使用 PHP ) 和 AS 溝通, 比較舊的方式是通過 XML, 比較多人用的是透過 AMF ( Flash remoting ), AS-PHP-talk 則是使用 JSON。

JSON 和 XML 相比的話, 同樣都是文字格式。XML 可以制訂的資料比較複雜; 然而, JSON 可以描述 Object、Array 和基本類型的資料 , 其實已經很夠用。

JSON 和 AMF 相比的話, AMF 體積應該會比較小, 但由於 AMF 是二元資料, 除錯相對於文字格式的 JSON 要來得麻煩。JSON 資料可以直接秀在網頁上, 有錯誤時也可以在網頁上就查覺。

前端和後端資料交換的程式, 最麻煩就是除錯。AS-PHP-talk的目的是, 可以在完全沒撰寫前端程式 ( Flash ) 之前, 利用簡單的網頁就達到後端 PHP 程式的除錯。後端的開發人員可以完全不用理會前端程式的開發進程; 前端的開發人員也可以透過簡單的後端 ( 送假資料 ) , 進行前端的開發。前、後端的程式可以很方便的切開來。

2012-03-16

在 Chrome 開發人員工具裡動態載入外部 JS libs

如何在 Google Chrome 開發人員工具裡, 動態載入外部 JS libs ?
qop 在 StackOverFlow 找到這篇 how to: dynamically load google ajax api into chrome extension content script 。
打開 Developer tools [ Ctrl + Shift + i ], 於 Console 內貼上以下的程式碼就可以在 Console 做些 Underscore/Backbone 練習 ^_^
var headElement = document.getElementsByTagName("head")[0];
var jsElement = document.createElement('script');
jsElement.type = 'text/javascript';
jsElement.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
headElement.appendChild(jsElement);
// ---
jsElement = document.createElement('script');
jsElement.type = 'text/javascript';
jsElement.src = 'http://documentcloud.github.com/underscore/underscore-min.js';
headElement.appendChild(jsElement);
// ---
jsElement = document.createElement('script');
jsElement.type = 'text/javascript';
jsElement.src = 'http://documentcloud.github.com/backbone/backbone-min.js';
headElement.appendChild(jsElement);

2012-03-14

Hello Backbone.js 用 CoffeeScript 改寫

Hello Backbone.js 是不錯的 Backbone.js 入門教學, 為了個人學習 CoffeeScript, 所以把裡面的例子都以 CoffeeScript 重新改寫, 希望可以一石兩鳥。執行使用的 JS lib 除了多了 http://jashkenas.github.com/coffee-script/extras/coffee-script.js 之外, 其餘只有版本上的差異。這篇主要的目的是做個人的學習過程記錄。

2012-02-29

Backbone.Events

Backbone.Events, CoffeeScript 對照寫法

JavaScript ------------------------------------------------
var object = {};
_.extend(object, Backbone.Events);
object.on("alert", function(msg) {
  alert("Triggered " + msg);
});
object.trigger("alert", "an event");

CoffeeScript ------------------------------------------------
obj = _.extend {}, Backbone.Events
obj.on 'alert', (msg)->
  alert 'Triggered ' + msg
obj.trigger 'alert', 'an event'

2012-02-28

Backbone.js 與 CoffeeScript

參考了一些 Backbone 搭配 CoffeeScript 的文章:


之後, 將 Backbone 範例 Todos 改用 CoffeeScript 重寫練習, 果然一開始就踩到地雷。
改寫之後, 是完全不會動的, 後來發現 initialize 方法根本沒被觸發, 但 constructor 有被觸發, 把 constructor 註解後就可以了。也就是使用 initialize 方法, 而不用 constructor。

另外, Backbone 原本的繼承寫法是呼叫 extend 方法, 除了改用 extends 繼承寫法之外, 其初設物件 (第一個參數), 可以放到 initialize 方法裡做初始化的動作。

CoffeeScript.js

感覺最近一兩年, JavaScript lib 發展的速度相當快, 在 Nodejs 問世之後, JS 更是如虎添翼。但個人對 JS 的 OO 寫法相當不適應, 因此看上了 CoffeeScript, 最近就學點基本語法。在還沒有接觸 CoffeeScript 之前, 會覺得寫某種程式語言再編譯成 JS, 有脫褲子放屁之疑慮。試用後發現, CoffeeScript 真的比較易讀易寫, 代價就是要學點新語法, 當然這問題是見仁見智, 因人而異。

一開始我會在網頁裡使用 <script src="http://jashkenas.github.com/coffee-script/extras/coffee-script.js" type="text/javascript" charset="utf-8"></script> , 如此一來就可以在 <script type="text/coffeescript"></script> 裡寫 CoffeeScript (或者 <script type="text/coffeescript" src="my.coffee"></script>  )。

單單學語法其實很無聊的, 試著改 Backbone.js 上的 todos 範例, 先將 backbone-localstorage.js 改寫成 backbone-localstorage.coffee, 結果發現一直抓不到 Store 類別, 裡面包括了兩個問題:

  1. 混用 todos.js 和 backbone-localstorage.coffee, 但 backbone-localstorage.coffee 被編譯成 JS 是比較慢的, 因此 .coffee 的內容是比較慢執行的。解決的方式是, 先編譯成 JS。
  2. CoffeeScript 的所有變數都會被包在 local 裡, 所以類別要定義為 global 時可以使用 '@' 或 'window.'。原來的 Store 類別要使用 window.Store 或 @Store 去定義。

2012-02-27

使用 RVM 時發生的 openssl 錯誤

之前在 ubuntu 安裝 rvm/ruby/ror 碰了一鼻子灰, 停了好一陣子沒看 ruby 的東西。看到有本書提到 middleman, 就來玩玩看。
使用的 OS 是 Fedora 16, 原則上在安裝時都算順利, 只有在啟動 mm-server 時, 發生了 "no such file to load openssl error" 的問題無法正常啟動。
在 ruby 論壇找到解法 http://www.ruby-forum.com/topic/90083#1022143

    rvm pkg install openssl
    rvm remove 1.9.2
    rvm install 1.9.2 --with-openssl-dir=$HOME/.rvm/usr
這個做法有個缺點, 因為一開始是用 root 安裝 rvm, 所以重新安裝 ruby 時也必須是 root 用戶安裝, 如此一來就不能在其他用戶使用了。

FB 留言