专注 专注再专注

mikel阅读(1012)

先从最近研究的一个有意思的技术谈起,iFrame的跨域访问,实际案例里就是现在很多人在卖的QQ访客系统

什么是QQ访客系统?

你的网站页面嵌入一段代码,然后访问你的人的QQ号都能被获取到,并且通过什么关键词访问的你的网站都能获取到,这样你就可以根据具体关键词直接联系他的QQ或者跟给他发邮件。

例如有个人通过“xxx产品报价”关键词访问的你的网站,看看之后就走了,通过这个系统你可以获取他的QQ,并知道他是通过查询报价进来的,很明显,这就是你的潜在客户,如果你给他发个报价邮件或者直接联系他QQ很可能就促成一笔订单。

技术上宽泛的说就是跨域访问QQ的页面获取来访者的浏览器cookie从而获取曾经登陆的QQ号。

很多搞技术的人对这个原理都知道,可是真正深入专注的去研究去实现的很少,都是知其然,不知其所以然!

我也早就知道这个原理,当时就一带而过,认为自己知道原理就行了,没啥难度,就没研究。

最近有朋友需要,我于是就深入的去研究了下,发现不是那么简单的,涉及很多知识,包括跨域访问的方式,包括QQ协议的解析,多浏览器的iframe的内容获取等等技术点。

通过这件事,觉得自己太浮躁,不够专注,其实程序员互联网上创业转型只要你专注于一点,把握好未来趋势,然后狠狠的钻研开发出用户体验好的产品很容易就能成功。

从技术再谈到网络营销,很多人都喜欢加很多的营销群,报很多的培训班,拜那些多营销大师为师,我感觉没必要!专注盯着几个顶尖的大牛就ok了,就像技术界那些国外牛人开发的开源框架一样,你能够通过看人家的源代码会从中学到很多东西,营销大牛的文章和视频就是人家经验的总结,专注研究消化为己用足以!

最近在读周鸿伟的《我的互联网方法论》很有感触, 里面也谈到专注用户痛点,解决用户痛点,做好用户体验,没必要大而全,只需要做对做好一件事,专注,专注再专注。

以后市场会越来越挑剔,没有亮点的产品很难生存!

[转载]由Tencent://Message协议想到的一个解决方案 - Phinecos(洞庭散人) - 博客园

mikel阅读(1233)

[转载]由Tencent://Message协议想到的一个解决方案 – Phinecos(洞庭散人) – 博客园.

源代码下载:http://files.cnblogs.com/phinecos/HelloWorldProtocal.rar

前天在BruceZhang 的一篇博文《求助:如何在ASP页面中调用Winform程序呢?》中回答了他提出的问题,但细想下觉得我的思路有误。

    今天在试用WebQQ的时候,无聊中想起很多人的博客上都有这样的小玩意,点击下就可以和博主进行对话,而且无需加博主为好友。

哎,这样的方式不就正好是BruceZhang那个问题的解决方案吗?那么腾讯是怎么做到在Web页面中调用QQ程序的呢?

先来看腾讯提供给我们的代码:

<href=”tencent://message/?uin=88888888&Site=JooIT.com&Menu=yes”>
<img border=”0″ SRC=’http://is.qq.com/webpresence/images/status/01_online.gif’ alt=”点击这里给我发消息”>
</a>

    很显然,奥妙就在“tencent://message/?uin=215555521&Site=JooIT.com&Menu=yes”这里,那这又到底是什么原理呢?

先扯开话题按自己的思路来想,要打开本地的QQ,肯定要分两步走,首先是定位到QQ,然后是传递给它一些参数,也就是“uin=215555521&Site=JooIT.com&Menu=yes”这样的东西。定位的话,借助注册表是最明显的方式了。可怎么把QQ跑起来呢?要我们自己去启动一个进程么?答案是否定的,Windows操作系统考虑了这一点,允许我们为自己的应用程序注册为一个协议处理者,具体参见MSDN上的文章《Registering an Application to a URL Protocol

腾讯的Tencent://Message协议注册表如下:

复制代码

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Tencent]
@=TencentProtocol
URL Protocol=D:\\Program Files\\Tencent\\QQ\\Timwp.exe

[HKEY_CLASSES_ROOT\Tencent\DefaultIcon]
@=D:\\Program Files\\Tencent\\QQ\\Timwp.exe,1

[HKEY_CLASSES_ROOT\Tencent\shell]

[HKEY_CLASSES_ROOT\Tencent\shell\open]

[HKEY_CLASSES_ROOT\Tencent\shell\open\command]
@=\D:\\Program Files\\Tencent\\QQ\\Timwp.exe\ \%1\“”

复制代码

 此注册表所实现的就是当浏览器(或其它)碰到 tencent://… 时,自动调用 Timwp.exe,并把 tencent://… 地址作为第一个参数传递给 Timwp.exe

 废话不多说,下面就动手实验一个demo来说明一切,源代码请在文章首部自行下载。 很简单的功能,就是显示传递给MFC Dialog程序的参数值。就只分析下我添加的代码:

     首先需要获取传入的参数,在控制台程序中我们都知道main()函数的参数argv里带入了传入的参数,而在MFC程序中则需要在InitInstance()中进行命令行参数解析。

    CCommandLineInfo   cmdInfo;
ParseCommandLine(cmdInfo);

     为了给对话框传入待显示的参数,加入了一个SetDisplayInfo方法。

    CHelloWorldDlg dlg;
dlg.SetDisplayInfo(cmdInfo.m_strFileName);
//设置待显示的信息

 

