2008-12-21

apache 301 Redirect 永久重新導向

最近因為 Cookie 重複的問題花了不少時間
當 wacanai.com 及 www.wacanai.com 同時在一台主機上
用遊覽器瀏覽 www.wacanai.com 的網站時
會因為之前在 wacanai.com 所存的 Cookie 變數
當變數名稱重複時瀏覽器只會送出 wacanai.com 的變數
雖然這兩個 domain 在 DNS 上都是正確
但為了避免這樣的問題發生
一台主機最好不要同時擁有這兩種 domain

所以我利用 apache 中的 Rewrite 模組功能
作永久性的重新導向
在瀏覽時都導去 www.wacanai.com 這個網址

首先先確定 Rewrite 模組已經載入了
$ sudo a2enmod rewrite

Apache 還有一個重要的目錄設定就是:
<Directory /myblogroot/>
    AllowOverride FileInfo
    Options FollowSymlinks
</Directory>

如果沒有將這個設定加上
Rewrite 在啟用時會出現 http 403 的錯誤

可以利用 .htaccess 作以下轉址設定
RewriteEngine On
RewriteCond %{HTTP_HOST} ^wacanai\.com
RewriteRule (.*) http://www.wacanai.com/$1 [R=301,L]


參考網址:
301 Redirects & Canonical Redirects for Apache
Apache之AllowOverride參數詳解
2008-12-18

find 指令進階用法 [Linux]

find 指令結構
find [path] [expression]
[path]啟始路徑
[expression]查詢參數

基本參數
-name 以指定的範本搜尋檔案名稱
-iname 同上,但不區分大小寫
find . -name 'a*.jpg'
在當前目錄下搜尋開頭為 a 的圖片檔案

-path 以指定的範本搜尋檔案路徑
-ipath 同上,但不區分大小寫
find . -path '*pics/*pic_*.jpg'
在當前目錄下搜尋 ./pics/pic_01.jpg, ./01/pics/pic_a1.jpg, ./02/pics/01/pic_aa.jpg 這些檔案

-regex 以正規表示式搜尋檔案路徑
-iregex 同上,但不區分大小寫
find . -regex '.*pic_[0-9]+\.jpg'
在當前目錄下搜尋 pic_01.jpg, pic_03.jpg, pic_03.jpg 這些檔案

-type 搜尋檔案類型:一般檔案 (f),裝置檔案 (b,c),目錄(d),連結檔(l),socket(s),FIFO(p)
find . -type l
在當前目錄下搜尋所有連結檔

-size 搜尋檔案大小:byte(c),Kilobytes(k),Megabytes(M),Gigabytes(G)
find . -size 3k
在當前目錄下搜尋大小為(3kb)的檔案

find . -size +3k
在當前目錄下搜尋大於(3kb)的檔案

find . -size -3k
在當前目錄下搜尋小於(3kb)的檔案


時間參數
-mtime 搜尋檔案的修改時間(天)
-mmin 同上,以分鐘為單位
-ctime 搜尋檔案的建立時間
-cmin 同上,以分鐘為單位
-atime 搜尋檔案的最後開啟時間
-amin 同上,以分鐘為單位
find . -mtime 3
在當前目錄下搜尋3天時修改的檔案

find . -mtime +3
在當前目錄下搜尋3天前修改的檔案

find . -mtime -3
在當前目錄下搜尋3天內修改的檔案


帳戶參數
-user 搜尋指定帳戶名稱的檔案
-nouser 同上,但是搜尋非帳戶名稱的檔案(-not -user)
find . -user ftp
在當前目錄下搜尋使用者名稱為(ftp)的檔案

find . -nouser ftp
在當前目錄下搜尋使用者名稱非(ftp)的檔案

-group 搜尋指定群組名稱的檔案
-nogroup 同上,但是搜尋非群組名稱的檔案(-not -group)
find . -group ftp
在當前目錄下搜尋群組名稱為(ftp)的檔案

find . -nogroup ftp
在當前目錄下搜尋群組名稱非(ftp)的檔案

-perm 搜尋指定的檔案權限
find . -perm 744
在當前目錄下搜尋檔案權限為(744)的檔案

find . -perm +744
在當前目錄下搜尋檔案權限小於(744)的檔案,(600,444)

find . -perm -744
在當前目錄下搜尋檔案權限大於(744)的檔案,(744,774)

如果上面的指令你都會了,來點特別的吧!

邏輯處理
() 將搜尋條件優先處理,在使用上記得用'\'跳脫
-not 將搜尋條件反相
! 同上,在使用上記得用'\'跳脫
-and 邏輯的(和)
-a 同上
-or 邏輯的(或)
-o 同上

find . \(-user ftp -perm 744\) -or \(-group ftp\)
在當前目錄下搜尋
使用者名稱為(ftp)且權限為(744)的檔案

群組名稱為(ftp)的檔案

其他
-delete 將搜尋出來的檔案刪除
find . -user ftp -delete
刪除使用者名稱為(ftp)的檔案

-printf 將搜尋出來的結果以自訂格式輸出
find . -printf '%p\n'

-fprintf 將搜尋出來的結果以自訂格式輸出至文件
find . -fprintf a.txt '%p\n'

參考來源:
find - Linux Command - Unix Command
2008-12-06

離開頁面前的對話匡 window.onBeforeUnload 事件

在頁面改變前會觸發 window.onBeforeUnload 事件
但要怎麼產生出離開前的確認匡呢?
根據在 MSDN(onbeforeunload Event) 找到的說明
When a string is assigned to the returnValue property of window.event, a dialog box appears that gives users the option to stay on the current page and retain the string that was assigned to it. The default statement that appears in the dialog box, "Are you sure you want to navigate away from this page? ... Press OK to continue, or Cancel to stay on the current page.", cannot be removed or altered.

我們只要對這個事件 return 一個訊息就可以達成
除了 undefined 以外的所有值都會產生確認匡

那到底要怎麼做呢?
/*註冊事件*/
window.onbeforeunload = function(){
    return "是否要離開此頁面";
};

/*解除事件*/
window.onbeforeunload = null;


就這樣簡單的幾行就可以達成
真是簡單到不行
而且大多數的瀏覽器都支援

展示頁面(Demo Page)
2008-12-05

Wacanai 改版了

花了一個多月的時間
終於將新的版面上線了
除了版面上的改變外
這次也降低 JavaScript 的使用量
根據之前的經驗
太多的 JavaScript 只會讓瀏覽器當掉
在 CSS 樣式上的規劃也改善不少
當然也為了介面與功能配置上做了一些修改
雖然整體來說還不是很完整
但希望新的版面能讓使用者感覺更親切

我們的網站:www.wacanai.com
2008-11-15

在固定大小的排版中做圖片選取

之前所用的圖片裁切介面(MooCrop 正方形選取( Square ))
在大尺寸圖片的選取上不是很直覺
明明就只是要裁出一張固定大小的圖
卻暫了大量的版面配置
所以我採用網路地圖的機制做了一個裁切工具
這個想法目前還只是個雛形

展示頁面(Demo Page)
2008-11-03

OWASP 2008 資訊安全年會-心得

