govo_music
enable marquee in Firefox and Opera/Firefox和Opera下的marquee行为
GOVO 发表于 2007-01-09 12:09:56
W
一、为了在FF和Opera上实现类似marquee的行为,先要了解marquee是怎样的一个行为。
Marquee特有的属性如下:
BEHAVIOR:设置或获取文本如何在字幕中滚动。
值:
scroll Default. Marquee scrolls in the direction specified by the direction property. The text scrolls off the end and starts over.
alternate Marquee scroll direction reverses when its content reaches the edge of the container.
slide Marquee scrolls in the direction specified by the direction property. The text scrolls to the end and stops.
DIRECTION:设置或获取文本滚动的方向。
值:
left Default. Marquee scrolls left.
right Marquee scrolls right.
down Marquee scrolls down.
up Marquee scrolls up.
SCROLLAMOUNT:设置或获取介于每个字幕绘制序列之间的文本滚动像素数。
值:一个整数。Integer that specifies or receives the number of pixels.
SCROLLDELAY:设置或获取字幕滚动的速度,以微秒计算。此值越小,动作就细腻,相当于电影的帖数。
TRUESPEED:设置或获取字幕的位置是否使用 scrollDelay 和 scrollAmount 属性计算,已过的实际时间来自于时钟计时。
Boolean值:默认为false,简单的说,此时scrollDelay的值总是高于60微秒,低于60微秒的也会归于60微秒。如果想得到scrollDelay小于60微秒的行为,就必须设置TRUESPEED为true。
false Default. Marquee computes movement based on 60-millisecond ticks of the clock. This means every scrollDelay value under 60 is ignored, and the marquee advances the amount of scrollAmount each 60 milliseconds. For example, if scrollDelay is 6 and scrollAmount is 10, the marquee advances 10 pixels every 60 milliseconds.
true Marquee advances the pixel value of scrollAmount by the number of milliseconds set for scrollDelay. For example, the marquee would advance 10 pixels for every 6 milliseconds if scrollDelay is 6, scrollAmount is 10, and the value of trueSpeed is true.
二、滚动行为的实现以及对scriptaculous的Effect的简单解释。
滚动当然少不了top和left属性,可以在元素的style.top和style.left中设置。在这里我第一时间想到的就是scriptaculous的Effect.Move方法。可惜这个Effect.Move在这里并不适用。因为scriptaculous的Effect都有一个事件驱动Effect.Base,这个驱动就像一个发动机,可以为Move、HightLight等行为提供强而有为的能源,能让这些从行为开始的结束提供足够的血液。当然你也可以使用它为自己写的行为特供能量,只要你的行为继承了这个驱动。
那么这个驱动是怎样的一个物件呢?能量又是什么呢?上一段说到从开始的结束,没错,每一个事件都有一个开始和结束,这就是此驱动的特性,必须一个开始和结束,而能量就是一个从0到1的浮点值,通过驱动的不断递归执行一系列句柄给行为传送“能量”,而句柄的行为方法就是根据这个“能量”为执行从始到终的行为,从而最终达到Effect的目的。
例如想把一个元素从left:0px到left:300px的移动,在你的方法中就可以这样计算:
currectLeft=能量*300
当“能量”为0时,currectLeft就是0,那么当“能量”为1的时候,cruuectLeft就是300了。
而递归执行的句柄就是一个event,event内执行的就是你写的方法,你可以在过程中写如下方法,而且从下面这方法中你可以看到Effect的整个生命过程:
event name remark
event: beforeStart, 最先执行
event: beforeSetup, 行为初始化前执行
event: afterSetup, 行为初始化后执行
event: beforeUpdate, 从“能量”0到1多次执行,
event: afterUpdate, 从“能量”0到1多次执行
event: beforeFinish, 结束前执行
event: afterFinish, 结束后执行
*另外,你可以在上面的方法中加上Internal后缀(如beforeStartInternal)以表示这是内部执行的,这也是生命周期同时执行的另一条路线。
只要你写的行为包含上面方法,然后继承自Effect.Base就可以实现你想要的了。当然事实上并不是如此的简单,有兴趣可以看看Effect的源码,我所说的只是一个思路。
因为Effect.Base能方便的使效果得以贯彻执行,但在“能量”从0到1的过程是难以让生命停下来的,而marquee需要的是一条没有终点的时间轴,滚动的目标有终点,但时间不能有终点,而且行为的过程与时间息息相关:每SCROLLDELAY微秒滚动多少像素。所以我仿照Effect.Base写了一个MoveSpeed方法:
var GDnew=function(){}//1
GDnews.Effect=function(){};//2
//上面两个方法是为了扩大命名空间
GDnews.Effect.MoveSpeed=Class.create();
GDnews.Effect.MoveSpeed.prototype={
initialize:function(element) {
this.element = $(element);
this.options = Object.extend({
x: 0,
y: 0,
mode: 'relative',
delay:85,
amountX:0,
amountY:0
}, arguments[1] || {});
this.event("beforeSetup");
this.options.amountX=Math.abs(this.options.amountX);
this.options.amountY=Math.abs(this.options.amountY);
this.scroX=0;//目前已经移动的X数目
this.scroY=0;//目前已经移动的Y数目
// Bug in Opera: Opera returns the "real" position of a static element or
// relative element that does not have top/left explicitly set.
// ==> Always set top and left for position relative elements in your stylesheets
// (to 0 if you do not need them)
this.element.makePositioned();
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
if(this.options.mode == 'absolute') {
// absolute movement, so we need to calc deltaX and deltaY
this.options.x = this.options.x - this.originalLeft;
this.options.y = this.options.y - this.originalTop;
}
this.event("afterSetup");
this.scroll();
},
update: function() {
this.event("beforeUpdate");
var _x=Math.abs(this.options.x);
var _y=Math.abs(this.options.y)
var amountX=(this.scroX+this.options.amountX)>=_x ?
(_x-this.scroX/*归零*/) : this.options.amountX;
var amountY=(this.scroY+this.options.amountX)>=_y ?
(_y-this.scroY/*归零*/) : this.options.amountY;
this.scroX+=amountX;//执行X总数累加
this.scroY+=amountY;//执行Y总数累加
this.element.setStyle({
left:Math.round(this.originalLeft+(this.options.x<0 ? -this.scroX : this.scroX)) + 'px',
top:Math.round(this.originalTop+(this.options.y<0 ? -this.scroY : this.scroY)) + 'px'
});
this.event("beforeFinish");
if (amountX==0 && amountY==0){//结束
this.scroY=0;
this.scroX=0;
this.cancel();
this.event("afterFinish");
}
},
scroll:function(){
this.cancel();
this.setTimeInt=window.setInterval(this.update.bind(this),this.options.delay);
},
cancel:function(){
if(this.setTimeInt) window.clearInterval(this.setTimeInt);
this.setTimeInt=null;
},
event: function(eventName) {
if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
if(this.options[eventName]) this.options[eventName](this);
}
}
在这个类的基础上,再写一个实现marquee的类:
GDnews.w3cMarquee=Class.create();
/**
*@param element 目标的marquee标签
*@ nomouseEvent 默认为false,类似传统marquee上的onMouseover=this.stop()系列行为
*此方法在IE中不执行。思路是把marquee删除,用一个div代替它,然后设置此div的left和top来实现滚动。
*/
GDnews.w3cMarquee.prototype={//目前仅实现behavior=scroll
initialize:function(element,nomouseEvent){
if(/MSIE/.test(navigator.userAgent)){//如果是IE,留着真marquee
if(nomouseEvent==true) return;
element=$(element);
Event.observe(element,'mouseover',function(){element.stop()});
Event.observe(element,'mouseout',function(){element.start()});
return;
}
this.marquee=$(element);
if("marquee"!=this.marquee.tagName.toLowerCase()) return;
this._createDiv();//创建DIV
this.makePosition();//设置位置
var _x=this.scrollWidth;
var _y=this.scrollHeight;
var newElementId=this.newElementId;
var options={x:_x,y:_y,delay:this.scrollDelay,
amountX:this.scrollAmount,amountY:this.scrollAmount,
beforeSetup:function(effect){
if(nomouseEvent==true) return;
var cancel=effect.cancel.bind(effect);
var scroll=effect.scroll.bind(effect);
Event.stopObserving(newElementId,'mouseover',cancel);
Event.stopObserving(newElementId,'mouseout',scroll);
Event.observe(newElementId,'mouseover',cancel);
Event.observe(newElementId,'mouseout',scroll);
},
beforeUpdate:function(effect){
// if(behavior=='alternate'){//本想实现'alternate'行为,但由于时间关系,我就把它先留着。
// var left=parseInt(effect.element.getStyle('left'));
// var top=parseInt(effect.element.getStyle('top'));
// see(left+","+top);
// if(effect.scroX>=_parentWidth || effect.scroY>_parentHeight){
// effect.options.x=-1*effect.options.x;
// effect.options.y=-1*effect.options.y;
// effect.cancel();
// window.setTimeout(effect.scroll.bind(effect),100);
// }
// }
},
afterFinish:function(effect){
/*if(behavior=='scroll'){*/
effect.element.setStyle({left:effect.originalLeft,top:effect.originalTop});
window.setTimeout(effect.scroll.bind(effect),100);
/*}*/
}
};
new GDnews.Effect.MoveSpeed(this.scrollId,options);
},
_createDiv:function(){
this.newElementId=(this.marquee.id || "_marquee")+"_"+(new Date().getTime());
var _attribute=$A(this.marquee.attributes);
this.divEl=document.createElement('div');
this.divEl.id=this.newElementId;
this.scrollId=(this.marquee.id || "_marquee")+"_child_"+(new Date().getTime());
this.scrollEl=document.createElement('div');
this.scrollEl.id=this.scrollId;
try{
this.marquee.parentNode.insertBefore(this.divEl,this.marquee);//新建一个node
this.divEl.appendChild(this.scrollEl);//一个用于滚动的node
_attribute.each(function(d,i){//把其它属性放回去
var key=d.nodeName.toLowerCase();
var nodeValue=d.nodeValue;
if(typeof nodeValue=='object' || typeof nodeValue=='function'
|| nodeValue=='' || nodeValue==null || key=='truespeed' || key=='id') return;
switch (key){
case 'direction':
this.direction=nodeValue;
return;
break;
case 'scrolldelay':
this.scrollDelay=parseInt(nodeValue);
return;
break;
case 'scrollamount':
this.scrollAmount=parseInt(nodeValue);
return;
break;
case 'behavior':
this.behavior=nodeValue;
return;
break;
case 'loop':
this.loop=parseInt(nodeValue);
return;
break;
}
this.divEl.setAttribute(key,nodeValue);//IE中只有className而没有class
}.bind(this));
$A(this.marquee.childNodes).each(function(d){//把子元素放回去
if(d.length!=1/*这是个长为1的textNode*/) this.scrollEl.appendChild(d);
}.bind(this));
this.selfWidth=parseInt($(this.scrollEl).offsetWidth);
this.selfHeight=parseInt($(this.scrollEl).offsetHeight);
}catch(e){
throw e;
}
Element.remove(this.marquee);//结束真marquee的使命
},
makePosition:function(){
$(this.newElementId).makeClipping();
var scrollEl=$(this.scrollEl);
scrollEl.makePositioned();
this.originalLeft = parseFloat(this.scrollEl.getStyle('left') || '0');
this.originalTop = parseFloat(this.scrollEl.getStyle('top') || '0');
this.loop = this.loop || -1;
this.scrollDelay = this.scrollDelay || 85;
this.scrollAmount = this.scrollAmount || 6;
this.direction = this.direction || 'left';
this.behavior = this.behavior || 'scroll';
if(window.opera) {//fix opera。Opera对marquee标签有不同的解释
switch (this.direction){
case '128':
this.direction='left';
break;
case '129':
this.direction='right';
break;
case '164':
this.direction='up';
break;
case '165':
this.direction='down';
break;
}
if(this.behavior='137') this.behavior='scroll';
if(this.behavior='138') this.behavior='alternate';
else this.behavior='slide';
}
this.behavior = this.behavior || 'scroll';
this.parentWidth = parseInt(this.divEl.offsetWidth);
this.parentHeight = parseInt(this.divEl.offsetHeight)
this.scrollWidth = this.parentWidth+this.selfWidth;
this.scrollHeight = this.parentHeight+this.selfHeight;
var topLeft={};
switch (this.direction){
case 'up':
this.scrollWidth=0;
this.scrollHeight=-this.scrollHeight;
topLeft={top:this.parentHeight+"px",left:this.originalLeft+"px"};
break;
case 'down':
this.scrollWidth=0;
topLeft={top:(-this.selfHeight-this.originalTop)+"px",left:this.originalLeft+"px"};
break;
case 'right':
this.scrollHeight=0;
topLeft={top:this.originalTop+"px" ,left:-this.selfWidth+"px"};
break;
default:
this.scrollHeight=0;
this.scrollWidth=-this.scrollWidth;
topLeft={top:this.originalTop+"px",left:this.parentWidth+"px"};
}
scrollEl.setStyle(topLeft);
scrollEl.show();
}
}
GDnews.w3cMarquee.initAll=function(){
var marquees=$A(document.getElementsByTagName('marquee'));
marquees.each(function(d){new GDnews.w3cMarquee(d);});
}
代码解释:因为在完成上面代码后,发现在Opera下可以轻松的运行,而在Firefox下就占六成以上CPU了,所以我就怕了,先停一停,发上来和大家讨论一下,或者有更好的方法。
如果想应用以上代码,只要在marquee之后执行一下GDnews.w3cMarquee.initAll()就可以了。
让标签转换为INPUT
GOVO 发表于 2006-07-18 00:38:43
/**
*把目标转为input输入的类
*@author govo
*/
var toInput=Class.create();
toInput.prototype={
initialize:function(element,format,unBack){
this.format=format || "";
this.El=$(element);
this.ELID=this.El.id;
this.unBack=unBack || false;//如果为true,则不把变为INPUT的标签转回原来的
Event.observe(this.El,"dblclick",this.convert.bind(this),false);//如果Event.observe最后一个为true,则无法在Opera中执行
},
convert:function(){
this.tempDiv="<div style=\"display:none\" id=\"_____temp_"+this.ELID+"\"></div>";
this.tempDivID="_____temp_"+this.ELID;
this.input="<input type=\"text\" id=\""+this.ELID+"\" value=\""+this.El.innerHTML+"\" name=\""+this.ELID+"\" "+this.format+" />";
new Insertion.After(this.ELID,this.tempDiv);
Element.remove(this.ELID);
new Insertion.Before(this.tempDivID,this.input);
Element.remove(this.tempDivID);
if(this.unBack) return;
Event.observe(this.ELID,"dblclick",this.unconvert.bind(this),false);
Event.observe(this.ELID,"blur",this.unconvert.bind(this),false);
},
unconvert:function(){
//很奇怪,当unconvert完一次后,在Firefox中有时候会自动执行一次unconvert,所以得进行一次对标签类型的判断。
if($(this.ELID).tagName.toUpperCase()!='INPUT') return;
Event.stopObserving(this.ELID,"blur",this.unconvert.bind(this),false);//另人头痛的Event.stopObserving,我不知道他到底有没有真正的起作用
Event.stopObserving(this.ELID,"dblclick",this.unconvert.bind(this),false);
this.inputNewValue=$(this.ELID).value;
new Insertion.After(this.ELID,this.tempDiv);
Element.remove(this.ELID);
this.tempEl=$(this.tempDivID);
this.tempEl.parentNode.insertBefore(this.El,this.tempEl);
this.El.innerHTML=this.inputNewValue;
Element.remove(this.tempDivID);
},
destroy:function(){
Event.stopObserving(this.El,"dblclick",this.convert.bind(this),false);
Event.stopObserving(this.ELID,"blur",this.unconvert.bind(this),false);
Event.stopObserving(this.ELID,"dblclick",this.unconvert.bind(this),false);
//不明白为何停止了监听,但作用还是在的,也就是说无法通过以上三个语句停止监听,因此下面4行语句被迫被注释掉
//this.format=null;
// this.El=null;
// this.ELID=null;
// this.unBack=null;
}
}
//==========================================================//
建立一个HTML文件,并加入prototype.js以执行它。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
<script type="text/javascript" src="prototype.js"></script>
<script>
//这里加入以上代码
var a,b,c,d;
window.onload=function(){
a=new toInput("1","style='width:200px' maxlength='20'");
b=new toInput("2","",true);
c=new toInput("3");
d=new toInput("4");
showDebug();
}
</script>
</head>
<body>
<div id="edittopic" style="width:200px; height:250px;margin:0 auto">
<div id="1" style="width:200px; height:20px; background-color:#FFECEC">1</div>
<div id="2" style="width:200px; height:20px; background-color:#ECFFF1">2</div>
<div id="3" style="width:200px; height:20px; background-color:#ECF8FF">3</div>
<div id="4" style="width:200px; height:20px; background-color:#FFEEFD">4</div>
<div id="stop" onclick="a.destroy();b.destroy();c.destroy();d.destroy()" style="width:200px; height:20px; background-color:#FF0000">STOP ALL </div>
</div>
</body>
</html>
下载样例和源码
当prototype-window class 遇上Really Simple History(RSH)
GOVO 发表于 2006-07-08 00:33:34
我用的浏览器有Firefox1.5,Opera9和IE7b2,现在的问题主要针对IE7b2,个人认为IE6和7没本质的区别,所以应该也能在IE6上运行。
我们来看看dhtmlHistory.js,在566行左右,有如下定义:
var styleValue = "position: absolute; top: -1000px; left: -1000px;";
var newContent =
"<form id='historyStorageForm' "
+ "method='GET' "
+ "style='" + styleValue + "'>"
+ "<textarea id='historyStorageField' "
+ "style='" + styleValue + "'"
+ "name='historyStorageField'></textarea>"
+ "</form>";
document.write(newContent);
用于生成如下语句:
<form id='historyStorageForm' method='GET' style='position: absolute; top: -1000px; left: -1000px;'>
<textarea id='historyStorageField' style='position: absolute; top: -1000px; left: -1000px;' name='historyStorageField'></textarea>
</form>
生成这个form主要是为了让页面在加载时保存历史记录状态,下面是引自dhtmlHistory.js的一段注释,偶的E文不好,各位自己看啊:
/** An object that uses a hidden form to store history state
across page loads. The chief mechanism for doing so is using
the fact that browser's save the text in form data for the
life of the browser and cache, which means the text is still
there when the user navigates back to the page. See
http://codinginparadise.org/weblog/2005/08/ajax-tutorial-saving-session-across.html
for full details. */
如果你没有用到prototype window class 组件的window.js(v0.85)做窗口浮动,你会很好的运行它,事实上,用了window.js,RSH也能很好的工作 ,只是window.js不工作了。:)
其实生成的form看上去也是没什么问题的,只是不知道为何它有魔力可以让window.js不工作,但直接写到HTML而不是通过document.write生成的话是没问题的。可能是document.write的工作方式问题吧:) document.write方法一般放在<head>标签前,那么在运行的时候它就可以在<body>标签面的第一句写上东西了,如果放在<body>内或者让页面onload完再用,那么很不幸,<body>里面的东西全被替换了(嘿嘿,可以用firefox的firebug扩展看到运行后的内容)。说回dhtmlHistory.js,在结尾部分,有这样一句:
/** Initialize all of our objects now. */
window.historyStorage.init();
以把这个form写到页面中。
很奇怪,通过document.write生成的form也不全有问题,只是form标签内对style的设置有问题,只要把 + "style='" + styleValue + "'>"去掉就可以了!因为水平有限,所以我左思右想也不懂为何,没能说出原由。
现在,我重新写了一段代码:
var newContent =
"<div style='" + styleValue + "'><form id='historyStorageForm'>"
+ "<textarea id='historyStorageField' name='historyStorageField'></textarea>"
+ "</form></div>";
我想这样组织HTML会更好,让form更干净。其实dhtmlHistory.js源码的很多地方都应能被修改得更好。如果应用到实际中,认真看看源码并改改它会好点。
另外提醒想对类似RSH这样通过iframe激活IE历史记录的朋友,如果你想测试,一定要通过运行服务的方式来浏览页面,否则会出错也得不到你最终的效果。因为直接通过IE来打开你的HTML文件,IE会对iframe的访问有限制,请大家小心。
本从水平有限,有错误之处,还请请各位指正,谢谢。
附:
RSH的主页:http://www.codinginparadise.org/projects/dhtml_history/README.html
prototype-window的主页: http://prototype-window.xilinus.com/
本文例子源码:
[点击下载]
javascript 内部类的疑惑
GOVO 发表于 2006-06-28 13:07:03
编写javascript的时候,我们需要模块化编程,于是我们编写一个类:
var ko= Class.create();//基于Prototype.js的创建类模式。
ko.prototype={
id:null,
initialize:function(id){//基于Prototype.js的类构造函数
this.id=id;
debug("this.id: "+this.id);//假设有一个debug能让我们看到内容,可以用alert()代替。
}
}
在页面中,我们这样创建对象:
var a=new ko("a");
debug("a.id:"+a.id);
var b=new ko("b");
debug("b.id:"+b.id);
debug(c.id+d.id+e.id);
//显示如下结果:
- this.id:a
- a.id:a
- this.id:b
- b.id:b
- ab
但我们还想实现丰富的对象类型,而不只有一个this.id,改成如下:
var ko= Class.create();
ko.prototype={
id:null,
array:{},//一个类似内部类的对象,虽然我还不知道应该怎么称呼它
initialize:function(id){
this.id=id;
this.array.id=id;//为它动态创建一个属性
debug("this.id: "+this.id);
debug("array.id: "+this.array.id);
}
}
然后在页面中我们创建三个对象:
var c=new ko("c");
debug("out c.id: "+c.id);
var d=new ko("d");
debug("out d.id: "+d.id);
var e=new ko("e");
debug("out e.id: "+e.id);
debug(c.id+d.id+e.id);
debug(c.array.id+d.array.id+e.array.id);
结果却是:
- this.id: c
- array.id: c
- out c.id: c
- this.id: d
- array.id: d
- out d.id: d
- this.id: e
- array.id: e
- out e.id: e
- cde
- eee//除了这里,其它都正确
为什么c.array.id、d.array.id、e.array.id会得到相同的内容呢?
难倒ko.array已经是“静态static”的了?就如java中的被声明为static的变量?或者如C语言的中共同体,共用一个内存地址?
思考了很久,也上网查了很久,始终找不到解决方法,基于本人的JS水平,也只能到这个地步了。
但我非等闲之辈,于是作了一个新的尝试:写了一个新的类来配合ko.array。代码改动如下:
var ko= Class.create();
ko.prototype={
id:null,
array:{},//根据下文提到的一些理解,可能把此定义去掉,事实也是行的
initialize:function(id){
this.id=id;
this.array=new ar(this);//array取而代之的是单纯的内部变量,类型是一个ar
debug("this.id: "+this.id);
debug("array.id: "+this.array.id);
}
}
var ar= Class.create();//一个新的类
ar.prototype={
id:null,//有一个属性:id
initialize:function(Obj){
this.id=Obj.id;
}
}
页面中的代码不用改动,然后你就可以看到正确的结果了:
- this.id: c
- array.id: c
- out c.id: c
- this.id: d
- array.id: d
- out d.id: d
- this.id: e
- array.id: e
- out e.id: e
- cde
- cde
本人是一个在校学生,因为最近学Ajax才开始写javascript,所以在这方面没有什么经验,请各位指点一下,谢谢!
=======================================
根据 风清云淡 的指点,他认为通过prototype写法得来的属性是静态的。下面是一些QQ聊天记录:
风清云淡() 14:17:08
你后面那个函数在initialize里覆盖了array
ko.prototype.array是相当静态值
ko.array和ko.prototype.array有区别
菜鸟GOVO() 14:18:08
initialize里覆盖了array?
风清云淡() 14:18:32
后面是产生一个ko.array
菜鸟GOVO() 14:19:07
后面指哪里?
风清云淡() 14:19:20
initialize里
菜鸟GOVO() 14:27:41
与ko.prototype.array与ko.array不一样吗?
风清云淡() 14:28:30
array:{}是ko.prototype.array
菜鸟GOVO() 14:29:05
然后我在initialize覆盖后的呢?
风清云淡() 14:29:23
你new了一个
风清云淡() 14:30:30
prototype的那种类写法太不好看了,不建议初学照他的
菜鸟GOVO() 14:34:09
在initialize中this一个也相当也prototype一个 吧?
风清云淡() 14:34:16
不是
菜鸟GOVO() 14:38:25
initialize中的new有什么不同吗?
风清云淡() 14:39:03
实例化一个新的,分配新的内存空间
菜鸟GOVO() 14:39:16
然后与ko的关系呢?
风清云淡() 14:40:30
ko是Class, c,d,e是具体实例,那个是实例的属性
菜鸟GOVO() 14:41:25
这样说ko.prototype.array是静态的,
ko.prototype.initialize也是静态的
菜鸟GOVO() 14:42:00
里面通过冒号得来的也叫静态的
风清云淡() 14:42:10
我感觉是
风清云淡() 14:47:29
function ko(id)
{
this.id=id;
this.array=new Object();
this.array.id=id;
document.write("this.id: "+this.id);
document.write("array.id: "+this.array.id);
}
一般这种适合学java之类的
风清云淡() 14:47:58
不到万不得以,是不去用prototype
======================================================
根据以上的正确理解,只要将代码改成如下即可:
var ko= Class.create();
ko.prototype={
id:null,
initialize:function(id){
this.id=id;
this.array={};//new一个当前对象的属性
this.array.id=id;
debug("this.id: "+this.id);
debug("array.id: "+this.array.id);
}
}
======================================================
在此十分感谢 风清云淡 的耐心指点!
JAVA判断是否ISBN号。
GOVO 发表于 2006-05-15 01:03:52
/**
* 判断是否ISBN号。
* <PRE>
* 国际标准书号ISBN是英文International Standard Book Number的缩写,
* 1971年国际标准化组织ISO(International Organization for Standardization)
* 批准了国际标准书号在世界范围内实施,迄今已经有30多年的历史,参加国家有159个。
* 国际标准书号由十位数字组成。由三条短横线分为四段,第一段都有不同的含义。
* 第一段号码是地区号,又叫组号,
* 由设在德国柏林国立普鲁士文化遗产图书馆的国际标准书号中心分配。
* 最短的是一位数字,最长的达五位数字,大体上兼顾文种、国别和地区。
* 把全世界自愿申请参加国际标准书号体系的国家和地区,划分成若干组,
* 各有固定的编码,如0、1代表英文出版物,7代表中国出版物等。
* 第二段号码是出版社代码,由其隶属的国家或地区ISBN中心分配,
* 允许取值范围为2-5位数字。出版社的规模越大,出书越多,其号码就越短。
* 第三段是书序号,由出版社自己给出,每个出版社的书序号是定长的。
* 最短的一位,最长的六位。出版社的规模越大,出书越多,序号越长。
* 第四段是校验位,用10至2这9个数分别去乘标准书号的前9位数然后以11为模计算得到。
* 取值范围为0-10,10由X代替。
* 10位ISBN:0-393-04002-?</PRE>
* @param s 待判断的字符串
* @return 如果是ISBN号,返回true,否则返回false。
*/
public static boolean isISBN(String s){
final String regex="\d{1,5}\-\d{2,5}\-\d{1,6}\-([0-9]|x|X)";
if(!s.matches(regex)) return false;
String regexSp[]=s.split("\-");
int leng=regexSp[0].length()+regexSp[1].length()+regexSp[2].length();
if(leng!=9) return false;
int check=0,ten_two=10;//检验数
for(int ii=0;ii<3;ii++){
for(int i=0;i<regexSp[ii].length();i++){
check=check+Integer.parseInt(String.valueOf(regexSp[ii].charAt(i)))*ten_two;
ten_two--;
}
}
int last="x".equals(regexSp[3].toLowerCase())? 10 : Integer.parseInt(regexSp[3]);
if((check+last)%11!=0) return false;
return true;
}
DWR的DWRUtil.addRows()函数
GOVO 发表于 2006-04-12 01:56:31
语法:
DWRUtil.addRows(id, array, cellfuncs, [options]);
描述:
它会名为id的表格添加表格行。每个array数组的元素将被创建一个行。cellfuncs函数为array中每个元素内的字段(列)进行处理单元格将根据cellfunc函数对字段的处理方法,历遍array数据元素内的各个字段而创建。
对于DWR1.1,addRows()函数对于对象类型的数据同样有效。如果你传递一个对象,而不是一个简单的数组,我们会根据单元处理格函数为此对象内的每个元素的字段值创建一个单元格。
以上功能,你可以用如下伪代码表示:
历遍数组array的每个元素
历遍cellfuncs函数中的每个处理方法
根据cellfuncs函数创建单元格。此单元格的值是第i个array数组元素,即array[i],中的一个字段(列)。
参数:
id:表格table的元素,推荐使用tbody
array:数组(或DWR1.1中的对象,如ArrayList),包含将被更新的表格的一个行的数据。
cellfuncs:为从array每个元素中提取字段(列),以写到单元格中的函数,它应当对每个字段(列)值进行加工处理。
options:一个包含多个选项的对象,请看下面说明。
可用的选项有:
*rowCreator:创建行的函数,(例如你想把CSS样式应用到每个行中)。默认的返回值是document.createElement("tr")
*cellCreator:创建单元格的函数,(例如你想把td换成th)。默认的返回值是document.createElement("td")
http://getahead.ltd.uk/dwr/browser/tables
Developer Collaboration: 创建一个账号并登陆
GOVO 发表于 2006-03-24 13:37:33
跟着下面的步骤去注册一个collaboration服务器并登陆它
1. 选择Collaborate > login ,会打开一个Collaborate窗口;
2. 点击 Add an account;
3. 选择你想注册的collaboration 账号类型(提示:你可以使用java.net上的collaboration service);
4. 输入一个要显示的账号名。这个名称将会作为一个显示名显示在本机和服务器上;
5. 选择代理类型。请紧记,这个用户名和密码都必须是在选择的代理服务器上是可行的(因为要连接到你公司的网络),但大多数的网络安装都是让它留空的。对于HTTPS类型的代理,勿忘记加上端口号。
例如:
SOCKS5: hostname=socks:1080
HTTPS: webcache:8080
6. 点击下一步;
7. 填写注册信息(名字和电子邮件),点击下一步;
8. 输入登陆名和密码,点击完成;
9. 点击登陆,你就可以用户这个新账号了;
注意:想得到更多的信息,请点击 help>help Contents ,然后查阅在Collaboration下面的信息。
Developer Collaboration: 安装
GOVO 发表于 2006-03-24 13:36:05
Developer Collaboration模块已经可以放在NetBeans的更新中心中了。跟着下面的步骤,你就可以把Developer Collaboration模块安装到NetBeans IDE中了:
1. 启动NetBeans IDE 5.0;
2. 打开菜单栏的 工具(Tools)=>更新中心(Update Center);
3. 请确保"NetBeans Update Center"被选中,然后随着更新导向进行下一步(本人注:可能你得把更新中心的bata也勾上);
4. 在插件窗口选中Developer Collaboration项;
5. 完成更新向导的余下步骤,(或者须要重启NetBeansIDE,)你会看到Collaborate出现在主菜单栏中了。
请参阅
创建一个账号并登陆
