像模式窗口一样传递参数给iframe

来源:互联网 发布:sql注入防御方法 编辑:程序博客网 时间:2024/05/17 08:29

很多人都使用过IE 的模式窗口, 打开一个模式窗口 window.ShowModalDialog(URL, 传递的参数, 属性).

 

window 打开窗口还有一个方法, 就是 open(URL, 窗口名, 属性).

 

我们直接从两个方法的参数对比中, 可以看出, 模式窗口传递参数是可以以JS 对象来传递的, 不用单纯通过URL 参数来传递. 并且在打开的模式窗口中, 你要获取传递过来的参数, 很简单! 你只需要 window.dialogArguments 就可以获取传递的参数了, window.dialogArguments 就是传递的参数的引用.

 

在现在的应用系统中, 弹出窗口, 对于用户的体验来说, 是很差劲的一个做法, 并且现在很多浏览器也或多或少会屏蔽弹出窗口, 所以现在一些div + iframe 来实现类似窗口的做法越来越多.

 

当然, 如果要做到类似模式窗口的功能, 那就必须具备模式窗口一样传递参数才行, 不然啥都是白搭. 这个周末有空, 我修改了以前的一篇文章,

 iframe高度自适应bylin49940

http://blog.csdn.net/lin49940/archive/2009/10/07/4639870.aspx, 修改的地方主要是iframe 的事件的捆绑,  其实我以前一个最大的失误就是对于iframe 的页面的加载情况的考虑不够周全, 并且通过状态来判断加载情况是否完成也不是100%靠谱, 通过一些尝试后, 我终于找到一个比较好的处理方式, 那就是异常和延迟器setTimeOut方法, 这个想法的来源是 jQuery 的 ready()方法, 如果还没加载完成, 那我就一直等到你加载完成.

 

如果我能对iframe 捆绑load 或 unload 以外的事件, 进一步想, 那捆绑参数到 iframe 应该也不是问题, 没可能iframe 里面的窗口是只读属性的. 好了, 下面让我们进入主题吧! 要做的事情就是把主窗口的window 对象传递给创建的iframe.  (csdn 抛弃IE6, 我就只能直接贴代码) 

 

function createElement(type,name){
 if(name == null || name == "")
  return document.createElement(type);
 var element = null;
 try{
  element = document.createElement("<" + type + " name='" + name + "'>");
 }catch(e){}
 if(element == null){
  element = document.createElement(type);
  element.name = name;
 }  
 return element;
}

 

这是一个创建元素的方法, 为什么要重新写一个这个方法呢, 原因就要问微软了, 微软的IE 是不允许对动态创建的元素的name属性进行修改的.

 

/*为对象添加事件, 兼容IE6, firefox, 这里不对参数进行验证,
  不覆盖原来的事件方法, 而是在原来的事件方法后面再添加事件方法
  obj 元素对象
  type 事件名称, 不带on, 如load, click
  fn 方法对象
  auto 布尔值, 表示是否用最后一种方法
*/
var addEvent = function(obj, type, fn, auto){  
 if(!obj)return obj;
 if (!auto &&obj.addEventListener){ //firefox
  //alert('ff: addEventListener');
  obj.addEventListener(type, fn, false);//这个不先执行  
 }
    else if(!auto && obj.attachEvent){   //IE
  //alert('ie: attachEvent ');
        obj.attachEvent('on' + type, fn);  
    }else{ //other, 在firefox 无法执行
  //alert('auto');
  var oldEvent = eval('obj.document.body.on' + type);
  //alert(oldEvent);
  //alert(Object.prototype.toString.call(oldEvent));
  eval('obj.document.body.on'+type+' = function(){ '+
   'if(oldEvent && typeof oldEvent == "function"){ '+
   ' oldEvent(); '+
   '} ' +
   'fn() ' +
  '} ');
 }
    return obj;  
}  

 

这是一个捆绑事件到元素的方法, 在iframe 高度自适应那篇文章里面写的.

 


function passArg(myIfrObj, args , trycount){
 if(myIfrObj == null) alert(' suitSelf myIfrObj is null');
 if(!trycount) trycount = 15;
 try{
  if(myIfrObj.timeHandle)
   clearTimeout(timeHandle);
  myIfrObj.contentWindow.args = args;
 }catch(e){//页面还没加载完成或跨域都会抛异常
  //alert(e);
  if(!myIfrObj.timeHandleCount)
   myIfrObj.timeHandleCount = 1;
  else
   ++myIfrObj.timeHandleCount;
  if(myIfrObj.timeHandleCount <= trycount){
   myIfrObj.timeHandle = setTimeout(function(){
           passArg(myIfrObj, args,trycount)
           },
           200);  //如果加载事件很长, 建议把等待时间加大
  }
 }
}

 

这个是传递参数的方法的, 但是还不是我们的最终目的.

 

function createIFr(target, name, src, args){
 var myIfrObj = createElement('iframe',name);
 target.appendChild(myIfrObj);
 myIfrObj.src = src;
 addEvent(myIfrObj,'load',function(){passArg(myIfrObj, args);});
}

 

这个就是我们最终需要调用的方法了.

target, 目标元素, 指的就是加载iframe 的元素容器;

name,  设置 iframe 的 name 属性;

src,      设置 iframe 的 src 属性;

args,    我们的需要传递的参数;

 

到这里大家应该发现一个问题了, 那就是没有设置iframe 属性的参数. 说实话, 本人能力不行, 不知道有什么好的方式实现属性, 并且写太多其他东西, 只会偏离文章的主题.

 

好了, 开始测试一次上面的方法是否有效.

测试页面 test1.html

 

function aa(){
 createIFr(document.body, 'myifa_2','test2.html',window);
}

 

function hello(){
 alert('hello from topener')
}

 

<INPUT TYPE="button" VALUE="创建一个iframe" ONCLICK="aa()">

 

测试页面 test2.html

 

<SCRIPT LANGUAGE="JavaScript">
<!--
 var bb = function() {
  alert(window.args); window.args.hello();
 }

//-->
</SCRIPT>

 

<INPUT TYPE="button" VALUE="查看传递的参数" ONCLICK="bb();">

 

呵呵, 还不错, 在IE6 和 firefox 3.5 正确执行.

 

上面的例子是把传递参数的方法捆绑到 iframe 的load 事件上, 我是建议这么做的, 因为如果不是捆绑在 load 事件上, iframe 里面的页面进行了刷新操作, 那传递的参数将会丢失. (这个本人感觉挺奇怪的, 捆绑在iframe.contentWindow的 load事件, 应该是捆绑在里面的window 对象上, 刷新操作应该是document 对象的重新载入而已, 不会涉及window 对象, 这个真是奇怪, 希望有高手能告知).

 

当然, 你想用通过点击按钮等方式来触发参数的传递, 也是可以做到的

 

test1.html

 

function passArgOnClick(){
 var myIfrObjs = document.getElementsByTagName('iframe');
 passArg(myIfrObjs[0],window);
}

 

<INPUT TYPE="button" VALUE="点击传递参数给第一个iframe" ONCLICK="passArgOnClick()">

 

另: 今天是8·15全国哀悼日, 全国各族人民对甘肃舟曲特大山洪泥石流遇难同胞的深切哀悼, 在这个沉痛的日子里,让我们一同为舟曲受灾的父老兄弟姐妹们祈祷祝福, 希望你们能尽快恢复正常的生活, 重新建设家园!