原本計劃實現這樣一個需求: 前台點擊觸發某業務動作,需要用戶補充信息,不做跳轉頁面,彈窗的形式進行補充信息。 折騰出來了,但是最終沒有用到。
代碼還有些毛躁,提供大概實現邏輯。
實現思路:在窗口鋪上蒙板以屏蔽原窗口功能按鈕操作,在蒙板上層絕對定位實現彈窗,彈窗中的數據交互采用ajax方式。 出發彈窗事件用onclick.
關鍵細節:彈窗和原窗體本質是同頁面,為了描述方便,姑且稱底層窗體為父窗體,彈窗為子窗體。為了實現字父窗體的交互,需要在父窗體中做一些特別標簽,以便選擇器選擇,並操作插入新的dom對象。
如此,首先看下父窗體的代碼,關鍵部分我是有注釋的。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="initial-scale=1.0, user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <title>測試彈窗</title> <script type="text/javascript" src="script/jquery/jquery.js" charset="utf-8"></script> <script type="text/javascript" src="script/js/outil.js" charset="utf-8"></script> <script charset="utf-8" type="text/javascript" src="script/jquery/jquery.ui.js"></script> <link rel="stylesheet" type="text/css" href="script/jquery/themes/ui-lightness/jquery.ui.css"> <script charset="utf-8" type="text/javascript" src="script/dialog/dialog.js" id="dialog_js"></script> <link href="script/dialog/dialog.css" rel="stylesheet" type="text/css"> <style type="text/css"> *{ margin: 0; padding: 0; text-align: center; text-decoration: none; } body{ font: 12px/1.5 宋體,Tahoma, Arial,sans-serif; font-family: "微軟雅黑"; width:320px; height: auto; margin:0 auto; } .content{ border: #ccc solid 1px; margin:60px 10px 10px; background:#fff; overflow:hidden; color:#6b6b6b; font-size:14px; border-radius:5px; } </style> </head> <body> <!-- 選擇器是通過ectype="dialog"來進行選擇的 --> <div class="content"> <a href="javascript:void(0);" ectype="dialog" dialog_id="dialog_test" dialog_title="對話測試" dialog_width="300" uri="pop_son.html" > 對話測試 </a> </div> </body> </html>
接著給出選擇器部分代碼,也就是outil.js的代碼,當然之前的jquery以及jquery ui就不說了。 其核心是綁定click事件。
jQuery.extend({ getCookie : function(sName) { var aCookie = document.cookie.split("; "); for (var i=0; i < aCookie.length; i++){ var aCrumb = aCookie[i].split("="); if (sName == aCrumb[0]) return decodeURIComponent(aCrumb[1]); } return ''; }, setCookie : function(sName, sValue, sExpires) { var sCookie = sName + "=" + encodeURIComponent(sValue); if (sExpires != null) sCookie += "; expires=" + sExpires; document.cookie = sCookie; }, removeCookie : function(sName) { document.cookie = sName + "=; expires=Fri, 31 Dec 1999 23:59:59 GMT;"; } }); $(function(){ /* dialog 選擇並綁定一個新的click事件 */ $('*[ectype="dialog"]').click(function(){ var id = $(this).attr('dialog_id'); var title = $(this).attr('dialog_title') ? $(this).attr('dialog_title') : ''; var url = $(this).attr('uri'); var width = $(this).attr('dialog_width'); ajax_form(id, title, url, width); return false; }); }); function drop_confirm(msg, url){ if(confirm(msg)){ window.location = url; } } /* 顯示Ajax表單 */ function ajax_form(id, title, url, width) { if (!width) { width = 400; } var d = DialogManager.create(id); d.setTitle(title); d.setContents('ajax', url); d.setWidth(width); d.show('center'); return d; } function go(url){ window.location = url; } function set_zindex(parents, index){ $.each(parents,function(i,n){ if($(n).css('position') == 'relative'){//alert('relative'); //alert($(n).css('z-index')); $(n).css('z-index',index); } }); } function js_success(dialog_id) { DialogManager.close(dialog_id); var url = window.location.href; url = url.indexOf('#') > 0 ? url.replace(/#/g, '') : url; window.location.replace(url); } function js_fail(str) { $('#warning').html('<label class="error">' + str + '</label>'); $('#warning').show(); } function check_pint(v) { var regu = /^[0-9]{1,}$/; if(!regu.test(v)) { alert(lang.only_int); return false; } return true; } /* 轉化JS跳轉中的 & */ function transform_char(str) { if(str.indexOf('&')) { str = str.replace(/&/g, "%26"); } return str; } // 復制到剪貼板 function copyToClipboard(txt) { if(window.clipboardData) { window.clipboardData.clearData(); window.clipboardData.setData("Text", txt); } else if(navigator.userAgent.indexOf("Opera") != -1) { window.location = txt; } else if (window.netscape) { try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); } catch (e) { return false; } var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard); if (!clip) return false; var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable); if (!trans) return false; trans.addDataFlavor('text/unicode'); var str = new Object(); var len = new Object(); var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString); var copytext = txt; str.data = copytext; trans.setTransferData("text/unicode",str,copytext.length*2); var clipid = Components.interfaces.nsIClipboard; if (!clip) return false; clip.setData(trans,null,clipid.kGlobalClipboard); } }
綁定事件的相關代碼就是dialog的核心代碼(dialog.js)了,這個是在網上找到的,在此感謝,代碼如下所示:
__DIALOG_WRAPPER__ = {}; /* IE6有個Bug,如果不給定對話框的寬度的話,在IE6下,對話框將以100%寬度顯示 */ DialogManager = { 'create' :function(id){ var d = {}; if (!__DIALOG_WRAPPER__[id]) { d = new Dialog(id); __DIALOG_WRAPPER__[id] = d; } else { d = DialogManager.get(id); } return d; }, 'get' :function(id){ return __DIALOG_WRAPPER__[id]; }, 'close' :function(id){ if (__DIALOG_WRAPPER__[id].close()) { __DIALOG_WRAPPER__[id] = null; } }, 'onClose' :function (){ return true; }, /* 加載對話框樣式 */ 'loadStyle' :function(){ var _dialog_js_path = $('#dialog_js').attr('src'); var _path = _dialog_js_path.split('/'); var _dialog_css = _path.slice(0, _path.length - 1).join('/') + '/dialog.css'; $('#dialog_js').after('<link href="' + _dialog_css + '" rel="stylesheet" type="text/css" />'); } }; ScreenLocker = { 'style' : { 'position' : 'absolute', 'top' : '0px', 'left' : '0px', 'backgroundColor' : '#000', 'opacity' : 0.5, 'zIndex' : 999 }, 'masker' : null, 'lock' : function(zIndex){ if (this.masker !== null) { this.masker.width($(document).width()).height($(document).height()); return true; } this.masker = $('<div></div>'); /* IE6 Hack */ if ($.browser.msie) { $('select').css('visibility', 'hidden'); } //var _iframe = $('<iframe></iframe>').css({'opacity':0, 'width':'100%', 'height':'100%'}); //this.masker.append(_iframe); /* 樣式 */ this.masker.css(this.style); if (zIndex) { this.masker.css('zIndex', zIndex); } /* 整個文檔的寬高 */ this.masker.width($(document).width()).height($(document).height()); $(document.body).append(this.masker); }, 'unlock' : function(){ if (this.masker === null) { return true; } this.masker.remove(); this.masker = null; /* IE6 Hack */ if ($.browser.msie) { $('select').css('visibility', 'visible'); } } }; Dialog = function (id){ /* 構造函數生成對話框代碼,並加入到文檔中 */ this.id = id; this.init(); }; Dialog.prototype = { /* 唯一標識 */ 'id' : null, /* 文檔對象 */ 'dom' : null, 'lastPos' : null, 'status' : 'complete', 'onClose' : function (){ return true; }, 'tmp' : {}, /* 初始化 */ 'init' : function(){ this.dom = {'wrapper' : null, 'body':null, 'head':null, 'title':null, 'close_button':null, 'content':null}; /* 創建外層容器 */ this.dom.wrapper = $('<div id="dialog_object_' + this.id + '" class="dialog_wrapper"></div>').get(0); /* 創建對話框主體 */ this.dom.body = $('<div class="dialog_body"></div>').get(0); /* 創建標題欄 */ this.dom.head = $('<h3 class="dialog_head"></h3>').get(0); /* 創建標題文本 */ this.dom.title = $('<span class="dialog_title_icon"></span>').get(0); /* 創建關閉按鈕 */ //this.dom.close_button = $('<span class="dialog_close_button">close</span>').get(0); /* 創建內容區域 */ this.dom.content = $('<div class="dialog_content"></div>').get(0); /* 組合 */ $(this.dom.head).append('<div class="dialog_ornament1"></div><div class="dialog_ornament2"></div>').append($('<span class="dialog_title"></span>').append(this.dom.title)).append(this.dom.close_button); $(this.dom.body).append(this.dom.head).append(this.dom.content); $(this.dom.wrapper).append(this.dom.body).append('<div style="clear:both;display:block;"></div>'); /* 初始化樣式 */ $(this.dom.wrapper).css({ 'zIndex' : 9999, 'display' : 'none', 'position' : 'absolute' }); $(this.dom.body).css({ 'position' : 'relative' }); $(this.dom.head).css({ 'cursor' : 'move' }); $(this.dom.close_button).css({ 'position' : 'absolute', 'text-indent': '-9999px', 'cursor' : 'pointer', 'overflow' : 'hidden' }); $(this.dom.content).css({ 'margin' : '0px', 'padding' : '0px' }); var self = this; /* 初始化組件事件 */ $(this.dom.close_button).click(function(){ DialogManager.close(self.id); }); /* 可拖放 */ $(this.dom.wrapper).draggable({ 'handle' : this.dom.head }); /* 放入文檔流 */ $(document.body).append(this.dom.wrapper); }, /* 隱藏 */ 'hide' : function(){ $(this.dom.wrapper).hide(); }, /* 顯示 */ 'show' : function(pos){ if (pos) { this.setPosition(pos); } /* 鎖定屏幕 */ ScreenLocker.lock(999); /* 顯示對話框 */ $(this.dom.wrapper).show(); }, /* 關閉 */ 'close' : function(){ if (!this.onClose()) { return false; } /* 關閉對話框 */ $(this.dom.wrapper).remove(); /* 解鎖屏幕 */ ScreenLocker.unlock(); return true; }, /* 對話框標題 */ 'setTitle' : function(title){ $(this.dom.title).html(title); }, /* 改變對話框內容 */ 'setContents' : function(type, options){ contents = this.createContents(type, options); if (typeof(contents) == 'string') { $(this.dom.content).html(contents); } else { $(this.dom.content).empty(); $(this.dom.content).append(contents); } }, /* 設置對話框樣式 */ 'setStyle' : function(style){ if (typeof(style) == 'object') { /* 否則為CSS */ $(this.dom.wrapper).css(style); } else { /* 如果是字符串,則認為是樣式名 */ $(this.dom.wrapper).addClass(style); } }, 'setWidth' : function(width){ this.setStyle({'width' : width + 'px'}); }, 'setHeight' : function(height){ this.setStyle({'height' : height + 'px'}); }, /* 生成對話框內容 */ 'createContents' : function(type, options){ var _html = '', self = this, status= 'complete'; if (!options) { /* 如果只有一個參數,則認為其傳遞的是HTML字符串 */ this.setStatus(status); return type; } switch(type){ case 'ajax': /* 通過Ajax取得HTML,顯示到頁面上,此過程是異步的 */ $.get(options, {ajax:1}, function(data){ if(data.substr(0,1) == '{' && data.substr(data.length - 1, 1) == '}'){ var JSON = eval('(' + data + ')'); if(!JSON.done){ self.setContents(JSON.msg); return; } } self.setContents(data); /* 使用上次定位重新定位窗口位置 */ self.setPosition(self.lastPos); //>>addByZZY20160909: 根據後台返回信息決定該窗口是否展示 /* 依據返回內容的前五位,值為close時候不展示 */ if(data.substr(0,5) == 'close'){ self.close(); } }); /* 先提示正在加載 */ _html = this.createContents('loading', {'text' : 'loading...'}); break; /* 以下是內置的幾種對話框類型 */ case 'loading': _html = '<div class="dialog_loading"><div class="dialog_loading_text">' + options.text + '</div></div>'; status = 'loading'; break; case 'message': var type = 'notice'; if (options.type) { type = options.type; } _message_body = $('<div class="dialog_message_body"></div>'); _message_contents = $('<div class="dialog_message_contents dialog_message_' + type + '">' + options.text + '</div>'); _buttons_bar = $('<div class="dialog_buttons_bar"></div>'); switch (type){ case 'notice': case 'warning': var button_name = lang.confirm; if (options.button_name) { button_name = options.button_name; } _ok_button = $('<input type="button" class="btn1" value="' + button_name + '" />'); $(_ok_button).click(function(){ if (options.onclick) { if(!options.onclick.call()) { return; } } DialogManager.close(self.id); }); $(_buttons_bar).append(_ok_button); break; case 'confirm': var yes_button_name = lang.yes; var no_button_name = lang.no; if (options.yes_button_name) { yes_button_name = options.yes_button_name; } if (options.no_button_name) { no_button_name = options.no_button_name; } _yes_button = $('<input type="button" class="btn1" value="' + yes_button_name + '" />'); _no_button = $('<input type="button" class="btn2" value="' + no_button_name + '" />'); $(_yes_button).click(function(){ if (options.onClickYes) { if (options.onClickYes.call() === false) { return; } } DialogManager.close(self.id); }); $(_no_button).click(function(){ if (options.onClickNo) { if (!options.onClickNo.call()) { return; } } DialogManager.close(self.id); }); $(_buttons_bar).append(_yes_button).append(_no_button); break; } _html = $(_message_body).append(_message_contents).append(_buttons_bar); break; } this.setStatus(status); return _html; }, /* 定位 */ 'setPosition' : function(pos){ /* 上次定位 */ this.lastPos = pos; if (typeof(pos) == 'string') { switch(pos){ case 'center': var left = 0; var top = 0; var dialog_width = $(this.dom.wrapper).width(); var dialog_height = $(this.dom.wrapper).height(); /* left=滾動條的寬度 + (當前可視區的寬度 - 對話框的寬度 ) / 2 */ left = $(window).scrollLeft() + ($(window).width() - dialog_width) / 2; /* top =滾動條的高度 + (當前可視區的高度 - 對話框的高度 ) / 2 */ top = $(window).scrollTop() + ($(window).height() - dialog_height) / 2; $(this.dom.wrapper).css({left:left + 'px', top:top + 'px'}); break; } } else { var _pos = {}; if (typeof(pos.left) != 'undefined') { _pos.left = pos.left; } if (typeof(pos.top) != 'undefined') { _pos.top = pos.top; } $(this.dom.wrapper).css(_pos); } }, /* 設置狀態 */ 'setStatus' : function(code){ this.status = code; }, /* 獲取狀態 */ 'getStatus' : function(){ return this.status; }, 'disableClose' : function(msg){ this.tmp['oldOnClose'] = this.onClose; this.onClose = function(){ if(msg)alert(msg); return false; }; }, 'enableClose' : function(){ this.onClose = this.tmp['oldOnClose']; this.tmp['oldOnClose'] = null; } }; //RemoveByZZY20160909: 手動引入樣式文件 //DialogManager.loadStyle();
好了,以上就是核心邏輯及代碼實現,代碼很好的解釋了整個過程,沒必要浪費文字了。這裡面把子窗體我再貼下。
<style> .btn{ margin:10px 5px; width: 100px; } </style> <form method="post" action="{$MyAction}" id="popupform"> <div class="content" style="margin-top:10px;" > <p> 這裡展示的內容可以是表單或非表單等內容。 <input type="hidden" name="ret_url" value="{$ret_url}" /> </p> <input type="submit" class="btn" value="完成" /> </div> </form>
最後再貼一張效果圖吧。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持。