晖's profileApple SoulPhotosBlogListsMore Tools Help

Blog


    April 30

    得诗一首,与众人享

    《猪瘟赞歌》
    啊,猪瘟。
    你是投机者的财富之神!!
    你悄悄的来到世间,
    从猪到人。
    你默默的履行着使命,
    惩罚罪恶的人群。
    哈哈,次贷的风暴刚刚使其自食恶果,
    还在苟延残喘之际,
    你又把灾难降临!
    去死吧!!!
    会有人接任世界的霸主!
    去见上帝吧,
    去忏悔罪恶而又贪婪的灵魂。
    上帝说过,
    不会再给我们一个地球了,
    生活在这蓝色星球上的生命啊,
    我们将拿什么去留给我们的子孙?! 

    此人写诗无数,唯此首与我有感动也。

    敬请期待大型图片blog--腹肌的存在。
    April 13

    今天是小毛虫的开心日

    今天看了顽^#$%#张的@¥@#,很有感触么,班长卡哇伊表象的包裹下,是一颗厚重和伤感心。灵 树上住着一只毛毛虫,原本的生活是很轻松,今天是小毛虫的开学日,它赶快回家准备钉书,吃完了早餐还要穿制服,所以伤脑筋啊还要穿鞋子,因为他的脚有八十八只,每只脚要穿上两只袜子~~! ? 我一直在寻找上面这首歌。 敬请期待,大型记录日志--腹肌的存在。
    December 02

    伟大的11月,伟大的xingxing

    Great经常被翻译成伟大的,其实经常它的意思就是真不错。为了我这篇伟大的博文能够誉满五洲,外国朋友能够准确的理解,就用伟大的吧。
     
    这个月过的好像过山车,月末最后一天终于落在软床上了,经历了这样的大起大落之后,“无事”总能给我注入兴奋。一个月完成了两片论文,四次作业,只逃了三节半课,真可谓硕果累累,虽然还一个很烦人的需求没有完成,那也是12月的事情了。今天天气真是不错,还在家门口找到一个篮球场,真可谓喜贯满盈,可喜可贺。可这膝盖还是不舒服,不太完美。最近可想打台球了,好不容易周末不用上课,可是就是没人陪我玩,我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷我郁闷。这一杆子又支到12月30号了。唉~,不太完美。
     
    12月还有一件重要的事情,找保姆,我找啊找啊找保姆,找到一个好保姆。各位仁兄仁姐如果知道有春节不回家的保姆一定帮我想着啊,我真急啊!我先谢了!!
     
    但是我的心情无比的好,完美!
     
     
    October 31

    以铜为镜正其冠,以人为镜正其行

    终于千挑万选的买了ipod nano,这是一个轮回啊,最后的选择真的成了最后的选择。
    IMAGE_00063
     
    原来家里养的一只狗,每次洗完澡都特别兴奋,满屋子乱窜,一直不解。
     
    原来家里养的一直波斯猫,也是,每次洗完澡和上完厕所都特别兴奋,满屋子上下乱窜,结果有一身脏,一直不解。
     
    昨天下班放下自行车就直奔理发店,实在受不了后面的头发了,决定理发,理完之后超级满意,一路颠儿着就回家了,就像小女孩那样跑跳着回家,回家之后赶紧给小米看,小米开始没看清楚,看清后给了三个字的评价--二傻子(似的)。她这么一说我到乐了,我说那也是你们家的二傻子,然后两个人一顿爆笑,o(∩_∩)o
     
    现在特别理解我家的阿猫阿狗了,身上俐落一些,还是很有利于好心情的,严格的说是兴奋,不过细想想也是因为好久没有俐落了,一天到晚不修边幅,到最后自己都忍不了了,这感觉就像嗑瓜子,磕出一大把瓜子仁,一起吃,咀嚼着,从冯巩嘴里说出来的:爽!
    October 22

    淡淡的

    有意思的事情: 周六日两天经历和看的事情汇总起来形成了昨晚的梦。
     
    周六参加校庆+周日看的加勒比3+今早要做的事情,这叫一个好玩,一觉起来腰酸背痛累坏了。
    先是戴泉和WH在北航毛主席像上面吵嘴,然后就是主角--小学有一个同学叫做赵珣,初中和我不是一个班的,但是当时还是很有交情的。昨晚梦到他变成黑社会的人了,就是混的那种,但是有些身份,所以每天晚上的必修课是被人追杀(砍),我开着车带着他被很多拿着棒球棒的人追着打,然后就开始在大街上跑,使劲的跑,跑到了一个饭店的厨房,接着跑。最后终于跑醒了,腰那个酸啊真是累。不过挺有意思。
     
    郁闷的事情:今天早上开到北航附中门口去了,本来人家用标有禁止通行的铁牌子拦住了路,我居然还是挤过去了,着急去体检然后上班,没顾那么多,抽完血出来,正赶上同学们上学,费劲巴拉的倒出来了。到了单位回想一下,总觉得自己做的太不好了,心情很郁闷了,就。失望
    October 17

    爱情是可以用金钱衡量的

    一个年轻漂亮的美国女孩在美国一家大型网上论坛金融版上发表了这样一个问题帖:我怎样才能嫁给有钱人?  “我下面要说的都是心里话。本人25岁,非常漂亮,是那种让人惊艳的漂亮,谈吐文雅,有品位,想嫁给年薪 50万美元的人。你也许会说我贪心,但在纽约年薪100万才算是中产,本人的要求其实不高。

      这个版上有没有年薪超过 50万的人?你们都结婚了吗?我想请教各位一个问题——怎样才能嫁给你们这样的有钱人?我约会过的人中,最有钱的年薪25万,这似乎是我的上限。要住进纽约中心公园以西的高尚住宅区,年薪25万远远不够。我是来诚心诚意请教的。有几个具体的问题:

    一、有钱的单身汉一般都在哪里消磨时光? (请列出酒吧、饭店、健身房的名字和详细地址。)

    二、我应该把目标定在哪个年龄段?

    三、为什么有些富豪的妻子看起来相貌平平?我见过有些女孩,长相如同白开水,毫无吸引人的地方,但她们却能嫁入豪门。而单身酒吧里那些迷死人的美女却运气不佳。

    四、你们怎么决定谁能做妻子,谁只能做女朋友? (我现在的目标是结婚。)”——波尔斯女士

      下面是一个华尔街金融家的回帖:

      “亲爱的波尔斯:我怀着极大的兴趣看完了贵帖,相信不少女士也有跟你类似的疑问。让我以一个投资专家的身份,对你的处境做一分析。我年薪超过50万,符合你的择偶标准,所以请相信我并不是在浪费大家的时间。

      从生意人的角度来看,跟你结婚是个糟糕的经营决策,道理再明白不过,请听我解释。抛开细枝末节,你所说的其实是一笔简单的“财”“貌”交易:甲方提供述人的外表,乙方出钱,公平交易,童叟无欺。但是,这里有个致命的问题,你的美貌会消逝,但我的钱却不会无缘无故减少。事实上,我的收入很可能会逐年涕增.而你不可能一年比一年漂亮。


      因此,从经济学的角度讲,我是增值资产,你是贬值资产,不但贬值,而且是加速贬值!你现在25,在未来的五年里,你仍可以保持窈窕的身段,俏丽的容貌,虽然每年略有退步。但美貌消逝的速度会越来越快,如果它是你仅有的资产,十年以后你的价值甚忧。

      用华尔街术语说,每笔交易都有一个仓位,跟你交往属于“交易仓位”(tradinglposition),一旦价值下跌就要立即抛售,而不宜长期持有——也就是你想要的婚姻。听起来很残忍,但对一件会加速贬值的物资,明智的选择是租赁,而不是购入。年薪能超过50万的人,当然都不是傻瓜,因此我们只会跟你交往,但不会跟你结婚。所以我劝你不要苦苦寻找嫁给有钱人的秘方。顺便说一句,你倒可以想办法把自己变成年薪50万的人,这比碰到一个有钱的傻瓜的胜算要大。

      希望我的回帖能对你有帮助。如果你对“租赁”感兴趣,请跟我联系。”——罗波.坎贝尔(J·P·摩根银行多种产业投资顾问)

    来源: 环球时报

    显然,反过来看,帅哥贬值速度慢些,HOHO~

     
    November 09

    BOBO

          还是不要含蓄的好,人与人么,应该大大方方无所畏忌的交流,好似高山瀑布,痛快。
          每天都在经历一些事情,每件事情又以其独特方式被分解,然后再积累,汇聚到魔方的六面,不知道调和成什么颜色。
          粘稠而又有力的几股液体缠绕着,毫无规律的扭动着,看上去,你只想把他们分解开,要不然太闹心。
          忽如一夜春风来,明月何时照我还。如此反复于两种心情,一点也不刺激,反而好像没了弹力的猴皮筋,松松垮垮。
          真想拥有一种气度,让宇宙之风可以穿膛而过,呼~~那是怎样一种胸怀,想想都那么令人兴奋。
          时间如流水,从指间流过,受它滋养,被它削弱,到头来只剩一架白骨,思想却飘散在空气中,供你我呼吸。
     
          好了,真是榨干了,脑子里如果不进点水还真是麻烦了,脑壳里面就空了。生活充满希望也应该多看看脚下。是性格与这社会相悖还是社会铸就了充满叛逆的性格。都是借口,都是TMD接口。就应该开开心心的活,高高兴兴地拥抱。世上本无事,庸人自扰之。
     
          苦是无人之苦。
    September 19

    生活好似荆棘路-痛并快乐着

          一条题目足以阐明一切,还要这内容做甚?将简单的问题复杂化,将复杂的问题简单化就是我们每天无意有意的忙碌。
          曾经激动地憧憬着宇宙之风穿怀而过胸襟,现在依然。
          痛然后快乐着,还是痛并快乐着是穿越生活的谷底才会考虑的问题,无数次心灵的撞击变化出无数种色彩的心情。
          我们一样在无边无垠的荆棘地中行走,说笑着,任凭粗细的青刺以不同的方式带走我们的血肉,有些朋友厌倦了,就顺着石阶上去了,领了一根平衡棍,走在万丈高的钢丝桥上,恐惧与刺激带走了他们心灵的血肉,我们微笑的仰望他们,与他们同速向前,也许前方的某一点我们会与他们在这里或那里拥抱,继续享受荆棘。
    August 07

    我,Ajax和Struts

    (这是一篇关于我将一点点Ajax技术的皮毛应用到Struts框架中的文章)
         光学不练那是假把式,而且是浮躁的假把式,看了很多关于Ajax的资料和书籍,真正在项目中用到的只有一些因为学习Ajax而学到的JavaScript技术,我想这也不能称为Ajax的应用吧。但是,不经意间,机会来了,项目有了新的需求,在我的学识能力范围之内,Ajax是最好也是唯一的选择。
         整个项目是使用WSAD5.0开发的基于Struts框架的Web应用。关于机票在线分摊的应用。一共涉及到三个用户录入Web页面:主页面--录入基本票面的信息;航程信息页面--用来录入从哪里飞到哪里,又去了哪里,然后又回到哪里的信息(航程中最多可以包含24个航段,比如北京-上海就是一个航段,用户录完一个航段回车,页面刷新显示已录航段,用户只需在最后一个航段录入整个航程的信息即表示航程录入结束);航段信息页面--航程中某段的特殊信息。三个录入的界面每个界面一个jsp,一个form,用户点击分摊按钮,ManageBean将三个form的内容分析整合,发送主机处理。然后是一个结果页面:分摊的结果。现在用户觉得票面信息、航程信息和航段信息分开录入甚是麻烦,要求所有信息都放到主页面录入。
     
         起初看到这个要求,我想,应该也不难做,无非是化零为整么。后来真的估算时间的时候我才发现,不是那么简单,首先这个三个jsp页面分别对应三个formBean,在Struts的configure文件中也是三个不同的分发策略。交验、数据的处理都要放在一个ManageBean中,所有的跳转都放在一个ActionBean中。做整合基本上和把程序重写一变没有区别。而且这种整合还会留下潜在的隐患,包括技术和业务上的。
     
         再重新分析了用户的需求后,简化了一些内容,航段信息可以不用录入,其实用户就是想尽可能的简单(所有的用户都是这个想法--简单、高效,这也是计算机也发展得原动力,我已经被大师们智慧的结晶闪晕了,虽然我一直渴望成为那样的大师)。好了,现在我产生了一个简单的修改策略:将票面信息和航程信息的两个form放在主页面上,所有的Bean都无需修改,用户点击分摊只需按照原来的逻辑整合这两个form即可。于是我开始修改了。
     
          修改过程中遇到一个小问题,这个问题不仅耽误了我一天的时间还差点让我放弃了既定的计划而回到开始的想法,那就是页面中的form不能嵌套。由于嵌套,在测试的时候Struts报了一些奇怪的错误。
     
          Ajax正是登场,前面的铺垫确实有些冗长了。如何同时提交两个form到两个action?我首先使用的方法:连续两个document.TktFORMBean.submit();document.SectorFORMBean.submit();这个方法的问题是由于第一个submit提交后控制权就交给了Struts框架,返回来的结果导致整个页面刷新,因此第二个的submit就不会执行了,那么分摊的时候就缺少一个form的信息。正是“刷新”二字让我想到了Ajax:票面信息form的最后一个内容录入完毕,该控件的onblur事件触发,异步提交form,票面信息的form内容保存在session中了,无须刷新页面。而用户可以在不知晓这一切的情况下继续录入航程信息,Struts中需要修改的只是struts-config.xml的一些内容。
     
          初始化request对象的代码我就用的翻译资料中的那些成熟的代码。现在的问题是,form的提交操作如何通过request用JavaScript来模拟?提交request是要给出明确的请求地址的,而怎样的格式才是Struts框架能够识别的呢?查了一些资料我才知道,原来点击页面上按钮向服务器发送请求或者提交form的时候,服务器接收到的就是一个你我都熟悉的URL,只不过这个URL是浏览器替我们生成的。我只要自己生成票面信息form的提交URL,并将这个URL作为request对象open函数的参数,那么request对象就可以替我完成这个form的提交请求,Struts收到这个请求,调用相应的Action,完成对form内容的保存,至于返回内容,我并不需要。(当然它返回的是整个新的页面的HTML源代码,如果有必要也可以从中提取有价值的信息)
     
          这个URL的格式(以我的实际应用为例):var url = "../jsp/xxxxx.do?"+getFormAsString(document.TktFORMBean);
          getFormAsString代码(这段代码使我从网上找的,直接用了,不是我的原创):
         
         function getFormAsString(formName){
               returnString ="";
               formElements=formName.elements;
               for ( var i=formElements.length-1; i>=0; --i ){
                   //使用escape可以将录入的内容转换成为URL的合法格式
                   returnString=returnString+"&"+escape(formElements[i].name)+"="+escape(formElements[i].value);
               }
               //alert(returnString);你可以看到它返回的内容
              return returnString;
          }
          name1=value1&name2=value2&name3=value3....呵呵,没什么神秘的。
     
          至此用户需求的技术难点已经没有了。
     
          我的文字驾驭能力实在很差,但希望这篇文章多少能有些价值。编程这东西就靠键盘,离了它,说啥也没用。
    June 13

    翻译 一些 Ajax 资料(25)

    使用服务器端响应改变无序列表(Unordered List)
     
    根据服务器传来的内容修改静态的ul(unordered list)
     
          ul标签是web页面上最为普通的标签之一,浏览器将其显示为伴随着标注的子弹。这一节的例子是让用户通过增加项来修改ul。项的内容来自服务器端。这一节的例子非常像前一节的例子。主要的区别就是处理ul而上一节是checkbox,ul被设计用来显示信息而不是提供选项。
     
          (说实话这一节的例子和上一节一样的,所以我想不翻译了,有些烦躁和懒惰情绪了,真是很抱歉,最近开始忙婚礼的事宜,大脑有些不够用了,呵呵--lazy translator)
     
    给出HTML代码吧,剩下的就看你的想象力了哦:
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="http_request.js"></script>
        <script type="text/javascript" src="example.js"></script>
        <title>View our sports offerings</title>
    </head>
    <body>
    <h3>Expand Your Sports Categories</h3>
    <h4>Expand Sport Choices</h4>
    <form action="javascript:void%200">
        <div id="exp">
        Expand the choices for:
        <select name="_expand" id="expand">
            <option value="individual">Individual</option>
            <option value="team">Team</option>
        </select>
        </div>
    </form>
    <h4>Restore Original Sport Choices</h4>
    <form action="javascript:void%200">
        <div id="rest">
        Restore the choices for:
        <select name="_restore" id="restore">
            <option value="individual">Individual</option>
            <option value="team">Team</option>
        </select>
        </div>
    </form>
    <h4>Team sport</h4>
        <ul id="team_u">
            <li>Baseball</li>
            <li>Soccer</li>
            <li>Football</li>
            <li>Basketball</li>
            <li>Lacrosse</li>
            <li>Hockey</li>
            <li>Tennis </li>
        </ul>
    <h4>Individual sport</h4>
        <ul id="individual_u">
            <li>Cycling</li>
            <li>Running</li>
            <li>Swimming</li>
            <li>Nordic Skiing</li>
            <li>Inline Skating</li>
            <li>Triathlon</li>
            <li>Track</li>
        </ul>
    </body>
    </html>
    June 08

    翻译 一些 Ajax 资料(24)

    根据服务器的返回组装已有的checkbox组
     
    动态向已有的checkbox组中添加控件
     
          这一节我将介绍另外一种类型的适应的web表单,这种表单中的一组控件能够根据使用者的喜好改变。在前面的例子中,代码在checkbox被点击的时候立刻将其值发送到服务器程序。这节将允许用户在已有的控件中做选择前,向同一组checkbox后面增加新的选项。页面中有一个select列表,其中包含队伍或者单独项目的选择。还有两组checkbox分别用来显示队伍和单独的体育项目。选择上面的select列表将从服务器取得新的内容来扩展已有的checkbox。选择下面的select列表将恢复原有的checkbox组。
     
    这些如何发生的?
     
          我们假设新的checkbox内容必须来自服务器,因为它经常根据组织的数据库改变。否则,一个像这样的应用可能使用JavaScript数组来存放新的内容而从不连接服务器。当用户从两个select中的一个做出了选择,这个动作将队伍或者单独项目的选择发送到服务器程序。代码使用请求对象和服务器联系,Ajax的方式。
          服务器返回新的checkbox的数组。在select列表作选择将触发一个JavaScript代码的onclick事件处理器,后面会有详细的代码。
     
    (这里作者没有给出HTML的代码,他说和咱们22节中的HTML代码一样,可是显然只有checkbox部分是一样的,22节中的HTML代码没有select列表,处于某种原因我不能贴出图片,请见谅,我自己根据理解完成了这个HTML页面的代码:)
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="exapmle.js"></script>
        <link rel="stylesheet" type="text/css" href="exapmle.css" />
        <title>submit checkbox values</title>
    </head>
    <body>
    <h3>Expand Sports Choices</h3>
    <form id="selectlist" action="javascript:void%200" method="get">
     Expand the choice for :<select id="expand" size="1">
                           <option value="inv">Individual</option>
                           <option value="team">Team</option>
                           </select>
     <br />
     <h3>Restore Original Sports Choices</h3>
     Restore the chioce for :<select id="restore" size="1">
                           <option value="inv">Individual</option>
                           <option value="team">Team</option>
                           </select>
    </form>
    <h4>Team sport</h4>
    <form id="team" action="javascript:void%200" method="get">
    <div id="team_d" class="team">
    <input type="checkbox" name="team_sports" id=
    "baseball" value="baseball" /> Baseball <br />
    <input type="checkbox" name="team_sports" id=
    "soccer" value="soccer"  /> Soccer  <br />
    <input type="checkbox" name="team_sports" id=
    "football" value="football"  /> Football  <br />
    <input type="checkbox" name="team_sports" id=
    "basketball" value="basketball"  /> Basketball  <br />
    <input type="checkbox" name="team_sports" id=
    "lacrosse" value="lacrosse" />Lacrosse  <br />
    <input type="checkbox" name="team_sports" id=
    "hockey" value="hockey" /> Hockey  <br />
    <input type="checkbox" name="team_sports" id=
    "tennis" value="tennis" /> Tennis  <br />
    </div>
    </form>
    <div id="team_poll" class="poll">
        <span id="t_title" class="p_title"></span>
        <span id="t_results" class="p_results"></span></div>
    <h4>Individual sport</h4>
    <form  id="ind" action="javascript:void%200" method="get">
    <div id="ind_d" class="ind">
    <input type="checkbox" name="individual_sports" id=
    "cycling" value="cycling" /> Cycling  <br />
    <input type="checkbox" name="individual_sports" id=
    "running" value="running"  /> Running  <br />
    <input type="checkbox" name="individual_sports" id=
    "swimming" value="swimming"  /> Swimming <br />
    <input type="checkbox" name="individual_sports" id=
    "nordic_skiing" value="nordic_skiing"  />Nordic Skiing  <br />
    <input type="checkbox" name="individual_sports" id=
    "inline_skating" value="inline_skating"  />Inline Skating <br />
    <input type="checkbox" name="individual_sports" id=
    "triathlon" value="triathlon"  />Triathlon <br />
    <input type="checkbox" name="individual_sports" id=
    "track" value="track"  />Track <br />
    </div>
    </form>
    <div id="individual_poll" class="poll">
        <span id="i_title" class="p_title"></span>
        <span id="i_results" class="p_results"></span></div>
    </body>
    </html>
     
    然后是JavaScript代码:
     
    var sportTyp="";
    var checksArray=null;
    var request=null;
     
    window.onload=function()
    {
        var sel=document.getElementById("expand");
        if(sel !=null)
        {
            sel.onclick=function(){getMoreChoices(this);};
        }
     
        var selr = document.getElementById("restore");
        if(selr !=null)
        {
            selr.onclick=function(){restore(this);};
        }
       
        //将所有已有的checkbox元素放入两个数组中,以便恢复原始的checkbox列表
        checkArray=new Object();
        checkArray.team = new Array();
        checkArray.indifidual = new Array();
        var ckArr = document.getElementsByTagName("input");
        populateArray(ckArr,"team");
        populateArray(ckArr,"individual");
    }
     
    function populateArray(arr,typ)
    {
         var inc=0;
         for(var i=0;i<arr.length;i++)
         {
             if(arr[i].type=="checkbox")
             {
                  if(arr[i].name.indexOf(typ) !=-1)
                  {
                        checksArray[typ][inc]=arr[i];
                        inc++;
                  }
             }
         }
    }
     
    function getCheckboxesLength(_sportTyp)
    {
         var div = document.getElementById(_sportType+"_d");
         var len=0;
         for(var i=0;i<div.childNodes.length;i++)
         {
               if(div.childNodes[i].nodeName=="INPUT" ||div.childNodes[i].ndoeName=="input")
               {
                   len++;
               }
         }
         return len;
    }
     
    //用请求对象取得新的checkbox的数组。
    function getMoreChoices(obj)
    {
          if(obj==null){return;}
          var url="";
          var optsArray=obj.options;
          var val="";
          for(var i=0;i<optsArray.length;i++)
          {
              if(optsArrya[i].selected)
              {
                    val=optsArrya[i].value;break;
              }
          }
          sportTyp=val;
          //检查checkbox是否已经扩展了
          if(checkArray[sportTyp].length<getCheckboxes.Length(sportTyp))
          {
              return; 
          }
                httpRequest("GET",url,true);
    }
     
    //将新的checkbox添加到原来的checkbox列表中。如果列表没有扩展过,那么只增加新的checkbox。如果已经扩展了,那么就返回不会和服务器发生联系
    function addToChecks(obj)
    {
         var div = document.getElementById(sportTyp+"_d");
         var el =null;
         for(var h=0;h<obj.length;h++)
         {
            el=document.createElement("input");
            el.type="checkbox";
            el.name=sporrtTyp+"_sports"
            el.value=obj[h];
            div.appendChild(el);
            div.appendChild(document.createTextNode(obj[h]));
            div.appendChild(document.createElement("br"));
         }
    }
     
    function restore(_sel)
    {
        var val ;
        var opts=_sel.options;
        for(var i =0;i<opts.length;i++)
        {
            if(opts[i].selected){ var=opts[i].value; break;}
        }
        if(checksArray[sportTyp].length<getCheckboxesLength(sportType))
        {
           var _div = document.getElementById(val+"_d");
           if(_div !=null)
           {
               _div.innerHtml="";
               var tmpArr = checksArray[val];
               for(var j =0;j<tmpArr.length;j++)
               {
                  _div.appendChild(tmpArr[j]);
                  _div.appendChild(document.createTextNode(tempArr[j].value));
                  _div.appendChild(document.createElement("br"));
               }
           }
        }
    }
     
    function handleResponse()
    {
         try
         {
               if(request.readyState==4)
               {
                   if(request.status==200)
                   {
                        var resp = request.responseText; 
                        if(resp !=null)
                        {
                           addToChecks(eval(resp));
                        }
                   }else
                   {
     //以下省略
     
     
    代码的大部分都是在获取和恢复checkbox的原始状态,代码的注释将会给代码一些清晰的解释。代码中还包括了防止相同的checbox被多次添加的情况。
          代码中检查列表是否已经被扩展了,通过比较现在的checkbox和原有checkbox的数量。如果现在的数量多于原有的,就说明列表是扩展过的。如果用户试图扩展这个列表两次,第二次将被忽略。
     
    再次阅读原代码,如果有什么不明白的地方请留言。
    June 07

    翻译 一些 Ajax 资料(23)

    使用服务器数据动态生成一个新的checkbox组
     
    从用户与应用的交互中生成新的checkbox内容
     
          大多数web表单是静态的,也就是说文本标签和录入控件(比如textarea,checkbox和单选按钮)都是在HTML中硬编码的。然而,如果基于用户点击的接口控件具有了动态生成元素的能力,大多数应用都能从中获益。表单的内容,如果需要的话,可以从服务器生成,比如各种类型的测试的答案和投票。
     
          前面的例子中我介绍了如何向select列表控件中动态生成内容,那么为什么checkbox就不行呢?
     
          这一节的例子是这样的:让用户在选择"运动队"或者"运动项目"的单选按钮中选择一个,然后当用户点击了任何一个按钮,应用从服务器组件获得运动分类并创建一组新的checkbox。
     
    下面是HTML代码:
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="example.js"></script>
        <title>Dynamic checkboxes</title>
    </head>
    <body>
    <h3>Voting on Favorite Sports</h3>
    <h4>Pick a sports category</h4>
    <form action="javascript:void%200">
        <table border="0">
            <tr><td>
            Team Sports:
            <input type="radio" name="_sports" value="team" />
            </td></tr>
            <tr><td>  Individual Sports:
            <input type="radio" name="_sports" value="individual" />
            </td></tr>
        </table>
        <hr />
        <div id="checks"></div>
    </form>
    </body>
    </html>
     
    当用户点击了单选按钮,页面立刻显示两组新的checkbox中的一组,体育项目或运动队。实际组成这个checkbox列表内容的是从服务器返回的数组或是字符串。这些内容显然也可以硬编码到JavaScript中,以防止网络问题,但是这一节中讨论的方法应用在checkbox控件中的值经常改变或者必须从服务器端的持久层中获取数据的情况中将会非常有用。
     
    好的,代码在哪里?
     
    不要急,就来了,不过事先要说明一下:我略去了那些创建和初始化请求对象的代码,你可以在前面的例子中找到,还有你首先应该注意给单选按钮的onclick事件处理器分配的那个方法。用户通过点击单选按钮来触发这些事件。
     
    var sportType="";
    var request=null;
     
    window.onload=function()
    {
          var rads=document.getElementByTagName("input);
          if(rads!=null)
          {
                 for(var i=0;i<rads.length;i++)
                 {
                       if(rads[i].type=="radio"){rads[i].onclick=function(){getSports(this);};}
                 }
          }
    }
     
    function getSports(obj)
    {
          if(obj==null){return;}
          var url="";
          var val="";
          if(obj.checked)
          {
                varl  = obj.value;
                sportType=val;
                url="http://www.parkerriver.com/s/fav_sports"+
                      "?sportType="+encodeURIComponent(val)+"&col=y";
                httpRequest("GET",url,true);
          }
    }
     
    function handleResponse()
    {
          try
          {
                if(request.readyState==4)
                {
                     if(reqeust.status==200)
                     {
                           var resp = request.responseText;
                           if(resp!=null)
                           {
                                 var objt = eval(resp);
                                 createChecks(objt);
                           }
                     }else
                     {
                           alert("XMLHttpRequest与服务器通信问题");
                     }
                }
          }catch(err)
          {
                alert(err);
          }
    }
     
    function createChecks(obj)
    {
          var _div = document.getElementById("checks");
          var el;
          while(_div.hasChildNodes())
          {
               for(var i =0;i<_div.childNodes.length;i++)
               {
                     _div.removeChild(_div.firstChild);
               }
          }
          for(var i=0;i<obj.length;i++)
          {
                el= document.createElement("input");
                el.setAttribute("type",checkbox);
                el.setAttribute("name",sportType);
                el.setAttribute("value",boj[i]);
                _div.appendChild(el);
                _div.appendChild(document.createTextNode(obj[i]));
                _div.appendChild(document.createElement("br");
          }
    }
     
    生成checkbox的第一阶段是发送请求对象,让它取回每个checkbox需要的值。当用户点击某一个单选按钮的时候,代码调用getSports()。这个方法根据单选按钮的选择生成一个URL,然后向服务器组件发送一个请求对象,要求相应运动的列表。
     
    数组返回值
     
    从服务器响应返回的是一个字符串被格式化为JavaScript的数组。响应的格式看起来是这样子的:
    ["football","soccer","tennis"]
     
    你通过请求对象的responseText属性获得响应,然后使用eval()方法将响应转换为一个JavaScript数组。唉,你已经很熟悉了,我真是有点多嘴。
     
          一旦代码拥有了从服务器返回的这个数组,它就将这个数组传递给createChecks()。这个方法使用DOM API创建checkbox。它利用数组中的每一个值创建一个checkbox:
     
    function createChecks(obj)
    {
          var _div = document.getElementById("checks");
          var el;
          while(_div.hasChildNodes())
          {
                for(var i=0;i<_div.childNodes.length;i++)
                {
                      _div.removeChild(_div.firstChild);
                }
          }
          for(var i=0;i<obj.length;i++)
          {
                el=document.createElement("input");
                el.setAttribute("type","checkbox");
                el.setAttribute("name",sportType);
                el.setAttribute("value",obj[i]);
                _div.appendChild(el);
                _div.appendChild(document.createTextNode(obj[i]));
                _div.appendChild(document.createElement("br");
          }
    }
     
    这个方法获得用来存放checkbox的div元素。然后将已经存在于div中的checkbox全部除去,因为,如果不这样做,用户可能不停的点击单选按钮并生成重复的checkbox。最后,代码为每一种运动建立一个新的input元素,看起来是这样的:
     
    <input type="checkbox" name="tema_sports" value="baseball" />baseball< /br>
     
    当这个方法执行的时候,checkbox就会出现在页面上,无须刷新页面,变魔术一般(当然,你不觉得是这魔术,因为你已经知道怎么回事了!!--HAHA translator)
     
    现在你可以发挥你的想象力,结合前面的学习,将select元素和checkbox元素结合起来,就看你有什么有趣的想法了,加油!!!
    June 06

    翻译 一些 Ajax 资料(22)

    无需刷新将CheckBox的值提交到服务器。
     
    当用户点击checkbox的时候生成服务器程序的立即响应
     
          checkbox就是那些有一个小的方框或者按钮,允许用户在多个选择项中作选择。通常的使用习惯是用户在表单的一个或者多个checkbox上做标记以便稍后提交。但是如果你只想让你的应用只提交checkbox的值而不是整个表单,并且希望提交的动作在用户点击checkbox时发生而不是稍候某个时间怎么办?
     
          这一节将介绍一个投票的例子,用户可以选择他们喜欢的球队和运动项目。当浏览器用户选择了任何checkbox时,这个动作触发一个事件,这个事件将选择的值提交到服务器程序然后显示投票的结果。
     
          服务器程序有一个数据库用来存放投票结果;这个程序更新然后返回这个结果。这个例子使用XMLHttpRequest对象发送运动项目的选择和处理服务器的响应,它使用DOM编程和CSS来显示投票结果。HTML代码:
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="example.js"></script>
        <link rel="stylesheet" type="text/css" href="example.css" />
        <title>submit checkbox values</title>
    </head>
    <body>
    <h3>Choose your favorite sports</h3>
    <h4>Team sport</h4>
    <form id="team" action="javascript:void%200" method="get">
    <div id="team_d" class="team">
    <input type="checkbox" name="team_sports" id="baseball" value="baseball" /> Baseball <br />
    <input type="checkbox" name="team_sports" id="soccer" value="soccer"  /> Soccer  <br />
    <input type="checkbox" name="team_sports" id="football" value="football"  /> Football  <br />
    <input type="checkbox" name="team_sports" id="basketball" value="basketball"  /> Basketball  <br />
    <input type="checkbox" name="team_sports" id="lacrosse" value="lacrosse" />Lacrosse  <br />
    <input type="checkbox" name="team_sports" id="hockey" value="hockey" /> Hockey  <br />
    <input type="checkbox" name="team_sports" id="tennis" value="tennis" /> Tennis  <br />
    </div>
    </form>
    <div id="team_poll" class="poll">
        <span id="t_title" class="p_title"></span>
        <span id="t_results" class="p_results"></span></div>
    <h4>Individual sport</h4>
    <form  id="ind" action="javascript:void%200" method="get">
    <div id="ind_d" class="ind">
    <input type="checkbox" name="individual_sports" id="cycling" value="cycling" /> Cycling  <br />
    <input type="checkbox" name="individual_sports" id="running" value="running"  /> Running  <br />
    <input type="checkbox" name="individual_sports" id="swimming" value="swimming"  /> Swimming <br />
    <input type="checkbox" name="individual_sports" id="nordic_skiing" value="nordic_skiing"  />Nordic Skiing  <br />
    <input type="checkbox" name="individual_sports" id="inline_skating" value="inline_skating"  />Inline Skating <br />
    <input type="checkbox" name="individual_sports" id="triathlon" value="triathlon"  />Triathlon <br />
    <input type="checkbox" name="individual_sports" id="track" value="track"  />Track <br />
    </div>
    </form>
    <div id="individual_poll" class="poll">
        <span id="i_title" class="p_title"></span>
        <span id="i_results" class="p_results"></span></div>
    </body>
    </html>
     
    这个页面首先从exapmle.js文件中引入执行所有应用功能的JavaScript代码。还引入了一个样式表(example.css)来控制页面的表现,使得投票结果直到用户准备好的时候才显示。
     
          这个页面包含两个div元素,每个都包含一组checkbox元素,列出了各只队伍和体育项目。
    JavaScript代码:
    var sportTyp="";
    var request = null;
     
    window.onload=function()
    {
          var allInputs=document.getElementsByTagName("input");
          if(allInputs!=null)
          {
                for(var i = 0;i<allInputs.length;i++)
                {
                      if(allInputs[i].type=="checkbox")
                      {
                            allInputs[i].onchange=function()
                            {
                                  sendSportsInfo(this);
                            };
                      }
                }
          }
    }
     
    function sendSportsInfo(obj)
    {
          if(obj==null){return;}
          var url = "";
          var nme="";
          if(obj.checked)
          {
                nme=obj.name;
                var sub=nme.substring(0,nme.indexOf("_"));
                sportTyp=sub;
                url="http://www.parkerriver.com/s/fav_sports?sportType="+nme+
                      "&choices=" +obj.value;
                httpRequest("GET",url,true);  
          }
    }
     
    function handleResponse()
    {
          try
          {
                if(request.readyState==4)
                {
                      if(request.status==200)
                      {
                            var resp=request.responseText;
                            if(resp !=null)
                            {
                                  var func = new Function("return "+resp);
                                  displayPollResults(func());
                            }
                      }else
                      {
                            alert("XMLHttpRequest与服务器通信问题");
                      }
                }
          }catch(err)
          {
                alert(err);
          }
    }
     
    function displayPollResults(obj)
    {
          var div = document.getElementById(sportTyp+"_poll");
          var spans=div.getElementsByTagName("span");
          for(var i=0;i<spans.length;i++)
          {
                if(spans[i].id.indexOf("title") !=-1)
                {
                      spans[i].innerHTML="<strong>Here are the latest poll "+
                                 "results for " + sportTyp+
                                 " sports</strong>"
                }else
                {
                      var str="<br />";
                      for(var prop in obj)
                      {
                            str +=prop +" : "+obj[prop]+"<br />";
                      }
                      spans[i].innerHTML=str;
                }
          }
          div.style.visibility="visible";
    }
     
    这段代码的首先的任务是为checkbox的状态改变时(从未选中到选中)分配一个要执行的方法。这就是window.onload事件处理器的职责,它是在页面完全加载完毕后调用的。
     
    window.onload=function()
    {
          var allInputs = document.getElementsByTagName("input")
          {
                if(allInputs != null)
                {
                      for(var i=0;i<allInputs.length;i++)
                      {
                            if(allInputs[i].type=="checkbox")
                            {
                                  allInputs[i].onchange=function(){sendSportsInfo(this);};
                            }
                      }
                }
          }
    }
     
    这段代码首先将页面的所有input元素存储在一个叫做allInputs的数组变量中。如果input元素的类型是checkbox,比如<input type="checkbox" ... />,它的onchange属性就被赋上一个方法叫做sendSportsInfo()。这段代码一次性将所有checkbox的onchange事件处理器都设置好;它不会影响到任何后来再加入的input元素。
     
    sendSportsInfo的this参数就是那个状态改变的input元素的引用。
     
    早投和常投
     
          我们来看一下sendSportsInfo()方法。这个方法构造了一个用户的选择将要发送到的服务器程序的URL:
    function sendSportsInfo(obj)
    {
          if(obj==null){reutrn;}
          var url="";
          var nme="";
          if(obj.checked)
          {
                formObj=obj;
                nme = obj.name;
                var sub = nme.substring(0,nme.indexOf("_"));
                sportType=sub;
                url="http://www.parkerriver.com/s/fav_sports?sportType="+nme+
                     "&choices="+obj.value;
                httpRequest("GET",url,true);
          }
    }
     
    由于我使用了this关键字作为sendSportsInfo()的参数,obj变量就是一个HTML中input元素的引用。我只会在input  checkbox被选择的时候连接服务器,代码中做了状态的检查。每一个input元素的名字在HTML中已经被设置成了team_sports或者individual_sports,因此,代码可以捕获这个名字以及名字中"_"字符前面的子字符串(我需要这个字符串来显示投票结果)。
     
    obj.name用来存取HTMLInputElement的name属性,这是DOM API的一部分。这个属性对应HTML元素中的name:<input name="myname" .../>
     
    服务器端在存储了用户的投票后,返回一个最新的投票结果的HTTP响应。这段代码定义在handleResponse()方法中,它调用另外一个方法来显示结果。
     
    服务器端返回的不是一个XML二是一个JSON格式的数据,很容易转换为JavaScript对象。
     
     
    displayPollResults()方法使用DOM生成了一个多彩的结果显示。
     
    投票结果显示在id为team_poll或者individual_poll的div元素中。每一个div元素都包含两个span元素。这span元素用来显示结果的标题和实际的结果。
     
          现在,我们来看一下CSS文件中定义的各种显示规则。div以及div中的内容是不显示的,直到用户点击checkbox:
     
    .p_title {font-size: 1.2em; color: teal }
    h3 { margin-left: 5%; font-size: 1.4em; }
    h4 { margin-left: 5%; font-size: 1.2em; }
    div.poll { margin-left: 5%; visibility: hidden; border: thin solid black;
        padding: 2%; font-family: Arial, serif;
        color: gray; background-color: yellow}
    div.team { margin-left: 5%; border: thin solid green; padding: 5%;
        font-family: Arial, serif}
    div.ind { margin-left: 5%; border: thin solid green; padding: 5%;
        font-family: Arial, serif }
    div { max-width: 50% }
     
    DOM和Ajax机制的很棒的一个方面是CSS属性也可以编程。当页面已经可以显示投票结果的时候,div元素的visibility属性被设置为visible。
     
          如果你不停的点击这些checkbox,你可以看到投票结果不停的增长,而浏览器中其他的部分没有改变。这对于那些收集离散的反馈并即时显示结果的应用来说是一个不错的设计。
     
     
    June 05

    翻译 一些 Ajax 资料(21)

    扩展已有的选择列表
     
    给浏览器用户修改已有列表的能力
     
          想象一下你有一个州列表,就和前面例子中的select一样。作为客户注册过程的一部分,你询问客户住在哪一个州(用于营业税)。但是你同时希望其他国家的客户也可以注册,因为你的产品已经可以销往海外了。你不想在select列表中维护地球上的所有国家,当然,既有地球政治的原因(比如前南斯拉夫),也是因为select列表会过大而影响使用。因此,你希望你的用户能够选择一块大陆,一个增加select选项子集的选择。你的应用将选择的大陆名字传送到服务器程序,在服务器查询相应大陆上的所有国家。
          开始,你先提供一个大陆的选择列表。当用户做出了选择,这块大陆上的国家名称从服务器传递来并自动增加到已有的select列表上,无需刷新列表。
          用户在最上面的select列表中选择一块大陆。这个操作触发select元素的onclick事件。下面是HTML代码:
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="example.js"></script>
        <link rel="stylesheet" type="text/css" href="example.css" />
        <title>Alter select lists</title>
    </head>
    <body>
    <h3>Add Entries to a Select List</h3>
    <form action="javascript:void%200">
        <table border="0">
            <tr><td>Add your country: <select id="cts" name="_continents">
                <option value="southam">South America</option>
                <option value="euro">Europe</option>
            </select></td></tr><tr><td>Choose one or more states: </td>
            <td> <select id="sts" name="_state" multiple="multiple" size="4">
                <option value="al">Alabama</option>
                <option value="ak">Alaska</option>
                <option value="az">Arizona</option>
                <option value="ar">Arkansas</option>
                <option value="ca">California</option>
                <option value="co">Colorado</option>
                <option value="ct">Connecticut</option>
                <option value="de">Delaware</option>
                <option value="dc">District of Columbia</option>
                <option value="fl">Florida</option>
                <option value="ga">Georgia</option>
                <option value="hi">Hawaii</option>
                <!--snipped here...-->
            </select></td></tr>
        </table>
    </form>
    </body>
    </html>
     
    所有的JavaScript都写在example.js文件中。下面是这个文件中的内容(省略了建立和初始化请求对象的内容,你应该已经烂熟了。)
     
    var origOptions = null;
    var request=null;
     
    window.onload=function()
    {
          var sel = document.getElementById("cts");
          var sel2 = document.getElementById("sts");
          if(sel !=null)
          {
                sel.onclick=function()
                {
                      addCountries(this);
                };
          }
          origOptions = new Array();
          //存储原来的州的选择列表,这样它重构的时候可以不丢失州列表
          for(var i = 0; i<sel2.options.length;i++)
          {
                origOptions[i]=sel2.options[i];
          }
    }
     
    function addCountries(obj)
    {
          if(obj==null {return;}
          var url="";
          var optsArray = obj.options;
          var val = "";
          for(var i=0;i<optsArray.length;i++)
          {
                 if(optsArray[i].selected)
                 {
                       val=optsArray[i].value;break;
                 }
          }
                  encodeURIComponent(val);
          httpRequest("GET",url,true);
    }
     
    function handleResponse()
    {
          try
          {
                 if(reqeust.readyState==4)
                 {
                       if(request.status==200)
                       {
                             var resp = request.responseText;
                             if(resp !=null)
                             {
                                   var objt = eval(resp);
                                   addToSelect(objt);
                             }
                       }else
                       {
                             alert("XMLHttpRequest和服务器通信有问题" );
                       }
                 }
          }catch(err)
          {
                alert(err);
          }
    }
     
    function addToSelect(obj)
    {
          var _select = document.getElementById("sts");
          var el;
          while(_select.hasChildNodes())
          {
                for(var i = 0;i<_select.childNodes.length;i++)
                {
                     _select.removeChild(_select.firstChild);
                }
          }
          for(var h=0;h<origOptions.length;h++)
          {
                _select.appendChild(origOptions[h]);
          }
          for(var i=0;i<obj.length;i++)
          {
                el =document.createElement("option");
                el.appendChild(document.createTextNode(obj[i]));
                _select.insertBefore(el,_select.firstChild);
          }
    }
     
    当浏览器首次加载页面,代码为包含州的select列表定义了一个onclick事件处理器。这个事件在用户点击select控件的时候被触发,无论是否改变列表上的值。这个事件处理器调用addCountries()方法,将这个select对象作为参数传递给这个方法。代码中还将原始的州列表中的内容存放在Array对象中。否则,当用户点击靠上的select列表时,相同的国家会一遍又一遍的被添加到第二个select列表中。因为origOptions Array变量缓存了原始的列表,每次用户点击上面的select列表,下面的select列表会重建,新的国家添加在原始州列表的前面。
     
          下一步是addCountries()方法。你不需要回头再看这个方法了,因为它却是非常简单。这个方法遍历大陆列表的options,如果某一个option被选择了,它的值被提交到Java servlet。这个servlet程序返回相应大陆上的国家,然后代码将这些国家添加到下面的列表上。
     
    新的列表还是海市蜃楼
     
          代码按照字符串取得返回值,返回值可以被转换成为JavaScript数组。返回值的格式:["Brazil","Ecuador",etc.],用JavaScript的eval()方法将这个字符串转换为JavaScript
    数组。接下来,好似魔术,新的国家出现在第二个选择列表的顶部,这是addToSelect()方法的把戏:
    function addToSelect(obj)
    {
          var _select = doucment.getElementById("sts");
          var el;
          while(_select.hasChildNodes())
          {
                for(var i=0;i<_select.childNodes.length;i++)
                {
                      _select.removeChild(_select.firstChild);
                } 
          }
          for(var h=0;h<origOptions.length;h++)
          {
                _select.appendChild(origOptions[h];
          }
          for(var i=0;i<obj.length;i++)
          {
                el = document.createElement("option");
                el.appendChild(document.createTextNode(obj[i]));
                _select.insertBefore(el,_select.firestChild);
          }
    }
     
    这个方法调用了基础的DOM API,将一个select列表作为几个option相关节点的父节点。首先,代码清空select列表并用原始的州重新生成它。这是这个应用的逻辑,用户能够在原始列表的顶部加新的国家,但是国家不会重复的在列表中出现。然后代码用每一个服务器传来的数组的元素建立新的option元素。最后,代码使用Node.insertBefore方法,将每个新的option插入到列表第一个option的前面。
     
          _select.firstChild节点是随着for循环不断改变的。
    June 02

    翻译 一些 Ajax 资料(20)

    使用服务器数据动态生成一个新的选择列表
     
    在页面上建立一个选择列表,它能在不刷新整个页面的情况下自动生成一个新的选择列表。
     
          有时候,用户界面伤得一个选择会很自然的导致另外一组选择。举一个例子,电脑硬件支持的页面,一个select列表用来选择硬件的平台,比如Apple或者HP,平台生成第二个列表--响应的操作系统,等等。Ajax在这样的用户接口为浏览器用户自动客户化的情况下非常有用,如果select列表中的内容要从服务器端取得就更不用说了。
     
          你只需使用动态HTML建立这个网页,用JavaScript创建那个新的select列表。但是,新的列表的选项可能要在JavaScript中硬编码了。最后,新的列表的内容可能会发生改变,这就造成了这样一个笨拙的局面:开发人员不得不经常性的在JavaScript文件中维护列表项。缺乏将这些值存放在明智的地方比如数据库或者其他持久存放的地方,这个应用模型变得很难维护和使用。
     
          这一节的例子中在页面有两个选择按钮,用户可以用来选择显示欧洲国家或者南美国家。每种选择会导致新的选择列表中的内容不一样。
     
          下面是HTML代码:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="example.js"></script>
        <link rel="stylesheet" type="text/css" href="example.css" />
        <title>Alter select lists</title>
    </head>
    <body>
    <h3>Create or Alter a Select List</h3>
    <form action="javascript:void%200" >
        <table border="0">
            <tr><td>Choose one or more states: </td>
            <td><select name="_state" multiple="multiple" size="4">
                <option value="al">Alabama</option>
                <!more options... -->
            </select></td></tr>
            <tr><td><span id="select_info" class="message">
            The server reports that you have chosen the following abbreviated        states:
            </span>
            <tr><td>Choose your list content:</td><td>European countries:
            <input type=
            "radio" name="countryType" id="euro" value=
            "euro" /> South American countries:
            <input type="radio" name=
            "countryType" id="southam" value="southam" /></td></tr>
            <tr><td><div id="newsel"></div></td></tr>
        </table>
    </form>
    </body>
    </html>
     
    这段代码的目的是只要用户点击了一个选择按钮就建立一个新的select列表。页面上的选择按钮只能有一个被选中(互斥)。如果你选择了一个,那么另一个自动取消选择。
     
          这个例子的核心就是每一个选择按钮的onclick事件处理器。这是一个HTML元素的属性,指向一个JavaScript方法。这个方法的代码在用户每次点击选择按钮的时候执行。也就是说,如果一个按钮没有被选择而用户点击了它,代码就会调用generateList()方法。
     
          下面是控制响应用户点击选择按钮的代码:
    window.onload=function()
    {
          var eur = document.getElementById("euro");
          if(eur !=null)
          {
                eur.onclick=function(){generateList(this);};
          }
          var southa = document.getElementById("southam");
          if(southa != null)
          {
                southa.onclick=function(){generateList(this);};
          }
    }
     
    每个onclick事件处理器都指向一个方法,generateList()。请注意作为参数的this关键字。它持有被点击的选择按钮的引用,因此这个方法可以获得按钮的值并将它发送给服务器组件。
     
    相当快!新的列表
     
          generateList()方法在example.js中定义。HTML代码在script标签中引入了这个文件。下面是这个文件的内容:
     
    var formObj = null;
    var formObjTyp = "";
    var request = null;
     
    function genreateList(obj)
    {
          if(obj==null) return;
          if(obj.checked)
          {
                formObj=obj;
                formObjTyp = obj.tagName.toLowerCase();
                var url = "http://www.parkerriver.com/s/selectl?countryType=" +
                              encodeURIComponent(obj.value);
                httpRequest("GET",url,true);
          }
    }
     
    function handleResponse()
    {
          try
          {
                if(request.readyState==4)
                {
                      if(request.status==200)
                      {
                           if(formObjTyp.length>0 && formObjType=="input")
                           {
                                 if(resp !=null)
                                 {
                                       var objt = eval(resp);
                                       var sel = document.createElement("select");
                                       sel.setAttribute("name","countries");
                                       createOptions(sel,objt);
                                       var newsel = document.getElementById("newsel");
                                       reset(newsel);
                                       newsel.appendChild(sel);
                                 }
                           }else if(formObjTyp.length>0 && formObjType=="select")
                           {
                                 //简单起见,这里的代码你看着发挥
                           }
                      } else
                      {
                            alert("XMLHttpRequest对象和服务器通信问题");
                      }
                }
          }catch(err)
          {
                alert(err);
          }
    }
     
    function createOptions(sel,_options)
    {
          if(_options==null || _options.length==0) {return;}
          var opt =null;
          for(var i =0;i<_options.length;i++)
          {
                opt = document.createElement("option");
                opt.appendChild(document.createTextNode(_options[i]));
                sel.appendChild(opt);
          }
    }
     
    function reset(elObject)
    {
          if(elObject !=null && elObject.hasChildNodes())
          {
                for(var i=0;i<elObject.childNodes.length;i++)
                {
                      elObject.removeChild(elObject.firstChild);
                }
          }
    }
     
    //下面是初始化request的代码,请参考前面的代码,这里略去。
     
    当用户点击一个选择按钮,onclick事件处理器对于选择按钮的状态是否选择不作区分;当按钮已经被按下的时候,这里的设计是重新响应。在建立一个新的select列表前,代码首先检查对象是否被按下了,确认选择按钮的被选择状态:
     
    function generateList(obj)
    {
          if(obj==null){return;}
          if(obj.checked)
          {
           .....
          }
    }
     
    查询服务器
     
          代码用被选择的按钮的值到服务器查询。记住新的select列表要包括选择项(比如 United Kingdom)是存放在服务器端的。为了确定那组值需要从服务器取得,是欧洲或者南美,我在URL参数中用了countryType名字的参数。它的值是从选择按钮的value属性获得的:
    <input type = "radio" name="countryType" id="southam" value="southam" />
     
    代码使用请求对象和httpRequest()方法将这个信息发送到服务器。 然后接收响应建立新的select列表。它将值从响应中拉出来,在handleResponse方法中做了这些事情:
     
    返回值是一个JSON的数组
     
    var objt = eval(resp);
    var sel = document.createElement("select");
    sel.setAttribut("name",countries");
    createOptions(sel,objt);
    var newsel = document.getElementById("newsel");
    reset(newsel);
    newsel.appendChild(sel);
     
    服务器返回值好像这样:["Spain","Germany","Austria"]。代码取得这个字符串返回值然后用eval()转成一个数组,我们在首次讨论JSON时候用过。JavaScript然后用DOM API建立新的select元素。给新生成的HTML元素一个名字和一个值是一个好习惯,尤其在你的应用要将这些值提交到服务器组件的时候。
    var sel = document.createElement("select");
    sel.setAttribtue("name","cuntries");
     
    使用服务器返回的值的数组,createOptions()方法用每一个数组的元素生成select的option元素。最终,一个新的select元素被勾勒出来:
    <select name = "countries">
      <option>United Kingdom</option>
      ....
    </select>
    以下是createOptions()方法:
    function createOptions(sel,_options)
    {
          if(_options ==null || _options.length==0){return;}
          var opt = null;
          for(var i = 0;i<_options.length;i++)
          {
                opt = document.createElement("option");
                opt.appendChild(document.createTextNode(_options[i]));
                sel.appendChild(opt);
          }
    }
     
    _options变量包含所有的国家名称。这段代码使用DOM API建立新的option元素,调用appendChild()方法将国家名称加在option上,最后调用select元素的appendChild()方法将option加在select列表上。
     
    最后一步:
     
    我们必须指出HTML中哪一个块元素将用来放置新的select元素,而不是将这个select元素随便仍在body标签的什么地方。下面的标签就是干这个用的:
    <div id="newsel"></div>
     
    div元素在选择按钮之下出现,但是由于它初始情况下不含有任何内容,用户不会意识到它的存在。代码使用另外一个流行的DOM方法,getElementById(),来获得这个div的引用,然后将select元素接在它的后面:
    var newsel = document.getElementById("newsel");
    reset(newsel);
    newsel.appChild(sel);
     
    为了防止用户不停的点击选择按钮(疯子)而生成上千上万上亿的新列表,另外一个方法reset()用来检查div是不是有已经存在的子节点。这个方法在代码向div的select列表前删除所有已经存在的节点:
     
    function reset(elObject)
    {
          if(elObject !=null && elObject.hasChildNodes())
          {
                for(var i = 0;i<elObject.childNodes.length;i++)
                {
                      elObject.removeChild(elObject.firstChild);
                }
          }
    }
     
    现在,都明白了么?试试看吧,加油!!!!
    June 01

    翻译 一些 Ajax 资料(19)

    向服务器提交选择列表中的值
     
    将用户的多个选择列表飞送到服务器,没有延迟
     
          很多网络开发者将会看到使用请求对象直接向服务器程序发送用户对select列表或者多选按钮的选择,而无需强制用户点击按钮发送整个表单。这样就给了应用更好的响应体验并通过发送小块数据而非大块的信息来提高效率。
          这一节的例子在键盘的焦点从select列表离开后,将用户的选择发送到服务器。select元素的HTML代码:
     
    <select name="_state" multiple="multiple" size="4">
     
    这个选择列表允许用户选择多个项。当键盘焦点从这个select列表离开(用户点击了Tab或者鼠标点击了select以外的地方)时,元素的onblur事件处理器被执行。size=4表示select元素中无需拖拉即可看到四个项。
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="example.js"></script>
        <link rel="stylesheet" type="text/css" href="example.css" />
        <title>Alter select lists</title>
    </head>
    <body>
    <h3>Create or Alter a Select List</h3>
    <form action="javascript:void%200" >
        <table border="0">
            <tr><td>Choose one or more states: </td><td>
            <select name="_state" multiple="multiple" size="4">
                <option value="al">Alabama</option>
                <option value="ak">Alaska</option>
                <option value="az">Arizona</option>
                <option value="ar">Arkansas</option>
                <option value="ca">California</option>
                <option value="co">Colorado</option>
                <option value="ct">Connecticut</option>
                <option value="de">Delaware</option>
                <option value="dc">District of Columbia</option>
                <option value="fl">Florida</option>
                <option value="ga">Georgia</option>
                <option value="hi">Hawaii</option>
                <!snipped...-->
            </select></td></tr>
            <tr><td><span id="select_info" class=
                    "message">The server reports that you have chosen the
                    following abbreviated states: </span>
            <tr><td>Choose your list content:</td>
            <td>European countries:
            <input type="radio" name="countryType" id="euro" value="euro" />
            South American countries:
            <input type="radio" name="countryType" id="southam" value="southam" />
            </td></tr>
            <tr><td><div id="newsel"></div></td></tr>
        </table></form>
    </body>
    </html>
     
    其中的span元素包含一条消息,用户在做完选择后会看到。这条消息用example.css中的CSS规则装饰。我们等会儿会看到返回给用户的这条消息,首先让咱们先来检视一下将用户的选择提交到服务器的代码。乍一看这段代码可能有点复杂,坚持看下去,因为它会变得非常简单。
     
    function getSelectInfo(selectObj)
    {
          if(selectObj == null{return;}
          formObj=selectObj;
          formObjTyp=formObj.tagName.toLowerCase();
          var optsArray = formObj.options;
          var selectedArray = new Array();
          var val="";
          //将选择的项存储到数组中
          for(var i = 0,j=0;i<optsArray.length;i++)
          {
                if(optsArray[i].selected)
                {
                      selectedArray[j]=optsArray[i].value;
                      j++;
                }
          }
          //创建一个用逗号分割的被选择值的组合
          for(var k =0;k<selectedArray.length;k++)
          {
                if(k != selectedArray.length-1){val+= selectedArray[k] +",";}
                else{val+=selectedArray[k];}
          }
                     encodeURIComponent(val);
          httpRequest("GET",url,true);
    }
     
    这段代码取得所有select元素中的项并判断哪些被选择了。将所有被选择的项组合成为一个字符串,用逗号分开,比如ma,nh,vt。
     
          如果浏览器将选择的值存放在一个方便的地方那么就会更容易一些,比如select对象的value属性,但是实际不是这样的。你不得不将所有的项浏览一遍,判断哪一个被选择了,然后将它存放在什么地方,比如JavaScript的数组中。
          select元素包含option元素:
    <select name="_states">
    <option vlaue="vt">Vermont</option>
    ...
    </select>
    在DOM中,select元素代表一个有options属性的select对象,options属性是一个option数组的对象。你使用一个option对象的value属性来获得用户看到的每个option的值。不要啧舌,代码就是无数的对象和属性。
     
          服务器组件期望一个objtype参数,在这里就是"select"。我还发送了用逗号分开的用户选择字符串,用val参数存放。由于使用了JavaScript全局方法encodeURIComponent(),每一个逗号都被编码成为%2C,因为URL中不允许出现一些特定的标点符号。
          encodeURIComponent()是一个全局方法,用来将部分URI编码,URI可能是你录入在浏览器地址栏的奇怪的地址。这个方法将URI中有特殊目的的标点符号比如/,:,@,;还有空格编码成为它们对应的十六进制。比如 ;  被编码成为 %3B 。encodeURIComponent不会将ASCII数字或者字符编码。使用encodeURIComponent来编码JavaScript代码处理的查询字符串或者路径信息。
     
          现在发生了什么?
          服务器获得了被选择的值然后间接的将它们返回到应用,还有而外的信息。这就是前面提到的那条消息。它将显示用户当前的选择和有关服务器的信息。
          这条消息是动态变换的,不需要任何重建或者刷新页面。当连接着服务器的时候它提供给用户一个立刻的反馈,不需要用户多次的提交。这些是如何发生的?下面是handleResponse()方法的代码,它处理服务器返回值:
    function handleResponse()
    {
          try
          {
                if(request.readyState==4)
                {
                      if(request.status==200)
                      {
                            if(formObjType.length>0 && formObjTyp=="input")
                            {
                                  var resp = request.responseText;
                                  var objt=func();
                                  var sel = document.createElement("select");
                                  sel.setAttribute("name","countries");
                                  createOptions(sel,objt);
                                  var newsel = document.getElementById("newsel");
                                  reset(newsel);
                                  newsel.appendChild(sel);
                            }else if(formObjTyp.length>0 && formObjTyp=="select")
                            {
                                 var resp = request.responseText;
                                 var func = new Function("return " + resp);
                                 var objt=func();
                                 var fld = document.getElementById("select_info");
                                 if(fld !=null)
                                 {
                                       fld.innerHTML = "The server <strong>"+
                                              objt.Server_info+
                                              "</strong> reports that you have chosen" +
                                              "<br /> the following " +
                                              "abbreviated states: <strong>" +
                                              objt.Selected_options+"</strong>";
                                 }
                            }
                      }else
                      {
                           alert("XMLHttpRequest对象和服务器交互出现问题");
                      }
                }
          }catch(err)
          {
                alert(err);
          }
    }
     
    又是JSON,你好~
     
    服务器以JSON格式的字符串提供反馈,这样它可以被客户端方便的转换成为浏览器的代码。
     
    涉足一些服务器端:
     
    以下是一个Java方法,返回给Ajax一个JSON格式的值。这个方法将属性名字和值的字符串作为参数,然后将属性名字和值分开:
     
    public static String getJsonFormat(String propValues, String delim) {
        if(propValues == null || propValues.length(  )==0) { return "";}
        StringBuffer structure = new StringBuffer("");
        structure.append("{\\n");
        if (delim == null || delim.length(  ) == 0) { delim = ",";}
        /* We're expecting comma-separated values such as prop1,val1,
        prop2,val2, etc. */
        StringTokenizer toke = new StringTokenizer(propValues,delim);
        int j = 0;
        int c =  toke.countTokens(  );
        for(int i = 1; i <=c; i++) {
            j = i%2;
            if(j != 0) { structure.append(toke.nextToken(  )).
                    append(": ");   } //it's a property name
            else { structure.append("\\"").append(toke.nextToken(  )).
                    append("\\""); //it's a property value
                if(i != c){structure.append(",");}
                structure.append("\\n");
            }
        }
        structure.append("}");
        return structure.toString(  );
    }
     
    DOM API
     
    这个例子接下来的步骤是将返回值存放到一个变量中,这样JavaScript就能将值显示给用户了。
     
    var func = new Function("return "+resp);
    var objt = func();
    var fld= document.getElementById("select_info");
     
    fld变量是HTML页面的那个div元素用来存放服务器返回给用户的那条消息。getElementById()是一个DOM API方法,用来在HTML中获得一个标签的引用,这样代码就能够改变这个标签的表现和行为了:
     
    if(fld != null)
    {
        fld.innerHTML = "The server <strong>"+objt.Server_info+
                        "</strong> reports that you have chosen"+
                        "<br /> the following "+
                        "abbreviated states: <strong>"+
                        objt.Selected_options+"</strong>";
    }
     
    使用类似objt.Selected_options这样的语法来直接显示对象信息。正如你看到的,用户选择的项和服务器软件的名字被动态显示出来。那条消息在用户作出不同的选择时自动改变。消息的内容从服务器端传来而不是用客户端的JavaScript代码生成。
    May 30

    翻译 一些 Ajax 资料(18)

    在文本框或者textarea中显示服务器数据
     
    无需刷新页面而使得服务器信息魔术般得显示在文本控件中。
     
          你能够编写一个服务器组件与用户录入到文本控件中的信息进行交互,这种交互不用在用户每次录入新的信息的时候重构页面。一个例子就是拼写检查或者自动填充的控件(不久的将来会介绍到)。使用请求对象作为一个中间人,服务器组件可以实时的响应用户敲入的内容。
     
          这个例子显示一个自动的服务器响应,这样,好像变魔术一般响应出现在文本控件中,无需改变页面的其他地方。这个例子是前面使用请求对象在幕后向服务器提交textarea或文本框值的例子的扩展。
    收集用户录入的信息然后在同一个控件中显示一个字符统计和单词统计。当然,你可以在客户端就完成这项任务,但是它只是用来证明服务器组件做了工作,这个例子还会在textarea中显示一些服务器信息。
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="js/hacks_2_1.js"></script>
        <link rel="stylesheet" type="text/css" href="/css/hacks.css" />
        <title>Submit your information</title>
    </head>
    <body>
    <h3>Get stats from textareas and textfields using Ajax</h3>
    <form action="javascript:void%200" >
    <table border="0"><tr>
    <td>Enter a few words for submitting to our server:
    <input type="text" name="tfield" size="35"/></td></tr>
    <tr><td valign="top">Enter a phrase for submitting to our server:
    <textarea name="tarea" rows="20" cols="20">
    </textarea></td>  </tr>
    </table></form>
    </body>
    </html>
     
    上一个例子已经解释了代码如何提交用户录入的信息而不用刷新页面。也就是说,在用户键入了一些信息并且点击控件以外的地方或者点击Tab键,用户录入到文本框和textarea中的内容就被放到HTTP请求中发送到服务器。
    getInfo()方法是onblur事件的处理器,已一个文本框或者textarea作为参数。
          整个代码的行为在上个例子中已经解释了,所以不会重复讲解。但是,我会在这里说明getInfo()和handleResponse()方法,它们分别用来向服务器组建发送服务器需要的信息和处理服务器响应。首先,我们来看一下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(formObjType)+"&val="+encodeURIComponent(obj.value);
          httpRequest("GET",url,true);
    }
          这个方法将用户键入的信息作为val参数的一部分传递给服务器组件。并且,obj参数存放的文本控件的引用,用户录入的信息都是在文本控件中的,比如文本框和textarea。这个引用明确的是一个DOM对象,比如一个HTMLInputElement或者HTMLTextAreaElement。
          你不比担心DOM对象树是啥样子(虽然它确实很有趣)。这个例子的HTML代码用this关键字来引用响应的文本控件。getInfo()方法能够通过取得对象的tagName属性来准确的决定用户正在和哪一种控件交互,文本框或者textarea。
         
    即时服务器消息
          服务器端程序收到用户录入的信息饭后返回响应的字符数和单词数。为了使得响应信息美味可口,服务器是一哦女冠JavaScript Object Notation(JSON)格式返回。JSON和XML类似都是格式化数据已使得数据可以容易的分类和使用。
          你自己的程序可能简单得返回XML格式得数据或者一个字符串。使用JSON格式得返回值是程序员得自由,如果服务器客户端由JavaScript代码组成,那么这种格式就特别有用了。
          下面是返回的值:
     
    {
          Form_field_type:"textarea",
          Text_length:"385",
          Word_count:"55",
          Server_info:"Apache Tomcat/5.0.19"
    }
    这段代码表示了一个由四个不同属性的JavaScript对象:Form_field_type,Text_length,Word_count,Server_info。
     
          现在,我们使用这个信息并将它加在textarea中。这是handleResponse()方法的任务:
    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
                {
                       alert("XMLHttpRequest对象和服务器通信问题"); 
                }
          }catch(err)
          {
                          alert(err);
          }
    }
     
    这段代码将响应作为文本。由于响应已经被格式化成为JSON格式,代码中使用的是前面讲解JSON的技术。Function构造函数返回作为JavaScript对象的文本。这样,objt变量就拥有了服务器组件响应,以JavaScript对象的方式,因此您就可以用objt.Server_info这样的方式获取服务器返回的信息。
     
          剩余的代码将这些信息插入到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;
          }
    }
     
    你可以存取textarea因为JavaScript的全局变量formObj引用了它。这段代码的关键是设置textarea和文本框的value。
     
          服务器程序向textarea发送了更多的信息,包括换行符号(\\n),因为textarea是一个大框框,可以方很多文本信息。你不能在一个文本框中放一个换行符号,因为它只有一行。
     
          虽然按照常规来讲用户期望textarea和文本框保留用户自己录入的数据,这个例子只是用来说明如何根据用户的录入信息来向控件提供直接的服务器反馈。
    May 29

    翻译 一些 Ajax 资料(17)

    将文本框或者文本域中的内容提交服务器而不用刷新页面
     
    在向文本框或者文本域中录入信息和立刻向服务器提交数据之间建立平滑过渡。
     
          Ajax应用可以自动向服务器程序发送用户录入到文本框或者文本域中的信息。应用的代码等待文本控件的onblur事件发生,然后使用请求对象只发送文本控件中的内容。在很多应用中,这种技术倾向于让用户点击提交按钮,然后将整个表单的所有一大陀信息发送到服务器。使用Ajax后当然服务器的响应也是很爽的。比如,一个在线考试或者教育应用可以在用户离开一个问题的时候获取和显示这个问题的正确信息,而无需让用户点击一个按钮刷新页面来看需要的答案。实时翻译是另外一个使用这种行为的用户接口的例子。
     
          onblur事件是在一个控件失去键盘焦点的时候被触发,用户点击Tab键或者在控件外部点击鼠标。你还可以使用onkeypress,onkeydown,onkeyup事件处理器来与用户操作的控件进行响应。
         
          下面是这节中向服务器发送文本的事件顺序:
           1  用户移动到控件或者点击一个textarea。
           2  用户录入一些文本
           3  用户点击Tab或者点击页面的其他地方离开了这个textarea。
         
           这种低干涉交互表单的一个问题是用户没法自行控制web表单的行为。一个用户可能对文本框动态提交它的数据感到反感或者困惑。当用户完成一个文本框的录入时,用户接口应该能清楚的说明“有些事情要发生了”,或者显示一个消息或者在请求对象发送数据的时候显示进度。另外,根据任务的敏感度,你可能希望增加虞泳户交互的层,比如一个alert窗口用来询问“你要提交这些信息么?”
     
          这一节的例子包括一个文本框和一个textarea,当用户完成它们后,用它们的数据发送HTTP请求。
          用户在文本框或者textarea中录入一些信息,然后离开这个控件,应用会自动发送用户录入的内容到服务器组件。下面是HTML代码:
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml " xml:lang="en" lang="en">
    <head>
          <meta http-equiv="content-type" content'=text/html; charset=utf-8" />
          <script type ="text/javascript" src="example.js"></script>
          <link rel = "stylesheet" type="text/css" href="example.css" />
          <title>Submit your information</title>
    </head>
    <body>
    <h3>使用Ajax从textareas和textfields中获取内容</h3>
    <form action="javascript:void%200">
    <div id="textf">
    Enter afew words for submitting to your server:
    <input type="text" name="tfield" id="tfield" size="35"/>
    </div>
    <div id="texta">
    <span style='vertical-align: top">Enter a phrase for submitting to our server:</span> <textarea name="tarea" rows="20" id ="tarea" cols="20">
    </textarea>
    </div>
    </form>
    </body>
    </html>
     
          每个文本控件自己定义行为而不是用户点击提交按钮发送表单信息。
          当用户按下Tab或者点击文本控件以外的地方,控件代码指定的onblur事件处理器就被执行。接下来的代码展示了在浏览器加载完页面后事件处理器是如何设置的。
     
          example.js包含了运行这个例子的所有代码,下面的嗲马包括发送请求和处理返回值的所有代码,下一节将结束将服务器响应插入到文本控件的相关技术。
     
    var formObj = null;
    var formObjTyp = "";
    var request = null;
     
    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(formObjType == "input" || formObjTyp =="INPUT")
          {
                formObjTyp = formObjTyp+" " +formObj.type;
          }
          formObjTyp = formObjTyp.toLowerCase();
          var url = "http://www.parkerriver.com/s/webforms?objtype="+encodeURIComponent(formObjTyp)+"&val=" + encodeURIComponent(boj.value);
          httpRequest("GET",url,trur);
    }
     
    function handleResponse()
    {
          try
          {
                if(reuqest.readyState==4)
                {
                      if(request.status ==200)
                      {
                            var resp = request.reponseText;
                            var func = new Function("return " + resp);
                            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(formObjType=="input text"
                            {
                                  if(formObj != null)
                                 {
                                       formObj.value = objt.Form_field_type +
                                                              "#characters:"+objt.Text_length+
                                                       "Word count:"+objt.Word_count;
                                 }
                            }
                      }else
                      {
                            alert(XMLHttpRequest和Server程序通讯错误");
                      }
                }
          }catch(err)
          {
                alert(err);
          }
    }
     
    function initReq(reqType,url,bool)
    {
          try
          {
                request.onreadystatechange=handleResponse;
                request.open(reqType,url,bool);
                request.send(null);
          }catch(errv)
          {
                alert(errv);
          }
    }
     
    function httpRequest(reqType,url,asynch)
    {
          if(window.XMLHttpRequest)
          {
                request = new XMLHttpRequest();
          }else if(window.ActiveXObject)
          {
                request = new ActiveXObject("Msxml2.XMLHTTP");
                if(!request)
                {
                      request = new ActiveXObject(Microsoft.XMLHTTP);
                }
          }
          if(request)
          {
                initReq(reqType,url,asynch);
          }else
          {
                alert("你的浏览器不支持XMLHttpRequest对象");
          }
    }
     
    代码声明了两个全局变量formObj和formObjTyp。前一个变量用来存放input或者textarea对象(代码中的其他方法在后面需要使用这两个对象),后面一个存放一个表示form对象标签名字的字符串,比如"INPUT"或者"TEXTAREA"。这个字符串是服务器组件需要的参数之一。
          当浏览器加载页面完毕时,代码设置文本控件的onblur事件处理器。你可以通过在JavaScript中给窗口的onload事件处理器赋一个方法来完成这项任务。使用window.onload代码是通过HTML元素的onblur属性调用JavaScript方法的一个方式:
    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);}};
          }
    }
     
    现在文本框们已经很性感了。一旦用户录入信息并离开控件,那么录入的信息就飞向了服务器;用户不必点击按钮来发送它。
     
    文本框事件处理器的主要工作是调用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方法的参数是表示文本框或者textarea的对象。我将input或者textarea对象的引用传入为的是JavaScript代码可以用它们来处理服务器返回值。(下一节将展示如何处理返回值,莫急--patient translator)
     
          代码的最后部分,httpRequest("GET",url,ture),是实际发送用户数据的方法。
     
          但是,有些事情要在调用这个方法之前发生,比如组合需要的URL。服务器组件期望一个字符串来描述数据是从哪一个表单对象来的。这个例子中,字符串是从Element对象的tagName属性格式化来得。
          代码需要这些值来告诉服务器,返回值将要会被插入到文本框中还是textarea中。当然,我们在下一节才讨论返回值处理。
     
          接下来,代码通过input对象的子类型的信息(text input,radio button等等)来提炼出input对象的描述。这是通过将input对象的type属性(这个例子中是text)的值接在input字符串后面来完成的,最终的字符串是:input text。
     
          换句话说,这个type属性只有对象是<input type="text"....>HTML元素时才会返回"text"。然后这个字符串被强制转换为小写,并与用户录入的内容一起提交到服务器:
     
    formObjTyp = obj.tagName;
    if(formObjTyp=="input" || formObjTyp=="INPUT")
    {
          formObjTyp = formObjTyp +" " + formObj.type;
    }
    formObjTyp = formObjTyp.toLowerCase();
                 encodeURIComponent(formObjTypp)+"&val=" + encodeURIComponent(val);
    httpRequest("GET",url,true);
     
    JavaScript的全局方法:encodeURIComponent()是一个方法,用来保证特别的字符,比如空格,能够在URL中被正确的编码。否则,你的程序可能发送一部分或者被截断的URL到服务器,并会产生错误。完整的URL看起来是这个样子的:
     
    接下来呢?
     
    httpRequest()方法将初始化和使用请求对象的代码封装起来,我们在前面已经详细讲解了这些内容。
     
          提交数据之后呢?那就要看你的应用要做什么了。下一节的例子将介绍一个不同的主题,但是却处理服务器的响应:使用JavaScript和Ajax取得HTTP响应并将数据插入到已有的文本框或者textarea中。
     
          用户可能在一个textarea中写入相当多的内容,因此这种情况下应该使用POST而不是GET。比如,你可以httpRequest("POST",url,true),请求对象的send()方法将使用POST查询字符串作为参数:
    request.send(val=Hello%20there%20and%20a%20lot%20of%20other%20stuff);

    翻译 一些 Ajax 资料(16)

    嘿嘿,有人留言了,有动力有动力,恩哈!

    从这节起我们将开始一个新的旅程--操作web表单
          每一个使用网络的人都会遇到过HTML表单(HTML form)。当用户在线购买书籍或者DVD,加入到一个讨论列表中或者一个网络社区,都不可避免的在文本框中录入信息,在select列表中选则,然后点击按钮提交表单。这些表单的目的就是将用户或者客户端相关的数据上载到服务器组件,服务器组件再根据这些信息完成任务,比如将用户登陆到应用上。
          使用Ajax相关技术的Web应用能够提供一种不同的机制来提交表单信息。JavaScript代码可以从特定的变量或者组件不连续的提交值,比如,无需用户像以前那样点击提交按钮。这种应用模型将web表单转换成为类似桌面应用的“胖客户端”,代码可以通过点击或者blur事件响应来经网络传送数据,而不用刷新整个页面。接下来的几节将说明如何使用XMLHttpRequest,如何动态生成服务器返回的数据给用户显示。
          又是一个新的开始,加油吧。
    May 26

    翻译 一些 Ajax 资料(15)

    在代码中生成用户消息的样式
     
    动态定义并应用CSS样式
     
          JavaScript和DOM编程允许你定义CSS样式属性并将它们应用到页面元素上。一个你可能实现这一点的例子就是Wiki页面,它允许用户开发设计自己的页面样式。
          大多数情况下,将样式定义和JavaScript代码分开是首选做法。按照行为将应用的关系或者层分开可以让每个元素相互独立并减少开发的复杂度提高效率。
     
          这一节中,14讲一样,根据用户选择的样式动态显示服务器信息。于前面不一样的是,这次我们将样式写进代码,然后将它们应用到HTML元素上。
     
    JavaScript代码:
     
    var request;
    var urlFragment=" http://localhost:8080/";
    var st;
     
    function getAllHeaders(url,styl)
    {
          if(url)
          {
             st=styl;
             httpRequest("GET",url,true);
          }
    }
    /*参数:
              stType:样式名称:plain  fancy loud  cosmo
              stylObj:HTML元素的样式属性,比如div.style
    */
    function setStyle(stType,styObj)
    {
          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':
                    ...//你喜欢的样式(原文中是给出了loud fancy cosmo样式的具体代码的--lazy translator)
                 case 'fancy':
                    ...
                    ...
                 default:
                    alert('default'); 
         }
    }
     
    function handleResponse()
    {
          try
          {
                if(request.readyState==4)
                {
                      if(request.status==200)
                      {
                            var headers = reuqest.getAllResponseHeaders();
                            var div = document.getElementById("msgDisplay");
                            if(st)
                            {
                                  setStyle(st,div.style);
                            }else
                            {
                                  setStyle("plain",div.style);
                            }
                            div.innerHTML="<pre>"+headers+"</pre>";
                      }else
                      {
                            alert(request.status);
                      }
                }
          }catch(err)
          {
                alert(err);
          }
    }
     
    function initReq(reqType,url,bool)
    {
    //和以前一样
    }
     
    function httpRequest(reqType,url,asynch)
    {
    //和以前一样
    }
     
    有关样式列表
          web页面的每一个HTML元素都有一个style属性,如果它所在机器的浏览器支持CSS样式列表的话。比如,一个div元素由一个属性叫做div.style允许JavaScript编码者给这个div元素设置样式属性(比如,div.style.fontFamily="Arial")。这就是setStyle()方法的工作支柱--传递样式类型和div元素的style属性,然后这个方法就能够设置这个div元素的样式了。
     
          显示在页面的信息是使用请求对象从服务器带回来的。就像前面的诸多例子一样,用户将URL填写完整,然后离开文本框,触发onblur事件处理程序,一切就着样发生了,唯一不同的是我们将样式写在JavaScript代码中而不是CSS样式列表文件中。
       
          (到这里为止,Ajax的学习告一段落,温故而知新,到这里需要快速浏览以下前面15节的内容,很快,但不要遗漏,然后你来想一下以下几个问题:
          我学到什么、哪些是我以前不知道,现在知道的、哪些内容我记住了、哪些没有、与开始相比较我继续学习Ajax的动力有怎样的变化。
          和所有学习Ajax技术的朋友们共勉!--super translator)