2010年10月21日 星期四

Ajax 入門簡介

網頁程式碼常被劃分為  - HTML程式碼、儲存資料的XML、處理資料的JavaScript
動態資料儲存在XML,可以達成在不動到HTML碼的前提下修改網頁內容
這樣的快速資料更新與動態呈現的技術就是Ajax
用戶端開始Ajax請求,並等待伺服器的回應
伺服器收到請求後回傳資料,並由JavaScript居中媒介及整合資料到網頁裡

在這段過程中
使用者依然可以持續享受原本的服務,並等待在背景執行的Ajax請求執行結束
這也就是Ajax名稱的由來(Asynchronous JavaScript + XML)

JavaScript內建一個XMLHttpRequest物件
用於初始Ajax請求,並處理Ajax回應
它有比較複雜的類別成員及方法:
abort() -
取消Ajax請求

open() -
準備請求,指定請求的型態、URL與其他細節

send() -
傳送請求給伺服器

readyState -
請求的狀態碼代號;0表示未初始,1是開啟,2是已傳送,3是接收中,4是已載入

status -
HTTP的請求狀態代碼(ex:404錯誤,200表示正常)

onreadystatechange -
請求狀態改變時會被呼叫的函式參考
                              
responseText -
伺服器回傳的純文字字串資料

responseXML -
伺服器回傳的的XML資料


因為不同的瀏覽器(其實是IE問題比較大...)有不同的 XMLHttpRequest 物件建立方式
建立時必須先寫如下的程式碼:
var request = null;
if(window.XMLHttpRequest){
    try{
      request = new XMLHttpRequest();   
    }catch(e){
      request = null;
    }
}
//for IE version
else if(window.ActiveXObject){
    try{
      request = new ActiveXObject("Msxm12.XMLHTTP");   
    }catch(e){
      try{
        //for older versions of IE 
        request = new ActiveXObject("Microsoft.XMLHTTP");         
      }catch(e){
        request = null;     
      }
    }
}

部分版本的 Mozilla 瀏覽器,在伺服器送回的資料未含 XML mime-type header 時會出錯
解決方法是,用下列方法覆寫伺服器傳回的檔頭,以免傳回的不是 text/xml:
request = new XMLHttpRequest();
request.overrideMimeType('text/xml');

建立Ajax請求物件後,接著要設定伺服器傳回資料後的處理方式,之後再開啟請求
API 如下:
request.onreadystatechange = handler;       //handler是處理傳回值的 JavaScript 函式名稱
request.open(type, url, true);                          //true set for being always asynchronous

onreadystatechange 直接指向 handler() 的位置
這裡用匿名函式來處理也是可以的
request.onreadystatechange = function(){
    //code
}

open() 的第一個參數是 HTTP request 的方法
也就是從 GET、POST、HEAD 等伺服器支援的方法中擇一使用
為遵循 HTTP 標準,請記得這些方法都是大寫
否則有的瀏覽器不會處理這些請求
第二個參數是請求頁面的 URL
基於安全考量,呼叫同網域以外的網頁是被禁止的
如果網域不同,則叫用 open() 時會出現「權限不足,拒絕存取」那類的錯誤
常見的錯誤多為在 domain.tld 的網站下呼叫 www.domain.tld 中的網頁
僅是一點點差別都不行
第三個參數決定此 request 是否不同步進行
如果設定為 TRUE 則即使伺服器尚未傳回資料也會繼續執行其餘的程式

type一般選擇填入 "GET" 或 "POST"
GET 適用於不會改變伺服器任何設定的資料傳輸
有需要的話還能透過 url 傳小量資料到伺服器
範例:
request.open("GET", "Data.xml", true);
request.send(null);                                         //請求傳送時沒有資料,所以設定成null  

POST 適用於會變更伺服器設定的資料傳輸
範例:
request.open("POST", "addData.php", true);
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;
                                                 charset=UTF-8"); 
request.send("date=10/10/18&demo_string=Hello World!");     //資料附在send()的參數裡傳送

send() 的參數在以 POST 發出 request 時,可以是任何想傳給伺服器的東西
不過以 POST 方式傳送資料前,必須先設定好 MIME type 才能讓伺服器理解資料的處理方式
application/x-www-form-urlencoded; charset=UTF-8 表示資料的型別是 URL-encoding
而資料則以查詢字串的方式列出


Mozilla教學的範例:
test.xml===========

<?xml version="1.0" ?>
<root>
I'm a test.
</root>

test.html===========

<script type="text/javascript" language="javascript">
function makeRequest(url) {
    var httpRequest;

    if (window.XMLHttpRequest) { // Mozilla, Safari, ...
        httpRequest = new XMLHttpRequest();
        if (httpRequest.overrideMimeType) {
            httpRequest.overrideMimeType('text/xml');
        }
    }
    else if (window.ActiveXObject) { // IE
        try {
            httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e) {
            try {
                httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e) {}
        }
    }

    if (!httpRequest) {
        alert('Giving up :( Cannot create an XMLHTTP instance');
        return false;
    }
    httpRequest.onreadystatechange = function() { alertContents(httpRequest); };
    httpRequest.open('GET', url, true);
    httpRequest.send('');

}

