项目中的pickupwindows原理大揭秘

今天潜心认真学习项目中的js框架,发现老李确实是个牛人,架构师就是架构师,确实是个JS牛人。

其中的

eval(String str)其中只能使用str字符串,不能使用对象。

eval("win._frame.contentWindow."+idMethod+"()"
不理解,win._frame指的是本窗口对象?应该是这个意思。

废话不多说,还是先上代码       shit

子页面代码如下:

t-qualification.vm

<head>
#import(["jquery","dwr","xTree"])
<script type="text/javascript" >
function initTreeStyle(){
	tree.enableRadioButtons(true);
    tree.enableSingleRadioMode(true, "0");
}

function initTreeData(){
	tree.showItemCheckbox(null,1);
	var children = tree.getAllItemsWithKids();
    var items = children.split(",");
    for(i=0;i<items.length;i++){
    	tree.showItemCheckbox(items[i],0);
    }
    tree.closeAllItems();
}

function getSelectedId(){
	return jQuery("#selectedId").val();
}

function getSelectedName(){
	return jQuery("#selectedName").val() + "-" + getSearchType();
}

function getSearchType(){
	return jQuery(":radio:checked").val();
}

function setSelected(){
	if(tree.getAllChecked()==""){
		alert("请先选择");
		return false;
	}
	var searchType = $(":radio:checked").val();
	var id = tree.getAllChecked();
	jQuery("#selectedId").val(id);
	jQuery("#selectedName").val(tree.getItemText(id));
	parent.dhxWins.window("gw").close();
}

function clearSelected(){
	jQuery("#selectedId").val("");
	jQuery("#selectedName").val("");
	alert(parent.dhxWins.window("gw").getText());
	parent.dhxWins.window("gw").close();	
}

function searchTree(){
	if(jQuery("#searchText").val()!=""){
    	var findItem = tree.findItemIdByLabel(jQuery("#searchText").val(),0,0);
		if(findItem!=null){
			tree.focusItem(findItem);
			tree.selectItem(findItem,false,true);
		}
	}
}
$(function(){
	var qualType = $("#qualType").val();
	if(qualType == ""){
		$("#selectTypeDiv").css("display","none");
	}
});
</script>
</head>
<body>
<div id="div-content">
<input type="hidden" id="selectedId">
<input type="hidden" id="selectedName">
<input type="hidden" id="qualType" value=$!qualType >
<div style="margin:0 0 5px 10px;"><input type="text" id="searchText"><input type="button" class="operainput" value="搜索" οnclick="searchTree()"/></div>
<div style="height:90%;" id="tree" name="tree" data="{xTree:{content:'dwr,getQualificationTree'}}" component="xTree"></div>
</div>
<div id="div-opera">
	<input type="button" class="operainput" value="确定" οnclick="setSelected()">
	<input type="button" class="operainput" value="取消" οnclick="clearSelected()">
</div>
</body>


XTree.js

var parentId;
function xTree(source,metadata){
	alert("XTREE");
	var content = metadata.content.split(",");
	if(content[0]=="dwr"){
		parentId = source.attr("id");
		if(!parentId){
			parentId = "treebox_tree";
			source.attr("id",parentId);
		}
		var params = "";
		if(content.length>2){
			for(i=2;i<content.length;i++){
				params += "'"+content[i]+"',";
			}
		}
                //调用dwr函数DWRService里面的方法
                eval("_ajax."+content[1]+"("+params+"{callback:callbackFunc});");
	}
	
}
//回调函数,处理xml展示的问题,注意,这里的回调是dwr的回调函数,为了显示树用的。呵呵
var tree;
function callbackFunc(xml){
	alert(xml);
	tree = new dhtmlXTreeObject(parentId, "100%", "100%", 0); 
    tree.setSkin('dhx_skyblue');
    tree.setImagePath("/js/xTree/imgs/csh_yellowbooks/");
    //tree.enableSmartCheckboxes(1);
    try{
    	initTreeStyle();
    }catch(e){
    }
	tree.loadXMLString(xml);
	try{
		initTreeData();
	}catch(e){
	}
}


主页面的代码如下

t-qualification-main-add.vm

<head>
#import(["jquery","validate","#component","xDate","upload","pickupWindows","dwr"])
<script type="text/javascript">

function saveSubmit(){
	//校验附件
	var attsList = document.getElementsByName('attachids');
	if(attsList.length==0){
		alert("请上传资格证书扫描件.");
		return;
	}
	//提交
	jQuery("#editForm").submit();
}

function addDetail(){
	if("$!_M.mainId"==""){
		alert("请先保存主项资质,然后再添加增项资质");
		return;
	}
	document.location.href="$base/t-qualification-add!edit.do?mainId=$!_M.mainId&enterpriseId=$!_M.enterpriseId";
}


function setRange(id,name){
	//设值
	jQuery("#typeLevel").val(id);
	var array = name.split("-");
	jQuery("#qualificationMainName").val(array[0]);
	//重置范围
	var level = jQuery("#typeLevel").val();
	if(level!=null&&level!=""){
		//清空范围
		jQuery("#businessRange").val('');
		_ajax.getCQualification(level,{
    		callback:function(qual){
    			if(qual!=null){
    				jQuery("#businessRange").val(qual.scope == null? "":qual.scope);
    			}
    		}
    	});
	}
}


var oldPauseReason = "$!_M.pauseReason";
jQuery(function(){
	jQuery("#preview").click(function(){
		window.open("/admin-qual-preview!preview.do?mainId=$!_M.mainId","代码证预览", "toolbar=no,location=no,directories=no,menubar=no,scrollbars=no,resizable=no,status=no, width="+screen.availWidth+",height="+screen.availHeight);
	});
	
	//暂停业务模块,控制显示暂停原因问题
	jQuery(":radio[name='_M.pause']").click( function() {
	   if(this.id == "pauseRadio"){
	   	 jQuery("#pauseReason").removeAttr("readonly").val(oldPauseReason);
	   }else {
		 jQuery("#pauseReason").val("").attr("readonly","readonly");
	   }
	});
});

function getCertificateNoMessage(){
	var message = "该证书在系统中已经存在!";
	jQuery.ajax({
		method:'post',
		url:'$base/t-qualification-main!getCertificateNoMessage.do',
		data:{
			mainId:"$!_M.mainId",
			certificateNo:jQuery("#certificateNo").val()
		},
		async:false,
		success:function(response){
			message = response;
		},
		error:function(data){
			message = "该证书在系统中已经存在!";
		}
	});
	
	return message;
}
</script>
</head>
<div id="div-title">
    <div id="title"><span>主项资质</span></div>
</div>
<form id="editForm" name="editForm" action="${defaultSaveUri}" validate="true" method="post">
<input type="hidden" name="_M.enterpriseId" value="$!_M.enterpriseId">
<input type="hidden" name="enterpriseId" value="$!enterpriseId">
<input type="hidden" name="_M.mainId" value="$!_M.mainId">
<div id="div-content">
	<table id="form-table" class="formtable" >
		<tr>
		  <!--
			<td class="nametd">行业类型</td>
            <td>
				<select name="_M.industryType" id="industryType" value="$_M.industryType" data="{v:{required:true}}">
					<option value="$!tl.uuid">--请选择--</option>
					#foreach($tl in $tradeList)
            	   		<option value="$!tl.uuid" #if($tl.uuid==$_M.industryType) selected='selected' #end>$!tl.name</option>
            	 	#end
				</select>
			</td>
			-->
			<td width="17%" class="nametd">资质类别及等级</td>
            <td width="33%">
				<input type="hidden" name="_M.typeLevel" id="typeLevel" value="$!_M.typeLevel" data="{v:{required:true}}"/>
				<input type="text" id="qualificationMainName" value="$!qualification.name" component="pickupWindows"
					data="{pickupWindows:{callbackFunc:'setRange',url:'${base}/pickup-windows!qualification.do',windowName:'资质类别及等级选择',targetId:'typeLevel',targetName:'qualificationMainName',width:'450'}}"/>
			</td>
			<td class="nametd">证书编号</td>
			<td><input type="text" name="_M.certificateNo" id="certificateNo" value="$!_M.certificateNo" 
			data="{v:{required:true,maxlength:30,gboatremote:{url:'$base/t-qualification-main!checkCertificateNo.do?mainId=$!_M.mainId',noCheckValue:'$!_M.certificateNo',cache:false,messages:{gboatremote:getCertificateNoMessage}}}}"/></td>
		</tr>
		<tr>
			<td class="nametd">发证机关</td>
			<td><input type="text" name="_M.certificateIssuer" id="certificateIssuer" value="$!_M.certificateIssuer" data="{v:{required:true,maxlength:60}}"/></td>
			<td class="nametd">发证时间</td>
			<td><input type="text" name="_M.certificateDate" id="certificateDate" value="$!_M.certificateDate" data="{v:{required:true},xDate:{format:'yyyy-MM-dd'}}" component="xDate"/></td>
		</tr>
		<tr>
			<td class="nametd">资质有效期始</td>
			<td><input type="text" name="_M.validStartDate" id="validStartDate" value="$!_M.validStartDate" data="{v:{required:true},xDate:{format:'yyyy-MM-dd'}}" component="xDate"/></td>
			<td class="nametd">资质有效期至</td>
			<td colspan="3"><input type="text" name="_M.validDate" id="validDate" value="$!_M.validDate" data="{v:{required:true, compareDateGreater:['validStartDate','有效期至时间必须大于有效期始']},xDate:{format:'yyyy-MM-dd'}}" component="xDate"/></td>
		</tr>
		#if("$!role" == "E")
			<tr>
				<td class="nametd">资质状态</td>
				<td colspan="3">
						#if("$!_M.mainId" == "")
							正常
						#elseif("$!_M.pause" == "Y")
							暂停资质
							#if("$!_M.pauseReason" != "")
							      暂停原因:$!_M.pauseReason
						    #end
						#elseif("$!_M.validDate"!="" && $date.toDate($date.systemDate).after($date.toDate($!_M.validDate)))
							过期
						##"2592000000"--指的是天数(30)对应的毫秒数
						#elseif("$!_M.validDate"!="" && $date.toDate($date.systemDate).before($date.toDate($math.sub($!_M.validDate.getTime(), $!math.mul($!warn.enterQualDate, 86400000)))))
							正常
						#else
							即将过期
						#end
				</td>
			</tr>
		#end
		#if("$!role" == "E")
			<input type="hidden" name="_M.pause" #if("$!_M.pause" == "") value="N" #elseif("$!_M.pause" != "") value="$!_M.pause" #end  />
		    <input type="hidden" name="_M.pauseReason" value="$!_M.pauseReason" />
		#end
		#if($priority.havePriority($request,"$!{resourceCode}.stop_cert"))
			<tr>
				<td class="nametd">是否暂停业务</td>
				<td colspan="3">
					<input type="radio" name="_M.pause" #if("$!_M.pause" == "N" || "$!_M.pause" == "") checked #end value="N" style="width:20px;border-width:0px;vertical-align:middle" /> 否  <input  id="pauseRadio"  type="radio" name="_M.pause" value="Y" #if("$!_M.pause" == "Y") checked #end style="width:20px;border-width:0px;vertical-align:middle"/> 是
					<br/>暂停原因:<br/>
					<textarea name="_M.pauseReason" id="pauseReason" #if("$!_M.pause" == "N" || "$!_M.pause" == "") readonly #end data="{v:{maxlength:1000}}"/>$!_M.pauseReason</textarea>
				</td>	
			</tr>
		#end
		<tr>
			<td class="nametd">可承担业务范围</td>
			<td colspan="3"><textarea name="_M.businessRange" id="businessRange" data="{v:{maxlength:1300}}">$!_M.businessRange</textarea></td>
		</tr>
		<tr>
			<td class="nametd">资格证书扫描件<span style="color:red">*</span><br><input type="hidden" data="{v:{attachment:'资质证书'}}"/></td>
			<td colspan="3">#attsvaild("editForm" $!atts)</td>
		</tr>
	</table>
	
	<div class="listtitle">
		<span class="right">
		      <a href="#" οnclick="addDetail()">添加增项资质</a>
	    </span>
        <h2>增项资质</h2>
	</div>
	<table id="list-table" class="listtable" border="0"  rules="none">
		<thead>
			<tr>
				<td>序号</td>
				<td>资质类别及等级</td>
				<td>操作</td>
			</tr>
		</thead>
		#foreach($item in $adds)
		<tr>
			<td>$velocityCount</td>
			<td>$!item.name</td>
			<td>
				<a id="editlink" class="operalink" href="$base/t-qualification-add!edit.do?SID=$item.addId&mainId=$item.mainId&enterpriseId=$!_M.enterpriseId" οnclick="">编辑</a>
				<a id="dellink" class="operalink" href="$base/t-qualification-add!delete.do?SID=$item.addId&mainId=$item.mainId&enterpriseId=$!_M.enterpriseId" οnclick="">删除</a>
			</td>
		</tr>	
		#end
	</table>
</div>
<div id="div-opera">
	<input type="submit" class="operainput" id="saveBt" name="saveBt" value="保存" οnclick=""/>
	<input type="button" class="operainput" id="returnBt" name="returnBt" value="返回" οnclick="#back("${defaultListUri}?enterpriseId=$!enterpriseId")"/>
	#if("$!_M.mainId" != "")
		<input type="button" class="operainput" id="preview" name="previewBt" value="#if("$!roleCode"=="E")查看#else审核#end" />
	#end
</div>
</form>


pickupwindow.js

var dhxWins;
var message;
function showAlert(alertMessage){
	message = alertMessage;
	dhxWins = new dhtmlXWindows();
	dhxWins.enableAutoViewport(true);
    dhxWins.attachViewportTo("winVP");
    dhxWins.setImagePath("imgs/");
    dhxWins.setEffect("maximize", false);
    dhxWins.attachEvent("onContentLoaded",doOnContentLoader);
    gw = dhxWins.createWindow("gw", 0, 0, 450, 300);
    gw.setText("系统信息");
    gw.setModal(false);
    gw.centerOnScreen();
    gw.attachURL("./alertWindow.html");
}

function doOnContentLoader(win){
	//alert(win);
	win._frame.contentWindow.showAlertMessage(message);
}
//这是核心的显示程序,所有的弹出页面都是这个函数实现的
function showModalWindow(windowName,url,callback,width,height){
	if(url.indexOf("rdm=")==-1){
		if(url.indexOf("?")==-1){
			url += "?rdm="+Math.random();
		}else{
			url += "&rdm="+Math.random();
		}
	}
	dhxWins = new dhtmlXWindows();
	dhxWins.enableAutoViewport(true);
    dhxWins.attachViewportTo("div-content");
    dhxWins.setImagePath("/comp/xWindows/imgs/");
    if(callback==undefined||callback==""){
    	callback = defaultCallback;
    }
    dhxWins.attachEvent("onClose",callback);//定义弹出窗口关闭时的回调函数,首先会调用最下面的那个函数callbackFunc(win)
    dhxWins.setEffect("resize", false);
    dhxWins.setEffect("max", false);
    maxwidth = jQuery(document).width();
    if(width==undefined||width==""||maxwidth<width){
    	width = maxwidth;
    }
    maxheight = jQuery(document).height();
    if(height==undefined||height==""||maxheight<height){
    	height = maxheight;
    }
    //定义窗口的名字
    gw = dhxWins.createWindow("gw", 0, 0, width, height,{});
    gw.setText(windowName);
    gw.setModal(true);
    gw.denyMove();
    gw.centerOnScreen();
    gw.attachURL(url);
    gw.button("minmax1").hide();
    return gw;
    //alert(win._frame);
}
//主要还是间接的调用了上面的核心函数showModalWindow
function showWindowOnTop(window,url,callback,width,height){
	if(callback=="")
		 callback="''";
	if(typeof(top.showModalWindowOnTop)=="function"){
		eval("top.showModalWindowOnTop('"+window+"','"+url+"',"+callback+",'"+width+"','"+height+"');");
	}else{
		eval("showModalWindow('"+window+"','"+url+"',"+callback+",'"+width+"','"+height+"');");
	}
}
//默认的回调函数的写法,其中的return true表明窗口关闭,只要return true 则弹出窗口就能够自动关闭
function defaultCallback(){
	return true;
}

function closeModalWindow(o){
	if(o){
		o.dhxWins.window("gw").close();
	}else{
		parent.dhxWins.window("gw").close();
	}
}

//这是弹出框的前期操作准备,尤其去调用下面的的showWindowInPickupWindow
var md;
function pickupWindows(source,metadata){
    var url = metadata.url;
    if(!url){
        showAlert("未设置打开的连接");
        return;
    }
    var windowName = metadata.windowName;
    if(!windowName){
        windowName = "请选择";
    }
    var width = metadata.width;
    if(!width){
        width = 600;
    }else if(width=="max"){
        width = jQuery(document).width();
    }
    var height = metadata.height;
    var maxheight = jQuery(document).height();
    if(!height){
        if(maxheight>500){
            height = 500;
        }else{
            height = maxheight;
        }
    }else if(height=="max"){
        height = maxheight;
    }else if(height>maxheight){
        height = maxheight;
    }
    
    var randId = Math.round(Math.random()*10000)+"";
    //存放数据,建立一个唯一的id,以便右面的默认的callbackFun的调用,呵呵,终于明白了。
    jQuery(document).data(randId,metadata);//此处是设置值,把主页面的值如targetId,targetName,callbackFun等等的值都放到里面
    md = metadata;
    //alert(source.attr("tagName")+","+source.attr("type"));
    if((source.attr("tagName")=="INPUT"&&source.attr("type")=="text")||source.attr("tagName")=="TEXTAREA"){
        source.after("<input type=\"button\" class=\"showinput\" value=\"...\" οnclick=\"showWindowInPickupWindow('"+randId+"','"
                +windowName+"','"+url+"',"+width+","+height+")\">");
        if(metadata.targetName){
            jQuery("#"+metadata.targetName).attr("readonly",true);
        }
    }else if(source.attr("tagName")=="INPUT"&&source.attr("type")=="button"){
        source.bind("click",function(event){
            showWindowInPickupWindow(randId,windowName,url,width,height);
        });
    }else if(source.attr("tagName")=="A"){
        source.attr("href","#");
        source.bind("click",function(event){
            showWindowInPickupWindow(randId,windowName,url,width,height);
        });
    }
}

function showWindowInPickupWindow(id,windowName,url,width,height){
    //读取弹出页面的参数
    var params = "";
    try{
        params = getParamsForPickupWindow();
    }catch(e){
    }
    if(params.length>0){
        if(url.indexOf("?")==-1){
            url += "?"+params;
        }else{
            url += "&"+params;
        }
    }
    var modWindow = showModalWindow(windowName+"-"+id,url,callbackFunc,width,height);
}

//很专业,只要是窗口关闭都会自动触发这个函数。所以很重要
function callbackFunc(win){
    alert("call back windows");
    var splited = win.getText().split("-");//这个是在构建模态窗口的时候设值进去的
    alert(splited);
    if(splited.length>0){
        //获取之前放入的metadata对象,splited[splited.length-1]则是pickupwindows中的randId,根据这个ID获取metadata的对象数组。
        md = jQuery(document).data(splited[splited.length-1]);
    }
    //前面三个都是能够获取到值得,后面两个是undifined,但是后面会给它设置值的。
    alert(md.callbackFunc+","+md.targetId+","+md.targetName+","+md.selectIdMethod+","+md.selectNameMethod);
    if(!md.callbackFunc&&(!md.targetId||!md.targetName)){//这三个值必须从原先的主页面带过来,要不然无法设值。
        alert("系统错误,请和管理员联系!");
    }else{
        var idMethod = "getSelectedId";
        if(md.selectIdMethod){
            idMethod = md.selectIdMethod;
        }
        var nameMethod = "getSelectedName";
        if(md.selectNameMethod){
            nameMethod = md.selectNameMethod;
        }
        var selectedId="",selectedName="";
        try{
            //动态调用子页面上的函数
            selectedId = eval("win._frame.contentWindow."+idMethod+"()");
            //alert("id selected : "+selectedId);
        }catch(e){
        }
        
        try{   

            //动态调用子页面上的函数

            selectedName = eval("win._frame.contentWindow."+nameMethod+"()");
            //alert("name selected : "+selectedName);
        }catch(e){}
        //调用主页面上的回调函数
        if(md.callbackFunc){
            eval(md.callbackFunc+"('"+selectedId+"','"+selectedName+"');");
        }else{
            settedId = document.getElementById(md.targetId);
            settedName = document.getElementById(md.targetName);
            if(!settedId){
                alert("ID["+md.targetId+"]不存在,无法设值!");
            }else{
                jQuery("#"+md.targetId).val(selectedId);
            }
            if(!settedName){
                alert("NAME["+md.targetName+"]不存在,无法设值!");
            }else{
                var tagtype = jQuery("#"+md.targetName).attr("tagName");
                if(tagtype=="INPUT"||tagtype=="textarea"){
                    jQuery("#"+md.targetName).val(selectedName);
                }else{
                    jQuery("#"+md.targetName).text(selectedName);
                }
            }
        }
        //alert(selectedId+" --> "+selectedName);
    }
    return true;//只有return true 才能关闭这个弹出窗口
}












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值