<![CDATA[gysan.bokee.com]]> zh_cn Thu,21 Jun 2007 16:24:50 CST Tue,08 Apr 2008 17:35:13 CST http://www.bokee.com http://reg.bokee.com/account/web/img/logo.gif 博客网 http://www.bokee.com 您好,欢迎访问yunle110.bokee.com <![CDATA[最近好忙没有时间写日志了,呵呵。]]> .html 近好没有时间写日志了,呵呵。

 

也不知道写点什么好了

 

呵呵

 

还是写点什么吧

]]>
Tue,08 Apr 2008 17:35:13 CST 0
<![CDATA[你的编程语言可以这样做吗?(map/reduce的js示范) (转)]]> .html
通过它,你可以写出很多非常奇特非常美妙的代码。短短几行,功能可不简单哦~
例如Scriptaculous中,一开篇就应用了一个findAll,两个each。8行代码,其实只是一句而已:
$A(document.getElementsByTagName("script")).findAll( function(s) {
 return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
}).each( function(s) {
 var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
 var includes = s.src.match(/\?.*load=([a-z,]*)/);
 (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
 function(include) { Scriptaculous.require(path+include+'.js') });
});


《你的编程语言可以这样做吗?(map/reduce的js示范) 》原文如下:

有一天,你在浏览自己的代码,发现有两大段代码几乎一样。实际上,它们确实是一样的——除了一个关于意大利面(Spaghetti)而另一个关于巧克力慕思(Chocolate Moose)。
 // 一个小例子:
 
 alert("偶要吃意大利面!");
 alert("偶要吃巧克力慕思!");
嗯,这个例子碰巧是用javascript写的,不过你就算不懂JavaScript,应该也能明白它在干什么。

拷贝代码不好。于是,你创建了个函数
 function SwedishChef( food ){
 alert("偶要吃" + food + "!");
 }
 SwedishChef("意大利面");
 SwedishChef("巧克力慕思");
Ok,这只是一个很小很小的例子而已,相信你能想像到个更实际一点的例子。这段代码有很多优点,你全都听过几万次了:可维护性、可读性、抽象性 = 好!

现在你留意到有另外两段代码几乎跟它们一模一样,除了一个反复调用一个叫BoomBoom的函数,另一个反复调用一个叫PutInPot的。除此之外,這两段代码简直没什么两样:
 alert("拿龙虾");
 PutInPot("龙虾");
 PutInPot("水");
 alert("拿鸡肉");
 BoomBoom("鸡肉");
 BoomBoom("椰子酱");
现在要想个办法,使得你可以將一个函数用作另一个函数的参数。这是个重要的能力,因为你更容易将框架代码写成一个函数(emu注:还记得template method模式吧?)。
 function Cook( i1, i2, f ){
 alert("拿" + i1);
 f(i1);
 f(i2);
 }
 Cook( "龙虾", "水", PutInPot );
 Cook( "鸡肉", "椰子酱", BoomBoom );
看看,我们居然把函数当成调用参数传递了!

你的编程语言能办到吗?

等等……假如我们已经有了PutInPot和BoomBoom这些函数的具体实现代码(而且又不需要在别的地方重用它们),那么用内联语法把它们写进函数调用里面不是比显式的声明这两个函数更漂亮吗?
 Cook( "龙虾",
 "水",
 function(x) { alert("pot " + x); } );
 Cook( "鸡肉",
 "椰子酱",
 function(x) { alert("boom " + x); } );
耶,真方便!请注意我只是随手创建了个函数,甚至不用考虑怎么为它起名,只要拎着它的耳朵把它往一个函数里头一丢就可以了。

当你一想到作为参数的匿名函数,你也许想到对那些对数组里的每个元素进行相同操作的代码。
 var a = [1,2,3];
 for (i=0; i<a.length; i++){
 a[i] = a[i] * 2;
 }
 for (i=0; i<a.length; i++){
 alert(a[i]);
 }
常常要对数组里的所有元素做同一件事,因此你可以写个这样的函数来帮忙:
 function map(fn, a){
 for (i = 0; i < a.length; i++){
 a[i] = fn(a[i]);
 }
 }
现在你可以把上面的东西改成:
 map( function(x){return x*2;}, a );
 map( alert, a );
另一个常见的任务是将数组内的所有元素按照某总方式汇总起来:
 function sum(a){
 var s = 0;
 for (i = 0; i < a.length; i++)
 s += a[i];
 return s;
 }
 
 function join(a){
 var s = "";
 for (i = 0; i < a.length; i++)
 s += a[i];
 return s;
 }
 
 alert(sum([1,2,3]));
 alert(join(["a","b","c"]));
sum和join长得很像,你也许想把它们抽象为一个将数组内的所有元素按某种算法汇总起來的泛型函数:
 function reduce(fn, a, init){
 var s = init;
 for (i = 0; i < a.length; i++)
 s = fn( s, a[i] );
 return s;
 }
 
 function sum(a){
 return reduce( function(a, b){ return a + b; }, a, 0 );
 }
 
 function join(a){
 return reduce( function(a, b){ return a + b; }, a, "" );
 }

许多早期的编程语言没法子做这种事。有些语言容许你做,却又困难重重(例如C有函数指针,但你要在別处声明和定义函数)。面向对象语言也不确保你用函数可以干些啥(把函数当对象处理?)。

如果你想将函数视为一类对象,Java要求你建立一个有单方法的对象,称为算子对象。许多面向对象语言要你为每个类都建立一个完整文件,像这样开发可真叫快。如果你的编程語言要你使用算子对象来包装方法(而不是把方法本身当成对象),你就不能徹底得到现代(动态)编程语言的好处。不妨试试看你可否退货拿回些钱?

不用再写那些除了经过一个数组对每个元素做一些事情之外一无是处的函数,有什么好处?

让我们看回map函数。当你要对数组内的每个元素做一些事,你很可能不在乎哪个元素先做。无论由第一个元素开始执行,还是是由最后一个元素执行,你的结果都是一样的,对不?如果你手头上有2個CPU,你可以写段代码,使得它们各对一半的元素工作,于是乎map快了两倍。

或者,发挥一下想像力,设想你在全球有千千万万台服务器分布在全世界的若干个数据中心,你有一个真的很大很大的数组,嗯,再发挥一下想像力,设想这个数组记录有整个互联网的内容。还了,现在你可以在几千台服务器上同时执行map,让每台服务器都来解决同一个问题的一小部分。

那么在这个例子里面,编写一段非常快的代码来搜索整个互联网这个问题,其实就和用一个简单的字符串搜索器(算子)作为参数来调用map函数一样简单了。

希望你注意到一个真正有意思的要点,如果你想要把map/reduce模式变成一个对所有人都有用,对所有人都能立刻派上用场的技术,你只需要一个超级天才来写最重要的一部分代码,来让map/reduce可以在一个巨大的并行计算机阵列上运行,然后其他旧的但是一向在单一个循环中运行良好的代码,仍可以保持正确的运行,惟一的差别只是比原来单机运行快了n倍。这意味着它们都一不留神突然变成可以被用来解决一个巨大的问题的代码。

让我再啰嗦一下,通过把“循环”这个概念加以抽象,你可以把用任何你喜欢的方式来实现“循环”过程,包括可以实现让循环迭代速度随着硬件计算能力保持令人满意的同步增长。

你现在应该可以明白不久为何对那些对除了Java之外什么都沒被学过的计算机系学生表示不满了:
( http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html ) :

Without understanding functional programming, you can't invent MapReduce, the algorithm that makes Google so massively scalable. The terms Map and Reduce come from Lisp and functional programming. MapReduce is, in retrospect, obvious to anyone who remembers from their 6.001-equivalent programming class that purely functional programs have no side effects and are thus trivially parallelizable. The very fact that Google invented MapReduce, and Microsoft didn't, says something about why Microsoft is still playing catch up trying to get basic search features to work, while Google has moved on to the next problem: building Skynet^H^H^H^H^H^H the world's largest massively parallel supercomputer. I don't think Microsoft completely understands just how far behind they are on that wave.

不理解函数式编程,你就发明不了MapReduce这个让Google的计算能力如此具有可扩展性的算法。Map和Reduce这两个术语源自Lisp语言和函数式编程……(这是另一篇文章的内容,emu也不是很理解其中的各种说法的来龙去脉,就不翻译了)

我希望你现在明白,把函数当成基本类型的(动态)编程语言能让你在编程过程中更好的进行抽象化,也就是使代码精悍、功能更内聚、更具可重用性及更具有扩展性。很多的Google应用使用Map/Reduce模式,因此一有人对其优化或修正缺陷,它们就都可以从中得益。

我准备要再罗嗦一下,我认为最有生产力的编程语言莫过于能让你在不同层次上都可以进行抽象化的。老掉牙的FORTRAN 语言以前是不让你写函数的注。C 有函数指针,可是它们都非常丑丑丑丑丑丑丑丑陋,不允许匿名声明,又不能在用它们时实现它们而偏偏要放在別处去实现。Java让你使用算子对象,一种更丑陋的东西。正如Steve Yegge所述,Java是個名词王国
( http://steveyegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html )。

作者注:这里提起了FORTRAN,不过我上次使用FORTRAN是27年前的事了。FORTRAN是有函数的,我码字那会儿脑子里面想的大概是GW-BASIC语言。(emu注,basic确实只有所谓的子程序和go-sub语句,作用只是重新组织代码结构而已,没有参数和调用堆栈,因此没有真正的函数调用)

译者注:原作者起了《你的编程语言可以这样做吗》这个标题其实并不是这篇文章的真正价值所在,我转这篇文章也不是因为原作者可以把语言的初级技巧玩得转,而是因为这是一篇map/reduce模型的示范。

 

你的编程语言可以这样做吗?(map/reduce的js示范) (转)

]]>
Wed,19 Dec 2007 17:26:07 CST 0
<![CDATA[股票中“多空双方”的意思]]> .html
空头:是指变为股价已上涨到了最高点,很快便会下跌,或当股票已开始下跌时,变为还会继续下跌,趁高价时卖出的投资者。
利空:促使股价下跌,以空头有利的因素和消息。

利多:是刺激股价上涨,对多头有利的因素和消息。

长空:是对股价前景看坏,借来股票卖,或卖出股票期货,等相当长一段时间后才买回的行为。

短空:变为股价短期内看跌,借来股票卖出,短时间内即补回的行为。

长多:是对股价远期看好,认为股价会长期不断上涨,因而买进股票长期持有,等股价上涨相当长时间后再卖出,赚取差价收益的行为。

短多:是对股价短期内看好,买进股票,如果股价略有不涨即卖出的行为。

补空:是空关买回以前卖出的股票的行为。

吊空:是指抢空头帽子,卖空股票,不料当天股价末下跌,只好高价赔钱补进。

多杀多:是普遍认为当天股价将上涨,于是市场上抢多头帽子的特别多,然而股价却没有大幅度上涨,等交易快结束时,竞相卖出,造成收盘价大幅度下跌的情况。

轧空:是普遍认为当天股价将下跌,于是都抢空头帽子,然而股价并末大幅度下跌,无法低价买进,收盘前只好竞相补进,反而使收盘价大幅度升高的情况。

死多:是看好股市前景,买进股票后,如果股价下跌,宁愿放上几年,不嫌钱绝不脱手。]]>
Wed,19 Dec 2007 14:31:09 CST 0
<![CDATA[股票手续费问题]]> .html lixiaobo2007 在 股票手续费问题 日志中写到:
如果是3元买100股
OK
前提必须要确定你是在卷商交易厅现场买卖还是网上买卖
大部分人都是在卷商交易厅现场买卖 一般手续费为0.003
像我是在网上买卖的 手续费为0.001 就跟你不一样
但不管多少 最少都要算5块!!!!

现在我们假设....

如果买的是沪股(上海股票)
是在卷商交易厅现场买卖 且卷商的手续费为0.003(每家卷商有些家不一样)
则3元买100股手续费为.....

[(3*100)*0.003]+[(3*100)*0.001)]+(100*0.001) 此为总式子
慢慢为你解释....

第1步的[(3*100)*0.003]
3*100(你所花费或收回的总金额)*0.003(卷商的手续费)
=0.9 (不足5块以5块计算)
现在问题来了
因为有规定 此项费用不足5块需以5块计算 所以你这次的买卖
卷商那的手续费即为5快 即你光给卷商的费用就亏了4.1!!

第2步的[(3*100)*0.001)]
3*100(你所花费或收回的总金额)*0.001(国家的印花税)
=0.3
这项是算出来为多少即多少 没有最低限制
同时印花税为固定的 即0.001 无论沪市还是深市皆为0.001