function alertContents(httpRequest) {

    if (httpRequest.readyState == 4) {         
        if (httpRequest.status == 200) {                //表示已傳輸完成且正常
            var xmldoc = httpRequest.responseXML;
            var root_node = xmldoc.getElementsByTagName('root').item(0);
            alert(root_node.firstChild.data);
        } else {
            alert('There was a problem with the request.');
        }
    }

}
</script>

<span
style="cursor: pointer; text-decoration: underline"
onclick="makeRequest('test.xml')">
    Make a request
</span>

2010年10月17日 星期日

JavaScript 筆記(3)

這篇筆記紀錄:
1.JavaScript的物件導向寫法與型別判斷
2.陣列的排序法
3.以for迴圈及foreach迴圈取出物件的差別
4.String物件的常用方法
5.Math 物件的常用方法
6.addEventListener 與 attachEvent 函式說明

1.JavaScript的物件導向寫法與型別判斷

   JavaScript本身就是個以物件為主體的script語言
   連函式本身也是物件,或者說JavaScript的function類似其他語言的class

   除了數值、字串、boolean、null、undefined,其他的所有值都是物件

   typeof運算子在判斷特性的型別有很大的幫助
   typeof obj.num         // 'number'
   typeof obj.arrival      // 'object'

   // 要小心有可能是涵式的值,因為原型鍊上的特性都可以產生值
   typeof obj.toString            // 'function'
   typeof obj.constructor      // 'function'

   hasOwnProperty() 在物件有指定屬性時回傳true,這個方法不會檢索原型鍊
   可以用來避免上述風險
   obj.hasOwnProperty('number')        //true
   obj.hasOwnProperty('constructor')  //false

   當需要自訂物件時,必須寫好物件的建構式,並使用new關鍵字來產生物件
   而JavaScript的類別成員不需要先宣告也不用處理型別,直接用this關鍵字來取得值
   範例:
    function ObjDemo(param1, param2){      //建構式必須首字大寫
        this.param1 = param1;
        this.param2 = param2;

        this.output = function(){
          return param1 + " " + param2;
        }
        ObjDemo.prototype.output2 = function(){
          return "This is a test ";

        }
    }

    var test = new ObjDemo("word1", "word2");
    test.output();
    test.output2();

    範例的程式碼可看出有兩種類別方法的寫法
    第一種用 this 關鍵字的方法會將方法指派給單一實例
    每建立一個物件時,物件內都會有方法的複本,處理方式像類別成員
    建立多個物件就會產生等同物件數量的方法複本
    第二種寫法使用了物件裡以特性的形式存在的prototype物件
    如此可建立類別所擁有的方法,所有建立的物件都會使用同一個方法    
    這樣可以改進資源的使用效率

    JavaScript實際上並不完全支援類別,但用prototype物件來模擬類別
    利用它也可以做到將類別成員給予物件類別共用
    ObjDemo.prototype.param3 = "This effect is like static member of other languages";


2.陣列的排序法

   範例:
    var tarray = [11, 35, 12, 9, 29];
    tarray.sort();

    sort() 方法預設依照升冪順序排列
   如果希望的排列規則不同,或是陣列裡存放的物件不是基本型別的話(也就是自訂物件)
   則依下列範例的形式修改:
    function compare(x, y){      //傳入物件x、y
      return x.value - y.value;     //回傳值<0,x排在y前;相同時則不排列;>0,y排在x前
    }
    tarray.sort(compare);

   又因為通常排序的函式只會用於sort() method
   所以寫成 tarray.sort( function(x, y){return x.value - y.value;} );  也行
   這樣也不需要為函式命名

3.以for迴圈及foreach迴圈取出物件的差別

   for ... in ... 敘述為JavaScript中for each的語法,但是為隨意排序取出資料;
   若想確保資料有一致的順序還是要乖乖用for迴圈

4.String物件的常用方法

    indexOf() 尋找字串是否包含特定子字串,找不到特定子字串則回傳 -1   
    charAt() 尋找特定字元在字串裡的位置
    toLowerCase()、toUpperCase()則是轉換字串大小寫的方法
    length 成員變數則提供字串裡的字元數量的訊息

    字串雖然看起來很像陣列物件,但沒辦法用 [index] 的形式去讀取它

5.Math 物件的常用方法

    Math 物件提供了常用的數學方法
    random() 產生介於0和1之間的亂數
    round() 將浮點數四捨五入為整數
    floor() 將浮點數無條件捨去為整數
    ceil() 將浮點數無條件進位為整數
    abs() 回傳絕對值
    PI 是Math物件提供的常數,值為3.14

