1 if(typeof(Sucang)=='undefined') window.Sucang={};
  2 if(!Sucang.lang) Sucang.lang={};
  3 /**
  4  * 页面布局和模板及UI组件的相关操作类
  5  * @namespace
  6  */
  7 Sucang.page={
  8 	tab:null,
  9 	/** 当前页是否被内嵌框架中 */
 10 	isFrame:true,
 11 	init:function(){
 12 		var fr=__frameElement(window);
 13 		if(typeof(fr)=='undefined' || fr==null){
 14 			this.isFrame=false;//表示非Frame框架加载
 15 			return;
 16 		}
 17 		var p = __top().MyPage;
 18 		if(!p || !p.objTab) return;
 19 		var tabId = fr.id.substring(5);
 20 		this.tab = p.objTab.getItem(tabId);
 21 		//this._tabMask = new Ext.LoadMask(Ext.get('tabPanel'), {msg:"Please wait..."});
 22 	},
 23 	/** 当前页的顶部工具条对象 as Ext.Toolbar */
 24 	tbar:null,
 25 	/** 
 26 	 * @description 当前面添加按钮
 27 	 * @param {btns} Array //Ext.Toolbar.Button的对象格式
 28 	 * @param {isPageCreate} boolean
 29 	 * @param {parentEl} Ext.Element //当isPageCreate==true,且未发现#pageToolbar工具旋转位置时,将工具放到该元素的最前面
 30 	 * @return {tbar} Ext.Toolbar
 31 	 *  */
 32 	addButton:function(btns,isPageCreate,parentEl){
 33 		if(location.search.indexOf('action=print')>0){
 34 			this.isPrint=true;
 35 			Sucang.page.initPrinter();//初始化打印选项
 36 			return;//如果是打印界面工具栏不生成
 37 		}
 38 		isPageCreate = true;//始终在当前页创建工具条
 39 		if(this.tab==null || isPageCreate){//创建Toolbar
 40 			var div=Ext.getDom('pageToolbar');
 41 			if(div==null){
 42 				var div=document.createElement("div");
 43 				div.id="pageToolbar";
 44 				if(parentEl) parentEl.insertFirst(div);
 45 				else Ext.getBody().insertFirst(div);
 46 			}
 47 			var obj={};
 48 			var cfg=div.getAttribute('config');
 49 			if(!Ext.isEmpty(cfg)) Ext.apply(obj,Ext.decode('{'+cfg+'}'));
 50 			this.tbar=new Ext.Toolbar(obj);
 51 			this.tbar.render(div.id);
 52 			/*if(this.tab!=null){
 53 				var obj=this.tab.getTopToolbar();
 54 				if(obj!=null && obj.getEl()!=null){
 55 					Ext.get(obj.getEl().dom.parentNode).remove();
 56 				}//end.if
 57 			}*/
 58 		}else{
 59 			this.tbar=this.tab.getTopToolbar();
 60 			//清空已存在的项
 61 			this._clearButtons(this.tbar);
 62 			__top().MyPage.getTabFrame().style.height=(__top().MyPage.objTab.getInnerHeight()-25)+'px';
 63 			//如果需要显示Tab页的工具条则将Frame高度降低,否则Viewport显示底部会被遮住
 64 			this.tbar.show();
 65 			this.tbar.getEl().parent().show();
 66 			//this.tbar.getEl();
 67 		}
 68 		this.tbar.setHeight(26);
 69 		this.tbar.addSeparator();
 70 		var keyMaps=new Array();
 71 		for(var i=0;i<btns.length;i++){
 72 			if(Ext.isEmpty(btns[i]) || i==1 && btns[i]=='-') continue;
 73 			if(Ext.isEmpty(btns[i].cls)) btns[i].cls = '';
 74 			if(!Ext.isEmpty(btns[i].icon)){
 75 				if(!btns[i].icon.startsWith('/')) btns[i].icon='/images/icon/'+btns[i].icon+'.gif';
 76 				btns[i].cls += ' x-btn-text-icon';
 77 			}
 78 			if(!Ext.isEmpty(btns[i].key)){
 79 				if(btns[i].text.indexOf('<u>')<0)
 80 					btns[i].text+='(<u><b>'+btns[i].key+'</b></u>)';
 81 				var b = this.tbar.addButton(btns[i]);//需要返回按钮对象,所以显式的调用addButton方法
 82 				keyMaps.push({key: btns[i].key,alt:true,stopEvent:true,
 83 					fn:b.handler,scope:btns[i].scope});
 84 			}else this.tbar.add(btns[i]);
 85 		}
 86 		if(keyMaps.length>0) this.keymap = new Ext.KeyMap(document.body,keyMaps);
 87 		setTimeout(function(tb){//需要延迟初始化,按钮对象有可能dom未生成
 88 			Sucang.page._initUserBtns(tb);
 89 			}, 300, this.tbar);
 90 		return this.tbar;
 91 	},
 92 	/**
 93 	 * @description 将工具条按钮或指定的id的input按钮转换成带复制功能的按钮
 94 	 * @param {btn} as Ext.Toolbar.Button|String
 95 	 * @param {handler} as Function 当btn参数是String,按钮id时必填
 96 	 */
 97 	initCopyBtn:function(btn,handler){
 98 		if(!btn) return;
 99 		if(typeof(ZeroClipboard)=='undefined') return; 
100 		var btnid;
101 		if(typeof(btn)=='string'){
102 			btnid = btn;
103 		}else{
104 			btnid = btn. getId();
105 			handler = btn.initialConfig.handler;
106 		}
107 		var clip = new ZeroClipboard.Client();	
108 		if(handler) clip.addEventListener('mousedown', handler);
109 		else console.log('initCopyBtn(..)初始化按钮时,handler函数不能为空.');
110 		clip.setHandCursor(true);
111 		clip.setCSSEffects(true);
112 		clip.glue(btnid);
113 	},
114 	/**
115 	 * @private
116 	 */
117 	_initUserBtns:function(tb){
118 		var t=window.UserButtons;
119 		if(typeof(t)!='object' || Ext.isEmpty(tb)) return;
120 		for(var i in t){
121 			if(!i.startsWith('BtnInit') || typeof(t[i])!='function') continue;
122 			var b=tb.items.get('btn'+i.substring(7));
123 			if(!b) continue;
124 			try{
125 				t[i](b,tb.isLink);
126 			}catch(e){
127 				alert('error:初始化['+b.text+']按钮的脚本时异常:'+e.message);
128 				if(location.host.startsWith('localhost')) throw e;
129 			}
130 		} //end.for(t);
131 	},
132 	/**
133 	 * @private
134 	 */
135 	_clearButtons:function(tbar){
136 		try{
137 			var el=tbar.getEl().dom;
138 			var tb=el.getElementsByTagName('table')[0];
139 			var tr=Ext.isIE?tb.rows(0):tb.rows[0];
140 			if(Ext.isIE){
141 				var l=tr.children.length;
142 				for(var i=0;i<l;i++) tr.deleteCell();
143 			}else{
144 				tr.innerHTML='';
145 			}
146 			tbar.items.clear();
147 		}catch(e){alert('addButton.Error:'+e);}
148 	},
149 	/**
150 	 * @description 将url链接在Tab标签中打开<br>
151 	 *	可以是<a href="test.html" onclick="return Sucang.page.openTab(this,event)">test.html</a><br>
152 	 *  <a href="test.html" tabtext="标签文本" target="_tab">test.html</a>该方式需要页面初始HTML加载才有效.
153 	 * @param {id} String 标签Tab标签的ID
154 	 * @param {url} String 要打开的URL
155 	 * @param {title} String Tab标签的标题
156 	 * @return {boolean} 返回值总是为false
157 	 */
158 	openTab:function(id,url,title){//<a href="**" onclick="return Sucang.page.openTab(this,event)">**</a>
159 		//if(url.endsWith('#'))return false;
160 		if(typeof(BBox)=='object') return false;//表示浏览框链接无效
161 		if(typeof(id)=='object'){//用于文档后DOM添加的<A链接
162 			this.stopBubble(url);//url===event.
163 			return this._anchorOpenTab(id);
164 		}
165 		
166 		if(!this.isFrame){//非框架表示首页加载
167 			if(this.objTab!=null) this.openIndexTab(id,url,title);//如果有Tab就打开Tab
168 			else if(__top().location.pathname!='/main.do'){
169 				if(typeof(this.openNewWindow)=='boolean' && this.openNewWindow){
170 					window.open(url,id);
171 				}else location.href=url;
172 				return false;
173 			}else{
174 				if(typeof(openTabIsNew)=='boolean' && openTabIsNew 
175 					&& window['openNewHasFrame']===true){
176 						url='/main.do?_url='+encodeURIComponent(url);
177 				}
178 				if(typeof(openTabIsNew)=='boolean' && !openTabIsNew
179 					 || url.startsWith('/portal.do')){//如果非新窗口和门户打开,则在原iframe页内
180 					id = 'frametabHome';
181 				}
182 				window.open(url,id);
183 			}
184 		}else{
185 			if(window.frameElement.id=='frametabHome' && __top().Sucang.page.objTab==null){
186 				window.open(url,id);
187 				return false;
188 			}else if(__top().location.pathname!='/main.do'){
189 				location.href=url;
190 				return false;
191 			}
192 			__top().MyPage.openTab(id,url,title);
193 		}
194 		return false;
195 	},
196 	/**
197 	 * @description 打开模式对话窗口,会覆盖在最顶层<br>
198 	 * <a href="$url" target="_browser" _bar="$values" _callback="$callback">链接文本</a> 只有在页面初始加载HTML时才有效
199 	 * @param {url} String 需要打开的URL地址
200 	 * @param {values} Array 可以为空或工具栏按钮,如:[{"text":"查询","handler":DefaultBtn.Query,"icon":"page_find"}] icon表示/images/icon下的文件名
201 	 * @param {callback} Function|Object 对话框关闭时的回调函数格式function callback(val){...},如果为Object时须指定callback属性的回调函数和height,width。
202 	 */
203 	openWindow:function(url,values,callback){
204 		if(!this.isFrame){
205 			this.openIndexWindow(url,values,callback);
206 		}else{
207 			__top().MyPage.openWindow(url,values,callback);
208 		}
209 		return false;
210 	},
211 	/**
212 	 * @description 刷新当前活动标签、当前窗口页面或转到指定的url页面
213 	 * @param {url} String 如果url为空表示刷新当前活动Tab标签和当前页
214 	 */
215 	refreshTab:function(url){
216 		if(Ext.isEmpty(__top().MyPage.objTab)){
217 			if(Ext.isEmpty(url) && typeof(isMultiTab)=='boolean' && !isMultiTab) Ext.getDom('frametabHome').contentWindow.location.reload();
218 			else if(!Ext.isEmpty(url)) location.replace(url);
219 			return;
220 		}
221 		var tabId=__top().MyPage.objTab.getActiveTab().id;
222 		var iframe=__top().Ext.getDom('frame'+tabId);
223 
224 			if(iframe){
225 			    var activeTab=__top().MyPage.objTab.getActiveTab();
226 	            if( typeof(activeTab.getInnerHeight) == 'function' )
227 	            	__top().Ext.get('frame'+activeTab.id).setHeight(activeTab.getInnerHeight());
228 				if(!Ext.isEmpty(url)) iframe.src=url;
229 				else{
230 					var host = location.protocol +'//'+ location.host;
231 					if(iframe.src.startsWith(host)){//表示同域
232 						var bl = false;
233 						if(Ext.isGeko) bl = true;
234 						iframe.contentWindow.location.reload(bl);
235 					}else{
236 						iframe.src = iframe.src; 
237 					}
238 				}
239 			}
240 	},
241 	/**
242 	 * @description 获取指定的标签页的Iframe对象,用.contentWindow属性获取iframe内的window对象
243 	 * @param {frameId} String //如果为空表示当前活动标签页
244 	 */
245 	getTabFrame:function(frameId){
246 		if(Ext.isEmpty(__top().MyPage.objTab)){
247 			if(__top().isMultiTab || !Ext.getDom('frametabHome')) return {'contentWindow':__top().window};
248 			else return Ext.getDom('frametabHome');
249 		}
250 		if(typeof(frameId)=='undefined') frameId=__top().MyPage.objTab.getActiveTab().id;
251 		return __top().Ext.getDom('frame'+frameId);
252 	},
253 	/**
254 	 * @description 获取当前活动标签的标题
255 	 * @return {title }String
256 	 */
257 	getTabTitle:function(){
258 		if(Ext.isEmpty(__top().MyPage.objTab)) return document.title;
259 		return __top().MyPage.objTab.getActiveTab().title;
260 	},
261 	/**
262 	 * @description 关闭当前活动Tab标签
263 	 */
264 	closeTab:function(win){
265 		if(Ext.isEmpty(__top().MyPage.objTab)){
266 			if(typeof(__top().isMultiTab)!='undefined' && !__top().isMultiTab) history.back(); 
267 			else window.close();
268 			return;
269 		}
270 		var tabId=null;
271 		var tab = null;
272 		if(typeof(win)=='object'){
273 			tab = __top().MyPage.objTab.getItem(win.frameElement.id.substring(5));
274 		}else if(typeof(win)=='string') tabId=win;
275 		else tabId=__top().MyPage.objTab.getActiveTab().id;
276 		
277 		if(!tab && tabId) tab=__top().MyPage.objTab.getItem(tabId);
278 		__top().MyPage.objTab.remove(tab);
279 	},
280 	objTab:null,
281 	onMenuClick:function(m){ 
282 		var tabId=__top().MyPage.objTab.getActiveTab().id;
283 		switch(m.id){
284 		case 'mClose':
285 			var tab=__top().MyPage.objTab.getItem(tabId);
286 			__top().MyPage.objTab.remove(tab);
287 		break;
288 		case 'mRefresh':
289 			var iframe=Ext.getDom('frame'+tabId);
290 			try{
291 				if(iframe) iframe.contentWindow.location.reload();
292 			}catch(e){alert('外部地址无法刷新,请使用右击"刷新"菜单'+e);}
293 		break;
294 		case 'mCloseOthers':
295 			Ext.Msg.confirm('关闭确认', '确认关闭其他Tab页(Y/N)?',function(id){
296 				if(id!='yes')return;
297 				__top().MyPage.objTab.items.each(function(item,i,l){
298 					if(item.id!='tabHome' && item.id!=tabId){
299 						__top().MyPage.objTab.remove(item);
300 					}
301 				});
302 			});
303 		break;
304 		default:
305 			if(__top().MyPage.objTab.getActiveTab().id!=m.id.substring(1)){
306 				var tab = __top().MyPage.objTab.getItem(m.id.substring(1));
307 	        	if(tab) __top().MyPage.objTab.setActiveTab(tab);
308 			}
309 		}//end.
310 		
311 	},
312 	onRemoveTab:function(p,t){
313 		__top().MyPage.tabMenu.items.each(function(item,i,len){
314 			if(item.id.substring(1)==t.id){
315 				__top().MyPage.tabMenu.remove(item);return false;
316 			}
317 		});
318 		var frame = Ext.getDom('frame'+t.id);
319 		var host = location.protocol + '//' + location.host;
320 		if(frame.src.startsWith(host)){//表示同域
321 			var win = frame.contentWindow;
322 			if(win.Sucang && win.Sucang.onLeaveConfirm===true){
323 				if(!confirm('当前内容未保存,是否关闭当前窗口(Y/N)?')) return false;
324 			}
325 		}
326 		if(Ext.isIE){
327 			//frame.dom.contentWindow.document.write('');//清空iframe的内容
328 			//frame.dom.contentWindow.close();//避免iframe内存泄漏
329 			console.log('ie iframe remove.');
330 			frame.src='about:blank';
331 			Ext.get(frame).remove();//删除iframe
332 		}else{
333 			frame.src='about:blank';
334 		}
335 		return true;
336 	},
337 	tabMenu:null,
338 	onTabMenu:function(p,tab,e){
339 		if(__top().MyPage.tabMenu!=null){
340 			//__top().MyPage.objTab.setActiveTab(tab);
341 			__top().MyPage.tabMenu.items.get(0).setDisabled((tab.id=='tabHome'));
342 			/*__top().MyPage.tabMenu.items.each(function(item,i,len){
343 				if(item.id.substring(1)==tab.id){
344 					item.setChecked(true);return false;
345 				}
346 			});*///右击时不让选中
347 			__top().MyPage.tabMenu.showAt(e.getXY());
348 		}
349 	},
350 	hideMask:function(obj){
351 		this._tabMask.hide();
352 	},
353 	_tabMask:null,
354 	openIndexTab:function(id,url,title){
355 		var tab = this.objTab.getItem(id);
356         if(tab){
357         	this.objTab.setActiveTab(tab);
358         	if(Sucang.overrideTab=='0') Ext.getDom('frame'+id).src=url;
359         	else if(Sucang.overrideTab=='1'){
360 				Ext.Msg.confirm("提示:","链接已打开,是否刷新!",function(no){
361 					if(no=="yes") Ext.getDom('frame'+id).src=url;
362 				}).setIcon(Ext.MessageBox.WARNING);
363 			}
364         }else{
365         	var nHeight=this.objTab.getInnerHeight();
366         	/*var spanFrame=Ext.DomHelper.append('mainPanel',{tag:'iframe', src:url,id:'frame'+id,name:'frame'+id,
367         		width:'1000',frameborder:0,style:'height:'+nHeight+'px'});*/
368         	var spanFrame='<iframe id="frame'+id+'" src="'+url+'" name="frame'+id+'" width="100%" style="height:'+nHeight+'px" frameborder="0"></iframe>';
369         	var t=this.objTab.add({
370 				id:id,
371             	title:Ext.util.Format.ellipsis(title,25),
372             	tabTip:title,
373                 //contentEl:spanFrame,
374                 html:spanFrame,
375 	            closable:true
376 	            ,tbar:new Ext.Toolbar({height:25,hidden:true,hideParent:true})//这在Tab上加工具栏是因为当页面过长下拉时工具栏不会卷曲掉。
377 	            ,listeners:{'beforeremove':MyPage.onRemoveTab}
378 	        });
379 	        /*if(Ext.isIE6){
380 	        	t.on('render',function(t){
381 	        		
382 	        	});
383 	        }*/
384 	        //Ext.get('mainPanel').enableDisplayMode().hide();//这一句是为了什么.
385 			this.objTab.setActiveTab(t);
386 			__top().MyPage.tabMenu.add({id:'m'+id,checked:true,text:title,group:'radioMenu'});
387 		}
388 	},
389 	doCancel:function(btn,n){
390 		var funCancel=Ext.getDom(MyPage._winIframe+n).contentWindow.Cancel;
391 		var ret=true;
392 		if(typeof(funCancel)=='function') ret=funCancel();
393 		if(ret){
394 			MyPage.closeWindow(MyPage._win[n]);
395 			//if(typeof(MyPage._winCallback[n])=='function') MyPage._winCallback[n](ret);
396 		}
397 	},
398 	doOk:function(btn,n){
399 		var funOk=Ext.getDom(MyPage._winIframe+n).contentWindow.OK;
400 		var ret=true;
401 		if(typeof(funOk)=='function') ret=funOk();
402 		if(ret){
403 			MyPage.closeWindow(MyPage._win[n]);
404 			if(typeof(MyPage._winCallback[n])=='function') MyPage._winCallback[n](ret);
405 		}
406 	},
407 	/**
408 	 * @description 关闭当前模式窗口
409 	 * @param {winIndex} Integer //如果为空表示第一层默认窗口,一般无须指定
410 	 */
411 	closeWindow:function(w){
412 		var n=0;
413 		if(Ext.isEmpty(w)){//如果为空,则从顶层窗口开始逐层关闭
414 			n=__top().MyPage._win.length-1;
415 			while(n>0 && !__top().MyPage._win[n].isVisible()){
416 				n-=1;
417 			}
418 		}else if(w.level) n=w.level;
419 
420 		if(__top().MyPage._win[n]!=null && __top().MyPage._win[n].isVisible()){
421 			var ww = __top().MyPage._win[n];
422 			ww.hide();
423 			ww.setTitle('Dialog');
424 			__top().Ext.getDom(__top().MyPage._winIframe+n).src='about:blank';
425 			if(typeof(ww.hasListener)=='function' && ww.hasListener('beforehide')){
426 				ww.removeListener('beforehide',ww._beforehideHandler);
427 				delete ww._beforehideHandler;
428 			}
429 		}else if(MyPage._htmlWin!=null && MyPage._htmlWin.isVisible()){
430 			//由于调用的页面parent.MyPage.closeWinodw()为对话框中的子窗口,则MyPage指的是当前页面的对象
431 			MyPage._htmlCancel();
432 		}else if(parent.MyPage._htmlWin!=null && parent.MyPage._htmlWin.isVisible()){
433 			parent.MyPage._htmlCancel();
434 		}
435 	},
436 	/**
437 	 * @description 获取当前弹出窗口的工具条对象
438 	 * @return {tbar} Ext.Toolbar
439 	 */
440 	getWindowToolbar:function(){
441 		var _win=MyPage.getWindow();
442 		var tbar=null;
443 		if(_win!=null) tbar=_win.getTopToolbar();
444 		return tbar;
445 	},
446 	/**
447 	 * @description 获取当前弹出窗口的window对象
448 	 * @return {win} HTMLWindow
449 	 */
450 	getWindow:function(){
451 		var fr = __frameElement(window);
452 		if(fr==null) return MyPage._win[0];
453 		var id=fr.id;
454 		var win=null;
455 		if(id.startsWith(MyPage._winIframe)){
456 			var _index=parseInt(id.substring(MyPage._winIframe.length),10);
457 			win=__top().MyPage._win[_index];
458 		}else if(Sucang.isParent(parent) && parent.MyPage._htmlWin!=null){
459 			 win=parent.MyPage._htmlWin;
460 		}else if(MyPage._htmlWin!=null){
461 			 win=MyPage._htmlWin;
462 		}
463 		return win;
464 	},
465 	doClear:function(btn,n){
466 		var funClear=Ext.getDom(MyPage._winIframe+n).contentWindow.Clear;
467 		var ret=true;
468 		var tmp=true;
469 		if(typeof(funClear)=='function') tmp=funClear();
470 		if(tmp){
471 			MyPage.closeWindow(MyPage._win[n]);
472 			if(typeof(tmp)=='boolean'){ret=['',''];}else{ret=['','',tmp];}//modified by wiley
473 			if(typeof(MyPage._winCallback[n])=='function') MyPage._winCallback[n](ret);
474 		}
475 	},
476 	_winMask:[],
477 	_winCallback:[],
478 	_win:[],
479 	_winIframe:'winIframeWindow',
480 	_initWindow:function(n,_btn){
481 		if(typeof(n)=='undefined')n=0;
482 		var span=document.createElement("span");
483     	span.id="win"+n;
484     	span.innerHTML='<iframe frameborder="0" style="background-color:#FFFFFF;" width="100%" height="100%" id="'+this._winIframe+n+'" src="about:blank"></iframe>';
485     	var _this=this;
486     	Ext.getBody().insertFirst(span);
487     	//document.body.appendChild(span);
488     	var SL=Sucang.lang;
489     	Ext.EventManager.on(this._winIframe+n, 'load', this.doneLoadFrame,this);
490     	var suffix = (n>0) ? '_'+n : '';
491     	var btnids = ['','_winBtnOk' + suffix, '_winBtnClear' + suffix, '_winBtnCanel' + suffix];
492     	this._win[n] = new Ext.Window({
493 			layout:'fit',
494 			contentEl:'win'+n,
495 			width:800,
496 			cls:Ext.isEmpty(Sucang.browser.cls)?'':Sucang.browser.cls,
497 			iconCls:'windowTitleIcon',
498 			height:550,
499 			constrain:Sucang.page.windowOutside?true:false,
500             constrainHeader:Sucang.page.windowOutside?true:false,
501 			title:'Dialog'+n,
502 			modal:true,//btns=='clear',//true,//当显示浏览框时显示为模态式
503 			closable:true,
504 			plain: true,
505 			listeners:{'beforeclose':function(p){_this.closeWindow(p);return false;} },
506 		tbar: ['-',{id: btnids[1], text: SL.buttonOk/*'确定'*/,handler:function(b){_this.doOk(b,n);},icon:'/images/icon/accept.gif',cls:"x-btn-text-icon browser-btnOk"},
507 		       {hidden:(_btn!='browser'),id: btnids[2], text: SL.buttonClear/*'清除'*/,handler:function(b){_this.doClear(b,n);},icon:'/images/icon/erase.gif',cls:"x-btn-text-icon browser-btnClear"},
508 		       {id: btnids[3],text: SL.buttonCancel/*'取消'*/,handler:function(b){_this.doCancel(b,n);},icon:'/images/icon/cancel.gif',cls:"x-btn-text-icon browser-btnCancel"}]
509 		});
510 		this._win[n].level=n;
511 	},
512 	openIndexWindow:function(url,_bar,callback){
513 		var n=-1;
514 		do{
515 			n+=1;
516 			if(typeof(this._win[n])=='undefined') this._initWindow(n,_bar);
517 		}while(this._win[n].isVisible());
518 		var _w=800,_h=550;//初始值应同_initWindow方法内的一致
519 		if(typeof(callback)=='function'){
520 			this._winCallback[n]=callback;
521 		}else if(!Ext.isEmpty(callback) && typeof(callback)=='object'){
522 			_w = Ext.value(callback.width, _w);
523 			_h = Ext.value(callback.height, _h);
524 			if(typeof(callback.callback)=='function') this._winCallback[n]=callback.callback;
525 			if(typeof(callback.beforehide)=='function'){
526 				this._win[n]._beforehideHandler=callback.beforehide;
527 				this._win[n].addListener('beforehide',this._win[n]._beforehideHandler);
528 			}
529 		}
530     	var tbb=this._win[n].getTopToolbar();
531     	if(typeof(tbb.setHeight)=='function') tbb.setHeight(26);
532     	if(tbb.items) tbb.items.itemAt(2).setVisible(_bar=='browser');
533     	Ext.getDom(this._winIframe+n).src=url;
534     	this._win[n].setSize(_w,_h);
535     	this._win[n].show();
536     	var xy=this._win[n].getPosition();
537     	if(xy[1]<0){//表示高度超出了
538     		this._win[n].setSize(_w, document.documentElement.clientHeight);
539     		this._win[n].setPosition(xy[0], 0);
540     	}
541 		//this._winMask.show();
542 	},
543 	doneLoadFrame:function(e){//Windows窗口加载完成后的回调函数
544 		var frame=e.getTarget();
545 		var n=frame.id.substring(this._winIframe.length);
546 		this._win[n].setTitle(frame.contentWindow.document.title);
547 		var _bw=Sucang.browser.borderWidth;
548 		if(typeof(_bw)=='number'){//新主题宽度适配
549 			var _oriW = this._win[n].getInnerWidth();
550 			this._win[n].body.dom.style.width = (_oriW-_bw)+'px';
551 		}
552 		//var _initCall=frame.contentWindow.init;
553 		if(frame.src!='about:blank' && typeof(__top().onShowBrwoser)=='function') 
554 			__top().onShowBrwoser(this._win[n]);
555 	},
556 	/**
557 	 * @description 查找对象obj的最近上级的标签为$tagName的对象
558 	 * @param {obj} HTMLElement 
559 	 * @param {tagName} String //大写的HTML标记名
560 	 * @return {obj} HTMLElement
561 	 */
562 	getParentDom:function(o,t){//根据tagName获取上层结点DOM
563 		do{o = o.parentNode;}while(o.tagName!=t);
564 		return o;
565 	},
566 	_anchorOpenTab:function(o){
567 		if(o.tagName!='A' && o.tagName!='AREA') o=this.getParentDom(o,'A');
568 		if(o==null) return false;
569 		var text=o.getAttribute("tabText");
570 		if(Ext.isEmpty(text)){
571 			text=Ext.util.Format.stripTags(o.innerHTML);
572 			if(text.length>16) text=Ext.util.Format.ellipsis(text,16);
573 			else if(text.length==0) text="Untitled";
574 		}
575 		var prefix=location.protocol+'//'+location.hostname+':'+location.port;
576 		var url=o.href.replace(prefix,"");
577 		if(url==location.pathname) return false;
578 		if(location.pathname=='/main.do' && typeof(jQuery)=='function'){//如果是首页的左侧导航菜单则处理
579 			jQuery(o).parents("div[class*='hover']").removeClass('hover');
580 		}
581 		return this.openTab(url.replace(/[\W_\-]+/gi,''),url,text);
582 	},
583 	_anchorOpenWindow:function(o){
584 		if(o.tagName!='A') o=this.getParentDom(o,'A');
585 		if(o==null)return;
586 		var _back=o.getAttribute('_callback');
587 		var _tbar=o.getAttribute('_tbar');
588 		if(_tbar==null) _tbar='';
589 		if(!Ext.isEmpty(_back)) _back=eval(_back);
590 		return this.openWindow(o.href,_tbar,_back);
591 	},
592 	stopBubble:function(e){
593         //如果提供了事件对象,则这是一个非IE浏览器
594         if(e && e.stopPropagation)//因此它支持W3C的stopPropagation()方法
595         	e.stopPropagation();
596         else{//否则,我们需要使用IE的方式来取消事件冒泡
597         	e.cancelBubble = true;
598         	e.returnValue=false;
599         }
600      },
601 logoff:function(){
602     	 location.replace('/login.do');
603 },
604 _htmlWin:null,
605 _callbackOk:null,
606 _htmlCancel:function(){
607 	var frameWin=Ext.getDom('_HTMLWindowFrame');
608 	var obj=document._htmlWinForm;
609 	if(frameWin!=null) obj=frameWin.contentWindow;
610 	MyPage._htmlWin.hide();
611 	if(typeof(MyPage._callbackOk)=='function') ret=MyPage._callbackOk(obj,true);
612 	//窗口取消操作也执行回调函数,第二个参数如果为true则表示取消操作
613 },
614 _htmlOk:function(btn){
615 	var ret=true;
616 	var frameWin=Ext.getDom('_HTMLWindowFrame');
617 	var obj=document._htmlWinForm;
618 	if(frameWin!=null){
619 		obj=frameWin.contentWindow;
620 		if(typeof(obj.OK)=='function') ret=obj.OK(btn);
621 		if(!ret) return;
622 	}
623 	if(typeof(MyPage._callbackOk)=='function') ret=MyPage._callbackOk(obj);
624 	if(ret){
625 		MyPage._htmlWin.hide();
626 	}
627 },
628 /**
629  * 判断指定的window对象是否内嵌在模式窗口中
630  * @param {win} HTMLWindow //如果为空时表示当前窗口的window对象
631  * @return boolean
632  */
633 isWindow:function(_win){
634 	if(typeof(_win)=='undefined') _win=window;
635 	var iswin=false;
636 	var oFrame=__frameElement(_win);
637 	if(oFrame!=null)
638 		iswin=(oFrame.id.startsWith(MyPage._winIframe) || oFrame.id.startsWith('_HTMLWindowFrame'));
639 	return iswin;
640 },
641 /**
642  * 获取指定的window对象内嵌在模式窗口中的类型,0表示当前window对象无内嵌,1表示Brwoser框,2表示当前Frame内的窗口
643  * @param {win} HTMLWindow //如果为空时表示当前窗口的window对象
644  * @return {nType} Number
645  */
646 getWindowType:function(_win){
647 	if(typeof(_win)=='undefined') _win=window;
648 	var wintype=0;
649 	var oFrame=_win.frameElement;
650 	if(oFrame!=null)
651 		if(oFrame.id.startsWith(MyPage._winIframe)) wintype=1;
652 		else if(oFrame.id.startsWith('_HTMLWindowFrame')) wintype=2;
653 	return wintype;
654 },
655 /**
656  * @description 在当前iframe窗口内打开模式对话框<br>
657  * <a href="$url" target="_window">链接文本</a> 只有在页面初始加载HTML时才有效
658  * @param {shtml} String|Object //如果是URL则内嵌Iframe打开,如果是HTML内容则在<form标记中打开
659  * @param {callback} Function 窗口关闭时的回调函数fucntion callback(win|form,isCancel){...}
660  * @param {config} Object //同Ext.Window的构造函数参数,tbar:[true|false]可以使默认的工具条隐藏或显示
661  * @return {dom} HTMLIFrameElement | HTMLFormElement
662  */
663 openHTMLWindow:function(shtml,_callbackOk,config){
664 	//if(this.isFrame){
665 	//	return __top().MyPage.openHTMLWindow(shtml,_callbackOk,config);
666 	//}
667 	if(typeof(shtml)=='object' && shtml.tagName=='A'){
668 		if(!Ext.isEmpty(shtml.getAttribute('data-config'))){
669 			config=Ext.decode(shtml.getAttribute('data-config'));
670 		}
671 		shtml=shtml.href;
672 	}
673 	this._callbackOk=_callbackOk;
674 	var _this=this;
675 	var defHeight=400;
676 	var defWidth=h=600;
677 	var div=null;
678 	if(this._htmlWin==null){		
679 		div=Ext.DomHelper.append(Ext.getBody(),{id: '_htmlWinDiv', tag: 'div',html: ''},true);
680 		div.setStyle({width:'100%',backgroundColor:'#FFFFFF',height:defHeight+'px'});
681 		var SL=Sucang.lang;
682 		var cfg={
683 			//id:'_htmlWinId',
684 			layout:'fit',
685 			contentEl:'_htmlWinDiv',
686 			width:defWidth,
687 			//autoScroll:true,
688 			height:defHeight+56,
689 			title:'Untitled',
690 			modal:true,
691 			cls:Ext.isEmpty(Sucang.browser.cls)?'':Sucang.browser.cls,
692 			closable:true,
693 			plain: true,
694 			listeners:{'beforeclose':function(p){_this._htmlWin.hide();return false;}},
695 			tbar: ['-',{id:'okBtn',text: SL.buttonOk/*'确定'*/,handler:_this._htmlOk,icon:'/images/icon/accept.gif',cls:"x-btn-text-icon"},
696 		       {id:'cancelBtn',text: SL.buttonCancel/*'取消'*/,handler:_this._htmlCancel,icon:'/images/icon/cancel.gif',cls:"x-btn-text-icon"}]
697 		};
698 		if(!Ext.isEmpty(config)){
699 			if(typeof(config.tbar)=='boolean' && !config.tbar){
700 				delete config.tbar;
701 				cfg.listeners.render=function(p){p.getTopToolbar().hide();};
702 			}
703 			Ext.apply(cfg,config);
704 		}
705     	this._htmlWin = new Ext.Window(cfg);
706 	}else if(config!=null && typeof(config)=='object'){//用于同步多次不同用途的大小时保持窗口的各自大小
707 		this._htmlWin.setSize(Ext.num(config.width,defWidth),Ext.num(config.height,defHeight+56));
708 		this._htmlWin.setTitle(Ext.value(config.title,'Untitled'));
709 		if(typeof(config.tbar)!='undefined')
710 			this._htmlWin. getTopToolbar().setVisible(config.tbar?true:false);
711 		h=Ext.num(config.height,defHeight);
712 		
713 	}else{
714 		this._htmlWin.setSize(defWidth,defHeight+56);
715 	} //end.if
716 	var wid='_htmlWinForm';
717 	var html='<form name="'+wid+'" id="_htmlWinForm">'+shtml+'</form>';
718 	if(shtml=='about:blank' || shtml.startsWith('http') || shtml.startsWith('/') && (shtml.indexOf('.do')>0 || shtml.indexOf('.jsp')>0)){
719 		wid='_HTMLWindowFrame';
720 		html='<iframe id="'+wid+'" name="'+wid+'" src="'+shtml+'" frameborder="0" width="100%" height="'+h+'" onload="MyPage._htmlWin.setTitle(this.contentWindow.document.title);"></iframe>';
721 	}
722 	if(div==null) div=Ext.getDom('_htmlWinDiv');
723 	else div=div.dom;
724 	div.style.height=h+'px';
725 	div.innerHTML=html;
726 	if(html.startsWith('<form ')) div.style.overflow='auto';
727 	//__top().document.htmlWinForm
728 	this._htmlWin.show();
729 	return Ext.getDom(wid);
730 }//end.fun
731 /**
732  * @description 获取指定name的Cookie值
733  * @param {name} String
734  * @return {val} String
735  */
736 ,getCookieValue:function(name){
737 	var val='';
738 	var keys=document.cookie.split(';');
739 	for(var i=0;i<keys.length;i++){
740 		var ar=keys[i].split('=');
741 		if(ar[0].trim()==name){
742 			val=ar[1];break;
743 		}
744 	}
745 	return val;
746 }
747 /**
748  * @description 指定打印选项参数和打印布局
749  * @param {options} String //打印选项参数,见Sucang.page.initPrinter();方法
750  * @param {layoutid} String|Object 按指定的页面打印或者是指定的参数对象
751  */
752 ,print:function(options,layoutid){
753 	if(typeof(window.printOption)=='object' && options!=null) window.printOption=undefined;//每次打印前先清空打印选项
754 	if(typeof(options)=='object' && options!=null) window.printOption=options;//该参数由打印页面来获取
755 	var paramsMap=Ext.isEmpty(location.search)?{}:Ext.urlDecode(location.search.substring(1));
756 	paramsMap.action='print';
757 	if(!Ext.isEmpty(layoutid)){
758 		if(typeof(layoutid)=='string') paramsMap.layoutid=layoutid;
759 		else paramsMap=Ext.apply(paramsMap,layoutid);
760 	}
761 	var surl=location.pathname+'?'+Ext.urlEncode(paramsMap)+location.hash;
762 	if(Ext.isAir) __top().external.print(surl);
763 	else window.open(surl,'print'+location.pathname.substring(1).replace('.',''));
764 }
765 /**
766  * @description 用于在布局中Ajax同步方式请求获取服务器端数据
767  * @param {sqlid} String //sqlid标识符
768  * @param {params} String|Object 指定参数对象,如果只传一个参数,则Sql页面用value变量表示
769  * @param {options} Object|function(txt)回调函数,如果为空则同步执行。String类型为layoutid,Function类型为回调函数且同步调用,Object可设置参数{dsname:'数据源名称',layoutid:'布局id',callback:异步回调函数}
770  * @return {val} String 如果服务器端执行失败则返回null,如果是单行单列的则直接返回字符串,否则为JSON字符串需转译
771  */
772 ,sql:Sucang.util.sql
773 /**
774  * @description 参数同Sucang.page.sql函数,只是返回结果是数组或者为空
775  * @param {sqlid} String
776  * @param {params} String|Object 指定参数对象,如果只传一个参数,则Sql页面用value变量表示
777  * @param {callback} function(txt)回调函数,如果为空则同步执行,否则为异步调用并返回结果。
778  * @return {result} 返回的是空或数组字面量,如:[{fieldname: value}] 
779  */
780 ,sql2:Sucang.util.sql2
781 /**
782  * @description 用于当前页面或流程的转向,会跳过,当启用关闭窗口时的确认对话框
783  * @param {surl} String //URL转向的地址,如果为空则默认为about:blank
784  * @param {isReplace} boolean //表示是否替换当前页面,即无法退回到上一个页面
785  * @return void
786  */
787 ,go:function(surl,isReplace){
788 	MyPage.leaveConfirm(false);
789 	if(isReplace) location.replace(surl);
790 	else location.href=surl;
791 },
792 exitFull: function () {//退出全屏 判断浏览器种类
793     // 判断各种浏览器,找到正确的方法
794     var exitMethod = document.exitFullscreen || //W3C
795         document.mozCancelFullScreen ||    //Chrome等
796         document.webkitExitFullscreen || //FireFox
797         document.webkitExitFullscreen; //IE11
798     if (exitMethod) {
799         exitMethod.call(document);
800     }else if (typeof window.ActiveXObject !== "undefined") {//for Internet Explorer
801         var wscript = new ActiveXObject("WScript.Shell");
802         if (wscript !== null) {
803             wscript.SendKeys("{F11}");
804         }
805     }
806 }
807 
808 };
809 
810 /** Sucang.page工具类的缩写前缀 */
811 var MyPage=Sucang.page;
812 Sucang.page.init();
813 Sucang.login={};
814 //Ajax登录窗口
815 Sucang.page.encrypt = null;
816 Sucang.page.initEncrypt = function(pubkey){
817 	var cry = new JSEncrypt();
818 	cry.setPublicKey(pubkey);
819 	Sucang.page.encrypt = cry;
820 	console.log('初始化密钥成功...');
821 };
822 Sucang.page._loginWin=null;
823 Sucang.page._submit=function(btn){
824 	//Sucang.page._loginWin.show();
825 	if(!btn) btn = Sucang.page._loginWin.buttons[0];
826 	var _frm = Sucang.page._form1;
827 	var uname = _frm.findById('_username').getValue();
828 	var pwd = _frm.findById('_password').getValue();
829 	var randcode = _frm.findById('_randcode');//Ext.getDom('_randcode');
830 	if(!randcode.hidden && Ext.isEmpty(randcode.getValue())){
831 		Sucang.page._showLoginMsg('验证码不能为空!');
832 		randcode.focus();
833 		return;
834 	}
835 	if(Ext.isEmpty(uname) || Ext.isEmpty(pwd)){
836 		Sucang.page._showLoginMsg('用户名或密码不能为空!');
837 		_frm.findById(Ext.isEmpty(uname) ? '_username' : '_password').focus();
838 		return;
839 	}
840 	pwd = Sucang.page.encrypt.encrypt(pwd);
841 Ext.Ajax.request({
842    url: '/login.do?action=login&isAjax=true',
843    success: function(resp){
844 	  var obj=Ext.decode(resp.responseText);
845 	  if(obj.errNum>=0){
846 	  	try{if(typeof(__top().getUnreadMessage)=='function') __top().getUnreadMessage(0);}catch(e){}//如果登录成功了才加载未读消息
847 	  	Sucang.page._loginWin.close();
848 	  	Sucang.page._loginWin.destroy();
849 	  	Sucang.page._loginWin=null;
850 	  	if(Sucang.page._refUrl=='none') alert('已登录,请重新操作!');
851 	  	else if(Ext.isEmpty(Sucang.page._refUrl)) window.location='/main.do';
852 		else{//检查是否隐藏Iframe内运行,如果是则不转向
853 			var w=Sucang.page._refWin;
854 			var isHideFrame=(!Ext.isEmpty(w.frameElement) && w.frameElement.style.display=='none');
855 			if(typeof(w)=='object'){
856 				if(isHideFrame){
857 					if(typeof(w.parent.RestoreBtn)=='function'){w.parent.RestoreBtn();alert('已登录,请重新操作!');}//用于解决Iframe提交时按钮禁用恢复用
858 				}else w.location.href=Sucang.page._refUrl;
859 			}else window.location.href=Sucang.page._refUrl;
860 	  	}
861 	  }else{
862 	  	//var randDom=Sucang.page._form1.findById('_randcode');
863 	  	if(obj.randcode && randcode.hidden){//如果是多次错误后的显示验证码
864 	  		Sucang.page._loginWin.setHeight(180);
865 	  		randcode.setVisible(true);
866 	  		if(typeof(randcode.getEl)=='function'){
867 	  			var el=randcode.getEl().parent('div[class*=x-hide-label]');
868 	  			el.removeClass('x-hide-label');
869 	  		}
870 	  		Sucang.login.initRandcode();
871 	  	}
872 	  	Ext.getDom('x-form-el-_info').innerHTML=Sucang.page._errMsg[Math.abs(obj.errNum)];
873 	  }
874 	  try{
875 	  	btn.setDisabled(false);
876 	  }catch(e){}
877 	  if(typeof(Main)=='object' && typeof(Main.LoginInited)=='function') Main.LoginInited();
878    },
879    method:'POST',
880    failure: function(resp){Sucang.page._showLoginMsg('Login Error!');alert('Login Error:'+resp.responseText);btn.setDisabled(false);},
881    params: {'username':uname,'password':pwd,'randcode':(randcode.hidden?'':randcode.getValue())}//这里也需要添加验证码
882 });
883 	if(btn){
884 		btn.setDisabled(true);
885 		Sucang.page._showLoginMsg('正在登录中...');
886 	}
887 };
888 Sucang.page._errMsg=['','Licence非法或过期请联系管理员!','帐号不存在或被冻结注销!','密码错误(或大写锁定,区分大小写)!','','验证码错误!'];
889 Sucang.login.initRandcode=function(bl){
890 	Ext.getDom('_randcode').size=8;
891 	var oImg=Ext.DomHelper.append('x-form-el-_randcode',{tag:'img',align:'absmiddle',src:'/verification.do?t='+new Date().getTime(),title:'看清清楚,点击重新获取验证码!'},false);
892 	Ext.get(oImg).on('click',function(e){e.getTarget().src="/verification.do?t="+new Date().getTime();});
893 };
894 Sucang.page._showLoginMsg=function(s){
895 	Ext.getDom('x-form-el-_info').innerHTML=s;
896 };
897 Sucang.page.login=function(url,win,isRandCode){
898 	if(Sucang.page._loginWin==null){
899 		var formItems=[{fieldLabel: '用户名',id: '_username',name: '_username',allowBlank:false,readOnly:true},
900 				{fieldLabel: '密码',name: '_password',id: '_password',inputType:'password',allowBlank:false,
901 				listeners:{'specialkey':function(f,e){ if(e.getKey() == e.ENTER) Sucang.page._submit(); }}
902 				}];
903 		formItems.push({fieldLabel: '验证码',id: '_randcode',name: '_randcode',allowBlank:true,hideLabel:!isRandCode,hidden:!isRandCode,
904 			listeners:{'specialkey':function(f,e){ if(e.getKey() == e.ENTER) Sucang.page._submit();}}
905 		});
906 		formItems.push({id: '_info', hideLabel:true, xtype:'displayfield'});
907       Sucang.page._form1=new Ext.FormPanel({
908     	width:260,
909     	defaultType:'textfield',
910         items:formItems,
911         bodyBorder: false,
912         border:false,
913         labelAlign:'right',
914         labelWidth:60,
915         plain:true,
916         //title:'sss',
917         frame:true
918     });
919     Sucang.page._loginWin= new Ext.Window({
920                 //applyTo     : 'hello-win',
921                 width       : 272,
922                 title:'用户登录',
923                 iconCls:'LoginWinIcon',
924                 cls:Ext.isEmpty(Sucang.browser.cls)?'':Sucang.browser.cls,
925                 height      : isRandCode?180:150,//如果有验证码则高度加30
926                 resizable:false,
927                 bodyBorder:false,
928                 modal:true,
929                 border:false,
930                 //bodyStyle:'0px solid',
931                 //closeAction :'hide',
932                 closable:false,
933                 //plain       : true,
934                 items       : Sucang.page._form1,
935                 buttons: [{id:'btnLogin1',
936                     text     : '登录',
937                     handler  : Sucang.page._submit
938                 }/*,{//不需要取消按钮,只有登录后才能操作或者直接关闭
939                     text     : '取消',
940                     handler  : function(){Sucang.page._loginWin.hide();}
941                 }*/]
942             });
943 	}
944 	Sucang.page._loginWin.show();
945 	if(isRandCode) Sucang.login.initRandcode();
946 	Sucang.page._showLoginMsg('登录超时或已退出,请重新输入密码!');
947 	var uname=Sucang.page.getCookieValue('username');
948 	if(uname.startsWith('%u')) uname = unescape(uname);
949 	else if(uname=='""') uname = "";
950 	Sucang.page._refUrl=url;
951 	Sucang.page._refWin=win;
952 	//Sucang.page._form1.findById('_username').setValue(Ext.isEmpty(uname)?'':uname);
953 	Ext.getDom('_username').value=uname;
954 	Ext.getDom('_password').value='';
955 	window.setTimeout(function(){
956 		if(!Ext.isEmpty(uname)) Ext.getDom('_password').focus();
957     	else Ext.getDom('_username').focus();
958 	},200);
959 };
960 
961 /**
962  * 该函数用于树形节点加载完毕时,遇到登录超时时显示登录界面的友好处理.
963  * @ignore
964  */
965 function treeNoedLoaded(tree,node,resp){
966 	var txt=Ext.util.Format.trim(resp.responseText);
967 	if(txt.startsWith('<scr'+'ipt')){
968 		node.loaded=false;
969 		node.collapse();
970 		Sucang.util.evalScripts(txt);
971 	}
972 }
973 
974 /**
975  * @description 初始化打印选项并调用打印窗口,
976  * 定义:如果布局中需要在打印预览窗口出现前设置一些参数可以定义回调函数initPrinter(){ .. }
977  * @param {options} String
978  */
979 Sucang.page.initPrinter=function(options){
980 	if(Ext.isAir && typeof(_printInit)=='function') _printInit();
981 	else print();
982 	return;
983 	//if(typeof(options)!='object'){print();return;}
984 	if(!Ext.isIE){
985 		alert('非IE浏览器暂不支持自定义打印选项,请手动修改!');
986 		print();
987 		return;
988 	}
989 	var factory=Ext.getDom('factory');
990 	/*if(factory==null){
991 		factory=Ext.DomHelper.append(document.body,
992 			{id: 'factory', tag: 'object', classid: 'clsid:1663ed61-23eb-11d2-b92f-008048fdd814'
993 			,codebase:"/plugin/smsx.cab",style:"display:none;"});
994 	}*/
995 	if(factory==null){
996 		alert('暂不支持自定义打印选项,请联系系统管理员.');
997 		return;
998 	}
999 	if(!Ext.isEmpty(options.header)) factory.printing.header = options.header;
1000 	if(!Ext.isEmpty(options.footer)) factory.printing.footer  = options.footer;
1001     if(!Ext.isEmpty(options.leftMargin)) factory.printing.leftMargin  = options.leftMargin;  
1002     if(!Ext.isEmpty(options.topMargin)) factory.printing.topMargin  = options.topMargin;  
1003     if(!Ext.isEmpty(options.bottomMargin)) factory.printing.bottomMargin  = options.bottomMargin;  
1004     if(!Ext.isEmpty(options.rightMargin)) factory.printing.rightMargin = options.rightMargin;  
1005     if(!Ext.isEmpty(options.bottomMargin)) factory.printing.bottomMargin = options.bottomMargin;  
1006     if(!Ext.isEmpty(options.printBackground)) factory.printing.printBackground = options.printBackground;  
1007     if(!Ext.isEmpty(options.portrait)) factory.printing.portrait = options.portrait;
1008     factory.printing.print();
1009 }
1010 /**
1011  * @description 根据指定的接口id和参数,生成布局中赋值的接口脚本,一般用于浏览框自动带出数据或填充明细行数据
1012  * @param {dataInterfaceId} String|Object  数据接口的ID或者浏览框的字段名或按钮对象,见DataInterface.id
1013  * @param {params} String|Object 当为string时参数值默认设置参数名为value来表示
1014  * @param {isSync} boolean 表示是否同步获取,默认为异步
1015  */
1016 Sucang.page.runDataInterface=function(did,params,isSync){
1017 	if(typeof(did)=='object' && did!=null){
1018 		var v=Sucang.browser.getValue(did);
1019 		if(Ext.isEmpty(params)) params=v; else params.value=v;
1020 		did=did.getAttribute('data-datainterface');
1021 	}else if(!Ext.isEmpty(did) && !Sucang.isGUID(did)){
1022 		var v=Sucang.browser.getValue(did);
1023 		if(Ext.isEmpty(params)) params=v; else params.value=v;
1024 		did=Sucang.getDom(did+'btn').getAttribute('data-datainterface');
1025 	}
1026 	if(Ext.isEmpty(did) || did=='null'){
1027 		//alert('Sucang.page.loadDataInterface::参数接口id不能为空!');
1028 		return;
1029 	}
1030 	if(Ext.isEmpty(params)){
1031 		params={};
1032 	}else if(typeof(params)!='object'){
1033 		params={'value':params.toString()};
1034 	}
1035 	var url='/datainterfacelist.do?action=json&_type=browser&id='+did;
1036 	Sucang.util.Ajax(url,params,function(txt){
1037 		if(isSync){alert('runDataInterface:'+txt);return;}
1038 		if(txt.startsWith('<scr'+'ipt')) Sucang.util.evalScripts(txt);
1039      	else alert('runDataInterface:'+txt);
1040 	},isSync);
1041 }
1042 
1043 /**
1044  * @description 根据指定对象和ID自动设置目标targetid是否显示还是隐藏
1045  * @param {visible} boolean|HTMLInputElement[checkbox] 是选中还是不选
1046  * @param {targetId} String|Array 表示目标HTML对象的ID
1047  * @param {hasRequired} as boolean 表示目标对象是否控制显示且必填,不显示不必填。
1048  **/
1049 Sucang.page.toggle=function(obj, targetId, hasRequired){
1050 	var ret = 0;
1051 	if(Ext.isEmpty(obj) || Ext.isEmpty(targetId)){
1052 		console.log('Sucang.page.toggle:argument obj and targetId is null or undefined.');
1053 		return ret;
1054 	}
1055 	var bl = true;
1056 	if(typeof(obj)=='boolean') bl = obj;
1057 	else if(obj.tagName=='INPUT' && obj.type=='checkbox') bl = obj.checked;
1058 	var ar = targetId;
1059 	if(!Ext.isArray(targetId)) ar = [targetId];
1060 	Ext.each(ar, function(destid){
1061 		var el = Ext.get(destid);
1062 		if(!el){
1063 			console.log('Sucang.page.toggle:targetId={'+destid+'} is null.');
1064 			return;
1065 		}
1066 		if( bl && el.hasClass('x-hide-display')){
1067 			el.removeClass('x-hide-display');
1068 			el.addClass('x-visible-display');
1069 		}else if(!bl && (el.hasClass('x-visible-display') || !el.hasClass('x-hide-display'))){
1070 			el.removeClass('x-visible-display');
1071 			el.addClass('x-hide-display');
1072 		}
1073 		//el.enableDisplayMode().setVisible(bl);
1074 		if(hasRequired){
1075 			if(bl) el.addClass("required");
1076 			else  el.removeClass("required");
1077 		}
1078 	});
1079 	return ret;
1080 }
1081 
1082 Sucang.page._msgCt=null;
1083 /**
1084  * 弹出消息提醒框
1085  * @param {title} String 标题
1086  * @param {msgContent} String 内容
1087  * @param {icon} String //图标,默认为success,可选项有:danger,info,warning,success
1088  */
1089  Sucang.page.msg=function(title, format, icon){
1090 	if(this.isFrame){__top().MyPage.msg(title,format,icon);return;}
1091     if(!this._msgCt) this._msgCt = Ext.DomHelper.insertFirst(document.body, {id:'msg-div'}, true);
1092     this._msgCt.alignTo(document, 't-t');
1093     var s = String.format.apply(String, Array.prototype.slice.call(arguments, 1));
1094     var iconImg = '';
1095     var icons = {'danger':'delete.png' ,'info':'exclamation.png' ,'warning':'error.png', 'success': 'accept.png'};
1096     var cls = '';
1097     if(icon && icons[icon]){
1098     	cls = 'msg-' + icon;
1099     	iconImg = '<img style="vertical-align: bottom;" src="/images/icon/led/' + icons[icon] + '"> ';
1100     }
1101     var _html='<div class="msg">';
1102 	_html+='<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>';
1103 	_html+='<div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc ' + cls + '">' + 
1104 		'<h3>' + iconImg + title+'</h3><span class="msg-txt">'+s+'</span>' + 
1105 		'</div></div></div>';
1106 	_html+='<div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>';
1107 	_html+='</div>';
1108     var m = Ext.DomHelper.append(this._msgCt, {html:_html}, true);
1109     m.slideIn('t').pause(3).ghost("t", {remove:true});
1110 }
1111 
1112 Sucang.page.leaveConfirm=function(a){
1113   if(__top().location.pathname=='/main.do'){
1114   	return;
1115   }
1116   if(a=='init' && Sucang.onLeaveConfirm===true){
1117 	window.onbeforeunload = function(){
1118     	var msg='';
1119     	if(Ext.isWebKit) msg='当前内容未保存,是否关闭当前窗口(Y/N)?';
1120 		return msg;
1121 	}
1122   }else if(typeof(a)=='boolean'){
1123   	Sucang.onLeaveConfirm=false;
1124   	window.onbeforeunload = null;
1125   }
1126 }
1127 
1128 /*
1129  * 初始化将链接中有<a taget="_tab"的在Tab页中打开
1130  * @ignore
1131  */
1132 function initLinkOpenTab(a){
1133 	
1134 	var openTab=function(e){
1135 		e.stopEvent();
1136 		var o=e.getTarget();
1137 		MyPage._anchorOpenTab(o);
1138 		return false;
1139 	};
1140 	var openWindow=function(e){
1141 		e.stopEvent();
1142 		MyPage._anchorOpenWindow(e.getTarget());
1143 		return false;
1144 	};
1145 	var openHTMLWindow=function(e){
1146 		e.stopEvent();
1147 		MyPage.openHTMLWindow(e.getTarget());
1148 		return false;
1149 	};
1150 	var openAirOffice=function(e){
1151 		e.stopEvent();
1152 		var link=e.getTarget();
1153 		var oper='print';
1154 		if(link.getAttribute('data-oper')!=null) oper=link.getAttribute('data-oper');
1155 		var params=link.getAttribute('data-params');
1156 		if(params!=null && typeof(window[params])=='function') params=window[params];
1157 		else params=null;
1158 		__top().external.office(link.href,oper,params);
1159 		return false;
1160 	};
1161 	var link=null;
1162 	var links=null;
1163 	if(a) links = [a];
1164 	else links = document.getElementsByTagName("a");
1165 	var len=links.length;
1166 	for(var i=0;i<len;i++){
1167 		link=links[i];
1168 		if(link.target=='_tab'){
1169 			Ext.EventManager.addListener(link,"click",openTab);
1170 		}else if(link.target=='_browser'){
1171 			Ext.EventManager.addListener(link,"click",openWindow);
1172 		}else if(link.target=='_window'){
1173 			Ext.EventManager.addListener(link,"click",openHTMLWindow);
1174 		}else if(link.className=='supportOpen'){
1175 			if(Ext.isAir) Ext.EventManager.addListener(link,"click",openAirOffice);
1176 			//else;//再实现其他的浏览器的打开方式 
1177 		}
1178 	}
1179 }//end fun.
1180 
1181 /**
1182  * URL的返回值格式参数参数查询页/formquery.do的返回值
1183  * @param {id} HTMLInputElement | String //可输入文本框的id或对象 
1184  * @param {options} Object | BrowserButton //参数选项或者是浏览框的按钮对象,当object是参数格式为{pageSize:10,keyId:'id',textField:'name',viewText:'{name}',fields:['id','name','type'],url:'/autocomplete.do?action=json'}
1185  */
1186 Sucang.autoComplete = function(id, btnDom){
1187 	if(!id) throw 'Sucang.autoComplete参数id不能为空';
1188 	var el = $(id);
1189 	if(typeof(id)=='string') el = $('#' + id);
1190 	var cls = 'x-combo-list';
1191 	var pageSize = 10;
1192     var keyId = '';
1193     var key = '';//搜索匹配的关键词字段
1194     var viewText = '';//显示文本的匹配模板
1195     var val = '';//输入的值
1196     var arFields = [];
1197 	var sUrl = '';
1198 	var elBtn = null;
1199 	if(btnDom){
1200 		var queryOpts = btnDom;
1201 		if(btnDom.tagName=='INPUT'){
1202 			elBtn = $(btnDom);
1203 			queryOpts = {};
1204 			var ar = elBtn.data('auto').split('|');
1205 			queryOpts.keyId = ar[0];
1206 			queryOpts.textField = ar[1];
1207 			queryOpts.viewText = ar[2];
1208 			ar = elBtn.data('queryinfo').split('|');
1209 			queryOpts.pageSize = parseInt(ar[0]);
1210 			queryOpts.url = ar[1];
1211 			queryOpts.fields = Ext.decode(ar[2]);
1212 		}
1213 		//console.log('queryOpts----'+Ext.encode(queryOpts));
1214 		pageSize = queryOpts.pageSize;
1215 		keyId = queryOpts.keyId;
1216 		key = queryOpts.textField;
1217 		viewText = queryOpts.viewText;
1218 		arFields = queryOpts.fields;
1219 		sUrl = queryOpts.url;
1220 	}
1221 	var inputId = el.attr('id');
1222 	if(!elBtn) elBtn = $('#' + inputId + 'btn');
1223 	var isMulti = false;
1224 	if(elBtn.length>0) isMulti = elBtn.data('multi');
1225 	if(isMulti){//如果是多选则改造Dom
1226 		elBtn.parent().removeClass('browserInput').addClass('browser');
1227 		$('#' + inputId + 'Handler').replaceWith('<input type="text" id="' + inputId + 'Handler" size="5" value=""/>');
1228 		el = $('#' + inputId + 'Handler');
1229 		$('#' + inputId + 'span').on('mouseover mouseout click', function(e){
1230 			var eobj = $(e.target);
1231 			if(eobj[0].tagName != 'SPAN') eobj = eobj.closest('span');//防止显示文本带有<a..之类的链接
1232 			var cls = eobj[0].className;
1233 			if(cls.length>0 && !cls.startsWith('bbox-')) return;
1234 			if(e.type=='click'){
1235 				var pos = eobj.position();
1236 				pos.left += eobj.outerWidth() - 20;
1237 				if(e.pageX < pos.left) return;//表示鼠标不是点击在×字符上
1238 				Sucang.browser.removeItem.call(Sucang.browser, eobj, inputId);
1239 				
1240 			}else if(e.type=='mouseover'){
1241 				Sucang.browser.Over(eobj[0], 1);
1242 			}else{//mouseout
1243 				Sucang.browser.Out(eobj[0], 1);
1244 			}
1245 		});
1246 	}
1247 	/*
1248     var pageSize = 2;
1249     var keyId = 'id';
1250     var key = 'name';//搜索匹配的关键词字段
1251     var val = "";//输入的值
1252     var arFields = ["id","name","old_station","station","old_orgid","orgid","telphone",
1253     	"old_hrstatus","hrstatus","secureLevel","modifydate","old_superior","superior"];
1254 	var sUrl='/formquery.do?action=json&isUnread=&isDraft=&id=4028b8815505851e015505c647c90011';
1255 	*/
1256 	var listEl = $(Ext.DomHelper.append(document.body, {tag: 'div', style: 'left: 0px; top: 0px',
1257 		cls: 'x-layer x-combo-list sc-autolist',
1258 		html: '<div tabindex="' + Math.ceil(Math.random()*899+100) + '" class="x-combo-list-inner sc-autowrap"></div>' +
1259 			 '<div class="sc-autopage"></div>'
1260 		}));
1261 	
1262 	this.store = new Ext.data.JsonStore({
1263 	    autoDestroy: true,
1264 	    url: sUrl,
1265 	    root: 'rootData',
1266 	    idProperty: 'id',
1267 	    totalProperty: 'totalCount',
1268 	    fields: arFields
1269 	});
1270 	this.store.proxy.on('loadexception', Sucang.Grid.storeLoadException);
1271 	this.store.on('load', function(st, recs, opt){
1272 	    	this.itemIndex = 0;
1273 			this.view.select(0, false, true);
1274 			var pd = pageBar.getPageData();//如果只有一页则隐藏页码
1275 			listEl.find('.sc-autopage')[ pd.pages==1 ? 'hide' : 'show' ]();
1276 			
1277 			if(!isMulti) return;
1278 			var ids = Sucang.browser.getValue(inputId);
1279 			if(Sucang.isEmpty(ids)) return;
1280 			for(var i = 0; i < recs.length; i++){
1281 				if(ids.indexOf(recs[i].get(keyId))<0) continue;
1282 				this.view.getNode(i).className += ' x-item-disabled';
1283 			}
1284 	    } //end.load
1285 	, this);
1286 	
1287 	this.view = new Ext.DataView({
1288 		store: this.store,
1289 		applyTo: listEl.find('.sc-autowrap')[0],
1290 		tpl: '<tpl for="."><div class="'+cls+'-item">{' + key + '}</div></tpl>',
1291 		singleSelect: true,
1292 		selectedClass: 'x-combo-selected',
1293 		itemSelector: '.' + cls + '-item',
1294 		emptyText: '当前数据为空',
1295 		deferEmptyText: false,
1296 		listeners:{'dblclick': function(v, index, node, e){
1297 				if(isMulti && node.className.indexOf('x-item-disabled')>=0) return;
1298 				this.itemIndex = index;
1299 				_doSelected.call(this, e);
1300 			}, 'selectionchange': function(vw, rec){
1301 				this.itemIndex = vw.getSelectedIndexes()[0];
1302 				//console.log('rec:'+rec.length+",item:"+this.itemIndex);
1303 			}, scope:this}
1304 	});
1305 
1306 	var pageBar = new Ext.PagingToolbar({
1307         store: this.store,
1308         applyTo: listEl.find('.sc-autopage')[0],
1309         displayInfo: false, //'共{2}条',
1310         pageSize: pageSize
1311     });
1312     var _prePage = function(e){
1313     	var d = pageBar.getPageData();
1314     	if(d.activePage<=1) return;
1315     	pageBar.changePage(d.activePage - 1);
1316     	this.itemIndex = 0;
1317     };
1318     var _nextPage = function(e){
1319     	var d = pageBar.getPageData();
1320     	if(d.activePage>=d.pages) return;
1321     	pageBar.changePage(d.activePage + 1);
1322     	this.itemIndex = 0;
1323     };
1324     
1325     var _tpl = null;
1326     var _viewTpl = new Ext.XTemplate(viewText || '{' + key + '}');
1327     
1328     //console.log('params----'+elBtn.attr('data-params'));
1329     
1330 	if(elBtn.length>0){
1331 		var objParams = elBtn.data('params');
1332 		//console.log('-----withjson-----'+Ext.encode(objParams.__WITHJSON));
1333 		if(objParams && objParams.__WITHJSON){
1334 			_tpl = new Ext.XTemplate(Ext.encode(objParams.__WITHJSON));
1335 		}
1336 	}
1337     var _doSelected = function(e){
1338 		//console.log('enter-----itemIndex:'+this.itemIndex);
1339 		var rec = this.store.getAt(this.itemIndex);
1340 		if(!rec) return;
1341 		var ar = [rec.get(keyId), _viewTpl.apply(rec.data)];
1342 		if(_tpl) ar.push(_tpl.apply(rec.data));
1343 		Sucang.browser[isMulti ? 'addValue' : 'setValue'](inputId, ar, true);//最后一个参数true表示在setValue时不执行后处理函数
1344 		if(isMulti){//多选时不执行回调函数和数据接口,因为用的addValue()方法
1345 			_showView();
1346 			$(this.view.getNode(this.itemIndex)).addClass('x-item-disabled');
1347 		}else{
1348 			Sucang.browser.dataInterface(ar, inputId, true);//最后一个函数表示执行数据接口(如果存在的话)后继承执行回调函数
1349 			this.hide();
1350 		}
1351     };
1352 	var keyNav = new Ext.KeyNav(this.view.el, {
1353             "up" : function(e){
1354                 //console.log('up-----itemIndex:' + this.itemIndex);
1355                 if(this.itemIndex==0){//表示往上直接到输入框焦点
1356                 	this.itemIndex = null;
1357                 	el[0].focus();
1358                 }else this.itemIndex -= 1;
1359 				this.view.select(this.itemIndex, false, true);
1360             },
1361             "down" : function(e){
1362                 //console.log('down-----itemIndex:' + this.itemIndex);
1363                 this.itemIndex += 1;
1364                 if(this.store.getCount() == this.itemIndex) this.itemIndex = 0;
1365 				this.view.select(this.itemIndex, false, true);
1366             },
1367             "enter" : function(e){
1368             	var row = this.view.getNode(this.itemIndex);
1369             	if(row && $(row).hasClass('x-item-disabled')) return;
1370             	_doSelected.call(this, e);
1371             },
1372             left:_prePage,
1373             pageUp:_prePage,
1374             right:_nextPage,
1375             pageDown:_nextPage,
1376             "esc" : function(e){
1377                 this.hide(true);
1378                 
1379             },
1380             scope: this
1381 	});
1382 	var viewH = listEl.outerHeight();
1383 	var viewW = listEl.outerWidth();
1384 	var _showView = function(){
1385 		var bodyH = document.documentElement.clientHeight;
1386 		var bodyW = document.documentElement.clientWidth;
1387 		var xy = el.position();
1388 		if((xy.top + viewH) > bodyH){//表示底部超出了
1389 			var tt = xy.top - viewH;
1390 			if(tt > 0) xy.top = tt;
1391 			else xy.top += el.height();
1392 			
1393 		}else xy.top += el.height();
1394 		
1395 		if((xy.left + viewW) > bodyW){//表示右边超出了
1396 			xy.left -= viewW;
1397 		}
1398     	listEl.css('visibility', 'visible').css('left', xy.left + 'px').css('top', xy.top + 'px');
1399 	};
1400     this.hide = function(focus){
1401     	this.view.el.update('');
1402     	listEl.css('visibility', 'hidden');
1403     	if(focus) el[0].focus();
1404     };
1405     this.itemIndex = null;
1406     var opt = {params:{start: 0, limit: pageSize}};
1407     this.query = function(v){
1408     	//console.log('query key:' + v + ",otp:" + Ext.encode(opt));
1409     	if(!v || Ext.isEmpty(v.trim())) return this.hide();
1410     	var pa = elBtn.attr('data-params');
1411     	if(pa){
1412     		pa = Ext.decode(pa);
1413 			if(pa.__WITHJSON) delete pa.__WITHJSON;
1414 		}else pa = {};
1415 		pa[key] = v;
1416 		this.store.baseParams = pa;
1417 		//this.store.setBaseParam(key, v);
1418 		opt.params[key] = v;
1419     	this.itemIndex = null;
1420     	//console.log("post params:" + Ext.encode(this.store.baseParams));
1421     	_showView();
1422 		this.store.load(opt);
1423 	};
1424 	var isCtrl = 0;//用于IE8下的keydown事件和inputChange事件重复导致,方向键和回车也会执行inputChange回调中的query()方法
1425 	
1426 	var enabled = true;
1427 	var precall = el.data('precall');
1428 	if(!Sucang.isEmpty(precall)){//判断是否有预处理函数
1429 		enabled = false;
1430 		precall = new Function("btn", "return " + precall + "(btn);");
1431 		el.on('focus', function(e){
1432 			if(enabled) return;
1433 			enabled = precall(elBtn[0]);
1434 			if(!enabled) elBtn[0].focus(); //需要设置别的元素为焦点,不然alert完了以后el会重复获得焦点,导致死循环
1435 			
1436 		}).on('blur',function(e){
1437 			enabled = false;
1438 		});
1439 		
1440 	}
1441 	
1442 	Ext.EventManager.on(el[0], 'keydown', function(e){
1443 		if(!enabled) return;
1444 		var count = this.store.getCount() - 1;
1445 		var key = e ? e.getKey() : 0;
1446 		if(key!=27 && count<0) return;//小于0表示查询数据记录为空,则直接返回
1447 		isCtrl = 0;
1448 		var target = e.getTarget();
1449 		if(key==40){//表示向下方向键
1450 			isCtrl = key;
1451 			this.view.focus();
1452 			var n = this.itemIndex;
1453 			if(n==null) n = 0;
1454 			else if(count==n){
1455 				return;
1456 			}else n += 1;
1457 			this.view.select(n, false, true);
1458 			this.itemIndex = n;
1459 		}else if(key==38){//表示向上方向键
1460 			isCtrl = key;
1461 			this.view.focus();
1462 			this.itemIndex = count;
1463 			this.view.select(count, false, true);
1464 		}else if(key==27){//表示esc取消键
1465 			isCtrl = key;
1466 			this.hide();
1467 		}else if(key==13){//表示回车
1468 			var row = this.view.getNode(this.itemIndex);
1469             if(row && $(row).hasClass('x-item-disabled')) return;
1470 			isCtrl = key;
1471 			_doSelected.call(this);
1472 		}
1473 	}, this);
1474 	Sucang.util.inputChange(el[0], function(obj, oriValue, newValue){
1475 		if(!Ext.isIE8 || Ext.isIE8 && isCtrl==0) this.query(newValue);
1476 	}, 500, this);
1477 };
1478 Sucang.autocomplete = {
1479 	_els : {},
1480 	_init : function(wrap){
1481 		if(Sucang.formular && !Sucang.formular._inited){//浏览框带出的参数初始化需要依赖于Sucang.formular初始化,所以这里要作延迟处理
1482 			setTimeout(function(){
1483 				Sucang.autocomplete._init.call(Sucang.autocomplete);
1484 			}, 100);
1485 			return;
1486 		}
1487 		var that = this;
1488 		if(!wrap) wrap = $(document.body);
1489 		else if(wrap instanceof jQuery);
1490 		else wrap = $(wrap);
1491 		wrap.find('input[data-auto]').each(function(){
1492 			var el = $(this).closest($.AdminLTE ? 'div' : 'span');
1493 			var inputid = this.id.substring(0, this.id.length - 3);
1494 			var isEmptyValue = Ext.isEmpty($('#' + inputid).val());
1495 			if(isEmptyValue && !el.hasClass('browserInput')){//如果浏览框的值为空且非输入状态的,则需要修改class使变成可输入
1496 				el.removeClass('browser').addClass('browserInput'); 
1497 			}
1498 			that._els[inputid] = new Sucang.autoComplete(inputid, this);
1499 		});
1500 	}
1501 };
1502 
1503 Ext.onReady(function(){
1504 	if(!Sucang.isEmptyObject(Ext.QuickTips)) Ext.QuickTips.init();
1505 	//Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
1506 	initLinkOpenTab();
1507 	Sucang.autocomplete._init();
1508 });