第3步的(100*0.001)
100(为你此次买卖股票的股数)*0.001(此为沪市独有的过户费率 深市没有!)
=0.1
这项也有最低限制即为1元 不足1元以1元计算
所以你在这项也亏了0.9!!
需注意 第3步这一项在买卖深市股票时是不用付费的!!!!!!!

OK
现在全部算一遍
[(3*100)*0.003]+[(3*100)*0.001)]+(100*0.001)
=5+0.3+1=6.3 次为你这次买或卖的手续费
记住 买的时候有买的手续费 卖的时候也有卖的手续费
只是把"你所花费或收回的总金额"变更一下即可

如果买的是深股(深圳股票)
则总式子为
[(3*100)*0.003]+[(3*100)*0.001)]=5.3!!
与沪市不同之处就在少了第3项 不用交过户费!!!!
--------------------------------------------
那假如我今天买了000021(深市股)
成交价是6.21 买了50手(5000股)
那手续费是多少呢?

[(6.21*5000)*0.001]+[(6.21*5000)*0.001)]=31.05+31.05=62.1
(要注意 我是网上买卖 卷商手续费为0.001)

假如我今天买了600321(沪市股)
成交价是3.23 买了200手(20000股)
那手续费是多少呢?

[(3.23*20000)*0.001]+[(3.23*20000)*0.001)]+(20000*0.001)
=64.6+64.6+20=149.2
(要注意 我是网上买卖 卷商手续费为0.001)

]]>
Mon,17 Dec 2007 14:16:10 CST 0
<![CDATA[美国媒体揭密:小鹰号航母赴港不成的幕后的中美较量]]> .html 美国媒体揭密:小鹰号航母赴港不成的幕后的中美较量

美国世界日报24日社论指出,刚刚过完的感恩节,是美国人独有的风习,是仅次于圣诞节和新年的重要节日。有83%的家庭在那天晚上享用火鸡大餐,与家人团聚。节日后的「黑色星期五」,更是大小商店展开年度大竞销的开始,零售商一年的业绩,一大半都寄望于这段时期。  

 航空母舰「小鹰号」(Uss Kitty Hawh)预定在感恩节前到香港靠岸,中国大陆方面21日表示拒绝,可是,22日也就是感恩节当天,外交部突然急转弯,准许小鹰号到香港,并称「这是基于人道考虑的决定」。就在北京作此宣布时,小鹰号战斗群已经驶离南海,返回驻日本的基地。八千官兵在风浪中度过感恩节,远从美国赶到香港的军眷未能和亲人相会,心情之错愕失望,可想而知。  

 这件事说大不大,说小也不能算小,因为它多多少少反应着中美国关系、特别是军事关系的不甚平稳圆熟。过去,美军舰艇到香港停靠休憩者,每年都有几十起。美方已视为顺理成章,香港商家也认为「好生意上门了」。但中方这次的欲拒还迎,最后一分钟的「人道考虑」,很难不被解释为「技术性的不欢迎」。拒绝在先,人道在后,表面上作到了「两面光」,实际上则是如上海人说的,「把点颜色侬看看」。  

 美方要求解释,外交部的回应是,「中方向来是根据主权原则和具体情况,逐案进行审批」。换言之,主权在我,准不准都在我。你若让我不称心,我也会让你不舒服。北京所要表达的是,中方可以向美国说「不」,但用「人道考虑」收场,不使对方太过难堪。  

 或谓,政策出现反覆,是因为军方与外交部的步调不一,口径有别,才会有这一次前倨后恭的转变。我们对此说表示怀疑。小鹰号赴港事前必早已循序申请,北京的急转弯是有意为之,是「把点颜色侬看看」的姿态。  

 至于北京为何要在小鹰号上借题发挥?军方与专家们不同的研判,本报都有报导;我们认为最可能的关键,仍在台湾局势。  

 国防部长盖兹最近访问北京,事后双方都形容他「此行甚为圆满」。不过,当他晋见国家主席胡锦涛时,原想敦促中方在制止伊朗发展核武一事多多出力,但胡锦涛一直和他谈「不容分割」的台湾问题,不容盖兹有发言的机会。而盖兹返美后,五角大厦立即宣布将爱国者二型飞弹售予台湾,触了中方之大忌。  

 北京高层一直怀疑,陈水扁之所以无所忌惮,大搞台独,一部分原因是美国朝野间有潜在的势力,与阿扁呼应支持。爱国者二型飞弹是否在为台独增声势?北京的怀疑并不是过敏吧。  

 美国如未能约束阿扁,但将来又不能「全心全力」去保扁保独,对台湾来说那是最危险的事。中国大陆潜艇两度跟踪小鹰号航母战斗群,并在射程范围内公然跟踪,是相当明显的挑战,美国传统的反潜防潜能力,并不是十分「固若金汤」。  


 由国会立法成立的「美中经济暨安全审查委员会」一周前发表年度报告,认为情报机构未能正确评估中国大陆建军的进度和能力。美国战争学院前任副院长柯尔接受本报访问时说,如果中国大陆的廿余艘潜舰在未遭侦测的情况下进入台海,自将延缓美国航母战斗群的介入。  

 换言之,到了那一步,就算美国有心「拔刀相助」,但为了自身安全,也不能不慎重其事。  

 小鹰号赴港不成,说大不大,说小也不小。中方新任的副总参谋长马晓天下月初访问华府,参加一年一度的战略谘商会议,计画行程并无变更。更多的交流互动,应可减少误会,增进瞭解,才不至于因政客操作而出现意外的变局。
]]>
Fri,30 Nov 2007 13:46:56 CST 0
<![CDATA[clientHeight / scrollHeight / offsetHeight 等属性的区别图]]> .html clientHeight / scrollHeight / offsetHeight 和 clientWidth / scrollWidth / offsetWidth 还有 clientTop / scrollTop / offsetTop 等属性的图示!

 

注意:
当页面使用的编码标准为下面语句时:

<!http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>

一些属性,如 body.clientHeight 就会失效,如果需要,可用下面语句代用:

document.documentElement.clientHeight;

 


 

]]>
Wed,28 Nov 2007 17:34:19 CST 0
<![CDATA[Java中如何正确使用字体编码]]> .html 在Java编程中,中文字体编码难倒了不少程序员,如果抓住了影响Java中文显示的几个关键因素,问题将迎刃而解。

Java是目前最流行的面向对象的编程语言之一,Java支持UTF-8、ISO-8 
859-1、GBK等各种字体编码,可笔者发现Java中字体编码的问题仍难倒了不少程序员,网上虽然也有不少关于在Java中如何正确显示中文的文章,但都不够全面,笔者特意总结如下。

影响Java中字体编码正确显示的有几个因素: 1)数据库的连接方式; 2)网页中使用的字体编码; 3)数据库里存放数据的字体编码; 4)Java的缺省字体编码。如果在编程中遇到不能正确显示中文时,要先弄清楚以上几项所使用的字体编码,再分析找出原因,即可解决问题。

众所周知,JSP是Java的一种,和网页有关,而网页也有自己的中文编码系统,所以JSP处理中文要比纯Java的类文件更为麻烦。本文的测试数据库是MySQL3.2,数据库连接驱动是用org.gjt.mm.mysql.Driver,这里主要讨论UTF-8和GBK的显示( GB2312是GBK的一个子集,Java中可以使用GBK来代替GB系列)。我们先来研究JSP中字体编码问题, 下面第一到第六点是针对JSP的(因为从数据库里读出中文数据与写入中文数据有所区别,咱们分别说明,前三点是从读取数据库到显示在网页,后三点是从网页输入数据到存入数据库),第七到第九点针对纯Java的类文件。 以下rs表示ResultSet的一个实例,是执行Select语句之后产生的数据集。

一、数据库连接方式使用UTF-8

在连接数据库的驱动后面加上这句参数useUnicode=true&characterEncoding=

UTF-8,例如jdbc:mysql://localhost/DBVF?autoReconnect=true&useUnicode=

true&characterEncoding=UTF-8,从数据库里读出中文显示在使用GBK的JSP的网页里,如果数据库里存放的字体编码是UTF-8,在JSP中使用 str=new String(rs.getBytes(1),"UTF-8")或者str=rs.getString(1),可以正确显示中文。如果数据库里存放的是GBK数据,那么JSP中也要使用str=new String(rs.getBytes(1),"GBK")来显示正确的中文。值得注意的是如果页面使用UTF-8,数据库里存放的是UTF-8,也可以用str=new String(rs.getBytes(1),"GBK")正确显示中文。如果网页是UTF-8,而数据库里存放的是GBK,无法直接显示中文,需要2步转换, str=new String(rs.getBytes(1),"GBK"); 再str=new String(str.getBytes("UTF-8"),"GBK"),才可以正确显示中文。

二、数据库连接方式使用GBK

在连接数据库的驱动后面加上这句参数useUnicode=true&characterEncoding=

GBK,例如jdbc:mysql://localhost/DBVF?autoReconnect=true&UseUnicode=true&

characterEncoding=GBK,从数据库里读出中文,显示在使用GBK的JSP的网页里,如果数据库里存放的字体编码是UTF-8,在JSP中一定要使用 str=new String(rs.getBytes(1),"UTF-8"),才正确显示中文。如果数据库里存放的是GBK数据,那么JSP中也要使用str=new String(rs.getBytes(1),"GBK") 或者直接使用str=rs.getString(1),即可显示正确的中文。 如果网页是UTF-8,而数据库里存放的是GBK,只能用str=new String(rs.getString(1).getBytes("UTF-8"),"GBK")的方法来显示中文; 如果网页是UTF-8,而数据库里存放的是UTF-8,可用str=new String(rs.getBytes(1),"GBK") 或者rs.getString(1)方法来显示中文。

三、使用缺省数据库连接方式

连接数据库的驱动后面没有这句参数useUnicode=&characterEncoding=,例如jdbc:mysql://localhost/DBVF?autoReconnect=true,没有参数useUnicode=true&characterEncoding,表示使用默认的ISO-8895-1编码。

1. 从数据库里读出中文,显示在GBK的网页里。如果数据库里存放的字体编码是UTF-8,在JSP网页中一定要使用语句 str=new String(rs.getBytes(1),"UTF-8") 或者str= new String(rs.getString(1).getBytes("ISO-8859-1"),"UTF-8"),才可正确显示中文。如果数据库里存放的是GBK数据,那么JSP中也要使用str=new String(rs.getBytes(1),"GBK")或str=new String(rs.getString(1).getBytes("ISO-8859-1"),"GBK") 显示正确的中文。

2. 如果网页是UTF-8,不能直接正确显示GBK,需要2步转换,str=new String(rs.getBytes(1),"GBK"),再str=new String(str.getBytes("UTF-8"),"GBK") 才可以正确显示中文。如果数据库里存的是UTF-8,直接用str=new String(rs.getBytes(1),"GBK")或者str=new String(rs.getString(1).getBytes("ISO-8859-1"),"GBK")就可以显示中文了。

以上是读取数据库里中文正确显示在网页上,下面三点是如何正确存入数据库。

四、数据库连接方式使用UTF-8编码

JSP中要把网页输入的中文存入数据库,通常有一个提交(Submit)的过程,是用str=request.getParameter("username"),然后执行update或者insert语句来存入数据库。如何赋值给str很重要,而且这里中文输入与网页所使用的字体编码有关。

1、 网页使用UTF-8,使用str= new String(request.getParameter("username").getBytes("ISO-8859-1"),"UTF-8")或者str= new String(request.getParameter("username").getBytes(),"UTF-8"),都可以使得存到数据库里的数据是UTF-8编码。

2. 网页使用GBK,使用str= new String(request.getParameter("username").getBytes(),"GBK"),那么存入数据库的是UTF-8编码。

3. 值得注意的是使用UTF-8的数据库连接方式不能存得GBK。

五、数据库连接方式使用GBK编码

1. 输入使用GBK网页,存到数据库里是GBK的方法: str= new String(request.getParameter("username").getBytes("ISO-8859-1"),"GBK") 或者str= new String(request.getParameter("username").getBytes(),"GBK")。

2. 网页使用GBK,想存入UTF-8到数据库里,要分2步: 先str=new String(request.getParameter("username").getBytes(),"GBK"),再str=new String(str.getBytes("UTF-8"),"GBK")即可。

3. 网页使用UTF-8,而且使用str= new String(request.getParameter("username").getBytes("ISO-8859-1"),"GBK") 或者str= new String(request.getParameter("username").getBytes(),"UTF-8"),那么存到数据库里的数据是UTF-8编码。