6.addEventListener 與 attachEvent 函式說明

   addEventListener 是DOM的標準功能之一,能為某一事件附加其它的處理事件
   一般常見到的指定事件的處理函式的寫法如:
   window.onload = method1;       //指定處理的函式是method1()

   或是用匿名函式來處理:
   window.onload = function(){ method1(); }

   第一種方法的缺點在於一個事件只能定義一種處理,如:

   document.getElementById("btn").onclick = method1;
   document.getElementById("btn").onclick = method2;
   document.getElementById("btn").onclick = method3;    //只有最後定義的method3()會被執行

   addEventListener 是為了解決這個問題存在的
   函式為 addEventListener(event,function,capture/bubble)
   第一個參數是參數接收事件名稱(名稱不含on,如:"load" or "click")
   第二個參數是要執行的函式
   第三個參數設定 capture 或 bubble 的事件讀取方式,以bool值表示
   簡單來說 capture 從讀取完document後再執行事件
   而bubble則是先尋找指定的網頁元件位置再執行事件
   true 表示選擇 capture,false 指定用 bubble,一般指定 false 即可

   IE不支援 addEventListener,要改用 attachEvent 這個IE特有的函式
   傳入的參數大致上相同,只是第一個參數要改成完整事件名稱(如:"onclick")
   而因為IE的事件的傳遞讀取方式預設用 bubble,所以第三個參數可以省略不輸入

   完整範例:
    var bt = document.getElementById("bt");

    if(window.addEventListener){
       bt.addEventListener("click",method1,false);
       bt.addEventListener("click",method2,false);
       bt.addEventListener("click",method3,false);
    }else if(window.attachEvent){
       bt.attachEvent("onclick",method1);
       bt.attachEvent("onclick",method2);
       bt.attachEvent("onclick",method3);
   }

   執行順序為method1->method2->method3

JavaScript DOM模型操作

Document Object Model(DOM) 能將HTML視為XML處理
對於JavaScript來說,可以藉此做到動態處理
DOM將網頁視為節點構成的階層樹,如下圖所示:

階層樹的頂點是Document,並往下聯繫到各個網頁元件形成的節點
HTML元件節點也被稱為元件節點(Element node)
網頁元件的文字內容則儲存在元件下的文字節點(Text node)
Attribute是元件的屬性,可以透過Element node取得,但不會直接出現在階層樹裡

document 提供了 getElementById()、getElementsByTagName()方法來導引到其它子節點

getElementById() 可以從整份DOCUMENT中取得有指定id的元素
getElementsByName() 與 getElementsByTagName() 也是有著類似作法的函式

不過因為後兩個函式取得的元件有可能為複數,所以需要用陣列存取
如:getElementsByTagName("div")[0]  取得第一個div元素

getElementById()一般是最常用到的函式
id在每個DOCUMENT中只能是獨特的,name卻有可能是重複的
此外, getElementsByName()在非IE的瀏覽器可能行不通


在各個節點可以取得我們需要的特性:
nodeName - 回傳節點的標籤名稱,如<div>會回傳 DIV
nodeValue - 儲存於節點的值,只限文字與屬性節點使用
nodeType - 回傳節點型態
                   element node回傳1,attribute node回傳2
                   text node回傳3,包括換行符號等
childNodes - 包含節點下所有子節點的陣列,以出現在HTML碼裡的順序排列
childElementCount - 回傳 element 子代 (child) 元素的數量
parentNode - 回傳其父節點
firstChild - 節點下的第一個子節點
lastChild - 節點下的最後一個子節點
nextSibling - 下一個節點(節點範圍不限同一層)
previousSibling - 上一個節點(節點範圍不限同一層)

較特殊的:
document.baseURI - 取得目前文件的路徑(即目前網址)
style - 設定或取得某個節點的屬性,類似CSS設定,如:node.style.width='100px';
className - 設定或取得節點的class屬性


另外說明.children屬性
這個也是相當常被看到的屬性,使用的方式也很類似childNodes
差別在於
1.childNodes是W3C標準,children則不是(但基本上browser都會實作這個屬性)
2.childNodes會回傳 NodeList,children則是HTMLCollection
3.children回傳的內容不包括 text node等,僅回傳 element node
   所以如有下列的情形
   <div>
         <a></a>
   </div>

   像這樣節點間存在換行符號、空白
   用 childNodes.firstChild 便有可能取不到我們真正想要的 node(視 browser 實作情形)

可以在節點上使用的方法則有
appendChild() - 加入子節點
cloneNode() -  參數設定為 true 可複製該元素的所有子代 (child)
                        設定為 false 則通常只會複製一個文字節點
    範例:
    var demo = document.getElementById("demo");
    var demo2 = demo.cloneNode(true);
    document.body.appendChild(demo2);

