      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