4. 网页使用UTF-8,而且使用str= new String(request.getParameter("username").getBytes("ISO-8859-1"),"UTF-8"),那么存到数据库里的数据是GBK编码。

六、数据库连接方式使用缺省,即不使用参数useUnicode和characterEncoding

1. 网页使用GBK,如果使用str= request.getParameter("username")或者str= new String(request.getParameter("username").getBytes()),那么在数据库里的数据是GBK码。网页使用UTF-8 和使用str= request.getParameter("username"),则存入数据库是UTF-8编码。

2. 如果使用str= new String(request.getParameter("username").getBytes("ISO-8859-1")),那么根据网页提供的字体编码而存到数据库里,比如是UTF-8的网页,那么存到数据库中就是UTF-8编码,如果使用GBK网页,那么存到数据库里的字就是GBK编码。

3. 如果使用str= new String(request.getParameter("username").getBytes("UTF-8"),"UTF-8")这一种组合能存到正确的数据外,其他存到数据库里的数据则都是乱码或者错误码。在这个UTF-8组合的特例中,网页使用的是GBK,则存放到数据库里就是GBK,网页使用UTF-8,那么存到数据库里的就是UTF-8。

4. 网页是GBK的要存得UTF-8,一定需要2步: company=new String(request.getParameter("company").getBytes(),"GBK")和company=new String(company.getBytes("UTF-8"))。

5. 网页是UTF-8的,不能存得GBK在数据库里,一句话,改变数据库连接方式不能存得GBK码。

以上所有的都是基于JSP网页和数据库交换数据,下面讨论一下纯JAVA编程下的字体编码转换。

七、数据库连接方式使用UTF-8编码

1. 数据库里的中文是UTF-8,可以转换为GBK,但不能把GBK存入数据库。

2. 数据库是GBK,如果转换为UTF-8,使用content=new String(rs.getBytes(2),"GBK")直接将content存入数据库就可为UTF-8。

八、数据库连接方式使用GBK编码

1. 数据库里的中文是UTF-8,如果转换为GBK,使用content= new String(rs.getString(2).getBytes(),"UTF-8"),再直接使用update或者insert语句插入到数据库,即存得GBK。如果使用content= new String(rs.getString(2).getBytes(),"GBK")或者content= new String(rs.getString(2).getBytes()),再存入数据库即存得还是UTF-8编码。

2. 数据库里的中文是GBK,如果转换为UTF-8,使用content= new String(rs.getString(2).getBytes("UTF-8"))或者content= new String(rs.getString(2).getBytes("UTF-8"),"GBK"),再直接使用update或者insert语句插入到数据库,即存得UTF-8。

3. 如果某个String是GBK,要转换为UTF-8,也是使用content= new String(GBKstr.getBytes("UTF-8"))或者content= new String(GBKstr.getBytes("UTF-8"),"GBK"); 如果某个String是UTF-8,要转换为GBK,应该使用new String(UTFstr.getBytes("GBK"),"UTF-8")。

九、数据库连接方式使用缺省,即不跟参数

1. str2=new String(GBKstr.getBytes("UTF-8"),"ISO-8859-1"),可以将数据库里的GBK编码转换为UTF-8。

2. 读取UTF-8然后存入UTF-8,则用str1=new String(UTFstr.getBytes(),"ISO-8859-1")或者str1=new String(UTFstr.getBytes("GBK"),"ISO-8859-1")。

3. 不能实现数据库里的UTF-8转换为GBK。

如果采用UTF-8的数据库连接方式或者缺省数据连接方式,那么无法将UTF-8转为GBK;而GBK的数据库连接方式可以实现UTF-8和GBK的相互转换。建议大家采用GBK的数据连接方式。

]]>
Tue,27 Nov 2007 15:29:29 CST 0
<![CDATA[5天收入10元--个人博客赚钱离你还有多远]]> .html   最近博客网和阿里妈妈合作推出了博客用户的广告位,每天都有进账,5天收入了10元,个人博客赚钱离你还有多远。

  个人用户坐在家里写博客,不用上班就可以获得固定收入?博客网近日宣布,将在所有博客全面铺开博客分账系统“博客金行”,实行自愿原则,今后广告利润三分之二归博客,三分之一归博客网。

在众多翘首以待的博客用户看来,不管怎样,博客网站们能够设身处地想到他们的利益,已经足够让他们激动一段时间,但对于“钱景”,却很少有人看好。

   一些著名博客更多地是把博客网站们的举动当作又一次炒作的噱头,而同为WEB2.0公司的老板们对于广告分成模式的前景也有着类似的看法,ZCOM公司总裁黄明明认为,这种模式作为一种探索和尝试是值得的,但不一定能够取得多好的实际收益。不仅如此,业界专家也对个人博客可以获得赢利的模式表示了不信任    草根博客坐家赚外快

   博客网推出“博客金行”,普通博客可分享广告收入

    个人用户写博客也能赚钱了?从此坐在家里不用上班就可以获得固定收入?这一“梦幻”般的美景曾为众多博客发烧友们所畅想,一旦真的来临,却又有几分不敢相信。“如果真能如此,那岂不是大家都可以罢工了?”一位博客道出了很多人的心声。尽管已有博客网站表了态,愿意同用户分享收入,但距离每个草根博客都可以获得稳定可观的收入还有一段路程。自诞生之日起就一直受“赢利模式”困扰的WEB2.0公司们真正为博客们提供这一生存道路的可能性还要接受更多考验。

  个人博客开始有进账

   博客网总裁方兴东在8月26日举行的中国“博客诞生四周年研讨会”上称,博客网将在所有博客全面铺开博客分账系统“博客金行”,实行自愿原则,今后广告利润三分之二归博客,三分之一归博客网。

   方兴东称该业务开创了一个新模式,首次把博客、博客网站和广告主三方利益捆绑在一起。目前博客网已经获得TCL、亚马逊和卓越等多家公司3000万元的首批推广赞助费用。据悉,博客用户在向博客金行提出申请后,博客网将在其博客页面上挂出相应的广告。之后,博客网通过技术手段,对各个博客页面广告进行跟踪分析和统计,按照广告访问量的不同、对广告主广告效果影响的不同等标准,与个人博客进行分成。首批广告投放具体的分成标准是:个人博客上的广告,每获得一个独立IP的点击,作者将获得0.05元至0.2元的分成。

   之前,Google曾经推出通过广告点击进行用户分成的模式。和讯网甚至还带动博客用户发起了“博客广告同盟”,希望一同获得广告收益

    想发财有点难

   尽管博客网愿意同用户分享收入,但由于客观条件限制,自诞生之日起就一直备受“赢利模式”困扰的WEB2.0公司们真正为博客们提供这一生存道路的可能性还要接受更多考验。按照博客网“博客金行”评价体系的规定,博客必须要保持经常性的更新、必须保证所有访问你页面的人都尽量去点击页面上的广告,还必须保证不出现重复点击……“假如你的全班同学都来为你争‘人气’,但由于他们在同一个校园网上网,那也只能算做是一个独立IP,这或许是让个人博客用户感到绝望的一件事。”一位资历较老的博客这样评价。

   按照该方法,互联网上的争议人物或者突发事件主角可以获得每天几百甚至上千元的收入,但对普通博客用户而言,以一个日访问量百人左右的普通博客用户来计算,每月的收入最多也就几十元钱

  但愿博客网和阿里妈妈合作会走好,阿里妈妈注册请点这里

]]>
Thu,15 Nov 2007 13:33:26 CST 0
<![CDATA[Vista.com域名卖了125万美元 收购者非微软]]> .html   Vista.com域名现在已经被售出,但是购买这个域名的买家可不是微软,而仅仅是一家做名片的公司。

  据称,这家名为VistaPrint的名片制作公司是从一家名为innuity的软件服务公司手中购得的此域名。

  2005年之前,Innuity公司并不为人所知,他们使用Vista.com这个域名的目的仅仅是为了出名。现在VistaPrint的目的和Innuity公司没有什么不同,他们购买这个域名是为了给自己打广告。

 

]]>
Thu,15 Nov 2007 11:54:25 CST 0
<![CDATA[博客赚钱四步成功--bokee添加广告攻略(图文)]]> .html 博客赚钱四步成功--bokee添加广告攻略(图文) 日志中写到:


在 bokee 安家了的博客朋友们,你们不用再嫉妒sina和猫扑的朋友,也可以在bokee的博客上面投放阿里妈妈的广告,让你们的博客更有价值了哦 !

PS:以下所有操作只能在 FireFox 浏览器下面实现,在 IE 核心的浏览器下可是行不通的。

一、登录bokee后,点击页面的公告管理链接

screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open(this.src);}" onmousewheel="return imgzoom(this);" alt="" border="0">


二、在弹出的公告编辑页面里面,粘贴上阿里妈妈的广告代码。阿里妈妈的广告代码获取可以参照帖子阿里妈妈注册攻略

这里需要注意的是,获取的代码应该是下面的针对博客的广告代码。获取的代码规格最好是 460*60,同时把代码放在 <div align="center"></div> 里面。这样做是为了让你的广告看起来和页面协调工整。


screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open(this.src);}" onmousewheel="return imgzoom(this);" alt="" border="0">


三、粘贴完毕广告代码之后,点击修改。这个时候会出来一个警告框。但是你可以不用理会,点击确定后会返回到编辑公告内容的对话框。


screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open(this.src);}" onmousewheel="return imgzoom(this);" alt="" border="0">


四、在返回的编辑公告内容对话框,不用做任何修改,再次点击“修改”按钮即可。这个时候你就可以看到成功的提示页面了。

screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open(this.src);}" onmousewheel="return imgzoom(this);" alt="" border="0">


大功告成,记得多宣传一下你的广告为让大家来抢购哦 !!

screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open(this.src);}" onmousewheel="return imgzoom(this);" alt="Click here to open new windowCTRL+Mouse wheel to zoom in/out" border="0" width="716">

合作伙伴用户不可以新增广告位,提示“此网站为合作伙伴用户,不允许新增广告位”,谁来为公告处的广告位买单呢?
]]>
Tue,13 Nov 2007 17:12:35 CST 0
<![CDATA[写博客可以赚钱吗?]]> .html 写博客可以赚钱吗?

答案是能,最近博客网和阿里妈妈合作了,在博客上的广告位每点一次博客用户将会得到0.1元-0.13元不等的收入。

]]>
Fri,28 Sep 2007 17:15:05 CST 0
<![CDATA[Actionscript 优化指南]]> .html Actionscript 优化指南 [来源 gotoAndStop.it January 27, 2004 ]
原著 Marco Lapi, aw[特别感谢好友杨鑫]

在这篇文章中,我们将讨论多种优化 Actionscript 代码的方法.
此外我们也针对一些典型的游戏代码进行了系列测试,来最大限度的发掘、提高Flash播放器的性能。

代码优化简介

在本文中,我们将向您展示一些通过技术手段得到了优化的flash小游戏。代码优化之所以重要是因为它能帮您节约flash播放器的资源,还能让您的游戏在不同的硬件环境下运行得更加稳定。本文主要讨论基于flashplayer6.0的一些问题,以及如何通过可行的技术手段去解决它们!

随着flashplayer7.0的发布,一些技术问题已经得到解决了,而且性能大体地有所提高,然而在写本文之时,flashplayer6.0仍然有着广泛的应用。所以我们还是主要集中在6.0这个版本上。-aw猜测:国外买盗版的很少,所以很多人可能都来不及使用7.0,尤其是那些非职业的flash设计者。

何时进行优化

对现有程序进行优化的过程,有时十分的冗长与困难,这与原始代码的非优化程度有关,所以在投入大量时间进行代码优化之前,最重要的是要估计出要在什么地方对代码做出修改或替换。

一个游戏代码的最重要的部分就是主循环体,通常情况下该循环体要在flash的每一帧上执行,并控制游戏中的角色属性和重要的数据参数。而对于主循环体以外的部分,也可能是次要循环部分,同样要注意是给其否分配了过多的资源,而没有分配给那些更需要资源的核心部分。

通过积累在各处节约出来的时间(可能每处仅仅是几个毫秒),您会明显发现自己的swf运行得更加稳定,并且游戏感也大大加强。

简洁与高效的代码

书写出十分简洁、可以再次调用的代码(有时可能是面向对象的)是一项精细的工作,但这需要多年的编程经验。对于OOP(object oriented programming, 面向对象的程序设计),有些场合根本利用不到它的优势,这使得它显得十分奢侈。 在有限的资源条件下(可能是flash播放器的原因),通过更先进的方法,像刚刚提到的OOP,就可能反而导致令人不满意的结果。

