空灵阁

Main | Next page »

http://blog.matrix.org.cn/Jekey/date/20070704 星期三 2007年07月04日

ORACLE转身份证号码函数

 一直负责项目的数据清理工作,旧系统的身份证号码进入新系统需要转换,根据网上的资料,写了个函数。功能比一般的要强,因为不但能将15位转18位,还能将16,17位转成18位,实属无奈啊!

[Read More]

http://blog.matrix.org.cn/Jekey/date/20061127 星期一 2006年11月27日

防过劳死看清27个危险信号

最近连续超负荷的工作,身体感觉越来越差,真的好想休息一下阿!IT人士真不容易啊……


要想防止“过劳死”,就必须了解身体为我们发出的“过劳死”信号。日本公众卫生研究所的科研人员曾对日本“过劳死”高发现象做过详细研究,从预防角度,他们列举了27种过劳症状和因素。


  研究者认为:在这27项症状和因素中占有7项以上,即是过度疲劳危险者,占10项以上就可能在任何时候发生“过劳死”。同时,在第1项到第9项中占两项以上或者在第10项到18项中占3项以上者也要特别注意,这27项症状和因素分别是:


  1.经常感到疲倦,忘性大;


  2.酒量突然下降,即使饮酒也不感到有滋味;


  3.突然觉得有衰老感;


  4.肩部和颈部发木发僵;


  5.因为疲劳和苦闷失眠;


  6.为一点小事生气;


  7.经常头痛和胸闷;


  8.患有高血压、糖尿病,心电图测试结果不正常;


  9.体重突然变化大,出现“将军肚”;


  10.几乎每天晚上聚餐饮酒;


  11.一天喝5杯以上咖啡;


  12.经常不吃早饭或吃饭时间不固定;


  13.喜欢吃油炸食品;


  14.一天吸烟30支以上;


  15.晚上10时也不回家或者12时以后回家占一半以上;


  16.上下班单程占2小时以上;


  17.最近几年运动也不流汗;


18.自我感觉身体良好而不看病;


  19.一天工作10小时以上;


  20.星期天也上班;


  21.经常出差,每周只在家住两三天;


  22.夜班多,工作时间不规则;


  23.最近有工作调动或工作变化;


  24.升职或者工作量增多;


  25.最近以来加班时间突然增加;


  26.人际关系突然变坏;


  27.最近工作失误或者与人发生不和。


  相关链接


  消除脑力疲劳法:适当参加体育锻炼和文娱活动,积极休息。如果是心理疲劳,千万不要滥用镇静剂、安眠药等,应找出引起心情忧郁的原因,并求得解脱。病理性疲劳,应及时找医生检查和治疗。


  饮食补充法:注意饮食营养的搭配。多吃含蛋白质、 脂肪和丰富的B族维生素食物,如豆腐、牛奶、鱼肉类,多吃水果、蔬菜,适量饮水。


  休息恢复法:每天都要留出一定的休息时间。听音乐、绘画、散步等有助解除生理疲劳。


  科学健身方法:一是有氧运动,如跑步、打球、打拳、骑车、爬山等;二是腹式呼吸,全身放松后深呼吸,鼓足腹部,憋一会儿再慢慢呼出;三是做保健操;四是点穴按摩。


 

http://blog.matrix.org.cn/Jekey/date/20061118 星期六 2006年11月18日

两表间差异查询SQL语句

最近在公司的项目组里负责做数据清理工作,整天对着数据库分析。今天对收上来的数据分析的时候,发现两个相关联的表之间差一条记录。两个表都有10多万记录,写了一个简单的查询语句,半个小时也没出结果。时间可不能等,只有求助高手(经理)了。


原来的语句:


select * from yang_yi where aac001 not in (select aac001 from ac01)如果记录比较少的话还是很管用的。可是记录过多的话,耗费大量的时间。其中表yang_yi 比表ac01多一条记录,相关字段是aac001。


重写语句:


SELECT yang_yi .aac001  FROM ac01,yang_yi  WHERE ac01.aac001 (+)= yang_yi .aac001 AND ac01.aac001 IS NULL


使用的数据库是oracle


 

http://blog.matrix.org.cn/Jekey/date/20061015 星期日 2006年10月15日

程序员如何缓解压力,保持心理健康(转载)

心理保健


心理保健-心理健康的标准



心理健康的标准


1.对现实的正确认识。看问题能持客观的态度。


2.自知、自尊与自我接纳。能现实地评价自己,不过分地显示自己也不刻意地取悦别人。既接纳自己的优点也接纳自己的缺点。一个人如果连自己都不喜 欢,又怎么谈得上喜欢别人。


3.自我调控的能力。能调节自己的行为,既能克制自己的冲动,又能调动自己 的身心力量,在实践中实现自己的更进阶目标。


4.与人建立亲密关系的能力。关心他人,善于合作,不为了满足自己的需要而 苛求于人。这种人有知心的朋友,有亲密的家人。而不健康的人,人际关系 紧张,处处利用他人,以达到自己的目的。


5.人格架构的稳定与协调。这种稳定与协调包括理想与现实差距的调适,包括 认知与情感的协调。


6.生活热情与工作效率。人人都会有苦恼,但心理健康的人能从生活与工作中 寻得快乐。


 


心理保健-良好心态



如何保持良好心态?


1.   将不快以适当模式发泄出来,以减轻心理压力。要敢于把自己不愉快的事向知心朋友或亲人诉说。当极其忧伤时哭泣、读诗词、写日记、看电影、听音乐都是常见的宣泄模式。节奏欢快的音乐能振奋人的情绪。


2.  多与人交往,摆脱孤独。每个人都有一种归属的需要,会习惯的把自己视为社会的一员,并希望从团契中得到爱。研究发现人际交往有助于身心健康。当你真诚的关心别人帮助别人,无私奉献自己的一片爱心时,你会欣喜地发现,你获得的比你给予的更多。千万不要因为怕别人不高兴而把自己同他人隔绝开来。孤独只会使抑郁状态更加严重。


3.  增强自信心,做情绪的主人。人在正常状态下是可以透过意志努力来消除不愉快情绪,并保持乐观心情的。一是有意识地获取成功的体验;二是不在乎别人对自己如何评价;三是善于发现自己的长处。知识是自信的源泉。要学会容忍,培养坚忍的毅力。用积极进取精神取代消极思想意识。把事情看透,心胸开阔,情绪就能保持稳定。


 


心理保健-面对挫折



人生在世,谁都会遇到挫折,在遭受挫折的时候,不妨试试以下方法︰


沉着冷静,不慌不怒。增强自信,提升勇气。


审时度势,迂回取胜。所谓迂回取胜,即目标不变,方法变了。


再接再厉,锲而不舍。当你遇到挫折时,要勇往直前。你的既定目标不变,努力的程度加倍。


移花接木,灵活机动。倘若原来太高的目标一时无法实现,可用比较容易达到的目标来替代,这也是一种适应的模式。


寻找原因,理清思路。当你受挫时,先静下心来把可能产生的原因寻找出来,再寻求解决问题 的方法。


情绪转移,寻求升华。可以透过自己喜爱的集邮、写作、书法、美术、音乐、舞蹈、体育锻炼等模式,使情绪得以调适,情感得以升华。


学会宣泄,摆脱压力。不妨找一两个亲近的人、理解你的人,把心里的话全部倾吐出来。从心理健康角度而言,宣泄可以消除因挫折而带来的精神压力,可以减轻精神疲劳。


必要时求助于心理咨询。当人们遭遇到挫折不知所措时,不妨求助于心理咨询机构。心理医生会对你动之以情,晓之以理,导之以行,循循善诱,使你从“山穷水复疑无路”的困境中,步入“柳暗花明又一村”的境界。


学会幽默,自我解嘲。“幽默”和“自嘲”是宣泄积郁、平衡心态、制造快乐的良方。当你遭受挫折时,不妨采用阿Q的精神胜利法,比如“吃亏是福”、“破财免灾”、“有失有得”等等来调节一下你失衡的心理。或者“难得胡涂”,冷静看待挫折,用幽默的方法调整心态。


 



心理保健-缓解工作压力1



如何缓解工作压力?


确定方向,不走冤枉路︰仔细想想做这项工作的重点是什么,希望藉此得到什么结果,这样做之后是不是真的能得到想要的结果,与你的主管及上下游流程的同事一同讨论,再决定整个方向及流程。


正面的看待问题,视为是一种挑战︰乐观而积极的工作态度是我们必胜的法宝。把负面的压力向正面转化,会有令人惊奇的斩获。


运用系统思考,工作分门别类进行︰养成把握重点,循序渐进,集中力量的习惯,决定次序,从最重要的事情着手。我们必须先决定那一个工作比较重 要,必须优先去做;那些比较不重要,可以缓办。不考虑优先次序所产生的另一结果,常是一无所成,而且被拖延或耽搁的事情,等之后再提出时,往往已失去时效性。


更有效地组织你的工作︰可能的话把工作分摊或委派以减小工作强度。要学会


   授权。我们可以为自己制订一个详尽的工作日志︰ 
  1.列出明天你所能预见的工作; 
  2.按照工作的重要性和紧急性做出划分和排序; 
  3.将不重要且不紧急的工作请别人代办,或者推后; 
  4.依照排序、有条不紊地把工作完成。  


 



心理保健-缓解工作压力2



建立良好的办公室关系︰与同事建立有益的、愉快的合作的关系;与同事建立有效的、支持性的关系,理解同事的问题并让同事也理解你的问题,了解自己和同事在工作中的权利和义务。


及时总结,妥善计划︰对所有的出色工作都记录在案,并不时查阅,一是总结经验,二是为自己寻找自信。为将要进行的工作,制定一些短期计划,做尽可能细致的准备。


不要给自己无谓的压力︰减少你所关注的琐事数量,别给自己增添无谓的压力,对自己无法控制的事情就由它去。


享受个人空间︰不要总是想着工作,努力在每天都安排一段时间处理自己的事情,如与家人、朋友在一起等。


适当的运动︰每天寻找时间放松,如呼吸新鲜空气,做适量的运动,散步,时常出入一下办公室,变换一下环境,这些活动有助于释放压力,放松大脑,恢复精力。


 



心理保健-放松心情的25个方法



1、如果您觉得力不从心,那么应停止任何额外的加班加点。


2、拥有一两个知心朋友。


3、犯错误后别过度内疚。


4、正视现实,因为回避问题只会加重心理负担,最后使得情绪更为紧张.


5、不必事事、时时进行自我责备。


6、有委屈不妨向知心人诉说一番。


7、常对自己提醒︰该放松放松了。


8、少说“必须”、“一定”等硬性词


9、对一些琐细小事不妨任其自然。


10、不要怠慢至爱亲朋。


11、学会"理智"地待人接物。


12、把挫折或失败当作人生经历中不可避免的有机组成部分。



13、实施某一计划之前,最好事先就预想到可能会出现坏的结果。


14、在已经十分忙碌的情况下,就不要再为那些份外事操心。


15、常常看相册,重温温馨时光。


16、常常欣赏谐剧,更应该学会说笑话.


17、洗个温水澡,边洗澡边唱歌。


18、卧室里常常摆放有鲜花。


19、欣赏最爱听的音乐。


20、去公园或花园走走。


21、回忆一下一生中最感福祉的经历。


22、结伴郊游。


23、邀请性格开朗、幽默的伙伴一聚。


24、力戒烟酒。


25、作5分钟的遐想。



        如果心态好,世界上一切都变得很美好。比如我今天很高兴,全心身都很轻松,走到马路上,看到阳光明媚,蓝天更蓝,空气很清新,满大街的人都很高兴,其实我个人高兴就感到世界很美好;我自己不高兴啊,心里很难受,就是山光水色你也欣赏不了,山珍海味也没有什么味道。因为躺上一张最好的床,高级席梦思床,一万多元钱一张的床,躺上床去翻来复去整夜地做恶梦也不行,心情不好,多好的东西都不行,实际上就是这样。心情好,一切都美好。

http://blog.matrix.org.cn/Jekey/date/20060613 星期二 2006年06月13日

好久没写blog了

由于最近一直忙于毕业论文答辩的问题,好久没来这里了,要去工作了,继续拾起以前的东西……

http://blog.matrix.org.cn/Jekey/date/20060503 星期三 2006年05月03日

(翻译)使用JSON加速AJAX

使用JSON加速AJAX

By Sean Kelly

当微软在IE中添加了用于执行JavaScript的ActiveX XMLHTTP对象以后,仿佛播下了AJAX这一Web应用开发的革命的火种。如今,Firefox, Safari, Opera, 以及其他的浏览器都提供了XMLHttpRequest,使得他们可以访问colr.org, backpackit.com, maps.google.com.这些网站的特点就是它们的应用程序表现和感觉和其他桌面应用程序一样,尽管他们运行在浏览器里边。

在AJAX里边,当用户查看和与页面交互的时候,页面的JavaScript代码向web服务器请求数据(AJAX里的“异步”)。这些请求是HTTP请求,就像一个浏览器在第一个地方取得页面,其中可以包括任意图片,样式表等等。同样的,XMLHttpRequest对象也可以用来取得各种数据,不只是XML。例如,JavaScript可以使用XMLHttpRequest从web服务器取得一个普通文本文件,并在一个表单里边显示其内容。

XMLHttpRequest对象通过查找位于数据前端的Content-type header来分析从web服务器返回的数据的MIME类型。例如,如果类型是text/plain,你可以通过检查XMLHttpRequest对象的responseText属性来访问该文本。但是,如果类型是text/xml,XMLHttpRequest对象有一个特殊的步骤:它对返回的文档运行一个XML解析,并在内存中建立一个文档对象模型(DOM)树来描述文档,使得文档在responseXML属性中可用。然后,你就可以使用JavaScript的标准DOM方法来操纵这个对象树并访问每个元素,属性以及树里的其他文本。

XML是交换数据的标准方法,但通常不是最好的方法。尽管XML可以为数据添加结构和元数据,但这确实是一个比较麻烦的方法。XML还有相当复杂的语法,需要一个解析器类解析它。在JavaScript中,XML必须被解析为DOM树才可以使用。并且,一旦构建了DOM树,你还不得不通过建立相应的JavaScript对象或其他方法才能在客户端应用程序中使用XML数据。

幸运的是,还有更好的办法。

使用JSON

JSON也就是JavaScript Object Notation,是一个描述数据的轻量级语法。JSON的优雅是因为它是JavaScript语言的一个子集。接下来你将看到它为什么如此重要。首先,来比较一下JSON和XML语法。

JSON和XML都使用结构化方法描述数据。例如一个地址簿应用程序可以提供用来产生XML格式的地址卡的web服务:



Sean Kelly
SK Consulting

kelly-AT-seankelly-DOT-biz

kelly-AT-seankelly-DOT-tv



+1 214 555 1212
+1 214 555 1213
+1 214 555 1214


1234 Main St
Springfield, TX 78080-1216

5678 Main St
Springfield, TX 78080-1316



http://seankelly-DOT-biz/

http://seankelly-DOT-tv/


使用JSON, 形式如下:

{
"fullname": "Sean Kelly",
"org": "SK Consulting",
"emailaddrs": [
{"type": "work", "value": "kelly-AT-seankelly.biz"},
{"type": "home", "pref": 1, "value": "kelly-AT-seankelly.tv"}
],
"telephones": [
{"type": "work", "pref": 1, "value": "+1 214 555 1212"},
{"type": "fax", "value": "+1 214 555 1213"},
{"type": "mobile", "value": "+1 214 555 1214"}
],
"addresses": [
{"type": "work", "format": "us",
"value": "1234 Main StnSpringfield, TX 78080-1216"},
{"type": "home", "format": "us",
"value": "5678 Main StnSpringfield, TX 78080-1316"}
],
"urls": [
{"type": "work", "value": "http://seankelly.biz/"},
{"type": "home", "value": "http://seankelly.tv/"}
]
}

如你所看到的,JSON有结构化的嵌套数据元素,这一点和XML相似。JSON也是基于文本的,XML也是如此。两者都使用Unicode。JSON和XML都很容易阅读。主观上,JSON更清晰,冗余更少。JSON WEB站点严格地描述了JSON语法,目前就是这样的。它确实是一个简单的小语言! XML确实适合标记文档,但是JSON是数据交互的理想格式。每个JSON文档描述了一个这样一个对象,该对象包含有:嵌套对象、数组、字符串、数字、布尔值或空值。

在这些地址卡例子代码中,JSON版本是更轻量级的,只占用了682字节的空间,而XML版本需要744字节空间。尽管这不是一个可观的节省。而实际的好处则来自解析过程。

XML对比JSON:地位丧失

通过使用XMLHttpRequest对象,可以从你的基于AJAX的应用程序取得XML和JSON文件。典型的,交互代码如下:

var req = new XMLHttpRequest();
req.open("GET", "http://localhost/addr?cardID=32", /*async*/true);
req.onreadystatechange = myHandler;
req.send(/*no params*/null);

作为WEB服务器响应,你提供的处理器函数(myHandler函数)被多次调用,为你提供提前终止事务,更新进度条等机会。通常的,只有在web请求完成以后才起作用:那时,你就可以使用返回的数据了。

为了处理XML版本的地址卡数据,myHandler的代码如下:

function myHandler() {
if (req.readyState == 4 /*complete*/) {
// Update address field in a form with first street address
var addrField = document.getElementById('addr');
var root = req.responseXML;
var addrsElem = root.getElementsByTagName('addresses')[0];
var firstAddr = addrsElem.getElementsByTagName('address')[0];
var addrText = fistAddr.firstChild;
var addrValue = addrText.nodeValue;
addrField.value = addrValue;
}
}

值得注意的是你不必解析XML文档:XMLHttpRequest对象自动地解析了,并使responseXML中的DOM树可用。通过使用responseXML属性,可以调用getElementsByTagName方法查找文档的地址部分,你还可以使用第一个去找到它。然后,可以再次调用getElementsByTagName在地址部分查找第一个地址元素。这就取得了文档的第一个DOM子节点,就是一个文本节点,并取得节点的值,这就是你想要的街道地址。最后,可以在表单域中显示结果。

确实不是一个简单的工作,现在,使用JSON再试一下:
function myHandler() {
if (req.readyState == 4 /*complete*/) {
var addrField = document.getElementById('addr');
var card = eval('(' + req.responseText + ')');
addrField.value = card.addresses[0].value;
}
}

你所做的第一件事情就是解析JSON响应。但是,因为JSON是JavaScript的一个子集,你可以使用JavaScript自己的编译器来解析它,通过调用eval函数。解析JSON仅需要一行!此外,操纵JSON中的对象就像操纵其他JavaScript对象一样。这显然要比通过DOM树来操纵简单,例如:
card.addresses[0].value 是第一个街道地址, "1234 Main Stb &"
card.addresses[0].type 是地址类型, "work"
card.addresses[1] 是家庭地址对象
card.fullname 是card的名称, "Sean Kelly"
如果更仔细观察,你可能会发现XML格式中文档至少有一个跟元素,card。这在JSON里是不存在的,为什么? 大概就是,如果你正在开发JavaScript来访问Web服务,你已经知道你想要得到的。然而,你可以在JSON中这么使用:
{"card": {"fullname": ...}}
使用这个技术,你的JSON文件总是以一个带有单一命名属性的对象开始,该属性标识了对象的种类。

JSON是快速可靠的吗?

JSON提供轻量的小文档,并且JSON在JavaScript更容易使用。XMLHttpRequest自动为你解析了XML文档,而你还要手工解析JSON文件,但是解析JSON比解析XML更慢么?作者通过几千次的反复测试,使用XMLHttpRequest解析XML和解析JSON,结果是解析JSON比XML要快10倍!当把AJAX当作桌面应用看待时,速度是最重要的因素,很明显,JSON更优秀。

当然,你不能总是控制服务器端来为AJAX程序产生数据。你还可以使用第三方服务器代替服务器提供XML格式的输出。并且,如果服务器恰好提供JSON,你可以确定你真的想使用它吗?

代码中值得注意的是,你将响应文本直接传入到eval中。如果你控制着服务器,就可以这么做。如果不是,一个恶意服务器可以使你的浏览器执行危险操作。在这样的情况下,你最好使用写在JavaScript中的代码来解析JSON。幸运地,这已经有了。

说到解析,Python爱好者可能注意到JSON不只是JavaScript的子集,它还是Python的一个子集。你可以在Python中直接执行JSON,或者使用安全JSON解析代替。JSON.org网站列举了许多常用JSON解析器。

服务器端的JSON

到现在为止,你或许将焦点注意在运行在客户浏览器中的基于AJAX的web应用程序使用JSON。自然地,首先,JSON格式的数据必须在服务器端产生。幸运地是,创建JSON或将其他存在的数据转换成JSON是相当简单的。一些WEB应用程序框架,例如TurboGears,自动包括对JSON输出的支持。

此外商业WEB服务提供商也注意到了JSON。Yahoo最近创建了许多基于JSON的web服务。Yahoo的多种搜索服务,履行计划,del.icio.us,还有高速公路交通服务也都支持JSON输出。毫无疑问,其他主要WEB服务提供商也将加入到对JSON的支持中。

总结

JSON的聪明在于它是JavaScript和Python的子集,使得它更易用,为AJAX提供高效的数据交互。它解析更快,比XML更易使用。JSON正成为现在“Web 2.0”的最强音。每个开发者,无论是标准桌面应用程序或Web应用程序,越来越注意到了它的简单和便捷。我希望你能体会到在buzzword-compliant, Web-2.0-based, AJAX-enabled, 敏捷开发中应用到JSON的乐趣。

关于作者

Sean Kelly 是一个希腊神话和喜剧爱好者,注意到了AJAX和JSON的潜在作用。他的AJAX团队Argonauts打算解决在web应用开发,python,AJAX,java,web服务以及令人生厌的XML中的各种问题。他在医学,天文学以及数字媒体工业等方面都有研究,还坚持每天都做瑜伽。他和他妻子Mary以及女儿Ariana居住在一个不为人知的地方。

http://blog.matrix.org.cn/Jekey/date/20060502 星期二 2006年05月02日

Ajax Hack 之hack 13 在text或textarea里显示服务器信息

本hack讲的是不刷新页面显示服务器信息。

