优秀的编程知识分享平台

网站首页 > 技术文章 正文

easyUi内嵌iframe时,弹出对话框被遮挡问题

nanyue 2024-08-10 18:45:05 技术文章 7 ℃

这是多年以前用传统JQuery(easyUi)做项目时遇到的问题,今天把解决思路发布出来,也许能帮助到还在使用老架构的同学。

在开发类ERP的后台管理系统时,经常会看到这样的布局结构


每打开一个菜单都是单独打开一个Tab页,easyUi打开Tab页有两种方式:

  • 动态增加iframe
  • 在同一个Dom树中增加div 的方式

同一Dom树中存在命名污染的问题,包括样式也会互相影响,新增加页面里的样式很可能影响原有页面的布局

因此我们采用iframe的方式实现:

function addTab(subtitle,url,icon,closable){
	if(!$('#tabs').tabs('exists',subtitle)){
		$('#tabs').tabs('add',{
			title:subtitle,
			content:createFrame(url),
			closable:(closable==null?true:closable),
			icon:icon,
			fit:true
		});
	}else{
		$.messager.confirm('提示',eship.messages.updateTab,function(r){  
			if (r){    
				$('#tabs').tabs('select',subtitle);
				var currTab = $('#tabs').tabs('getSelected');
				$('#tabs').tabs('update',{
					tab:currTab,
					options:{content:createFrame(url)}
				});
			}
		});
	}
	tabClose();
}

function createFrame(url){
	var s = '<iframe scrolling="auto" frameborder="0"  src="'+url+'" style="width:100%;height:99%;"></iframe>';
	return s;
}

我们在使用时iframe Tab页时,页面中经常会有打开对话框的需求。

因为我们采用了iframe的方式,其实打开对话框是在子页面的iframe的dom中打开的,因此会被主页面遮挡,如图所示:


对话框移动过程中会被Tab标签遮挡,并且无法继续向上移动,并且不同iframe传递参数也比较麻烦,不是很方便,因此决定进行封装,基本原理如下:

封装模态对话框插件

  1. 判断是否在最顶层dom中执行,如果不在获取到顶层dom对象
  2. 在最顶层iframe中自动增加一个div,并通过这个div打开模态对话框
  3. 用堆栈记录打开对话框的相关属性options
  4. 关闭时,依次调用堆栈中的对话框,并关闭

优点:

  1. 增加getDialogOption方法,可方便获取当前对话框的option对象,可以方便的通过该对象进行窗口之间的值传递。
  2. 在关闭时,增加回调方法,可以在关闭时方便的调用父窗体的回调方法。
/**
 * jQuery dialog
 * 
 * @author rogerkuo
 * 
 * easy ui 对话框扩展,自动创建DIV,并将DIV放置在最顶层DOM中,避免对话框被iframe覆盖的情况
 */
