iframe通常用来加载一个页面,而后嵌入到主页面中。建立起来消耗资源,并且消耗链接数。可是它是一个物超所值的东西,能够实现无缝刷新,模拟onhashchange跨域,安全的加载第三方资源与广告,实现富文本编辑,文件上传,用它搞定IE6-IE7的select BUG(select标签会移到遮罩层的上面来,可使用iframe遮住)。javascript
想要隐藏iframe那个很粗的边框,咱们可使用frameBorder属性。css
好比:<iframe frameborder=0 src="" width="" height=""></iframe>html
动态建立的iframe,标准浏览器可使用setAttribute来设置frameborder。但IE低版本只支持iframe.frameborder=0的用法(全部浏览器都支持)。java
去掉iframe中的滚动条:iframe.scrolling = "no"。node
IE下设置iframe的透明须要知足两个条件:git
(1)iframe自身设置allowTransparency属性为true.(但设置了allowTransparency=true,就遮不住select了)github
(2)iframe中的文档(src指向的页面),background-color或body元素的bgColor属性必须设置为transparent。web
获取iframe中的window对象ajax
在主页面直接,frames[iframeName],iframes是主页面中的一个对象,它的属性iframeName能够得到此名字的iframe的window对象。chrome
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对象的方法
主页面:
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。
加油!