随笔 - 51  文章 - 0 评论 - 210 trackbacks - 6
<2008年3月>
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345

严正声明 : 本站文章转载请注明出处.

与我联系

搜索

 

留言簿(11)

我的标签

随笔分类

随笔档案

Atlas相关

积分与排名

  • 积分 - 58801
  • 排名 - 800

阅读排行榜

Douban是2.0 社区里面比较成功的一个产品, 里面ajax技术也做得不错, 把它的源码拿来研究了一下, 它在页面上使用了jquery,  我比较喜欢它的一体式的事件处理机制,不用写很多的事件绑定代码,只需要通过一定的命名规则就可以自动给页面元素加上一些功能, 它上面几乎所有的功能都通过这个实现, 配合jquery强大的选择器,代码看起来比较简洁清晰.  下面我们就来看看它的一些核心部分. 我使用的是jquery 1.2.3,压缩之后29kb大小, 速度感觉上比以前有比较大的改善.废话不多说了,直接看看代码吧. 另外推荐一下blueprint 这个css框架,还挺好用的.

//定义命名空间
var Bowtech=new Object();

//注册全局的事件监视器.
Bowtech.EventMonitor = function(){
    
this.listeners = new Object();
}

//广播事件
Bowtech.EventMonitor.prototype.broadcast=function(widgetObj, msg, data){
    
var lst = this.listeners[msg];

    
if(lst != null){
        
for(var o in lst){
            lst[o](widgetObj, data);
        }

    }

}

//绑定所有的事件. 
Bowtech.EventMonitor.prototype.subscribe=function(msg, callback){
    
var lst = this.listeners[msg];
    
if (lst) {
        lst.push(callback);
    }
 else {
        
this.listeners[msg] = [callback];
    }

}

//取消事件绑定.
Bowtech.EventMonitor.prototype.unsubscribe=function(msg, callback){
    
var lst = this.listener[msg];
    
if (lst != null){
        lst 
= lst.filter(function(ele, index, arr){return ele!=callback;});
    }

}


// Page scope event-monitor obj.
var event_monitor = new Bowtech.EventMonitor();
//对于所有 class="j a_xxx yyy" id="xxx-123"的元素执行事件绑定, xxx-123部分用来获取元素的ID,比如一个帖子的ID,
//
 a_xxx  后面的部
//
分用来标识应用如 vote / review / blog 等.
//
绑定的事件就是 :  Bowtech.init_vote / Bowtech.init_blog 等.
function load_event_monitor(root) {
    
var re = /a_(\w+)///正则表达式获取ID.
    var fns = {};
    $(
".j", root).each(function(i) {
        
var m = re.exec(this.className);
        
if (m) {
            
var f = fns[m[1]];
            
if (!f) //如果事件处理函数不存在则创建函数对象.
                f = eval("Bowtech.init_"+m[1]); 
                fns[m[
1]] = f;//调用绑定函数.
            }

            f 
&& f(this);
        }

    }
);
}

//在文档加载完毕后将执行的方法(参见jquery文档)
//
一般来说文档加载的时候应该绑定所有的事件, 但是有一种情况例外.
//
比如 通过Ajax方法取回来的内容里面还含有动作按钮的,这时需要针对这部分功能执行绑定.
//
需要手动调用 load_event_monitor(element);  方法.
$(function() {
    load_event_monitor(document);
}
);
//注意这里的o对象是一个html 元素而非是一个jquery对象,所以在调用它的方法时应该使用$(o)函数
//
把它转化为jquery对象.
Bowtech.init_forder = function(o) {
    
var eid = $(o).attr("id").split("-")[1];
    
var fo = $("#f-"+eid);
    
var unfo = $("#unf-"+eid);
    
    fo.click(
function() {
       $(o).hide();
       unfo.show();
       fo.hide();
    }
);
    unfo.click(
function() {
        $(o).show();
        fo.show();
        unfo.hide();
    }
);
}