我们并不是说OOP对游戏编程不好,只是在某些场合它显得过于奢侈和多余。毕竟有时候“传统的方法”却能得到更好的结果。

大体而言,用OOP是比较好的,因为它让代码维护更加简单。但在后文中,你会看到有时为了充分发挥flashplayer性能,而不采用OOP技术。例如:处理快速滚动或者计算十分复杂的数学问题。

基本的优化

一提及代码优化,我们马上会联想到执行速度的改进,而很少去考虑系统资源的分配。这是因为当今,即使是将被淘汰的计算机,都有足够的内存来运行我们大部分的flash游戏(128M的内存足以满足大多数情况的需要,况且,512M的内存是当今新电脑的基本配置)


变量

在各种重要的代码优化手段中,有这么一条:在定义局部变量的时候,一定要用关键字var来定义,因为在Flash播放器中,局部变量的运行速度更快,而且在他们的作用域外是不耗占系统资源的。

aw附:var变量仅仅在花括号对中才有“生命”,个人认为没有系统学过编程的人容易出错的一个地方:

awMC.onLoad = function(){
  var aw = 1;
}
awMC.onEnterFrame = function(){
 //不存在aw这个变量
}

一段非优化代码:

function doSomething()
{
	mx = 100
	my = 100
	ar = new Array()
	
	for (y=0; y < my; y++)
	{
		for (x=0; x < mx; x++)
		{
			i = (y * mx) + x
			arr[i] = i			
		}
	}
	return arr
}

这段代码中,并未声明函数体内的那些变量(那些仅仅在函数内使用的变量)为局部变量,这使得这些变量被播放器调用的速度更慢,并且在函数执行完毕的时候仍然耗占系统资源。

下面列出的是经过改进的同样功能的代码:

function doSomething()
{
	var mx = 100
	var my = 100
	var ar = new Array()
	
	for (var y=0; y < my; y++)
	{
		for (var x=0; x < mx; x++)
		{
			var i = (y * mx) + x
			arr[i] = i			
		}
	}
	return arr
}

这样一来所有的变量均被定义为了局部变量,他们能够更快地被播放器调用。这一点在函数大量(10,000次)循环运行时显得尤为重要!当一个函数调用结束的时候,相应的局部变量都会被销毁,并且释放出他们占有的系统资源。

onEnterFrame 事件

onEnterFrame事件对于游戏开发者而言是非常有用的,它使得我们能够快速、反复地按照预设帧频(fps)运行一段程序。回想在Flash5的时代,这(onEnterFrame实时监控)是一种非常流行的技术,用这样的事件来控制机器游戏对手的逻辑,又或者我们可以在每一个子弹上设置这样的事件来监测子弹的碰撞。

实际上,我们并不推荐给过多的MoveClip添加这样的事件,因为这样做会导致“无头绪码(spaghetti code)”的出现,并且容易导致程序效率明显降低。

大多数情况下,用单独一个onEnterFrame事件就可以解决问题了:用这一个主循环来执行你所需要的操作。

另一个简单的办法是设置一个合适的帧频:要知道帧频越高,CPU资源就越紧张。

在帧频为25-35(fps)之间时,onEnterFrame足以很好地执行较复杂代码,哪怕你的计算机配置较低。因此,在没有特殊要求的场合,我们不推荐使用高于60(fps)的帧频。

矢量图与位图

在处理图形前,我们一定要做出正确的选择。Flash能对矢量图和位图进行完美的兼容,然而矢量图和位图在播放器中的表现实质却完全不同。

在用到矢量图的时候,我们要尽可能简化它们的形状,去除多余的端点。这样做将大大降低播放器用于呈现矢量图所要进行的计算量。另一个重要方面在于线条的运用,尽量减少和避免冗陈的线条结构,因为它们会直接影响到flash的播放效率。

当某个实例透明度小于100时,也会对播放速率造成影响,所以如果你发现自己的Flash播放速率过慢,就去挑出这些透明的实例来吧!

那么,如果真的需要呈现比较复杂的场景时,你就最好考虑使用位图实现。虽然Flash在对位图的渲染效率上并不是最优越的(比如和Flash的“兄长”Director比起来),但丰富的视觉内容呈现只能靠位图(与位图同复杂度的矢量图形渲染速率非常低)了,这也是很多基于区块的游戏中广泛采用像素图作为背景的原因。顺便要提到的是,Flash虽然对GIF,JPG和PNG都有所支持,但是渲染速度上PNG还是占有绝对优势,所以我们建议flash中的位图都尽可能采用PNG格式。

影片剪辑(MovieClip)的可视性[下面将MovieClip简称为mc]

您可能会经常碰到这样一种情况:有大量不可见/屏幕外的mc等待出场(比如游戏中屏幕外的地图、人物等等)。
要知道,播放器仍然要消耗一定的资源来处理这些不可见/屏幕外的mc,哪怕他们是单帧,非播放的状态。

最好的解决办法之一是给这些mc一个空白帧,当他们不出现在屏幕上时,你能用gotoAndStop()语句跳转到这一帧,从而减少播放器对资源的需求。

请务必记住,这种情况下,简单的设置可见度属性为不可见( _visible = false )是无效的,播放器将继续按照这些mc所停留或播放的帧的复杂度来分配资源 。

数组

数组在各种需要记录数据的应用程序和游戏中都被广泛的使用。

一个典型的例子就是基于区块的Flash游戏,在这样一类的游戏中,地图有时被存放成形如arr[y][x]的二维数组。虽然这是一种很常见的方法,但是如果用一维数组的话,却能提高程序的运行效率。另一个重要的方法来提高数组效率是在数组遍历的时候使用for in 循环来代替传统的 for 或者while循环语法。
例如:

一段代码如下

for (var i in arr)
{
	if (arr[i] > 50)
	{
		// 进行某些操作
	}
}

它的执行速度明显高于这一段代码:

for (var i=0; i<10000; i++)
{
	if (arr[i] > 50)
	{
		// 进行某些操作
	}
}

前者的效率比后者提高了30%,这个数字在你的游戏要逐帧执行这一段代码的时候显得更加宝贵!

高级优化:

这里我们对一些游戏中的常用代码进行了效率测试,并给出了结果。其中有一些思路借鉴了本文最后所提到的一些个人或者团体。

我们在两个不同型号的电脑上进行了测试。

AthlonXP 2.6Ghz 台式机 512M内存,Windows2000Pro

P4 2.0Ghz 笔记本 ,WindowsXP家庭版

每一项测试都分为三组,取平均值得到最后结果。

测试的结果单位为“毫秒”,反映了代码执行时间。显然,数值越小,反映代码的性能越好。

所有的代码均由MX2004编译生成的Flash6.0版本。有趣的是,我们可以看到由MX和MX2004编译的差距。

所有的测试细节可以看这个PDF文件(aw注:未翻译,很简单的PDF文档,都能看懂的)

我把测试的结果如下归纳出来,同大家分享:

1) for循环while循环

while循环将会得到比for循环更好的效率。然而,从数组中读取数据,用for in循环式最好的选择!

所以我们推荐使用:

for (var i=0; i<1000; i++)
{
	//进行某些操作
}

推荐使用

var i=-1
while (++i < 1000)
{
	//进行某些操作
}

2) 从数组中读取数据

我们通过测试发现,for in循环的效率大大高于其他的循环方式。参看:

arr = []
MAX = 5000
// Fill an array
for (i=0; i < MAX; i++)
{
	arr[i] = i
}
var item = null
// For Loop
for (var i=0; i < MAX; i++)
{
	item = arr[i]
}
// For In Loop
for (var i in arr)
{
	item = arr[i]
}
// While Loop
i = -1
while(++i < MAX)
{
	item = arr[i]
}

3) 向数组中写入数据(while , for)

可以看到while循环稍占优势。

4) _global(全局)变量同Timeline(时间轴)变量

我们猜测采用全局变量能提高变量调用速度,然而效果并不像预计的那样明显。

5) 行、变量赋值

我们发现单行变量赋值效率大大高于多行。比如:

 

a = 0
b = 0
c = 0
d = 100
e = 100

的效率就不如

a = b = c = 0
d = e = 100

6) 变量名寻址

这个测试反映了变量名的预寻址是非常重要的,尤其是在循环的时候,一定要先给丁一个指向。这样大大节约了寻址时间。

比如:

var num = null
t = getTimer()
for (var i=0; i < MAX; i++)
{
	num = Math.floor(MAX) - Math.ceil(MAX)
}
t1.text = "Always lookup: " + (getTimer() - t)

不如

t = getTimer()
var floor = Math.floor
var ceil  = Math.ceil
for (var i=0; i < MAX; i++)
{
	num = floor(MAX) - ceil(MAX)
}

7) 变量名和变量名

变量名越短,效率越高。考虑到长变量名也有它的好处(比如,便于维护等),因此建议在关键部位(比如大量循环出现的时候)使用短变量名,最好就1-2个字符。

8) 循环前、后声明变量

在测试前,我们认为循环前声明变量会更加节约时间,不料测试结果并不明显,甚至还恰恰相反!

// 内部声明
t = getTimer()
for (var i=0; i < MAX; i++)
{
	var test1 = i
}
t1.text = "Inside:" + (getTimer() - t)
// 外部声明
t = getTimer()
var test2
for (var i=0; i < MAX; i++)
{
	test2 = i
}

9) 使用嵌套的if结构

当用到复杂的条件表达式时。把他们打散成为嵌套的独立判断结构是最佳方案。下面的代码我们进行了测试,发现这种效果改进明显!

MAX = 20000
a = 1
b = 2
c = -3
d = 4
var i=MAX
while(--i > -1)
{
	if (a == 1 && b == 2 && c == 3 && d == 4)
	{
		var k = d * c * b * a
	}
}
//下面的判断更加节省时间
var i=MAX
while(--i > -1)
{
	if (a == 1)
	{
		if (b == 2)
		{
			if (c == 3)
			{
				if (d == 4)
				{
					var k = d * c * b * a
				}
			}
		}
	}
}

11) TellTarget语法同“点”语法比较

如果你从Flash5.0开始接触Flash代码,那么你一定会记得那时,我们用“tellTarget”来控制MC。

这里测试表明,用tellTarget比点语法效率更高。所以必要的时候,可以考虑采用这种官方公开否认的语法(aw注:个人觉得有点恍惚,不明白为什么会这样。不过既然测试结果如此,那么也有可行性了……)

MAX = 10000
mc = _root.createEmptyMovieClip("test", 1000)
function test_dot()
{
	var i=MAX
	while(--i > -1)
	{
		mc._x = 10
		mc._y = 10
	}
}
function test_tellTarget()
{
	var i=MAX
	while(--i > -1)
	{
		tellTarget(mc)
		{
			_x = 10
			_y = 10
		}
	}
	
}

12) 寻找局部变量(this方法同with方法比较)

局部变量的定位方法很多。我们发现用with比用this更加有优势!

obj = {}
obj.a = 1
obj.b = 2
obj.c = 3
obj.d = 4
obj.e = 5
obj.f = 6
obj.g = 7
obj.h = 8
obj.test1 = useThis
obj.test2 = useWith
MAX = 10000
function useThis()
{
	var i = MAX
	while(--i > -1)
	{
		this.a = 1
		this.b = 2
		this.c = 3
		this.d = 4
		this.e = 5
		this.f = 6
		this.g = 7
		this.h = 8
	}
}
function useWith()
{
	var i = MAX
	while(--i > -1)
	{
		with(this)
		{
			a = 1
			b = 2
			c = 3
			d = 4
			e = 5
			f = 6
			g = 7
			h = 8
		}
	}
}

13) 循环监听键盘事件

同刚才所提到的寻址一样,我们实现给一个指向会得到更好的效率,比如:

keyDown = Key.isDown 
keyLeft = Key.LEFT
//我们再用 if (keyDown(keyLeft))

附:我们测试了按键代码和键值常量的效率发现并无太大差别。

14) Math.floor()方法与int()

这个问题曾在Flashkit的论坛被提出讨论过。测试表明,int方法反而效率更高。我们的测试结果也反映了这一点。

15) eval表达式与中括号语法

我们并没有发现明显的差别,并不像刚才所述那样,旧的eval表达式比起中括号方法并没有太大的优势

var mc = eval("_root.myMc" + i)
var mc = _root["myMc" + i]
//两者效率差不多

16) 涉及MC的循环:ASBroadcaster 同欢同循环的差别

测试反映,用未公开的ASBroadcaster 方法能大大提高对MC的循环操作的效率。我们的测试中,建立了500个MC,然后测试把它们清楚所花费的时间。

传统的循环式:

