锁定老帖子 主题:网页插件开发总结
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-07
最后修改:2010-03-14
目前我们开发的产品涉及到大量的JavaScript,特别是前台的网页插件部分。因为这部分是一个网页中的第三方插件,是用户(站长或者blogger)通过在其网页上加入<script>标签来载入,所以和其他的JavaScript略有不同。
我总结一下,这部分功能有如下需求:
这部分的代码是我从去年下半年开始写的,到目前经过多次调整,目前结构已经基本稳定。对于上面提到的1、3、4已经很好的解决,而2和5则只是部分解决,至少我对目前的方案还不是很满意 。 loadModule: function(url, callback) { var script = d.createElement('script'); script.setAttribute('src', url); script.setAttribute('charset', "utf-8"); script.setAttribute('type','text/javascript'); if (callback) { script.onload = callback; script.onreadystatechange = function() { if (this.readyState == 'complete' || this.readyState == 'loaded') { callback(); } }; } d.getElementsByTagName("head")[0].appendChild(script); }
function onDocumentReady(callback){ // Mozilla, Opera and webkit if (document.addEventListener) { document.addEventListener("DOMContentLoaded", function(){ document.removeEventListener("DOMContentLoaded", arguments.callee, false); callback.call(this); }, false ); // If IE event model is used } else if (document.attachEvent) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent("onreadystatechange", function(){ if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", arguments.callee ); callback.call(this); } }); // If IE and not an iframe // continually check to see if the document is ready if (document. documentElement.doScroll && window == window.top) (function(){ if (isReady) return; try { // http://javascript.nwbox.com/IEContentLoaded/ document. documentElement.doScroll("left"); } catch( error ) { setTimeout(arguments.callee, 0); return; } callback.call(this); })(); } window.onload = callback; };
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-03-12
浏览器前端设计就是受煎熬的事情
|
|
返回顶楼 | |
发表时间:2010-03-14
(二)Ajax和Iframe的跨域通信
既然是网页插件,还用到了iframe,自然会涉及到跨域的问题。其实跨域的问题有很多种解决方案,比如XDomainRequest,Crossdomain XHR,还有让人期待的HTML5,可惜这些目前很多主流浏览器都不支持。其实Ajax的跨域还是很好解决的,目前最常用的就是JSONP了,即使没有jQuery,用前一篇里的loadModule函数也可以进行简单的JSONP调用。 不过iframe的跨域问题就有点棘手了。因为插件是在第三方页面上的,而我们的iframe是在我们自己的域名下面的,因此如果iframe里的内容有所更新,我们无法直接从iframe内来通知页面以更新页面上的内容或是改变iframe大小。 不过我们从这篇文章里找到解决方法,文章里作者提出了下面这一个定义和四个法则。 引用 定义:一个窗口可以指一个iframe或者是顶层窗口(即主窗口)
法则1:这个层级系统中任意一个窗口都可以获取到另一个窗口的对象。 法则2:只有同属一个域名的窗口才能相互存取它们的内部状态和数据。 法则3:这个层级系统中的任意一个窗口都可以设置(但不一定能读取)另一个窗口的URL,即使它们属于不同的域名。 法则4:当一个窗口的URL Fragment发生改变时,页面不会刷新。 作者其实提到了三种解决方法,但它们最基本的原理都是上面提到的那些法则。我们使用的是第一种方法,在iframe里通过设置主窗口的URL Fragment来给主窗口传递信息,而主窗口里的JavaScript则每隔100ms轮询一次处理消息并把URL Fragment复位。主窗口中的代码如下: setInterval(function() { var h = window.location.hash; if (h.substring(0,7) == "#height") { window.location.hash = "#_"; currentHeight = parseInt(h.substring(8), 10); adjustPostion(currentHeight); } else if (…) { …… } }, 100); 在IFrame中则用如下代码传递消息: window.parent.location.href = srcUrl + "#height=280"; 或者 parent.window.location.hash = “height=280”; 前者代码里的的srcUrl就是主窗口的URL;后者更方便,但有时在IE下面好像有问题,所以我们还是用的前者。 当然这个方法也有副作用,首先你需要去轮询,必然就会有延迟,而且会改变主窗口的URL(多一个Fragment)。不过对我们来说都还可接受。作者还提到了另外两个方法,都是通过第三个隐藏的iframe作为proxy来避免轮询和改变主窗口URL。一种是每次发送消息时就创建一个proxy iframe,发送完就关掉;另一种是只创建一个proxy iframe,并同过window.resize和监控resize事件来通知proxy iframe有新的消息。可惜这两个方法我们都没法用。因为它们都要求创建一个和主窗口在同一个域名下的iframe,再由此iframe内的JavaScript来传递消息给主窗口,而主窗口是第三方网页,其域名根本不在我们的控制范围内……当然在一定的情况下,这两种方法还是有用的,有兴趣的可以参考原文。 参考: Cross-Domain Communication with IFrames http://softwareas.com/cross-domain-communication-with-iframes |
|
返回顶楼 | |
浏览 5197 次