hasChildNodes() - 回傳boolean值,判斷有無子節點
hasAttributes() - 回傳是否有無屬性值
insertBefore() - 使用方式:parentNode.insertBefore(newElement, referenceElement)
removeChild() - 刪除子節點,使用方式:parentNode.removeChild(node)
replaceChild() - 使用方式:node.replaceChild(newChild, oldChild);
getAttribute() - 取得節點的某項屬性,如:node.getAttribute("nowrap")
setAttribute() - 設定節點的某項屬性,如:node.getAttribute("height", "100px")
removeAttribute() - 刪除節點的某項屬性,如:node.getAttribute("nowrap")


使用範例:document.getElementsByTagName("div")[0].childNodes[1].nodeValue = 1;
當然範例要先確定childNode[1]底下只有一個節點,否則會得不要想要的效果
如果不確定所要更改的節點內容是否有多個子節點
那麼更改的時候就要先清除所有的子節點後,再新增有新內容的新子節點,如:
var node = document.getElementById("target");
//有子節點的話,firstChild回傳true
while(node.firstChild){ node.removeChild(node.firstChild); }
node.appendChild(document.createTextNode("alter OK"));

當然先寫好一個替換節點文字內容的函式,通常是個方便的選擇,如:
function replaceNodeText(id, newText){
   var node = document.getElementById(id);
   while(node.firstChild){ node.removeChild(node.firstChild); } 
   node.appendChild(document.createTextNode(newText));
}

DOM提供了透過節點調整CSS的機制
透過節點物件的className特性可以操作網頁元件的類別(class)特性
如:document.getElementById("target").className = "deco2";
節點的style特性提供對單一樣式性質的存取
如:document.getElementById("target").style.visibility = "hidden";

前面看到過的createTextNode()只能建立純粹的文字內容
接著要提的createElement() 可以用來建立任何的HTML元件
建立段落文字的範例:
var newElem = document.createElement("p");
newElem.appendChild(document.createTextNode("Hello World"));
document.getElementById("target").appendChild(newElem); 

加入的段落文字會以符合標準的形式呈現 -> <p>Hello World</p>

2010年10月16日 星期六

JavaScript 筆記(2)

這篇筆記紀錄:
1.Timer用法
2.使用JavaScript作網頁元件CSS調整修改
3.取得外部CSS資訊的方法
4.Cookie範例
5.分離JavaScript與HTML程式碼
6.快速取得物件的小技巧
7.離開頁面的確認視窗寫法

1.Timer用法

計時器只能做到延遲時間,並非是依照真實時間來觸發
單次計時器的書寫方式:setTimeout("String型別的JavaScript Code", 6000);
單次計時器示範: setTimeout("document.getElementById('a').src='b.jpg';", 5*1000);

間歇計時器則使用 setIntervel()函式,引入的參數則與單次計時器相同
間歇計時器示範:var timerID = setIntervel(...);
儲存ID的資訊的作用是要使用下一個介紹的函式 clearInterval()
clearInterval(timerID)能清除間歇計時器,停止它的作用

location物件的reload() 可以重新讀取頁面,使用範例:location.reload();
結合timer可以做到定時重讀頁面等效果

2.使用JavaScript作網頁元件CSS調整修改

JavaScript能以document物件取得用戶端的視窗寬度,並進而調整顯示物件的大小
用戶端視窗是指瀏覽器視窗裡呈現網頁的部分,並不包含瀏覽器工具列等的部分
用戶端視窗高度= document.body.clientHeight  用戶端視窗寬度=  document.body.clientWidth
其他常用的查詢需要去查API

取得圖片等元件的高度及寬度的取法如: var width = document.getElementById('a').width;
而網頁裡的所有元件都有一個style物件,能借助它達到調整CSS的顯示效果
如: document.getElementById('a').style.left = "300px";
注意一點,由 style 取得的資料有些是帶有px之類單位的字串
處理方式如:var picPos =  eval(document.getElementById('a').style.left.replace("px", ""));
這樣一來會先以replace()把 px 移除,將著用eval()函式將之轉換成數值

3.取得外部CSS資訊的方法

在IE中要取得外部CSS的資訊必須使用特有的 currentStyle
其他瀏覽器則必須使用 defaultView 物件的 getComputedStyle()
範例如下:
var item = document.getElementById('a');
var iStyle = item.currentStyle || document.defaultView.getComputedStyle(item, null);
document.write("字體大小=" + iStyle.fontSize);


4.Cookie範例

w3cschool的Cookie的示範程式碼
function getCookie(c_name)
{
if (document.cookie.length>0)
  {
  c_start = document.cookie.indexOf(c_name + "=");
  if ( c_start != -1 )
    {
    c_start = c_start + c_name.length+1;
    c_end = document.cookie.indexOf(";", c_start);
    if (c_end == -1) c_end = document.cookie.length;
    return unescape(document.cookie.substring(c_start, c_end));
    }
  }
return "";
}

function setCookie(c_name, value, expiredays)
{
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie=c_name + "=" + escape(value) +
((expiredays == null) ? "" : "; expires = " + exdate.toUTCString() );
}

function checkCookie()
{
username = getCookie('username');
if (username != null && username != "")
  {
  alert('Welcome again ' + username + '!');
  }
else
  {
  username = prompt('Please enter your name:',"");
  if (username != null && username != "")
    {
    setCookie('username', username, 365);
    }
  }
}

清除cookie的方法是將他的值改成空值,並將有效日期改成-1

5.分離JavaScript與HTML程式碼

透過HTML屬性聯繫事件處理函式(如:<button... onclick="script();" />)的寫法有缺點
HTML與JavaScript的混雜不利於維護
在JavaScript碼中指定函式的參考就可以避免動到HTML碼
如:window.onload = init;
上式效果等同於<body onload="init();">
onload是window物件的屬性,並被指派了 init() 函式的參考

如果需要將參數傳入函式中,則如下面範例改寫:
document.getElementById("test").onclick = function(evt){
     testFunc("hi");
}

外層的 function literal包裹住對 testFunc() 的呼叫,並允許將參數傳入函式中
function literal 本身則傳入了事件物件做參數,若需要事件的資料可以靠它取得
假如不需要事件物件的話,參數evt會被忽略
function literal 會以函式參考被指派到onclick事件

假使JavaScript碼會取用網頁元件,必須注意在網頁的onload事件接收完資料後才能指定元件
window.onload 能在這種情況下完成要求,事件處理器在這裡接上應用程式:
window.onload = function(){
    document.getElementById("test").onclick = function(evt){ testFunc("hi"); }
    .....  //程式碼配置
};

順便一提的是如果網頁文件載入的時間比較長
在完成之前可能會讓使用者看到未經處理的內容
要避免這種情形可以先將處理前的內容隱藏起來,處理完畢後再顯示出來

另外,因DOM的載入速度一般來說會比較慢
window.onload這樣綁定DOM物件的程式碼放在<head>裡可能不會有作用
這類型建議放在body標籤後才可能會有效

6.快速取得物件的小技巧

經常使用的 document.getElementById() method 可以寫成快捷函式來方便使用:
function $(id){
    return document.getElementById(id);
}

7.離開頁面的確認視窗寫法

//using JQuery
$(window).bind("beforeunload",function(){
     return ("您確定離開?");
});

2010年10月15日 星期五

[轉載] 美式鍵盤的微軟日文輸入法轉換狀態快速鍵

我們多數人使用的鍵盤是美式鍵盤(101/104鍵),安裝微軟的日文輸入法後會發現轉換輸入法狀態很麻煩,常常要用滑鼠點來點去。因為微軟日文輸入法提供的使用說明,是針對日本特殊鍵盤的使用者,沒提到美式鍵盤的轉換快速鍵。
常常看到有新手問這問題,我也不藏私。在此提供我個人經過多次嘗試後找出的美式鍵盤轉換快速鍵的對照表。
功能 快速鍵 說明
輸入語系轉換 ALT + SHIFT 循環轉換。如果系統上只安裝了中文語系及日文語系輸入法,就會在 CH <-> JP 之間轉換。
英、日文輸入模式轉換 ALT + ~ ~ 就是 TAB 上面那顆按鍵。循環轉換。英文輸入模式即 Direct Input mode 。
平假名模式(Hiragana) CTRL + CAPS 注意,若是在英文輸入模式按此快速鍵,會先轉換到先前的日文輸入模式,而不是直接轉換到平假名模式。例如你原本是在片假名模式,按 ALT+~ 轉換到英文輸入模式之後再按 CTRL+CAPS ,則會轉換回先前的片假名模式。
片假名模式(Full-width Katakana) ALT + CAPS 注意,若是在英文輸入模式按此快速鍵,會先轉換到先前的日文輸入模式,而不是直接轉換到片假名模式。
半形片假名模式(Half-width Katakana) SHIFT + SPACE 須先轉換到片假名模式,此一快速鍵才會作用。
半形英數符號模式(Half-width Alphanumeric) SHIFT + CAPS 須先轉換到平假名模式或片假名模式,此一快速鍵才會作用。另外,在半形英數符號模式按此快速鍵時,將會轉換到平假名模式。
我當年在大學修日文時,老師不准學生標國語注音或羅馬拼音。還會檢查課本,標拼音的扣學期成績。因為是必修的,只好乖乖照辦。如果你跟我一樣是這麼學日文 的,那麼用起羅馬拼音可能不是很順手。有些字如うぁ, を, しゃ等等,可能需查一下微軟日文輸入法的羅馬拼音輸入表才會輸入。查看方式有些麻煩,首先切換到日文語系輸入狀態,接著用滑鼠點擊語言列上的那顆紅色圖 案,叫出選單,選 Help > Contents and Index > Romaji-Kana Correspondence Chart 。如圖所示:


圖1: 查看羅馬拼音輸入表的操作圖例
自己列印出來以便查看吧。當然這張表僅供電腦輸入時查看。正式學日語時,最好不要依賴羅馬拼音。
單獨使用或後接子音時,僅需輸入 n 。 若後接母音(aiueo),則須輸入 nn 或 n'
促音 っ
重覆其後子音的首鍵。例: いった = itta (た = ta, 重覆 t)
不用的古音
ゐ: wi (須選字) ゑ: we (須選字)

