Xi's profile风中的甜椒PhotosBlogListsMore Tools Help

Blog


    November 24

    偶然与必然,因果与相关

    每天晚上都回做梦是必然的,
    但能记起梦境是偶然的。
     
    不知道是因为从梦中惊醒才记起了梦境,
    还是因为流连于梦境才从梦中惊醒。
     
    November 22

    甲流与2012

    睡在床上的时候就容易胡思乱想。正好手机报说到英美的甲流有了一些变异,已经能够抵抗达菲;同时在中国境内也有猪感人了甲流;甲流疫苗似乎也没有挡住甲流的肆虐。。。
     
    这种全球性的大规模传染病,如果具有了以下两个特征将变得特别可怕:传播途径简单多样,病毒变异迅速。目前看来,甲流病毒的变异速度还不是那么快,但是有增加的趋势。同时,如果猪也能感染甲流,进而受感染群体扩增到人、畜、禽,以及其他哺乳动物,后果将不堪设想。
     
    未来的一两个月将显得比较关键,注射疫苗已经逐渐进入高峰。如果这些疫苗是有用的,甲流病毒的变异速度还不是那么的快,甲流将在这一两个月中消失。反之,如果疫苗的注射还是不能低档甲流的扩张,那么最有可能的是甲流病毒发生了变异,暂且不说变异后病毒的毒性是否增加,要重新研制新的疫苗也需要花一两个月的时间。如果甲流的变种不止一种,那事情就会更加复杂了。
     
    人们对2012的猜想有很多很多,但是也不能排除这场瘟疫也有可能是2012的罪魁祸首。当然有一个前提就是,2012真的会是世界末日吗?我不愿看到这种可能。瘟疫来的不够壮烈,而且更加残忍。因为人们不是同归于尽,而是殊途同归:不是被病毒折磨死,就是被悲痛折磨死。
     
    如果地球只有2年的阳寿了,我们要好好珍惜眼下的时光;如果2012是个玩笑,我们同样要好好珍惜每一天。
    November 14

    以李开复之名

    以开复之名,说两件事情。

    前天中午去万人排队领开复先生演讲的票,本来通知发200张票。可是到了万人,被告知今天发95张。排队的同学大为不满,学生会被迫改成发票140张。其实,这个时候我已经知道我们没有希望了,因为去得太晚,在140人之外了。但是还是留了下来作最后的争取,为了200张票作最后的争取。没想到留下来后见证了最后的精彩,票数又从140张减到了100张,然后又从100张涨到了140张。当票数减到100张时,大家愤怒了,学生会主席无法解释票的去向,搪塞,沉默,失色。

    两件事情:一是,中国官僚的腐败也许就来源于学生工作:他们知道听领导的话,上级的话,没有原则,不为同学争取利益;他们知道和其它高级部门搞好关系,可以有事没事的向后勤等部门送票;他们知道内部利益高于外部利益,可以把80张票内部消化;他们还可以利用清华女生来当挡箭牌,因为前一天是女生发票,所以多发出去了70张票。二是,同学们也太把李开复当腕了吧,居然这么多人为了他而疯狂(我只能作为不明真相的群众在围观),不知道他们是把他当作成功人士呢,名人呢,还是明星。

    November 01

    雪·冰·舞

    今天发生两件事,一件是下雪了,当然不是我在下;另一件是中国杯世界花样滑冰大奖赛之表演专场落幕,当然也不是我在表演。

    2009年的第一场雪,比以往时候来的更早更猛了一些。据北京的老人们说,这是距1987年来最早下雪的一次。至于为什么,有的人说是为了缅怀钱老的逝世,也有人说是为了庆祝国安的夺冠。不管怎样,这场雪已经创造了纪录,是我在北京所经历的最大雪。看到别人拍着雪景,自己也想要去尝试。无奈相机色彩不够饱满,拍的竟都是苍茫大地,只有包容万物的胸襟,却无色彩斑斓的精彩。

    昨天看到申雪赵宏博复出夺金的新闻,于是今天有了兴致去看了大奖赛的表演专场。去过现场看比赛人都知道,在现场肯定没有在家看电视看得舒服,除了能感受到那种气氛,热烈而激扬的气氛。而且今天我感受到的不仅仅是这些,通过望远镜,我能很清楚的看到选手们脸上的表情,已经流露出来的那种专注和敬业的精神。如果说所有人在能力上都是平等的,那么能胜出的只有那些把自己的全部投入进表演的人。也许有人被申雪最后的换装所雷到,可那正是为了喜剧效果的需要。临走的时候,一个小女孩(应该比我小一些)给她妈妈打电话,兴奋的说见到活的申雪赵宏博,那个激动啊。

    有雪有冰有舞,这才是人生。

    October 31

    下潇湘(3)-中南大学

    虽然说湘雅医院也隶属于中南大学,但是由于历史的原因,在地理位置上他们差的很远。需要补充一下的是,在去湘雅医院之前,我居然不知道南湘雅,北协和的说法,真是孤陋寡闻啊。随着咱们国家医学的快速发展,湘雅医院也不断的在扩大,如今已经有三个院区,而且还都附带研究院。我们访问的医学遗传学实验室就在最老的院区。
     
    这个老院区坐落在长沙市相对繁华的地区,湘江东岸。而当地人更习惯叫湘江东岸为河东。中南大学校本部却在河西,于是这次踏访中南大学就需要从河东到河西了。
     
    虽说湘雅老区在较繁华的地区,但置身于商务区中,除了酒店、洗浴城、KTV、酒吧之外,连一个街边的小摊、小饭馆都很少见。而河西的中南大学附近就是另一番景象了。与中南大学毗邻的有湖南大学、湖南师范大学。这里是年轻人的世界。一路上就能感受到年轻的气息,生命的活力。人头攒动,生意兴隆。
     
    感谢羽一路专业的导游讲解。到达中南大学的时候,天色已晚。在视觉的朦胧中,形象的讲解下,想象会插上轻快的翅膀飞得更高更远。羽在中南已经4年多了,她见证了部分中南大学的历史。这座学校正在飞速的发展。中南大学环境的优雅是任何一所北方的高校所不能比拟的。背靠着岳麓山,让校园有了层峦叠翠的后花园;前临着湘江,让学子们在炎炎夏日有了江风带来的阵阵清凉。可惜天色已晚,没有机会到岳麓山上去看那满山的红叶。就算看不到红叶,在久违的山峦中,远离城市的喧嚣,呼吸一下新鲜空气也是十分美好的。
     
    October 25

    下潇湘(2)-从步行街到橘子洲

    还是要多谢镭的陪伴,我们坐上了2路汽车。长沙的司机开车之彪悍是全国少有的。湘军不仅打战厉害,开车也是很厉害的。急起急停急转弯,需要时时刻刻警惕着,否则就可能成为牛顿运动定律的实验品。不过,公共汽车倒成了减肥的最佳场所。

    言归正传,汽车到了长沙城最繁华的地方,我们下了车。和其他城市一样,商业区除了人多就是商店多。而长沙与众不同的是,这里酒吧也很多。挨着步行街的太平街就是著名的酒吧一条街,虽然没有北京什刹海那里人潮涌动的景象,但也初具规模。其实,很多更大更炫的酒吧根本就不愿屈身于太平街,而是找到了更好的地段。

    我们快9点了才到达这里,而这里的繁忙才刚刚开始。因为没有吃晚饭,我们先去了长沙的小吃街,品尝了锅饺、酸梅汤、豆皮。锅饺其实就是锅贴,不过这里的锅贴色香味俱全,再加上那独特的辣椒酱,或者可以说是辣椒汁,更是有湖南特色。酸梅汤好像也有一些不太一样,只是喝得太快,没细细品尝。倒是很便宜。豆皮,从这个名字很难猜想到其内容。其实他是以豆、米、浆拌鸡蛋做皮,以糯米为馅,色泽金黄透亮,外脆内嫩。

    吃罢,我们就向橘子洲进发。不知道当年毛主席是怎么到达橘子洲的,我们选择了比较不浪漫的做法,从大桥上走过去。湘江一桥年代已久,双向四车道,为行人留下的也就不多了。可是长沙的电动车成灾,威胁着行人的安危,走在着大桥上也提心吊胆的,尤其是当你遇到会走S路线的电动车。湘江的水的确走得太早,虽然每年湘江都会断流,可是现在才10月,长沙最美丽的季节,湘江却露出突兀的河床,真是大煞风景。从桥上下去到橘子洲头还有3.4公里,无奈只能作罢。也为下次再去长沙留下了借口。

    从橘子洲回来,长沙的夜市也开始了。这时候已经是晚上11点了。在北方即使是夏天,11点也是小商小贩收摊的时间。在这个季节大街上已经几乎没有太多的行人了。正是他们及他们造就了不夜的长沙。

     

    October 23

    下潇湘(1)-长沙初识

    飞机习惯性的晚点了。老板在抱怨国内航班就是不如国际航班,在下午的高峰期,晚点已经不再是五百年修来的缘分了。
     
    Lei,一个帅气的小伙已经在机场等了我们很久了。举着一个大牌子,上面写着老板的名字,很专业。可是黄花机场有两个出口,立在另一个出口的大牌子却也无法让我们看到。
     
    出了机场,长沙潮湿的空气让我有了重庆的感觉。刚下完雨,小车外壳上还有残留的雨滴,晶莹剔透。也许是潮湿的原因,我总觉得南方的城市没有北方的城市干净。尘土受不了分水的纠缠,从空中降落到道路旁、树叶上。。
     
    一路上,我们聊到了湘江的水,河东和河西的中南大学校区,省政府前的湖底隧道,还有那弯了n道弯的浏阳河。长沙也是一个有水的城市,我总觉得有水的城市就会比较有灵性,使得这座城市的生命力更加的旺盛。比如,湖南电视台,大家所熟知的芒果台标就在这里诞生。快男超女,引得多少帅哥美女尽折腰。
     
    当然,还有不得不提的长沙娱乐业。这里的人比较会享受,不管是有钱的还是没钱的,都在享受着娱乐的生活。随处可见KTV,洗脚城,洗浴中心,酒吧,歌舞厅。。而且娱乐的时段非常之多,一天n个时段,n>3。还有夜市夜宵,晚上11点才开始,至于几点收摊,也许看店主的兴致吧,反正他们是需要为这座不夜城做贡献的。
     
    在这样的城市搞科研,我真的很佩服,他们需要多么高的定力啊!
     
    October 07

    中原行(8)--东湖、黄鹤楼、江汉路&江滩

    记得我在写杭州西湖的时候提到东湖之大。不错,东湖真的很大,大到不能一一走到。上午,几人相约打车来到湖边。虽然我一直觉得上午不是游湖的最好时间,但是不能扫了大家的兴致。其实,人多的好处就是大家可以聊聊天,除了学术之外,还可以八卦天下的所有。阳光,柳条,波纹,还有垂钓的人们。远离了城市的喧嚣,比西湖更加幽静安逸。没有自行车,绕湖一圈,估计需要一整天的时间。为了吃午饭,我们找了条近道,找了个饭馆。

    虽然中午吃了武昌鱼,但是仍然意犹未尽。顶着太阳到了黄鹤楼。当然没有那么夸张,都是在打的。跟着大部队的好处就是可以拼车,比两个人划算。而且武汉打的的确很便宜,和重庆差不多吧,不过人家没有罢工。

    黄鹤楼在长江边上。其实那天晚上火车经过长江大桥之后,就奔着这来了。但是那天,一来夜色朦胧,二来没有心理准备,便错过了。在武汉的行程就比在开封轻松多了。于是,我们一定要把整个景区逛透。写到这里,想起一件事:如果不懂历史,到这些地方来游玩,恐怕就只能看看风景,而不能体会其内涵;当然也可以听导游吹得天花乱坠,但是一定要小心,不要被忽悠了。所以,游行之前最好能补点课,免得浪费门票了。还好,我们一行人中有pt这样的大才子。每到一处,他都似曾相识,都能说出那么些故事来。登楼的好处就在于可以望远。虽然比不上杜甫一览众山小的胸怀,孔子登泰山而小天下的气魄,我也很喜欢站在高处,俯视整个大地,哪怕是武汉城的一部分,哪怕是长江大桥的一角。

    晚上,为了寻觅武汉的著名小吃,鸭脖子,我们“不远万米”从武昌来到了汉口。江汉路算是武汉最著名的商业街,犹如北京的王府井,上海的南京路,成都的春熙路,重庆的解放碑。当然,逛街不是我们的兴趣所在,我们来到了长江边上:江滩。虽然这里是长江之滨,可是比不上黄浦江边的外滩,没有商业的运作,只是市民休闲的场所。甚至没有明亮的路灯,使得碰巧快没电的相机失去了它的作用。江的那一边就是繁华的武昌,但是在宽阔的长江的对岸看来,霓虹灯显得那么柔弱,经不起距离的折腾。在江边狂喊几声之后,我们也该打道回府了。

    至此,中原之行也告一段落了。

    中原行(7)--华中科技大学、武汉大学

    第二天就和大部队汇合了。虽说是来开会的,也不可能不到处走走。

    华中科技大学,虽然在这里开会,但是没有怎么好好逛过。人们对于这种唾手可得的东西期望往往不高。唯一能留下映象的可能就是桂花了。金秋十月真是桂花盛开的季节。与哈工大的紫丁香,清华的紫荆不同,这种白黄色的花正好是紫色的补色,花朵不是那么艳丽,但是花香沁人心脾。还让我想起莲子桂花羹的味道。徜徉于园中,真是舍不得离去。华科的校园,和清华的校园相似,规划得很好,道路横平竖直,就是路更窄,间隔更密。树木茂盛,比起北国的清华,更显得生机,显得有朝气。途中经过一处古老的电影院,露天的石阶,门口还贴着影讯,想必在这看电影更是别有情调吧。

    如果说华科和清华相似,武汉大学就可以和北大媲美了。当然用北大和武大相比,并不是有意贬低武大这所世界上最美丽的大学。武汉大学的美在于她不拘一格,武汉大学的美在于她古今融合,武汉大学的美在于她山水交错。目睹了武汉大学牌楼“国立武汉大学”,感受到她历史的悠久;目睹了武汉大学那依山而建的早期建筑,感受到了她幽静的学习环境;目睹了武汉大学那相映成趣的行政主楼和操场,感受到了她在新世纪的生命力。可惜不是在4月,无法目睹樱花盛开的校园,只能为下次相遇留下一个借口了。写到这里,不免有一些伤感,越是美丽的东西,越难用语言描绘。不管是转瞬即逝的,还是永久不灭的。唯一的解决方法,恐怕就是珍惜了。

     

    中原行(6)--武汉初见

    奔向火车站之后,我们就失望了。由于国庆出游高峰,火车晚点,一个多小时。其实晚点我们不怕,怕的是这趟火车到了郑州之后,我们要换的另一趟火车不等我们。于是,祈祷。

    事情的发展并没有想象的那么坏。当我们在站台上等属于我们的头文字K的火车的时候,一列驶来的头文字D的火车的目的地也是郑州,而到达的时间要早1个小时。我们悄悄地和站台上的工作人员说明情况,你们的火车晚点导致我们这么大的损失,是不是可以让我们上这列头文字D呢。为了不扩大事端,这位好同志说,你们一会上去吧,我和列车员说一下。谢天谢地,总算可以及时赶到郑州了。

    逃过一劫,可逃不过另一劫。按照郑州到武汉的火车的时间,我们到达郑州的时间差不多就是上车的时间。为了能赶上车,我们决定不出站,直接从站台上车。可以找了两遍,硬是没有找到那趟火车。难道开走了?不可能吧。铁道部什么时候变得这么高效了?没有找到那趟车,站台是不能随便让你上去的。无奈之下,只好出站了。回想起来,当时做这个决定可是放弃了当天能回到武汉的打算了。(今年在上海,错过了人生的第一趟火车,似乎也没有当时难受)

    出站后才知道,那趟火车压根就没有到,同样的晚点了。小凡还在抱怨做了这么大的努力,最后居然是这种结果。不过我倒觉得庆幸,免受了在火车上多折磨一个小时之苦,环境也好了不少啊。

    同样K字头的火车,人多,无座。小凡在车上高调的教两个小姑娘怎么无票出站,于是也使得屁股尝到了硬座的滋味,虽然是偶尔的。晚点的火车犹如迟到的人一样,人人痛恨,当然也不会让你跑的痛快。

    不知不觉中过了武汉长江大桥,武昌站也就近了。此时已经是深夜12点,在夜色匆匆中打车到住的地方,来不及品味这座城市的美,但是已经隐约的闻到了桂花的香味。

    中原行(5)--包公湖&祠、开封府、大相国寺、龙亭

    第二天早上6点刚过就起床了。虽然已经是10月,中原的太阳还是很强劲,把这个城市照得亮堂堂的。倦意散尽,背包出门。

    住的地方就在包公湖边上。湖水中的太阳显得比较柔弱,微风徐来,波光粼粼,才敢用眼睛和太阳亲密接触。包公祠就在包公湖的岸边,也可以说是一个半岛,三面环水。也许包公日理万机最后就喜欢的事情就是在湖边赏水吧。也许湖里还有几只野鸭,几条小鱼。从对岸开过去,包公祠实在太小,犹如鸡肋,遂弃之。前往开封府。

    步行到开封府,的确不远。可惜开封旧城的风貌已经不在,如果置身于北宋,或许才能感受到当时的繁荣吧。开封府与之前过去的总统府风格大不相同,虽然各种厅、堂、院、宫俱全。古典的建筑更加显得雄伟壮观,更加气势宏大,正好与包公的刚正不阿相映生辉。亲眼所见龙头铡,虎头铡,狗头铡,仿佛回到了那个包公断案的年代。当今的中国也正需要这样的一位人物。离开的时候,正好没有错过开封府的当街演出。虽然演出重现了当年包青天的气势,但要把包青天的思想作风保留到今天并非易事。

    下一站是大相国寺。大相国寺的镇寺之宝应该是那尊千手千眼观音像。全木雕结构,四面立体结构。相传相国寺曾多次遭遇黄河洪水的洗礼,这座木雕恐怕很难逃过这些劫难,想必也是现代的作品了。

    最后一站到了龙亭。因为时间不多,很多比较远的经典便无暇光临了。比如著名的开封铁塔。龙亭也算是开封的古迹吧,北宋的皇宫。当然,没人相信北宋的皇宫能保留到现在。的确不错,这座叫亭非亭的皇宫是在清朝的时候重建的。值得感慨的是,清朝的时候,人们已经知道保护文物了。抑或是,清朝的皇帝已经在北京建了紫禁城,为了显示自己的强大,匆匆修葺了这座“故宫”,以作对比。

    中午,天色大变,走马观花之后奔向了火车站。期待武汉。

    中原行(4)--开封

    从嵩山下来,按照计划,下一个目的地就是开封。时间不多,我们抓紧出发。可惜到了登封市区,到开封的直达车已经没有了。还需要去郑州转车。

    也许正值国庆旅游高峰,虽然郑开公交班车很多,但也足以让我们在车站的长龙中盘旋了接近2个小时。到了开封,已经是万家灯火了。没有吃饭,虽然街边的饭店还没有关门,但是想吃一些有特色的东西,找了个蓬蓬车,带我们到了包公湖附近的小吃街。时隔一年,我忘了那条街的名字,隐约中叫做:鼓楼夜市。

    吸引眼球的第一家就是现场手打花生糖。也许是因为空着肚子,觉得那热腾腾的花生糖真是香啊。虽然当时没有买,但最后回来的时候还是买了,15元一封。哪知一回到住的小旅社,就被老板嘲笑了,这种东西顶多买7,8块,我们居然出了两倍的价格。:-( 后来,这封花生糖随我辗转武汉,北京,重庆,带回家发现已经不能吃了。

    也许是去年物价上涨比较厉害,尤其是食品。各小店都纷纷打出旗号:还是那个价。这里大多的是游人,过客,纵然你涨价了,也无人知道。说实话,这种名气大的地方,一般都不怎么好吃。不知道是不是期望太高,总是没有想象中的好。也许是饿了,吃了两处,终于汤足肉饱。

    还有值得一提的是,开封这个城市明显比郑州要让人感到舒服,环境、建筑、人文,不愧是一个古都。

    中原行(3)--嵩山

    题外话 — 遥想去年今日,与小凡游玩于豫鄂之间,虽说当时日夜奔波,但也悠然自乐。回想起来,恰是一种美好。于是,把没完成的游记写完吧。

    上次写到少林寺,最近看到释永信CEO的各种新闻,还对那个曾经去过的少林寺回忆颇多。也许是出于商业的目的,少林寺和嵩山景区已经合二为一,景区票不分开出售,于是游玩少林寺,我们就上山了。

    少林寺在嵩山的西面,从少林寺这边上山的确没有什么看头。于是缆车成了人们的首选。虽然我们都背着大包,但是缆车的确不是我们的兴趣,来到大山面前,不亲自登一下,怎么对得起这景区的门票呢。说来也巧,我们正在的犹豫的时候,遇上一个少林寺的俗家弟子,小凡有了攀谈的兴趣(其实不是攀谈,更是为了知道那些网上查不到的秘密)。虽然小和尚也是第一次上山,不过听师傅说这山不是很难爬。于是就三人行,必有我师了。

    到了山顶之后,山的另一边的确是另一番景象。为了不给嵩山抹黑,我这里就不写了。看看照片就好了。要说嵩山有多么险,我想是不及华山的,虽然我没有去过华山。前段时间看过一个帖子,有照片有证据,嵩山还不及华山的一半。虽然在垂直的山壁上开道,这些现代建造技术已经让我们感到了安全。虽然在某处的两峰之间的吊桥上写着:限六人于桥上,但是实际上20人在上面也没见桥有任何不安的迹象。更有甚者,在桥上蹦蹦跳跳,引起胆小的人不断的尖叫。

    下山后便于小和尚道别,他还要独自走回少林寺。为了给他发照片,交换了email。风流唐伯虎。一年不见了,希望他离他的梦想不远了。

    August 11

    JavaScript判断浏览器类型及版本

    JavaScript判断浏览器类型及版本

    Posted on 2008-09-06 23:14 李战 阅读(19002) 评论(31)  编辑 收藏 网摘 所属分类: 前端开发

          你知道世界上有多少种浏览器吗?除了我们熟知的IE, Firefox, Opera, Safari四大浏览器之外,世界上还有近百种浏览器。

           几天前,浏览器家族有刚诞生了一位小王子,就是Google推出的Chrome浏览器。由于Chrome出生名门,尽管他还是个小家伙,没有人敢小看他。以后,咱们常说浏览器的“四大才子”就得改称为“五朵金花”了。

           在网站前端开发中,浏览器兼容性问题本已让我们手忙脚乱,Chrome的出世不知道又要给我们添多少乱子。浏览器兼容性是前端开发框架要解决的第一个问题,要解决兼容性问题就得首先准确判断出浏览器的类型及其版本。

           JavaScript是前端开发的主要语言,我们可以通过编写JavaScript程序来判断浏览器的类型及版本。JavaScript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性来分辨,另一种是通过分析浏览器的userAgent属性来判断的。在许多情况下,值判断出浏览器类型之后,还需判断浏览器版本才能处理兼容性问题,而判断浏览器的版本一般只能通过分析浏览器的userAgent才能知道。

           我们先来分析一下各种浏览器的特征及其userAgent。

           IE

          只有IE支持创建ActiveX控件,因此她有一个其他浏览器没有的东西,就是ActiveXObject函数。只要判断window对象存在ActiveXObject函数,就可以明确判断出当前浏览器是IE。而IE各个版本典型的userAgent如下:

            Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)
            Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)
            Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
            Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)

          其中,版本号是MSIE之后的数字。

           Firefox

           Firefox中的DOM元素都有一个getBoxObjectFor函数,用来获取该DOM元素的位置和大小(IE对应的中是getBoundingClientRect函数)。这是Firefox独有的,判断它即可知道是当前浏览器是Firefox。Firefox几个版本的userAgent大致如下:

            Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1
            Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3
            Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12
          其中,版本号是Firefox之后的数字。

           Opera

           Opera提供了专门的浏览器标志,就是window.opera属性。Opera典型的userAgent如下:

            Opera/9.27 (Windows NT 5.2; U; zh-cn)
            Opera/8.0 (Macintosh; PPC Mac OS X; U; en)
            Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0

          其中,版本号是靠近Opera的数字。

           Safari

           Safari浏览器中有一个其他浏览器没有的openDatabase函数,可做为判断Safari的标志。Safari典型的userAgent如下:

            Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13
            Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3

          其版本号是Version之后的数字。

          Chrome

          Chrome有一个MessageEvent函数,但Firefox也有。不过,好在Chrome并没有Firefox的getBoxObjectFor函数,根据这个条件还是可以准确判断出Chrome浏览器的。目前,Chrome的userAgent是:

            Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13

          其中,版本号在Chrome只后的数字。

          有趣的是,Chrome的userAgent还包含了Safari的特征,也许这就是Chrome可以运行所有Apple浏览器应用的基础吧。

          只要了解了以上信息,我们就可以根基这些特征来判断浏览器类型及其版本了。我们会将判断的结果保存在Sys名字空间中,成为前端框架的基本标志信息,供今后的程序来读取。如果判断出谋种浏览器,Sys名字空间将有一个该浏览器名称的属性,其值为该浏览器的版本号。例如,如果判断出IE 7.0,则Sys.ie的值为7.0;如果判断出Firefox 3.0,则Sys.firefox的值为3.0。下面是判断浏览器的代码:


        <script type="text/javascript">
            
    var Sys = {};
            
    var ua = navigator.userAgent.toLowerCase();
            
    if (window.ActiveXObject)
                Sys.ie 
    = ua.match(/msie ([\d.]+)/)[1]
            
    else if (document.getBoxObjectFor)
                Sys.firefox 
    = ua.match(/firefox\/([\d.]+)/)[1]
            else if (window.MessageEvent && !document.getBoxObjectFor)
                Sys.chrome 
    = ua.match(/chrome\/([\d.]+)/)[1]
            else if (window.opera)
                Sys.opera 
    = ua.match(/opera.([\d.]+)/)[1]
            
    else if (window.openDatabase)
                Sys.safari 
    = ua.match(/version\/([\d.]+)/)[1];
            
            
    //以下进行测试
            if(Sys.ie) document.write('IE: '+Sys.ie);
            
    if(Sys.firefox) document.write('Firefox: '+Sys.firefox);
            
    if(Sys.chrome) document.write('Chrome: '+Sys.chrome);
            
    if(Sys.opera) document.write('Opera: '+Sys.opera);
            
    if(Sys.safari) document.write('Safari: '+Sys.safari);

        </script>

     

          我们把对IE的判断放在第一,因为IE的用户最多,其次是判断Firefox。按使用者多少的顺序来判断浏览器类型,可以提高判断效率,少做无用功。之所以将Chrome放在第三判断,是因为我们预测Chrome很快会成为市场占有率第三的浏览器。其中,在分析浏览器版本时,用到了正则表达式来析取其中的版本信息。

          如果你的JavaScript玩得很高,你还可以将前面的判断代码写成这样:

     

        <script type="text/javascript">
            
    var Sys = {};
            
    var ua = navigator.userAgent.toLowerCase();
            window.ActiveXObject 
    ? Sys.ie = ua.match(/msie ([\d.]+)/)[1] :
            document.getBoxObjectFor 
    ? Sys.firefox = ua.match(/firefox\/([\d.]+)/)[1] :
            window.MessageEvent && !document.getBoxObjectFor ? Sys.chrome = ua.match(/chrome\/([\d.]+)/)[1] :
            window.opera ? Sys.opera = ua.match(/opera.([\d.]+)/)[1] :
            window.openDatabase 
    ? Sys.safari = ua.match(/version\/([\d.]+)/)[1] : 0;
            
            
    //以下进行测试
            if(Sys.ie) document.write('IE: '+Sys.ie);
            
    if(Sys.firefox) document.write('Firefox: '+Sys.firefox);
            
    if(Sys.chrome) document.write('Chrome: '+Sys.chrome);
            
    if(Sys.opera) document.write('Opera: '+Sys.opera);
            
    if(Sys.safari) document.write('Safari: '+Sys.safari);
        
    </script>

     

          这样可以使JavaScript代码更精简些。当然,可读性稍差一些,就看你是重视效率还是重视可维护性了。

          使用不同特征来判断浏览器的方法,虽然在速度上比用正则表达式分析userAgent要来的快,不过这些特征可能会随浏览器版本而变化。比如,一种浏览器本来独有的特性取得了市场上的成功,其他浏览器也就可能跟着加入该特性,从而使该浏览器的独有特征消失,导致我们的判断失败。因此,相对比较保险的做法是通过解析userAgent中的特征来判断浏览器类型。何况,反正判断版本信息也需要解析浏览器的userAgent的。

          通过分析各类浏览器的userAgent信息,不难得出分辨各类浏览器及其版本的正则表达式。而且,对浏览器类型的判断和版本的判断完全可以合为一体地进行。于是,我们可以写出下面的代码:


        <script type="text/javascript">
            
    var Sys = {};
            
    var ua = navigator.userAgent.toLowerCase();
            
    var s;
            (s 
    = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] :
            (s 
    = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] :
            (s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] :
            (s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] :
            (s 
    = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0;

            
    //以下进行测试
            if (Sys.ie) document.write('IE: ' + Sys.ie);
            
    if (Sys.firefox) document.write('Firefox: ' + Sys.firefox);
            
    if (Sys.chrome) document.write('Chrome: ' + Sys.chrome);
            
    if (Sys.opera) document.write('Opera: ' + Sys.opera);
            
    if (Sys.safari) document.write('Safari: ' + Sys.safari);
        
    </script>

     

          其中,采用了“... ? ... : ...”这样的判断表达式来精简代码。判断条件是一条赋值语句,既完成正则表达式的匹配及结果复制,又直接作为条件判断。而随后的版本信息只需从前面的匹配结果中提取即可,这是非常高效的代码。

           以上的代码都是为了打造前端框架所做的预研,并在五大浏览器上测试通过。今后,判断某种浏览器只需用if(Sys.ie)或if(Sys.firefox)等形式,而判断浏览器版本只需用if(Sys.ie == '8.0')或if(Sys.firefox == '3.0')等形式,表达起来还是非常优雅的。

          前端框架项目已经启动,一切就看过程和结果了...

     

    原创:李战(leadzen) 阿里软件 2008-9-6 杭州
    原文:http://www.cnblogs.com/leadzen/archive/2008/09/06/1285764.html
    转载务必注明作者及出处

    May 16

    错过

    上天都有过错
    创造悲欢离合 要我们承担结果
    每一个人 是另一个人的景色
    在寂寞的时候 什么比爱更赤裸裸
    April 10

    mono- di- tri- and next

    1 mono
    2 di
    3 tri
    4 tetra
    5 penta
    6 hexa
    7 hepta
    8 octa
    9 nona
    10 deca.
    March 19

    old memories

    看到几张重庆的老照片,一些童年的记忆又跳出来了。列举几例。注:照片是1983年的,我第一次到重庆大概是90年左右,变化不大。
     
    这个缆车,记忆犹新。当时也比较土,看见这个高科技的东西,要多坐一下。于是,我和妈妈从上面坐下来,到了下面,妈妈下车,我不下车,再坐一个来回。这个好像没有人清场,或者我躲起来了。然后,车上去了,马上一辆车又下去了。妈妈在下去的那辆车上找我,怎么也找不到。紧张。。。把我丢了。过了一会,才回过神来,我再另一辆车上。
     
    朝天门码头。当时这个时候ms好一些了。第一次坐渡船。船很好。比在上海坐的渡船好。
     
    重庆的电车。当时看见这个东西很新奇。天上挂两根电线就能跑路了。还有,老式汽车。
     
    火车,这个也比较神奇。
    应该是又过了一段时间的事情了。我和妈妈去菜园坝火车站,想去看看火车。但是,去了才知道,候车室一挡,看什么火车啊,啥都看不见。那个里面是不是随便就能进去的。可是,来了不能白来啊,得想办法。看着有人往车站里面走,我们跟了进去。居然,神不知鬼不觉的就能通往站台了。兴奋。然后得寸进尺。看见有车就想上。说来也巧,正好遇到了一趟内部车,还能到沙坪坝,省得我们回去再坐汽车了!
     
     
    March 15

    星座来历

    处女座:

     

          人间管理谷物的农业之神、希腊的大地之母--狄蜜特,有一个美丽的独生女--泊瑟芬,她是春天的灿烂女神,只要她轻轻踏过的地方,都会开满娇艳欲滴的花朵。有一天她和同伴正在山谷中的一片草地上摘花,突然间,她看到一朵银色的水仙,甜美的利味飘散在空气中,泊瑟芬想:“它比我任何一朵花都漂亮!”美得光彩照人,于是她远离同伴偷偷地走近,伸手正要碰到花儿,突然,地底裂开了一个洞,一辆马车由两匹黑马拉着,冲出地面,原来是阴间之王海地士,他因爱慕“最美的春神”泊瑟芬,设下诡计掳走了她。

          泊瑟芬的呼救声回荡在山谷、海洋之间,当然,也传到了母亲狄蜜特的耳中,狄蜜特非常的悲伤!她抛下了待收割的谷物,飞过千山万水去寻找女儿。

         人间少了大地之母,种子不再发芽,肥沃的土地结不出成串的麦穗,人类都要饿死了,宙斯看到这个情形只好命令冥王放了泊瑟芬,冥王不得不服从宙斯,但暗中却生诡计--临走前给泊瑟芬一颗果子,泊瑟芬怎么知道一旦她吃了这颗果子便无法在人间生活,注定要回到阴暗恶臭的地狱里。

          宙斯没有辨法,只好说:“一年之中,你将只有四分之一的时间可以和泊瑟芬在一起”。从此以后只要大地结满冰霜,寸草不生的时候,人们就知道这是因泊瑟芬又去了地府。处女座象征着春神泊瑟芬的美丽与纯洁,母亲养育的麦穗,也成为她手持之物。即使如此,她再也不是那个无忧无虑嬉戏于草地上的少女,每年春天她虽然会复活,依旧明艳动人,但地狱的恶臭与可怕的气氛却永远随着她。

    March 12

    shell 备忘

    13.2.3 Shell 参数

    几个需要记住的特殊参数

         $0      = shell 名称或 shel 脚本名称
         $1      = 第一个(1)shell 参数
          ...
         $9      = 第九个(9)shell 参数
         $#      = 位置参数的个数
         "$*"    = "$1 $2 $3 $4 ... $n"
         "$@"    = "$1" "$2" "$3" "$4" ... "$n"
         $?      = 最近执行的命令的退出状态
         $$      = 当前 shell 脚本的 PID
         $!      = 最近启动的后台作业的 PID
    

    需要记住的基本扩展参数

             形式        如果设置了 var      如果没有设置 var
         ${var:-string}  $var                string
         ${var:+string}  string              null
         ${var:=string}  $var                string 
                                             (并且执行 var=string)
         ${var:?string}  $var                (返回 string 然后退出)
    

    在此,冒号“:”在所有运算表达式中事实上均是可选的。

    • 有“:” = 运算表达式测试“存在”和“非空”。

    • 没有“:” = 运算表达式仅测试“存在”。

    需要记住的替换参数

             形式        	结果
         ${var%suffix}   删除位于 var 结尾的 suffix 最小匹配模式
         ${var%%suffix}  删除位于 var 结尾的 suffix 最大匹配模式
         ${var#prefix}   删除位于 var 开头的 prefix 最小匹配模式
         ${var##prefix}  删除位于 var 开头的 prefix 最大匹配模式
    

    13.2.4 Shell 重定向

    需要记住的基本重定向(redirection)运算符(在此[n]表示定义文件描述符的可选参数):

         [n]> file     重定向标准输出(或 n)到 file。
         [n]>> file    重定向标准输出(或 n)到 file。
         [n]< file     将file重定向到标准输入(或 n)。
         [n1]>&n2      重定向标准输出(或 n1) 到n2。
         2> file >&2    重定向标准输出和错误输出到 file。
         | command     将标准输出通过管道传递给 command。
         2>&1 | command 将标准输出或错误输出通过管道传递给 command。
    

    在这里:

    • stdin: 标准输入 (文件描述符 = 0)

    • stdout: 标准输出 (文件描述符 = 1)

    • stderr: 标准错误 (文件描述符 = 2)

    shell 允许你通过使用 exec 内嵌一个任意的文件描述符来打开文件。

         $ echo Hello >foo
         $ exec 3<foo 4>bar  # 打开文件
         $ cat <&3 >&4       # 重定向标准输入到 3,标准输出到 4
         $ exec 3<&- 4>&-    # 关闭文件
         $ cat bar
         Hello
    

    在这里, n<&- 和 n>&- 表示关闭文件描述符 n。


    13.2.5 Shell 条件表达式

    每条命令均可返回一个退出状态,这个状态值可用于条件表达式:

    • 成功:0 (True)

    • 错误:1–255 (False)

    注意该用法,返回值0用来表示“true”与计算机其它领域中常见的转换是不同的。另外`['等阶于使用test命令进行参数赋值`]'相当于一个条件表达式。

    需要记住的常用基本条件表达式

         command && if_success_run_this_command_too || true
         command || if_not_success_run_this_command_instead
         
         if [ conditional_expression ]; then  
          if_success_run_this_command
         else
          if_not_success_run_this_command
         fi
    

    当 shell 使用 -e 调用的时候, 需要使用 || true 来确保这个 shell 不会在本行意外退出。

    在条件表达式中使用的文件比较运算符有:

         -e file         file 存在则返回True。
         -d file         file 存在且是一个目录则返回 True。
         -f file         如果 file 存在且是一个普通文件则返回 True。
         -w file         如果 file 存在且可写则返回 True。
         -x file         如果 file 存在且可执行则返回 True。
         file1 -nt file2 如果 file1 比 file2 新则返回 True。(指修改日期)
         file1 -ot file2 如果 file1 比 file2 旧则返回 True。(指修改日期)
         file1 -ef file2 如果两者是相同的设备和具有相同的结点(inode)数则返回 True。
    

    条件表达式中使用的字符串比较运算符有:

              -z str    如果 str 长度为零则返回 True。
              -n str    如果 str 长度为非零则返回 True。
         str1 == str2   如果字符串相等则返回 True。
         str1 =  str2   如果字符串相等则返回 True。
             (使用"=="代替"="符合严格意义上的 POSIX 兼容) 
         str1 != str2   如果字符串不相等则返回 True。
         str1 <  str2   如果 str1 排在 str2 之前则返回 True(与当前位置有关)。
         str1 >  str2   如果 str1 排在 str2 之后则返回 True(与当前位置有关)。
    

    条件表达式中的算术整数比较运算符有-eq-ne-lt-le-gt-ge


    13.2.6 命令行处理

    shell按如下的方式处理脚本:

    • 用这些元字符将其分割成 tokens:SPACE, TAB, NEWLINE, ;, (, ), <, >, |, &

    • 如果不在"..."或'...'内就检查 keyword(循环检查)

    • 如果不在"..."或'...'内就扩展 alias(循环检查)

    • 如果不在"..."或'...'内就扩展 bracea{1,2} -> a1 a2

    • 如果不在"..."或'...'内就扩展 tilde, ~user -> user's home directory

    • 如果不在'...'内就扩展 parameter, $PARAMETER

    • 如果不在'...'内就扩展 command substitution, $(command)

    • 如果不在"..."或'...'内就用 $IFS 分割成 words

    • 如果不在"..."或'...'内就扩展 pathname *?[]

    • 查找 command

      • function

      • built-in

      • file in $PATH

    • 循环

    在双单号内单引号将失效。

    在 shell 里执行 set -x 或者使用 -x 选项调用 shell,该 shell 将会显示出所有执行的命令。 这对调试非常有用。

    March 02

    Linux 关于动态链接库以及静态链接库的一些概念

    库有动态与静态两种
    动态通常用.so为后缀,静态用.a为后缀。例如:libhello.so libhello.a
    为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。
    ln -s libhello.so.1.0 libhello.so.1
    ln -s libhello.so.1 libhello.so
    使用库
    当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。然而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记‘指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。
    现在假设有一个叫hello的程序开发包,它提供一个静态库libhello.a 一个动态库libhello.so,一个头文件hello.h,头文件中提供sayhello()这个函数
    /* hello.h */
    void sayhello();
    另外还有一些说明文档。
    这一个典型的程序开发包结构
    1.与动态库连接
    linux默认的就是与动态库连接,下面这段程序testlib.c使用hello库中的sayhello()函数
    /*testlib.c*/
    #include 
    #include 
    int main()
    {
    sayhello();
    return 0;
    }
    使用如下命令进行编译
    $gcc -c testlib.c -o testlib.o
    用如下命令连接:
    $gcc testlib.o -lhello -o testlib
    在连接时要注意,假设libhello.o 和libhello.a都在缺省的库搜索路径下/usr/lib下,如果在其它位置要加上-L参数
    与与静态库连接麻烦一些,主要是参数问题。还是上面的例子:
    $gcc testlib.o -o testlib -WI,-Bstatic -lhello
    注:这个特别的"-WI,-Bstatic"参数,实际上是传给了连接器ld.
    指示它与静态库连接,如果系统中只有静态库当然就不需要这个参数了。
    如果要和多个库相连接,而每个库的连接方式不一样,比如上面的程序既要和libhello进行静态连接,又要和libbye进行动态连接,其命令应为:
    $gcc testlib.o -o testlib -WI,-Bstatic -lhello -WI,-Bdynamic -lbye
    3.动态库的路径问题
    为了让执行程序顺利找到动态库,有三种方法:
    (1)把库拷贝到/usr/lib和/lib目录下。
    (2)在LD_LIBRARY_PATH环境变量中加上库所在路径。例如动态库libhello.so在/home/ting /lib目录下,以bash为例,使用命令:
    $export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ting/lib
    (3) 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见、
    4.查看库中的符号
    有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种,一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所谓的“弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。例如,假设开发者希望知道上央提到的hello库中是否定义了 printf():
    $nm libhello.so |grep printf
    U printf
    U表示符号printf被调用,但是并没有在函数内定义,由此可以推断,要正常使用hello库,必须有其它库支持,再使用ldd命令查看hello依赖于哪些库:
    $ldd hello
    libc.so.6=>/lib/libc.so.6(0x400la000)
    /lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000)
    从上面的结果可以继续查看printf最终在哪里被定义.