存档

‘HTML’ 分类的存档

ajax-cross-domain

2010年5月19日

现在是Web 2.0时代,AJAX使用得非常多。但是使用纯粹的AJAX,经常会遇到跨域的问题。

其实归结起来,解决跨域问题,也不外乎几种方式:

1、代理方式

2、on-Demand方式

3、iframe方式

4、用户本地转储方式 (local)

5、其实还是在服务端A用iframe解决了与服务器B通信的问题

6、PHP + HTML(含JS)

其实这几种方式,原理基本上都是一样的,绕开AJAX对于跨域的限制。下面就对这几种处理方式大概谈一下。

1、web代理方式

即用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面,由该页面代替用户页面完成交互,从而返回合适的结果。此方案可以解决现阶段所能够想到的多数跨域访问问题,但要求A网站提供Web代理的支持,因此A网站与B网站之间必须是紧密协作的,且每次交互过程,A网站的服务器负担增加,且无法代用户保存session状态。

2、on-Demand 方式

MYMSN的门户就用的这种方式,不过 MYMSN中不涉及跨域访问问题。在页面内动态生成新的<script>,将其src属性指向别的网站的网址,这个网址返回的内容必须是合法的Javascript脚本,常用的是JSON消息。此方案存在的缺陷是, script的src属性完成该调用时采取的方式时get方式,如果请求时传递的字符串过大时,可能会无法正常运行。不过此方案非常适合聚合类门户使用。

<html>
<head>
<script language="javascript" type="text/javascript">
function loadContent()
{
var s=document.createElement(‘SCRIPT’);
s.src=’http://www.anotherdomain.com/TestCrossJS.aspx?f=setDivContent’;
document.body.appendChild(s);
}

function setDivContent(v)
{
var dv = document.getElementById("dv");
dv.innerHTML = v;
}
</script>
</head>
<body>
<div id="dv"></div>

<input type="button" value="Click Me" onclick="loadContent()">
</body>
</html>

其中的www.anotherdomain.com/TestCrossJS.aspx是这样的,

<script language="C#" runat="server">
void Page_Load(object sender, EventArgs e)
{
  string f = Request.QueryString["f"];
  Response.Clear();
  Response.ContentType = "application/x-javascript";
  Response.Write(String.Format(@"
                   {0}(‘{1}’);",
                   f,
                   DateTime.Now));
  Response.End();
}
</script>

点击“Click Me”按钮,生成一个新的script tag,下载对应的 Javascript 脚本,结束时回调其中的setDivContent(),从而更新网页上一个div的内容。 

3、iframe方式

查看过醒来在javaeye上的一篇关于跨域访问的帖子,他提到自己已经用iframe的方式解决了跨域访问问题。数据提交跟获取,采用 iframe这种方式的确可以了,但由于父窗口与子窗口之间不能交互(跨域访问的情况下,这种交互被拒绝),因此无法完成对父窗口效果的影响。

在页面内嵌或动态生成指向别的网站的IFRAME,然后这2个网页间可以通过改变对方的anchor hash fragment来传输消息。改变一个网页的anchor hash fragment并不会使浏览器重新装载网页,所以一个网页的状态得以保持,而网页本身则可以通过一个计时器(timer)来察觉自己anchor hash的变化,从而相应改变自己的状态。

1. http://domain1/TestCross.html:

<html>
<head>
<script language="javascript" type="text/javascript">
var url = "http://domain2/TestCross.html"
var oldHash = null;
var timer = null;

function getHash()
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == ‘#’))
{
hash = hash.substring(1);
}

return hash;
}
function sendRequest()
{
var d = document;
var t = d.getElementById(‘request’);
var f = d.getElementById(‘alienFrame’);
f.src = url + "#" + t.value + "<br/>" + new Date();
}

function setDivHtml(v)
{
var d = document;
var dv = d.getElementById(‘response’);
dv.innerHTML = v;
}

function idle()
{
var newHash = getHash();

if (newHash != oldHash)
{
setDivHtml(newHash);
oldHash = newHash;
}

timer = window.setTimeout(idle, 100);
}

function window.onload()
{
timer = window.setTimeout(idle, 100);
}
</script>
</head>
<body>

请求:<input type="text" id="request"> <input type="button" value="发送" onclick="sendRequest()" /><br/>
回复:<div id="response"></div>

<iframe id="alienFrame" src="http://domain2/TestCross.html"></iframe>

</body>
</html>

2. http://domain2/TestCross.html:

<html>
<head>
<script language="javascript" type="text/javascript">
var url = "http://domain1/TestCross.html"
var oldHash = null;
var timer = null;

