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