年會都快過一個星期了,終於在六日將筆記中的紀錄作了整理,雖然都是觀念上的問題,但如果你以前沒有這些觀念的話,請現在開始養成,因為這些都是很重要的問題。
在開發過程就該考慮安全問題
在系統發展生命週期(System Development Life Cycle[SDLC])中就應該考量安全性問題,甚至是在系統設計階段,一個好的設計可以提升系統安全性,可是一個壞的設計,卻會讓整個系統漏洞百出。
別相信[先求有再求好]這句話,因為錯誤的決策很有可能讓整個網站打掉從練,那怕是開發一年多的系統都會有可能碰到這個問題,不如現在多花 2 小時,未來省 10 小時。
Server 管理介面是否安全
別以為將管理頁面放在別人連不到的地方就可以放心,像 phpMyAdmin 這類的頁面常常被放再公開的網站目錄下,即使是換了名稱還是會有被猜到的可能,所以在公開的網站目錄下避免放置這類的管理介面。
在網站目錄下是否有不應該存在的檔案
常常在上線更新時將整個系統壓縮檔放在網站目錄下,如果不甚檔名被別人 try 出來了,那整個系統的架構都會被看光,甚至 DataBase 的帳號跟密碼都會外洩,所以在網站目錄下的檔案管理對整個安全性是非常重要的。
系統設定是否安全
在 Web Server 或其他 Server 的設定是否有安全性的漏洞,Web Server 會有可以跨目錄的設定,這常常會是 Server 的機密外洩的漏洞之一,而且有許多漏洞是在系統上線後產生的,由於 Server 環境的不同造成漏洞的出現。
相關文章:
Apache 安全設定-1
Apache 安全設定-2
PHP SQL Injection 和 XSS 的偵測程式 和 程式撰寫注意事項 - 2008
便利性與安全性是互相矛盾的
在這次的講習後我感覺這兩件事是互相矛盾,雖然不是絕對的,但為了達到好的便利性,就必須在安全問題做更多的處理跟考量,所以在系統的安全防護是有代價的,勢必會花費更多的資源在安全問題上。
互動式網站的漏洞是必然的
只要是互動式網站就會有漏洞,不管是系統上或者是個人資料的處理,或多或少都會有漏洞的存在。
新的技術必定伴隨著新的安全問題
新的技術尚未經過時間的考驗,所以必然會存在未被發現的漏洞,在目前的許多新軟體都有這樣的狀況,甚至是軟體 Update 之後又出現新的漏洞。
個人資料外流得可能性?
網站沒有 100% 的安全機制,與其期望對方的網站系統,不如做好自我保護,別將太過私密的資料放在網路上,因為那個風險實在太高了,那怕是 0.01% 的可能,因為只要過了那唯一的防線後就是海闊天空了,資料就會很快的被散播出去,很帥的事,這份資料就會被備份一百份或一千份,甚至更多。
別忽視安全性測試
人的能力是有限的,總會疏忽一些事情造成一些漏洞的出現,所以還是需要程式去檢查是否有漏洞的存在,雖然光靠[黑箱測試]及[白箱測試]可以找出大部分的漏洞,仍然會有程式找不到的錯誤,還是需要人為去校定。
別太相信自己的能力
在太過於自負的時候,人總會看不到潛在的問題,當你覺得這是安全的時候,請記得查證你的作法及環節是不是會有漏洞的出現。
2008-11-01

用 CSS 實現 blogger [繼續閱讀]的方法

雖然與白花花所寫的在blogger實現繼續閱讀的作法是用同樣的方法,但為了增加使用上的彈性,我做了不一樣的基本設定,讓任何 HTML Tag 只要套用 fullpost 這個 ClassName 就可以在部分閱覽中隱藏。

在 <b:skin> 中的 CSS 設定:

/*部分隱藏樣式*/
.posts-index .fullpost{
display:none;
}


在詳細樣版中找到 <data:post.body/> 這行,並修改成以下形式:

<div expr:class='"post-body
entry-content
posts-"+data:blog.pageType'>
<data:post.body/>
<div style='clear: both;'/> <!-- clear for photos floats -->
<!-- 非單篇顯示時,顯示繼續閱讀 -->
<b:if cond='data:blog.pageType != "item"'>
<p>
<b:if cond='data:post.link'>
<a expr:href='data:post.link'>繼續閱讀...</a>
<b:else/>
<a expr:href='data:post.url'>繼續閱讀...</a>
</b:if>
</p>
</b:if>
</div>
2008-10-07

(IE6) white-space 在表格中怪問題

最近遇到一個怪問題
在 IE6 的表格中設定 white-space 屬性卻無效
只因為 IE6 怪異的 box 解析方式
對於用 px 設定的寬度有至高的優先權
完全忽略 white-space 的存在
解決的辦法就是用百分比(%)定寬

<table border="1"><tr>
<td>彈性欄位</td>
<td style="width: 1px; white-space: nowrap;">文字測試</td>
<td style="width: 1%; white-space: nowrap;">文字測試</td>
</tr></table>


IE6 的呈現:

CSS fixed 定位( FF / IE6 )

fixed 定位主要是以 window 物件區塊做定位依據,所以不會隨頁面捲動而變動定位。

以往要達成這種模式的定位都要利用 JavaScript 的 onscroll 事件去達成,是蠻吃重的一種方法,而且流暢度也不好,會有閃爍的現象。

利用 fixed 定位可以簡化 JavaScript 的開發和負擔,而且又穩定且簡單設定。

body{
    height:1200px;

    /* prevent screen flash in IE6(解決 IE6 不正常閃爍) */
    background:url(nothing.txt) white fixed;
}

div{
    background:#FF0066;
    border:4px solid #FF9999;
}

/* 水平置中 */
.fixed-center{
    width:100px;
    height:100px;
    position:fixed;
    top:50%;
    left:50%;

    /* 上邊界計算 */
    /* -(border-top-width + padding-top + (height/2) ) */
    /* 或者是整體高除以二(offsetHeight/2) */
    margin-top:-52px;

    /* 左邊界計算 */
    /* -(border-left-width + padding-left + (width/2) ) */
    /* 或者是整體寬除以二(offsetWidth/2) */
    margin-left:-52px;

    /* position fixed for IE6 */
    _position: absolute;
    _margin-top:0;

    /* clientHeight:不包含邊匡的區塊高度( padding + height ) */
    /* offsetHeight:包含邊匡的區塊高度( border + padding + height ) */
    _top:expression(documentElement.scrollTop + ( documentElement.clientHeight-this.offsetHeight )/2
    );
}

.fixed-top-center{
    width:100px;
    height:100px;
    position:fixed;
    top:0;
    left:50%;
    margin-left:-52px;

    /* position fixed for IE6 */
    _position: absolute;
    _top:expression(documentElement.scrollTop);
}

.fixed-bottom-center{
    width:100px;
    height:100px;
    position:fixed;

    bottom:0;
    left:50%;
    margin-left:-52px;

    /* position fixed for IE6 */
    _position: absolute;
    _top:expression( documentElement.scrollTop+documentElement.clientHeight-this.offsetHeight );
}


展示頁面(Demo Page)

參考來源:上下左右置中、不隨頁面捲動的內容-小正正教室
2008-09-17

create_function 匿名函數

在 PHP 中的函數只要宣告後就是全域的,而且還不能修改,不小心就會撞名,真是麻煩的事,而且實體宣告在當做變數傳遞時非常麻煩,最近習慣 JavaScript 的函數傳遞方法,為了達到這個作法,PHP 中有一個匿名函數的宣告方法,會直接已變數的形式呈現,可惜的事在宣告上必須用字串編寫,也是很麻煩,但總比沒有好。

<?php
    $newfunc = create_function('$a,$b', 'return $a + $b');
    echo $newfunc(2,5);



參考來源:PHP Manual
2008-09-13

利用 JavaScript 讓 IE6 支援 CSS 2.0 hover 的方法

利用 IE6 特有的 expression 屬性質,去執行 JavaScript 程式。
好處是可以簡化開發,讓設計師可以自己去控制想要的樣式。
壞處是執行大量的 expression 會讓 IE6 很吃重。


ie_hover.htc 中的程式碼:
this.onmouseover=function(){
    if(!this.className.match(/(^|\s)hover(\s|$)/)){
        this.className=(this.className+' hover')
            .replace(/\s{2,}/g,' ')
            .replace(/^\s+|\s+$/g, '');
    }
}
this.onmouseout=function(){
    this.className=this.className
        .replace(/(^|\s)hover(\s|$)/,' ')
        .replace(/\s{2,}/g,' ')
        .replace(/^\s+|\s+$/g, '');
}
this.style.behavior=null;