用户可以通过输入text和服务器组件交互而不用每次都等待页面的刷新。一个典型的例子就是拼写检测或自动完成field[Hack #78]。使用request 对象作为媒介,服务器组件可以和用户之间实时交互。

本hack显示一个自动的服务器响应,响应无刷新的显示在text中。本hack是[Hack #12]的扩展,该hack使用request对象将用户提交的数据传送给服务器组件。

本hack获取用户提交的信息,并将统计的结果显示在相同的标签里边。你也可以使用client-side JavaScript完成相同的工作,当然,为了证明某个服务器组件做了这个工作,本hack还显示了服务器的一些信息。

图2-2 显示了初始页面

图2-3显示了输入信息以后按tab后的结果

下面是页面的html代码。引入了js文件hacks_2_1.js。

"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">





Submit your information


Get stats from textareas and textfields using Ajax






Enter a few words for submitting to our server:
Enter a phrase for submitting to our server:


上一个hack讲的是如何无刷新地提交用户信息。换句话说,在用户键入一些信息并按tab按钮或点击其他区域后,text里边的数据就被传送给了服务器。

onblur事件将调用getInfo( )函数,将text中的信息作为参数传递。

完整的代码在hack12里边,在这里就不再完整列举了。下面将getInfo( )函数和handleResponse( )函数作为重点介绍一下。

function getInfo(obj){
if (obj == null ) { return; }
formObj=obj;
formObjTyp =obj.tagName;
if(formObjTyp == "input" || formObjTyp == "INPUT"){
formObjTyp = formObjTyp + " "+formObj.type;
}
formObjTyp = formObjTyp.toLowerCase( );
var url = "http://www.parkerriver.com/s/webforms?objtype="+
encodeURIComponent(formObjTyp)+"&val="+
encodeURIComponent(obj.value);
httpRequest("GET",url,true);
}

这个函数将用户键入的信息作为val参数传递给服务器组件。此外obj参数持有的是text对象,用来取得键入的信息。这是一个DOM对象,如HTMLInputElement或HTMLTextAreaElement

即时服务器消息传递

服务器程序取得用户键入的信息,然后将统计的结果返回。为了确定响应信息,服务器返回的信息的格式是JSON格式[Hack #7]。JSON是一种很容易处理的XML文件格式。

返回的数据也可以作为一个简单的字符串。使用JSON格式只是作者的个人爱好而以。不过确实很容易使用。

下面的代码是一个服务器返回的JSON文件,如果用户在textarea里键入了55个词:
{
Form_field_type: "textarea",
Text_length: "385",
Word_count: "55",
Server_info: "Apache Tomcat/5.0.19"
}

这段代码描述了一个有四个不同属性的js对象:Form_field_type, Text_length,Word_count, 和Server_info. 下面的代码也显示了如何处理这个对象的每个属性。接着heack取得这一服务器响应信息,并将它插入到textarea里边。
handleResponse( )函数:
//event handler for XMLHttpRequest
function handleResponse( ){
try{
if(request.readyState == 4){
if(request.status == 200){
var resp = request.responseText;
if(resp != null){
var func = new Function("return "+resp);
var objt = func( );
if(formObjTyp == "textarea"){
if(formObj != null){
formObj.value = objt.Form_field_type +
" character count: "+objt.Text_length+
"\\nWord count: "+
objt.Word_count+"\\nServer info: "+
objt.Server_info;
}
} else if(formObjTyp == "input text"){
if(formObj != null){
formObj.value = objt.Form_field_type +
" # characters: "+objt.Text_length+
" Word count: "+objt.Word_count; }
}
}
} else {
//request.status is 503
//if the application isn't available;
//500 if the application has a bug
alert(
"A problem occurred with communicating "+
"between the XMLHttpRequest object and "+
"the server program.");
}
}//end outer if
} catch (err) {
alert(err.name);
alert("It does not appear that the server "+
"is available for this application. Please"+
" try again very soon. \\nError: "+err.message);
}
}

代码以文本格式取得响应信息。因为文本的格式是JSON(作为js的对象),代码使用了这一特殊的技术在hack7里边。构造函数将text作为一个js对象返回。在这个例子里,objt变量指的是服务器组件的响应,使用传递对象方法,你可以使用objt.Server_info来取得服务器信息。

下面的代码就是将响应信息作为一个对象返回:
var resp = request.responseText;
var func = new Function("return "+resp);
//call the function and return the object to which
//the objt variable now points
var objt = func( );

下面的代码是将信息插入到textarea里边。

if(formObjTyp == "textarea"){
if(formObj!= null){
formObj.value = objt.Form_field_type +
" character count: "+objt.Text_length+
"\\nWord count: "+
objt.Word_count+"\\nServer info: "+
objt.Server_info;
}
}

图2-3显示了结果。
你可以访问 textarea,使因为这是一个顶级JavaScript变量,formObj指向了它。代码的关键之一是设置textarea或text的值。

当服务器发信息给textarea而不是text时,会包括换行(\\n in JavaScript),因为textarea能显示更多文本。而text不能包含换行符,因为text只有一行。

http://blog.matrix.org.cn/Jekey/date/20060423 星期日 2006年04月23日

Ajax Hack 之hack 12不刷新浏览器的情况下向服务器提交text或textarea的值

本节主要讲的是:将text或textarea的值平滑地传递给服务器。

当用户输入text或textarea的值以后,Ajax能将这些值自动的发给服务器。程序等待text的onblur
事件,然后使用request对象向服务器发送数据。在常用的情况是,用户点击一个按钮,然后将
整个form作为一个大的数据包向服务器发送。服务器相应也与此类似。例如,在线测试或者
教程能在用户输入完成以后很快显示结果,而不需要用户点击按钮刷新页面得到结果。

形如form的某些元素,如text等失去键盘焦点的时候将激发onblur事件,通常是用户点击tab键
或者点击其他区域。也可以使用onkeypress, onkeydown, 或 onkeyup 等来处理用户和text部件
的交互。

接下来向服务器发送数据的步骤:
1. 用户将焦点移入text。
2. 在text中输入信息。
3. 用户点击tab键或点其他区域。

用户在text里输入一些信息,然后程序自动将信息发给服务器。在这个过程中,最好加入
信息提示,如alert一个对话框,在发送过程中最好能让用户知道程序在运作,如有一个进度条。

下面是页面的html代码:

"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">





Submit your information


Get stats from textareas and textfields using Ajax




Enter a few words for submitting to our server:



Enter a phrase for submitting to our
server:




用户不必点击任何按钮来发送信息,每个text都能控制自己的行动。

当用户按tab键,或者点了text部件以外的区域时,onblur事件将激发处理程序。下面的代码
将显示事件处理者是如何进行工作的。

本节使用的js源代码在文件hacks_2_1.js中。这个文件中有程序运行所需的所有代码。
代码中包括了发送请求和处理相应值(handleResponse( )函数)的所有代码。在下一节中,
会讲述如何将服务器相应插入到text部件中的相关技术,但这丝毫不影响你理解handleResponse( )
函数,下面是js代码:

var formObj = null;
var formObjTyp = "";
var request=null;

//input field's event handlers
window.onload=function( ){
var txtA = document.getElementById("tarea");
if(txtA != null){
txtA.onblur=function( ){if (this.value) { getInfo(this);}}; }

var tfd = document.getElementById("tfield");
if(tfd != null){
tfd.onblur=function( ){if (this.value) { getInfo(this);}}; }
}

function getInfo(obj){
if (obj == null ) { return; }
formObj=obj;
formObjTyp =obj.tagName;
if(formObjTyp == "input" || formObjTyp == "INPUT"){
formObjTyp = formObjTyp + " "+formObj.type;
}
formObjTyp = formObjTyp.toLowerCase( );
var url = "http://www.parkerriver.com/s/webforms?objtype="+
encodeURIComponent(formObjTyp)+"&val="+ encodeURIComponent(obj.value);
httpRequest("GET",url,true);
}

//event handler for XMLHttpRequest
function handleResponse( ){
try{
if(request.readyState == 4){
if(request.status == 200){
var resp = request.responseText;
var func = new Function("return "+resp);
var objt = func( );
if(formObjTyp == "textarea"){
if(formObj != null){
formObj.value = objt.Form_field_type +
" character count: "+objt.Text_length+
"\\nWord count: "+
objt.Word_count+"\\nServer info: "+
objt.Server_info;
}
} else if(formObjTyp == "input text"){
if(formObj != null){
formObj.value = objt.Form_field_type +
" # characters: "+objt.Text_length+
" Word count: "+objt.Word_count; }
}
} else {
//request.status is 503
//if the application isn't available;
//500 if the application has a bug
alert(
"A problem occurred with communicating between the "+
"XMLHttpRequest object and the server program.");
}
}//end outer if
} catch (err) {
alert("It does not appear that the server is available "+
"for this application. Please"+
" try again very soon. \\nError: "+err.message);

}
}

/* Initialize a request object that is already constructed */
function initReq(reqType,url,bool){
try{
/* Specify the function that will handle the
HTTP response */
request.onreadystatechange=handleResponse;
request.open(reqType,url,bool);
request.send(null);
} catch (errv) {
alert(
"The application cannot contact the server "+
"at the moment. "+
"Please try again in a few seconds." );
}
}
/* Wrapper function for constructing a request object.
Parameters:
reqType: The HTTP request type, such as GET or POST.
url: The URL of the server program.
asynch: Whether to send the request asynchronously or not. */
function httpRequest(reqType,url,asynch){
//Mozilla-based browsers
if(window.XMLHttpRequest){
request = new XMLHttpRequest( );
} else if (window.ActiveXObject){
request=new ActiveXObject("Msxml2.XMLHTTP");
if (! request){
request=new ActiveXObject("Microsoft.XMLHTTP");
}
}
//the request could still be null if neither ActiveXObject
//initialization succeeded
if(request){
initReq(reqType,url,asynch);
} else {
alert("Your browser does not permit the use of all "+
"of this application's features!");}
}

代码首先声明了两个全局的js变量:formObj和formObjTyp。前者持有input
或textarea对象(其他函数需要访问),后者持有一个string描述form对象的标记
名称,如input或textarea。这个string也是服务器组件需要的变量之一。

如前所述,在浏览器加载页面时,代码就为text部件的onblur事件指定了处理器。
你可以使用js在window的onload事件处理中来完成这个工作。使用window.onload,
也可在html中直接指定。
window.onload=function( ){
var txtA = document.getElementById("tarea");
if(txtA != null){
txtA.onblur=function( ){if (this.value) { getInfo(this);}}; }
var tfd = document.getElementById("tfield");
if(tfd != null){
tfd.onblur=function( ){if (this.value) { getInfo(this);}}; }
}
现在,这些text是hot的。当用户输入完信息,退出控制以后,信息输入就完成了,
接下来向服务器发送信息;用户不必点击其他按钮。

text-field事件处理器调用getInfo( )函数。函数抽取用户键入的信息,并向服务器发送。
function getInfo(obj){
if (obj == null ) { return; }
formObj=obj;
formObjTyp =obj.tagName;
if(formObjTyp == "input" || formObjTyp == "INPUT"){
formObjTyp = formObjTyp + " "+formObj.type;
}
formObjTyp = formObjTyp.toLowerCase( );
var url = "http://www.parkerriver.com/s/webforms?objtype="+
encodeURIComponent(formObjTyp)+"&val="+
encodeURIComponent(obj.value);
httpRequest("GET",url,true);
}

getInfo( )函数的参数是text或textarea对象。传递进取是为了能够取得该对象的信息。

最后一部分httpRequest("GET",url,true)函数发送用户信息到服务器。

然而,在代码调用函数前,一些事情发生了。服务器组建期待的是一个描述form类型的字符串。
formObjTyp =obj.tagName;
if(formObjTyp == "input" || formObjTyp == "INPUT"){
formObjTyp = formObjTyp + " "+formObj.type;
}
formObjTyp = formObjTyp.toLowerCase( );
var url = "http://www.parkerriver.com/s/webforms?objtype="+
encodeURIComponent(formObjTyp)+"&val="+ encodeURIComponent(val);
httpRequest("GET",url,true);

全局函数encodeURIComponent( )方法用来确认某些特性,如空格等,在他们被包含到URL中
的时候得到编码。否则,程序可能会发送一个错误的URL给服务器,而引发错误。

接下来:
在提交数据以后,会发生什么呢? 这要取决于你的程序。下一节将讲述另一个话题:是用js和
ajax将服务器相应值插入到一个存在的text部件中。

http://blog.matrix.org.cn/Jekey/date/20060417 星期一 2006年04月17日

Ajax Hack 之hack 11 动态产生样式

为web内容动态定义和制定CSS样式。

JavaScript和DOM编程允许用户定义CSS样式属性,并应用于页面元素。一个典型的例子是一个wiki页面允许用户设计自己页面的方案和样式。

通常情况下,比较好的方法是将样式定义从JavaScript代码中分离出来。这样的习惯可以使元素独立扩展,降低web页面元素的复杂性,使之更高效。

本hack和上一个相似,根据用户选择的样式,动态显示服务器信息。和前一个不同之处就是:这里是在代码里边定义样式,然后应用于html。代码如下:

var request;
var urlFragment="http://localhost:8080/";
var st;

function getAllHeaders(url,styl){
if(url){
st=styl;
httpRequest("GET",url,true);
}
}

/* Set one or more CSS style attributes on a DOM element
CSS2Properties Object.
Parameters:
stType stands for a style name, as in 'plain,''fancy,''loud,' or 'cosmo'.
stylObj is the HTML element's style property, as in div.style. */

function setStyle(stType,stylObj){
switch(stType){
case 'plain' :
stylObj.maxWidth="80%";
stylObj.border="thin solid black";
stylObj.padding="5%";
stylObj.textShadow="none";
stylObj.fontFamily="Arial, serif";
stylObj.fontSize="0.9em";
stylObj.backgroundColor="yellow"; break;
case 'loud' :
stylObj.maxWidth="80%";
stylObj.border="thin solid black";
stylObj.padding="5%";
stylObj.fontFamily="Impact, serif";
stylObj.fontSize="1.4em";
stylObj.textShadow="0 0 2.0em black";
stylObj.backgroundColor="rgb(181,77,79)"; break;
case 'fancy' :
stylObj.maxWidth="80%";
stylObj.border="thin solid black";
stylObj.padding="5%";
stylObj.fontFamily="Herculanum, Verdana, serif";
stylObj.fontSize="1.2em";
stylObj.fontStyle="oblique";
stylObj.textShadow="0.2em 0.2em grey";
stylObj.color="rgb(21,49,110)";
stylObj.backgroundColor="rgb(234,197,49)"; break;
case 'cosmo' :
stylObj.maxWidth="80%";
stylObj.border="thin solid black";
stylObj.padding="1%";
stylObj.fontFamily="Papyrus, serif";
stylObj.fontSize="0.9em";
stylObj.textShadow="0 0 0.5em black";
stylObj.color="aqua";
stylObj.backgroundColor="teal"; break;
default :
alert('default');

}
}

//event handler for XMLHttpRequest
function handleResponse( ){
try{
if(request.readyState == 4){
if(request.status == 200){
/* All headers received as a single string */
var headers = request.getAllResponseHeaders( );
var div = document.getElementById("msgDisplay");
if(st){
setStyle(st,div.style);
} else {
setStyle("plain",div.style);
}
div.innerHTML="

"+headers+"
";
} else {
//request.status is 503 if the application isn't available;
//500 if the application has a bug
alert(request.status);
alert("A problem occurred with communicating between "+
"the XMLHttpRequest object and the server program.");
}
}//end outer if
} catch (err) {
alert("It does not appear that the server is available for "
"this application. Please"+
" try again very soon. \\nError: "+err.message);

}
}

/* Initialize a request object that is already constructed */
function initReq(reqType,url,bool){
try{
/* Specify the function that will handle the HTTP response */
request.onreadystatechange=handleResponse;
request.open(reqType,url,bool);
request.send(null);
} catch (errv) {

alert(
"The application cannot contact the server at the moment. "+
"Please try again in a few seconds." );
}
}

/* Wrapper function for constructing a request object.
Parameters:
reqType: The HTTP request type such as GET or POST.
url: The URL of the server program.
asynch: Whether to send the request asynchronously or not. */
function httpRequest(reqType,url,asynch){
//Mozilla-based browsers
if(window.XMLHttpRequest){
request = new XMLHttpRequest( );
} else if (window.ActiveXObject){
request=new ActiveXObject("Msxml2.XMLHTTP");
if (! request){
request=new ActiveXObject("Microsoft.XMLHTTP");
}
}
//the request could still be null if neither ActiveXObject
//initialization succeeded
if(request){
initReq(reqType,url,asynch);
} else {
alert("Your browser does not permit the use of all "+
"of this application's features!");
}
}

如果浏览器支持CSS样式,每个页面上的每个HTML元素都会有一个style属性。例如,div元素有一个元素叫div.style允许JavaScript编写者为此div设置内联样式属性(如div.style.fontFamily="Arial")。这就是setStyle函数的工作。两个参数一个是样式名称,例如“Fancy”(从预选定义的list里边选择),另一个是样式所指定的div元素。函数设定了HTML div元素在页面上的外观。

显示在页面上的信息(一串响应头信息)来自服务器的响应对象。如前一个hack一向,用户输入一个URL,然后点击tab或者其他部分,最后显示信息。代码如下:

"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">





view response headers


Find out the HTTP response headers when you "GET" a Web page


Choose the style for your message






Enter a URL: "getAllHeaders(this.value,this.form._style.value)">
«press tab or
click outside the field when finished editing»





getAllHeaders函数,onblur的时间处理,将用户选择的style名称传入。服务器组件的唯一目的就是提供要显示的信息。我们重点是在动态产生样式代码。

http://blog.matrix.org.cn/Jekey/date/20060413 星期四 2006年04月13日

观点争鸣:AJAX是否能够取代桌面应用程序(转载自天极yesky)

作者:朱先忠编译
 
 一、 引言

  在AJAX是否能够取代桌面应用程序的问题上,存在很多争论。如今,这两种阵营正在逐步形成。在本文中,我的看法是:AJAX不可能取代桌面应用程序;但是它将导致一种新型软件应用程序的出现。大多数AJAX程序应该会是生产工具、协作和商业应用程序。许多桌面应用程序将不再会出现;当然,大多数应用程序也不可能很快就会离开强有力的和舒适的桌面环境。我想,软件发展的下一个阶段应该是,桌面应用不大可能全部消失;相比之下,而更有可能是适度的重新组合,其结果是各种应用程序分别在最适合它们的领域繁荣壮大。

  面向AJAX的web应用程序紧紧跟随在你的身边,就象所有的web应用软件一样。我们中的大多数至少有一位在世界其它地方的朋友并且经由电子邮件,如hotmail或yahoo电子邮件,帐户与之保持联系。事实上,这些基于浏览器的电子邮件接口大大帮助驱动了电子邮件为个人所采纳使用。如今,针对商业类型电子邮件使用的更传统型的html接口已经逐渐地不再具有实用价值。因某些原因,Outlook Web Access(OWA)(尽管它有一个伟大的AJAX接口)不再象以前那么流行,但是Gmail和Zimbra却正在异军突起,而且Zimbra力图全面取代Outlook和Exchange-全面地通过浏览器来实现UI表达。微软值得被赞扬的是,是Live.com的出现正在产生一种新型的AJAX化的电子邮件客户端-如果它的样子类似于OWA的话,它将比Hotmail更为易用和好用。如果你观察一下CRM世界,你就会注意到,似乎Web应用软件已经接管其主要功能。例如,Salesforce.com就是一个明显的例子,而MS CRM就是几年来通过一个Web浏览器表达实现的。

  二、 基于AJAX的Web应用程序会在哪些方面取代桌面程序?

  基于AJAX的Web应用程序是某些应用程序的合乎逻辑的自然选择-在这样的程序中,最新的和共享的信息至关重要,例如后勤、财务和CRM系统等方面的程序。常规的Excel工作簿,作为一种分布价格和顾客列表的方法,将会自然地走到历史的角落里。及时的商业数据是现代商业软件中的一个关键组成部分,而Web应用程序本来就是以数据为中心的。AJAX仅是把一个UI放到了应用程序之上,而这一点在用户等待鼠标点击之间的页面刷新时不会给他们带来过多的麻烦。

  许多应用程序依赖于Web服务和例如映射服务这样的迥异数据源来结合多重的庞大的数据源以保持相关连和有用性。另外,许多基于面向服务的架构(SOA)的企业系统成为具有分布性和可用性优点的AJAX应用软件的完美候选。通过浏览器发行的丰富的客户端将帮助降低单套软件的许可花费,例如在企业报告应用软件方面。最近一个大型SOA软件供应商的CTO问我,怎样在基于AJAX的UI客户端强制实现单套软件许可证协议。而这一问题的简短答案是,它不可能是与以前大部分客户端程序走相同的路子。这一事实将导致开发软件许可新途径的软件供应商更快地向AJAX迁移,但是不会减少消费者对于其喜爱的丰富的客户端软件的需要。

  显然,软件主要的好处主要还是看市场需求而定。很多软件,作为一种服务,应用程序服务供应商仍旧在应用之,因为该应用程序仍在通过Web和Web浏览器传送中。浪费时间去细究基于浏览器的应用软件的好处是愚蠢的;然而,特别要注意的是,AJAX使得基于浏览器的应用软件相当易于使用。这些可用性好处可以从在与更快的用户接口进行交互时节约大量时间这一角度加以衡量。Alexei White已经在他的《Measuring the Benefits of Ajax》一文中详细地探讨了这个问题。由于这些原因,AJAX在在线应用软件方面将是一个大的获胜者-这种场所下,用户总是在做大量的重复的任务-例如呼叫中心和金融机构。在你有大量的相同任务的场所,应用软件和信息工人往往能够熟练地使用AJAX Web应用软件。

  一直以来不断发展和变化的应用程序也会从中受益。用户迁移到新型应用软件将毫无副作用影响。另外,AJAX技术有助于提升已经基于HTML接口或有一个SOA架构的应用程序的质量。这对于一直在寻求提升可用性的开发团队将是极具吸引力的。

  另一个AJAX将会占上风的领域是在商业-这里用户分布在不同的地理区域并且支持多个Web浏览器并且其互联网连接是很昂贵的。

  三、 桌面程序会在什么地方继续保持霸主地位?

  特别值得开发者们注意的是,桌面应用在哪些方面不会被丰富的Web应用软件所取代,因为即使是最大的AJAX福音传道者也会告诉你,我们利用这种技术目前所仅能够达到的程度。让我们分析一下AJAX无法良好实现的几个方面:

  · 浏览器定制:添加按钮、工具栏、书签、图标;改变浏览器行为。

  · 本地文件存取:读写用户硬盘上的文件。

  · 声音播放:音乐和声音效果。

  · 丰富的图形:提供丰富的动态变化的图形。(随着SVG慢慢地引入到一些浏览器,这种应用正在逐渐发展中,但是它目前还不匹配桌面图形。)

  · 键盘快捷键:提供全范围的键盘快捷键从而避免与浏览器自己的键盘快捷键发生冲突。

  · 硬件存取:从如麦克风,webcams,和gamepads等进行输入设备;输出到设备象打印机和便携式小器具。

  · 扩大的通讯:从客户端机器到位置超出基本服务器以外位置的通讯,以及用除了普通的旧式HTTP协议以外的其它协议。

  · 操作系统交互:缓冲事件;改变配置;弹出警告;读取硬件信息。

  当然,AJAX还不支持视频或音频;因此,视频会议、VOIP和丰富的媒体应用软件还无法加入到其中。但是随着Flash加入到UI开发技术中,丰富的媒体将会被集成进一个AJAX接口。另外,在其它应用程序担心处理器及需要消耗大量内存的程序中,AJAX技术还不适合。我们还会看到,象视频编辑、相片操作和视频游戏等一类应用程序相当恰当地出现在Web浏览器上还需要一段时间。目前,我还从未看到有人在玩一种通过JavaScript技术实现的Quake风格的第一人称射击游戏。其实,其意义也并不大。

  四、 桌面软件会在什么方面利用web技术的优点?

  桌面应用世界将极大地受益(并且已经受益)于Web服务和SOA的使用,并且我们将继续看到这两个世界的更多的集成。如今,我们已经看到桌面应用软件在使用着互联网所提供的丰富的内容,例如iTunes和与基于AJAX的服务在线集成的桌面应用软件,如Live.com和MS Office。
在为新型应用软件(基于Web的)渗透和接纳率方面,AJAX广受欢迎。从未有其它技术具有如此小的阻碍-所有你需要的就是一个浏览器和一个互联网连接。而且,既然新型软件能够那么快地接纳这一技术,那么,许多AJAX应用程序将会比客户端应用软件能更快速地体验网络效果的优点。

  五、 AJAX会在哪些方面创造新的服务机会?

  让我们先分析一下Google地图-没有用户能够在他们的本地桌面上拥有所有的地图、图象和生意/地址目录数据。进一步推进这一概念的mashups是一个网站或web应用程序,它无缝地把来自于多个数据源的内容整合进一种完整的体验中。如果当用户想结合不同数据集时必须安装一个插件或某种程序的话,这种程序不会工作。即使一客户端应用程序拥有这些数据,它们也无法让其与以Web为中心的应用程序一样容易地保持最新。

  协作将被加入到应用程序中,这在以前是从未有过的。象Writely这样的系统,一旦被纳入到实践中,将改变我们看待办公室类型应用程序的方式。从一开始,所有的应用程序都有一个共同的浏览器平台,并且使用共同的语言(XML,HTML,等等)。这意味着,随着这些小应用程序的不断发展,集成它们也会越来越容易。当前MS Office能够与其自身良好集成并且如果你使用SharePoint的话,它对于协同工作相当不错。然而这要依赖于在每个客户端安装巨大量的软件和启动精深的服务器基础结构。但是web应用软件应该改进这种体验并且AJAX将使得这些Web应用软件具有极大的可用性。

  借助于web上强有力的数据服务,再结合丰富的AJAX UI的力量,实时协作应用程序将永远改变。

  六、 结论

  软件的未来会是什么样子呢?我想,这在我们这一代正发生着巨大变化。由于AJAX增强的可用性,我们将毫无疑问地看到出现大量的新型的基于Web的应用程序。并且,因为随着开发者社区继续协同工作,我们一定会在今天AJAX所依赖的技术方面作出许多重大改进。如今,我们只是刚刚看到了冰山一角罢了。然而,我想桌面应用程序的力量将继续统治着某些应用程序领域并且实际上可能从不会消失。

http://blog.matrix.org.cn/Jekey/date/20060412 星期三 2006年04月12日

Ajax Hacks-Hack 10. 使用CSS文件产生格式化的信息

让用户选择他们喜爱的消息格式。

hack向服务器发送一个请求,服务器返回一个文本信息。而用户的选择将决定信息的内容和表现形式。HTML代码有一个下拉选择,让用户选择结果的表示形式。

下面是HTML代码:

"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">





view response headers



Find out the HTTP response headers when you "GET" a Web page


Choose the style for your message






Enter a URL: "getAllHeaders(this.value,this.form._style.value)"> "instr" class="message">«press tab or click outside the field
when finished editing»





函数setSpan的目的是将("press tab or click outside the field when finished editing")的格式设置为,当鼠标移动到上方是文本背景变为黄色,当鼠标移开时,恢复为白色。

此web页面的CSS格式源于文件hacks.css。当用户从下拉选项中选择一个样式后,输入URL,按tab键或点击输入框以外的部分,按照用户选择的样式的响应信息将会显示出来。

以下是文件hacks.css:

div.header{ border: thin solid black; padding: 10%;
font-size: 0.9em; background-color: yellow; max-width: 80%}

span.message { font-size: 0.8em; }
div { max-width: 80% }

.plain { border: thin solid black; padding: 10%;
font: Arial, serif font-size: 0.9em; background-color: yellow; }
.fancy { border: thin solid black; padding: 5%;
font-family: Herculanum, Verdana, serif;
font-size: 1.2em; text-shadow: 0.2em 0.2em grey; font-style: oblique;
color: rgb(21,49,110); background-color: rgb(234,197,49)}
.loud { border: thin solid black; padding: 5%; font-family: Impact, serif;
font-size: 1.4em; text-shadow: 0 0 2.0em black; color: black;
background-color: rgb(181,77,79)}
.cosmo { border: thin solid black; padding: 1%;
font-family: Papyrus, serif;
font-size: 0.9em; text-shadow: 0 0 0.5em black; color: aqua;
background-color: teal}

样式表定义了几个类(plain, fancy, loud, and cosmo)。

The Ajax-related JavaScript code can assign the predefined styles to page elements based on user choices. Therefore, the presentation tier of your web application is separated from the application logic or domain tier.

The onblur event handler for the text field submits the URL value and the style name to a function named getAllHeaders( ):

onblur="getAllHeaders(this.value,this.form._style.value)"

The reference this.form._style.value is JavaScript that represents the value of the option chosen from the select list (the style name). The reference this.value is the text entered by the user in the text field.

Here is the JavaScript code that the page imports from hacks8.js, with the code that dynamically assigns the style to the displayed message highlighted:

var request;
var urlFragment="http://localhost:8080/";
var st;

function getAllHeaders(url,styl){
if(url){
st=styl;
httpRequest("GET",url,true);
}
}

//event handler for XMLHttpRequest
function handleResponse( ){
try{
if(request.readyState == 4){
if(request.status == 200){
/* All headers received as a single string */
var headers = request.getAllResponseHeaders( );
var div = document.getElementById("msgDisplay");
div.className= st == "" ? "header" : st;
div.innerHTML="

"+headers+"
";
} else {
//request.status is 503 if the application isn't available;
//500 if the application has a bug
alert(request.status);
alert("A problem occurred with communicating between "+
"the XMLHttpRequest object and the server program.");
}
}//end outer if
} catch (err) {
alert("It does not appear that the server is available for "+
"this application. Please"+
" try again very soon. \\nError: "+err.message);

}
}

/* See Hacks #1, #2, and others for definitions of the httpRequest( )
and initReq( ) functions; snipped here for the sake of brevity. */

Easy as Pie
The getAllHeaders( ) function sets a top-level st variable to the name of a CSS style class (plain, fancy, loud, or cosmo). The code then sets the className property of the div that holds the message in a shockingly simple way, which changes the style assigned to the message:

if(request.status == 200){
/* All headers received as a single string */
var headers = request.getAllResponseHeaders( );
var div = document.getElementById("msgDisplay");
div.className= st == "" ? "header" : st;
div.innerHTML="

"+headers+"
";
}

http://blog.matrix.org.cn/Jekey/date/20060410 星期一 2006年04月10日

Ajax Hacks-hack9 深入了解HTTP Response

HTTP响应头是描述性的信息,符合HTTP 1.1 协议规范,web服务器向请求端发送精确的页面或数据。如果你已经使用XMLHttpRequest对象编过程(在本章的前面讨论过),你应该知道request.status属性是从服务器返回的响应状态码。它是用来检测HTTP响应状态的重要值。

装态值包括200(请求成功)、404(请求的URL不存在,或页面不存在)500(服务器内部错误)。

然而,你还想看到更多的其他优选请求的响应头信息,例如与响应相关的web服务器软件类型(服务器请求头),或者响应的content类型(Content-Type)。本hack请求用户输入的一个URL。当用户点击输入框以外的部分时,浏览器会显示该URL的响应头信息。作为一个ajax应用,页面是不会出现刷新情况的。

请求对象方法只返回可用的响应头的一个子集,包括Content-Type, Date, Server,和Content-Length.

HTML代码如下:

"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">




view response headers



Find out the HTTP response headers when you "GET" a Web page


Enter a URL:

::press tab when finished editing the
field::





Figure 1-13 shows the page in the Safari browser.

Figure 1-13. Scoping the response

程序预先使用http://www.parkerriver.com/s/sender?name=guest来填充该text。

当用户输入URL以后点击Tab键,或点击输入框外的部分时,输入框的onblur事件被激发。事件处理函数是getAllHeaders,该函数传递用户输入的RUL进入request对象。request对象向此URL发送请求,并向web页面返回的响应头。

下面的代码是文件hack7.js。显示代码以后,将解释一下如何显示服务器响应头信息。其余的可以参考本章其他hack。

var request;
var urlFragment="http://www.parkerriver.com/s/sender?name=guest";

function getAllHeaders(url){
httpRequest("GET",url,true);
}

//function for XMLHttpRequest onreadystatechange event handler
function handleResponse( ){
try{
if(request.readyState == 4){
if(request.status == 200){
/* All headers received as a single string */
var headers = request.getAllResponseHeaders( );
var div = document.getElementById("msgDisplay");
div.className="header";
div.innerHTML="

"+headers+"
";
} else {
//request.status is 503 if the application isn't available;
//500 if the application has a bug
alert(request.status);
alert("A problem occurred with communicating between "+
"the XMLHttpRequest object and the server program.");
}
}//end outer if
} catch (err) {
alert("It does not appear that the server is "+
"available for this application. Please"+
" try again very soon. \\nError: "+err.message);

}
}

/* Initialize a request object that is already constructed */
function initReq(reqType,url,bool){
try{
/* Specify the function that will handle the HTTP response */
request.onreadystatechange=handleResponse;
request.open(reqType,url,bool);
request.send(null);
} catch (errv) {
alert(
"The application cannot contact the server at the moment. "+
"Please try again in a few seconds." );
}
}

/* Wrapper function for constructing a request object.
Parameters:
reqType: The HTTP request type, such as GET or POST.
url: The URL of the server program.
asynch: Whether to send the request asynchronously or not. */
function httpRequest(reqType,url,asynch){
//Mozilla-based browsers
if(window.XMLHttpRequest){
request = new XMLHttpRequest( );
} else if (window.ActiveXObject){
request=new ActiveXObject("Msxml2.XMLHTTP");
if (! request){
request=new ActiveXObject("Microsoft.XMLHTTP");
}
}
//the request could still be null if neither ActiveXObject
//initialization succeeded
if(request){
initReq(reqType,url,asynch);
} else {
alert("Your browser does not permit the use of all "+
"of this application's features!");
}
}

令人感兴趣的部分是handleResponse函数。该函数调用request对象的getAllResponseHeaders方法,该方法返回所有的可用的响应头信息,预格式为string。开发者更喜欢这些值作为JSON格式返回,而不是作为一个单一的字符串返回。

为取得一个头信息,也可以使用request.getResponseHeader方法。例如request.getResponseHeader("Content-Type")可以得到响应头的Content类型:

接下来代码将取得div元素,并在其中显示头信息:

if(request.status == 200){
/* All headers received as a single string */
var headers = request.getAllResponseHeaders( );
var div = document.getElementById("msgDisplay");
div.className="header";
div.innerHTML="

"+headers+"
";
}...

为能向信息显示提供CSS格式,代码设置了div的className属性,这个类已经预先定义了,代码如下:

div.header{ border: thin solid black; padding: 10%;
font-size: 0.9em; background-color: yellow}
span.message { font-size: 0.8em; }

以这样的方式,代码会动态地将一个div连向一个特定的CSS类,这个类是单独定义的。这种策略帮助DOM编程者描述区分。最后div的innerHTML属性被设置进返回头值里边。

http://blog.matrix.org.cn/Jekey/date/20060408 星期六 2006年04月08日

Ajax Hacks-hack8 处理Request Object 的错误

让Ajax能检测服务器的错误,并能像用户提供有用的信息。
Ajax技术的魅力在于允许JavaScript能在用户不干预的情况下与服务器连接。然而JavaScript开发者经常无法控制服务器组件(可能是一个web服务或其他软件)。尽管你的应用程序包括了你自己的服务器组件,也无法保证服务器永远运行正常或者用户遇到错误。因此,当程序出错时候,必须保证应用产业程序能恢复。

本hack跟踪错误并显示出错误信息,当Ajax程序失去服务器连接的时候。

问题, 问题...
Hack捕获下列异常事件,并为应用程序推荐解决的办法:

正在连接的web应用程序或服务器组件暂时不可用。
应用程序连接的服务器挂掉了,或者URL改变了。
要连接的服务器组件错误,在连接的过程中发作了。

当requst对象调用open方法时,代码使用了不同的主机地址而不是用户下载的web页面地址。当调用open方法时,request对象抛出一个异常。

你可以在其他地方使用本hack的异常处理方法。hack还使用了hack6种的股票计算程序代码。看一下html代码:

"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">




Tally your stocks


Your total Stock Holdings


"getStockPrice(this.stSymbol.value,this.numShares.value);return false">

Enter stock symbol:


Enter share amount:






When users load this file into their browsers, they see the screen shown in Figure 1-11.

Figure 1-11. Request a stock's price

我们感兴趣的代码是能捕获异常的部分,后台服务器关闭、错误、或者错误的URL。handleResponse函数是事件处理函数用来管理服务器响应,request.onreadystatechange=handleResponse。接下来的代码使用try/catch/finally 来捕获并处理无效数字这一问题。

function handleResponse( ){
var statusMsg="";
try{
if(request.readyState == 4){
if(request.status == 200){
/* Check if the return value is actually a number.
If so, multiple by the number
of shares and display the result */
var stockPrice = request.responseText;

try{
if(isNaN(stockPrice)) { throw new Error(
"The returned price is an invalid number.");}
if(isNaN(numberOfShares)) { throw new Error(
"The share amount is an invalid number.");}
var info = "Total stock value: $"+
calcTotal(stockPrice);
displayMsg(document.
getElementById("msgDisplay"),info,"black");
document.getElementById("stPrice").style.fontSize="0.
9em";
document.getElementById("stPrice").innerHTML ="price: "+
stockPrice;
} catch (err) {
displayMsg(document.getElementById("msgDisplay"),
"An error occurred: "+
err.message,"red");
}
} else {
//request.status is 503 if the application isn't available;
//500 if the application has a bug
alert(
"A problem occurred with communicating between the "
"XMLHttpRequest object and the server program. "+
"Please try again very soon");
}
}//end outer if
} catch (err) {
alert("It does not appear that the server "+
"is available for this application. Please "+
"try again very soon. \\nError: "+err.message);

}
}

下面看一下用来处理不同异常的代码。

try块将抛出内部的任何异常,而相应的catch将捕获这个异常,并解决异常。try catch是相对的。

当主机挂掉了会发生什么呢?尽管你请求的URL是正确的。这种情况下,试图访问request.status 属性的代码会抛出一个异常,应为request对象没有从服务器接收到响应,以及相应的状态属性。
因此,代码会弹出一个警告对话框来提示用户。
Figure 1-12 depicts what the alert window looks like after this type of error.

Figure 1-12. Uh-oh, server down

代码显示了用户的信息,以及更多异常错误的相关信息。你可以不管学些信息,不过这些对程序的修改和调试很有帮助。

代码里的错误变量是JavaScript错误对象。对象的信息属性就是一个错误信息,是由JavaScript引擎产生的string。

如果没有使用 TRy/catch/finally 机制,用户只能看到很不容易懂得由JavaScript引擎产生的错误信息。在关闭这个讨厌的错误提示框以后,用户就无法了解应用程序的更多状态信息了。

有时,服务器或主机运行正常,但是要连接的服务器组件有问题。这样的情况下,request.status 属性的值是503(服务不可用)。因为状态属性的值不是200,代码的这一部分将捕获这个异常:

} else {
//request.status is 503 if the application isn't available;
// 500 如果服务有错误
alert(
"A problem occurred with communicating between the "
"XMLHttpRequest object and the server program. "+
"Please try again very soon");
}

换句话说,用户可以在弹出窗口中看到应用程序状态信息。也可以显示服务器组件的错误。这样的情况下,响应状态码是500(内部服务错误)。此外404状态响应码表示服务器的静态或动态组件无法找到请求的URL,就是常见的令人讨厌的400错误(页面不存在或被删除)。

try/catch/finally语句只适用于1.4或更高的版本中。finally语句是可选的。

令人沮丧的错误的URL
如果用户请求的URL是错误的或已经改变了,会发生什么呢? 调用request.open方法会抛出异常,因此必须放在try/catch/finally语句里边处理。
在犯法initReq( )里边,有相应的代码:

function httpRequest(reqType,url,asynch){
//Mozilla-based browsers
if(window.XMLHttpRequest){
request = new XMLHttpRequest( );
} else if (window.ActiveXObject){
request=new ActiveXObject("Msxml2.XMLHTTP");
if (! request){
request=new ActiveXObject("Microsoft.XMLHTTP");
}
}
//the request could still be null if neither ActiveXObject
//initialization succeeded
if(request){
initReq(reqType,url,asynch);
} else {
alert("Your browser does not permit the use of all "+
"of this application's features!");
}
}
/* Initialize a request object that is already constructed */
function initReq(reqType,url,bool){
try{
/* Specify the function that will handle the HTTP response */
request.onreadystatechange=handleResponse;
request.open(reqType,url,bool);
request.send(null);
} catch (err) {

alert(
"The application cannot contact the server at the moment."+
" Please try again in a few seconds.");
}
}

另一种情况是请求的URL不是所想的。例如,用户想从http://www.myorg.com/app下载页面,但是打开的URL却是http://www.myorg.com,这样的错误也可以使用try/catch/finally 语句捕获。

本hack讲述了Ajax常见的异常以及捕获他们的办法。

http://blog.matrix.org.cn/Jekey/date/20060407 星期五 2006年04月07日

Ajax Hacks-hack7接收JSON格式的数据

怎样才能使用Ajax从服务器接收js对象数据呢?你可以使用一种叫javascript 对象符号的格式接收数据。本hack讲述用户输入信息,从服务器得到JSON格式的响应数据。
JSON很普通而直观,这也许是许多开发者喜欢使用的原因吧。一个例子就是,服务器程序从服务器得到信息,然后以JSON格式返回给web页面。JSON格式的数据描述如下:
左大括号“{”
一个或多个属性名,以冒号隔开的对应的值,以逗号隔开的属性/值对。
右大括号 “}”
每个属性的值可以是:
简单的字符串,例如 "hello"
数组,例如 [1,2,3,4]
数字
true, false, 或 null
其他对象,组合的,或者对象中还有对象。
详细信息请访问:http://www.json.org
在JavaScript中,对象的格式是严格的。作为一个例子,在hack2中的请求信息改写为JSON格式为:
{
firstname:"Bruce",
lastname:"Perry",
gender:"M",
country:"USA"
}

Magic JSON
在这一部分里,我们还使用hack2中的例子,只是处理的数据是JSON格式的数据。页面的html代码如下:

"http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">




Receive JSON response


A Few Facts About Yourself...



First name:


Last name:


Gender:


Country of origin:







脚本标记引入的js文件为hack5.js。JS将用户输入的值发送到服务器;这些都已经在hack2等节介绍过了,这里就不详细解释了。

当js处理返回值的时候,需要注意XSS攻击。这对于那些使用eval或其他相关函数来说是一个潜在的威胁。

作为一个相应的措施,在函数eval使用responseText之前,客户端代码可以过滤并检测返回值(即,通过检查XMLHttpRequest responseText属性)

下面是hack的代码,我们将着重关注处理返回值部分的代码:

var request;
var queryString; //保存POSTed 数据

function sendData( ){
setQueryString( );
url="http://www.parkerriver.com/s/json";
httpRequest("POST",url,true);
}

//event handler for XMLHttpRequest
function handleJson( ){
if(request.readyState == 4){
if(request.status == 200){
var resp = request.responseText;
var func = new Function("return "+resp);
var objt = func( );
var div = document.getElementById("json");
stylizeDiv(resp,div);
div = document.getElementById("props");
div.innerHTML="

In object form...

"+
"
Properties
firstname= "+
objt.firstname +"
lastname="+
objt.lastname+ "
gender="+
objt.gender+ "
country="+
objt.country;
} else {
alert("A problem occurred with communicating between "+
"the XMLHttpRequest object and the server program.");
}
}//end outer if
}

/* Initialize a request object that is already constructed */
function initReq(reqType,url,bool){
/* Specify the function that will handle the HTTP response */
request.onreadystatechange=handleJson;
request.open(reqType,url,bool);
request.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded; charset=UTF-8");
request.send(queryString);
}

/* Wrapper function for constructing a request object.
Parameters:
reqType: The HTTP request type, such as GET or POST.
url: The URL of the server program.
asynch: Whether to send the request asynchronously or not. */

function httpRequest(reqType,url,asynch){
//Snipped... See Hack #1 or #2
}

function setQueryString( ){
queryString="";
var frm = document.forms[0];
var numberElements = frm.elements.length;
for(var i = 0; i < numberElements; i++){
if(i < numberElements-1){
queryString += frm.elements[i].name+"="+
encodeURIComponent(frm.elements[i].value)+"&";
} else {
queryString += frm.elements[i].name+"="+
encodeURIComponent(frm.elements[i].value);
}
}
}

function stylizeDiv(bdyTxt,div){
//reset DIV content
div.innerHTML=" ";
div.style.fontSize="1.2em";
div.style.backgroundColor="yellow";
div.appendChild(document.createTextNode(bdyTxt));
}

如本章前面的hack介绍的,initReq( )函数初始化request对象并向服务器发送HTTP请求。

事件处理函数将调用handleJson。相应数据的格式是JSON格式的字符串,而不是其他的XML或其他格式的数据。JS将这些返回文本看作string对象。因此,代码启动open步骤,在服务器返回值被转化成js对象之前。(btw,在本节里,服务器在发送响应数据之前会将请求参数重新格式化成JSON格式。)

这里没有包括特定的错误处理代码,而将其放在hack8中介绍。

在函数handleJson内的代码(高亮显示的部分),变量resp保存HTTP响应文本,js将其看作string。令人感兴趣的是函数的构造函数:
var func = new Function("return "+resp);

上面的代码将创建一个新的函数对象,以变量func命名。JavaScript编程者应当明白,大多数函数需要在代码中预先定义和声明,或者作为函数字