Yahoo! UI Library: Connection Manager

Yahoo!最近放出了他的UI Library(以後簡稱YUI),一開始我還沒特別在意,直到看了Forget addEvent, use Yahoo!’s Event Utility,才覺得好像很方便用,而且甚麼瀏覽器間的問題都處理好了,真是好XD。所以最近寫的東西就拿來用了,現在已經研究了Connection ManagerEvent,其中Event的部份已經有Forget addEvent, use Yahoo!’s Event Utility這篇文章介紹了,所以這篇先介紹Connection Manager吧。

其實,Connection Manager就是Ajax技術用到的XMLHttpRequest的library。IE不支援XMLHttpRequest,他是用ActiveX來達到HttpRequest的功能(不過最早可以做到這件事的也是IE),當然程式碼也會不一樣,YUI的Connection Manager就可以迴避掉這個問題,以下大部分範例都是用YUI的文件的範例。

首先要使用YUI先要把程式碼include進來,檔案在官方網頁有得抓:

<!-- Namespace source file -->
<script src = "http://yourwebsite.com/util/YAHOO.js" ></script>

<!-- Connection Manager source file -->
<script src = "http://yourwebsite.com/util/connection.js" ></script>

其中第一個YAHOO.js是不管哪一個library都需要的,不過也只需要include一次,如果有同時用到兩個以上的YUI,記得YAHOO.js只需要一次喔。接下來我們就可以建立連線做出HttpRequest了:

var cObj = YAHOO.util.Connect.asyncRequest('GET','http://www.yahoo.com',callback,null);

這樣就做出連線了,這邊要稍微解釋一下asyncRequest裡面的幾個參數,基本上就是如上所示的四個:

  1. 就是傳資料的method,就只有GET和POST可用,不過我還不會用POST。
  2. 是RequestUri,如果使用GET method,要傳遞的資料就要字幾家在網址後面。
  3. 則是伺服器回傳後負責處理的function。
  4. 最後則是使用POST method時要送出的資料,我不會用POST就是因為這裡看不懂,似乎是需要用實際的HTML表單來作傳出的資料,而不能自己用javascript產生,有時間測試再說。

如果只是要偷偷上傳資料,那這樣就可以了,不過Ajax的精華在於背後傳遞資料的互動模式,所以伺服器回傳後的動作一定是要的,因此接下來要介紹callback這個function的形式。

到這我要改口了,callback(名稱可以自取)其實是個物件,裡面至少要指定成功回傳和失敗時負責處理的兩個function,另外還有兩個屬性,argument、scope:長相如下:

var responseSuccess = function(o){ //transaction success case logic }
var responseFailure = function(o){ //transaction failure case logic }

var callback =
{
    success:responseSuccess,
    failure:responseFailure,
    argument: arguments ,
    scope: this
}

argument用途不明,似乎不論是成功還是失敗function都會收到的樣子,可以不加,scope只有在function要用到this的時候需要。至於一開始的兩個則是一定要的。一開始定義functiong時的function(o)裡面的o就是代表回傳的物件,如果成功,裡面會包含回傳的網頁內容,可能是XML或是string,不過為了有效利用當然是要回傳XML啦。如果是失敗的狀況,則會包含相關錯誤訊息。至於XML的資料使用方法當然就是DOM了,以上面的function為例,回傳的XML文件就是o.responseXML,可以直接對他套用DOM的function。以下提供一個我前兩天寫的回傳成功的處理function給各位做參考:

var updateS = function (o) {
    var strDocument = o.responseText; 
    var xmlDocument = o.responseXML;
    if(!xmlDocument || xmlDocument.childNodes.length==0) {
           xmlDocument = (new DOMParser()).parseFromString(strDocument, "text/xml");
    }
    sselect = document.createElement("select");
    sselect.name = "s";
    sselect.id = "s";
    YAHOO.util.Event.addListener(sselect, "change", getList, 's');
    YAHOO.util.Event.addListener(sselect, "keydown", getList, 's');
    var options = xmlDocument.getElementsByTagName('option');
	soption = document.createElement("option");
	soption.value = "-1";
	soption.id = "fb";
	text = document.createTextNode("學校");
	soption.appendChild(text);
	sselect.appendChild(soption);
	for (i = 0; i < options.length; i++) {
		soption = document.createElement("option");
		soption.value = options[i].getAttribute('value');
		text = document.createTextNode(options[i].firstChild.nodeValue);
		soption.appendChild(text);
		sselect.appendChild(soption);
	}
	remove(null, 's');
	remove(null, 'b');
	document.getElementById('form').insertBefore(sselect, document.getElementById('sub'));
}
不過這個function有另外用到別的function IE可能不支援,所以還有如下的code:
if (typeof DOMParser == "undefined") { DOMParser = function (){}
  DOMParser.prototype.parseFromString = function (str, contentType) {
    if (typeof ActiveXObject != "undefined") { 
      var d = new ActiveXObject("MSXML.DomDocument"); 
      d.loadXML(str); 
      return d; 
    } 
    else if (typeof XMLHttpRequest != "undefined") {
      var req = new XMLHttpRequest; 
      req.open("GET", "data:" + (contentType || "application/xml") +  
                                 ";charset=Big-5," + encodeURIComponent(str), false); 
      if (req.overrideMimeType) { 
        req.overrideMimeType(contentType); 
      } 
      req.send(null); 
      return req.responseXML; 
    } 
  } 
}
如果大家發現IE不能正常的取得回傳的XML的話,可以參考我的作法,上面這段code也是找來的,出處會再補上。