27/06/2005
文字與 Unicode 脫逸序列碼雙向轉換
因為之前介紹過透過 Javascript 產生 Unicode 脫逸序列的方法。後來有網友又問道如何再將這 Unicode 序列轉回字串,我將解答公佈於下,有興趣的朋友自己試試囉!
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
<script language=javascript>
<!--
function StringToUniCode(source) {
sret = "";
// Unicode 跳脫序列之格式為 u00ff
for(var i=0; i < source.length; i++) {
var num = new Number( source.charCodeAt(i));
sret += "\u" + num.toString(16);
}
return sret;
}
function UniCodeToString(source) {
var codeAry = source.split("\u");
var sret = "";
for(var i=0; i < codeAry.length; i++) {
if(codeAry[i]=="")
continue;
sret += String.fromCharCode("0x" + codeAry[i]);
}
return sret;
}
//-->
</script>
將文字轉成 Unicode 跳脫序列
<form name=content>
來源:<input type=TEXT name=source size=40 value="常用連絡人"><br>
結果:<input type=TEXT name=result size=40><br>
<input type=button value="轉換成Unicode" onclick=
"document.forms.content.result.value = StringToUniCode(document.forms.content.source.value)">
<input type=button value="轉換回文字" onclick=
"alert(UniCodeToString(document.forms.content.result.value))">
</form>
22:10 發表於 Developing | 永久網址 | 留言 (9) | Email this | Tags: Programming, javascript, unicode, convert
22/03/2005
你所想像不到的 JavaScript
這不是一篇教你如何在網頁中應用 JavaScript 的教材。這是一篇讓你明瞭看似簡單的 JavaScript,其實其核心語法功能強大。我將在這篇文章中說明 JavaScript 物件導向的特性,並說明如何透過這些特性,達到傳統程式語言 (C++/Java) 所難以完成的功能。
Written by Edward Hsieh/謝鎮澤
January 04, 2002
Everything is Object in JavaScript
開宗明義:在 JavaScript 中任何東西都是物件:變數是物件、函式是物件,常數也是物件。證明方式:
alert (typeof('abc')); alert (typeof(123)); var ary = [123, "abc"]; alert (typeof(ary)); 上面的 typeof 會顯示物件資料型態。得到結果分別是 string, number, object。 Create Objects in JavaScript
既然任何東西都是物件,那建立物件的方法就多了。直接看個例子:var main = new Object; // 建立新物件 main.x = 123; // 設定物件成員變數(屬性)之一 main["y"] = "XYZ"; // 設定物件成員變數(屬性)之二 alert(main["x"]); // 取得物件屬性並輸出 alert(main.y);
可以看到在 JavaScript 中,main.x 與 main["x"] 這兩種語法是通用的。其實在其他語言中,這兩種表示法的語意並不相同。我稍後再作說明。
List All Members in an Object這是 JavaScript 的必殺技,使用 JavaScript 的人務必要學會這個技巧。底下函式可以傳回一個物件的所有成員的字串表達式,包括物件中的屬性及方法。在物件導向程式設計中,這種技術叫 reflection。
functin listMember(main) { var s = ""; for( key in main ) // 使用 in 運算子列舉所有成員 s += key + ": " + main[key] + "n"; return s; } 範例碼中的 key 會對應到物件中的屬性名稱,如 "x" 或 "y",而 main[key] 則對應到屬性值。 說這項技巧是必殺技的原因是,你可以透過這項技巧,將物件封裝的黑箱打開來,看看裡面藏有什麼東西。我常用這項技巧來看看 IE 與 Mozilla 的 Dom 物件模型有何不同。試試看下面呼叫範例,就可以知道這項技巧的強大了:
var ary = [123, "abc"]; alert (listMember(ary)); alert (listMember(document.location));
Construct Object with Initial Value
要在建立物件的同時指定物件初始值,必須先透過 function 建立一個「原型物件」(或稱為 constructor),再透過 new 運算子建立新物件。例如以下程式碼會建立一個二維陣列的原型,再產生一個新的二維物件。 function Array2DVar(x,y) { // 定義二維陣列原型 this.length = x; this.x = x; // x 維度長度 this.y = y; // y 維度長度 for(var i = 0; i < this.length; i++) // 初始各元素值為 null this[i] = new Array(y); // this 代表物件本身 } var a2dv = new Array2DVar(10, 10); // 建立新的 10*10 的二維陣列 a2dv[1][3] = "ABC"; // 設定二維陣列元素值 a2dv[2][6] = "XYZ"; a2dv[9][9] = 1000; alert( a2dv[1][3]); // 取得二維陣列元素值,並顯示出來 alert( a2dv[2][6]); alert( a2dv[9][9]); Initial Array Object 在 JavaScript 中陣列也是物件 (其實近代多數語言中陣列也都是物件,只有像 C 或 Assembly 這類古老的語言才不把陣列看成物件),因此也可以用 constructor 的語法來建構。當然 JavaScript 還提供了 [] 語法,以更方便建構陣列,範例如下: a = new Array("abc", "xyz", 1000); // constructor 語法,或 a = ["abc", "xyz", 1000]; // 陣列標準語法 陣列的元素可以是簡單的資料、其他物件,或是函數。舉個例子來在陣列裡面放函式: b = [ // 使用函式作為陣列元素 function () { alert("這個好玩!") }, function () { alert("再按一次離開!") }, function () { alert("再來一次!") }, function () { alert("最後一次!") } ]; for (var i = 0; i < b.length ; i++) b[i](); 最後一個 for 迴圈是個有趣的應用。由於 b 陣列中現在存放的所有元素都是函式,因此我們可以對 b 的每個元素進行呼叫。
Object as Association Array關連陣列 (Assocation Array) 又稱作 Map 或 Dictionary,是一種物件容器,其中可以放置許多的 key-value pair,以存取子物件。在JavaScript 中,物件本身就可以作為關連陣列。以關連陣列的方式初始化物件的範例如下:
obj1 = {"a" : "Athens" , "b" : "Belgrade", "c" : "Cairo"}; alert(obj["a"]); // 顯示 Athens obj2 = { name: "Edward", showName: function() { alert(this.name); } // 使用函式作為物件屬性 } obj2.showName(); // 顯示 Edward obj2.age = 23; // 屬性可以動態加入 其 中 obj1 儲存了三個子元素,其鍵 (key) 為 "a", "b" 與 "c",而值 (value) 為 "Athens", "Belgrade" 與 "Cairo"。obj2 中 showName 鍵所對應的值為 function,因此 obj2.showName() 即為函式呼叫。 Object as Return Value
雖然 Javascript 的函式只能傳回一個變數,但您卻可以將傳回值設定為物件,達到傳回 1個以上變數值的效果 function a () { return [32, 17]; } b = a(); alert( b ); // 或 alert(a());
function pixel () { return {"x": 32, "y":17}; }
point = pixel (); alert (point.x + "n" + point.y); // 或 alert (pixel().x + "n" + pixel().y); Delegation Function Object
函式也是物件,只是其中包含的是程式的邏輯。這項特性可拿來作為委任式的程式設計,亦即使用委任函式當作另一函式的參數: function doloop(begin, end, func) { // 這個函式是個 iterator for (var i = begin; i < end; i++) { func(i); } } function func1(i) { // 印出 ** n ** document.writeln("** " + i + " **
"); } doloop(1, 10, func1); // 印出 1o 行 ** n ** doloop(20, 29, function(i) { // 印出 1o 行 ## n ## document.writeln("## " + i + " ##
"); }); Object = Properties + Behaviors 古有明訓:程式 = 資料結構 + 演算法。而物件是建構程式的基本單位,自然的具有相同的性質。物件除了有屬性 (property),也可具有操作 (behavior),也就是函式。
假如我們要使用一維陣列來模擬二維陣列,那麼就無法使用 ary[x][y] 這種表示法來設定或取得陣列成員。不過我可以定義一個 set 方法來設定成員變數,而以 get方法來取得成員變數值。原型函式定義如下: function Array2D(x,y){ // 以一維陣列模擬二維陣列的原型物件 this.length = x * y; // 陣列總長 this.x = x; // x 維度長度 this.y = y; // y 維度長度 for(var i = 0; i < this.length; i++) // 初始各元素值為 null this[i] = null; this.get = function(x,y){ // 成員函式:取得陣列第 [x,y]個元素值 return this[x*this.x + y]; } this.set = function(x,y,value){ // 成員函式:設定陣列第 [x,y] 個元素值 this[x*this.x + y] = value; } } 我們接著來使用它: var a2d = new Array2D(10, 10); // 建立新的「二維」陣列 a2d.set(1, 3, "ABC"); // 設定「二維」陣列元素值 a2d.set(2, 6, "XYZ"); a2d.set(9, 9, 1000); alert( a2d.get(1,3) ); // 取得「二維」陣列元素值,並顯示出來 alert( a2d.get(2,6) ); alert( a2d.get(9,9) );
Member Function Outside of Constructor
我們也可以將物件成員函式寫於原型物件之外。以下的Array2D物件與上一個範例中的 Array2物件有相同的作用,只不過這次是寫在原型物件之外。 function Array2D(x,y){ // 以一維陣列模擬二維陣列的原型物件 this.length = x * y; // 陣列總長 this.x = x; // x 維度長度 this.y = y; // y 維度長度 for(var i = 0; i < this.length; i++) // 初始各元素值為 null this[i] = null; this.get = Array2DGet; // 用這種方式把成員函式掛進來 this.set = Array2DSet; } function Array2DGet(x,y){ // 成員函式:取得陣列第 [x,y] 個元素值 return this[x*this.x + y]; } function Array2DSet(x,y,value){ // 成員函式:設定陣列第 [x,y] 個元素值 this[x*this.x + y] = value; } Dynamic Object Function 這裡說明如何為一個已定義物件,動態的加上其他操作的方法。
如 果一物件已定義完成,而您也使用它來建立了新的物件,這時候您想為原型物件增加新的操作 (而不修改原型物件的原始碼),讓所有該物件的複本都能使用該操作,該如何達成呢?方法是使用物件的 prototype 屬性。以下這個例子,為 Array 這類 Object 在執行期加入一個 max 方法,以取得陣列元素之最大值 (修改自微軟 jscript.chm之範例): function array_max(){ // 定義求取 Array 最大值之函式 var i, max = this[0]; for (i = 1; i < this.length; i++){ if (max < this[i]) max = this[i]; } return max; } Array.prototype.max = array_max; // 在 Array 原型中加入 max 函式 上面的程式碼,首先建立一個 array_max 方法,以求取陣列之最大元素。接著將這個方法設定給 Array 原型物件。 var x = new Array(1, 2, 3, 4, 5, 6); // 透過 Array 建構子建立一陣列 // 想求取 x 中某一元素之最大值 var y = x.max( ); // 取得 x 之最大元素Dynamic Mix in
假 如物件 dynamic 有 mathod1, method2 兩個函式;而另一物件 main 有 methodA 及 methodB 兩個函式。現在我想把 dynamic 的所有特性 (feature) 匯入到 main 中,我們可以在 main 中加上一個 imports 函式:
function main(){ // main 之建構子 // ... this.imports = function (object) { if( typeof object == "object") for( value in object ) this[value] = object[value]; } // ... } obj = new main(); main.imports(new dynamic()); // 匯入 dynamic 物件之所有功能 這個 imports 函式可以動態的為 main 加上另一物件的所有操作。這種 Mix in 的功能可是 C++/Java 的 static type 語言所望塵莫及的。
22:40 發表於 Developing | 永久網址 | 留言 (15) | Email this | Tags: Programming, javascript, programming, object, oriented, oo
08/01/2005
RIA - Rich Internet Application
RIA - Rich Internet Application 一詞在最近在電腦網路、軟體產業竄紅。有多紅呢? 紅到上了 e 天下雜誌網站的封面故事 --《2005年7種哈燒新科技》。RIA 簡而言之,就是一種同時擁有瀏覽器的輕巧,與傳統應用程式豐富操作性的網路程式。
傳統上,當我們在使用網頁應用程式,像是 web mail 時,每點一個連結,畫面就自伺服器上更新(refresh)一次,以便顯示不同的資料。這與桌面應用程式並不相同,以收信軟體為例,在收件夾中點選不同的郵件並不會造成整個收信軟體的 refresh,會更新的只有信件內容顯示區。
摒除使用性較低,反應較慢這兩缺點之外,網頁應用程式卻有著傳統應用程式所難以達到的優點:免安裝(只需要瀏覽器)、永遠是最新版(只要更新伺服器上的應用程式就行了)、無遠弗屆的存取能力,以及(通常)較易於開發。RIA 就是擷取網頁應用程式與桌面應用程式兩者之長的產物。
目前在網路上,中文資料蒐集最豐富的網站當是阿修的部落格 » RIA,裡面介紹了各式各樣的 RIA 應用程式。如果想對 RIA 的原理及開發環境有所理解,則可參考 Overview - Rich Internet Applications。若是想隨時追蹤 RIA 的發展現況,那還有一個專門提供 RIA 資訊的入口網站: RichClients.org。
從以上的訊息來源可以歸納出,目前 RIA 所採用的 Client 端展示技術,似乎是以 Flash 最受歡迎。而採用 Flash 的 RIA 架構中,又以 Laszlo 及 Macromedia Flex 開發社群最堅強。究竟 Flash 的 RIA 技術可以給網頁應用程式帶來怎樣的豐富性呢,不妨連上它們的 demo 網站看看-- Laszlo demo, Flex demo。

如果你是 HTML 或 XML 基本教義派的支持者,打死也不肯用 Flash,那採用 DHTML 的 RIA client 也是有的。其中整個 Framework 比較完善的有 Isomorphics、DomAPI - DHTML Platform,以及 Bindows。如果你連上這些網站,並執行 demo 程式,你必定會訝異於原來 DHTML 可以做到這等地步。
最後,我又要為 Mozilla 抱不平了。Mozilla 的展示技術 - XUL,可以說是最早的 RIA 技術之一 (甚至有一個網站 Open XUL Alliance 專門提供各種 XUL 專案的資訊),可是卻在這一波 RIA 的浪潮中被冷落在一旁。我敢保證,現今的許多 RIA 技術,乃至微軟的 InfoPath、 XAML (XML Application Markup Language) 等,都必定在某些程度受到 XUL、Mozilla 的啟發。前思後想,Mozilla 在 RIA 較少人提及只有一個原因,Mozilla 的 XUL 並不是跨瀏覽器的標準,而前面所提的 Flash 及 DHTML 卻可以達到跨瀏覽器的要求。為此,我若是 Mozilla 瀏覽器的開發者,便會開發一個 XUL 的 activeX 元件,讓 IE 可以使用,問題就解決了。
06:55 發表於 Developing, Goodies, Thinking, Web | 永久網址 | 留言 (0) | Email this | Tags: Taiwanese bloggers, ria, ajax, javascript
13/11/2004
Unicode 脫逸序列轉換
這裡提供一段程式碼,可以透過 JavaScript 將文字轉換為 Unicode 脫逸序列。這段程式碼,不論是對網頁開發人員,還是對 java resource bundle 的翻譯人員,都有很大的方便性。使用時只要將底下的程式碼複製起來,以 html 副檔名儲存,就可以用 browser 執行了。
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5"><script language=javascript>
<!--
function StringToUniCode(source) {
sret = "";
// Unicode 跳脫序列之格式為 u00ff
for(var i=0; i < source.length; i++) {
var num = new Number( source.charCodeAt(i));
sret += "\u" + num.toString(16);
}
return sret;
}
function convert(){
document.forms.content.result.value
= StringToUniCode(document.forms.content.source.value);
}
//-->
</script>
將文字轉成 Unicode 跳脫序列
<form name=content>
來源:<input type=TEXT name=source size=40 value="常用連絡人"><br>
結果:<input type=TEXT name=result size=40><br>
<input type=button value=轉換 onclick="convert()">
06:50 發表於 Developing, Web | 永久網址 | 留言 (1) | Email this | Tags: Programming, javascript, unicode, convert
08/06/2004
Javascript: Scripting Search Enging
底下是一個用 JavaScript 實作的 search engine,基本上只要把這些 code 複製下來,放到一個 HTML 頁面中即可。有興趣的研究看看...
<</span>script language="JavaScript1.3"> var s = new Array(); s[0]="Java: IoC^java_ioc.html^Inversion of Control^Micro Kernal, Application Framework" s[1]="Eclipse: Useful External Tools^ecli_extls.html^" s[2]="Some Useful Eclipse Plugins^ecli_plugin.html^" s[3]="Who am i?^about_me.html^who am i" s[4]="My Software List^soft_list.html^" s[5]="Enterprise Character^ent_charact.html^Enterprise culture" s[6]="Database Design Patterns^db_depat.html^" s[7]="Java Book Recommend(in Chinese)^java_book.html^" s[8]="Java network library^java_netlib.html^" s[9]="Java: AOP^java_aop.html^" var results_location = location.href; function search_form(jse_Form) { if (jse_Form.d.value.length > 0) window.location = results_location+"?"+escape(jse_Form.d.value); } // ---------- search functions ----------- var p = location.href.indexOf("?"); if (p != -1) var d = unescape(location.href.substring(p + 1, location.href.length)); var m = 0; if(typeof(d)=="undefined"){ m=-1; d=""; } else if (d.charAt(0) == '"' && d.charAt(d.length - 1) == '"') { m = 1; } var od = d; var r = new Array(); var co = 0; if (m == 0) { var woin = new Array(); var w = d.split(" "); for (var a = 0; a <</span> w.length; a++) { woin[a] = 0; if (w[a].charAt(0) == '-') { woin[a] = 1; } } for (var a = 0; a <</span> w.length; a++) { w[a] = w[a].replace(/^-^+/gi, ""); } a = 0; for (var c = 0; c <</span> s.length; c++) { pa = 0; nh = 0; for (var i = 0; i <</span> woin.length; i++) { if (woin[i] == 0) { nh++; var pat = new RegExp(w[i], "i"); var rn = s[c].search(pat); if (rn >= 0) { pa++; } else { pa = 0; } } if (woin[i] == 1) { var pat = new RegExp(w[i], "i"); var rn = s[c].search(pat); if (rn >= 0) { pa = 0; } } } if (pa == nh) { r[a] = s[c]; a++; } } co = a; } if (m == 1) { d = d.replace(/"/gi, ""); var a = 0; var pat = new RegExp(d, "i"); for (var c = 0; c <</span> s.length; c++) { var rn = s[c].search(pat); if (rn >= 0) { r[a] = s[c]; a++; } } co = a; } function return_query() { document.jse_Form.d.value = od; } function num_jse() { if(m==-1) document.write('Please input keyword(s) to search with.'); else document.write(co, " page(s) found "); } function out_jse() { if (co == 0 ) { if(m!=-1) document.write('Your search did not match any documents.
' + 'Make sure all keywords are spelt correctly.
' + 'Try different or more general keywords.'); return; } document.write('
); for (var a = 0; a <</span> r.length; a++) { var os = r[a].split("^"); var br = "" + d + ""; os[2] = os[2].replace(pat, br); document.write("- ", ', os[1], '">', os[0], ' ',os[2], ''); } document.write('
'); } </</span>script> <</span>form name="jse_Form" onsubmit="search_form(jse_Form);return false"> <</span>input type="text" name="d"> <</span>input type="button" value="Go" onclick="search_form(jse_Form)"> </</span>form> <</span>script language="JavaScript1.3" type="text/javascript">return_query()</</span>script> <</span>script language="JavaScript1.3" type="text/javascript">num_jse()</</span>script> <</span>script language="JavaScript1.3" type="text/javascript">out_jse()</</span>script>
05:40 發表於 Developing, Web | 永久網址 | 留言 (0) | Email this | Tags: Programming, javascript, programming, search engine