ie_hover.html 中的 CSS:
p{
    padding-left:30px;
    behavior: url(ie_hover.htc);
}
p:hover,
p.hover{
    padding-left:0;
}


展示頁面(Demo Page)
2008-09-09

CSS 三欄排版

  1. float 排版
    CSS 三欄排版
    這是在 Table 排版之後最常見的排版方式,利用 float 與 clear 的屬性設定去達成的分欄排版。

    最近發現除了利用 clear 屬性的空 Tag 以外還有其他的方式可以達到這個效果,在最外層的 div 上加入以下屬性也可以達到相同的效果:
    * html #demo_1{
        height: 1%;
    }
    #demo_1:after {
        content: ".";
        display: block;
        height: 0;
        clear: both;
        visibility: hidden;
    }
    #demo_1 {
        zoom: 1;
    }
    


  2. table 排版
    CSS 三欄排版
    這是最早期排版方式,雖然有種種的缺點,但還是有很多網站使用,除了利用原有的 Table Tag,也可以使用其他 Tag 設定 display 屬性去達到 Table 排版的效果,雖然在寬度的定義上的彈性,但還是建議保持只有一個欄位的彈性寬度,過多的彈性寬度只會造成意想不到的後果。


  3. margin and float 排版
    CSS 三欄排版
    這是利用中欄的 margin 屬性空出側欄位空間,再利用 float 及負邊界方式去達成的三欄排版,因為 float 屬性不會對整體高度做出貢獻,如果需要側欄的高度影響,必須上擁有 clear 屬性的 Tag 或利用第一個範例的方法,由於中欄沒有 float 屬性所以不能在內容使用 clear 屬性。


  4. margin and position排版
    CSS 三欄排版
    這是利用中欄的 margin 屬性空出側欄位空間,再利用 position 的定位方式去達成的三欄排版,因為 position 屬性不像 float 屬性,可以利用 clear 屬性做出高度的貢獻,所以側欄的高度不可以大於主欄,要不然會造成顯示重疊。


  5. padding and float排版
    CSS 三欄排版
    這是結合 (float 排版) 及 (margin and float 排版) 的排版方式,主要是解決 (margin and float 排版) 的主欄中不可以使用 clear 屬性的問題,CSS 的差別只在於利用外匡的 padding 屬性去做預留空間的設定。


優劣差異:
floattablemargin
float
margin
position
padding
float
靈活性
親和力
HTML 結構簡單複雜簡單簡單簡單
寬度彈性noyesyesyesyes
允許彈性的欄位數0all111
overflow 容錯
瀏覽器的解析差異
欄位的高度影響allallall1all


展示頁面(Demo Page)
2008-08-20

Ajax 模組架構的應用

Ajax 模組架構的應用
一樣的就之前所提到的問題(Ajax 開發所產生的問題),這是另一種以模組架構為基礎的方法,模組開發的好處我就不多作說明了,主要的行為模式是:
  1. 在請求 Page 時就先將 Module Include,讓頁面再第一次讀取時就可以完整呈現。
  2. 在頁面需要執行局部置換時,再利用 Ajax 向 Module 請求局部內容。

這樣做既不會失去模組開發的優點,也不會有 Ajax 造成的過長等待,讓 Ajax 主要應用在局部置換及 UI 處理。
2008-08-19

利用屏壁來延長頁面的呈現時間

就之前提到的問題(Ajax 開發所產生的問題),這很可能連帶出現以下問題:
  1. 瀏覽者再頁面尚未完整呈現時誤觸連結,造成錯誤操作。
  2. 功能的初始未完成,瀏覽者再使用上出現無法動作的錯愕情形。


這些問題可以用一個有效的方法去延長瀏覽者的等待時間,在一開始的頁面裡預設疊上一個遮蓋整個頁面的等待圖示,在 JavaScript 處理完後再移出屏壁,一個很好的範例就是 Gmail,再一個主要的頁面呈現前,置入一個等待圖示去避免一些可能的不當操作。

順帶一提,Gmail 利用 ifreme 去做出局部置換的效果,這樣做的好處是,瀏覽器會自動去紀錄上下頁,在 Ajax 的應用上瀏覽紀錄這件事是必須額外處理的。
2008-08-18

利用 Ajax 減少 Server 運算量

在 Ajax 還沒有出現時 JavaScript 本身就可以執行許多計算方面的程式了,像之前的文章『HTML 比較(diff)』、『數獨(sudoku)解題』、『線性代數-計算機』等都是利用 JavaScript 去達成的計算程式,象 Yahoo 也有在 Login 時利用 JavaScript 做 md5 的計算,其實瀏覽器還是可以做一些有規模的運算。

利用 Ajax 減少 Server 運算量

主要是將運算資料取回,計算結果明細後,再跟 Server 取得剩餘的詳細資料,這個架構可以讓 Server 原本的運算量轉由瀏覽器執行,是一個以空間換時間的作法,當然有一好沒兩好,沒錯這樣的方法明顯會發生之前所說的問題(Ajax 開發所產生的問題),是否要用這個方法就看各位的考量了。

其中特別要注意的一些事項:
  1. 再資訊必須是即時性,且運算量大於一定時間以上時,考慮這種架構才會有意義,要不然只會浪費頻寬。
  2. 資料安全性問題,必須定義哪些瀏覽者可以取得計算資料,要不然會造成嚴重的漏洞。
  3. 資料量的大小,太大的資料可能會造成瀏覽器整個當掉,再規劃時要特別注意最大上限,至於詳細的範圍要依瀏覽者的設備而定。
2008-08-16

利用 Plugin 的架構做模組應用


這是我很久之前在開發所有的類別架構,主要是以 MoreModile 類別為主作延伸應用,這個繼承方式並不是一個很好架構,因為 Base 的 MoreModile 常常會有異動的可能,而且子類別也不是完全以父類別為基礎,有時候只需要部份的成員函數,這樣的架構在之前的開發上變得綁手綁腳,怕改錯一個東西造成其他的類別也受到牽連。


後來想到這樣的開發架構,由一個主要的 DataLoad 類別負責整體的處理,再選擇需要 Plugin 那些 Module,這個方法讓架構變得更有彈性,且整體的牽連性也不至於像之前那麼嚴重,而且還有預留一個 Plugin 的虛擬類別,提供額外的修改空間,再實行的過程中也明顯的加快日後的開發速度。


這是目前的類別架構圖,每一個新類別都可以選擇所需的 Module,或者實作一個特定需求的虛擬類別,讓基礎類別有更多的應用,且實作上也具有很高的彈性。
這樣的架構並不是一個標準的類別繼承架構,正常來說應該利用成員物件的方式去執行 Plugin 這樣的架構,但可惡的是 JavaScript 有一個麻煩的事件問題,物件再做事件整合上其實並不是那麼快樂,常常會因為參數的傳遞及 this 的處理造成不少困境,所以使用標準架構只會讓開發更複雜。
2008-08-15

CSS 與 HTML 規劃心得檢討

由於所開發的系統愈來愈大,免不了開始出現一些排版上的問題,對於目前的狀況做了一些整理:
每加入一個新功能就建立一個新樣式,造成過多獨立應用的樣式。
再新功能規劃時,可多考慮使用舊有的樣式。
HTML 在的設計上過於精簡缺乏彈性及流通性。
在結構上的規劃時多考慮多變應用以增加日後應用上的彈性。
類似的樣式過多沒有統一的規劃。
再設計多預想未來的應用,增加樣式重複利用的可能性。
過度使用已 Tag 為主的選擇器,造成過度的樣式覆寫。
在較複雜的樣式區塊中,先做分割規劃出許多小區塊,簡化樣式選擇器的深度。
ID 與 Class 命名沒有規範清楚,造成樣式與功能上的混淆。
排版與樣式沒有分離,造成管理不易。
對於排版的寬度定義不明確,造成異常 overflow 跑版。

主要的問題還是出在一致性的樣式共用與命名規則的問題上,在開發的過程中沒有謹慎規劃,對於未來可能的應用也許要考慮進去,避免重複定義相似的樣式。
2008-08-14

