1 
  2 /**
  3  * @name	CeL function for Ajax
  4  * @fileoverview
  5  * 本檔案包含了 web Ajax 的 functions。
  6  * @since	
  7  */
  8 
  9 if (typeof CeL === 'function'){
 10 
 11 /**
 12  * 本 module 之 name(id),<span style="text-decoration:line-through;">不設定時會從呼叫時之 path 取得</span>。
 13  * @type	String
 14  * @constant
 15  * @inner
 16  * @ignore
 17  */
 18 var module_name = 'net.Ajax';
 19 
 20 //===================================================
 21 /**
 22  * 若欲 include 整個 module 時,需囊括之 code。
 23  * @type	Function
 24  * @param	{Function} library_namespace	namespace of library
 25  * @param	load_arguments	呼叫時之 argument(s)
 26  * @return
 27  * @name	CeL.net.Ajax
 28  * @constant
 29  * @inner
 30  * @ignore
 31  */
 32 var code_for_including = function(library_namespace, load_arguments) {
 33 
 34 //	requires
 35 if (eval(library_namespace.use_function(
 36 		'code.compatibility.is_DOM')))
 37 	return;
 38 
 39 
 40 /**
 41  * null module constructor
 42  * @class	web Ajax 的 functions
 43  */
 44 CeL.net.Ajax
 45 = function() {
 46 	//	null module constructor
 47 };
 48 
 49 /**
 50  * for JSDT: 有 prototype 才會將之當作 Class
 51  */
 52 CeL.net.Ajax
 53 .prototype = {
 54 };
 55 
 56 
 57 
 58 
 59 
 60 
 61 //	XMLHttp set	ajax通信処理ライブラリ	==================
 62 
 63 
 64 
 65 /*
 66 to use: include in front:
 67 way1(good: 以reg代替functionPath!):
 68 //	[function.js]_iF
 69 //	[function.js]End
 70 
 71 way2(old):
 72 //	[function.js]getU,functionPath,'eval(getU(functionPath));'
 73 //	[function.js]End
 74 
 75 old:
 76 function getU(p){var o;try{o=new ActiveXObject('Microsoft.XMLHTTP');}catch(e){o=new XMLHttpRequest();}if(o)with(o){open('GET',p,false),send(null);return responseText;}}
 77 */
 78 
 79 
 80 
 81 /*	JScript or .wsh only, 能 encode
 82 	http://neural.cs.nthu.edu.tw/jang/books/asp/getWebPage.asp?title=10-1%20%E6%8A%93%E5%8F%96%E7%B6%B2%E9%A0%81%E8%B3%87%E6%96%99
 83 */
 84 function getPage(p,enc,t){	//	page url, encode, POST text
 85 try{
 86  var X=new ActiveXObject('Microsoft.XMLHTTP'),AS;	//	may error
 87  X.open(t?'POST':'GET',p,false);
 88  X.setRequestHeader("Content-Type","application/x-www-form-urlencoded");	//	POST need this
 89  X.send(t||null);	//	Download the file
 90  with(AS=new ActiveXObject("ADODB.Stream")){
 91   Mode=3,	//	可同時進行讀寫
 92   Type=1,	//	以二進位方式操作
 93   Open(),	//	開啟物件
 94   Write(X.responseBody),	//	將 binary 的資料寫入物件內	may error
 95   Position=0,
 96   Type=2;	//	以文字模式操作
 97   if(enc)Charset=enc;	//	設定編碼方式
 98   X=ReadText();	//	將物件內的文字讀出
 99  }
100  AS=0;//AS=null;	//	free
101  return X;
102 }catch(e){
103  //sl('getPage: '+e.message);
104 }}
105 
106 
107 
108 /*	set a new XMLHttp
109 	Ajax程式應該考慮到server沒有回應時之處置
110 
111 return new XMLHttpRequest(for Ajax, Asynchronous JavaScript and XML) controller
112 	http://www.xulplanet.com/references/objref/XMLHttpRequest.html
113 	http://zh.wikipedia.org/wiki/AJAX
114 	http://jpspan.sourceforge.net/wiki/doku.php?id=javascript:xmlhttprequest:behaviour
115 	http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/
116 	http://developer.apple.com/internet/webcontent/xmlhttpreq.html
117 	http://www.klstudio.com/catalog.asp?cate=4
118 	http://wiki.moztw.org/index.php/AJAX_%E4%B8%8A%E6%89%8B%E7%AF%87
119 	http://www.15seconds.com/issue/991125.htm
120 	http://www.xmlhttp.cn/manual/xmlhttprequest.members.html
121 	http://www.blogjava.net/eamoi/archive/2005/10/31/17489.html
122 	http://www.kawa.net/works/js/jkl/parsexml.html
123 	http://www.twilightuniverse.com/
124 
125 	XMLHttp.readyState 所有可能的值如下:
126 	0 還沒開始
127 	1 讀取中 Sending Data
128 	2 已讀取 Data Sent
129 	3 資訊交換中 interactive: getting data
130 	4 一切完成 Completed
131 
132 	XMLHttp.responseText	會把傳回值當字串用
133 	XMLHttp.responseXML	會把傳回值視為 XMLDocument 物件,而後可用 JavaScript DOM 相關函式處理
134 	IE only(?):
135 	XMLHttp.responseBody	以unsigned array格式表示binary data
136 				try{responseBody=(new VBArray(XMLHttp.responseBody)).toArray();}catch(e){}
137 				http://aspdotnet.cnblogs.com/archive/2005/11/30/287481.html
138 	XMLHttp.responseStream	return AdoStream
139 */
140 function newXMLHttp(enc,isText){
141  //if(typeof XMLHttp=='object')XMLHttp=null;
142  var _new_obj_XMLHttp;
143  if(typeof newXMLHttp.objId=='string')_new_obj_XMLHttp=new ActiveXObject(newXMLHttp.objId);	//	speedy
144  //	jQuery: Microsoft failed to properly implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available.
145  else if(typeof ActiveXObject!='undefined')for(var i=0,a=['Msxml2.XMLHTTP','Microsoft.XMLHTTP','Msxml2.XMLHTTP.4.0'];i<a.length;i++)
146   try{_new_obj_XMLHttp=new ActiveXObject(a[i]);newXMLHttp.objId=a[i];break;}catch(e){}//'Msxml2.XMLHTTP.6.0','Msxml2.XMLHTTP.5.0','Msxml2.XMLHTTP.4.0','Msxml2.XMLHTTP.3.0',["MSXML2", "Microsoft", "MSXML"].['XMLHTTP','DOMDocument'][".6.0", ".4.0", ".3.0", ""]
147   //	或直接設定:	XMLHttpRequest=function(){return new ActiveXObject(newXMLHttp.objId);}
148  //	皆無:use XMLDocument. The document.all().XMLDocument is a Microsoft IE subset of JavaScript.	http://www.bindows.net/	http://www.java2s.com/Code/JavaScriptReference/Javascript-Properties/XMLDocument.htm
149  else if(typeof window=='object'&&window.XMLHttpRequest/* && !window.ActiveXObject*/){//typeof XMLHttpRequest!='undefined'
150   _new_obj_XMLHttp=new XMLHttpRequest();
151   //	有些版本的 Mozilla 瀏覽器在伺服器送回的資料未含 XML mime-type 檔頭(header)時會出錯。為了避免這個問題,你可以用下列方法覆寫伺服器傳回的檔頭,以免傳回的不是 text/xml。
152   //	http://squio.nl/blog/2006/06/27/xmlhttprequest-and-character-encoding/
153   //	http://www.w3.org/TR/XMLHttpRequest/	search encoding
154   if(_new_obj_XMLHttp.overrideMimeType)
155    _new_obj_XMLHttp.overrideMimeType('text/'+(isText?'plain':'xml')+(enc?'; charset='+enc:''));//oXML
156  }
157  return _new_obj_XMLHttp;
158 }
159 
160 /*	讀取URL by XMLHttpRequest
161 	http://jck11.pixnet.net/blog/post/11630232
162 
163 * 若有多行程或為各URL設定個別XMLHttp之必要,請在一開始便設定getURL.multi_request,並且別再更改。
164 ** 在此情況下,單一URL仍只能有單一個request!
165 ** 設定 dealFunction 須注意程式在等待回應時若無執行其他程式碼將自動中止!
166 	可設定:
167 	while(getURL.doing)WScript.Sleep(1);	//||timeout
168 
169 arguments f:{
170 	URL:'',	//	The same origin policy prevents document or script loaded from one origin, from getting or setting properties from a of a document from a different origin.(http://www.mozilla.org/projects/security/components/jssec.html#sameorigin)
171 	enc:'UTF-8',	//	encoding: big5, euc-jp,..
172 	fn:(dealFunction),	//	onLoad:function(){},
173 	method:'GET',	//	POST,..
174 	sendDoc:'text send in POST,..'
175 	async:ture/false,	//	true if want to asynchronous(非同期), false if synchronous(同期的,會直到readyState==4才return)	http://jpspan.sourceforge.net/wiki/doku.php?id=javascript:xmlhttprequest:behaviour
176 	user:'userName',
177 	passwd:'****',	//	password
178 
179  //TODO:
180 	parameters:'~=~&~=~', // {a:1,b:2}
181 	header:{contentType:'text/xml'},
182 	contentType:'text/xml',
183 	run:true/false,	//	do eval
184 	update:DOMDocument,	//	use onLoad/onFailed to 加工 return text. onFailed(){throw;} will about change.
185 	interval:\d,
186 	decay:\d,	//	wait decay*interval when no change
187 	maxInterval::\d,
188 	//insertion:top/bottom,..
189 	onFailed:function(error){this.status;},	//	onFailed.apply(XMLHttp,[XMLHttp.status])
190 	onStateChange:function(){},
191  }
192 
193 
194 dealFunction:
195 自行處理	typeof dealFunction=='function':
196 function dealFunction(error){..}
197 代為處理	dealFunction=[d_func,0: responseText,1: responseXML]:
198 	responseXML:	http://msdn2.microsoft.com/en-us/library/ms757878.aspx
199 function d_func(content,head[,XMLHttp,URL]){
200  if(head){
201   //	content,head各為XMLHttp.responseText內容及XMLHttp.getAllResponseHeaders(),其他皆可由XMLHttp取得。
202  }else{
203   //	content為error
204  }
205 }
206 e.g., the simplest: [function(c,h){h&&alert(c);}]
207 
208 )
209 */
210 getURL[generateCode.dLK]='newXMLHttp';
211 function getURL(f){	//	(URL,fn) or flag			URL,dealFunction,method,sendDoc,asyncFlag,userName,password
212  var _f=arguments.callee;
213  if(typeof _f.XMLHttp=='object'){
214   //try{_f.XMLHttp.abort();}catch(e){}
215   _f.XMLHttp=null;	//	此時可能衝突或lose?!
216  }
217  //	處理 arguments
218  if(!(f instanceof Object))a=arguments,f={URL:f,fn:a[1],method:a[2],sendDoc:a[3]};
219 
220  if(!f.URL||!(_f.XMLHttp=newXMLHttp(f.enc,!/\.x(ht)?ml$/i.test(f.URL))))return;//throw
221  //try{_f.XMLHttp.overrideMimeType('text/xml');}catch(e){}
222  if(typeof f.async!='boolean')
223   //	設定f.async
224   f.async=f.fn?true:false;
225  else if(!f.async)f.fn=null;
226  else if(!f.fn)
227   if(typeof _f.HandleStateChange!='function'||typeof _f.HandleContent!='function')
228    // 沒有能處理的function
229    return;//throw
230   else
231    f.fn=_f.HandleContent;//null;
232  if(/*typeof _f.multi_request!='undefined'&&*/_f.multi_request){
233   if(!_f.q)_f.i={},_f.q=[];	//	queue
234   _f.i[f.URL]=_f.q.length;	//	** 沒有考慮到 POST 時 URL 相同的情況!
235   _f.q.push({uri:f.URL,XMLHttp:_f.XMLHttp,func:f.fn,start:_f.startTime=new Date})
236  }else if(_f.q&&typeof _f.clean=='function')_f.clean();
237 
238  //	for Gecko Error: uncaught exception: Permission denied to call method XMLHttpRequest.open
239  if(f.URL.indexOf('://')!=-1&&typeof netscape=='object')
240   if(_f.asked>2){_f.clean(f.URL);return;}
241   else try{
242    if(typeof _f.asked=='undefined')
243     _f.asked=0,alert('我們需要一點權限來使用 XMLHttpRequest.open。\n* 請勾選記住這項設定的方格。');
244    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
245   }catch(e){_f.asked++;_f.clean(f.URL);return;}//UniversalBrowserAccess
246 
247  //if(isNaN(_f.timeout))_f.timeout=300000;//5*60*1000;
248  with(_f.XMLHttp)try{	//	IE:404會throw error, timeout除了throw error, 還會readystatechange; Gecko亦會throw error
249   try{setRequestHeader("Accept-Encoding","gzip,deflate");}catch(e){}
250   //	Set header so the called script knows that it's an XMLHttpRequest
251   //setRequestHeader("X-Requested-With","XMLHttpRequest");
252   //	Set the If-Modified-Since header, if ifModified mode.
253   //setRequestHeader("If-Modified-Since","Thu, 01 Jan 1970 00:00:00 GMT");
254   if(f.method=='POST'){//&&_f.XMLHttp.setRequestHeader
255    //setRequestHeader("Content-Length",f.sendDoc.length);	//	use .getAttribute('method') to get	長度不一定如此
256    //	有些CGI會用Content-Type測試是XMLHttp或是regular form
257    //	It may be necessary to specify "application/x-www-form-urlencoded" or "multipart/form-data" for posted XML data to be interpreted on the server.
258    setRequestHeader('Content-Type',f.fn instanceof Array&&f.fn[1]?'text/xml':'application/x-www-form-urlencoded');	//	application/x-www-form-urlencoded;charset=utf-8
259   }
260   abort();
261   open(f.method||'GET',f.URL,f.async,f.user||null,f.passwd||null);
262   //alert((f.method||'GET')+','+f.URL+','+f.async);
263   //	 根據 W3C的 XMLHttpRequest 規格書上說,①在呼叫 open 時,如果readyState是4(Loaded) ②呼叫abort之後 ③發生其他錯誤,如網路問題,無窮迴圈等等,則會重設所有的值。使用全域的情況就只有第一次可以執行,因為之後的readyState是4,所以onreadystatechange 放在open之前會被清空,因此,onreadystatechange 必須放在open之後就可以避免這個問題。	http://www.javaworld.com.tw/jute/post/view?bid=49&id=170177&sty=3&age=0&tpg=1&ppg=1
264   //	每使用一次XMLHttpRequest,不管成功或失敗,都要重設onreadystatechange一次。onreadystatechange 的初始值是 null
265   //	After the initial response, all event listeners will be cleared. Call open() before setting new event listeners.	http://www.xulplanet.com/references/objref/XMLHttpRequest.html
266   if(f.async)
267 	_f.doing=(_f.doing||0)+1,
268 	onreadystatechange=typeof f.fn=='function'?f.fn:function(e){_f.HandleStateChange(e,f.URL,f.fn);},//||null
269 	//	應加 clearTimeout( )
270 	setTimeout('try{getURL.'+(_f.multi_request?'q['+_f.i[f.URL]+']':'XMLHttp')+'.onreadystatechange();}catch(e){}',_f.timeout||3e5);//5*60*1000;
271   send(f.sendDoc||null);
272   if(!f.fn)return responseText;//responseXML: responseXML.loadXML(text)	//	非async(異步的)能在此就得到response。Safari and Konqueror cannot understand the encoding of text files!	http://www.kawa.net/works/js/jkl/parsexml.html
273  }catch(e){if(typeof f.fn=='function')f.fn(e);else if(typeof window=='object')window.status=e.message;return e;}
274 }
275 getURL.timeoutCode=-7732147;
276 
277 //	agent handle function
278 getURL.HandleStateChange=function(e,URL,dealFunction){	//	e: object Error, dealFunction: function(return text, heads, XMLHttpRequest object, URL) | [ function, (default|NULL:responseText, others:responseXML) ]
279  var _t=0,isOKc,m=getURL.multi_request,_oXMLH;
280  if(m)m=getURL.q[isNaN(URL)?getURL.i[URL]:URL],_oXMLH=m.XMLHttp,dealFunction=m.func,URL=m.uri;else _oXMLH=getURL.XMLHttp;
281  if(dealFunction instanceof Array)_t=dealFunction[1],dealFunction=dealFunction[0];
282  if(!dealFunction || typeof dealFunction!='function'){getURL.doing--;getURL.clean(URL);return;}
283  //	http://big5.chinaz.com:88/book.chinaz.com/others/web/web/xml/index1/21.htm
284  if(!e)
285   if(typeof _oXMLH=='object'&&_oXMLH){
286    if(_oXMLH.parseError&&_oXMLH/*.responseXML*/.parseError.errorCode!=0)
287     e=_oXMLH.parseError,e=new Error(e.errorCode,e.reason);
288    else if(_oXMLH.readyState==4){	//	only if XMLHttp shows "loaded"
289     isOKc=_oXMLH.status;	//	condition is OK?
290     isOKc=isOKc>=200&&isOKc<300||isOKc==304||!isOKc&&(location.protocol=="file:"||location.protocol=="chrome:");
291     if(dealFunction==getURL.HandleContent)dealFunction(0,isOKc,_oXMLH,URL);//dealFunction.apply()
292     else dealFunction(
293 	isOKc?_t?_oXMLH.responseXML:
294 		//	JKL.ParseXML: Safari and Konqueror cannot understand the encoding of text files.
295 		typeof window=='object'&&window.navigator.appVersion.indexOf("KHTML")!=-1&&!(e=escape(_oXMLH.responseText)).indexOf("%u")!=-1?e:_oXMLH.responseText
296 	:0
297 	,isOKc?_oXMLH.getAllResponseHeaders():0,_oXMLH,URL);//dealFunction.apply()
298     //	URL之protocol==file: 可能需要重新.loadXML((.responseText+'').replace(/<\?xml[^?]*\?>/,""))
299     //	用 .responseXML.documentElement 可調用
300     getURL.doing--;getURL.clean(URL);
301     return;
302    }
303   }else if(new Date-(m?m.start:getURL.startTime)>getURL.timeout)
304    //	timeout & timeout function	http://www.stylusstudio.com/xmldev/199912/post40380.html
305    e=new Error(getURL.timeoutCode,'Timeout!');//_oXMLH.abort();
306  //alert(URL+'\n'+_t+'\n'+e+'\n'+_oXMLH.readyState+'\n'+dealFunction);
307  if(e){dealFunction(e,0,_oXMLH,URL);getURL.doing--;getURL.clean(URL);}//dealFunction.apply(e,URL);
308 };
309 
310 /*	agent content handle function
311 有head時content包含回應,否則content表error
312 */
313 getURL.HandleContent=function(content,head,_oXMLHttp,URL){
314  if(head){
315   // _oXMLHttp.getResponseHeader("Content-Length")
316   alert("URL:	"+URL+"\nHead:\n"+_oXMLHttp.getAllResponseHeaders()+"\n------------------------\nLastModified: "+_oXMLHttp.getResponseHeader("Last-Modified")+"\nResult:\n"+_oXMLHttp.responseText.slice(0,200));//_oXMLHttp.responseXML.xml
317  }else{
318   //	error	test時,可用getURL.XMLHttp.open("HEAD","_URL_",true);,getURL(url,dealResult,'HEAD',true)。
319   if(content instanceof Error)alert('Error occured!\n'+(typeof e=='object'&&e.number?e.number+':'+e.message:e||''));
320   else if(typeof _oXMLHttp=='object'&&_oXMLHttp)alert((_oXMLHttp.status==404?"URL doesn't exist!":'Error occured!')+'\n\nStatus: '+_oXMLHttp.status+'\n'+_oXMLHttp.statusText);
321  }
322 };
323 
324 //	在MP模式下清乾淨queue
325 getURL.clean=function(i,force){
326  if(force||getURL.multi_request)
327   if(!i&&isNaN(i)){
328    if(getURL.q)
329     for(i in getURL.i)
330      try{
331       getURL.q[getURL.i[i]].XMLHttp.abort();
332       //getURL.q[getURL.i[i]].XMLHttp=null;
333      }catch(e){}
334    getURL.q=getURL.i=0;//null
335   }else if(!isNaN(i)||!isNaN(i=getURL.i[typeof i=='object'?i.uri:i])){
336    try{getURL.q[i].XMLHttp.abort();}catch(e){};
337    //getURL.q[i].XMLHttp=0;
338    delete getURL.i[getURL.q[i].uri];getURL.q[i]=0;
339   }
340 };
341 
342 //	↑XMLHttp set	==================
343 
344 
345 
346 
347 
348 
349 return (
350 	CeL.net.Ajax
351 );
352 };
353 
354 //===================================================
355 
356 CeL.setup_module(module_name, code_for_including);
357 
358 };
359