2010年10月13日 星期三

非 Servlet 的Java程式碼取得JSP request 物件

在JSP中常有藉有 request 物件來獲得所需物件(如parameter、cookie)的需求
在Servlet裡我們會將 request、response 物件傳入所要覆寫的傳輸協定裡,如下:
public void doPost(HttpServletRequest request, HttpServletResponse response){
....
}

那假如要在非Servlet取得request,我們就自行將request物件傳入即可,例如:
public void setPageInfo(HttpServletRequest request){
    if(request.getParameter("page") != null){
    page = Integer.parseInt(request.getParameter("page"));
    }
    request.setAttribute("page", page);
}

之後在目標JSP頁面中就可以用標籤或 EL呼叫method:
<jsp:setProperty property="pageInfo" name="view" value="${pageContext.request}" />

當然不只可以用標籤來進行就是了,<%=xxx.xxx(request)%> 這樣子的處理也OK
不過需要注意一下
如果要做 set 或 動態性的處理似乎只能在有傳入request的該method才能做
推測是傳入request物件表示在請求過程的處理
如果是回應已經送出的話,可能就只能使用 getParameter() 之類的method

2010年10月12日 星期二

[轉載] JSTL fmt 格式標籤庫使用介紹

在該標籤庫中的標籤一共有 12 個,被分為了兩類,分別是:
 
國際化核心標籤: 
<fmt:setLocale> 、 <fmt:bundle> 、 <fmt:setBundle> 、 <fmt:message> 、 <fmt:param> 、 <fmt:requestEncoding> 。

格式化標籤:
<fmt:timeZone> 、 <fmt:setTimeZone> 、 <fmt:formatNumber> 、 <fmt:parseNumber> 、 <fmt:formatDate> 、 <fmt:parseDate> 。
下面只選擇其中常見的一些標籤和屬性進行介紹。

用於設置本地化環境的 <fmt:setLocale> 標籤

<fmt:setLocale> 標籤用於設置 Locale 環境。它的屬性和描述如下表所示:

屬性 描述
value Locale 環境的指定,可以是 java.util.Locale 或 String 類型的實例
scope Locale 環境變量的作用範圍(可選)
下面看一個示例:
<fmt:setLocale value="zh_TW"/>
表示設置本地環境為繁體中文。

用於資源文件綁定的 <fmt:bundle> 、 <fmt:setBundle> 標籤

這兩組標籤用於資源配置文件的綁定,唯一不同的是 <fmt:bundle> 標籤將資源配置文件綁定於它標籤體中的顯示,<fmt:setBundle> 標籤則允許將資源配置文件保存為一個變量,在之後的工作可以根據該變量來進行。
根據 Locale 環境的不同將查找不同後綴的資源配置文件,這點在國際化的任何技術上都是一致的,通常來說,這兩種標籤單獨使用是沒有意義的,它們都會與 I18N formatting 標籤庫中的其他標籤配合使用。它們的屬性和描述如下所示:

屬性 描述
basename 資源配置文件的指定,只需要指定文件名而無須擴展名,二組標籤共有的屬性
var <fmt:setBundle> 獨有的屬性,用於保存資源配置文件為一個變量
scope 變量的作用範圍
下面看一個示例
<fmt:setLocale value="zh_CN"/>
<fmt:setBundle basename="applicationMessage" var="applicationBundle"/>
該示例將會查找一個名為 applicationMessage_zh_CN.properties 的資源配置文件,來作為顯示的 Resource 綁定。

用於顯示資源配置文件信息的 <fmt:message> 標籤

用於信息顯示的標籤,將顯示資源配置文件中定義的信息。它的屬性和描述如下所示:

屬性 描述
key 資源配置文件的「鍵」指定
bundle 若使用 <fmt:setBundle> 保存了資源配置文件,該屬性就可以從保存的資源配置文件中進行查找
var 將顯示信息保存為一個變量
scope 變量的作用範圍
下面看一個示例:
<fmt:setBundle basename="applicationMessage" var="applicationBundle"/>
<fmt:bundle basename="applicationAllMessage">
         <fmt:message key="userName" />
         <fmt:message key="passWord" bundle="${applicationBundle}" />
</fmt:bundle>
該示例使用了兩種資源配置文件的綁定的做法,「 applicationMessage 」資源配置文件利用 <fmt:setBundle> 標籤被賦於了變量「 applicationBundle 」,而作為 <fmt:bundle> 標籤定義的「 applicationAllMessage 」資源配置文件作用於其標籤體內的顯示。

第一個 <fmt:message> 標籤將使用「 applicationAllMessage 」資源配置文件中「鍵」為「 userName 」的信息顯示。