void CHelloWorldDlg::SetDisplayInfo(CString& strInfo)
{
this->m_strInfo = strInfo;
}

     最后在OnInitDialog函数中进行参数解析

    //解析传入的完整地址,e.g “helloworld://hello world/”
    int pos = m_strInfo.Find(//);//找到分隔符
    m_strInfo = m_strInfo.Mid(pos+2);//取到传入的参数
    m_strInfo.Delete(m_strInfo.GetLength()1);//去掉最后的’/’
    m_edit_info.SetWindowText(m_strInfo);

     好了,来到最关键的步骤了,在注册表中为我们自定义的helloworld协议建立起注册表项,从而让HelloWorld应用程序支持此协议。将如下的注册表项加入即可,这里为了简单起见我直接用一个.reg文件来实现,也可以用其他方式进行:

复制代码

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\HelloWorld]
@
=HelloWorld Protocol
URL Protocol=“”

[HKEY_CLASSES_ROOT\HelloWorld\DefaultIcon]
@
=D:\\My Documents\\Visual Studio 2005\\Projects\\HelloWorld\\release\\HelloWorld.exe,1

[HKEY_CLASSES_ROOT\HelloWorld\shell]
@
=“”

[HKEY_CLASSES_ROOT\HelloWorld\shell\open]
@
=“”

[HKEY_CLASSES_ROOT\HelloWorld\shell\open\command]
@
=\D:\\My Documents\\Visual Studio 2005\\Projects\\HelloWorld\\release\\HelloWorld.exe\ \%1\“”

复制代码

结果如图所示

     好了,这下可以来测试helloworld协议了,在地址栏中输入:helloworld://hello world/,怎么样,下面的画面出来了吧,

     再来到web页面进行测试,修改上面的html代码如下:

复制代码

<html>
<head></head>
<body>
<div>
<href=”helloworld://hello world”>
<img border=”0″ SRC=’http://is.qq.com/webpresence/images/status/01_online.gif’ alt=”点击这里给我发消息”>
</a>
</div>
</body>
</html>

复制代码

    若是要在web页面调用本地的winform程序,同理也是可行,不过我不大懂.net,有心的朋友请试试看。

参考资料:

1, Registering an Application to a URL Protocol

2, Tencent://Message/协议的实现原理

3仿腾讯 QQ 和 Skype 通过URL触发自己的程序

4,Register protocol

作者:洞庭散人

 

出处:http://phinecos.cnblogs.com/

本博客遵从Creative Commons Attribution 3.0 License,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。

[转载]Tencent://Message/协议的实现原理 - zzh - 博客园

mikel阅读(1096)

 

[转载]Tencent://Message/协议的实现原理 – zzh – 博客园.

腾讯官方通过 Tencent://Message/协议可以让QQ用户显示QQ/TM的在线状态发布在互联网上;并且点击 ,不用加好友也可以聊天:

官方链接: http://is.qq.com/webpresence/code.shtml

具体代码:

<a href=”tencent://message/?uin=215555521&Site=JooIT.com&Menu=yes”>
<img border=”0″ SRC=’http://wpa.qq.com/pa?p=1:215555521:3′ alt=”点击这里给我发消息”>
</a>

但它是如何实现的呢?下面文章以及微软官方说明详细解释了其工作原理:


 

微软官方说明:http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/pluggable/overview/appendix_a.asp

Register protocol,此文中对于 Windows、Linux 和 OS X 操作系统如何注册协议都有说明。比如说 Windows,其实只需写入注册表,即可实现协议与执行程序的关联。例如腾讯的Tencent://Message协议注册表如下:

[HKEY_CLASSES_ROOT\TENCENT]
@=”TencentProtocol”
“URL Protocol”=”D:\\Program Files\\Tencent\\QQ\\Timwp.exe”

[HKEY_CLASSES_ROOT\TENCENT\DefaultIcon]
@=”D:\\Program Files\\Tencent\\QQ\\Timwp.exe,1″

[HKEY_CLASSES_ROOT\TENCENT\shell]

[HKEY_CLASSES_ROOT\TENCENT\shell\open]

[HKEY_CLASSES_ROOT\TENCENT\shell\open\command]
@=”\”D:\\Program Files\\Tencent\\QQ\\Timwp.exe\” \”%1\””

此注册表所实现的就是当浏览器(或其它)碰到 tencent://… 时,自动调用 Timwp.exe,并把 tencent://… 地址作为第一个参数传递给 Timwp.exe。

更多参见:Registering an Application to a URL Protocol。 


附:原文

A protocol is a method that is used to send, receive, and handle information over a connection. Common protocols viewed from the browser include http, ftp, and mailto. In order for you to view information sent over a specific protocol, it must be registered. Once registered, the protocol can then be handled by the program you specify, such as your browser or a 3rd party viewer. This means that a hyperlink ( e.g. foo://fred ) can use the handler for protocol foo to open the file named fred. 

Contents [hide]
1 Registering an unsupported protocol 
1.1 Windows 
1.2 Linux 
1.3 OS X 
2 Redirecting a registered protocol 



[edit]Registering an unsupported protocol
Mozilla products utilize protocols defined internally, as well as those defined by the operating system. You can add the ability to use an unsupported protocol by registering it. The OS-specific method of doing this is described below. 

[edit]Windows
Create the registry .reg file, replacing foo with your unregistered protocol, and the path with whatever handler program you want to run. Then merge it into the Windows registry.


REGEDIT4

[HKEY_CLASSES_ROOT\foo]
@="URL:foo Protocol"
"URL Protocol"=""

[HKEY_CLASSES_ROOT\foo\shell]

[HKEY_CLASSES_ROOT\foo\shell\open]

[HKEY_CLASSES_ROOT\foo\shell\open\command]
@="\"C:\\Program Files\\Application\\program.exe\" \"%1\"" 
See Registering an Application to a URL Protocol for additional information. 

[edit]Linux
Registration is unnecessary. Simply associate whatever proto: with a program through Firefox: Example: Add the sip: protocol to launch kphone for VoIP calls in Firefox: 

- Type about:config into the address bar
- Right-click create new boolean value: network.protocol-handler.external.sip and set to true
- Right-click create new boolean value: network.protocol-handler.warn-external.sip and set to false
- Right-click create new string value: network.protocol-handler.app.sip and set to /usr/bin/kphone
This will actually launch kphone. Not sure if it will dial though. That is untested :) 