jQuery.fn.extend(
{
    set_caret: 
function(){
        
if(!$.browser.msie) return;
        
var initSetCaret = function(){this.caretPos = document.selection.createRange().duplicate()};
        
this.click(initSetCaret).select(initSetCaret).keyup(initSetCaret);
    }

    insert_caret:
function(textFeildValue){
        
var textObj = this[0];
        
if(document.all && textObj.createTextRange && textObj.caretPos){
            
var caretPos=textObj.caretPos;
            caretPos.text 
= caretPos.text.charAt(caretPos.text.length-1== '' ? textFeildValue+'' : textFeildValue;
        }
 else if(textObj.setSelectionRange){
            
var rangeStart=textObj.selectionStart;
            
var rangeEnd=textObj.selectionEnd;
            
var tempStr1=textObj.value.substring(0,rangeStart);
            
var tempStr2=textObj.value.substring(rangeEnd);
            textObj.value
=tempStr1+textFeildValue+tempStr2;
            textObj.focus();
            
var len=textFeildValue.length;
            textObj.setSelectionRange(rangeStart
+len,rangeStart+len);
            textObj.blur();
        }
 else {
            textObj.value
+=textFeildValue;
        }

    }

}
)

前台要用就比较简单了,  只需要这样写:
<div id="test2" class="mod">
                
<h3>
                    这里可以放标题
                
</h3>
                
<div class="j modb a_forder" id="modb-1002">
                    这里是一些主要的内容
                    
<dl>
                        
<dt>Hello world</dt>
                        
<dd>
                            hahaha
</dd>
                    
</dl>
                    这个实验在沙加的神舟本上完成
                
</div>
                
<div class="edit">
                    
<id="f-1002" class="forder" href="javascript:void(0);">[收起]</a> <id="unf-1002"
                        class
="unforder" href="javascript:void(0);">[展开]</a>
                
</div>
            
</div>

样式就省略了, 大家可以自己写, 最后发两个效果图:

收起时的样子

开发环境:  沙加的神舟本, VS2008, Framework 2.0
Tag标签: javascript
posted on 2008-03-31 15:32 沙加 阅读(3069) 评论(25)  编辑 收藏 网摘 所属分类: Javascript

FeedBack:
#1楼  2008-03-31 16:19 怪怪      
不喜欢使用class的方式, 对语义破坏太大。
  回复  引用  查看    
#2楼  2008-03-31 16:37 deerchao      
@怪怪
我也不喜欢,但是比起用rel还是强多了,rel的每个值本来就有约定的含意.
Html里没有定义与行为有关的属性,挤到原本为表现而定义的class里也是没办法的事.
  回复  引用  查看    
google group也是这样的,但是jquery 28k太大了
  回复  引用    
#4楼 [楼主] 2008-03-31 16:49 沙加      
@ASP.NET CMS
同类的js框架里面据我所知好象还没有更小的.
  回复  引用  查看    
#5楼  2008-03-31 16:56 Q.Lee.lulu      
学习下
  回复  引用  查看    
#6楼  2008-03-31 17:04 RicCC      
@deerchao
同意
几年之前htc就是很好用的东西,不过只能在IIS上跑,当时给人讲解什么是htc时用的就是: CSS是样式的呈现,决定html元素怎样显示;htc是行为的呈现,决定html元素怎样响应用户事件。
html的确是缺了这么一块,比起将onclick、onchange、onkeypress之类直接嵌到html tag中,使用class更有点AOP动态注入的概念,语义上也比较好理解,jquery也能够运用于任何http服务器和浏览器
  回复  引用  查看    
#7楼  2008-03-31 17:19 RicCC      
最近也一直在思考怎样让web应用开发更快捷方便,选定jquery是无疑的
豆瓣的这个做法跟我的方案非常吻合,不过还只是一小部分。早几天才发现豆瓣使用了jquery,并且url rewrite做的很不错,rest的味道比较浓了,不过文章讲的地方倒是没有注意,改天再看看
  回复  引用  查看    
#8楼  2008-03-31 18:00 Kevin Li      
@RicCC
也发一篇关于豆瓣使用jquery的例子 学习一下
  回复  引用  查看    
#9楼  2008-03-31 18:10 Kevin Li      
@沙加
分析的不错,收藏,希望多一些juqery和aspx结合使用的列子,因为正在学 :)
  回复  引用  查看    