function getHash()
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == ‘#’))
{
hash = hash.substring(1);
}

return hash;
}
function sendRequest()
{
var d = document;
var t = d.getElementById(‘request’);
var f = parent;
//alert(f.document); //试着去掉这个注释,你会得到“Access is denied”
f.location.href = url + "#" + t.value + "<br/>" + new Date();
}

function setDivHtml(v)
{
var d = document;
var dv = d.getElementById(‘response’);
dv.innerHTML = v;
}

function idle()
{
var newHash = getHash();

if (newHash != oldHash)
{
setDivHtml(newHash);
oldHash = newHash;
}

timer = window.setTimeout(idle, 100);
}

function window.onload()
{
timer = window.setTimeout(idle, 100);
}
</script>
</head>
<body>

请求:<input type="text" id="request"> <input type="button" value="发送" onclick="sendRequest()" /><br/>
回复:<div id="response"></div>

</body>
</html>

两个网页基本相同,第一个网页内嵌一个IFRAME,在点击“发送”按钮后,会将文本框里的内容通过hash fragment传给IFRAME。点击IFRAME里的“发送”按钮后,它会将文本框里的内容通过hash fragment传给父窗口。因为是只改动了hash fragment,浏览器不会重新load网页内容,这里使用了一个计时器来检测URL变化,如果变化了,就更新其中一个div的内容 。

4、用户本地转储方式 (local)

IE本身依附于windows平台的特性为我们提供了一种基于iframe,利用内存来“绕行”的方案,即两个window之间可以在客户端通过 windows剪贴板的方式进行数据传输,只需要在接受数据的一方设置Interval进行轮询,获得结果后清除Interval即可。FF的平台独立性决定了它不支持剪贴板这种方式,而以往版本的FF中存在的插件漏洞又被fixed了,所以FF无法通过内存来完成暗渡陈仓。而由于文件操作FF 也没有提供支持(无法通过Cookie跨域完成数据传递),致使这种技巧性的方式只能在IE中使用。

5、其实还是在服务端A用iframe解决了与服务器B通信的问题

要解决的问题:发生在用户提交网页 URL (还包括 Tag, Notes 等)给 Bookmark 服务器时。

关于 URL 的提交至少可以有三种方式:

1.       登陆 Bookmark 服务器的提交页面,将要收藏的 URL 通过该页面提交给服务器。

2.       安装浏览器插件,通过插件将 URL 提交给服务器。

3.       从 Bookmark 服务器动态加载 javascript 小工具到当前页面,通过它来完成提交工作。

    第一种方式开发起来最简单,但对用户来讲比较麻烦,每次都需要先登陆 Bookmark 服务器才能完成提交;第二种方式我并不熟悉插件开发,而且用户也不喜欢太多的插件堆满自己的浏览器;第三种方式开发难度小,又避免了每次登陆服务器的麻烦,所以最终采用它。第三种方式中动态加载的 javascript 小工具除了需要生成 UI 供用户填写信息( URL , tag , notes 等),当用户点击提交的时候,还要完成与服务器通信的功能。

     跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容。由于安全原因,跨域访问是被各大浏览器所默认禁止的。写过跨域访问 ajax 的朋友相信都遇到过被告知“没有权限”的情况。通过 XMLHttp 来发送数据给 Bookmark 服务器的尝试失败了。于是,看到网上的一些资料,我又开始尝试用 javascript 小工具在用户网页动态创建一个隐藏的 iframe, iframe 的 src 指向服务器的一个 servlet ,试图通过调用 iframe 中提供的 javascript 来完成与服务器的通信。但不幸的是,用户网页中的 javascript 代码访问 iframe 也被浏览器归为跨域访问(特指 iframe 的 src 指向其它网站的情形),尝试再次失败。

最终,在一篇文章中看到,与 iframe 不同,如果 A 网站从 B 网站加载 javascript , A 网站可以自由的访问该 javascript 的内容,并不会被浏览器认为是跨域访问。模仿刚才 iframe 的思路,当用户点击提交时,可以动态创建一个 javascript 对象,该对象的 src 指向 Bookmark 服务器的一个 servlet ,注意: URL 、 Tag 、 Notes 、 User 、Password 等信息被作为 src URL 参数传给服务器。请看下面的代码:

var url = "http://localhost:8080/Deeryard/BookmarkServlet?" +

           "url=" + url_source + "&" + "title=" + title + "&" +

"tag=" + tag + "&" + "notes=" + notes + "&" + "user=" + user + "&" + "password=" + password;

