— Designsor

一直以为这是个不可能完成的任务,最近又被颠覆了价值观- -。

首先,最经典的例子,以前做BS应用,大多采用三栏布局,top,left,main三个iframe。然后总是有各种人问你,那个top里的js下拉导航菜单是否可以下拉覆盖住main或者left?

我一直给他们的答案是,NO,不行……

最近看新浪xweibo的浮动层源码还有my97日历里的一个新功能时,想到了,其实这是可以实现的。

后来看my97的源码,终于想明白了。我们回到最开始那个情景,几个iframe拼了一个布局,那么在子iframe里或者几个平行的iframe里,如何实现浮层能盖住他们2个呢?

永远都在自己的top的那个window窗口里再创建一个顶级的iframe,然后装载浮层内容,再找到自己被激活的那个点的相对浏览器窗口的x,y坐标,(比如,我在子iframe里激活一个按钮,这个按钮相对自己窗口的x,y可以找到,简单递归,它可以累积加上自己这个点相对于parent的x,y一直找到top),然后再再top里相对自身窗口激活x,y这个坐标的浮动层,实现真正的顶层浮层,数据的操作由于都在一个iframe中完成,那当然就可以写一个通用的方法,把这个iframe和创建浮层的相对应的页面进行联系和通讯。

但是这里要说,相对于这种实现,涉及数据的操作,必须是要一个很相对独立完成的应用,比如my97日历,比如微博内部的那一套已经封装的很好的内部ajax套件,否则你自己每次生成这个都要自己再在操作完浮层写一堆代码回调回数据到子帧。最好的办法就是同域使用ajax,统一对浮层管理数据间的管理【这就要考虑业务代码了】,亦或者my97这样相比很单一的功能去实现几口接口。

不给出代码了。用jquery可以很容易的写出来,主要还在于是否有必要这么去做,值得考虑,毕竟有时候这样效率不高,在高密度的多iframe的应用里,或者未知的场景里做浮动,这样比较保险。

我最后还是我决定在自己的业务框架里增加这个功能……= =||因为很多时候我这边的页面条件还都是很恶劣的。。

Read More

这文章早在2个月前就想写了,我还记得刚入行的时候,无数的人和我说,能别用它就别用,还有无数的人说这货各种难调试,各种复杂,当时自己确实也惧怕过一段时间,暂且不说iframe性能上的种种,抛开性能层面,单就跨域和安全限制与互相调用同步数据那一块,在开始的时候也一直头疼。

经过之前在淘宝的一个项目还有在新公司的一段时间,发现这东西其实,真心不复杂,做点个人的笔记,也分享下经验教训。

首先,从基础说起,开始就怕这货最主要的原因就是根本不知道这货到底是什么。

尽量简洁的表达就是,我们都知道每个窗口都有一个window全局对象,其下会有多个对象其中就有frames对象,好吧,这里给大家写全了。

current window->self,parent,top,window.navigation.frames.location.history.document.screen.其他先不说,单说frames,里面保存了当前window对象中所嵌入的iframe帧数组。嗯哼,分为2种查询形式:frames[i],frames[name];那么好,我们抽象出来,写过css的人肯定知道一个属性z-index.其实这里我们可以把所有iframe,或者说每个window帧,当成z轴上的一个图层片,把0当成最底层,ok。自己想一下就明白了,无论你页面里的iframe又套了多少个iframe或者多级iframe,其实只不过是在每个不同针里叠加这种z轴性质的东西而已了。

其中parent是访问上一层的方法,比如parent.document;其中self和window所指就是当前自身,而top就是快速查找最顶层的方法了。理解到这里,一目了然,iframe无论你怎么套嵌就都不可怕了,我做过最复杂的是4层iframe的深度,其中从第2层开始跨域,从第3层里又跨回来,或者多个外域互相调用【由于淘宝应用的复杂,这种情况有时候真的是挺常见】。

跨域问题下面再说,我会给出多种解决方案。就iframe本身来说,概念上就是这么点东西了。

然后我想说一下,我们经常惧怕的iframe的一些地方,1,自适应高宽,2方法或者类或者数据的共享。

其实解决起来如果明白了他们之间互相的关系,不管跨域不跨域,是完全跨域还是跨子域,都是可以完美解决的。

首先我来说一般的iframe应用,一个iframe挂页面里,几个链接操作切换那个iframe实现局部刷新,很简单,a链接的target对应上iframe的name即可,js都不用写。

然后是我们切换iframe,不同的iframe高度不一样,大家都知道iframe被嵌入页面,高度一开始可以写死,但是我们不知道它变化后的高度了,需要让iframe自身告诉我们它自己的高,再进行2次设置。那么好,这个操作一般是操作高度,我们这里分3种情况来做:

1,同域。2,夸子域。3,完全跨域。

1.同域名的iframe,是没有安全限制的,之间是可以尽情互相访问的,简单来说.写入的iframe那一帧,在onload时,触发一个函数,读自己的高宽,怎么读?在父页面是这样的:

<iframe name=”myiframe” src=”xx”>

window.frames['myiframe'].onload=function(){alert(this.contentWindow.document.offsetHeight);}

暂时不考虑兼容性,就是不同浏览器里的offsetHeight读取是有差异的,单简单举例,就是在父页面,等我的这个iframe load完,我去读他的window对象下的document下的offsetHeight属性而已。

如果从子页面往父页面去读怎么写呢?window.onload=function(){if(parent) parent.alert(document.offsetHeight);}也很简单了,在子页面写一个onload监听,如果他有parent了,就调用parent下的alert方法,弹一个自身的offsetHeight。

嗯,那么跨域了怎么办?首先这里说明,js里怎么判断域的,这里有一个document.domain属性是关键。如果仅仅是xxx.name.com和ooo.name.com互相2个iframe互相引用控制,我们依然按照2个情况方法来举例:

1,父去取子的属性。这个时候如果你依然用上面的contentWindow去读,是被拒绝访问的,因为你们子域名不一样。一个是xxx一个是ooo。那么怎么办。好,我们这个时候在子页面写一句document.domain=’name.com’; ok,这时候父去读子域的时候,子的domain已经被我们改成了和父一样的域,name.com,是不被禁止的,可以自由读或者改了。2,子去读父,方法和道理一样。

所以我们往往在一些站点的全局js里看到会显式的声明一下docuemnt.domain,原因其实也就是这个了。

3,完全跨域。ooo.name1.com和xxx.name2.com2个窗口之间如何交互,这时候你再设置domain也白搭了。解决办法也有,我们可以染过安全限制这块,方法也非常经典,肯定很多人都会了,就是在2个iframe中间创建一个专门的代理页面。

为什么呢?既然ooo.name1.com读不了xxx.name2.com的页面,他只能读xxx.name1.com的帧页面,那么我们在xxx.name2.com里创建一个ooo.name1.com的iframe就好了么。这个页面呢,是和xxx.name2.com平级的一个iframe,他的创建过程是在xxx.name2.com里的脚本完成的,在创建他的时候,我们把src写上我们要传递给最终父的数据或者方法名,之后通过这个代理iframe里的脚本访问他的top,实现跨域的2个窗口通讯。

说的有点绕了。我们这里用代码简单解释一下:

A,B,C 3个页面: A套B,B动态创建C,C和A同域名。A写一个方法,等待被C调用,调用用top的方法。B写一个创建C这个iframe的方法,在动态插入的时候把height或者其他东西写入C的src里。C写一个读自己src的方法,再写一个访问自己top下的页面的方法的方法。。比如重新设置B的iframe标签的高宽~

OK搞定……。我觉得有点基础的人都能看明白了。

数据啊,方法名字啊,同样可以用这种方法传递,比如我们一个页面有多个B-iframe,那么A怎么知道调整哪一个B的高度?这里就需要一些技巧了,解决办法A在创建B的时候写入固定的排序id名,比如iframe-01,02,03,然后C再反回A这个01,02,03,就可以设置相应的B-iframe了。。比较猥琐和累,可是没办法了……

不过其实说白了,理解安全限制在哪一块和iframe之间互相的关系,无论页面放多少页面,都是会有办法解决的了,重在理解。

之后我再说一个关于iframe高度的恶心问题,上面刚才的做法,只是在页面onload的时候一次性设置了高度,可是如果iframe页面里有动态的效果需要随时改变document里面内容的高度呢?

没办法了,如果是你写的交互,你可以在需要改高度的地方都增加一次onload时候的方法,重新设置,如果不是你做的交互,那么如果为了方便,setInterval吧。。= =||
再之后iframe还有一些其他的功效吧。比如持久化的长连接,比如用来异步加载js模块,比如完成异步的表单提交,图片上传,比如没有ajax时候一些替代ajax的猥琐方案,比如用它在ie6里来遮挡select,比如实现富文本编辑器,等等等等了。

不得不说,你总会在各种地方面对它,理解它,不能怕它,而且短时间内它也不可能被淘汰,哪怕它每次被加载都会造成一次服务器端的请求,或者查询,但是目前来看,让它退出html标签舞台还只是个梦想。。

Read More

这次正经下定决心了,从基本用法到开发已经要搞定这货……

很多东西,搜到了之后不用又忘记,开一篇文章保存记录留做备份……

保存修改默认配色,显示行号,设置tab长度,语法高亮,自动缩进等等见注释,我会慢慢补充……
先 e: $Vimruntime/_vimrc 打开配置文件

"配色
colorscheme slate
"字体
set guifont=Monaco:h12:cANSI
"行号,行号栏目宽度
set nu
set numberwidth=2
"tab长度
set tabstop=2
"自动对齐
set autoindent
"语法高亮
syntax on
"设置gbk字符会有编码问题,设置字符集
set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936
"行间距
set linespace=2
"<>调整缩进时的长度
set shiftwidth=2
"初始化窗口宽度高度
set columns=150
set lines=30
"初始化窗口位置
winpos 52 42

"禁止自动换行
set nowrap
"在输入命令时列出匹配项目
set wildmenu
"显示光标位置
set ruler
"分割窗口保持相等宽高
set equalalways

"匹配括号规则,增加html的<>
set matchpairs=(:),{:},[:],<:>
"让退格,空格,上下箭头遇到行首位自动移到下一行(包括insert模式)
set whichwrap=b,s,<,>,[,]
"取消自动备份
set nobackup
"关闭文件之前保留一个备份
set writebackup

"js语法高亮脚本
let g:javascript_enable_domhtmlcss=1

"光标准星
set cursorline
hi cursorline guibg=NONE gui=underline
set cursorcolumn
hi cursorcolum gui=underline

"自动修改
set autoread

"不明字体宽度,按照double的来
set ambiwidth=double

"jQuery语法高亮
au BufRead,BufNewFile *.js set ft=javascript syntax=jquery

目前只设置了这几个,然后相关的js,html模板是从下面下载的:

JavaScript syntax : Better JavaScrirpt syntax support

html.vim

开启js,python自动缩进的几个文件下载

IndentAnything : Write indentations or enhance existing indentations without writing code
Javascript Indentation : Indentation for Javascript
indent/python.vim : An alternative indentation script for python

最后下载了一个目录树插件

The NERD tree : A tree explorer plugin for navigating the filesystem

jquery的语法

jQuery : Syntax file for jQuery

直接CD到相关目录:NERDTree就好了。

其他的慢慢补……

Read More