MAX = 500
SX = 550
SY = 330
MovieClip.prototype.onCustomEvent = function()
{
	this.removeMovieClip()
}
function init()
{
	var i=MAX
	var rnd = Math.random
	while(--i > -1)
	{
		var m = _root.attachMovie("enemy","e"+i,i)
		m._x = rnd() * SX
		m._y = rnd() * SY 
	}
}
init()
function bench()
{
	var t = getTimer()
	var i=MAX
	while(--i > -1)
	{
		_root["e"+i].onCustomEvent()
	}
	res.text = "time: " + (getTimer() - t)
}

同样的效果,用事件广播(ASBroadcaster)

MAX = 500
evtManager = {}
ASBroadcaster.initialize(evtManager)
SX = 550
SY = 330
MovieClip.prototype.onCustomEvent = function()
{
	this.removeMovieClip()
}
function init()
{
	var i=MAX
	var rnd = Math.random
	while(--i > -1)
	{
		var m = _root.attachMovie("enemy","e"+i,i)
		m._x = rnd() * SX
		m._y = rnd() * SY 
		evtManager.addListener(m)
	}
}
init()
function bench()
{
	var t = getTimer()
	evtManager.broadcastMessage("onCustomEvent")
	res.text = "time: " + (getTimer() - t)
}

用MX04为6.0播放器编译、生成文件:

在MX04种,一件有趣的事是,脚本编译器的性能在各方面提高不少。新的编译器在局部、全局变量寻址效率方面有极大的提高,您还可以通过PDF文件发现很多有趣的结果:全局变量寻址比时间轴变量更快了,而嵌套循环也有所改进。几乎每一个用MX04编译的代码效率都高于MX版本。

awflasher.com附:为什么要为6.0编译呢,国外还有相当一部分用户在使用MX6.0。虽然7.0Player是免费的,但是在国外升级软件似乎不像国内这么火,什么东西马上升到最高。我个人的一些猜测而已

结论:

我们从这些测试结果中发现,对于不同的需求,采用不同的代码,我们可以大大提高脚本的执行效率。虽然我们在这里罗列了许多的优化代码的方法,需要大家自己测试、实验的还有很多(考虑到每个人的需求不同).如果你想更加深入地讨论这类问题。可以来我们的论坛

aw附:

终于翻译完了,自己也学到很多好东西,大家又什么问题可以去gotoAndPlay的官方,也可以来我的Blog提出!

这片HTML文档也可以直接保存(浏览器-文件-另存即可),不含有任何图片,下到本地亦可查看:)

]]>
Thu,27 Sep 2007 23:27:35 CST 0
<![CDATA[Aswing 和 MVC]]> .html Aswing 和 MVC

我们用AsWing 开发应用程序的时候,可以考虑用 MVC,下面我来帖一个我自己平时用的 MVC 的写法。
如果还一直对 “逻辑代码与界面代码混淆” 感到困扰的话,可以参考一下这样的写法。

大概是这样的。

有一个 View 类,这个类负责建立界面,然后界面上需要活动的组件通过 getXXX 方式向外部提供。
View 当中没有逻辑代码,对外公开的只有对需要活动的组件的访问,至于这些组件是被放置在什么位置,多大等等界面细节外部是看不到的。另一方面,界面的布局发生变化不会影响到 View 以外的类。

有一个 Model 类,这个类就是数据,同时也是一个 EventDispatcher, 当数据发生变化的时候会对外发布事件。

有一个 Controller 类,这个类有两个通道,一个通道监听界面的事件,并且把相应的数据写入 Model。另一个通道负责监听Model 的事件,把更新显示到 View 上面。

主程序是这样的:

var view:View = new View(this);
                       
var model:Model = new Model();
                       
var controller:Controller = new Controller();
controller.setModel(model);
controller.setView(view);

controller.start();
View 类的代码是这样的:

package example {
        import org.aswing.JLabel;
        import org.aswing.JButton;
        import org.aswing.JTextField;
        import org.aswing.JFrame;
        import flash.display.DisplayObjectContainer;
        import org.aswing.SoftBoxLayout;
        import org.aswing.JPanel;
        import org.aswing.GridLayout;
        import org.aswing.border.LineBorder;
        import org.aswing.Container;
        import org.aswing.ASColor;
        import org.aswing.border.TitledBorder;
        import org.aswing.BorderLayout;
        import org.aswing.FlowLayout;
       
        public class View {
                private var label:JLabel;
                private var textField:JTextField;
                private var btn:JButton;
               
                public function View(owner:DisplayObjectContainer) {
                        this.build(owner);
                }
               
                protected function build(owner:DisplayObjectContainer) :void {
                       
                        this.label = new JLabel("No Data");
                        this.textField = new JTextField();
                        this.btn = new JButton("向 Model 提交");
                       
                        var frame:JFrame = new JFrame(owner, "显示界面", true);
                        frame.setSizeWH(300, 200);
                        frame.setLocationXY(18, 18);
                        frame.setBackground(ASColor.WHITE);
                        frame.setVisible(true);
                       
                        var c:Container = frame.getContentPane();
                        c.setLayout(new SoftBoxLayout(SoftBoxLayout.Y_AXIS, 15, SoftBoxLayout.CENTER));
                       
                        var panel0:JPanel = new JPanel(new BorderLayout());
                        panel0.setBorder(new TitledBorder(null, "这里显示从 Model 获取的内容", 1.0, 0.0, 0.0, 3.0));
                        panel0.append(this.label);
                       
                        c.append(panel0);
                       
                        var panel1:JPanel = new JPanel(new BorderLayout());
                        panel1.setBorder(new TitledBorder(null, "输入您要提交给 Model 的内容", 1.0, 0.0, 0.0, 3.0));
                        panel1.append(this.textField);
                       
                        c.append(panel1);
                       
                        var panel2:JPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
                        panel2.append(this.btn);
                       
                        c.append(panel2);
                }
               
                public function getLabel() :JLabel {
                        return this.label;
                }
               
                public function getTextField() :JTextField {
                        return this.textField;
                }
               
                public function getButton() :JButton {
                        return this.btn;
                }
        }
}
Model 类的代码是这样的:

package example {
        import flash.events.EventDispatcher;
        import flash.events.Event;
       
        public class Model extends EventDispatcher {
                private var data:String;
               
                public function setData(src:String) :void {
                        if (src != data) {
                                this.data = src;
                       
                                var event:Event = new Event(Event.CHANGE);
                                this.dispatchEvent(event);
                        } else {
                                //pass
                        }
                }
               
                public function getData() :String {
                        return this.data;
                }
        }
}
Controller 类的代码是这样的:

package example {
        import flash.events.Event;
        import flash.events.MouseEvent;
        import org.aswing.event.AWEvent;
       
        public class Controller {
               
                private var model:Model;
               
                private var view:View;
               
                public function Controller(model:Model=null, view:View=null) {
                        this.setModel(model);
                        this.setView(view);
                }
               
                public function setModel(model:Model) :void {
                        this.model = model;
                }
               
                public function setView(view:View) :void {
                        this.view = view;
                }
               
                //start controling
                public function start() :void {
                        var inController:InputController = new InputController(this.view, this.model);
                        var outControler:OutputController = new OutputController(this.view, this.model);
                }
        }
}
        import flash.events.Event;
        import example.View;
        import example.Model;
        import org.aswing.JLabel;
       

class InputController {
        private var view:View;
        private var model:Model;
       
        public function InputController(view:View, model:Model) {
                this.view = view;
                this.model = model;
               
                this.view.getButton().addActionListener(this.actionPerformed);
        }
       
        public function actionPerformed(e:Event) :void {
                var src:String = this.view.getTextField().getText();
                this.model.setData(src);
        }
}

class OutputController {
        private var view:View;
        private var model:Model;
       
        public function OutputController(view:View, model:Model) {
                this.view = view;
                this.model = model;
               
                this.model.addEventListener(Event.CHANGE, this.actionPerformed);
        }
       
        public function actionPerformed(e:Event) :void {
                var data:String = this.model.getData();
                this.view.getLabel().setText(data);
        }
}

]]>
Thu,27 Sep 2007 21:42:51 CST 0
<![CDATA[Flash全站的技术应用(七)——解决Flash中FileReference类的路径获取问题]]> .html 如果写后台通信,我想我可以补充的,也就是一些后台管理的技巧了,但是,我的站在后台管理方面,其实是乱七八糟的,每次更新都很麻烦,尽管自己也制作了一些方便更新的脚本或程序,但是,最失败的一点就是始终无法离开FTP的上传。所以,这方面的内容,还是等我经验积累多了再跟大家谈,以免贻笑大方。

火山的Flash+asp教程:
http://bbs.blueidea.com/thread-2701824-1-1.html

废话说完了,转入正题。
其实这个问题,我一直都忽略了。我是从Flash MX时代走过来的人,MX2004出来后,AS就没有再去认真地学下去,直到现在,Player7后的很多新功能我几乎都没有用过,像Tween类,filters类等等。
FileReference类其实也有很长一段时间没引起我的兴趣,但是,看了Flash 8自带的Sample以后,发觉这东东蛮有用的,可以选择本地图片,然后显示在Flash里头。
不过,它的显示是通过上传,然后再下载来实现的,觉得很麻烦,看个本地图片也要经过网络(不过当初没有怪它,大概是要演示FileReference类的upload吧),决定把它改装一下,做个本地的图片浏览器。Flash 8能支持jpg,gif,png三类图片,能改出来觉得用途还是有滴。
然而,一切都让我失望了,搞了大半天,都不能把图片直接读出来,就是因为FileReference类无法获取文件的路径,只能得到文件名,想用loadMovie或者mcLoader类通过图片路径读取相应图片,还是没办法。可是,感觉只是差一点点啊。
虽然帮助文件没有提到如何获取文件路径,但是我仍不死心,总感觉是有的,于是,我写了下面的代码测试:
import flash.net.FileReference;
var fr:FileReference = new FileReference();
fr.browse();
var listener:Object=new Object();
fr.addListener(listener)
listener.onSelect = function(file:FileReference) {
    for (var i in file) {
        trace(i+":"+file[i]);
    }
};
选好了一个文件以后,输出的结果
_listeners:[object Object]
creator:undefined
creationDate:Thu Feb 15 20:58:03 GMT+0800 2007
modificationDate:Thu Feb 15 20:58:04 GMT+0800 2007
size:3753620
type:.mp3
name:2007127171248.mp3
晕了,用for来枚举都得不到路径,看来这次是彻底绝望了。限制安全性也不用限制成这样吧,Macromedia?
而且,这也将意味着,代码中的file对象不能自己手动构造,必须通过FileReference的browse方法来构造。因为,仅通过输出的结果,是不可能得到你浏览的文件的,就是因为没了路径。
通过各大搜索引擎去寻找如何获取文件路径的答案,都是只有问的,没有回答的。
因为问这一问题的人不多,所以,这事情早搁浅了,一直没管它。
后来,朱高兄想做个可以播放本地音乐的播放器,是因为他看中了Flash 8的FileReference类。但是,当我道出了FileReference类不能获得文件路径的真相以后,他的这一想法就像我当初做图片浏览器的想法那样,给打消了。

最近又有人问到了此问题,看来,也是时候要研究下了。
http://bbs.blueidea.com/thread-2721771-1-1.html

要解决FileReference中的这一问题,至少目前来说,靠Flash是没有用的了,既然网页里头的文件域有完整路径,我们为何不去应用一下呢?

所以,解决此问题,用到的,主要还是Flash与js的通讯了,之前的教程都是用fscommand来弄,这次尝试用ExternalInterface来实现,所以,接下来会先介绍ExternalInterface类的用法(这个相信大多数人会了,说简单些),然后就是文件域中的一个相当于FileReference中browse的一个方法,以及类似于FileReference中onSelect的一个事件。

演示地址:http://hbro.cincn.com/HBrO/course/fileField/fileField.html