url = encodeURI(url);

//Submit to server with a trick

var js_obj = document.createElement( "script" );

js_obj.type = "text/javascript" ;

js_obj.setAttribute( "src" , url);

//Get response from server by appending it to document

document.body.appendChild(js_obj);

上面例子中, js_obj.setArrribute() 将信息作为 src 的 URL 参数提交给了 Bookmark servlet 。那么用户又如何取得服务器的响应信息呢?答案就是最末一行代码, servlet 的输出必须是 javascript 代码,它可以调用用户网页上的其他 javascript 函数,以及操作 dom 对象。下面的 servlet 代码生成了一个 javascript 函数调用:

out.write("onServerResponse(INADEQUATE_INFORMATION);");

document.body.appendChild(js_obj) 执行后 onServerResponse( INADEQUATE_INFORMATION) 就会得到执行,使客户网页响应服务器结果。这样一个完整的通信过程就完成了。

6、PHP + HTML(含JS)

服务器A上已经装好了Tomcat, 我们写一个test.html(含JS),再写一个PHP文件(由其来完成跨域通信要求)。

更多地,请参考:https://www6.software.ibm.com/developerworks/cn/education/xml/x-ajaxtrans/index.html

http://www.xyhhxx.com/news/net/20061013121041.htm

 

以上几种方式,其实方式都差不多,只是实现方式不同而已。诸君可根据具体情况选择其一做为具体的解决办法。

 

怎么样?简单吧?简单就回复一下。。。。

HTML, Javascript, PHP从入门到精通

关于JS获取select的值

2010年3月16日

近日,在一项目中需要采用JS获取Select选择框所选中项的值,居然一下子忘记了如何获取。于是看了DOM文档,真觉得是自己老了,连这么简单的东西都忘记了。

为怕以后再忘记,也给同行一个提示,遂记录于此。

<select id="s1" name="s1">
<option selected="selected" value="1">选项一</option>
<option value="2">选项二</option>
<option value="3">选项三</option>
</select>

操作一、获取所选择项显示的文字

document.getElementById(‘s1’).options[document.getElementById(‘s1’).selectedIndex].text

若当前选中“选项二”,则这种方式所取的结果为:选项二

操作二、获取所选择项的value

document.getElementById(‘s1’).options[document.getElementById(‘s1’).selectedIndex].value

若当前选中“选项二”,则这种方式所取的结果为:2

操作三、获取当前选择项

document.getElementById(‘s1’).selectedIndex

若当前选中“选项一”,则这种方式所取的结果为:1

这里对于select必须得有id属性,才能采用getElementById获取该控件,这点需要注意。

另外,对于PHP获取页面所提交的Select控件的值,需要Select控件得有name属性,在PHP内获取表单上的Select控件数据时,采用$s = $_POST[‘select的name属性值’];这种方式来获取。

怎么样? 其实很简单的吧,希望能给初学者一个启示!

HTML, Javascript, PHP教程 , , ,

关于web开发中的POST与GET表单提交方式

2009年9月14日

近日在给前期所作博客添加一个功能模块时,无意中发现一个BUG,就是在博客的模块配置时,总是可能会在某个位置出错。但也总找不到出错的具体位置,很是纳闷!

后经过测试前辈的努力,终于把这小虫子给抓了出来。只要在IE7及以下版本的浏览器上完全选中所有模块,这时就会出现意料不到的错误。而IE8、FF3却一点问题都没有,难怪我在开发时没有测出任何问题,因为我的电脑上就是IE8和FF3。

问题是找出来了,但是原因是什么呢?

这又是一费心事,于是慢慢追寻,却发现是在博客配置时采用的AJAX的问题。当时所采用的AJAX所使用的提交方式为GET方式。GET方式与POST方式的区别,这里自不必讲,有兴趣的朋友可参见本博另一文。由于GET方式是将所有的参数以值对的方式转入,并也就只支持大约2M的数据,当时采用GET方式完全满足要求。但是现在刚添加一个模块,在完全选中时,整个数据量就刚好超过了2M,难怪IE7及以下版本的浏览器会出问题。

找到了问题所在了,就很容易了,只需要将所使用的AJAX改为POST方式提交即可。

虽然这个BUG是解决掉了,但是为何同一种提交方式,在不同浏览器却有不同的表现呢?这个不得其解,有知道这问题的朋友可留言解答,也可一起探讨该问题。

为谢!

HTML , , ,

媲美163博客的博客系统

2009年4月30日

首先讲一个博客系统的主要功能:

1、博客系统的主页以模块为单位进行显示

2、博客的所有模块可进行自由配置显示,

3、博客的页面布局可进行自由选择,即选择几列显示、或左宽右窄之类

4、博客的皮肤可进行自己选择

5、博客的皮肤可自行定义设置(开发中)

6、博主设置类别,每一种类别有自己默认的菜单、页面布局和默认显示模块

还是一样,先上两张效果图看看:

第一张:模块配置与页面布局设置

页面布局及模块设置

第二张:博客风格选择

博客风格选择

稍后将关于这个系统的代码进行分析,敬请期待!

HTML, Javascript, PHP教程 , , , ,

执行innerHTML中的Javascript代码

2009年4月10日

之前曾讲到采用set_innerHTML函数实现执行innerHTML中的JAVASCRIPT代码,其中讲到一种方法就是采用JS创建一个iframe的方式。

这里就将该方式的实现作一个介绍。

在我们使用AJAX的时候,经常要用到innetHTML来更新对象的内容,但是对于更新的<script>脚本程序浏览器却无法执行,我前面AJAX初学常遇问题解答这篇文章曾提到过这个问题,它不执行的原因是:<script>标签只在浏览器第一次文档加载中被解析,下面介绍怎么样让<script>跑起来。

分析问题
既然<script>只在文档加载中才被解析,那么我就得调用document.write()方法来重新加载一次,但是这样的话原来页面的内容也会被覆盖掉了,所以不得不用IFRAME把document.write()装载起来。

解决问题
var jsCode = 需要执行的JS代码
var jsIframe = document.createElement(“iframe”);
jsIframe.style.display = “none”;//把jsIframe隐藏起来
document.body.appendChild(jsIframe);
with(window.frames[window.frames.length - 1]){
document.open();
document.write(jsCode); //执行JS代码
document.close();
}
document.body.removeChild(jsIframe);//执行后删除iframe对象
这里需要注意一个问题,因为jsCode是在iframe中运行,所以所有的页面元素都在iframe父对象之下,要调用页面元素对象必须得用 parent.obj 这种方式。

另外一种方法:

用dom动态创建一个script对象
var script=document.createElement(“script”);
script.src=”XXXX.js”;
document.body.appendChild(script);

DIV/CSS, HTML, Javascript , , ,

CSS开发框架

2009年2月16日

搞了好长一段时间的Web开发,对于前端开发而言,一直其于作坊式的开发,没有一个全面的框架性的开发。和PHP的开发一样,开发进行到了一定的时间,感觉只有借助于框架的开发,才能够让开发更加快捷。

现谈谈CSS的几种常见框架:

一、BluePrint

该框架主要在于减少开发时间,提供强大开发基础与你创建Web项目。

二、Elements

这是一个基础性的CSS框架。它用来帮助设计者书写CSS更加快捷简单。它不仅是一个框架,它拥有自己的工作流。它拥有你需要完成项目的各种元素。

三、YAML CSS Framework

四、YUI Grids CSS

五、CleverCSS

六、Tripoli Beta CSS Framework

七、Boilerplate CSS Framework

八、WYMstyle: a CSS framework

DIV/CSS, HTML , , ,

获取页面元素位置

2009年2月11日

在Web编程中,常常会使用某个元素的位置,即相对于整个屏幕左上方的位置。

这里有一个较好的方法实现。

function getElementPos(elementId){
var ua = navigator.userAgent.toLowerCase();
var isOpera = (ua.indexOf('opera') != -1);
var isIE = (ua.indexOf('msie') != -1 && !isOpera); // not opera spoof
var el = document.getElementById(elementId);
if(el.parentNode === null || el.style.display == 'none'){
return false;
}
var parent = null;
var pos = [];
var box;
if(el.getBoundingClientRect) //IE
{
box = el.getBoundingClientRect();
var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
//alert(box.left+scrollLeft);
return {x:box.left + scrollLeft, y:box.top + scrollTop};
}
else if(document.getBoxObjectFor) // gecko
{
box = document.getBoxObjectFor(el);
var borderLeft = (el.style.borderLeftWidth)?parseInt(el.style.borderLeftWidth):0;
var borderTop = (el.style.borderTopWidth)?parseInt(el.style.borderTopWidth):0;
pos = [box.x - borderLeft, box.y - borderTop];
}
else // safari & opera
{
pos = [el.offsetLeft, el.offsetTop];
parent = el.offsetParent;
if (parent != el) {
while (parent) {
pos[0] += parent.offsetLeft;
pos[1] += parent.offsetTop;
parent = parent.offsetParent;
}
}

if (ua.indexOf('opera') != -1|| ( ua.indexOf('safari') != -1 && el.style.position == 'absolute' )){
pos[0] -= document.body.offsetLeft;
pos[1] -= document.body.offsetTop;
}

}
if (el.parentNode) { parent = el.parentNode; }
else { parent = null; }

while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML'){ // account for any scrolled ancestors
pos[0] -= parent.scrollLeft;
pos[1] -= parent.scrollTop;
if (parent.parentNode) { parent = parent.parentNode; }
else { parent = null; }
}
return {x:pos[0], y:pos[1]};
}

