1 
  2 /**
  3  * @name	CeL function for HTA
  4  * @fileoverview
  5  * 本檔案包含了 web HTA 的 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.HTA';
 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.HTA
 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 HTA 的 functions
 43  */
 44 CeL.net.HTA
 45 = function() {
 46 	//	null module constructor
 47 };
 48 
 49 /**
 50  * for JSDT: 有 prototype 才會將之當作 Class
 51  */
 52 CeL.net.HTA
 53 .prototype = {
 54 };
 55 
 56 
 57 
 58 /*	
 59 TODO:
 60 JavaScript closure and IE 4-6 memory leak
 61 Mozilla ActiveX Project	http://www.iol.ie/%7Elocka/mozilla/mozilla.htm
 62 IE臨時文件的位置可以從註冊表鍵值 HKLM\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Cache\paths\Directory 中讀取。
 63 */
 64 
 65 CeL.net.HTA
 66 .
 67 /**
 68  * Internet Explorer Automation tool
 69  * @param {String} [URL]	initial URL
 70  * @returns {IEA}
 71  * @memberOf	CeL.net.HTA
 72  */
 73 IEA = function (URL) {
 74 
 75 	try {
 76 /*	COM objects
 77 WScript.CreateObject("InternetExplorer.Application","Event_");
 78 new ActiveXObject(class[, servername]);
 79 
 80 http://www.cnblogs.com/xdotnet/archive/2007/04/09/javascript_object_activexobject.html
 81 var obj=new ActiveXObject(servername,typename[,location]);
 82 servername提供該對象的應用程序名稱;
 83 typename要創建的對象地類型或類;
 84 location創建該對象得網絡服務器名稱。
 85 */
 86 		this.app = new ActiveXObject("InternetExplorer.Application");
 87 	} catch (e) {
 88 		// TODO
 89 		//return;
 90 	}
 91 	if (!this.app)
 92 		return;
 93 
 94 	//	要先瀏覽了網頁,才能實行IEApp.Document其他功能。
 95 	this.go(URL || '');
 96 
 97 	return this;
 98 
 99 /*	other functions
100 http://msdn2.microsoft.com/en-us/library/aa752085.aspx
101 http://msdn2.microsoft.com/en-us/library/Aa752084.aspx
102 IEApp.Visible=true;
103 IEApp.Offline=true;
104 IEApp.Document.frames.prompt();
105 */
106 };
107 
108 /**
109  * get <frame>
110  * @param document_object	document object
111  * @param name	frame name
112  * @returns
113  */
114 _.IEA.frame = function(document_object, name) {
115 	try {
116 		document_object = document_object.getElementsByTagName('frame');
117 		return name ? document_object[name].contentWindow.document : document_object;
118 	} catch (e) {
119 		// TODO
120 	}
121 };
122 
123 _.IEA.prototype = {
124 	/**
125 	 * 本 IEA 之 status 是否 OK.
126 	 * 以有無視窗,否則以有無內容判別OK 關掉視窗時, typeof this.app.Visible=='unknown'
127 	 * @param w	window object
128 	 * @returns
129 	 */
130 	OK : function(w) {
131 		try {
132 			if (w ? typeof this.app.Visible == 'boolean'
133 					: this.doc().body.innerHTML)
134 				return this.app;
135 		} catch (e) {
136 		}
137 	},
138 	autoSetBase : true,
139 	baseD : '',
140 	baseP : '',
141 	//initP : 'about:blank',
142 	timeout : 3e4, // ms>0
143 	setBase : function(URL) {
144 		var m = (URL || '').match(/^([\w\d\-]+:\/\/[^\/]+)(.*?)$/);
145 		if (m)
146 			this.baseD = m[1], this.baseP = m[2].slice(0,
147 					m[2].lastIndexOf('/') + 1);
148 		//WScript.Echo('IEA.setBase:\ndomin: '+this.baseD+'\npath: '+this.baseP);
149 		return this.baseD;
150 	},
151 	/**
152 	 * go to URL
153 	 * @param URL	URL or history num
154 	 * @returns
155 	 */
156 	go : function(URL) {
157 		var _t = this;
158 		try {
159 			if (URL === '' || isNaN(URL)) {
160 				if (URL === '')
161 					URL = 'about:blank';// _t.initP;
162 				if (URL) {
163 					if (URL.indexOf(':') == -1)// if(URL.indexOf('://')==-1&&URL.indexOf('about:')==-1)
164 						URL = _t.baseD + (URL.charAt(0) == '/' ? '' : _t.baseP)
165 								+ URL;
166 
167 					//	IEApp.Document.frames.open(URL);	**	請注意:這裡偶爾會造成script停滯,並跳出警告視窗!
168 					_t.app.Navigate(URL);
169 
170 					if (_t.autoSetBase)
171 						_t.setBase(URL);
172 					_t.wait();
173 
174 					//	防止自動關閉
175 					//_t.win().onclose=function(){return false;};//_t.win().close=null;
176 				}
177 			} else
178 				_t.win().history.go(URL), _t.wait();
179 
180 		} catch (e) {
181 		}
182 		eName = 0;
183 		return _t;
184 	},
185 /*	完全載入
186 TODO:
187 http://javascript.nwbox.com/IEContentLoaded/
188 try{document.documentElement.doScroll('left');}
189 catch(e){setTimeout(arguments.callee, 50);return;}
190 instead of onload
191 */
192 	waitStamp : 0,
193 	waitInterval : 200, // ms
194 	waitState : 3, // 1-4: READYSTATE_COMPLETE=4 usual set to interactive=3
195 	wait : function(w) {
196 		if (!w && !(w = this.waitState) || this.waitStamp)
197 			return; // !!this.waitStamp: wait中
198 		this.waitStamp = new Date;
199 		try {
200 			// 可能中途被關掉
201 			while (new Date - this.waitStamp < this.timeout
202 					&& (!this.OK(1) || this.app.busy || this.app.readyState < w))
203 				try {
204 					// Win98的JScript沒有WScript.Sleep
205 					WScript.Sleep(this.waitInterval);
206 				} catch (e) {
207 				}
208 		} catch (e) {
209 		}
210 		w = new Date - this.waitStamp, this.waitStamp = 0;
211 		return w;
212 	},
213 	quit : function() {
214 		try {
215 			this.app.Quit();
216 		} catch (e) {
217 		}
218 		this.app = null;
219 		if (typeof CollectGarbage == 'function')
220 			//	CollectGarbage(): undocumented IE javascript method: 先置為 null 再 CollectGarbage(); 設置為null,它會斷開對象的引用,但是IE為了節省資源(經常釋放內存也會佔系統資源),因此採用的是延遲釋放策略,你調用CollectGarbage函數,就會強制立即釋放。
221 			//	http://www.cnblogs.com/stupidliao/articles/797659.html
222 			setTimeout(function() {
223 				CollectGarbage();
224 			}, 0);
225 		return;
226 	},
227 	// 用IE.doc().title or IE.app.LocationName 可反映狀況
228 	doc : function() {
229 		try {
230 			return this.app.document;
231 		} catch (e) {
232 		}
233 	},
234 	href : function() {
235 		try {
236 			return this.app.LocationURL;
237 		} catch (e) {
238 		}
239 	},
240 	win : function() {
241 		try {
242 			return this.doc().parentWindow;
243 		} catch (e) {
244 		}
245 	},
246 /*
247 reload:function(){
248  try{IE.win().history.go(0);IE.wait();}catch(e){}
249 },
250 */
251 	/**
252 	 * get element
253 	 * @param e
254 	 * @param o
255 	 * @returns
256 	 */
257 	getE : function(e, o) {
258 		try {
259 			return (o || this.doc()).getElementById(e);
260 		} catch (e) {
261 		}
262 	},
263 	/**
264 	 * get tag
265 	 * @param e
266 	 * @param o
267 	 * @returns
268 	 */
269 	getT : function(e, o) {
270 		try {
271 			return (o || this.doc()).getElementsByTagName(e);
272 		} catch (e) {
273 		}
274 	},
275 	// name/id, HTML object to get frame, return document object or not
276 	// .getElementsByName()
277 	// http://www.w3school.com.cn/htmldom/met_doc_getelementsbyname.asp
278 	frame : function(n, f, d) {
279 		try {
280 			f = f ? f.getElementsByTagName('frame') : this.getT('frame');
281 			if (isNaN(n))
282 				if (!n)
283 					return f;
284 				else
285 					for ( var i = 0; i < f.length; i++)
286 						if (f[i].name == n) {
287 							n = i;
288 							break;
289 						}
290 			if (!isNaN(n))
291 				return d ? f[n].contentWindow.document : f[n];
292 		} catch (e) {
293 		}
294 	},
295 	//	IE.frames()['*']	IEApp.document.frames
296 	//	Cross Site AJAX	http://blog.joycode.com/saucer/archive/2006/10/03/84572.aspx
297 	//	Cross-Site XMLHttpRequest	http://ejohn.org/blog/cross-site-xmlhttprequest/
298 	frames : function() {
299 		try {
300 			var i = 0, f = this.getT('frame'), r = [];
301 			for (r['*'] = []; i < f.length; i++)
302 				r['*'].push(f(i).name), r[f(i).name] = r[i] = f(i);
303 			// use frame.window, frame.document
304 			return r;
305 		} catch (e) {
306 		}
307 	},
308 	// form name array
309 	// formNA : 0,
310 	//	return name&id object. 設置這個還可以強制 do submit 使用 name 為主,不用 id。
311 	fillForm_rtE : 0,
312 	/**
313 	 * 填充 form
314 	 * @param parameter	parameter={id/name:value}
315 	 * @param submit_id	do submit(num) 或 button id
316 	 * @param form_index	submit 之 form index 或 id
317 	 * @returns
318 	 */
319 	fillForm : function(parameter, submit_id, form_index) {
320 		try {
321 			var i, j, n = {}, h = 0, f = this.doc().forms[form_index || 0] || {}, t,
322 			// g=f.getElementById,
323 			s = function(
324 					o, v) {
325 				t = o.tagName.toLowerCase();
326 				if (t == 'select')
327 					if (isNaN(v) || v < 0 || v >= o.options.length)
328 						o.value = v;
329 					else
330 						//	.options[i].value==v
331 						//	.selectedIndex= 的設定有些情況下會失效
332 						o.selectedIndex = v; 
333 				// 參考 cookieForm
334 				else if (t == 'input') {
335 					t = o.type.toLowerCase(); // .getAttribute('type')
336 					if (t == 'checkbox')
337 						o.checked = v;
338 					else if (t != 'radio')
339 						o.value = v;
340 					else if (o.value == v)
341 						o.checked = true;
342 					else
343 						return true; // return true: 需要再處理
344 				} else if (t == 'textarea')
345 					o.value = v;
346 			};
347 			/*	needless
348 			  if(!f){
349 			   f=this.getT('form');
350 			   for(i in f)if(f[i].name==fi){f=a[i];break;}
351 			  }
352 			  if(!f)f={};
353 			*/
354 			for (j in parameter)
355 				if (!(i = /* f.getElementById?f.getElementById(j): */this
356 						.getE(j))
357 						|| s(i, parameter[j]))
358 					n[j] = 1, h = 1;
359 			if ((h || this.fillForm_rtE)
360 					&& (i = f.getElementsByTagName ? f
361 							.getElementsByTagName('input') : this.getT('input')))
362 				for (j = 0; j < i.length; j++)
363 					if (i[j].name in n)
364 						s(i[j], parameter[i[j].name]);
365 					else if (submit_id && typeof submit_id != 'object' && submit_id == i[j].name)
366 						submit_id = i[j];
367 			// if(i[j].name in pm)s(i[j],pm[i[j].name]);
368 			if (submit_id) {
369 				if (i = typeof submit_id == 'object' ? submit_id
370 						: /* f.getElementById&&f.getElementById(l)|| */
371 							this.getE(submit_id))
372 					i.click();
373 				else
374 					f.submit();
375 				this.wait();
376 			} else if (this.fillForm_rtE) {
377 				h = {
378 					'' : i
379 				};
380 				for (j = 0; j < i.length; j++)
381 					if (i[j].name)
382 						h[i[j].name] = i[j];
383 				return h;
384 			}
385 		} catch (e) {
386 		}
387 		return this;
388 	},
389 	setLoc : function(w, h, l, t) {
390 		try {
391 			var s = this.win().screen;
392 			with (this.app) {
393 				if (w) {
394 					Width = w;
395 					if (typeof l == 'undefined')
396 						l = (s.availWidth - w) / 2;
397 				}
398 				if (h) {
399 					Height = h;
400 					if (typeof t == 'undefined')
401 						t = (s.availHeight - h) / 2;
402 				}
403 				if (l)
404 					Left = l;
405 				if (t)
406 					Top = t;
407 			}
408 		} catch (e) {
409 		}
410 		return this;
411 	},
412 	write : function(h) {
413 		try {
414 			if (!this.doc())
415 				this.go('');
416 			with (this.doc())
417 				open(), write(h || ''), close();
418 		} catch (e) {
419 		}
420 		return this;
421 	},
422 	//	使之成為 dialog 形式的視窗
423 	//	http://members.cox.net/tglbatch/wsh/
424 	setDialog : function(w, h, l, t, H) {
425 		try {
426 			with (this.app)
427 				FullScreen = true, ToolBar = false, StatusBar = false;
428 		} catch (e) {
429 		}
430 		this.setLoc(w, h, l, t);
431 		if (H)
432 			this.write(H).focus();
433 		try {
434 			//	太早設定 scroll 沒用。
435 			with (this.doc().body)
436 				scroll = 'no', style.borderStyle = 'outset',
437 						style.borderWidth = '3px';
438 		} catch (e) {
439 		}
440 		return this;
441 	},
442 	show : function(s) {
443 		try {
444 			this.app.Visible = s || typeof s == 'undefined';
445 		} catch (e) {
446 		}
447 		return this;
448 	},
449 	focus : function(s) {
450 		try {
451 			if (s || typeof s === 'undefined')
452 				this.win().focus();
453 			else
454 				this.win().blur();
455 		} catch (e) {
456 		}
457 		return this;
458 	},
459 	get_page : function() {
460 		return this.getT('html')[0].outerHTML;
461 	},
462 	save_page : function(path, encoding) {
463 		var text = this.get_page();
464 		if (path && text) {
465 			href = this.href(), l = href.length;
466 			l = (l > 9 ? l > 99 ? l > 999 ? '' : '0' : '00' : '000')
467 			+ l;
468 			simpleWrite(path, '<!-- saved from url=(' + l + ')' + href
469 					+ ' -->' + NewLine + text, encoding || TristateTrue);
470 		}
471 		return this;
472 	},
473 	getC : function(class_name) {
474 		return find_class(class_name, this.doc());
475 	}
476 };
477 //	IEA.prototype={
478 
479 
480 
481 
482 
483 
484 //	WSH環境中設定剪貼簿的資料:多此一舉	http://yuriken.hp.infoseek.co.jp/index3.html	http://code.google.com/p/zeroclipboard/
485 //setClipboardText[generateCode.dLK]='IEA';//,clipboardFunction
486 function setClipboardText(cData,cType){
487  if(typeof clipboardFunction=='function')return clipboardFunction();
488  var IE=new IEA;
489  if(!IE.OK(1))return '';
490  if(!cType)cType='text';
491 
492  with(IE.win())
493   if(cData)window.clipboardData.setData(cType,cData);
494   else cData=window.clipboardData.getData(cType);
495 
496  IE.quit();//try{IEApp.Quit();}catch(e){}
497  return cData||'';
498 };
499 
500 CeL.net.HTA
501 .
502 /**
503  * WSH 環境中取得剪貼簿的資料
504  * @memberOf	CeL.net.HTA
505  */
506 getClipboardText = setClipboardText;
507 
508 
509 
510 
511 
512 return (
513 	CeL.net.HTA
514 );
515 };
516 
517 //===================================================
518 
519 CeL.setup_module(module_name, code_for_including);
520 
521 };
522