(续)
进入实例讲解之前,先介绍上面所说的几点内容:
1 ExternalInterface类的使用
这里均以网页里Flash与js的通讯为例。首先,在Flash里头,ExternalInterface类是在Flash.net包里头,一般为方便以后调用该类时不输入此路径,as里会先添加
import flash.net.FileReference
添加了这一句以后,在使用该类时,就不需要重复输入flash.net了。
接着,要在Flash里头调用js的函数,可以使用call方法
call(methodName:String, [parameter1:Object]) 
为方便演示,我使用js一个内置的alert方法来进行测试。
新建个Flash文档,保存为ExternalInterface.fla,然后输入下面的代码:
import flash.net.FileReference;
ExternalInterface.call("alert",1);
发布一下,然后在IIS下测试你刚生成的网页,就会看到有个1的对话框出来了。就是说,Flash调用js的函数这一步已经实现。
然后,就是到js控制Flash了。js可以调用Flash里头的函数,这里,ExternalInterface类也起到重要的作用。
要使Flash里头某个函数可以被js调用,需要用ExternalInterface对其进行注册:
addCallback(methodName:String, instance:Object, method:Function) : Boolean
其中,methodName是给js调用的名称,instance是as函数所在的实例,method则是as里头函数的名称
返回一个布尔值,指示调用是否成功,不过下面的演示把这个返回值忽略。
在ExternalInterFace.fla里头,追加代码:
ExternalInterface.addCallback("gotoGoogle",this,goto_Google);
function goto_Google(){
  getURL("http://www.google.com","_blank");
}
然后,用Ctrl+Enter生成下Flash影片。
在ExternalInterFace.html里头,找到</body>,在此前面添加代码:
<a href="#" onclick="ExternalInterface.gotoGoogle">gotoGoogle</a>
保存下html,运行,点上面的gotoGoogle按钮,将打开google的首页。也就是说,as里头的goto_Google函数已经通过js被调用起来了。

2 网页文件域中文件路径的获取
既然要使用文件域了,那么,文件域的路径如何获取就必须解决。使用的就是文件域的value属性,这跟文本域的获取方法一样。但是,这个属性貌似只好读取,不好设置,设置的话,通过file.value="xxx",文件域里的文本框似乎没有跟着变化。可能有一个设置值的函数吧,但是还没找出来。
测试的代码比较简单
<input type="file" id="a" /><br />
<input type="button" onclick="alert(a.value)" value='查看'>
a为文件域的id,通过一个按钮点击以后,文件域的路径就通过对话框显示出来。

3 替代“浏览”按钮的方法
因为要在Flash里头调用,所以,用户使用的时候,是不点文件域后面的浏览按钮的。那么,如何代替这一按钮,让我们可以自行打开本地浏览窗口,并且对文件域的值进行设置呢?
为寻找这个问题的答案,我可以说是几经艰辛,虽然本帖的问题是昨晚解决的,但是FileReference类,文件域等问题就困扰了我很久。
在介绍网页制作的书里头,说到表单元素的插入时,很多都对各种表单元素如何设置值,如何设置属性都讲得很详细。Dreamweaver中,属性面板的任何一项都介绍得相当清楚。像文本域,初始值,最大字符数等等,都会讲得一清二楚。如果书中包含js的内容,那么,如何用js对文本域进行设置也会有相应的讲解。
然而,尽管文件域也不能躲开作者的笔下,但是,文件域的介绍总是几句带过,讲完如何插入就完事了。如何进行设置也很少进行深入讲解,同样,作者也会想方设法在js部分省略掉文件域的内容。有的通过全面的调查表单实例,让读者感到全面,而不再追究如何使用文件域,有的则在对某一元素的设置进行讲解,而叫读者举一反三,于是,由于文本域使用频率不高,读者看完书后,也就不会有问题反馈给作者。但实际上,他们对文本域的一些用法还是不那么了解。
但是,造成这一问题也不能完全归因于作者,毕竟文件域具有它的特殊性。
表单最初是用于给用户提交数据给后台用的。在不包含文件域的表单中,提交的数据基本上都是ASCII的字符串,或者说,提交的数据在记事本中打开不会有乱码。后台在获取这些数据的时候,通常使用Request("xxx")就可以成功获取并进行处理了。但是,文件域所提交出去的数据则不一样,它包含了文件域中相应文件的每个字节,可能包含二进制数据,不能为记事本所识别,用的时候,单靠Request不能成事,还需要用到上传组件,ASP的话,有的会使用无组件上传类。虽然处理二进制数据很多时候用的是Request.BinaryRead,Request.BinaryWrite,但相比起不带文件域的表单来说,要复杂些。在网页程序的书或教程里头,提交含文件域的表单要独立出来讲解,说明文件域在后台处理方面具有特殊性。
随着js客户端脚本的发展,以及服务器负担日益加重的趋势,表单的数据若都直接传输,服务器将更容易崩溃。因此,表单的内容很多时候都会先在前台处理一下,以减少不必要的传输。在一些简单应用中,甚至所有表单数据都不提交到后台,一切皆为前台服务。在这情况下,文件域的应用也不广泛,如果只考虑前台,文件域不过比文本域多了个浏览功能,可以获得一些特定的字符串,而获得这些字符串的目的,很多时候只是要读取或写入文件。然而,在网页前台进行文件的读写操作,一般都会给浏览器的安全性禁止,于是,文件域也就失去了它特有的价值,跟文本域没什么区别了。
所以,文件域的使用会非常容易给人忽略,特别是前台脚本方面。找这个“浏览”方法,也就很让我头痛。尝试使用过for in枚举,但可惜,只能得到属性和事件,没有函数。所以,使用各大搜索引擎,用不同的关键字搜索,都无法找到答案。
经过一小时的查找和尝试,我居然在经典论坛前台区600多天前一个讨论css的帖里头一个不是很起眼的回答中找到了问题的答案。
http://bbs.blueidea.com/thread-1803020-1-1.html
3楼的marvellous提供了一个通过隐藏文件域,添加其它表单控件来实现CSS的方法。
<input type=file name=j style="display: none;" onchange="ye.value=value"><input name=ye style="color: green;border: 1px solid green"> <input type=button value="File" onclick=j.click() style="border: 1px solid green">
虽然讨论的是CSS,但是由于他通过外部控制了文件域,所以达到了我要的效果。在此,非常感谢这位版主提供的答案。
在按下一个普通按钮的时候,调用j.click()方法,j又是文件域的id,明显,click就是文件域的浏览函数啦。
有了他的这几句代码,下面的一切就很好解决了。

4 文件域里相当于FileReference类中onSelect的事件
有了上面的代码,这个事件也就不难发现了。因为显示的文本框也不是文件域本身所带的文本框,而是自己另外创建的一个文本域,在测试他代码的过程中,点了自创建的按钮以后,选了文件,文件路径也可以显示在自己做的文本域中,文本域的id是ye,那么,让ye.value=value的事件onchange,自然就是选了文件以后所响应的事件啦。

有了它这一模型以后,我们发现,文件域中我们需要的内容都可以获取了,只要通过ExternalInterface类,把这些内容传给as,就可以实现Flash对文件路径的获取了。

具体步骤如下:
1 在Flash里创建一动态文本或输入文本,用来显示路径,再创建一个浏览按钮。
2 在网页中创建一个隐藏的文件域,给js调用。
3 点Flash的浏览按钮后,通过ExternalInterface.call调用js的一个函数,该函数包含了网页文件域的click方法。
4 打开浏览本地文件的对话框,选择了文件后,响应onchange事件,调用flash里头的一个函数,该函数在Flash里头包含了设置动态文本框文本内容的语句。

下面跟据这些步骤,创建这个Flash版的文件域
(续)

1 新建一个Flash文档,保存为fileField.fla。
然后,在场景里头放一个动态文本框或输入文本框,实例名为fileName,再放一个按钮,实例名为browse_btn。

2 选择“文件”-“发布设置”,点下发布按钮以后,把格式选项卡中的html前的勾去掉(现在不用fscommand了,所以不用像以前那样做跟踪)。
然后,在fileField.fla所在目录下,用记事本打开fileField.html,找到</body>,在前面输入如下代码:
<input type="File" id="myFile" onchange="giveValueToFlash(myFile.value)" style="visibility:hidden">
这里有个giveValueToFlash,就是说,文件域选了文件以后,调用此函数,这一函数在后面定义,将会把文件域的value属性传给Flash。

3 回到fileField.fla,在帧里头输入代码:
import flash.external.ExternalInterface;//载入ExternalInterface类
browse_btn.onRelease = function() {
    ExternalInterface.call("browse");//让Flash调用js的browse函数,这函数等下定义,用于打开浏览对话框
};

转到fileField.html,在</body>前面输入代码:
<script language="javascript">
function browse(){
  myFile.click();//Flash所调用的browse函数就可以因此而打开浏览对话框了
}
</script>

4 在function browse(){}后面,追加onchange事件所响应的giveValueToFlash函数:
function giveValueToFlash(val){
  fileField.setValue(val);//fileField为Flash生成的HTML的swf默认id,这句话就调用fileField的setValue方法,但是,这不是Flash自带的,需要用addCallback来注册。
}

转回fileField.fla,追加代码:
ExternalInterface.addCallback("setValue",this,setTextValue);//让setValue成为Flash的一个方法,setTextValue的意思是:当在网页或者其它容器里头调用Flash的setValue方法时,Flash中的setTextValue将被调用。
//所以下面这个函数就是给外部调用的
function setTextValue(val:String):Void {
    fileName.text = val;//让动态文本或者输入文本的值等于文件域的value属性
}

走到这一步,文件路径已经可以为Flash所获取,但是,可以看到,FileReference类完全没有参与其中,所以,它里头的一切方法,属性,事件你都没办法用上。所以,这一切如果可以封装成一个类就完美了。可惜的是,它要和js代码交互,js存在于网页中,不容易放到AS类里头,但是,看了abc12hjc的保持html干净的办法以后,也可以尝试用getURL("xxx")的办法,把一部分的js写到类里头。加上ExternalInterface类也大量减少了网页的代码,写成类还是可以尝试的。
如果你要用这一个文件域来上传文件的话,就要给回html去提交数据了。但是,html提交数据需要页面跳转,那么,如何实现像Flash一样的无跳转页面上传?mirycat已经提到了,就是用隐藏的iframe上传。具体的我没有在演示地址里实现,不过我会继续补充的。

本来想继续把上传那块教程写出来的,没想到这么快就一堆不能在FF下运行的回复.
哭,给这个FF玩死了.居然连文件域的click方法都不可用.还有什么设置Flash参数的,还是今天才知道怎么弄才能在FF下有效.我倒,FF跟IE的差别太多了,真是头痛.
这回总算给我搞了个可以在FF下运行的了,但是问题还是有的,大家尽管踩吧.反正我就发现不少了.
http://hbro.cincn.com/HBrO/course/fileField(FF)/fileField.html
]]>
Wed,19 Sep 2007 10:17:21 CST 0
<![CDATA[一些flash地址]]> .html http://www.5uflash.com/Html/sljx/145823598.html

http://bbs.blueidea.com/thread-2701824-1-1.html

http://www.webstudio.com.cn/forum/showthread.php?t=235
http://v.mdbchina.com/VideoDetail/

http://www.lukee.cnhttp://www.csksoft.net
http://vamos.cn/
http://www.blog.incito.lt/#/Category/Flash/
http://www.nijj.cn/blog/article.asp?id=2

]]>
Tue,18 Sep 2007 18:33:18 CST 0
<![CDATA[A4纸的另种用途]]> .html

]]>
Tue,18 Sep 2007 14:55:00 CST 0
<![CDATA[理解JavaScript中的事件]]> .html 寒冰 在 理解JavaScript中的事件 日志中写到:
在很多语言的学习中,“事件”都是一个比较难理解,但是又是一个很重要的概念。JavaScript中的事件处理也是一样,正因为有了事件处理,才会出现Ajax拖动的效果。本文就讨论一下JavaScript中的事件处理,读过之后,您就会知道,很多Ajax框架实现拖动效果的原理了。
一、 IE Event对象
(一)IE Event对象的主要属性和方法
  在IE中有一个专门负责事件处理的对象Event,这个对象负责对事件的处理,含有很多的属性和方法,通过这些方法和属性的调用,就能完成很多的事件处理。
  type:事件的类型,就是HTML标签属性中,没有“on”前缀之后的字符串,例如“Click”就代表单击事件。
  srcElement:事件源,就是发生事件的元素。
  button:声明了被按下的鼠标键,是一个整数。1代表鼠标左键,2代表鼠标右键,4代表鼠标的中间键,如果按下了多个鼠标键,就把这些值加在一起,所以3就代表左右键同时按下。
  clientX/clientY:是指事件发生的时候,鼠标的横、纵坐标,返回的是整数,它们的值是相对于包容窗口的左上角生成的。
  offsetX/offsetY:鼠标指针相对于源元素的位置,可以确定单击Image对象的哪个象素。
  altKey,ctrlKey,shiftKey:顾名思义,这些属性是指鼠标事件发生的时候,是否同时按住了Alt、Ctrl或者Shift键,返回的是一个布尔值。
  keyCode:返回keydown和keyup事件发生的时候,按键的代码以及keypress事件的Unicode字符。
  fromElement、toElement前者是指代mouseover事件移动过的文档元素,后者指代mouseout事件中鼠标移动到的文档元素。
  cancelBubble:一个布尔属性,把它设置为true的时候,将停止事件进一步起泡到包容层次的元素。
  returnValue:一个布尔值属性,设置为false的时候可以组织浏览器执行默认的事件动作,相当于<a href=”#” onclick=”ProcessMethod();return false;” />。
  attachEvent()和detachEvent()方法:为制定DOM对象事件类型注册多个事件处理函数的方法,它们有两个参数,第一个是事件类型,第二个是事件处理函数。在attachEvent()事件执行的时候,this关键字指向的是window对象,而不是发生事件的那个元素。
  (二)IE Event对象的一些说明
  1.IE Event对象是一个全局属性
  在IE中,不能把Event对象作为参数传递给事件处理程序,只能用window.event或者event来引用Event对象。因为在IE中,Event是window的一个属性,也就是说event是一个全局变量,这个变量提供了事件的细节。
  2.IE中事件的起泡:IE中事件可以沿着包容层次一点点起泡到上层,也就是说,下层的DOM节点定义的事件处理函数,到了上层的节点如果还有和下层相同事件类型的事件处理函数,那么上层的事件处理函数也会执行。例如,<div>标签包含了<a>,如果这两个标签都有onclick事件的处理函数,那么执行的情况就是先执行<a>标签的onclick事件处理函数,再执行<div>的事件处理函数。如果希望<a>的事件处理函数执行完毕之后,不希望执行上层的<div>的onclick的事件处理函数了,那么就把cancelBubble设置为false即可。
  
二、 IE中拖动DOM元素的例子
/*
  该函数由mousedown事件处理调用
  它为随后发生的mousemove和mouseup事件注册了临时的捕捉事件处理程序
  并用这些事件处理程序拖动指定的文档元素
  第二个参数必须是mousedown事件的事件对象
*/
function beginDrag(elementToDrag,event)
{
  //该元素当前位于何处
  //该元素的样式性质必须具有left和top css属性
  //此外,我们假定他们用象素做单位
  //var x=parseInt(elementToDrag.style.left);
  //var y=parseInt(elementToDrag.style.top);
 
  //计算一个点和鼠标点击之间的距离,下面的嵌套的moveHandler函数需要这些值
  var deltaX=event.clientX-parseInt(elementToDrag.style.left);
  var deltaY=event.clientY-parseInt(elementToDrag.style.top);
 
//  注册mousedown事件后发生的mousemove和mouseup事件的处理程序
//  注意,它们被注册为文档的捕捉事件处理程序
//  在鼠标按钮保持按下的状态的时候,这些事件处理程序保持活动的状态
//  在按钮被释放的时候,它们被删除
  document.attachEvent("onmousemove",moveHandler);
  document.attachEvent("onmouseup",upHandler);
  
  //我们已经处理了该事件,不要让别的元素看到它
 event.cancelBubble=true;
 event.returnValue=false;
 
  /*
    这是在元素被拖动时候捕捉mousemove事件的处理程序,它响应移动的元素
   
  */
  function moveHandler(e) 
  {
    //把元素移动到当前的鼠标位置
    e=window.event;
    elementToDrag.style.left=(event.clientX-deltaX)+"px";
    elementToDrag.style.top=(event.clientY-deltaY)+"px";
   
    //不要让别的元素看到该事件
    event.cancelBubble=true;
   
  }
 
  /*
    该事件将捕捉拖动结束的时候发生的mouseup事件
  */
  function upHandler(e)
  {
    //注销事件处理程序
      document.detachEvent("onmouseup",upHandler);
      document.detachEvent("onmousemove",moveHandler);}
  
      event.cancelBubble=true;
    } 
   调用它的HTML文件代码:
 <html>
 <head>
     <title>Untitled Page</title>
     <script type="text/javascript" src="dragIE.js"></script>
 </head>
 <body>
 <div style="position:absolute;left:100px;top:100px;background-color:White;border:solid black;">
   <div style="background-color:Gray;border-bottom:solid black;padding:3px;font-family:Sans-Serif;font-weight:bold;" onmousedown="beginDrag(this.parentNode,event);">
   拖动我&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
   </div>
   <div>
   <p>This is a test.Testing,testing</p></div>
 </div>
 </body>
三、 DOM中的高级事件处理
 IE 6中的事件处理,并不是W3C DOM标准的事件处理模型,所以如果上述代码运行在Mozilla Firefox的浏览器中,就会失去作用,同时即将发布的IE 7也将支持W3C DOM的二级标准,所以掌握DOM的高级事件处理显得就很重要了,因为W3C DOM二级标准是未来Web的发展方向,同时W3C DOM的API非常常用,为未来更加复杂的Web开发提供了良好的基础。
(一)事件处理程序的作用域和事件的传播
  在正式讨论DOM高级事件处理之前,我们有必要了解一下事件处理程序的作用域。事件处理程序的作用域要比普通的函数作用域复杂很多。普通的函数作用域链比较容易,例如在一个普通函数中查找一个变量a,那么JavaScript解释器会先在该函数的调用对象中查找是否有a这个变量,如果没有,将会在作用域链的下一个对象,一般是全局对象中查找。但是事件处理程序没这么简单,特别是用HTML的属性定义的,它们的作用域链的头部是调用它们的对象,而下一个对象并不是全局对象,而是触发事件处理程序的对象。这样就会出现一个问题,window和document都有一个方法open(),如果open()前面不加修饰,那么在事件处理的函数中将会调用document.open()方法,而不是常用的window.open()方法,所以使用的时候应该明确指明是window.open()。
(二)事件传播和注册事件处理程序
1.事件传播
  在二级DOM标准中,事件处理程序比较复杂,当事件发生的时候,目标节点的事件处理程序就会被触发执行,但是目标节点的父节点也有机会来处理这个事件。事件的传播分为三个阶段,首先是捕捉阶段,事件从Document对象沿着DOM树向下传播到目标节点,如果目标的任何一个父节点注册了捕捉事件的处理程序,那么事件在传播的过程中就会首先运行这个程序。下一个阶段就是发生在目标节点自身了,注册在目标节点上的相应的事件处理程序就会执行;最后是起泡阶段,事件将从目标节点向上传回给父节点,同样,如果父节点有相应的事件处理程序也会处理。在IE中,没有捕捉的阶段,但是有起泡的阶段。可以用stopPropagating()方法来停止事件传播,也就是让其他元素对这个事件不可见,在IE 6中,就是把cancelBubble设置为true。
2.注册事件处理程序
  和IE一样,DOM标准也有自己的事件处理程序,不过DOM二级标准的事件处理程序比IE的强大一些,事件处理程序的注册用addEventListner方法,该方法有三个参数,第一个是事件类型,第二个是处理的函数,第三个是一个布尔值,true表示制定的事件处理程序将在事件传播的阶段用于捕捉事件,否则就不捕捉,当事件发生在对象上才触发执行这个事件处理的函数,或者发生在该对象的字节点上,并且向上起泡到这个对象上的时候,触发执行这个事件处理的函数。例如:document.addEventListener("mousemove",moveHandler,true);就是在mousemove事件发生的时候,调用moveHandler函数,并且可以捕捉事件。
  可以用addEventListener为一个事件注册多个事件处理的程序,但是这些函数的执行顺序是不确定,并不像C#那样按照注册的顺序执行。
  在Mozilla Firefox中用addEventListener注册一个事件处理程序的时候,this关键字就表示调用事件处理程序的文档元素,但是其他浏览器并不一定是这样,因为这不是DOM标准,正确的做法是用currentTarget属性来引用调用事件处理程序的文档元素。
3.二级DOM标准中的Event
  和IE不同的是,W3C DOM中的Event对象并不是window全局对象下面的属性,换句话说,event不是全局变量。通常在DOM二级标准中,event作为发生事件的文档对象的属性。Event含有两个子接口,分别是UIEvent和MutationEvent,这两个子接口实现了Event的所有方法和属性,而MouseEvent接口又是UIEvent的子接口,所以实现了UIEvent和Event的所有方法和属性。下面,我们就看看Event、UIEvent和MouseEvent的主要属性和方法。
  1.Event
    type:事件类型,和IE类似,但是没有“on”前缀,例如单击事件只是“click”。
    target:发生事件的节点。
    currentTarget:发生当前正在处理的事件的节点,可能是Target属性所指向的节点,也可能由于捕捉或者起泡,指向Target所指节点的父节点。
    eventPhase:指定了事件传播的阶段。是一个数字。
    timeStamp:事件发生的时间。
    bubbles:指明该事件是否起泡。
    cancelable:指明该事件是否可以用preventDefault()方法来取消默认的动作。
    preventDefault()方法:取消事件的默认动作;
    stopPropagation()方法:停止事件传播。
  2.UIEvent
    view:发生事件的window对象。
    detail:提供事件的额外信息,对于单击事件、mousedown和mouseup事件都代表的是点击次数。
  3.MouseEvent
   button:一个数字,指明在mousedown、mouseup和单击事件中,鼠标键的状态,和IE中的button属性类似,但是数字代表的意义不一样,0代表左键,1代表中间键,2代表右键。
   altKey、ctrlKey、shiftKey、metaKey:和IE相同,但是IE没有最后一个。
   clientX、clientY:和IE的含义相同,但是在DOM标准中,这两个属性值都不考虑文档的滚动情况,也就是说,无论文档滚动到哪里,只要事件发生在窗口左上角,clientX和clientY都是0,所以在IE中,要想得到事件发生的坐标相对于文档开头的位置,要加上document.body.scrollLeft和document.body.scrollTop。
   screenX、screenY:鼠标指针相对于显示器左上角的位置,如果你想打开新的窗口,这两个属性很重要。
   relatedTarget:和IE中的fromElement、toElement类似,除了对于mouseover和mouseout有意义外,其他的事件没什么意义。
(三)兼容于两种主流浏览器的拖动DOM元素的例子
  好了,刚才讲了这么多DOM编程和IE中的事件,那么如何编写兼容IE和Mozilla Firefox两种主流浏览器的拖拽程序呢?代码如下:
function beginDrag(elementToDrag,event)
{
  var deltaX=event.clientX-parseInt(elementToDrag.style.left);
  var deltaY=event.clientY-parseInt(elementToDrag.style.top);
 
if(document.addEventListener)
{
  document.addEventListener("mousemove",moveHandler,true);
  document.addEventListener("mouseup",upHandler,true);
}
else if(document.attachEvent)
{
  document.attachEvent("onmousemove",moveHandler);
  document.attachEvent("onmouseup",upHandler);
 
}
 
  if(event.stopPropagation)   event.stopPropagation();
  else event.cancelBubble=true;
  if(event.preventDefault)  event.preventDefault();
  else event.returnValue=false;
 
  function moveHandler(e) 
  {
  if (!e) e=window.event; //如果是IE的事件对象,那么就用window.event
  //全局属性,否则就用DOM二级标准的Event对象。
    elementToDrag.style.left=(event.clientX-deltaX)+"px";
    elementToDrag.style.top=(event.clientY-deltaY)+"px";
   
     if(event.stopPropagation)   event.stopPropagation();
    else event.cancelBubble=true;
   
  }
 
  function upHandler(e)
  {
       if(document.removeEventListener)
    {
      document.removeEventListener("mouseup",upHandler,true);
      document.removeEventListener("mousemove",moveHandler,true);}
      else
    {
      document.detachEvent("onmouseup",upHandler);
      document.detachEvent("onmousemove",moveHandler);}
    }
      if(event.stopPropagation)   event.stopPropagation();
    else event.cancelBubble=true;
   
  }

]]>
Thu,23 Aug 2007 09:54:05 CST 0
<![CDATA[理解JavaScript中的事件]]> .html 一、 IE Event对象
(一)IE Event对象的主要属性和方法
  在IE中有一个专门负责事件处理的对象Event,这个对象负责对事件的处理,含有很多的属性和方法,通过这些方法和属性的调用,就能完成很多的事件处理。
  type:事件的类型,就是HTML标签属性中,没有“on”前缀之后的字符串,例如“Click”就代表单击事件。
  srcElement:事件源,就是发生事件的元素。
  button:声明了被按下的鼠标键,是一个整数。1代表鼠标左键,2代表鼠标右键,4代表鼠标的中间键,如果按下了多个鼠标键,就把这些值加在一起,所以3就代表左右键同时按下。
  clientX/clientY:是指事件发生的时候,鼠标的横、纵坐标,返回的是整数,它们的值是相对于包容窗口的左上角生成的。
  offsetX/offsetY:鼠标指针相对于源元素的位置,可以确定单击Image对象的哪个象素。
  altKey,ctrlKey,shiftKey:顾名思义,这些属性是指鼠标事件发生的时候,是否同时按住了Alt、Ctrl或者Shift键,返回的是一个布尔值。
  keyCode:返回keydown和keyup事件发生的时候,按键的代码以及keypress事件的Unicode字符。
  fromElement、toElement前者是指代mouseover事件移动过的文档元素,后者指代mouseout事件中鼠标移动到的文档元素。
  cancelBubble:一个布尔属性,把它设置为true的时候,将停止事件进一步起泡到包容层次的元素。
  returnValue:一个布尔值属性,设置为false的时候可以组织浏览器执行默认的事件动作,相当于<a href=”#” onclick=”ProcessMethod();return false;” />。
  attachEvent()和detachEvent()方法:为制定DOM对象事件类型注册多个事件处理函数的方法,它们有两个参数,第一个是事件类型,第二个是事件处理函数。在attachEvent()事件执行的时候,this关键字指向的是window对象,而不是发生事件的那个元素。
  (二)IE Event对象的一些说明
  1.IE Event对象是一个全局属性
  在IE中,不能把Event对象作为参数传递给事件处理程序,只能用window.event或者event来引用Event对象。因为在IE中,Event是window的一个属性,也就是说event是一个全局变量,这个变量提供了事件的细节。
  2.IE中事件的起泡:IE中事件可以沿着包容层次一点点起泡到上层,也就是说,下层的DOM节点定义的事件处理函数,到了上层的节点如果还有和下层相同事件类型的事件处理函数,那么上层的事件处理函数也会执行。例如,<div>标签包含了<a>,如果这两个标签都有onclick事件的处理函数,那么执行的情况就是先执行<a>标签的onclick事件处理函数,再执行<div>的事件处理函数。如果希望<a>的事件处理函数执行完毕之后,不希望执行上层的<div>的onclick的事件处理函数了,那么就把cancelBubble设置为false即可。
  