DIV/CSS, HTML, Javascript , , , ,

两个网页颜色拾取器

2009年2月11日

在Web应用中,常常需要让用户直接选择。这里使用了两种。第一种更为简单,可直接进行使用。

第一种: 256色安全选择器。

//this,colorDiv,colorTxt
var curDiv,curTxt;

function showColorPicker(btn, colorDiv, colorTxt){
	curDiv = colorDiv;curTxt = colorTxt;
	if(document.getElementById("colorPicker") != null){
		if(document.getElementById("colorPicker").style.visibility=="hidden"){
			var a=getElementPos(btn.id);
			var b=eval(a);
			document.getElementById("colorPicker").style.top=b.y+15+"px";
			document.getElementById("colorPicker").style.left=b.x+"px";
			document.getElementById("colorPicker").style.visibility="visible";
		}
		else{
			document.getElementById("colorPicker").style.visibility="hidden";
		}
		return false;
	}
	ColorPicker(btn, colorDiv, colorTxt);
}
function ColorPicker(btn, colorDiv, colorTxt) {
	var baseColor=new Array(6);
	baseColor[0]="00";
	baseColor[1]="33";
	baseColor[2]="66";
	baseColor[3]="99";
	baseColor[4]="CC";
	baseColor[5]="FF";
	var myColor;
	myColor="";
	var myHTML;
	myHTML="
<table style="text-align:left;" border="1" cellspacing="0" cellpadding="0" width="200">
<tbody>
<tr>
<td bgcolor="#cccccc">"+
	"
<input id="colorInput" style="background-color:#cccccc;border:1px solid #000000;" size="6" />"+
	"</td>
</tr>
<tr>
<td>";
	myHTML=myHTML+"
<table style="background-color:#ccc;" border="0" cellspacing="1" cellpadding="0" width="100%">";
	for(i=0;i&lt;6;i++){
		myHTML=myHTML+"
<tbody>
<tr height="10">";
		for(j=0;j&lt;3;j++){
	        for(k=0;k&lt;6;k++){
				myColor=baseColor[j]+baseColor[k]+baseColor[i];
				myHTML=myHTML+"
<td onclick="colorpickerclose();" onmouseover="\&quot;selectColor(this.bgColor," width="10" height="10" bgcolor="#00c000"></td>
";
			}
		}
		myHTML=myHTML+"</tr>
";
	}
	for(i=0;i&lt;6;i++){
		myHTML=myHTML+"
<tr height="10">";
		for(j=3;j&lt;6;j++){
			for(k=0;k&lt;6;k++){
				myColor=baseColor[j]+baseColor[k]+baseColor[i];
				myHTML=myHTML+"
<td onclick="colorpickerclose();" onmouseover="\&quot;selectColor(this.bgColor," width="10" height="10" bgcolor="#00c000"></td>
";
			}
		}
		myHTML=myHTML+"</tr>
";
	}
	myHTML=myHTML+"</tbody></table>
";
	myHTML=myHTML+"</td>
</tr>
</tbody></table>
";
	var a=getElementPos(btn.id);
	var b=eval(a);
	var div = document.createElement("div");
	div.id = "colorPicker";
	div.style.width="200px";
	div.style.height="158px";
	div.style.position="absolute";
	div.style.left=b.x+"px";
	div.style.top=b.y+15+"px";
	div.style.borderWidth="1px";
	div.style.borderStyle="solid";
	div.style.borderColor="#999";
	div.style.display="block";
	div.style.zIndex="10000";
	div.innerHTML=myHTML;
	if(document.getElementById("colorPicker") != null)
		document.body.removeChild(div);
	document.body.appendChild(div);
}
function selectColor(colorStr, colorDiv, colorTxt){
	document.getElementById("colorText").innerHTML="      "+colorStr;
	document.getElementById("colorInput").style.backgroundColor=colorStr;
	if(document.getElementById(curTxt)!=null) {document.getElementById(curTxt).innerHTML=colorStr;document.getElementById(curTxt).style.backgroundColor=colorStr;}
	if(document.getElementById(curDiv)!=null) {document.getElementById(curDiv).style.backgroundColor=colorStr;}
}
function colorpickerclose(){
	document.getElementById("colorPicker").style.visibility="hidden";
}

function getElementPos(elementId){
	var ua = navigator.userAgent.toLowerCase();
	var isOpera = (ua.indexOf('opera') != -1);
	var isIE = (ua.indexOf('msie') != -1 &amp;&amp; !isOpera); // not opera spoof
	var el = document.getElementById(elementId);
	if(el.parentNode === null || el.style.display == 'none'){
		return false;
	}
	var parent = null;
	var pos = [];
	var box;
	if(el.getBoundingClientRect) //IE
	{
		box = el.getBoundingClientRect();
		var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
		var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
		//alert(box.left+scrollLeft);
		return {x:box.left + scrollLeft, y:box.top + scrollTop};
	}
	else if(document.getBoxObjectFor) // gecko
	{
		box = document.getBoxObjectFor(el);
		var borderLeft = (el.style.borderLeftWidth)?parseInt(el.style.borderLeftWidth):0;
		var borderTop = (el.style.borderTopWidth)?parseInt(el.style.borderTopWidth):0;
		pos = [box.x - borderLeft, box.y - borderTop];
	}
	else // safari &amp; opera
	{
		pos = [el.offsetLeft, el.offsetTop];
		parent = el.offsetParent;
		if (parent != el) {
			while (parent) {
				pos[0] += parent.offsetLeft;
				pos[1] += parent.offsetTop;
				parent = parent.offsetParent;
			}
		}

		if (ua.indexOf('opera') != -1|| ( ua.indexOf('safari') != -1 &amp;&amp; el.style.position == 'absolute' )){
			pos[0] -= document.body.offsetLeft;
			pos[1] -= document.body.offsetTop;
		}

	}
	if (el.parentNode) { parent = el.parentNode; }
	else { parent = null; }

	while (parent &amp;&amp; parent.tagName != 'BODY' &amp;&amp; parent.tagName != 'HTML'){ // account for any scrolled ancestors
		pos[0] -= parent.scrollLeft;
		pos[1] -= parent.scrollTop;
		if (parent.parentNode) { parent = parent.parentNode; }
		else { parent = null; }
	}
	return {x:pos[0], y:pos[1]};
}

第二种:类windows的颜色选择器。

pickercolor

DIV/CSS, HTML, Javascript , , ,

执行innerHTML中的Javascript

2009年2月10日

在使用AJAX时,往往只是将reponse的内容直接innerHTML到指定的容器里面,这种应用都非常简单。但是对于reponse的内容包含javascript内容时将如何处理呢?能否执行其返回的JS呢?

实际上,对于返回的内容,页面不会直接执行该JS代码,google一下,才发现关于这个问题的解决方法大概有三种:

1、首先在head标签内容设定一个指定ID的script标签,待响应时修改其src 属性。

2、创建一个iframe,然后将JS写入到该IFRAME中,对于要操作原页面的HTML标签,需要在里面的JS中添加parent。

3、应用较多的set_innerHTML,该函数是由andot所开发的。

以下为set_innerHTML函数内容。

var global_html_pool = [];
var global_script_pool = [];
var global_script_src_pool = [];
var global_lock_pool = [];
var innerhtml_lock = null;
var document_buffer = "";