Ajax 開發所產生的問題

wacanai 的開發中發現了一個問題,就是在頁面載入後又開始執行多個 Ajax 請求,這會發生什麼現象呢?頁面一開始會空空的,然後資訊開始慢慢的呈現出來,這樣的現象會造成兩種問題:
  1. Server 在同一時間會有來自單一位址的大量請求
  2. 使用者的等待時間變長

第一個問題會使 Server 連接端口的負荷增加,雖然在流量上並沒有很大的區別,但卻會考驗 Server 的硬體資源。

第二個問題是使用者必須等待所有 Ajax 回應後才能看到完整的頁面資訊,而且會因為使用者的頻寬成倍數關係。

Ajax 開發所產生的問題

我們會發生這樣的問題,來自於過度使用以 Ajax 為基礎的模組架構,將一些沒必要利用 Ajax 處理的應用,也使用 Ajax 來呈現,Ajax 原先是用來優化呈現上的局部置換,及增加與使用者互動的應用介面,主要是用來避免重新載入已有的資訊,並讓頁面可以有更好的介面輔助,但在習慣 Ajax 的架構時,不知不覺就習慣利用這個架構去作模組的規劃。

所以再利用 Ajax 作開發時,必須考慮到 Ajax 主要的應用目的,不然在過度不當採用這個應用時,會造成更多的問題存在。
2008-08-09

vimrc - VIM 的設定檔

vim 是什麼? Linux 下的老牌文字編輯器,詳細說明請看Wikipedia-vim

/etc/vim/vimrc 中的常用設定

set nu "顯示行號
set tabstop=4 "Tab 的空白數
set hls "加亮搜尋到的關鍵字
set cursorline "標註顏色至游標整行
syntax on "開啟語法加亮


" 選擇語法加亮的配色,配色檔目錄(/usr/share/vim/vim72/colors)
"colorscheme blue
"colorscheme darkblue
colorscheme default
"colorscheme delek
"colorscheme desert
"colorscheme elflord
"colorscheme evening
"colorscheme koehler
"colorscheme morning
"colorscheme murphy
"colorscheme pablo
"colorscheme peachpuff
"colorscheme ron
"colorscheme shine
"colorscheme slate
"colorscheme torte
"colorscheme zellner



" gVim UTF-8 支援設定
set fileencodings=utf-8,big5,euc-jp,gbk,euc-kr,utf-bom,iso8859-1
"set encoding=utf8 "不設定 menu bar 就不會變亂碼.
set tenc=utf8


if has("gui_running")
set termencoding=utf-8
else
set termencoding=big5
endif


參考來源:
gvim編UTF-8的文件
2008-08-08

ASUS P5K SE/EPU 音效卡驅動程式安裝

之前買新電腦時,為了音效卡一直裝不起來,弄了很久,最後終於找到有效的解決辦法了,怕以後會忘記先記下來。

原文出處

  1. 請先確認您的作業系統是否已包含 WinXP SP1或 SP2?
  2. 確認裝置管理員內的系統裝置底下有無“Microsoft UAA Bus Driver for High Definition Audio”? 若沒有此裝置,請執行 KB888111xpsp1.exe(使用SP1)或 KB888111xpsp2.exe(使用SP2)
  3. “Microsoft UAA Bus Driver for High Definition Audio”已正常驅動,在「音效,視訊及遊戲控制器」底下應該會有一個Audio Device on High Definition Audio Bus 或無法辨識的裝置。請將此裝置【停用】。 若無Audio Device on High Definition Audio Bus 或無法辨識的裝置在裡面可直接跳過此步驟
  4. 接著再將系統裝置底下的 Microsoft UAA Bus Driver for High Definition Audio 【停用】
  5. Microsoft UAA Bus Driver for High Definition Audio【解除安裝】
  6. 做好上述動作後,請在裝置管理員畫面『檢視』的下方按下【硬體變更掃描】的圖示。
  7. 此時會出現新增硬體精靈,請注意勿按下下一步,只需按下『取消』,再進驅動程式光碟片或是網站上下載下來的音效驅動內執行Setup.exe即可完整安裝音效驅動程式

PS:上述的安裝軟體在光碟或官方的安裝包都有
2008-06-11

Mootools 1.2 正式上線

今天突然發現 beta 已久的 Mootools 1.2 終於進入正式版了
多了不少新的函數與物件
連官方網站也整個換過

可惜的是 Ajax 連結物件跟 v1.11 完全不同
雖然在連接上更容易些
在撰寫上也更加精簡化了
整個 framework 也變小了
可是對於以前的架構卻完全不同

為了提升這個版本
卻要改幾萬行程式
為了 PDO 的使用就已經有不少要改了
再加上 mootools 的 Ajax
這不是一天兩天可以搞定的

雖然 v1.2 好用歸好用
在實質運算上的效率考量
再加上是不是改寫後會提升開發速度
這一切看來要多觀望一下
2008-06-07

將查詢結果新增至資料表 INSERT for SELECT [MySQL]

最近愛上的這個技巧,一整個就只有方便而已,將查詢結果直接寫入資料表中,唯一的缺點就是沒有錯誤跳過,只要錯了一行,後面的筆數就會被放棄,所以在 SELECT 的時候就要濾掉會錯誤的筆數

INSERT INTO orderlist (book_id, last_time)
SELECT book_id, MAX(time) FROM orders;


參考文章:
MySQL 將查詢結果存入資料表

Aptana 中文亂碼問題(Snippets,Code Assist Profiles)

Aptana 中文亂碼雖然這已經不是問題了,而且也有很多網站提出解決方法了:

Windows選單→ Preferences → General → Content Types,選擇 Text ,在下方指定默認編碼為UTF-8,並添加文件類型,如*.js

如果文檔的編碼不是UTF-8就指定成相應的編碼。不過還是建議使用UTF-8編碼

雖然這個已經解決了,可是 SnippetsCode Assist Profiles 這兩個工具欄卻還是有亂碼的問題,所有的註解和說明都變成亂碼,在 Shan 的提點下找到亂碼的根源,發現原來是 Aptana 在讀檔時採用雙位元檢查,造成檔案編碼跑掉,改善的方法就是將這兩個工具欄的檔案改成 Big5 編碼格式(windows)

PS:Linux 則使用 UTF-8
2008-06-06

GROUP_CONCAT 筆數串接函數 [MySQL]

這是一個跟 COUNT() 類似的聚總函數,用來串接結果,函數說明如下:
GROUP_CONCAT([DISTINCT] expr [,expr ...]
    [ORDER BY {unsigned_integer | col_name | expr}
    [ASC | DESC] [,col_name ...]]
    [SEPARATOR str_val])

-- DISTINCT 唯一值設定
-- ORDER BY 排序設定
-- ASC|DESC 排序方式
-- SEPARATOR 間隔字串(預設是 ',')



不過今天在使用時卻發現忽視已久的問題,這個函數是有上限值的,可以透過設定 group_concat_max_len 變數變更(預設 1024)

參考文章:
MySQL 5.0 Reference Manual :: GROUP BY (Aggregate) Functions
MySQL的几个实用字符串函数
2008-06-04

CASE 指令,MySQL 的 switch 與 if else

今天在玩 CASE 這個指令,雖然已經在同學 黑色 深淵 的 Blog 中看到過了,為了明確瞭解這個指令的語法及功能,今天花了一點時間實證。
  1. 必須依附在 SELECT,UPDATE,INSERT,DELETE 下
  2. 不可用在區段中加其他動作
  3. 具有 switch 與 if else 兩種架構

-- switch 的用法
SELECT CASE col
    WHEN 100 THEN '1'
    WHEN 50 THEN '2'
    ELSE '3'
END
FROM table;

-- if else 的用法
SELECT CASE
    WHEN col>100 THEN '1'
    WHEN col>50 THEN '2'
    ELSE '3'
END
FROM table;