You can also optionally register the protocol with whatever window manager you are using. In KDE this is done through Control Center - KDE Components - File Associations. This step is usually unnecessary unless your window manager has a custom browser, such as konqueror.

[edit]OS X
Probably very similar to Linux (above). 

[edit]Redirecting a registered protocol
If the protocol is already handled by the browser, you can specify what program will be used as a handler to open the file. To do this, add the pref:
network.protocol-handler.app.foo as a string with value C:\Program Files\Application\program.exe
Note: If the path or name is incorrect, the browser will display an error saying "protocol (foo) isn't associated with any program". (See bug 312953).

You may also need to use the following prefs, although this is uncertain:
network.protocol-handler.external.foo = true
network.protocol-handler.expose.foo = false

[转载]鲜为人知的QQ自动强制加好友代码_QQ技巧_QQ地带

mikel阅读(1629)

转载鲜为人知的QQ自动强制加好友代码_QQ技巧_QQ地带.

是的,你也许见过强行聊天的代码:

 tencent://Message/?Uin=574201314&websiteName=www.oicqzone.com&Menu=yes

 

但是你应该不知道,还有强行加好友的代码:

tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=574201314&fuin=938065079&website=www.oicqzone.com

 

用浏览器打开以上的地址,会提示:

是的fuin代表主动添加的一方,uin是被加的一方,你也可以去掉fuin,如:

tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=574201314&website=www.oicqzone.com

 

把574201314换成你自己的就可以啦。在网页上放置这样的链接,别人点击可以直接添加你的QQ啦。

比如html:

点击添加我的QQ为好友

代码:

 

  1. <a href=“tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=574201314&website=www.oicqzone.com”>点击添加我的QQ为好友</a>

你还可以在网页里添加跳转代码,打开网页自动添加你为好友哦。以下代码需要添加在head里。

 

  1. <meta http-equiv=“refresh” content=“0; url=tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=574201314&website=www.oicqzone.com”>

 

当然啦,如果你是想批量添加好友,可以下载批量加QQ好友软件

[转载]Iframe跨域通信完美解决方案 | 我爱互联网

mikel阅读(1229)

[转载]Iframe跨域通信完美解决方案 | 我爱互联网.

跨域通信这个话题在之前已经提到总结过,关于跨域通信大家可以参考同源策略跨域资源共享的10种方式以及IE下因设置document.domain而无法和Iframe通信的解决方法

以前在项目中开发了不少跨域功能,但都比较依赖项目,今天我将跨域功能模块抽出并精简为一个通用的javascript包,它用纯js实现,不依赖于flash,而且已经包含了目前最常用的跨域通信方法:window.postMessagewindow.name,大家只需简单引用即可实现单向双向跨域通信,非常方便。使用方法如下(将下面的代码同时放到要跨域通信的两个页面中)引入xd.js:

&lt;<a title="script" href="http://www.woiweb.net/tag/script">script</a> type='text/<a title="javascript" href="http://www.woiweb.net/tag/javascript">javascript</a>' src='http://crossdomain.sinaapp.com/xd/xd.js'&gt;

添加监听回调函数

var callback = function(data) {
//data为返回的json对象
}
XD.receiveMessage(callback);

调用跨域通信方法

//target:跨域通信的window对象,parent或iframe.contentWindow
//json:要发送的数据对象,json格式,如:{'height':'300px'}
XD.sendMessage(target, json);

Over

至此,一个双向跨域的功能已经完成了,这个方案有一个小小的缺陷,就是会重写window.name,所以请避免在开发中借用window.name来传递数据。

光看代码可能还不太清晰,来看个demo,给大家个使用比较频繁的示例:iframe高度自适应,如有不明白可留言或@woiweb

demo下载

[转载]谷歌专题-设定控

mikel阅读(1430)

[转载]谷歌专题-设定控.

谷歌被封,实乃国内学术界一大悲剧。有人不断为当局洗地,强调谷歌搜索为网络间谍,这里只能说一句:政治已经很脏了,你们这些键盘斗士自己玩屎就可以了,不要把这些脏东西泼在专心治学的人身上。

 

另外,谷歌并非完全被封,很多时候和地域有关,这里提供多种访问谷歌的方式,请多次尝试。

 

 

 

1.谷歌复原 

 

网址: http://www.Google.com.im/
谷 歌复原 ( Google.com.im ) 是由 Google Fans 于2010年创办的非营利性、基于 Google Search Engine 的搜索项目,旨在纪念2010年退出中国市场的谷歌公司,帮助国内的用户取得最好的搜索体验。谷歌公司拥有全球各个地区400多个以“Google”为前 缀的域名,但唯独缺少“.com.im”为后缀的域名,因此本站并不同于官方的其它站点。速度较慢。

 

 

 

2.Googlestable

 

网址:http://www.googlestable.com/

 

目前最稳定且高速,但是只能进行普通搜索和图片搜索

 

 

 

3.Googleout

 