二、 IE中拖动DOM元素的例子
/*
  该函数由mousedown事件处理调用
  它为随后发生的mousemove和mouseup事件注册了临时的捕捉事件处理程序
  并用这些事件处理程序拖动指定的文档元素
  第二个参数必须是mousedown事件的事件对象
*/
function beginDrag(elementToDrag,event)
{
  //该元素当前位于何处
  //该元素的样式性质必须具有left和top css属性
  //此外,我们假定他们用象素做单位
  //var x=parseInt(elementToDrag.style.left);
  //var y=parseInt(elementToDrag.style.top);
 
  //计算一个点和鼠标点击之间的距离,下面的嵌套的moveHandler函数需要这些值
  var deltaX=event.clientX-parseInt(elementToDrag.style.left);
  var deltaY=event.clientY-parseInt(elementToDrag.style.top);
 
//  注册mousedown事件后发生的mousemove和mouseup事件的处理程序
//  注意,它们被注册为文档的捕捉事件处理程序
//  在鼠标按钮保持按下的状态的时候,这些事件处理程序保持活动的状态
//  在按钮被释放的时候,它们被删除
  document.attachEvent("onmousemove",moveHandler);
  document.attachEvent("onmouseup",upHandler);
  
  //我们已经处理了该事件,不要让别的元素看到它
 event.cancelBubble=true;
 event.returnValue=false;
 
  /*
    这是在元素被拖动时候捕捉mousemove事件的处理程序,它响应移动的元素
   
  */
  function moveHandler(e) 
  {
    //把元素移动到当前的鼠标位置
    e=window.event;
    elementToDrag.style.left=(event.clientX-deltaX)+"px";
    elementToDrag.style.top=(event.clientY-deltaY)+"px";
   
    //不要让别的元素看到该事件
    event.cancelBubble=true;
   
  }
 
  /*
    该事件将捕捉拖动结束的时候发生的mouseup事件
  */
  function upHandler(e)
  {
    //注销事件处理程序
      document.detachEvent("onmouseup",upHandler);
      document.detachEvent("onmousemove",moveHandler);}
  
      event.cancelBubble=true;
    } 
   调用它的HTML文件代码:
 <html>
 <head>
     <title>Untitled Page</title>
     <script type="text/javascript" src="dragIE.js"></script>
 </head>
 <body>
 <div style="position:absolute;left:100px;top:100px;background-color:White;border:solid black;">
   <div style="background-color:Gray;border-bottom:solid black;padding:3px;font-family:Sans-Serif;font-weight:bold;" onmousedown="beginDrag(this.parentNode,event);">
   拖动我&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
   </div>
   <div>
   <p>This is a test.Testing,testing</p></div>
 </div>
 </body>
三、 DOM中的高级事件处理
 IE 6中的事件处理,并不是W3C DOM标准的事件处理模型,所以如果上述代码运行在Mozilla Firefox的浏览器中,就会失去作用,同时即将发布的IE 7也将支持W3C DOM的二级标准,所以掌握DOM的高级事件处理显得就很重要了,因为W3C DOM二级标准是未来Web的发展方向,同时W3C DOM的API非常常用,为未来更加复杂的Web开发提供了良好的基础。
(一)事件处理程序的作用域和事件的传播
  在正式讨论DOM高级事件处理之前,我们有必要了解一下事件处理程序的作用域。事件处理程序的作用域要比普通的函数作用域复杂很多。普通的函数作用域链比较容易,例如在一个普通函数中查找一个变量a,那么JavaScript解释器会先在该函数的调用对象中查找是否有a这个变量,如果没有,将会在作用域链的下一个对象,一般是全局对象中查找。但是事件处理程序没这么简单,特别是用HTML的属性定义的,它们的作用域链的头部是调用它们的对象,而下一个对象并不是全局对象,而是触发事件处理程序的对象。这样就会出现一个问题,window和document都有一个方法open(),如果open()前面不加修饰,那么在事件处理的函数中将会调用document.open()方法,而不是常用的window.open()方法,所以使用的时候应该明确指明是window.open()。
(二)事件传播和注册事件处理程序
1.事件传播
  在二级DOM标准中,事件处理程序比较复杂,当事件发生的时候,目标节点的事件处理程序就会被触发执行,但是目标节点的父节点也有机会来处理这个事件。事件的传播分为三个阶段,首先是捕捉阶段,事件从Document对象沿着DOM树向下传播到目标节点,如果目标的任何一个父节点注册了捕捉事件的处理程序,那么事件在传播的过程中就会首先运行这个程序。下一个阶段就是发生在目标节点自身了,注册在目标节点上的相应的事件处理程序就会执行;最后是起泡阶段,事件将从目标节点向上传回给父节点,同样,如果父节点有相应的事件处理程序也会处理。在IE中,没有捕捉的阶段,但是有起泡的阶段。可以用stopPropagating()方法来停止事件传播,也就是让其他元素对这个事件不可见,在IE 6中,就是把cancelBubble设置为true。
2.注册事件处理程序
  和IE一样,DOM标准也有自己的事件处理程序,不过DOM二级标准的事件处理程序比IE的强大一些,事件处理程序的注册用addEventListner方法,该方法有三个参数,第一个是事件类型,第二个是处理的函数,第三个是一个布尔值,true表示制定的事件处理程序将在事件传播的阶段用于捕捉事件,否则就不捕捉,当事件发生在对象上才触发执行这个事件处理的函数,或者发生在该对象的字节点上,并且向上起泡到这个对象上的时候,触发执行这个事件处理的函数。例如:document.addEventListener("mousemove",moveHandler,true);就是在mousemove事件发生的时候,调用moveHandler函数,并且可以捕捉事件。
  可以用addEventListener为一个事件注册多个事件处理的程序,但是这些函数的执行顺序是不确定,并不像C#那样按照注册的顺序执行。
  在Mozilla Firefox中用addEventListener注册一个事件处理程序的时候,this关键字就表示调用事件处理程序的文档元素,但是其他浏览器并不一定是这样,因为这不是DOM标准,正确的做法是用currentTarget属性来引用调用事件处理程序的文档元素。
3.二级DOM标准中的Event
  和IE不同的是,W3C DOM中的Event对象并不是window全局对象下面的属性,换句话说,event不是全局变量。通常在DOM二级标准中,event作为发生事件的文档对象的属性。Event含有两个子接口,分别是UIEvent和MutationEvent,这两个子接口实现了Event的所有方法和属性,而MouseEvent接口又是UIEvent的子接口,所以实现了UIEvent和Event的所有方法和属性。下面,我们就看看Event、UIEvent和MouseEvent的主要属性和方法。
  1.Event
    type:事件类型,和IE类似,但是没有“on”前缀,例如单击事件只是“click”。
    target:发生事件的节点。
    currentTarget:发生当前正在处理的事件的节点,可能是Target属性所指向的节点,也可能由于捕捉或者起泡,指向Target所指节点的父节点。
    eventPhase:指定了事件传播的阶段。是一个数字。
    timeStamp:事件发生的时间。
    bubbles:指明该事件是否起泡。
    cancelable:指明该事件是否可以用preventDefault()方法来取消默认的动作。
    preventDefault()方法:取消事件的默认动作;
    stopPropagation()方法:停止事件传播。
  2.UIEvent
    view:发生事件的window对象。
    detail:提供事件的额外信息,对于单击事件、mousedown和mouseup事件都代表的是点击次数。
  3.MouseEvent
   button:一个数字,指明在mousedown、mouseup和单击事件中,鼠标键的状态,和IE中的button属性类似,但是数字代表的意义不一样,0代表左键,1代表中间键,2代表右键。
   altKey、ctrlKey、shiftKey、metaKey:和IE相同,但是IE没有最后一个。
   clientX、clientY:和IE的含义相同,但是在DOM标准中,这两个属性值都不考虑文档的滚动情况,也就是说,无论文档滚动到哪里,只要事件发生在窗口左上角,clientX和clientY都是0,所以在IE中,要想得到事件发生的坐标相对于文档开头的位置,要加上document.body.scrollLeft和document.body.scrollTop。
   screenX、screenY:鼠标指针相对于显示器左上角的位置,如果你想打开新的窗口,这两个属性很重要。
   relatedTarget:和IE中的fromElement、toElement类似,除了对于mouseover和mouseout有意义外,其他的事件没什么意义。
(三)兼容于两种主流浏览器的拖动DOM元素的例子
  好了,刚才讲了这么多DOM编程和IE中的事件,那么如何编写兼容IE和Mozilla Firefox两种主流浏览器的拖拽程序呢?代码如下:
function beginDrag(elementToDrag,event)
{
  var deltaX=event.clientX-parseInt(elementToDrag.style.left);
  var deltaY=event.clientY-parseInt(elementToDrag.style.top);
 
if(document.addEventListener)
{
  document.addEventListener("mousemove",moveHandler,true);
  document.addEventListener("mouseup",upHandler,true);
}
else if(document.attachEvent)
{
  document.attachEvent("onmousemove",moveHandler);
  document.attachEvent("onmouseup",upHandler);
 
}
 
  if(event.stopPropagation)   event.stopPropagation();
  else event.cancelBubble=true;
  if(event.preventDefault)  event.preventDefault();
  else event.returnValue=false;
 
  function moveHandler(e) 
  {
  if (!e) e=window.event; //如果是IE的事件对象,那么就用window.event
  //全局属性,否则就用DOM二级标准的Event对象。
    elementToDrag.style.left=(event.clientX-deltaX)+"px";
    elementToDrag.style.top=(event.clientY-deltaY)+"px";
   
     if(event.stopPropagation)   event.stopPropagation();
    else event.cancelBubble=true;
   
  }
 
  function upHandler(e)
  {
       if(document.removeEventListener)
    {
      document.removeEventListener("mouseup",upHandler,true);
      document.removeEventListener("mousemove",moveHandler,true);}
      else
    {
      document.detachEvent("onmouseup",upHandler);
      document.detachEvent("onmousemove",moveHandler);}
    }
      if(event.stopPropagation)   event.stopPropagation();
    else event.cancelBubble=true;
   
  }]]>
Wed,04 Jul 2007 10:06:39 CST 16773800
<![CDATA[首页不更新问题]]> .html Fri,22 Jun 2007 10:55:17 CST 0 <![CDATA[第一次写博客]]> .html Fri,22 Jun 2007 10:48:07 CST 0 <![CDATA[我在博客有家了]]> .html  我已经在博客网落户了,欢迎你时常过来看看,大家多多交流哦。我会在这里记录我的工作也会记录我的心情与你分享。也希望你记住我的地址,你可以把她添加到你的收藏夹(Ctrl+D),也可以把她复制下来告诉你的朋友们

 我的博客地址:  http://gysan.bokee.com

]]>
Thu,21 Jun 2007 16:24:50 CST 0