在需要對欄位做多種情況區分時,這個指令就很好用,可惜不行加入其他動作,例如:
CASE 
    WHEN EXISTS(SELECT * FROM table WHERE id=1)
    THEN (UPDATE table SET txt='test' WHERE id=1)
    ELSE (INSERT INTO table(id,txt) VALUES(1,'text'))
END;


參考文件:
MySQL 5.1 Reference Manual :: 21.2.10.2 CASE Statement
mysql语句中用if的例子
2008-06-03

IF(exp1,exp2,exp3) 好用的 MySQL 函數

最近在找 MySQL 函數時,忽然看到這個函數,它的使用方法就跟三元運算子一樣,在 select 時做資料判別還蠻方便的,而且查詢時的效率也沒有太大的影響。

IF(exp1,exp2,exp3)
-- 當 exp1 為 true 時就丟出 exp2
-- 為 false 則丟出 exp3

-- 這個函數是可以允許疊加
IF(exp1,
IF(exp21,exp22,exp23),
IF(exp31,exp32,exp33)
)

-- EX:
SELECT IF(a='1','yes','no');

好用的 Eclipse!我墮落了!

在 Shan 的幫助下,發掘更多 Eclipse 上的功能跟 plugin。

雖然 Shan 愛用的(Remote System Explorer) plugin 不怎麼適合我,少了專案搜尋真是很不方便的說。

但也找到好用的 SQL 工具(Database Explorer),這套並沒有什麼特別的,除了語法加亮和可以直接連結 Database 下 Query之外,並沒更特別的功能,不過至少不用一直在 phpMyAdmin 貼上貼下的。

而且我也終於會用 Eclipse FTP and WebDAV 這套 plugin 了,雖然在使用上還是需要特別小心,要不然他內定的同步機制會將自己 local 端的檔案刪除,出過一兩次意外,我現在都會仔細看他要執行的動作。

當然也少不了 PHPEclipse 和 Aptana 這兩個 plugin,最近剛會使用 Aptana 的程式巨集,這也是編輯工具必備功能之一,雖然這個巨集功能沒有 PHPEclipse 中的好用,只好加減一下了,但Aptana 的巨集有個特點,就是不管在任何檔案類型都可以插入。

其實 Eclipse 本身在文字編輯和專案管理上就有很多不錯的功能了,單字完成、函數提示、刪除行段、複製行段、移動行段等編輯上常用快捷功能,當然還有兩個好用的功能,就是"書籤"和"作業"這兩個記錄器,可以用來分擔大腦的記憶,尤其是在專案規模大到有點難以尋找的時候,這兩個記錄器就會發揮很大的幫助。

用了那麼多方便的工具,哪一天我會不會變成失去魔法的麻瓜!!
2008-06-01

HTML & Smarty、JavaScript、CSS 及 PHP 註解清除器

之前為了上線前去除不要的註解及多餘的空白符號,一直在找合適的工具,可是找到大部分都是 windows 的軟體,想找 Linux 的卻沒找到,於是就自己用 Lex 寫了一些,幾本上我分成四個語言的清除器,設計上是直接覆寫原始的檔案,所以在應用前請先自行複製備份,由於清除器沒有做語法驗證,再撰寫時需要特別嚴謹 ( PS: 程式碼中常被忽略的結束符號 ";" )。

