历史版本2 :跨域调用 JS 返回文档
编辑时间: 内容长度:图片数:目录数: 修改原因:

1. 问题描述编辑

用户想要实现在自己的OA系统里点击按钮,就能触发我们的报表的提交事件。但是如果报表和他们的OA不在一个应用中,会存在js跨域调用的权限问题,这个问题该如何解决呢?

2. 实现思路编辑

如果是谷歌和火狐等支持html5的浏览器,则可通过postMessage()方法即可跨域通信;如果是ie8之前等不支持html5的,则通过一个可以跨域的全局属性window.name,外部应用可以访问并修改iframe中的window.name。然后iframe中的页面每隔一段时间检查一下,如果window.name的值变化了则做出相应的事件响应。下面我们将这两种方法放在一起,这样不论在fiefox或者ie8等浏览器下都可以实现跨域提交,避开了浏览器的问题。

3. 解决方案编辑

3.1 模板设置
在需要进行填报的模板添加加载结束事件,我们这边选择新建一张模板CrossSubmit.cpt,直接在填报预览处添加加载结束事件,代码如下:
  1. function send(val){     sendMessage(val);  
  2.         }  
  3.         (function(win, doc){  
  4.             var ifr = win.parent;  
  5.               
  6.             var cb = function(msg){  
  7.                 eval(msg);            
  8.             };  
  9.             var sendMessage = function(){  
  10.                 if(win.postMessage){  
  11.                     if (win.addEventListener) {  
  12.                         win.addEventListener("message",function(e){  
  13.                         cb.call(win,e.data);  
  14.                     },false);  
  15.                     }else if(win.attachEvent) {  
  16.                         win.attachEvent("onmessage",function(e){        cb.call(win,e.data);  
  17.                 });  
  18.                     }  
  19.   
  20.                     return function(data){  
  21.                         ifr.postMessage(data,'*');  
  22.                     };  
  23.                 }else{  
  24.                     var hash = '';  
  25.                       
  26.                     setInterval(function(){  
  27.                         if(win.name!==hash){  
  28.                             hash = win.name;  
  29.                             cb.call(win,hash);  
  30.                         }  
  31.                     },200);  
  32.                     return function(data){  
  33.                         ifr.name = data;  
  34.                     };  
  35.                 }  
  36.             }  
  37.             win.sendMessage = sendMessage();  
  38.         })(window, document);  
3.2 提交页面设置
在本地新建test.html,此时test.html与我们报表模板是两个不同的域,在test.html中点"跨域提交"按钮,调用send("_g().writeReport()")则可以实现跨域提交。test.html的代码如下:
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2. <html xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  5. <title>Untitled Document</title>  
  6. </head>  
  7. <script>  
  8. window.name="aaaa";  
  9.   
  10. function f(){  
  11.   
  12. }  
  13. </script>  
  14. <body>  
  15.   <input type="button" name="aa" value="跨域提交" onclick="send('_g().writeReport()')"/>  
  16. <iframe name="iframeA" id="iframeA" width="900" height="400" src="http://localhost:8075/WebReport/ReportServer?reportlet=CrossSubmit.cpt&op=write"></iframe>  
  17.   
  18. <script type="text/javascript">  
  19.         //document.getElementById('host').innerHTML = location.host;  
  20.         function send(msg){  
  21.             sendMessage(msg);  
  22.         }  
  23.         (function(win, doc){  
  24.             var ifr = doc.getElementById('iframeA').contentWindow;  
  25.             var cb = function(json){  
  26.                 eval(json);  
  27.             };  
  28.             var sendMessage = function(){  
  29.                 if(win.postMessage){  
  30.                     if (win.addEventListener) {  
  31.                         win.addEventListener("message",function(e){  
  32.                         cb.call(win,e.data);  
  33.                     },false);  
  34.                     }else if(win.attachEvent) {  
  35.                         win.attachEvent("onmessage",function(e){  
  36.                         cb.call(win,e.data);  
  37.                     });  
  38.                     }  
  39.                     return function(data){  
  40.                         ifr.postMessage(data,'*');  
  41.                     };  
  42.                 }else{  
  43.                     var hash = '';  
  44.                       
  45.                     setInterval(function(){  
  46.                       
  47.                         if (win.name !== hash) {  
  48.                             hash = win.name;  
  49.                             cb.call(win, hash);  
  50.                         }  
  51.                     }, 200);  
  52.                     return function(data){  
  53.                         ifr.name = data;  
  54.                     };  
  55.                 }  
  56.             };  
  57.             win.sendMessage = sendMessage();  
  58.         })(window, document);  
  59. </script>  
  60. </body>  
  61.   
  62. </html>  
3.3 效果查看
由于使用的最简单的模板,即模板没有设计模板主体。
  • IE8下:
  • 谷歌下: