24

1. Hidden iframe

将iframe的src指向一个url,server收到请求后,Keep-Alive。
数据直接以script的方式下发到Browser,Browser收到数据后直接执行。
只要不超时,链接会一直保留。

优:感觉这是真正的长连接,对stream也有完整的支持。
劣:Browser状态栏会一直处于“连接中”,ESC会导致链接断开,会有跨域问题

2. Script Tag

用JS创建一个script对象,将该对象的src指向一个url,Keep-Alive。
在一定时间内(超时前),如果sever有数据下发,则用script的方式发送到Browser。
Browser收到数据后直接执行,此时需要重建script对象,建立另一个链接。

优:没有Hidden iframe的缺点,也比较轻量
劣:不是真正的长链接,每收到一个新的下发数据,都需要重新建立链接

3 AJAX

用JS创建一个XHR对象,将该对象的src指向一个url,Keep-Alive。
在一定时间内(超时前),如果sever有数据下发,则通过已建立的链接发送到Browser。
Browser收到数据后直接执行,此时需要重建XHR对象,建立另一个链接。

优:没有Hidden iframe的缺点
劣:存在跨域问题,不是真正的长链接,每收到一个新的下发数据,都需要重新建立链接

2 和 3也可以叫做Long Polling

除了这三种方法,还可以用Flash,由Flash和Server通信,页面用过JS和Flash通信。
这可以实现真正的下发,甚至不需要维护长链接。
但也可能存在被防火墙屏蔽的问题。

三种方法都用php模拟了一下:

Hidden Iframe

<html>
<head>
<script>
function callback(data)
{
	document.getElementById("t").value = data + "\n" + document.getElementById("t").value;
}
 
callback("abc");
</script>
</head>
<body>
hello
<textarea id="t"></textarea>
<iframe src="/hiddeniframe.php" width="0" height="0"></iframe>
</body>
</html>
<?php
	ob_end_flush();
	echo "<script>";
	echo "domain=serverpush";
	echo "</script>";
	for( ; ; )
	{
		$t = time();
		echo "<script>";
		echo "parent.callback($t);";
		echo "</script>";
		flush();
		sleep(1);
	}
?>

Script Tag

<html>
<head>
<script>
function callback(data)
{
	document.getElementById("t").value = data + "\n" + document.getElementById("t").value;
}
 
function connect()
{
    var _script = document.createElement("script");
    _script.setAttribute("type", "text/javascript");
    _script.setAttribute("src", "script.php");
    document.getElementsByTagName("head")[0].appendChild(_script);	
}
 
connect();
</script>
</head>
<body>
<textarea id="t"></textarea>
</body>
</html>
<?php
	sleep(10);
	$r = time();
	echo "callback($r);";
	echo "setTimeout(connect, 1000)";
?>

AJAX

<html>
<head>
<script>
function callback(data)
{
	document.getElementById("t").value = data + "\n" + document.getElementById("t").value;
}
 
function connect()
{
	var ajax = new XMLHttpRequest;
	ajax.open("POST", "ajax.php");
	ajax.onreadystatechange = function()
	{       
		if (ajax.readyState == 4)
		{       
			if (ajax.status == 200) 
			{       
				callback(ajax.responseText);	
				setTimeout(connect, 1000);
			}       
		}       
	}
	ajax.send();
}
 
connect();
 
</script>
</head>
<body>
<textarea id="t"></textarea>
</body>
</html>
<?php
	sleep(10);
	echo time();
?>
Tagged with:
23

想在mail的一个页面里,用隐藏iframe引用soso的一个页面,加载后将数据取出。
但一直报错,说…undefine。
到群里咨询过前台高手们,原来又遇到所谓的“跨域”问题了。

处于安全性的考虑,JavaScript不允许脚本处理来自不同域(Domain)的资源。
用里的话说,就是同源策略(Same-Origin Policy):

一个脚本只能读取与它同源(如由同一个主机下载、通过同一个端口下载或者下载协议相同)的窗口或文档的属性。

对于我的需求,常规的解决跨域问题的方法都不适用,而非常规手段又过于复杂,代价太大。
只有作罢了。

我所知的常规手段包括:

  1. 设置document.domain,只适合位于不同子域的页面中使用
  2. 采用proxy页面中转

非常规手段

  1. 借助Flash
  2. GreaseMonkey

很久没写JS了~~~

function Search()
{
	var keyword = $("keyword").value;
	debug("search for " + keyword);
	var url = "http://qzone.soso.com/qz.q?&amp;sc=qz&amp;pid=qz.s.idx&amp;ch=s.qz.diary&amp;pg=1&amp;ty=diary&amp;w=" + keyword;
 
	var soso = document.createElement("iframe");
	soso.setAttribute("onload", "ParseResult()");
	soso.setAttribute("src", url);
	soso.setAttribute("id", "soso");
	document.getElementsByTagName("body")[0].appendChild(soso);
	return false;
}
 
function ParseResult()
{
	debug("begin to parse");
	var soso = $("soso");
	if(!soso)
		return;
 
//	var ids = document.frames[0].contentWindow.document.getElementsByTagName("div");
	var ids = document.getElementById("soso").contentWindow.document.getElementsByTagName("div");
 
	for( var i = 0; i &lt; ids.length; i++)
	{
		var d = ids[i];
		if( d.getAttribte("ss_c") == "qz.show.res")
		{
			debug("found");
		}
		else
		{
			debug(d.className);
		}
	}
	debug("end of parse");
	document.getElementsByTagName("body")[0].removeChild($("soso"));
}
Tagged with:
17

Google Reader有462个GM脚本(GreaseFire的结果),而整个qq.com的域名只有一个,是用来优化qq.com的打印功能的。
这样的对比反映出了Geek们对两个域名的认同差异吧。

早上起床,写了一个用于用于阅读空间GS脚本。
just for fun啦,主要功能是在阅读时改变背景色,因为感觉现在的色彩有点单调。

已经上传到userscrips,可以在这里找到。

效果图:)
阅读空间

可惜Qzone对Firefox的支持还不好,否则也可以做一个:)

出去晒太阳了~~~

Tagged with:
16

如果用obj.onclick = function(){…},
则脚本会异常终止。
改用addEventListener(“click”, function(){…}, true),
则一切正常。

Tagged with:
22

想给自己写的log加上一个WYSIWYG,
于是google一番,
找到某人推荐的fckedit

其实之前已经在wp里试过,感觉一般。
不过这次是要和自己的程序整合,所以了解比之前深入。

看了一下sample,然后用了不到10分钟就拼凑出一个可以工作的版本。
得益于实用的例子、详细的注释和通用的命名,
优秀的程序都应该这样。

Tagged with:
07


function objectClone(obj,preventName){
if((typeof obj)==’object’){
var res=(!obj.sort)?{}:[];
for(var i in obj){
if(i!=preventName)
res[i]=objectClone(obj[i],preventName);
}
return res;
}else if((typeof obj)==’function’){
return (new obj()).constructor;
}
return obj;
}

同事的作品:)

12

var wintype = !!os[1];

取变量的Boolean值,
应该相当于 var wintype = os[1]?true:false,
但显然简洁很多。

十二 21


function getHeight(){
s = “网页可见区域宽:”+ document.body.clientWidth;
s += “\r\n网页可见区域高:”+ document.body.clientHeight;
s += “\r\n网页可见区域高:”+ document.body.offsetWeight +” (包括边线的宽)”;
s += “\r\n网页可见区域高:”+ document.body.offsetHeight +” (包括边线的宽)”;
s += “\r\n网页正文全文宽:”+ document.body.scrollWidth;
s += “\r\n网页正文全文高:”+ document.body.scrollHeight;
s += “\r\n网页被卷去的高:”+ document.body.scrollTop;
s += “\r\n网页被卷去的左:”+ document.body.scrollLeft;
s += “\r\n网页正文部分上:”+ window.screenTop;
s += “\r\n网页正文部分左:”+ window.screenLeft;
s += “\r\n屏幕分辨率的高:”+ window.screen.height;
s += “\r\n屏幕分辨率的宽:”+ window.screen.width;
s += “\r\n屏幕可用工作区高度:”+ window.screen.availHeight;
s += “\r\n屏幕可用工作区宽度:”+ window.screen.availWidth;
s = “\r\n网页正文全文高:”+ document.body.scrollHeight;
alert(s);
}

preload preload preload