第二個 <fmt:message> 標籤雖然被定義在 <fmt:bundle> 標籤體內,但是它使用了 bundle 屬性,因此將指定之前由 <fmt:setBundle> 標籤保存的「 applicationMessage 」資源配置文件,該「鍵」為「 passWord 」的信息顯示。

用於參數傳遞的 <fmt:param> 標籤

<fmt:param> 標籤應該位於 <fmt:message> 標籤內,將為該消息標籤提供參數值。它只有一個屬性 value 。
<fmt:param> 標籤有兩種使用版本,一種是直接將參數值寫在 value 屬性中,另一種是將參數值寫在標籤體內。

用於為請求設置字符編碼的 <fmt:requestEncoding> 標籤

<fmt:requestEncoding> 標籤用於為請求設置字符編碼。它只有一個屬性 value ,在該屬性中可以定義字符編碼。

用於設定時區的 <fmt:timeZone> 、 <fmt:setTimeZone> 標籤

這兩組標籤都用於設定一個時區。唯一不同的是 <fmt:timeZone> 標籤將使得在其標籤體內的工作可以使用該時區設置, <fmt:setBundle> 標籤則允許將時區設置保存為一個變量,在之後的工作可以根據該變量來進行。它們的屬性和描述如下表所示:

屬性 描述
value 時區的設置
var <fmt:setTimeZone> 獨有的屬性,用於保存時區為一個變量
scope 變量的作用範圍

用於格式化數字的 <fmt:formatNumber> 標籤

<fmt: formatNumber > 標 簽用於格式化數字。它的屬性和描述如下表所示:

屬性 描述
value 格式化的數字,該數值可以是 String 類型或 java.lang.Number 類型的實例
type 格式化的類型
pattern 格式化模式
var 結果保存變量
scope 變量的作用範圍
maxIntegerDigits 指定格式化結果的最大值
minIntegerDigits 指定格式化結果的最小值
maxFractionDigits 指定格式化結果的最大值,帶小數
minFractionDigits 指定格式化結果的最小值,帶小數
<fmt:formatNumber> 標籤實際是對應 java.util.NumberFormat 類, type 屬性的可能值包括 currency (貨幣)、 number (數字)和 percent (百分比)。
下面看一個示例。
<fmt:formatNumber value="1000.888" type="currency" var="money"/>
該結果將被保存在「 money 」變量中,將根據 Locale 環境顯示當地的貨幣格式。

<fmt:formatNumber value="12" type="currency" pattern="$.00"/>   //$12.00

<fmt:formatNumber value="12" type="currency" pattern="$.0#"/>   //$12.0

<fmt:formatNumber value="1234567890" type="currency"/>   //$1,234,567,890.00(那個貨幣的符號和當前web服務器的 local 設定有關)

<fmt:formatNumber value="123456.7891" pattern="#,#00.0#"/> // 123,456.79   

<fmt:formatNumber value="123456.7" pattern="#,#00.0#"/>     // 123,456.7   

<fmt:formatNumber value="123456.7" pattern="#,#00.00#"/>  // 123,456.70

<fmt:formatNumber value="12" type="percent" />   // 1,200% (type 可以是currency、 number、 和percent)。

用於解析數字的 <fmt:parseNumber> 標籤

<fmt:parseNumber> 標籤用於解析一個數字,並將結果作為 java.lang.Number 類的實例返回。 <fmt:parseNumber> 標籤看起來和 <fmt:formatNumber> 標籤的作用正好相反。
它的屬性和描述如下表所示:

屬性 描述
value 將被解析的字符串
type 解析格式化的類型
pattern 解析格式化模式
var 結果保存變量,類型為 java.lang.Number
scope 變量的作用範圍
parseLocale 以本地化的形式來解析字符串,該屬性的內容應為 String 或 java.util.Locale 類型的實例
下面看一個示例。
<fmt:parseNumber value="15%" type="percent" var="num"/>
解析之後的結果為「 0.15 」。

用於格式化日期的 <fmt:formatDate> 標籤

<fmt:formatDate> 標籤用於格式化日期。它的屬性和描述如下表所示:

屬性 描述
value 格式化的日期,該屬性的內容應該是 java.util.Date 類型的實例
type 格式化的類型
pattern 格式化模式
var 結果保存變量
scope 變量的作用範圍
timeZone 指定格式化日期的時區
<fmt:formatDate> 標籤與 <fmt:timeZone> 、 <fmt:setTimeZone> 兩組標籤的關係密切。若沒有指定 timeZone屬性, 也可以通過 <fmt:timeZone> 、 <fmt:setTimeZone> 兩組標籤設定的時區來格式化最後的結果。

用於解析日期的 <fmt:parseDate> 標籤

<fmt:parseDate> 標籤用於解析一個日期,並將結果作為 java.lang.Date 類型的實例返回。 <fmt:parseDate> 標籤看起來和 <fmt:formatDate> 標籤的作用正好相反。
它的屬性和描述如下表所示:

