你的位置:首页 > Java教程

[Java教程]前端弹出对话框 js实现 ajax交互


  原本计划实现这样一个需求: 前台点击触发某业务动作,需要用户补充信息,不做跳转页面,弹窗的形式进行补充信息。 折腾出来了,但是最终没有用到。

  代码还有些毛躁,提供大概实现逻辑。

实现思路:  在窗口铺上蒙板以屏蔽原窗口功能按钮操作,在蒙板上层绝对定位实现弹窗,弹窗中的数据交互采用ajax方式。 出发弹窗事件用onclick.

关键细节:  弹窗和原窗体本质是同页面,为了描述方便,姑且称底层窗体为父窗体,弹窗为子窗体。为了实现字父窗体的交互,需要在父窗体中做一些特别标签,以便选择器选择,并操作插入新的dom对象。

 

如此,首先看下父窗体的代码,关键部分我是有注释的。

<html ="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 >' + 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 + '" ></div>').get(0);    /* 创建对话框主体 */    this.dom.body      = $('<div ></div>').get(0);    /* 创建标题栏 */    this.dom.head      = $('<h3 ></h3>').get(0);    /* 创建标题文本 */    this.dom.title     = $('<span ></span>').get(0);    /* 创建关闭按钮 */    //this.dom.close_button  = $('<span >close</span>').get(0);    /* 创建内容区域 */    this.dom.content    = $('<div ></div>').get(0);    /* 组合 */    $(this.dom.head).append('<div ></div><div ></div>').append($('<span ></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 ></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 ><div >' + options.text + '</div></div>';        status = 'loading';      break;      case 'message':        var type = 'notice';        if (options.type)        {          type = options.type;        }        _message_body = $('<div ></div>');        _message_contents = $('<div >' + options.text + '</div>');        _buttons_bar = $('<div ></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" 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" value="' + yes_button_name + '" />');            _no_button = $('<input type="button" 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>

 

最后再贴一张效果图吧。