easyUi內嵌iframe時,彈出對話框被遮擋問題

這是多年以前用傳統JQuery(easyUi)做項目時遇到的問題,今天把解決思路發佈出來,也許能幫助到還在使用老架構的同學。

在開發類ERP的後臺管理系統時,經常會看到這樣的佈局結構


easyUi內嵌iframe時,彈出對話框被遮擋問題

每打開一個菜單都是單獨打開一個Tab頁,easyUi打開Tab頁有兩種方式:

  • 動態增加iframe
  • 在同一個Dom樹中增加div 的方式

同一Dom樹中存在命名汙染的問題,包括樣式也會互相影響,新增加頁面裡的樣式很可能影響原有頁面的佈局

因此我們採用iframe的方式實現:

<code>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>';return s;}/<code>

我們在使用時iframe Tab頁時,頁面中經常會有打開對話框的需求。

因為我們採用了iframe的方式,其實打開對話框是在子頁面的iframe的dom中打開的,因此會被主頁面遮擋,如圖所示:


easyUi內嵌iframe時,彈出對話框被遮擋問題

對話框移動過程中會被Tab標籤遮擋,並且無法繼續向上移動,並且不同iframe傳遞參數也比較麻煩,不是很方便,因此決定進行封裝,基本原理如下:

封裝模態對話框插件

  1. 判斷是否在最頂層dom中執行,如果不在獲取到頂層dom對象
  2. 在最頂層iframe中自動增加一個div,並通過這個div打開模態對話框
  3. 用堆棧記錄打開對話框的相關屬性options
  4. 關閉時,依次調用堆棧中的對話框,並關閉

優點:

  1. 增加getDialogOption方法,可方便獲取當前對話框的option對象,可以方便的通過該對象進行窗口之間的值傳遞。
  2. 在關閉時,增加回調方法,可以在關閉時方便的調用父窗體的回調方法。
<code>/** * 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(" 
");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{//如果是最頂層的iframeif (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");} //獲取當前對話框idvar id = _joy_get_top_dialog();var top = _joy_get_top_body(); //釋放自動創建的divvar 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);/<code>

這樣在使用時,只需調用簡單方法即可

<code>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');}}/<code>


分享到:


相關文章: