iframe一般用来加载一个页面,然后嵌入到主页面中。创建起来消耗资源,而且消耗连接数。但是它是一个物超所值的东西,可以实现无缝刷新,模拟onhashchange跨域,安全的加载第三方资源与广告,实现富文本编辑,文件上传,用它搞定IE6-IE7的select BUG(select标签会移到遮罩层的上面来,可以使用iframe遮住)。

想要隐藏iframe那个很粗的边框,我们可以使用frameBorder属性。

比如:<iframe frameborder=0  src=""  width=""  height=""></iframe>

动态创建的iframe,标准浏览器可以使用setAttribute来设置frameborder。但IE低版本只支持iframe.frameborder=0的用法(所有浏览器都支持)。

去掉iframe中的滚动条:iframe.scrolling = "no"。

IE下设置iframe的透明需要满足两个条件:

(1)iframe自身设置allowTransparency属性为true.(但设置了allowTransparency=true,就遮不住select了)

(2)iframe中的文档(src指向的页面),background-color或body元素的bgColor属性必须设置为transparent。

获取iframe中的window对象

在主页面直接,frames[iframeName],iframes是主页面中的一个对象,它的属性iframeName可以获得此名字的iframe的window对象。

iframe.contentWindow,在主页面通过document.getElementById("iframeID").contentWindow。

获取iframe中的文档对象

首先获得iframe的引用,比如:var node = document.getElementById("iframeID"),然后通过node.contentDocument || node.contentWindow.document。

前面是w3c,后面的写法是IE.

判定页面是否在iframe里面

在页面中添加以下代码:

window.onload = function(){  

  if(window != window.top) 在iframe中;

  if(window.frameElement !== null) 在iframe中;

  if(window.eval !== top.eval) 在iframe中;

}

判定iframe是否加载完成

if(iframe.addEventListener){

  iframe.addEventListener("load",callback,false)

}

else{

  iframe.attachEvent("onload",callback);

}

不过动态创建的iframe,webkit系统浏览器可能会触发两次onload问题。

例如:

var iframe = document.createElement("iframe");

iframe.onload = function(){}

document.body.appendChild(iframe)

iframe.src="bokeyuan";

safari和chrome会在appendChild之后就进行第一次加载,并且在设置src之前就加载完成了,所以触发了两次。如果在插入body之前给iframe随便设置一个src(除了空值),间接的加长第一次加载,那么也只触发一次。不设置或设置空值,它的src相当于链接到"about:blank"(空白页)。

动态创建的iframe,如果需要用到name属性,IE6-7下会有问题

if(不是IE6和IE7){

  iframe = document.createElement("iframe");

  iframe.name = name;

}else{

  iframe = document.createElement("<iframe name='" + name + "'>");

}

iframe和父窗口共享history,因为我们可以使用iframe解决ajax的后退按钮问题

链接地址:https://github.com/devote/HTML5-History-API

清空iframe,同时不保留历史的写法

iframeWindow.location.replace("about:blank"),此replace方法不是字符串的replace方法,这个replace方法是location专有的方法,意思是替换window的链接地址,而且被替换的链接地址不存入历史记录中。

同源策略

同源策略:域名,协议,端口相同。

js允许同源访问。

同一域名不同文件夹,同源。http://www.a.com/lab和http://www.a.com/lab1

域名和域名对应的ip,不同源。http://www.a.com和http://70.32.72.54

主域相同,子域不同,不同源。http://www.a.com和http://script.a.com

同一域名,不同二级域名,不同源。http://www.a.com和http://a.com,因为cookie,每次访问相同的域名时,都会带上cookie请求服务器。为了请求同一域名下的文件带上cookie,我们可以设置二级域名,这样就不会带上cookie了。比如:用户操作的都是http://a.com域名下的页面,每次请求都会带上http://a.com域名的cookie,这时我们设置boke.js为http://www.a.com,这时请求boke.js时,就不会带上http://a.com域名的cookie了。

判定iframe与父页面同源

在主页面调用此方法,返回false就是不同源。

function isSameOrigin(iframe){

  var ret =false;

  try{

    ret = !!iframe.contentWindow.location.href;

    //如果同源,就可以访问iframe的href。href如果存在,就会转换成true。ret就返回true,about:blank跟任何域名同源。

  }catch(e){}    //如果不同源,访问出错,ret是默认的false。

  return ret;

}

js跨域

跨大域:也就是主域名和子域名都不相同。

(1)postMesssage方法:在IE8以及以上浏览器支持,标准浏览器也支持。通过postMesssage方法传数据,通过message事件取数据。(IE8,IE9只能传字符串)

IE6和IE7可以通过navigator对象搞定跨域。navigator对象是window对象的属性。IE6和IE7下没有控制台,不能使用console对象的方法

  • appCodeName -- 浏览器代码名的字符串表示
  • appName -- 官方浏览器名的字符串表示
  • appVersion -- 浏览器版本信息的字符串表示
  • cookieEnabled -- 如果启用cookie返回true,否则返回false
  • javaEnabled -- 如果启用java返回true,否则返回false
  • platform -- 浏览器所在计算机平台的字符串表示
  • plugins -- 安装在浏览器中的插件数组
  • taintEnabled -- 如果启用了数据污点返回true,否则返回false
  • userAgent -- 用户代理头的字符串表示

主页面:

iframe.attachEvent && iframe.attachEvent("onload",funtion(){

  //iframe加载页面完成,就会每隔3200毫秒,执行window.navigator.b方法(此方法是在iframe页面中定义的,因此可以传入各种信息)

  setInterval(function(){  

      window.navigator.b(msg);   //主页面把要传的数据放进去。

  },3200);        

})

navigator.a = function(msg){

  msg;    (收到iframe页面传来的数据,可以显示出来,或者计算,或者传给后台)

}

iframe页面:

navigator.b = function(msg){

  msg;(收到主页面传来的数据,可以显示出来,或者计算,或者传给后台)

}

setInterval(function(){  

    window.navigator.a(msg1);   //iframe页面把要传的数据放进去。

},3300);

(2)动态创建script,动态创建Image

(3)利用iframe和location.hash

a.com下的文件,cs1.html文件:     浏览器加载完页面后,执行以下代码,新建一个iframe,加载其他域的页面

function startRequest(){
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';
document.body.appendChild(ifr);
}
function checkHash() {
try {
var data = location.hash ? location.hash.substring(1) : '';
if (console.log) {
console.log('Now the data is '+data);
}
} catch(e) {};
}
startRequest();
setInterval(checkHash, 2000);   

cnblogs.com域名下的cs2.html:     //当iframe加载完之后,执行以下代码

switch(location.hash){               //此hash值是从主页面传过来的,因此可以算作主页面传过来的数据(a.com域传给cnblogs.com域的数据)
case '#paramdo':
callBack();
break;
case '#paramset':
//do something……
break;
} function callBack(){
try {
parent.location.hash = 'somedata'; //因为不在同一个域,所不允许改变hash
} catch (e) {
// ie、chrome的安全机制无法修改parent.location.hash,
// 所以再创建一个iframe

var ifrproxy = document.createElement('iframe');
ifrproxy.style.display = 'none';
ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata'; // 注意该文件在"a.com"域下
document.body.appendChild(ifrproxy);
}
}

a.com下的域名cs3.html:      //当iframe加载完之后,执行以下代码

//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1); //此iframe(a.com)的parent是cs2(cnblogs.com),parent.parent是cs1(a.com)

只要这里一改变主页面的hash,主页面就会把这个hash取到(这是cnblogs.com域传给a.com域的数据)。

(4)利用iframe和window.name(这里跨域的重点是主页面可以获得iframe的对象,并且可以改变iframe的location。)

a.com/app.html:

var state = 0,
iframe = document.createElement('iframe'),
loadfn = function() {
if (state === 1) {
var data = iframe.contentWindow.name; // 因为此时,iframe中的页面和主页面不存在跨域,所以可以通过iframe.contentWindow.name获得数据
alert(data); // 此数据,就是从b.com域名下传来的数据。
} else if (state === 0) {
state = 1;
iframe.src = "http://a.com/proxy.html"; // 这时改变iframe中的src,使之变成a.com域下的一个空html文件。
}
};
iframe.src = 'http://b.com/data.html'; //加载完这个页面后,window.name 是b.com传过来的数据,因为跨域,所以无法取得iframe中的window.name
if (iframe.attachEvent) {
iframe.attachEvent('onload', loadfn);
} else {
iframe.onload = loadfn;
}
document.body.appendChild(iframe);

b.com/data.html:

window.name = 'msg';      //域名b.com传给域名a.com的数据    

跨小域:也就是主域名一样,子域名不一样

http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;那么他们就属于同一域名下了,就可以相互访问了。

然后通过a.html文件中创建一个iframe,加载b.htm,最后就可以在主页面获取iframe中b.htm页面的document对象了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带的前缀通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com,只能设置为它的主域名a.com。

加油!

第十五课:奇葩的元素节点iframe的更多相关文章

  1. NeHe OpenGL教程 第十五课:纹理图形字

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  2. NeHe OpenGL教程 第四十五课:顶点缓存

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. NeHe OpenGL教程 第三十五课:播放AVI

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. NeHe OpenGL教程 第二十五课:变形

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  5. MyBatis基础入门《十五》ResultMap子元素(collection)

    MyBatis基础入门<十五>ResultMap子元素(collection) 描述: 见<MyBatis基础入门<十四>ResultMap子元素(association ...

  6. 第四十五课:MVC,MVP,MVVM的区别

    前端架构从MVC到MVP,再到MVVM,它们都有不同的应用场景.但MVVM已经被证实为界面开发最好的方案了. MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/P ...

  7. 第二十五课:jQuery.event.trigger的源码解读

    本课主要来讲解jQuery.event.trigger的源码解读. trigger = function(event, data, elem, onlyHandlers){ if(elem & ...

  8. 如何用webgl(three.js)搭建一个3D库房,3D仓库,3D码头,3D集装箱可视化孪生系统——第十五课

    序 又是快两个月没写随笔了,长时间不总结项目,不锻炼文笔,一开篇,多少都会有些生疏,不知道如何开篇,如何写下去.有点江郎才尽,黔驴技穷的感觉. 写随笔,通常三步走,第一步,搭建框架,先把你要写的内容框 ...

  9. 如何用webgl(three.js)搭建一个3D库房,3D仓库3D码头,3D集装箱,车辆定位,叉车定位可视化孪生系统——第十五课

    序 又是快两个月没写随笔了,长时间不总结项目,不锻炼文笔,一开篇,多少都会有些生疏,不知道如何开篇,如何写下去.有点江郎才尽,黔驴技穷的感觉. 写随笔,通常三步走,第一步,搭建框架,先把你要写的内容框 ...

随机推荐

  1. vbs 的二个解释程序区别与切换及与BAT互调用。

    WScript.exe : 窗口中运行CScript.exe :命令行中运行 用法:<CScript|WScript> scriptname.extension [option...] [ ...

  2. Linux Epoll相关知识

    其实在Linux下设计并发网络程序,向来不缺少方法,比如典型的Apache模型(Process Per Connection,简称PPC),TPC(Thread PerConnection)模型,以及 ...

  3. JVM1.6 GC详解

    前言  JVM GC是JVM的内存回收算法,调整JVM GC(Garbage Collection),可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java程序的工作效率. ...

  4. PLSQL不好用,提示ora-12514 错误解决方法

    我的PLSQL不好用,提示ora-12514 错误时 我分两步干的: 1:用户名,密码,不写,提示错误后,cancel登陆 tools->preference左侧选->connection ...

  5. 关于NGINX的502的装逼打怪之路

    写日志之前先copy一段nginx502的原因,从某网看到如下,然而这并不是重点,最重要还是看博主手敲的东西. 一.NGINX 502错误排查 NGINX 502 Bad Gateway错误是Fast ...

  6. spring mvc 删除返回字符串中值为null的字段

    在spring的配置文件中进行一下配置: <bean class="org.springframework.web.servlet.mvc.method.annotation.Requ ...

  7. 超链接实现post方式提交

    思路:如果想要超链接实现post方式提交,必须借助表单.下面得两种方式,一种是借助显示的form表单,一种是借助隐式的form表单方式一:将超链接放到一个form表单中,或者超链接本身就在一个form ...

  8. 关于litJson的System.InvalidCastException

    最近在做一个Unity3D的项目,用到了litJson库, 它比JavaScript里的JSON解析更加严格, 有时候解析数据的时候会出现类型不对. 比如说 {"data":12} ...

  9. [POJ3468] A Simple Problem with Integers (Treap)

    题目链接:http://poj.org/problem?id=3468 这题是线段树的题,拿来学习treap. 不旋转的treap. #include <cstdio> #include ...

  10. (Tree)94.Binary Tree Inorder Traversal

    /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * Tre ...