#10楼  2008-03-31 19:19 侯垒      
支持一下.
  回复  引用  查看    
#11楼  2008-03-31 20:41 StillWartersRunDeep      
lz 说的 blueprint 这个css框架 在那里可以下到?
  回复  引用  查看    
#12楼 [楼主] 2008-03-31 21:09 沙加      
@StillWartersRunDeep
http://code.google.com/p/blueprintcss/
  回复  引用  查看    
#13楼  2008-04-01 00:52 怪怪      
@deerchao
@RicCC
语义更多的不是给人看的, 咱先不说class在行为与表现混淆, 以及对未来重构造成的隐患和工作量, 问题是由于class只有简单的空格分隔,这样的文档不是对智能抓取程序友好的。

说实话,这就是我为什么又佩服jQuery(确实写的很好), 在思考高度上又有点看不上他作者的原因。 类似的问题可能还有IE8的WebSlice和所谓的MicroFormat。要不JQuery自己都说是quick and dirty。

最近流行的很多牛人牛理论牛格式牛框架, 应该把"牛"字,通通换成"聪明"。 天天在说正交, 最后用了这样那样的机巧手段, 弄出一大堆非正交的玩意。

这个我比较赞同国外另外一派的做法, 自定义属性, 然后增加定义, 引用自己的命名空间。 所有的优点照样还有, 可是使用class和rel的却不在了。

我是不是又开始扮演愤愤的角色了? :P 不过说实话, 我自己干活时, 也照样乱来,自己看着都恶心。
  回复  引用  查看    
#14楼  2008-04-01 13:32 RicCC      
@怪怪
如果不注意,对class的这种运用方式的确可能带来一些问题的,但稍加关注就能解决的。

从semantic web的角度来看它指的只是内容、数据,所以它只包含html tag+内容,html tag的任何属性都不会对这个语义造成影响。而html tag的属性是html markup language的语义,明显它的具体表现形式是具体应用相关的,例如同一个class在站点a可以显示为白色背景,站点b可以显示为灰色背景,他们的目的只是给用户呈现一个可以在浏览器中浏览的视图,这个呈现动作本身就是具体应用相关的一种行为,不过可以将它做一个分流,标准的CSS样式修饰行为交给浏览器完成,具体应用相关的交互行为交给jquery完成,唯一需要注意的地方就是最好不要将这两种样式全部混合运用。
不同站点之间如果要采用semantic web方式共享数据根本不会有理解困难,至于具体如何呈现如何交互是具体应用相关的事情。

另外关于quick and dirty,用它形容一种解决方案时比较准确地中文单词应当是"简陋",jquery首页的那个准确地意义应当是"简洁"。
  回复  引用  查看    
#15楼  2008-04-01 13:42 RicCC      
@Kevin Li
jquery的学习使用官方文档和示例就足够了,如果想了解多一点看看代码就行
  回复  引用  查看    
#16楼  2008-04-01 15:00 怪怪      
@RicCC
呵呵, 本来写了上千字, 删了。 你的这种想法我过去也有, 我也受quick and dirty(无论它是啥意思)的诱惑, 不过经过不断的思考, 最终我还是否定了。否定的主角倒不完全是用className表达行为, 更多的是MicroFormat所谓的表达语义; 当然, 行为的表达也有特定的语义成分在内。