(function($) {
	$.joyplus = function(){};
	$.joyplus.messager = function(){};
	
	//私有方法,用来负责创建对话框
	function _joy_show(options) {
		var defaults = {
			width : 800,
			height : 500,
			title : 'My Dialog',
			modal : true,
			onLoad : function(){
				var topDiaOptions = $.joyplus.getDialogOption();
				if( topDiaOptions.dialogId != undefined){//如果需要处理对话框连续弹出问题时,对焦点进行处理
					var topBody = _joy_get_top_body();
					var ele = $(topBody).find("#" + $.joyplus.getModelDialogId());
					var inputs = $(ele).find("input");
					if( inputs.length > 0 ){
						inputs[0].focus();
					}
				}
			}
			//dialogId : ""用来判断是否同一窗体,避免同一个业务多次弹出一个对话框,造成对话框堆叠,如果没有,不作处理
		};

		var isString = (typeof options == "string");
		if (isString) {
			options = {};
		}
		
		var d = {};
		
		$.extend(d , options);
		
		var topDiaOptions = $.joyplus.getDialogOption();
		
		if( topDiaOptions != undefined && topDiaOptions.dialogId != undefined &&  topDiaOptions.dialogId == d.dialogId ){

			return;
		}
		
		var isDataFunction = false;
		//新增dialog传值基础功能,可调用父窗体的方法,获取附加数据
		if( jQuery.type(d.extdata) == "function"){
			isDataFunction = true;
			d.extdata = d.extdata.call(this);
		}
		//新增dialog传值grid功能
		if( jQuery.type(d.grid) == "function"){
			isDataFunction = true;
			d.grid = d.grid.call(this);
		}
		if(!isDataFunction){
			d = $.extend(d , options);
		}
		

		_joy_get_options_cache().push(d);

		var opt = $.extend(defaults, options);

		opt.onClose = $.joyplus.closeModelDialog;

		var id = _joy_create_div();
		var top = _joy_get_top_body();

		var element = $(top).find("#" + id);
		$(element).dialog(opt);
		
	};

	//获取最上层的dialog对象
	function _joy_get_top_dialog() {
		var stack = _joy_get_dialog_stack();
		return stack.pop();
	};

	//获取对话框堆栈,因为用户可以在对话框上继续点开对话框,因次要记录对话框堆栈
	//先进后出
	function _joy_get_dialog_stack() {
		var top = _joy_get_cahce();
		return top;
	};

	//自动创建div,在dom的最顶层创建
	function _joy_create_div() {

		var new_id = _joy_get_new_id();
		var stack = _joy_get_dialog_stack();
		stack.push(new_id);
		$(_joy_get_top_body()).last().append("<div id='" + new_id + "'></div>");
		return new_id;
	};

	function _joy_get_top_body() {
		var top = window.parent.document.body;
		return $(top)
	};

	function _joy_get_cahce() {
		var a = window.top.$.fn._cache;
		return a;
	};

	function _joy_get_options_cache() {
		return window.top.$.fn._options_cache;
	};

	function _joy_get_new_id() {
		var date = new Date();
		return date.getTime().toString();
	};

	$.joyplus.showModelDialog = function(options , ifr) {
		if( ifr ){
			_joy_show(options);
		}
		else{
			//如果是最顶层的iframe
			if (window.top == window) {
				_joy_show(options);
			} else {//如果不是最顶层的iframe,则执行最顶层的showModelDialog方法
				options.curDom = window;
				window.top.$.joyplus.showModelDialog(options);
			}
		}
	};
	
	//获取当前对话框的options
	$.joyplus.getDialogOption = function(){
		var options = _joy_get_options_cache();
		return options[options.length-1];
	};
  
	//延时关闭
	$.joyplus.delayedClose = function(millisecond){
		var dialogId = $.joyplus.getModelDialogId();
		if(dialogId){
			$('#'+dialogId).dialog('minimize');
		}
		setTimeout($.joyplus.closeModelDialog,millisecond);
	};
  
	$.joyplus.closeModelDialog = function() {
		
		if (window.top == window) {
			var options = _joy_get_options_cache().pop();
      
      //父窗体可以实现onClose方法,在对话框关闭时,会调用该方法
			if (options.onClose != undefined && $.isFunction(options.onClose)) {
				options.onClose();
			}
     
      //提供父窗体回调函数
			if (options.callBack != undefined && $.isFunction(options.callBack)) {
				options.callBack();
			}
      
			if (options.validObj != undefined) {
				options.validObj.validatebox("validate");
			}
      //获取当前对话框id
			var id = _joy_get_top_dialog();
			var top = _joy_get_top_body();

      //释放自动创建的div
			var element = $(top).find("#" + id);
			$(element).dialog("destroy");
		} else {
			window.top.$.joyplus.closeModelDialog();
		}
	};
	
	$.joyplus.messager.alert = function(title, msg, icon, fn){
		if( eship.messages[msg] != undefined ){
			msg = eship.messages[msg];
		}
		$.messager.alert(title, msg, icon, fn);
	};
	
	//获取dialog对象ID
	$.joyplus.getModelDialogId = function() {
		var c =  _joy_get_cahce();	
		return c[c.length - 1];
	};

	$.fn._cache = new Array();
	$.fn._options_cache = new Array();

})(jQuery);

这样在使用时,只需调用简单方法即可

function invCageEdit(){
	var row = $('#invCageDG').datagrid('getSelected');
	if(row){
	    var options = {title:"出库包装",height:500,width:1000,contentOverflow:'hidden'};
	    options.invCageId = row.uuid;//需要传递的扩展属性
      options.href = contextPath +'/web/comm/invCageItemDialog.jsp';
	    options.backFunc = function(data){
	    	//updatePickItem();回调函数
	    };
	    $.joyplus.showModelDialog(options);
	}else{
		$.joyplus.messager.alert('提示',eship.messages.selectOne,'info');
	}
}
最近发表
标签列表