网址:http://www.googleout.com/

 

速度和前面的Googlestable 一样,不过只能进行网页搜索。

 

类似站点

 

wen.lu

 

www.opengg.cn

 

http://www.ose.cc/

 

4.Google 全球 IP 地址库

 

网址:https://github.com/justjavac/Google-IPs

 

失效的已经很多了

 

 

 

5.Chrome 浏览器设置

 

在Chrome 浏览器中打开「实验性功能」页面(chrome://flags/),启用「实验性 QUIC 协议」和「经由实验性 QUIC 协议发出的 HTTPS 请求」,重启浏览器后可以正常登陆 Google 相关服务。

 

 

 

6.免翻墙镜像

 

网址:https://github.com/greatfire/wiki

 

不稳定,另外那个自由微博的可信度存疑

 

 

 

7.美国在线

 

http://www.aol.com/

 

该站搜索结果就是谷歌的结果,速度很快。

 

 

 

8.Baigoogledu.com

 

http://www.baigoogledu.com/

 

百度谷歌出现在同一界面上的搜索引擎,之前因为技术问题,该站将谷歌换成了必应,现在已经将问题解决,不过部分地区谷歌的搜索结果仍然无法显示。

 

 

 

9.Startpage

 

网址:https://startpage.com/

 

基于谷歌搜索结果的隐私安全搜索引擎,说它是隐私安全搜索是因为它(自称)不会保留用户的ip地址信息,也不会把这些信息提供给谷歌。当然你们不在乎这个,它最让我们喜欢的是,其搜索结果是基于谷歌的,虽然顺序会略有不同,不过应该比百度更加精准。

 

有中文界面,不过没什么区别,当然支持中文内容的检索,不过底下的搜索结果页数有时显示不出来。比谷歌优秀的是,没有恼人的定向广告。我以前还常用一款类似的印度颠覆者搜索引擎,那个不依靠谷歌,不用考虑谷歌的政治偏向,结果不是很精确,但还不错,可惜被墙了。

 

 

 

10.glgoo

 

https://www.glgoo.com/

 

上面的几个一般只能实现网页搜索,这个的学术搜索http://scholar.glgoo.com/ 没有问题。

 

类似站点

 

www.gfsoso.com(可搜索学术、图片)

 

http://www.gvgle.com/

 

http://music.google.cn/webhp

 

https://www.sssis.com/

 

http://www.886404.com/

 

 

 

11.百度浏览器

下载百度浏览器,访问时浏览器会自动跳转至“https://”模式,速度快覆盖广,某不存在引擎的搜索、地图、邮箱等均可使用╮(╯▽╰)╭ 真是美好的爱情啊。

[转载]iframe跨域问题 - wensongyu - 博客园

mikel阅读(1043)

[转载]iframe跨域问题 – wensongyu – 博客园

一般分两种情况:

一、 是同主域下面,不同子域之间的跨域;

同主域,不同子域跨域,设置相同的document.domian就可以解决;

父页访问子页,可以document.getElementById(“myframe”).contentWindow.document来访问 iframe页面的内容;如果支持contentDocument也可以直接 document.getElementById(“myframe”).contentDocument访问子页面内容;

子页访问父页,可以parent.js全局属性

二、 是不同主域跨域;

前提,www.a.com下a.html,a.html内iframe调用了www.b.com下的b.html,b.html下iframe调用了www.a.com下的c.html

b.html是不无法直接访问a.html的对象,因为涉及到跨域,但可以访问parent,同样c.html的parent可以访问b.html。c.html和a.html同域,是可以访问a下的对象的。parent.parent.js对象!

 

来源:http://www.cnblogs.com/pigtail/archive/2013/01/24/2875310.html

 

 

很多人一直都有个想法,要是可以随心所欲的操作iframe就好了。这样静态页面也就有了相当于后台动态页面php,jsp,asp中include,require实现统一多页面布局的能力。

通过JavaScript的帮忙我们可以像后台一样动态加载操作iframe对象属性src指向的html页面的内容。这样的操作需要提供两个页面,一个页面是iframe所在页面(页面名称:iPage.html),另一个页面是iframe属性src指向页面(页面名称:srcPage.html)。

iPage.html,<body>里dom:

  1. <iframe id=“iId“ name=“iName“ src=“srcPage.html“ scrolling=“no“ frameborder=“0“></iframe>

srcPage.html,<body>里dom:

  1. <h1>妹妹的一天</h1>
  2. <p>早上吃早点,中午约会吃饭,下午K歌,晚上和哥哥瞎折腾</p>

下面讨论ie下JS是怎么操作以上两个页面,再讨论firefox的做法,最后给出兼容ie,firefox浏览器操作iframe对象的方法。

一、ie下访问操作iframe里内容

大家都知道iframe是非标准html标签,它是由ie浏览器推出的多布局标签, 随后Mozilla也支持了这个标签。(闲话,嘿嘿)

1. ie通过document.frames[“IframeName”]获取它,例子:我们在iPage.html里输出srcPage.html里h1的内容,JS如下:

  1. alert(document.frames[“iName”].document.getElementsByTagName(‘h1‘)[0].firstChild.data);

你会发现这样在页面里加入代码,好像并没有输出想要的东东,为什么呢?这个我也没有搞清楚,只是习惯性的加入了window.onload就有输出 了(注:JS代码都写到这个事件里去),知道的人士可否告诉我下。why?更改之后代码ie下有了输出,firefox下document.frames 没有定义错误提示:

  1. window.onload = (function () {
  2.   alert(document.frames[“iName”].document.getElementsByTagName(‘h1‘)[0].firstChild.data);
  3. });

2. ie另一种方法contentWindow获取它,代码:

  1. window.onload = (function () {
  2.  var iObj = document.getElementById(‘iId‘).contentWindow;
  3.  alert(iObj.document.getElementsByTagName(‘h1‘)[0].firstChild.data);
  4. });

此方法经过ie6,ie7,firefox2.0,firefox3.0测试都通过,好事啊!嘿嘿。(网上一查,发现Mozilla Firefox iframe.contentWindow.focus缓冲区溢出漏洞,有脚本注入攻击的危险。

后来听说可以在后台防止这样的事情发生,算是松了口气。不过还是希望firefox新版本可以解决这样的危险。)

3.改变srcPage.html里h1标题内容,代码:

  1. iObj.document.getElementsByTagName(‘h1‘)[0].innerHTML=‘我想变成她一天的一部分‘;

通过contentWindow后访问里面的节点就和以前一样了。

二、firefox下访问操作iframe里内容

Mozilla支持通过IFrameElmRef.contentDocument访问iframe的document对象的W3C标准,通过标准可以少写一个document,代码:

  1. var iObj = document.getElementById(‘iId‘).contentDocument;
  2. alert(iObj.getElementsByTagName(‘h1‘)[0].innerHTML=‘我想变成她一天的一部分‘);
  3. alert(iObj.getElementsByTagName(‘p‘)[0].firstChild.data);

兼容这两种浏览器的方法,现在也出来了,就是使用contentWindow这个方法。

嘿嘿!操作iframe是不是可以随心所欲了呢?如果还觉得不爽,你甚至可以重写iframe里的内容。

三、重写iframe里的内容

通过designMode(设置文档为可编辑设计模式)和contentEditable(设置内容为可编辑),你可以重写iframe里的内容。代码:

  1. var iObj = document.getElementById(‘iId‘).contentWindow;
  2. iObj.document.designMode = ‘On‘;
  3. iObj.document.contentEditable = true;
  4. iObj.document.open();
  5. iObj.document.writeln(‘<html><head>‘);
  6. iObj.document.writeln(‘<style>body {background:#000;font-size:9pt;margin: 2px; padding: 0px;}</style>‘);
  7. iObj.document.writeln(‘</head><body></body></html>‘);
  8. iObj.document.close();

这两个对象的资料可参考:http://msdn.microsoft.com/en-us/library/ms533720(VS.85).aspx

firebug测试以上代码性能,如图

注释掉 iObj.document.designMode = ‘On’;

iObj.document.contentEditable = true;

如图:

效果没有变,时间效率是注释前的将近三倍。嘿嘿。那两个对象是参考网络一些人的写法,重写iframe里内容,其实没有必要用designMode和contentEditable,除非有其他的需求。

四、iframe自适应高度

有了上面的原理要实现这个相当简单,就是把iframe的height值设置成它里面文档的height值就可以。代码:

  1. window.onload = (function () {
  2. var iObj = document.getElementById(‘iId‘);
  3. iObj.height =  iObj.contentWindow.document.documentElement.scrollHeight;
  4. });

现在对JS操作iframe你已经有了全新的认识,说不定那天会因为这个有什么新的web技术名词,嘿嘿,臭美下!

 

来源:http://www.kuqin.com/webpagedesign/20081109/26336.html

[转载]使用 window.name 解决跨域问题 _ PlanABC – 怿飞’s Blog

mikel阅读(1128)

[转载]使用 window.name 解决跨域问题 _ PlanABC – 怿飞’s Blog.

window.name 传输技术,原本是 Thomas Frank 用于解决 cookie 的一些劣势(每个域名 4 x 20 Kb 的限制、数据只能是字符串、设置和获取 cookie 语法的复杂等等)而发明的(详细见原文:《Session variables without cookies》),后来 Kris Zyp 在此方法的基础上强化了 window.name 传输 ,并引入到了 Dojo dojox.io.windowName),用来解决跨域数据传输问题。

window.name 的美妙之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

window.name 传输技术的基本原理和步骤为:
window.name 技术的基本原理和步骤图示

name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面时,name 的属性值依旧保持不变。通过在 iframe 中加载一个资源,该目标页面将设置 frame 的 name 属性。此 name 属性值可被获取到,以访问 Web 服务发送的信息。但 name 属性仅对相同域名的 frame 可访问。这意味着为了访问 name 属性,当远程 Web 服务页面被加载后,必须导航 frame 回到原始域。同源策略依旧防止其他 frame 访问 name 属性。一旦 name 属性获得,销毁 frame 。

在最顶层,name 属性是不安全的,对于所有后续页面,设置在 name 属性中的任何信息都是可获得的。然而 windowName 模块总是在一个 iframe 中加载资源,并且一旦获取到数据,或者当你在最顶层浏览了一个新页面,这个 iframe 将被销毁,所以其他页面永远访问不到 window.name 属性。

基本实现代码,基于 YUI,源自克军写的样例

(function(){
    var YUD = YAHOO.util.Dom, YUE = YAHOO.util.Event;

    dataRequest = {
        _doc: document,
        cfg: {
            proxyUrl: 'proxy.html'
        }
    };

    dataRequest.send = function(sUrl, fnCallBack){
        if(!sUrl || typeof sUrl !== 'string'){
            return;
        }

        sUrl += (sUrl.indexOf('?') > 0 ? '&' : '?') + 'windowname=true';

        var frame = this._doc.createElement('iframe'), state = 0, self = this;
        this._doc.body.appendChild(frame);
        frame.style.display = 'none';

        var clear = function(){
            try{
                frame.contentWindow.document.write('');
                frame.contentWindow.close();
                self._doc.body.removeChild(frame);
            }catch(e){}
        };

        var getData = function(){
            try{
                var da = frame.contentWindow.name;
            }catch(e){}
            clear();
            if(fnCallBack && typeof fnCallBack === 'function'){
                fnCallBack(da);
            }
        };

        YUE.on(frame, 'load', function(){
            if(state === 1){
                getData();
            } else if(state === 0){
                state = 1;
                frame.contentWindow.location = self.cfg.proxyUrl;
            }
        });

        frame.src = sUrl;
    };
})();

Web 服务器如何提供 window.name 数据

为了让 Web 服务器实现 window.name,服务器应该只寻找请求中是否包含 windowname 参数。如果包含了 windowname 参数,服务器应该返回一个设置了 window.name 字符串值的 HTML 文档,回应此请求并传送到客户端。例如:
http://www.planabc.net/getdata.html?windowname=true

如果服务器想用 Hello 响应客服端,它应该返回一个 HTML 页面:

<html>
    <script type="text/javascript">
        window.name="Hello";
    </script>
</html>

同样也可以转换为 JSON 数据:

<html>
    <script type="text/javascript">
        window.name='{"foo":"bar"}';
    </script>
</html>

如果你手动创建资源,书写大量的多行的 JSON 对象为一个引用的字符串应该是比较困难的并且易于出错的。可以使用这样的 HTML 样例简单的创建 JSON 数据,将会转换为一个 JSON 字符串而无需手动转义 JSON 为字符串:

<html>
    <script type="\'text/javascript\'">
        window.name = document.getElementsByTagName("script")[0].innerHTML.match(/temp\s*=([\w\W]*)/)[1];
        temp= {
            foo:"bar", // put json data here
            baz:"foo"
        }
    </script>
</html>

同样的,如果你想传递 HTML/XML 数据,这里有一个样例实现,而无需手动将这些数据转换成字符串:

<html>
    <body>
        <p id="content">
            some <strong>html/xml-style</strong>data
        </p>
    </body>
    <script type="text/javascript">
        window.name = document.getElementById("content").innerHTML;
    </script>
</html>

window.name 传输技术相比其他的跨域传输的一些优势:

它是安全的。也就是说,它和其他的基于安全传输的 frame 一样安全,例如 Fragment Identifier messaging (FIM)和 Subspace。(I)Frames 也有他们自己的安全问题,由于 frame 可以改变其他 frame 的 location,但是这个是非常不同的安全溢出,通常不太严重。
它比 FIM 更快,因为它不用处理小数据包大小的 Fragment Identifier ,并且它不会有更多的 IE 上的“机关枪”声音效果。它也比 Subspace 快,Subspace 需要加载两个 Iframe 和两个本地的 HTML 文件来处理一个请求。window.name 仅需要一个 Iframe 和一个本地文件。
它比 FIM 和 Subspace 更简单和安全。FIM 稍微复杂,而 Subspace 非常复杂。Subspace 也有一些额外的限制和安装要求,如预先声明所有的目标主机和拥有针对若干不同特殊主机的 DNS 入口。window.name 非常简单和容易使用。
它不需要任何插件(比如 Flash)或者替代技术(例如 Java)。

[转载]JS iframe 跨域 - wujiajun1020 - ITeye技术网站

mikel阅读(1104)

[转载]JS iframe 跨域 – wujiajun1020 – ITeye技术网站.

方案一、剪贴板

原理:IE本身依附于windows平台的特性为我们提供了一种基于iframe,利用内存来“绕行”的方案,在这里我称之为,本地存储原理。

缺点:不支持非IE浏览器,并且影响到用户对剪贴板的操作,用户体验非常不好,特别是在IE7下,受安全等级影响,会弹出提示框。

 

子页面在子域:demo.ioldfish.cn下,在页面中加入如下代码获取页面高度并存入剪贴板。

  1. <script type=text/JavaScript>
  2. var ua = navigator.userAgent;
  3. if ((i = ua.indexOf(MSIE)) >= 0) 
  4. {
  5.  var iObjH = window.document.documentElement.scrollHeight;
  6.  window.clipboardData.setData(text,String(iObjH));
  7. }
  8. </script>

主页面在主域:www.ioldfish.cn下,在页面中加入如下代码,获取剪贴板的值并赋值为子页面所在的iframe的高度。

  1. <script type=text/JavaScript>
  2. window.onload = function()
  3. {
  4.  var iObj =document.getElementById(iId);
  5.  iObj.style.height=parseInt(window.clipboardData.getData(text))+px;
  6. }
  7. </script>

方案二、document.domain

原理:设置了document.domain,欺骗浏览器

缺点:无法实现不同主域之间的通讯。并且当在一个页面中还包含有其它的iframe时,会产生安全性异常,拒绝访问。

主页面在主域:www.ioldfish.cn下,子页面在子域:demo.ioldfish.cn下,在两个页面的头部都加入如下代码:

  1. <script type=text/javascript>
  2.  document.domain=ioldfish.cn;
  3. </script>

方案三、通过JS获取hash值实现通讯

原理:hash可以实现跨域传值实现跨域通讯。

缺点:对于父窗口URL参数动态生成的,处理过程比较复杂一些。并且IE之外的浏览器遇到hash的改变会记录历史,影响浏览器的前进后退功能,体验不佳。

 

子页面在主域:www.lzdaily.com下,在页面中添加如下代码,因为hash是不受跨域限制的,所以可以将本页面的高度顺利的传送给主页面的hash。

  1. <script type=text/javascript>
  2.  var hashH = document.documentElement.scrollHeight;
  3.  var urlA = http://www.ioldfish.cn/wp-content/demo/domain/hash/a2.html;
  4.  parent.location.hrefurlA+#+hashH;
  5. </script>

主页面在主域:www.ioldfish.cn下,在页面中添加如下代码,首先取得子页面传递过来的hash值,然后将hash值赋到子页面所在的iframe的高度上。

  1. <script type=text/javascript>
  2. window.onload = function()
  3. {
  4.  var iObj = document.getElementById(iId);
  5.  if(location.hash)
  6.  {
  7.   iObj.style.height=location.hash.split(#)[1]+px;
  8.  }
  9. }
  10. </script>

方案四、传hash值实现通讯改良版

原理:该方案通过“前端代理”的方式,实现hash的传值,体验上比之方案三有了很大的提升。

缺点:对于父窗口URL参数动态生成的,处理过程比较复杂一些。

子页面在主域:www.lzdaily.com下,在页面中添加如下代码,首先在页面里添加一个和主页面同域的iframe[也可动态生成],他的作用就像是个跳板。C页面中不需任何代码,只要确保有个页面就防止404错误就可以了!该方法通过修改iframe的name值同样可以跨域传值,只是比较”猥琐“而已。

  1. <iframe id=iframeC name=iframeC src=http://www.ioldfish.cn/wp-content/demo/domain/hashbetter/c.html frameborder=0 height=0></iframe>

然后在页面中加上如下代码,利用页面C的URL接收hash值,并负责把hash值传给同域下的主页面。

  1. <script type=text/javascript>
  2.  hashH = document.documentElement.scrollHeight;
  3.  urlC = http://www.ioldfish.cn/wp-content/demo/domain/hashbetter/c.html;
  4.  document.getElementById(iframeC).src=urlC+#+hashH;
  5. </script>

主页面在主域:www.ioldfish.cn下,在页面中添加如下代码,获取从C页面中传递过来的hash值。这里应用到一个技巧,就是直接从A页面用frames[“iId”].frames[“iframeC”].location.hash,可以直接访问并获取C页面的hash值。这样一来,通过代理页面传递hash值,比起方案三,大大提高了用户体验。

  1. <script type=text/javascript>
  2. window.onload = function()
  3. {
  4.  var iObj = document.getElementById(iId);
  5.  iObjH = frames[iId].frames[iframeC].location.hash;
  6.  iObj.style.height = iObjH.split(#)[1]+px;
  7. }
  8. </script>

方案五、JSONP

原理:有点脚本注入的味道

缺点:服务器端程序运行比脚本早,跨域交互时无法捕获前端页面元素的相关数据,比如自适应高度。


主页面在主域:www.ioldfish.cn下,在页面中添加如下代码,动态创建一个script,然后指定到子域的动态文件,在动态文件后面可以添加参数,在这里我加了一个回调函数,当请求返回后,会运行这个回调函数。

1. <script type=”text/javascript”>
2. function loadContent()
3. {
4.  var scriptDom=document.createElement(‘script’);
5.  var url = “http://www.lzdaily.com/domain/jsonp/Test.aspx?f=setDivContent'”;
6.  scriptDom.src= url;
7.  document.body.appendChild(scriptDom);
8. } 
9. function setDivContent(love)
10. {
11.  var fishDiv = document.getElementById(“oldFish”);
12.  fishDiv.innerHTML = love;
13. }
14. </script>

子页面在主域:www.lzdaily.com下,在页面中添加如下代码,首先先取得主页面传过来的回调函数名,然后生成一段 javascript代码,以回

调函数带参数的形式返回主页面,这样就完成了跨域之间的通讯。由于服务器端程序执行总是优先于javascript代码,所以基本上没办法获取

到子页面中DOM的相关数据,所以小白同学,我可以很负责人的告诉你,想通过这种方法实现跨域自适应高度是不可能的!

1. <script language=”C#” runat=”server”>
2. void Page_Load(object sender, EventArgs e)
3. {
4.   string f = Request.QueryString[“f”];
5.   Response.Clear();
6.   Response.ContentType = “application/x-javascript”;
7.   Response.Write(String.Format(@”{0}({1});”, f,1122));
8.   Response.End();
9. }
10. </script>

方案六、window.name

原理:window.name本身并不能实现跨域,只是中间做了代理。

缺点:获取异域的前端页面元素值有一定局限性,比如取自适应高度的值。但是此方法在前端页面元素的数据交互上明显比JSONP强。

这个方案,YAHOO的同事已经给出了详细的demo,我就不重复了,演示demo出自YAHOO克军之手。详细的说明可以参看“怿飞的BLOG”,个人觉

得方案四比window.name适用面更广一些。


方案七、window.navigator

原理:window.navigator这个对象是在所有的Iframe中均可以访问的对象。应该是IE的一个漏洞!
缺点:不支持IE外的浏览器下的跨域。严格的dtd申明后,该方法失效!

主页面在主域:www.ioldfish.cn下,首先先申明一个Json用来保存所有页面的高度window.navigator.PagesHeight={””:0};,然后根据name

的属性找到页面的数据window.navigator.getData,最后将页面的数据注册到window.navigator.PagesHeight中。这里还定义了一个函数

resetIframeData,在页面加载的时候调用它,完成跨域的数据交互。注释中详细说明了参数的作用。

1. <script type=”text/javascript”>
2. window.navigator.PagesHeight={“”:0};   
3. window.navigator.getData=function(pageName) {     
4.  return window.navigator.PagesHeight[pageName];  
5. };   
6. window.navigator.putData=function(pageName,pageHeight) 
7. {  
8.  window.navigator.PagesHeight[pageName]=pageHeight;  
9. };

1. /*
2. *iframeId:页面中iframe的标识id
3. *key:子页面自定义的json标识,这里就是子页面定义的”PortalData”.
4. *defaultData:无法取到值时候调用
5. */
6. function resetIframeData(iframeId,key,defualtData)
7. {       
8.  var obj=document.getElementById(iframeId);  
9.  if(window.navigator.getData)
10.  {  
11.   var pageHeight = window.navigator.getData(key); 
12.   if(pageHeight && String(pageHeight).match(/\d+/))
13.   {  
14.    obj.style.height=pageHeight+’px’;  
15.   }
16.   else
17.   {  
18.    obj.style.height=defualtData + ‘px’;  
19.   }  
20.  }
21.  else
22.  {  
23.   obj.style.height=defualtData + ‘px’;  
24.  }     
25. } 
26. </script>

子页面在主域:www.lzdaily.com下,获取到页面高度后,将高度存到主页定义的Json中,Json标识为”PortalData”,这里可以自定义。

1. <script type=”text/javascript”>
2. window.onload = function getPageData()
3. {         
4.  var pageHeight = document.body.scrollHeight;  
5.  if(window.navigator.putData)
6.  {
7.   window.navigator.putData(“PortalData”,pageHeight);
8.  }
9. } 
10. </script>

其实通过css也可以实现跨域,数据获取的实质其实就是动态载入一段CSS,然后解析其中的字段提取数据,这个方法比较“猥琐”,再这里就

不多介绍了

[转载]IFRAME跨域名的解决方法,终结版 - 37度2 - 博客频道 - CSDN.NET

mikel阅读(971)

[转载]IFRAME跨域名的解决方法,终结版 – 37度2 – 博客频道 – CSDN.NET.

记得要将域名指为根域名,而不是WWW或者其它的,例:sendnet.cn 而不能指向www.sendnet.cn

1、请在父网页上加上以下代码:

<script language="VBScript">// <![CDATA[

 document.domain = "sendnet.cn"
// ]]></script>

2、请在要套的IFRAME网页上加上以下代码(此页面可以放在任何服务器上,可以不是shagndu8.com的服务器上,比如:http://www.csdn.net/;

<script language="VBScript">// <![CDATA[

document.domain = "sendnet.cn"
// ]]></script>

这样,IE就被骗了,上当了,他认为是在同一个域下,IFRAME就可以让IFRAME自适应高度或者赋值或者其它操作父框架动作。

注:本代码虽小,但可以解决大问题,本人已经测试过了,请放心使用,如果要套的IFRAME内容在别人的服务器上,那么想完成本操作,哈哈,要改网页内容,加上以上的代码就可以了。

===================================================================
跨域iframe高度自适应(兼容IE/FF/OP/Chrome)

采用JavaScript来控制iframe元素的高度是iframe高度自适应的关键,同时由于JavaScript对不同域名下权限的控制,引发出同域、跨域两种情况。

由于客户端js使用浏览器的同源安全策略,跨域情况下,被嵌套页面如果想要获取和修改父页面 的DOM属性会出现权限不足的情况,提示错误:Permission denied to access property 'document'。这是因为除了包含脚本的文档载入的主机外,同源策略禁止客户端脚本链接到其他任何主机或者访问其他任何主机的数据。这意味着访问一 个web服务的JavaScript代码通常只有在它也驻留在Web服务本身所在的同一个服务器的时候才有用。

所以在跨域情况下,我们遇到的问题就是:父窗口无法获得被嵌套页面的高度,而且被嵌套页面也无法通过驻留在其服务器上的js修改父窗口Dom节点的属性。所以我们需要一个媒介,来获得被嵌套页面的高度同时又能修改主界面iframe节点的高度。

思路:现有主界面main在域a下,被嵌套页面B在域b 下,被嵌套页面B又嵌套一个在域a下的中介页面A。 当用户打开浏览器访问mail.html的时候载入B,触发B的onload事件获取其自身高度,然后B载入A,并将高度值作为参数赋值给A的 location对象。这样A就可以通过location.hash获得B的高度。(location是javascript里边管理地址栏的内置对象, 比如location.href就管理页面的url,用location.href=url就可以直接将页面重定向url。而location.hash 则可以用来获取或设置页面的标签值。比如http://domain/#admin的location.hash="#admin"。利用这个属性值可以 做一些非常有意义的事情。)。由于A和main页面同域,所以可以修改main的dom节点属性,从而达到我们设置iframe标签高度的目的。

    <iframe id="iframeB"  name="iframeB" src="www.b.com/B.html" width="100%" height="auto" scrolling="no" frameborder="0"></iframe>  

iframe嵌套页面:B.html

<iframe id="iframeA" name="iframeA" src="" width="0" height="0" style="display:none;" ></iframe> 
<script type="text/javascript">
function sethash(){
hashH = document.documentElement.scrollHeight; //获取自身高度
urlC = "www.a.com/A.html"; //设置iframeA的src
document.getElementById("iframeA").src=urlC+"#"+hashH; //将高度作为参数传递
}
window.onload=sethash;
</script>

中介页面:A.html

<script>
function pseth() {
var iObj = parent.parent.document.getElementById('iframeB');//A和main同域,所以可以访问节点
iObjH = parent.parent.frames["iframeB"].frames["iframeA"].location.hash;//访问自己的location对象获取hash值
iObj.style.height = iObjH.split("#")[1]+"px";//操作dom
}
pseth();
</script>

同域情况下就不用多说了,直接在被嵌套的页面B中获取其自身高度并操作其父窗口main的dom属性即可。

iframe主页面:main.html