主要是几点:
1. 不要站在人能理解的角度想问题, 想想一个在访问你网站前,根本不知道你className的定义和含义的程序。
2. 不要局限于浏览器, 网页最根本的它首先是一个文档, 想想一个尽量不需要人参与的智能信息抓取和分析的程序。
3. 不要局限于目前用它来标记行为暂时够用, 想想随着信息表达丰富性的要求, 是不是一个简单的空格分隔字符串就能用最少的代价对付。
4. 不要高看人的能力, 认为稍加关注就怎么样; 当很多人参与的时候, 侵入性的做法通过人之间的约定防止彼此干扰, 这是依靠最不可靠的因素。
5. 想想人和机器白白浪费的能量, 比如字符串分割, 比如更复杂的维护class中字符串和各种内存对象的一致性的代码,现在能量、环保和猪肉涨价可是首要问题。
6. 即使最窄的范围内, 光看浏览器编程, 如果又出现一个极其好用的JS框架, 但是偏偏它采用了某些特定的className, 和你的定义有多处冲突, 又如何?
7. ....
8. ..
..

当然, 所有问题都是能解决的, 而且解决起来可能很简单, 可本来是可以不存在问题的。 尤其是当发现问题的时候, 可能已经是一堆问题堆积在一起, 麻烦变成了非线性增长的。 jQuery之流添加行为表示, MicroFormat之流添加简单语义表示, 一旦开始, 很多人就会分别的,乐观的走下去, 最后会师的时候发现一团乱麻。 事实上我认为就目前存在的应用, class attribute已经承担不该承受之重了。

可能是我杞人忧天了, 毕竟大多数应用甚至大多数文档的建立, 实际上都是面向当前的(即使看起来是风口浪尖的“技术”),这种情况下确实无需考虑太多,这也是为什么我这么疑虑重重, 还是一边自我否定,又经常采取纯dirty的做法的缘故。

只是, 凡是可以获得更大的正交性的地方, 采取了较低级的做法, 我就会变得比较敏感 :)
  回复  引用  查看    
#17楼  2008-04-02 00:02 RicCC      
@怪怪
你太能侃了

网站间基于语义整合我想3、5年之内还是很难普及开来,这么长的时间之内还有很多项目需要解决一些混乱状态

我上面回复的主要意思是说基于语义的整合应当只会关注数据,就是说使用某个网站REST风格的API,我只需要他的数据,例如豆瓣上面一本书的描述、出版社、价格,或者也会需要他的一些评论内容(目前豆瓣的API还不属于这种类型),类似于将对象序列化成xml,在这里则是序列化成html了,就是我上面说的html tag+内容
至于html tag上的属性,例如class、style、onclick、onchange之类的,它是不会适合其他网站的,其他网站也不会去分析这些内容
类似于RSS,桌面的RSS订阅器也好还是其它RSS聚合网站,主要都是使用数据,而不会理会那些跟特定网站相关的属性,最基本的就是将标题、摘要拿出来,用自己的方式呈现。REST风格的API基于语义的整合就是这种效果

以这个为基础可能就不会有你思考的那么多内容了,因为我们这里所说的语义冲突问题只是具体站点应用范围之内,而不是不同应用的整合这个范围
另外你说的新的JS框架之类的,一般框架不大会征用具体的class name或类似概念,所以是否冲突取决于如何使用这些框架,并且象jquery这样它是有上下文这个概念可以用来区分,有一点点类似作用域。另外具体的应用也不必非得将有冲突的东西运用在同一个地方,例如jquery和prototype,一般是选择其中之一

另外再从整体的角度考虑,如果使用这样的思想提供一个框架或工具集,能够极大的提高开发效率;让html内容、css样式、客户端交互的行为比较彻底的分离,让团队中不同角色的职责不再交叉;让client与server更进一步的分离,而不是象目前各种视图引擎,站在服务器端却一直力求对客户端的良好控制,怎么看也有点矛盾。能达到这个效果那是何乐而不为,是不。
并且这样也不与REST、semantic web冲突
  回复  引用  查看    
#18楼  2008-04-02 10:39 怪怪      
@RicCC
呵呵, 这样, RSS文档(或者其它格式的XML)与HTML文档是分立的; 问题是尤其xhtml本身就是xml,很多时候可以重用, 分立让我们失去了这个机会,增加了不少工作量。 比如RSS有定义, 那么比如苹果销售行业的数据发布暂时没有定义又怎么办呢? Micro Format在某些方面就是要解决这样的问题, 而我觉得它用class来添加语义是不合适的。

在上述范围以外, 纯网站和网页的考虑, 我不喜欢主要是因为我说的人的因素。 哪怕有时候一个人干, 还有不严格的情况出现。 比如一个xxx本来用来描述样式, 我就是忘了, 结果又给用于比如行为描述了; 这种情况,你可以赖我干活不认真,或者没有仔细看项目开始时做给人看的命名参考,但干嘛不直接避免呢?

或者,在合并两个项目时, 产生冲突有如何呢? 如果是采用dc:proerty="x"这样的方式, 即使我一时错误, 也不会影响到已有的东西。 当然,合并项目时,可能会有重复, 但鉴于定义严格的xml比空格分隔的xml好处理,这种情况解决起来工作量会比较小。同时, 可以用现成的xml检查工具让机器替我们检查文档的合法性。

其实, 我们把class内部的猫腻放大来看, 这就相当于纯text格式(比如csv)和xml/SGML之间的差别。 所以到底怎么做,就像你说的, 至少是需要权衡一下的;而我个人则在理念上(而不是行动上), 倾向于直接统一起来, 采用更严格的方式:)
  回复  引用  查看    
#19楼  2008-04-02 12:21 RicCC      
@怪怪
RSS针对的领域是特定的,所以它的消息格式被抽取为一种标准,其它特定领域一开始只能是采用各自的消息格式
我考虑过的方案有几个,例如使用class、自定义属性、一个html tag中的内容、一组html tag,都无法解决冲突,而基本只是取舍于用类xml的描述,还是你说的用空格分割的纯文本语言,以及可行性、合理性的大小问题,并且可以肯定的是不存在趋于完美的优雅方案,也就是你说的"最后用了这样那样的机巧手段, 弄出一大堆非正交的玩意"
  回复  引用  查看    
#20楼  2008-04-02 13:22 怪怪      
@RicCC
感觉咱俩的讨论, 每次咱们重合的点不多, 要是所有的开发人员都住一起就世界大同了呵呵 :)

但是你不认为, 自定义属性加dtd, 至少可以:

1. 至少不存在围绕class属性内部文本产生的非正交。
2. 可以更高效的使用已有的xml解析工具,可以直接使用通用的检查工具。
3. 由于1、2, 就拥有了自动化、而不是基于对人的要求的严格性。
4. 为无人工干预的智能分析程序提供了一个基础。

趋于完美的方案是不存在的, 但是我们总能提高正交性, 至少不会反而引入非正交的因素。 我认为使用class或者rel的方案, 肯定在很多情况下是有优势的, 问题只是咱们要意识得到付出的代价。

这样说, 应该就能达成共识了吧。
  回复  引用  查看    
#21楼  2008-05-26 10:13 scotoma      
看上面2位的讨论我晕了.....
  回复  引用  查看    
#22楼  2008-06-16 15:39 su27 [未注册用户]
我是在douban维护js的。需要指出的是,后面那段jquery扩展的代码来自Zeal blog,见http://www.zeali.net/entry/561
  回复  引用    
lst = lst.filter(function(ele, index, arr){return ele!=callback;});

取消事件绑定,貌似在豆瓣里从来没用过嘛,
另外,那个filter有点莫名其妙了,有人解释下吗?
  回复  引用    
#24楼  2008-07-10 17:58 微蓝 [未注册用户]
在做类似的东西,觉得用着不太爽,页面是干净了,如果是不熟悉的人开发或者修改,要浪费好多时间呀...

  回复  引用