清除規則:
  • HTML & Smarty
    • 清除 < 及 > 前後的空白及換行(\n)符號
    • 清除 HTML 註解 (<!-- 註解 -->)
    • 清除 Smarty 註解 ({* 註解 *})
    • 清除 JavaScript 單行及多行註解 (/* 註解 */ , //註解)
    • 清除 JavaScript 多餘的空白及換行(\n)符號
    • 完整保留單引號及雙引號內的字串
  • JavaScript
    • 清除多餘的空白及換行(\n)符號
    • 清除單行及多行註解 (/* 註解 */ , //註解)
    • 完整保留單引號及雙引號內的字串
  • CSS
    • 清除多餘的空白及換行(\n)符號
    • 清除多行註解 (/* 註解 */)
    • 完整保留單引號及雙引號內的字串
  • PHP
    • 清除行首及行尾的空白符號
    • 清除無用的空白行
    • 清除單行及多行註解 (/* 註解 */ , //註解)
    • 完整保留單引號及雙引號內的字串

這已經經過很多次的測試跟修改了,目前還沒有出現特別的狀況,有需要的人可以用用看,在 linux 上必許要安裝 flex 及 gcc 才可以編譯,當然 windows 也有的flex 及 gcc 的編譯器。

檔案連結
2008-05-04

好用的 lex 詞彙解析語言

lex 這個語言是我在二技時學會的,這原本是用來開發編譯器的語言,但他對於詞彙解析有很強的能力,而且不需要寫太多的程式碼就可以做到很大的能力,用來處理一些有規則文檔的是輕而一舉的事。

其實 lex 的語法就是『正規表示式』所組成的,所以撰寫上花的腦筋跟測試會比寫程式碼來的多,雖然很好用,但在想解析的規則時卻不是那麼快樂。

lex 是 base 在 C 上面的語言,除了解析的規則外,其他都是屬於 C 語言的撰寫,所以基本上還必須會寫 C,而且 C 的文字處理函數卻不怎麼好用。


lex&yacc
以入門書來說這本寫的真是不錯,除了語法上都講解得很清楚,還有有很多教學範例。
相關連結:Yacc 与 Lex 快速入门

在 IE 中對表格的操作問題(innerHTML,style)

問題1:在對以存在的表格用 innerHTML 新增列或其他 DOM 子節點時,會發生錯誤或警告,或者是完全沒反應。

table.innerHTML+="<tr><td>test</td></tr>";


解決方法:採用 createElement 去建立 DOM 物件,再用 insertBefore 插入新的子節點。

var tdObj=document.createElement('td');
trObj.appendChild(document.createTextNode("test"));

var trObj=document.createElement('tr');
trObj.insertBefore(tdObj);

table.insertBefore(trObj);


問題2:在現存表格中的子節點(tr,td)作 style 操作時,完全沒反應的現象。

tr.style.display="none";
td.style.display="none";


解決方法:利用 className 去套用以設定好的樣式。

table .hide{ display : none; }

tr.className="hide";
td.className="hide";


目前我只在 IE 上遇到這些問題,Firefox 則不會有這樣的問題,可能是 IE 對 table 的 DOM 解析比較特別,其他的 DOM 物件都不會有類似的狀況。
2008-05-03

JavaScript 效率優化

最近開始重視 JavaScript 的效率問題,原因在於感到自己寫的網頁越來越不流暢,其中大量的計算跟無法避免的迴圈愈來愈多,加上 UI 介面跟動態效果的需要,使得瀏覽器的負荷過大,所以這是個需要重視的問題,這直接的影響網站名聲的好壞。

要如何作效率優化呢?因為 JavaScript 是直譯語言,無法透過編譯器加以優化,所以只能從撰寫方式下手。

下面有一個效率很差的例子:
for (var i=0; i<data.length; i++) {
    document.getElementById("link").innerHTML += data[i];
    document.getElementById("link").hreh += "&" + data[i];
    document.getElementById("link").title += data[i] + ",";
    document.getElementById("link").className += data[i] + " ";
    document.getElementById("link").name += data[i] + "_";
}


當中有幾個影響效率的問題:
  1. 過渡的使用 getElementById 搜尋 DOM 物件,尤其是在 for 迴圈中
  2. 大量的存取 length、innerHTML 等成員變數
  3. 多次的存取 data[i],這跟上一個差不多



這些問題的修改方法:
/*利用暫存變數作處理*/
var temp1='', temp2='', temp3='', temp4='', temp5='';

/*利用 l 紀錄 length 的值,以避免多次存取成員變數*/
for (var i=0,l=data.length; i<l; i++) {
    /*利用 d 紀錄 data[i] 的值,以避免多次存取成員變數*/
    d = data[i];
    temp1 += d;
    temp2 += "&" + d;
    temp3 += d + ",";
    temp4 += d + " ";
    temp5 += d + "_";
}

/*利用暫存變數紀錄 DOM 物件*/
var link = document.getElementById("link");
link.innerHTML += temp1;
link.hreh += temp2;
link.title += temp3;
link.className += temp4;
link.name += temp5;



實驗 1000 筆資料的結果:
第 1 個耗時:5625(msec)
第 2 個耗時:47(msec)
展示(demo)

參考來源:
JavaScript loop performance
随時innerHTMLに書き込んだ場合と一括して書き込んだ場合
innerHTMLとinnerText/textContentの速度比較
getElementByID、変数、withによる参照速度比較
シリアルサーチと正規表現の速度比較

善用 Mootools 的 onComplete 事件

用了 Mootools 那麼久終於有點心得了,尤其是在 Effects 類別庫上,因為之前一直對變換效果的後續處理很困擾,而採用的延遲函數,可是這不是很好的作法,因為 JavaScript 的計時器非常的耗資源,會讓整個網頁的流暢度降低。

而其實在 Effects 都附有 onComplete 事件可以使用,這個事件會在變換效果結束後被呼叫,而且還附帶本身物件(this),利用 firebug 的 console.log() 函數可以直接觀察 this 所帶有的成員參數,這比之前的延遲函數要好多了,而且程式碼也不會那麼多。

其他的類別庫中也有定義或繼承 onComplete 事件,如 Drag、Remote 及 Plugins 中的部分類別都帶有此事件,雖然官方的 docs 沒有寫得很清楚,只寫了繼承的來源及本身帶有的成員函數,有部分的成員變數可能要看原始碼會比較清楚,Mootools 的設計架構其實在撰寫上還蠻具彈性的。
2008-05-02

用 JavaScript 作 HTML 比較(diff)

為了做到文字比較,我利用『最長共同部分序列』(Longest Common Subsequence)演算法,這是屬於動態規劃演算法的一種,特點就是以空間換速度,在比較過程需要 (m+1)*(n+1) 的記憶體空間,效率是 m*n,m 跟 n 的數量取決於文章的長度與切割的大小,我的切割方式是以空白符號及 HTML tag 作分界,對英文的切割有正向的優勢,所以在中文上就有點糟,但因為切割的長度大效率會比較快。
/*切割文字*/
function toReg(str){
    var array = str.match(/<[^>]*>|[^< ,.\r\n\t]+[ ,.\r\n\t]*/ig);
    result = [];
    for(var i = 0, l = array.length; i < l; i++) {
        if(array[i].charAt(0) == '<') {
            temp = array[i].match(/[^<][^> ]*/i);
            result[i] = {
                txt: array[i],
                tag: temp
            };
        }else{
            result[i] = {
                txt: array[i],
                tag: false
            };
        }
    }
    return result;
}

/*最長共同部分序列*/
function LCS(na, oa){
    var m = na.length, n = oa.length;
    var i, j;
    var d = [];

    /*Dynamic*/
    for(i = 0; i <= m; i++) {
        d[i] = [];
        d[i][0] = 0;
    }
    for(j = 1; j <= n; j++) {
        d[0][j] = 0;
    }

    /*動態規劃演算法*/
    for(i = 1; i <= m; i++) {
        for(j = 1; j <= n; j++) {
            if(na[i - 1].txt == oa[j - 1].txt) {
                d[i][j] = d[i - 1][j - 1] + 1;
            }else if(na[i - 1].tag && na[i - 1].tag==oa[j - 1].tag) {
                d[i][j] = d[i - 1][j - 1] + 1;
            }else if (d[i][j - 1] > d[i - 1][j]) {
                d[i][j] = d[i][j - 1];
            }else {
                d[i][j] = d[i - 1][j];
            }
        }
    }

    /*標註共同部分序列*/
    i = m;
    j = n;
    while (i > 0 && j > 0) {
        if(d[i][j] == d[i - 1][j]) {
            i--;
        }else if(d[i][j] == d[i][j - 1]) {
            j--;
        }else{
            i--;
            j--;
            na[i].com = j;
            oa[j].com = i;
        }
    }
    delete d;
}

/*合併比較陣列*/
function merge(na, oa){
    var m = na.length, n = oa.length;
    var result = [];
    if(!m && !n) { return null; }

    var i;
    var oldPrint = 0;
    for(i = 0; i < m; i++) {
        /*有共同的資料*/
        if(na[i].com != undefined) {
            /*有刪除的舊資料*/
            if(na[i].com > oldPrint) {
                var maxRow=(na[i].com < n) ? na[i].com : n;
                for(j = oldPrint; j < maxRow; j++) {
                    if(oa[j].tag) {
                        result.push(oa[j].txt);
                    }else{
                        result.push('<del>' + oa[j].txt + '</del>');
                    }
                }
            }
            /*記錄下一次舊資料的指標*/
            oldPrint = na[i].com + 1;
            /*儲存共同的資料*/
            result.push(na[i].txt);

        /*新的差異資料*/
        }else{
            if(na[i].tag) {
                result.push(na[i].txt);
            }else{
                result.push('<ins>' + na[i].txt + '</ins>');
            }
        }
    }
    return result;
}

展示(demo)
2008-05-01

在 IE 中對 window.open (子視窗)的參數傳遞

由於子視窗和母視窗是使用不同的 document,在 IE 的架構上不可以對母視窗作 call by reference,要先將要用的值設定給母視窗的變數,再作函數呼叫,在 JavaScript 中字串的屬性是一般變數值,不會有 reference 的現象。

//要回傳的陣列
var selData=["A","B","C","D"];

//清空母視窗的陣列,將陣列長度設為零
window.opener.resultArray.length = 0;

//將參數值填入母視窗的陣列中
for(i=0,l=selData.length; i<l; i++){
    window.opener.resultArray.push(selData[i]);
}


參考來源:請問子母視窗如何傳遞變數


結論:IE 真的很麻煩!難道不可以允許符合邏輯的語法嗎?
2008-04-30

Mootools 可以對物件陣列做 forEach 操作的函數

除了上次在Mootools Event 設定函數中提到 addEvent()addEvents() 可以直接對物件陣列做操作外,Mootools 還有其他函數也支援這種用法:

//移除 id="button" 下所有 <a> 元素群的 click 事件
$$('#button a').removeEvent('click');

//移除 id="button" 下所有 <a> 元素群中的所有事件
$$('#button a').removeEvents();

//檢查 id="button" 下所有 <a> 元素群中是否有此"red"的class樣式
//會回傳一個 Array
$$('#button a').hasClass('red');

//為 id="button" 下所有 <a> 元素群加入"red"的class樣式
$$('#button a').addClass('red');

//移除 id="button" 下所有 <a> 元素群中有"red"的class樣式
$$('#button a').removeClass('red');

//切換 id="button" 下所有 <a> 元素群中"red"的class樣式
$$('#button a').toggleClass('red');

//設定 id="button" 下所有 <a> 元素群的color樣式為#F00
$$('#button a').setStyle('color','#F00');

//設定 id="button" 下所有 <a> 元素群的color及width樣式
$$('#button a').setStyles({
'color':'#F00',
'width': 300
});


類別庫:
Element.js
2008-04-17

iGoogle 上的日曆小工具

將日曆加入 iGoogle 分頁,這個小工具還可以置換成其他網頁
介紹網站:Your Page Here (an iGoogle gadget)
工具連結

利用 HTML/Javascript 小工具將 Google 日曆的 iframe 加入 iGoogle
介紹網站:Add Full Web Pages to iGoogle
工具連結
2008-04-07

[PHP] 圖檔上傳檢查


<?php
/*檢查上傳的圖片類型,並轉存成 JPG*/
if (isset ($_FILES['image'])) {
$imgFile = $_FILES['image'];
/*檔案存放路徑(目錄權限必須可寫入)*/
$imagePathDir = '/home/www/pics/';
/*上傳圖片文件類型列表 */
$uptypes = array (
'image/jpg',
'image/jpeg',
'image/pjpeg',
'image/gif',
'image/png'
);
/*產生唯一的檔案名稱*/
$imgName = md5(uniqid(rand())) . '.jpg';
/*檢查檔案大小 2Mb*/
if ($imgFile['size'] > 2097152) {
echo '檔案過大';
/*檢查文件類型 */
} elseif(in_array($imgFile['type'], $uptypes)) {
/*上傳圖片類型為jpg,pjpeg,jpeg */
if (strstr($imgFile['type'], "jp")) {
if(!($source = @ imageCreatefromjpeg($imgFile['tmp_name']))){
echo '檔案類型錯誤';
return;
}
/*上傳圖片類型為png */
}elseif(strstr($imgFile['type'], "png")) {
if(!($source = @ imagecreatefrompng($imgFile['tmp_name']))){
echo '檔案類型錯誤';
return;
}
/*上傳圖片類型為gif */
}elseif(strstr($imgFile['type'], "gif")) {
if(!($source = @ imagecreatefromgif($imgFile['tmp_name']))){
echo '檔案類型錯誤';
return;
}
/*其他例外圖片排除 */
} else {
echo '檔案類型錯誤';
return;
}
$w = imagesx($source); /*取得圖片的寬 */
$h = imagesy($source); /*取得圖片的高 */
/*檢查檔案最小尺寸 160px*160px */
if ($w < 160 || $h < 160) {
echo '檔案過小';
return;
}
/* 儲存到檔案目錄(JPG) */
imagejpeg($source, $imagePathDir . $imgName);
/* 列出檔案路徑 */
echo $imagePathDir . $imgName;
} else {
echo '檔案類型錯誤';
}
} else {
echo '其他錯誤';
}
?>
2008-04-06

MooCrop 正方形選取( Square )

MooCrop 是建構 MooTools 上的圖片裁切類別
不過本身沒有方形鎖定的功能
我利用一個簡單的觀念改寫原本的函數
將兩個方向的寬高同時加減
在初始為正方形的狀況下
不管如何縮放都會達成正方形

我還增加預覽裁切功能

範例(example)
展示(demo)
2008-02-12

Mootools Event 事件函數

Mootools 的事件設定可以支援群組元素


//設定 id="button" 元素的 click 事件
$('button').addEvent('click',function(){
alert(this.getHTML());
});

//設定 id="button" 下所有 <a> 元素群的 click 事件
$$('#button a').addEvent('click',function(e){
alert(this.getHTML());
});

//設定 id="button" 元素的 click 與 mouseover 事件
$('button').addEvents({
'click': function(e){
alert('click');
},
'mouseover': function(e){
alert('mouseover');
}
});

//移除 id="button" 元素上的 click 事件
$('button').removeEvents('click');
//執行 id="button" 元素上的 click 事件
$('button').fireEvent('click');



其他事件名稱:
圖片事件abort讀取中斷
error讀取錯誤
焦點事件blur離開焦點
focus取得焦點
選單事件change選單狀態改變
滑鼠按鍵事件click點擊點選鍵
dblclick點擊二次點選鍵
mousedown按下點選鍵時
mouseup放開點選鍵時
鍵盤事件keydown鍵盤按下時
keyup鍵盤放開時
頁面讀取load讀取結束時
unload切換頁面時
滑鼠事件mouseover游標重疊時
mouseout游標離開時
mousemove游標移動時
mouseenter游標進入時, 經過子元素時不觸發
mouseleave游標離開時, 經過子元素時不觸發
表單事件submit表單送出時
reset表單重置時
捲軸事件scroll捲動時
文字選取事件select選取文字時


類別庫:
Element.Event.js
Element-Event.js
2008-02-11

Mootools Element 選擇函數

$('button')
這個用法在很多 framework 上都一樣,只是簡化了
document.getElementById('button') 這個函數


$$('#button')
這個選擇函數跟 CSS 的選擇方式是一樣的,可以選出一個元素群

$$('#button a')
取得 id="button" 下所有 <a> 的元素

$$('#button a','#button b')
取得 id="button" 下所有 <a> 及 <b> 的元素

$$('#button a.link')
取得 id="button" 下所有 <a class="link"> 的元素


$('button').getElements('a[title=link]')
取得 id="button" 下所有 <a title="link"> 的元素

$('button').getElements('a[title$=ink]')
取得 id="button" 下所有 <a> 屬性 title 以 ink 結尾的元素

其他選擇方式:
= :等於
^=:開始等於
$=:結尾等於
!=:不等於


$('button').getElement('a[name=link]')
與 getElements() 相同:
但只會取得 id="button" 下第一個 <a name="link"> 的元素

$('button').getElementsBySelector('a','b')
與 getElements() 相同:
可以取得 id="button" 下所有 <a> 及 <b> 的元素


類別庫:
Element.js
Element.Selectors.js
Element-Selectors.js
2008-01-27

Ubuntu CVS 安裝 for Eclipse

現在工作時都要將 Eclipse 與 Dreamweaver 開啟,主要都是以 Eclipse 來編寫網頁,而 Dreamweaver 只是拿來做上傳同步,這兩個軟體都是出了名的肥,光是開啟就用 500 MB 的記憶體。
原本想用 CVS 做遠端同步,可惜 CVS 不是拿來做這種簡單的事,CVS 是用在多人開發間的同步橋樑,透過一個版本管理伺服器,去協調多個開發者的同步問題,所以不適合用在網頁上傳的同步處理

由於花了很久的時間在安裝這套工具上,其實要安裝這個工具是很簡單的,但為什麼我會花那麼的時間呢?這是個好問題,所以想為這些光陰來寫個詳細的安裝流程。

架設 CVS Server
1.安裝 CVS:
$sudo apt-get install cvs

2.安裝 CVSD:
$sudo apt-get install cvsd

3.在 /var/lib/cvsd 下建立 /myrepos 目錄,這是以後 CVS 的專案集(工作區)
$cd /var/lib/cvsd
$sudo mkdir myrepos

4.初始化這個/myrepos。
$sudo cvs -d /var/lib/cvsd/myrepos init

5.設置 myrepos 專案集的使用者認證方式,預設是使用系統中的帳號,為了安全還是使用 CVS 來管理使用者。
$sudo vi /var/lib/cvsd/myrepos/CVSROOT/config

加入以下設定:
# 關閉系統帳號的使用者連結 CVS
SystemAuth=no
PamAuth=no
# 設定 LockDir 的相對路徑
LockDir=/tmp/myrepos
然後保存退出。注意此處的/tmp/myrepos是指相對於RootJail的路徑。

6.建立 LockDir 目錄
$sudo mkdir /var/lib/cvsd/tmp/myrepos

7.增加 CVS 的用戶帳號
$sudo cvsd-passwd /var/lib/cvsd/myrepos cvsuser

8.編輯 CVSD 的設定檔。
$sudo vi /etc/cvsd/cvsd.conf
# 預設設定如下:
RootJail /var/lib/cvsd
Repos /myrepos。
# 連接阜(Port)
Listen * 2401

10.設定目錄權限,以後加入新專案時也要檢查權限設定。
$sudo chown -R cvsd:cvsd /var/lib/cvsd

11.重新啟動 CVSD。
$sudo /etc/init.d/cvsd restart

12.測試連線狀況
$cvs -d :pserver:cvsuser@localhost:/myrepos login
$cvs -d :pserver:cvsuser@localhost:/myrepos checkout

利用 Eclipse 連結 CVS (PS:記得先將本地端的專案備份)。
1.在 /myrepos 中建立專案 test
$cd /var/lib/cvsd/myrepos
$sudo mkdir test
$sudo chown -R cvsd:cvsd test

2.在 Eclipse 中建立專案 test
檔案→新建→專案
專案類型:(自訂)
專案名稱:test

3.切換工作至:團對同步化
CVS for Eclipse

4.建立新同步
CVS for Eclipse

5.選擇同步方式:CVS
CVS for Eclipse

6.填入連線設定:
儲存庫路徑上記得加上/
CVS for Eclipse

7.填入同步的專案名稱 (myrepos 中 test)
點選下一步
CVS for Eclipse

8.選擇初始的同步方式 (PS:如果沒選第三個會將本地端的專案給清空)
然後點選完成
CVS for Eclipse

9.再次點選新同步
CVS for Eclipse

10.選擇同步方式:CVS
CVS for Eclipse

11.這時候就會出現剛剛設定好的連線,選擇 test 按下完成。
CVS for Eclipse

參考資料:
分享Ubuntu Linux上边的CVS服务器的配置
Ubuntu CVS服务器设置
Ubuntu下CVS服务器的搭建
Ubuntu Linux操作系统CVS安装与配置详解

架站使用 UTF-8 要檢查的項目

一開始最基本的就是環境設定,Server 對於文字的編碼設定,這也是最重要的。

關於 Apache Server 的設定:
在 /etc/httpd/conf/httpd.conf(Red Hat) 或 /etc/apache2/conf.d/charset(Ubuntu) 中開啟對 UTF-8 編碼的設定:
AddDefaultCharset utf-8

關於 Mysql Server 的設定:
在使用 script 進行新增/修改時記得在 script 檔中加入:
SET NAMES 'utf8';
在 PHP 存取前也應該先宣告編碼方式:
mysql_query("SET NAMES 'UTF8'");

在建立文字欄位(TEXT, VARCHAR, ...)時也必須定義文字的編碼方式:
CHARACTER SET utf8 COLLATE utf8_unicode_ci

在編寫網頁文件時,除了要注意檔案是否使用 UTF-8 編碼外,還要記得加上編碼宣告,因為解讀器並沒有那麼聰明,沒辦法準確的辨別檔案的編碼方式,所以請一定要加上編碼宣告。

關於 HTML 文件的宣告:
<meta equiv="Content-Type" content="text/html; charset=UTF-8">

關於 XML 文件的宣告:
<?xml version="1.0" encoding="UTF-8"?>

關於 PHP 文件的宣告:
header('Content-type: text/html; charset=utf-8');

參考文章:UTF-8 checklist - soledad penadés
2008-01-22

cookie 路徑問題

在 PHP 中使用 Cookie 是一個簡單又快樂的事
你可以用下面的方法設置一個暫存 1800 秒的 Cookie 變數:
setcookie ("a", "123", time()+1800);

如果你想要一個能暫存七天的 Cookie 變數:
setcookie("a","123",mktime(0,0,0,date("m"),date("d")+7, date("Y")));

然後利用下面的方法去取得 Cookie 變數,這也是既簡單又快樂的事
$_COOKIE['a']

但是要是不瞭解 Cookie 的路徑設定,你可能會發生非常不快樂的問題,造成其他頁面無法取的某路徑下的 Cookie,所以 Cookie 路徑設定這時候就會變的很重要,關於詳細的 Cookie 設定如下
setcookie ( string name [, string value [, int expire [, string path [, string domain [, int secure]]]]])

參數說明
(name) Cookie的變數名稱
(value) Cookie名稱的值
(expire) Cookie的留存時間,以「秒」為單位,如果沒有設定,當瀏覽器關掉時,cookie也跟著結束。
(path) 指在哪些目錄下的檔案可以使用Cookie
(Domain) 設定哪些網域可以使用Cookie
(Secure) 安全性-如果結合HTTPS安全傳輸協定(SSL),就是「1」,一般則為「0」。

使用setcookie( )函數時,得先注意下列事項:
  1. 與session_start( )函數的狀況一樣,在使用setcookie( )函數時,之前都不可以有任何的結果輸出。
  2. 如果 php.ini 的「register_globals」設為 on,只要在cookie有效期限用,可以直接使用 $變數輸出變數的內容,但如果設成 off ,則需要用 $_COOKIE["名稱"] 或 $HTTP_COOKIE_VARS["名稱"] 方式取得內容。
  3. 如果沒有設定留存時間,雖然有指定cookie名稱及數值,但因為一設定就過期,結果是無法讀取您寫入的 Cookie。
  4. 如果要刪除cookie的話,直接把要刪除cookie名稱的值設定為空白即可。

參考文章:PHP程式設計講義區
2008-01-06

TinyMCE 好用的 HTML 編輯器

這是個不錯的 HTML 編輯器,完全只使用 JavaScript 寫成,可以在沒有 Web server 的狀況下 work,有非常強大的功能,可以自行開發外掛模組,而且有詳細的參數設定,可以根據個人的需求加一改寫,支援多國語言,有官方語言包,而且也支援各種的瀏覽器。

官方網站-下載頁面
中文設定說明

<script language="javascript" type="text/javascript"
src="../jscripts/tiny_mce/tiny_mce.js"></script>
<script language="javascript" type="text/javascript">
tinyMCE.init({
mode: "textareas",
/* (textareas) 將所有 textarea 轉換成編輯器。*/
/* (exact) 只轉換特定的元素。
在 elements 設定中指定那些元素的 ID 或 name 。*/
theme: "advanced",
/* (advanced) 這是TinyMCE的高級主題,*/
/* 這個主題允許用戶增加刪除按鈕/面板,並且比簡單或默認主題更加靈活。*/
/* (simple) 這是TinyMCE最簡單的主題,只包括最基本的功能。*/

language: "zh_tw_utf8",
/* 設定多國語言的檔案名稱*/

content_css: "example_full.css",
/* 用於編輯器內部(可編輯區域)的 CSS文件*/

plugins: "devkit,style,layer,...",
/* TinyMCE 的外掛插件,也可以載入自己寫的外掛*/

theme_advanced_buttons1_add_before: "save,newdocum...",
theme_advanced_buttons1_add: "fontselect,fontsizes...",
theme_advanced_buttons2_add: "separator,insertdate...",
theme_advanced_buttons2_add_before: "cut,copy,paste...",
theme_advanced_buttons3_add_before: "tablecontrols...",
theme_advanced_buttons3_add: "emotions,iespell,...",
theme_advanced_buttons4: "insertlayer,moveforward,...",
/*共有三類的方法設定按鈕列的配置,所有按鈕的清單*/
/* theme_advanced_buttons<1-n> 直接設置按鈕的清單*/
/* theme_advanced_buttons<1-n>_add 在預設的清單後面加入額外的按鈕*/
/* theme_advanced_buttons<1-n>_add_before 在預設的清單前面加入額外的按鈕*/


theme_advanced_toolbar_location: "top",
/* 按鈕列的位置 "top", "bottom", "none"*/

theme_advanced_toolbar_align: "left",
/* 按鈕列的對齊方式。left, right, center。*/

theme_advanced_path_location: "bottom",
/*路徑及調整大小按鈕的狀態列的位置。
"top", "bottom", "none"*/
theme_advanced_resize_horizontal: false,
theme_advanced_resizing: true,
nonbreaking_force_tab: true,
apply_source_formatting: true,
relat2ive_urls: false,
rem2ove_script_host: false,
});
</script>
2008-01-05

PHP 上傳變數 $_FILES

在 PHP 中可以透過 $HTTP_POST_FILES 或 $_FILES 變數來存取所上傳的檔案詳細內容。輸入元素名為 inputfile,其中資訊有:
$_FILES['inputfile']['name']
// 檔案在客戶端電腦上的檔案名稱

$_FILES['inputfile']['type']
// 檔案的 MIME 類型,例如 "image/gif"

$_FILES['inputfile']['size']
// 上傳檔案的檔案大小,單為為 bytes

$_FILES['inputfile']['tmp_name']
// 上傳檔案儲存在伺服器端的暫存檔案名

$_FILES['inputfile']['error']
// 在 PHP 4.2.0 或更新的片本才有的這個陣列元素,上傳檔案的錯誤號碼


參考頁面:
PHP Developer Channel
PHP5網管實驗室