<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title></title>
    <description></description>
    <link>http://kkfc.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>AJAX developers continue migrating to unobtrusive </title>
        <author>KKFC</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kkfc.javaeye.com">KKFC</a>&nbsp;
          链接：<a href="http://kkfc.javaeye.com/blog/208199" style="color:red;">http://kkfc.javaeye.com/blog/208199</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Posted by Matthew Bass on Jun 24, 2008 01:31 PM<br /><br />Community<br />    Java<br />Topics<br />    Javascript<br />Tags<br />    AJAX<br /><br />Unobtrusive JavaScript is an emerging technique that separates JavaScript from HTML markup. This is quite similar to the separation between styling and HTML that came about with the creation of CSS in the late 90s. For example, obtrusive JavaScript would add an onClick handler directly to an input field like this:<br /><br />&lt;input id="field" onclick="alert('hello')" /><br /><br />Unobsutrive JavaScript waits until the page has finished loading before hooking up the event handler to the input field:<br /><br />&lt;script type="text/javascript"><br />  Event.observe(window, 'load', function() {<br />    Event.observe($('field'), 'click', function() {<br />      alert('hello');<br />    };<br />  });<br />&lt;/script><br /><br />&lt;input id="field" /><br /><br />This keeps the HTML (our input tag in this example) clean and provides the developer with a single point of reference for debugging JavaScript code. Unobtrusive JavaScript is typically stored in external .js files as opposed to being embedded inside &lt;script> tags in the HTML page itself. While the unobtrusive example here takes up more lines of code, larger blocks of JavaScript will generally end up being clearer and more concise when made unobtrusive.<br /><br />Some other benefits of unobtrusive JavaScript include:<br /><br />    * Separation of concerns: the behavior layer is separated from the content and presentation layers<br />    * Easier handling of browser inconsistencies<br />    * Concise code that's easier to read<br /><br />When used with open source libraries like Prototype, unobtrusive JavaScript gets even easier to create. There are even frameworks specifically designed for taking obtrusive JavaScript and making it unobtrusive.<br /><br />Low Pro, for example, adds several useful helper functions to Prototype, dramatically improves access to the browser's event model, and provides a behavior library that makes it a breeze to hook up unobtrusive triggers. Our previous example can be written in Low Pro like this:<br /><br />&lt;script type="text/javascript"><br />  Event.addBehavior({<br />    'input#field:click' : function(e) {<br />      alert('hello');<br />    }<br />  });<br />&lt;/script><br /><br />&lt;input id="field" /><br /><br />Behaviors are automatically hooked up after the page finishes loading. Additional behaviors can be added using CSS selectors to pick elements for triggering.<br /><br />With the number of AJAX-enabled web sites steadily increasing, JavaScript is becoming a much larger part of web application development. Keeping JavaScript unobtrusive makes it much simpler to develop flashy features. It will also make future maintenance of these web sites much easier and more cost effective.
          <br/>
          <span style="color:red;">
            <a href="http://kkfc.javaeye.com/blog/208199#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 26 Jun 2008 13:12:24 +0800</pubDate>
        <link>http://kkfc.javaeye.com/blog/208199</link>
        <guid>http://kkfc.javaeye.com/blog/208199</guid>
      </item>
      <item>
        <title>构建基于慢速网络的实时应用</title>
        <author>KKFC</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kkfc.javaeye.com">KKFC</a>&nbsp;
          链接：<a href="http://kkfc.javaeye.com/blog/208063" style="color:red;">http://kkfc.javaeye.com/blog/208063</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          HTTP连接往往被考虑为慢速的。通常不会考虑在之上构建所谓实时应用。然而玩过网络游戏的人都知道，除了类似于CS之类实时性要求非常高的外，延迟在500毫秒以下是可以继续游戏的，而750毫秒以下也可以勉强凑合，如果放到网页中，需要用户之间实时交互的应用延迟在1秒左右完全可以接受。据我的检测，国内绝大部分ISP到用户桌面的延迟远远小于这个数字。技术催生需求，这种情况下我们可以考虑利用这些特性来做一些有趣的应用。那么在这种情形下，我们该如何编写具备实时性的客户端代码？<br /><br />在前面讨论的双向流模拟同步HTTP连接中，我提到了Bidirectional-streams Over Synchronous HTTP (BOSH)。然而经过验证，这种通用的设计在项目设计中并不吃香。原因之一是过于复杂，无论是服务器端还是客户端。如果有成熟的服务器端还好，否则要自行实现双通道 HTTP连接的控制，这其中设计大量的低级Socket以及线程操作，相当需要技巧。在此之上，如果有更复杂的伸缩性需求，整个实现将会使梦魇。实现的复杂性同样会出现在客户端。客户端需要控制消息的拆包、封包，更高级些，能够精巧的控制Http连接（基本上是XMLHTTP的连接）个数。这些也需要相当的功底。<br /><br />有一种更加简单，并且容易实现的方式，经过我的实验，能够完美的应用到新的应用中，能够满足实时性的要求。基本原理就是：<br /><br />当上一个请求返回之前，不要发起下一个请求。一旦上一个请求返回，立即发起下一个请求。<br /><br />这是一个非常简单的设计。但非常有效。写成代码就是：<br /><br /><br />function forever_request() {<br />new Ajax.Request('url', {onCompleted: function(response) {<br />//do your stuff<br />forever_request();<br />}})<br />}<br /><br />这个确实很简单，但这不是构建实时应用的全部。实时意味着，大多数的用户操作需要广播到所有当前可见用户的桌面上。理想情况下，界面只是一个哑终端，只是如实的表现服务器端传递过来的消息。forever_request方法有两个作用：用来发送消息以及获取服务器响应。增强后的 forever_request方法就是：<br /><br /><br />function forever_request() {<br />new Ajax.Request('url',<br />parameters: pendingMessages.pickAll().serialize();<br />{onCompleted: function(response) {<br />responseMessage(response.Text);<br />forever_request();<br />}})<br />}<br /><br />responseMessage方法负责对从服务器端收到的消息进行展示。例如，某一次的请求中，他得到了类似于userA MOVE 3,4的消息，客户端只需要将userA移动到3,4的位置。<br /><br />pendingMessages负责收集所有的用户操作。为了节约网络流量，并非每一次的用户操作都将发起一次网络请求，而是将其压入到 pendingMessages中。例如，在3秒内，用户说了一句话，点击了另外一个用户查看详细信息，pendingMessages中就有了类似于如下的记录：<br /><br />SAY 大家好啊<br />GETINFO userB<br /><br />在下一次请求，这些消息被发送到服务器端，用户可以得到响应。<br /><br />这是基本的实现了。可以看到这种实现非常简单，任何一个具备基本javascript技巧的人都可以在半天内写出实现来。然而这仍然不是全部。构建基于慢速网络的实时应用需要我们对流量、并发数非常在意。只要用户察觉不出来，尽可能少的数据，尽可能少的与服务器交互。现在带宽资源非常昂贵——共享 10M与独享10M之间的价格差别可能让你咂舌。我们可以引入ConnectionManager对forever_request方法进行统筹调用，例如，当用户不怎么活跃（Idle）的时候降低更新量，尝试将更多的message pending并发送，等等。
          <br/>
          <span style="color:red;">
            <a href="http://kkfc.javaeye.com/blog/208063#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 26 Jun 2008 00:40:58 +0800</pubDate>
        <link>http://kkfc.javaeye.com/blog/208063</link>
        <guid>http://kkfc.javaeye.com/blog/208063</guid>
      </item>
      <item>
        <title>非结构化形式表现结构化内容</title>
        <author>KKFC</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kkfc.javaeye.com">KKFC</a>&nbsp;
          链接：<a href="http://kkfc.javaeye.com/blog/208061" style="color:red;">http://kkfc.javaeye.com/blog/208061</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          关于可用性设计，说到底是对用户操作心理期待的把握。如果操作反馈低于用户期待，感觉会很差；如果正好符合期待，用户感觉会很平滑；如果超出用户期待，做得比用户想象的更多，大多数用户都会惊喜并很快接受新的方式。<br /><br />界面的表现形式占据了很大分量。在过去C/S年代，几乎没有非结构化内容。界面约等于数据库表，无论是外观或是功能。而随着Web2的介入，越来越多的应用引入了非结构化形式来表现结构化内容，以达到更好整合信息的目的。关于非结构化形式，有一些非常明显的特征：<br /><br />* 使用用户用户的语言而不是计算机语言作为界面。非常典型的如使用“昨天”、“前天”取代2007-7-29等计算机友好时间。<br />* 使用松散布局而非紧凑布局。几乎绝大部分成功的Web2应用都拥有独一无二过目难忘的布局和色调<br />* 几乎不使用Grid控件。作为C/S年代代表的Grid, 几乎每个写代码的人都会用到。然而在成功的消费类应用的中，几乎没有人使用Grid, 如果需要使用，也是美化过后，或者采用能够表现对应单元格属性的表现方式。例如一条 张三 男 记录很可能被表现为张三的小图标以及象征性别特征的图片。<br />* 尝试将更多的信息而不是更少的信息放在首页。对于常规应用的开发者而言，这几乎是噩梦。因为这意味着信息整合。Portal就是这类问题的解决方案。然而看看Campfire的basecamp, 通过将常用的信息摘要放在首页，用户几乎不用进行额外的点击。<br /><br />然而，非结构化形式并非意味着凌乱。凌乱的排版和信息堆砌给用户一种暗示：我可以在这里为所欲为。破窗户理论在这里同样有效。这可以解释为什么绝大多数看着很乱的聊天室内容也很乱。真正有意义的非结构化信息及其组织方式完全来自于真实用户的真实体验。<br /><br />得出的结论是，结构化的表现形式造出的软件像工具，因为大多数人对工具的理解就是灰色、规整、耐用，同时乏味。非结构化表现形式造出的软件像精致的消费品，美观舒心。值得一提的是，Dell公司已经开始在沃尔玛摆起了柜台卖电脑。笔记本这个曾经商务人士标榜的东西，已经成为消费品。我们现在正在为客户开发的项目中，已经加入了很多消费类程序才有的UI特性。从长远看，消费品将是不可避免的终极目标，因为用户不是机器。<br /><br />ChinaUI(http://www.chinaui.com)上每天都有新的设计作品产生，有相当大的数量集中在B/S系统的产品上。B/S给软件开发带来巨大改变，但与此同时进行改变的是用户的审美品位的提高。你无法再将windows经典的窗体颜色应用到绝大多数Web应用中，美工开始变得重要。客户口味越来越奇怪，很多时候一个项目的交付被卡在美工上，客户喋喋不休的说这个颜色/那个颜色不喜欢。从国内外已经出现的软件界面设计公司，可以看到这样一个趋势：用户对软件的需求已经不仅仅满足于实现功能，对软件的体验开始变得同样重要。回忆一下，《冒牌天神》中发邮件的界面，一些电影中显示人员档案的界面，《黑衣人》中的海关电脑界面。随着软件的发展，这些界面相信也会出现在实际的软件中。<br />RIA应运而生。Macromedia公司的Flex(http://www.macromedia.com/software/flex)，开源的 Leszlo(http://www.openlaszlo.org)，都是这方面的代表。Flash经过多年的发展，已经从典型的动画格式开始向着一种用户友好的表现形式发展。从Macromedia官方公布的资料看来，已经有一些成功的商业应用采用了Flex，用户体验相当好。而从我给一些客户演示 laszlo的实例来看，Laszlo“增加了对Web应用的期待”。这种期待显然是界面、操作感觉的期待。RIA, Rich Internet Application, 在我看来一个最为体贴的解释就是“丰富客户体验的Web应用”。Rich在这里，所指并不仅仅是提供开发者丰富的控件，更重要的是给客户丰富友好的体验。
          <br/>
          <span style="color:red;">
            <a href="http://kkfc.javaeye.com/blog/208061#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 26 Jun 2008 00:37:56 +0800</pubDate>
        <link>http://kkfc.javaeye.com/blog/208061</link>
        <guid>http://kkfc.javaeye.com/blog/208061</guid>
      </item>
      <item>
        <title>Customizing Existing YUI Components</title>
        <author>KKFC</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kkfc.javaeye.com">KKFC</a>&nbsp;
          链接：<a href="http://kkfc.javaeye.com/blog/208059" style="color:red;">http://kkfc.javaeye.com/blog/208059</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Let’s begin by looking at how you would go about creating your own custom version of an existing YUI component.<br /><br />For example, a server-side transaction may take quite a while and you may want to signal to the user that it is in progress. The YUI Panel component is a handy way to produce a floating pop-up window. Panel serves many purposes, though, so it is not specifically tailored for this "loading message" implementation. You will need to implement something like the following to have your "loading-panel" pop-up displayed:<br /><br />if (!loadingPanel) {<br />    loadingPanel = new YAHOO.widget.Panel('loadingPanel',{<br />        width:"100px", <br />        fixedcenter: true, <br />        constraintoviewport: true, <br />        underlay:"shadow", <br />        close:false, <br />        visible:false, <br />        draggable:true<br />    });<br />    loadingPanel.setHeader("Loading ...");<br />    loadingPanel.setBody('&lt;img src="loading.gif" />');<br />    Dom.setStyle(loadingPanel.body,'textAlign','center');<br />    loadingPanel.render(document.body);<br />}<br />                    <br />loadingPanel.show();<br /><br />Variable loadingPanel holds a reference to the Panel instance; once this instance is declared, later popups just reuse the existing instance and are therefore faster and less resource-intensive. But including implementation code like this inline in every page you need is a waste of time (because any change needs to be made in multiple places) and, for your users, a waste of bandwidth. Let’s trim this down by turning it into a custom version of YUI’s Panel.<br /><br />In the first sample, you can see this same code both as inline code and as a reusable custom component. The custom component would normally reside in a separate file that would be included in all pages. I defined it in the page in this sample to make it easier to compare the inline syntax with the library-style syntax. The page uses the YUI Loader to load components.<br /><br />The YUI Library takes care to avoid using global variables that might collide with other libraries. In fact, the whole library is packed in the properties of a single global object called YAHOO; thus, as long as everybody keeps away from the YAHOO global variable, there should be little risk of collision. We can do the same for our own libraries because, though we control our own code, in the hopefully long life of that code other features might be added. Mashups, ad providers and others might use the global namespace carelessly and inadvertently break our application. Thus, the first step is to call the YAHOO.namespace static function to create an object space for our own library.<br /><br />YAHOO.namespace('SATYAM');<br /><br />This will create a property SATYAM under YAHOO. YUI uses only a very few names under YAHOO; you can keep safe by simply avoiding any of those few. None of those names uses anything but lowercase characters so any or all uppercase letters will keep you even safer.<br /><br />You could create your own namespace by simply assigning an empty object to YAHOO directly, but the namespace function first checks to see if the namespace exists and preserves it if it does exist. If you have several library files, you will likely want to load more than one of them in any page. Each of those library files will want to make sure the new namespace exists but while preserving it if it has already been created by another of your library files.<br /><br />Once you have your own branch under the YAHOO namespace, you define the constructor for your custom loading panel:<br /><br />YAHOO.SATYAM.LoadingPanel = function(id) {<br />                <br />    YAHOO.SATYAM.LoadingPanel.superclass.constructor.call(this, <br />        id || YAHOO.util.Dom.generateId() , <br />        {<br />            width: "100px", <br />            fixedcenter: true, <br />            constraintoviewport: true, <br />            underlay: "shadow", <br />            close: false, <br />            visible: false, <br />            draggable: true<br />        }<br />    );<br /><br />    this.setHeader("Loading ...");<br />    this.setBody('&lt;img src="loading.gif" />');<br />    YAHOO.util.Dom.setStyle(this.body, 'textAlign', 'center');<br />    this.render(document.body);<br />};<br /><br />Using YAHOO.lang.extend<br /><br />Compare this code with the previous code box; you’ll note that it’s quite similar. You might be wondering what superclass is. That is part of the inheritance mechanism provided by YUI’s extend method. After you declare the constructor for your new object, you call extend:<br /><br />YAHOO.lang.extend(YAHOO.SATYAM.LoadingPanel, YAHOO.widget.Panel);<br /><br />The sequence of first defining the constructor for the new object and then extending it with the base object may seem counterintuitive when read in a linear fashion. When you think about the sequence of execution, though, it makes perfect sense: The new object is defined by what will become its constructor, but the constructor itself does not get executed immediately. The extend function does get executed immediately, so by the time a new LoadingPanel object is instanced, our new object has already been extended.<br /><br />After extending the new object, this will refer to both the new object and the base object. Our new object inherits from Panel methods such as setHeader, setBody, render as well as properties like body that can then be accessed via this.<br /><br />Sometimes we might want to override a method of the base object. Indeed, we have already done that — by declaring the constructor of our custom object, we are overriding the constructor of the base class. The extend function places all original methods under a property named superclass, so you still have access to all the functionality of the original method. The first thing we do within the constructor of the new object is to call the constructor of the base (superclass) object and, since that is a static function, we need to adjust the scope of the superclass constructor so that it runs in the scope of our Loading Panel’s constructor. We use method call of JavaScript native Function object, which takes the first argument as the execution scope of the function called and passes it the rest of the arguments.  The YUI Librarydocumentation often uses the term "class" or "superclass" as a carry over from classical programming languages. JavaScript doesn’t actually have classes (objects are derived from one another and inheritance is prototypal instead of classical)  but the word "class" is loosely descriptive of the mechanism.<br /><br />Calling the base class constructor does not need to be the first thing to do in the constructor of the new class; in fact, it might not be done at all, depending on the object you are defining. You are free to do it if and when you choose. The sequence of first defining the new constructor and then extending it before trying to create an instance of that object is mandatory.<br /><br />Using the object we just created is easy:<br /><br />if (!loadingPanel2) {<br />    loadingPanel2 = new YAHOO.SATYAM.LoadingPanel();<br />}<br />loadingPanel2.show();<br /><br />We simply create a new instance if none exists, and then we show it. We don’t use the optional argument, a string that would become the id of the HTML element that our widget will create. Since we don’t care to, we leave it out and let our function make one up via YUI Dom’s method generateId.
          <br/>
          <span style="color:red;">
            <a href="http://kkfc.javaeye.com/blog/208059#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 26 Jun 2008 00:35:06 +0800</pubDate>
        <link>http://kkfc.javaeye.com/blog/208059</link>
        <guid>http://kkfc.javaeye.com/blog/208059</guid>
      </item>
  </channel>
</rss>