屬性 描述
value 將被解析的字符串
type 解析格式化的類型
pattern 解析格式化模式
var 結果保存變量,類型為 java.lang.Date
scope 變量的作用範圍
parseLocale 以本地化的形式來解析字符串,該屬性的內容為 String 或 java.util.Locale 類型的實例
timeZone 指定解析格式化日期的時區
<fmt:parseNumber> 和 <fmt:parseDate> 兩組標籤都實現解析字符串為一個具體對象實例的工作,因此,這兩組解析標籤對 var 屬性的字符串參數要求非常嚴格。就 JSP 頁面的表示層前段來說,處理這種解析本不屬於份內之事,因此 <fmt:parseNumber> 和 <fmt:parseDate> 兩組標籤應該儘量少用,替代工作的地方應該在服務器端表示層的後段,比如在 Servlet 中。

JSP 頁面透過JSTL格式標籤庫取得整數

在一般的JSTL頁面,若是以 EL 進行運算會取得有小數點的 Float 數值
例如 ${6/9} 這行EL會在JSP頁面中轉換成0.6666666666666666
在不寫Java程式碼於JSP頁面的前提下,我們可以考慮使用JSTL的格式標籤庫

使用時先引入JSTL的格式標籤庫:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

這樣就可以在JSP頁面中使用formatNumber標籤               
<fmt:formatNumber type="number" value="${requestScope.page / 10}" maxFractionDigits="0" var="num" />

maxFractionDigits指定成0,表示取0個小數點,也就是取整數的意思
這樣就能夠在網頁中用EL: ${var} 取得運算後的整數值

2010年10月11日 星期一

JavaScript 筆記(1)

JavaScript 藉由事件來觸發執行的客戶端指令稿
因為JavaScript已經被瀏覽器內建接納,所以可以看到HTML元素裡有不少JavaScript事件

1.每句JavaScript碼的結束都必須添加分號 ;

2.alert 會跳出對話方塊,confirm() 函式會跳出確認視窗
   prompt() 則是跳出請求輸入的視窗,型式是 var x = prompt("提示", "預設值");

3.onload 事件用在<body>標籤上會在網頁剛被載入完時執行,ex:<body onload="alert('Hi');"

4.自訂函式寫法: function xxx(){}
    如果需要函式回傳物件,在結尾加上程式碼:   return  要回傳的物件; 

5.所有的指令稿通常是將資料儲存於記憶體中
    JavaScript的資料型別有三種:Text、Number、Boolean
    Number實際表現為64bit的浮點數,等同Java的double型別
    寫javascript要注意變數或常數的設定,常數的值永不改變
    變數剛被建立的時候是沒有值的
    當我們賦予值給變數時,值會自動將資料型別指派給變數
    const幫助建立不會改變的常數值,另外建立常數時務必要初始化

6.JavaScript的命名方式大致與Java相同

7.parseInt() 與 parseFloat() 函式將文字轉換成數字,因為資料表單總是將欄位的值儲存為字串

8.Number 有個函式 toFixed(int i) 會將數值四捨五入到 i 指定的小數點位置

9.JavaScript中出現NaN表示某個預期應該是數值的資料,其值卻不是數值
   NaN不等於任何值,包刮NaN;isNaN() 函式用來判斷是否為空白或不為數值

10.Infinity值代表大於1.7976313486231570e+308的所有值

11.注意,網頁在onload事件後才載入
      如果JavaScript碼會取用網頁內的元件,那這段程式碼沒辦法在onload事件前執行

12.在自訂函式裡面傳入form 物件是處理表單的常見手法,如:function xx(form){...}
      傳入的form物件是陣列型式,能用欄位名稱作為key去讀取欄位的值
      而 form.submit() 函式會送出整個表單

13.建立陣列的方式是讓JavaScript建立陣列物件,如: var a = new Array();
      建立並初始化陣列內容:var a = ["0","1","2"];
      JavaScript陣列於單一場所儲存多段資料,資料型別可以是不同的(但不建議)
      新增元素到初始化完畢的Array在JavaScript是被允許的
      或者也可以呼叫Array物件的push() 方法新增
      取得陣列總元素的數量則是呼叫Array物件的length成員,如:a.length
      清除陣列內容的方式很簡單,a.length = 0;  像這樣把長度設為0就可以了

2010年10月3日 星期日

網頁符號對應

部分符號需要在撰寫HTML文件時使用HTML語法才能正常顯示
完整的資料可以在W3C找到,筆記紀錄較常見的符號

                符號                HTML語法
空白                                    &nbsp;
單引號        '                        &#39; (實體名稱是&apos;,但因IE不支援,所以用實體編號替代)
雙引號        "                        &quot;
連號           &                       &amp;
小於           <                       &lt;
大於           >                       &gt;
版權符號    ©                       &copy;
註冊商標    ®                       &reg;
勾選符號    Ö                       <font face=symbol>&Ouml;</font>
加減號        ±                       &plusmn;
乘號           ×                       &times;
除號           ÷                       &devide;
度               °                       &deg;