function set_innerHTML(obj_id, html, time) {
if (innerhtml_lock == null) {
innerhtml_lock = obj_id;
}
else if (typeof(time) == "undefined") {
global_lock_pool[obj_id + "_html"] = html;
window.setTimeout("set_innerHTML('" + obj_id + "', global_lock_pool['" + obj_id + "_html']);", 10);
return;
}
else if (innerhtml_lock != obj_id) {
global_lock_pool[obj_id + "_html"] = html;
window.setTimeout("set_innerHTML('" + obj_id + "', global_lock_pool['" + obj_id + "_html'], " + time + ");", 10);
return;
}

function get_script_id() {
return "script_" + (new Date()).getTime().toString(36)
+ Math.floor(Math.random() * 100000000).toString(36);
}

document_buffer = "";

document.write = function (str) {
document_buffer += str;
}
document.writeln = function (str) {
document_buffer += str + "\n";
}

global_html_pool = [];

var scripts = [];
html = html.split(/<\/script>/i);
for (var i = 0; i < html.length; i++) {
global_html_pool[i] = html[i].replace(/<script[\s\S]*$/ig, "");
scripts[i] = {text: '', src: '' };
scripts[i].text = html[i].substr(global_html_pool[i].length);
scripts[i].src = scripts[i].text.substr(0, scripts[i].text.indexOf('>') + 1);
scripts[i].src = scripts[i].src.match(/src\s*=\s*(\"([^\"]*)\"|\'([^\']*)\'|([^\s]*)[\s>])/i);
if (scripts[i].src) {
if (scripts[i].src[2]) {
scripts[i].src = scripts[i].src[2];
}
else if (scripts[i].src[3]) {
scripts[i].src = scripts[i].src[3];
}
else if (scripts[i].src[4]) {
scripts[i].src = scripts[i].src[4];
}
else {
scripts[i].src = "";
}
scripts[i].text = "";
}
else {
scripts[i].src = "";
scripts[i].text = scripts[i].text.substr(scripts[i].text.indexOf('>') + 1);
scripts[i].text = scripts[i].text.replace(/^\s*<\!--\s*/g, "");
}
}

var s;
if (typeof(time) == "undefined") {
s = 0;
}
else {
s = time;
}

var script, add_script, remove_script;

for (var i = 0; i < scripts.length; i++) {
var add_html = "document_buffer += global_html_pool[" + i + "];\n";
add_html += "document.getElementById('" + obj_id + "').innerHTML = document_buffer;\n";
script = document.createElement("script");
if (scripts[i].src) {
script.src = scripts[i].src;
if (typeof(global_script_src_pool[script.src]) == "undefined") {
global_script_src_pool[script.src] = true;
s += 2000;
}
else {
s += 10;
}
}
else {
script.text = scripts[i].text;
s += 10;
}
script.defer = true;
script.type =  "text/javascript";
script.id = get_script_id();
global_script_pool[script.id] = script;
add_script = add_html;
add_script += "document.getElementsByTagName('head').item(0)";
add_script += ".appendChild(global_script_pool['" + script.id + "']);\n";
window.setTimeout(add_script, s);
remove_script = "document.getElementsByTagName('head').item(0)";
remove_script += ".removeChild(document.getElementById('" + script.id + "'));\n";
remove_script += "delete global_script_pool['" + script.id + "'];\n";
window.setTimeout(remove_script, s + 10000);
}

var end_script = "if (document_buffer.match(/<\\/script>/i)) {\n";
end_script += "set_innerHTML('" + obj_id + "', document_buffer, " + s + ");\n";
end_script += "}\n";
end_script += "else {\n";
end_script += "document.getElementById('" + obj_id + "').innerHTML = document_buffer;\n";
end_script += "innerhtml_lock = null;\n";
end_script += "}";
window.setTimeout(end_script, s);
}

在实际的应用中稍有修改。例如,对于第一次使用ajax所返回的HTML中的JS来修改所返回的HTML中的某个DIV,这样往往会看不到实际修改的结果。经研究发现,曾执行了两次写入操作。于此,只需要将修改操作的timeout的时间改长一点即可(即add_script的执行时间)。

HTML, Javascript , , , , , , ,

JS获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度

2009年2月5日

网页可见区域宽:document.body.clientWidth
网页可见区域高:document.body.clientHeight
网页可见区域宽:document.body.offsetWidth (包括边线的宽)
网页可见区域高:document.body.offsetHeight (包括边线的宽)
网页正文全文宽:document.body.scrollWidth
网页正文全文高:document.body.scrollHeight
网页被卷去的高:document.body.scrollTop
网页被卷去的左:document.body.scrollLeft
网页正文部分上:window.screenTop
网页正文部分左:window.screenLeft
屏幕分辨率的高:window.screen.height
屏幕分辨率的宽:window.screen.width
屏幕可用工作区高度:window.screen.availHeight
屏幕可用工作区宽度:window.screen.availWidth

HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth
scrollHeight: 获取对象的滚动高度。
scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离
scrollTop:设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离
scrollWidth:获取对象的滚动宽度
offsetHeight:获取对象相对于版面或由父坐标 offsetParent 属性指定的父坐标的高度
offsetLeft:获取对象相对于版面或由 offsetParent 属性指定的父坐标的计算左侧位置
offsetTop:获取对象相对于版面或由 offsetTop 属性指定的父坐标的计算顶端位置
event.clientX 相对文档的水平座标
event.clientY 相对文档的垂直座标
event.offsetX 相对容器的水平坐标
event.offsetY 相对容器的垂直坐标
document.documentElement.scrollTop 垂直方向滚动的值
event.clientX+document.documentElement.scrollTop 相对文档的水平座标+垂直方向滚动的量

IE,FireFox 差异如下:

IE6.0、FF1.06+:

clientWidth = width + padding

clientHeight = height + padding

offsetWidth = width + padding + border

offsetHeight = height + padding + border

IE5.0/5.5:
clientWidth = width – border

clientHeight = height – border

offsetWidth = width

offsetHeight = height

(需要提一下:CSS中的margin属性,与clientWidth、offsetWidth、clientHeight、offsetHeight均无关)

网页可见区域宽: document.body.clientWidth
网页可见区域高: document.body.clientHeight
网页可见区域宽: document.body.offsetWidth (包括边线的宽)
网页可见区域高: document.body.offsetHeight (包括边线的高)
网页正文全文宽: document.body.scrollWidth
网页正文全文高: document.body.scrollHeight
网页被卷去的高: document.body.scrollTop
网页被卷去的左: document.body.scrollLeft
网页正文部分上: window.screenTop
网页正文部分左: window.screenLeft
屏幕分辨率的高: window.screen.height
屏幕分辨率的宽: window.screen.width
屏幕可用工作区高度: window.screen.availHeight
屏幕可用工作区宽度: window.screen.availWidth

-------------------

技术要点
本节代码主要使用了Document对象关于窗口的一些属性,这些属性的主要功能和用法如下。

要得到窗口的尺寸,对于不同的浏览器,需要使用不同的属性和方法:若要检测窗口的真实尺寸,在Netscape下需要使用Window的属性;在 IE下需要深入Document内部对body进行检测;在DOM环境下,若要得到窗口的尺寸,需要注意根元素的尺寸,而不是元素。

Window对象的innerWidth属性包含当前窗口的内部宽度。Window对象的innerHeight属性包含当前窗口的内部高度。

Document对象的body属性对应HTML文档的标签。Document对象的documentElement属性则表示HTML文档的根节点。

document.body.clientHeight表示HTML文档所在窗口的当前高度。document.body. clientWidth表示HTML文档所在窗口的当前宽度。

实现代码

< !DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>请调整浏览器窗口</title>
<meta http-equiv=”content-type” content=”text/html; charset=gb2312″>
</meta></head>
<body>
<h2 align=”center”>请调整浏览器窗口大小</h2><hr />
<form action=”#” method=”get” name=”form1″ id=”form1″>
<!–显示浏览器窗口的实际尺寸–>
浏览器窗口 的 实际高度: <input type=”text” name=”availHeight” size=”4″/><br />
浏览器窗口 的 实际宽度: <input type=”text” name=”availWidth” size=”4″/><br />
</form>
<script type=”text/javascript”>
<!–
var winWidth = 0;
var winHeight = 0;
function findDimensions() //函数:获取尺寸
{
//获取窗口宽度
if (window.innerWidth)
winWidth = window.innerWidth;
else if ((document.body) && (document.body.clientWidth))
winWidth = document.body.clientWidth;
//获取窗口高度
if (window.innerHeight)
winHeight = window.innerHeight;
else if ((document.body) && (document.body.clientHeight))
winHeight = document.body.clientHeight;
//通过深入Document内部对body进行检测,获取窗口大小
if (document.documentElement  && document.documentElement.clientHeight && document.documentElement.clientWidth)
{
winHeight = document.documentElement.clientHeight;
winWidth = document.documentElement.clientWidth;
}
//结果输出至两个文本框
document.form1.availHeight.value= winHeight;
document.form1.availWidth.value= winWidth;
}
findDimensions();
//调用函数,获取数值
window.onresize=findDimensions;

//–>
</script>
</body>
</html>

源程序解读

(1)程序首先建立一个表单,包含两个文本框,用于显示窗口当前的宽度和高度,并且,其数值会随窗口大小的改变而变化。

(2)在随后的JavaScript代码中,首先定义了两个变量winWidth和winHeight,用于保存窗口的高度值和宽度值。

(3)然后,在函数findDimensions ( )中,使用window.innerHeight和window.innerWidth得到窗口的高度和宽度,并将二者保存在前述两个变量中。

(4)再通过深入Document内部对body进行检测,获取窗口大小,并存储在前述两个变量中。

(5)在函数的最后,通过按名称访问表单元素,结果输出至两个文本框。

(6)在JavaScript代码的最后,通过调用findDimensions ( )函数,完成整个操作。

jswidthjpg

DIV/CSS, HTML, Javascript , , , , ,