      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