读者的进步速度远大于博客的进步速度。
2009年06月29日Javascript

5条评论
132 views

jQuery.datePicker日历插件

作者:不羁虫
从事IT3年左右,专业前端工作2年左右,熟悉前端体验,Web标准(大侠很多,不敢自言精通),对jQuery的认识不到一年,jq很符合前端开发的习惯,努力学习中,也正是因为jquery认识了cssrain,这里的文章和插件都很不错,非常骄傲国内能有这样熬的交流的地方。
个人开发习惯:Firefox+Firebug+Fireworks+Editplus
博客:http://hi.baidu.com/bujichong(当记事本和收藏夹用,可观性不强…)
邮箱:bujichong@163.com
qq:347408820(欢迎同行加我交流)

jQuery.datePicker日历插件

 

此datePicker应非jQuery ui中的datepicker插件,名称上虽然只差一个字母的大小写。jQuery ui中的datepicker嵌在整个ui里不太好用,本人系懒人一个,也不善于做剥离代码,说实话,我也不喜欢他收缩显示隐藏的方式,对这些效果真是感觉厌倦了,实用才是第一需要的,所以在网上搜搜寻寻,找到这个插件。
插件源地址:
http://www.kelvinluck.com/assets/jquery/datePicker/
原网站给出的datePicker,其实包括两个js文件:datePicker.js与date.js,这个具体的看他原给出的示例就明白,我觉得影响调用,干脆就把2个合成一个(如果你自己从原网站上下要注意和我示例中的不同)。
然后把日历中的英文称改成中文(在函数的最上面,原脚本在date.js中设置),又将Date.firstDayOfWeek=1改成0,把一周第一天为周一,改成周日,再稍微改改其他细节(相信有些脚本基础的都会改改)。
最后压缩了一下,由于源代码注解比较多,一压,原来2个文件加起来50多k,只剩下18k左右,哈哈。
还有一个bgiframe脚本,由于日历插件在表单上应用比较多,就非常有可能有下拉菜单, 不用说,ie6的下拉菜单层级无人能敌问题是远近闻名。所以这里又附了一个 jquery.bgiframe.min.js 如示例中的源码:
<!–[if IE]><script type="text/javascript" src="js/jquery.bgiframe.min.js"></script><![endif]–>
如果有下拉菜单在日历控件下,这样再调用一行就ok了。
原网站上的日历外观灰土土的,实在不适合网站上广泛使用,我根据需要改了下,淡蓝色感觉,希望大家喜欢,呵呵,如果个人有需求,直接可以改datePicker.css样式, datePicker在具体示例中的调用:

 

html:
< input type="text" name="it" class="it date-pick" />
js:
$(window).ready(function(){
$('.date-pick').datePicker({clickInput:true});
});

 

clickInput 为选择参数,表示点击input框时,是否显示日历控件, 其他更多参数,和更多调用方法(双日历,或者博客日历模式以及日期选择范围)大家可看原网站上的说明,地址为: http://www.kelvinluck.com/assets/jquery/datePicker/v2/demo/

附:
有一个小bug:当单选框里的日期为非法时,页面会报错,
当然这是人有意测试脚本时才会去手动输入非法日期,
一般浏览者都以方便直观的选择日期为主,
也期待完美吧。(设置为readonly?)
点击下载此文件 :http://www.cssrain.cn/attachments/month_0906/k2009629144950.rar
66推荐---my97日历控件:
my97主页:
http://www.my97.net/dp/index.asp
my97皮肤:
http://www.cssrain.cn/article.asp?id=1343

 

2009年06月28日TeamWork

没有评论
49 views

仿CD碟片选择效果(beta1).

作者:66
Hi,大家好,我是CssRain的站长。爱好前端开发的我先后从事过Java开发,JavaScript,CSS开发等,已经工作2年+了。目前就职于亚信中国(Asiainfo),担任前端开发和创新工作。忠心希望所有的读者在这里都能够有收获和进步,同时也希望大家多多支持CssRain。这是我的最大心愿。Best Regards。

仿CD碟片选择效果(beta1).

这是一款仿照CD播放器选择专辑时的效果。
截图:

1,基本布局

从上面截图中,我们可以看到有5张显示出来的专辑,它们的大小都不同。因为需要上下滚动的话,所以它们的背后还有5张,不过后面的5张是隐藏的。所以我们可以清楚的知道,总共需要10个div。然后我们在外面包一层div。总计11个div,代码如下所示:

< div id="wrap">
< div class="pic pic_01" style="background:#99B2DA;">1< /div>
< div class="pic pic_02" style="background:#CB99DA;">2< /div>
< div class="pic pic_03" style="background:#DA99C6;">3< /div>
< div class="pic pic_04" style="background:#99DAB4;">4< /div>
< div class="pic pic_05" style="background:#A3DA99;">5< /div>
< div class="pic pic_06" style="background:#DAD499;">6< /div>
< div class="pic pic_07" style="background:#99DAD9;">7< /div>
< div class="pic pic_08" style="background:#A9DA99;">8< /div>
< div class="pic pic_09" style="background:green;">9< /div>
< div class="pic pic_10" style="background:red;">10< /div>
< /div>

 

1,首先我们给id为wrap的元素添加高度和宽度和定位方式,有一点你必须明白,做这种效果99%都是使用相对定位+绝对定位来做。为什么?因为wrap如果设置为relative的话,那么它里面的 absolute元素 都是根据 wrap 来偏移。同时设置为relative的元素并不对 原始 布局产生影响。
2,从截图中,我们可以清楚的看到,层之间有层叠关系,因为我们已经设置了absolute,所以可以通过z-index来控制它们的上下层 关系。
3,图片的位置:5个div的位置(left,top)和大小都需要非常小心的设置。注意对称性即可。
显示效果如下:
http://www.cssrain.cn/demo/icd/demo0.html

2,添加脚本,控制滚动

滚动意味着里面的元素需要以动态的方式进行移动。比如pic_03移动到pic_02的位置,同时大小变为pic_02的大小,pic_02移动到pic_01的位置,同时大小变为pic_01的大小,依次类推。当然这里有一个特殊元素,那么就是第一个pic_01,因为它上面没有元素,所以对它需要特殊处理。如果它上面没有元素,则找到当前最后一个元素,然后pic_01移动到最后一个元素那。注意:对于pic_01不仅仅是移动,元素必须append到最后。
当动画结束后,我们需要对所有元素进行z-index设置,达到初始化效果。具体代码可以看Demo:
http://www.cssrain.cn/demo/icd/demo1.html
我已经在代码中添加了相应的注释,相应大家能看明白。

3,实际运用

在第2步中,我们已经做出了一个原型效果。接下来我们将此效果稍做修改放到实际应用中。
具体代码可以看Demo:
http://www.cssrain.cn/demo/icd/demo2.html
本例代码下载:
http://www.cssrain.cn/demo/icd/icd.rar

2009年06月23日TeamWork

1条评论
61 views

仿Google的一个鼠标拖动效果.

作者:66
Hi,大家好,我是CssRain的站长。爱好前端开发的我先后从事过Java开发,JavaScript,CSS开发等,已经工作2年+了。目前就职于亚信中国(Asiainfo),担任前端开发和创新工作。忠心希望所有的读者在这里都能够有收获和进步,同时也希望大家多多支持CssRain。这是我的最大心愿。Best Regards。

仿Google的一个鼠标拖动效果.

在 igoogle 的娱乐频道栏目里,有一个非常酷的效果,它能通过鼠标的拖动 来控制 视频显示区域 的滚动 。
截图:

1,基本布局

我们在网页中加入 40 个 li 元素,同时不限制 ul 的高度。
显示效果如下:
http://www.cssrain.cn/demo/igooglevideo/demo1.html

2,将多余的加入滚动条

这步非常简单,只需要通过height: 400px; overflow: auto; 2个css属性,即可对列表加入滚动条。
具体代码可以看Demo2:
http://www.cssrain.cn/demo/igooglevideo/demo2.html

3,如何控制滚动条滚动呢?

通过JavaScript的对象有一个属性:scrollTop。它能控制滚动条距对象上边的距离。它不仅能被获取,也能被设置。
需要注意的是:scrollTop 这个属性总是非负数,尽管它可以设成负数,但是对于小于0的数,它会自动设置成0。如果大于自身的最大scrollTop高度,那么将设置为最大的scrollTop值。
代码如下:

var obj = $("#scroll")[0]; //Dom对象
$("#down").click(function(){
obj.scrollTop += 200;
});
$("#up").click(function(){
obj.scrollTop -= 200;
});

具体代码可以也可以看Demo3:
http://www.cssrain.cn/demo/igooglevideo/demo3.html

 

4,如何加入动画?

Demo3中已经实现了控制scrollTop,那么改成动画就非常简单了。只需要换成 jquery的 animate 方式即可。
请看Demo4:
http://www.cssrain.cn/demo/igooglevideo/demo4.html

5,通过鼠标拖动来控制滚动

通过鼠标拖动来控制Div滚动,我们需要注意有3个状态:mousedown,mouseup,mouseleave。其中mousedown里包含 mousemove。 mousedown的时候,记录初始化位置,同时启动mousemove,在movesemove里 计算 每次滑动的距离,即时滚动。 mouseup和mouseleave 都是用来解除mousemove的事件。当然,最重要的就是 mousemove 这个 事件了。
另外要注意一个属性,e.pageX来获取鼠标点击的绝对位置。
请看Demo5:
http://www.cssrain.cn/demo/igooglevideo/demo5.html

6,改成动画滚动模式

和前面一样,只需要把控制scrollTop的方式 换成 jquery的 animate 方式即可。
需要注意的是,动画模式要清除动画。.stop(true, false).
请看Demo6:
http://www.cssrain.cn/demo/igooglevideo/demo6.html

7,最终效果

把滚动条去掉,把overflow:auto — > overflow:hidden;即可达到效果, 但直接改css这个并不太好。为什么?当用户禁用javascript的时,那么截断的部分将无法显示。所以我们仍保持css中的overflow为 auto,通过js来重新设置overflow为 hidden;当用户启用js的时候,才设置为hidden。禁用js的时候,那么列表将会出现默认的滚动条,保证了可用性。
请看Demo7:
http://www.cssrain.cn/demo/igooglevideo/demo7.html
本例下载:
http://www.cssrain.cn/demo/igooglevideo/igooglevideo.rar

2009年06月20日TeamWork

没有评论
34 views

打造强大的输入框.

作者:$('demo')
大家好,我是$('demo'),从事Web前端开发已经1年多了,对Web开发始终充满了激情和兴趣。希望在CssRain这个平台上交到更多的Web开发爱好者。

打造强大输入框.

大家都知道 win + r 在运行里输入cmd 就进入了 Command 窗口。输入框有个光标在闪,别小看它,它不仅是一个文本框,它会记录我们输入的内容,用 上/下方向键就可以查看之前输入的内容。好了,今天我们就来模拟这个效果。

1,基本布局和样式

布局和样式对这个例子的影响几乎为0,所以我们随意做了一个。
Demo1:
http://www.cssrain.cn/demo/advanceText/demo1.html

2,添加脚本

在脚本中,我们首先定义一个Commmand类,在类里我们定义了接下来需要使用的方法,比如:增加记录,清空记录,上一条记录等。主要的逻辑就是对一个 数组 进行操作。比如清空数组,我们把length设置为0 即可。比如当存储数据大于规定的长度时,我们使用slice来截取数组,保存最新的数据。
具体代码可以看Demo2:
http://www.cssrain.cn/demo/advanceText/demo2.html

3,了解更多数组操作

如果你对数组操作还不太熟悉,那马上点击下面的链接去学习吧
http://cssrain.cn/article.asp?id=438

2009年06月18日TeamWork

没有评论
65 views

基于jQuery的饭否输入框.

作者:66
Hi,大家好,我是CssRain的站长。爱好前端开发的我先后从事过Java开发,JavaScript,CSS开发等,已经工作2年+了。目前就职于亚信中国(Asiainfo),担任前端开发和创新工作。忠心希望所有的读者在这里都能够有收获和进步,同时也希望大家多多支持CssRain。这是我的最大心愿。Best Regards。

基于jQuery的饭否输入框.

相信大多数人都使用过饭否。总的来说,饭否算是国内一个不错的互联网产品。个人比较喜欢。特别是那个140字的输入框,我觉得还不错,能实时的显示 “已经输入多少字”和“还可以输入多少字”。所以,这篇文章就是来讲解如何制作一个类似的输入框。

1,基本布局

所需要的元素:一个标题,一个提示字数的元素,多行输入框一个,loading图片一张,提交按钮一个。
布局涉及到2个状态:"1个默认状态" 和" 1个已经超出" 的状态。
具体布局可以看下面的2个例子:
http://www.cssrain.cn/demo/fanfoutext/demo1.html
http://www.cssrain.cn/demo/fanfoutext/demo2.html

2,添加脚本

布局做好后,添加脚本就相对简单了。
很多人做这个效果的第一反应就是 使用 onkeydown或者onkeyup。我以前也是,当时遇到了很多问题。
不过上次看了国外一个代码后,我改变了思路。使用的是focus + setInterval() + +blur来实现。
具体思路就是 当鼠标获取焦点(onfoucs)后,添加一个setInterval(), setInterval()中的函数就是用来截取字符串的。当鼠标失去焦点后, 清除interval。另外需要注意的是,在focus时,需要判断 避免重复执行。
具体代码可以看Demo3:
http://www.cssrain.cn/demo/fanfoutext/demo3.html

3,ctrl+enter提交表单

这是一个很普通,但非常实用的提交方法,所以我打算添加进去。
代码如下:

$content.keydown(function(e){
if(e.ctrlKey&&e.keyCode=="13"){
...
}
})

具体代码可以也可以看Demo3:
http://www.cssrain.cn/demo/fanfoutext/demo3.html

 

4,改变成另外一种提示方式

Demo3中即使超过了,用户还是能输入。如果你打算超过后,就不让输入,那么请看Demo4:
http://www.cssrain.cn/demo/fanfoutext/demo4.html

2009年06月16日TeamWork

没有评论
43 views

创建一个可调大小的图片网格系统(译).

作者:珊瑚
大家好, 我是珊瑚。 和66一样工作2+年了,在经过第一年的PHP开发之后, 对前端开发的喜爱被挖掘出来,并且一发不可收拾。 同时也迷恋平面设计, 可用性设计。 在CssRain这个平台上, 我希望把国外优秀的前端开发, 互联网设计方面的文章介绍给大家, 希望可以给大家带来设计灵感,分享开发经验。 翻译的拙劣之处请大家见谅, 我会持续改进。
我的城堡:Little Fox's Candy Castle

创建一个可调大小的图片网格系统

像iPhoto和Picasa这样的桌面应用可以用一个简单的滑动条改变图片网格的大小, 但现在, 不只是它们可以做到了. 感谢CSS和jQuery UI, 流体图片网格可以在网页上实现了. ( 看一看最终的效果吧.)

1. 创建网格

首先我们创建一个静态的图片网格. 我准备了6张照片, 把它们裁剪成宽高不大于500像素的图片. 我们会生成一个ul列表, 把图片放在li标签里.

[code]
< ul id="grid">
< li>< img src="1deadsea.jpg"/>< /li>
< li>< img src="2akko.jpg"/>< /li>
< li>< img src="3jordan.jpg"/>< /li>
< li>< img src="4petra.jpg"/>< /li>
< li>< img src="5pyramids.jpg"/>< /li>
< li>< img src="6deadsea.jpg"/>< /li>
< /ul>
[/code]

 

然后, 我们使这些li浮动, 这样它们就会换行, 同时给它们的右侧和底部加一些白边. 当图片水平,竖直都居中的排列在网格中时是很好看的. 所以我们可以为图片设置宽, 高, 行距, 并在ul标签上声明text-align:center, 在图片上声明vertical-align:middle(更多关于这方面的技术请看iBloom的文章).

 

ul#grid li {
list-style: none outside;
float: left;
margin-right: 20px;
margin-bottom: 20px;
width: 500px;
height: 500px;
line-height: 500px;
text-align: center;
}
ul#grid li img {
vertical-align: middle;
}

例1: 基础的图片网格.(这个时候图片有点大, 但我们一会儿会解决.)
Demo1 :http://demos.webdesignledger.com/jquery_image_grid/example1.htm

 

2. 爱上em

这是最令人兴奋的一个部分. 还记得em这个单位么?一个em等于当前字体大小. 所以如果字体大小是10像素, 那么1em也是10像素.这个小单位就是我们的神奇要素. 我们接下来要做的是用em而不是像素来设定图片以及它们父级li的宽高. 我们会用jQuery测量每个图片的像素大小, 然后把结果转换成以em为单位的尺寸, 在用内联CSS把这些新尺寸加到每一张图片上.

[code]
$(document).ready(initializeGrid);
function initializeGrid() {
$("ul#grid li img").each(function() {
var width = $(this).width() / 100 + "em";
var height = $(this).height() / 100 + "em";
$(this).css("width",width);
$(this).css("height",height);
});
}
[/code]

 

你会发现我们用宽和高分别除以100得到新尺寸. 也就是说如果字体大小设置为100像素, 宽和高就是5em. 在这个例子里, 我们把字体大小设置为50像素. 同时, 我们把li的宽, 高, 行距从500px转换为5em.

ul#grid li {
...
font-size: 50px;
width: 5em;
height: 5em;
line-height: 5em;
}

 

3. 添加滑动条

jQuery UI提供了一个轻量级的滑动条, 我们可以把它和li的字体大小绑定. 也许你猜到了: 当字体变大时, 图片变大; 变小时, 图片缩小. 很灵活, 对么?
创建滑动条的第一步是要包含jQuery和jQuery UI的JavaScript文件, 还有jQuery UI的CSS文件.

< link rel="stylesheet" href="ui.all.css" type="text/css">
< script src="jquery.js" type="text/javascript">< /script>
< script src="jquery-ui.js" type="text/javascript">< /script>

然后我们为滑动条写一些简单的HTML:

< div id="grid_slider">
< div class='ui-slider-handle'>< /div>
< /div>

我们还要初始化滑动条, 比如调用一个叫initializeGrid()的方法. 设置最大值为100, 最小值为10, 初始化的值设置为50.

$("#grid_slider").slider({
value: 50,
max: 100,
min: 10,
slide: function(event, ui) {
$('ul#grid li').css('font-size',ui.value+"px");
}
});

转眼我们就有了这样一个可以自由伸展的图片网格, 并且对于浏览器来讲它是轻量级的.
最终效果:http://demos.webdesignledger.com/jquery_image_grid/example2.htm
原文出处: http://webdesignledger.com/tutorials/create-a-resizable-image-grid-with-jquery

 

jQuery新书推荐<<锋利的jQuery>>.

作者:66
Hi,大家好,我是CssRain的站长。爱好前端开发的我先后从事过Java开发,JavaScript,CSS开发等,已经工作2年+了。目前就职于亚信中国(Asiainfo),担任前端开发和创新工作。忠心希望所有的读者在这里都能够有收获和进步,同时也希望大家多多支持CssRain。这是我的最大心愿。Best Regards。

jQuery新书推荐—[[锋利的jQuery]].

一年前我认识了它—jQuery,从此就一发不可收拾。有人说:jQuery是毒药,会使人不思进取,放弃原生的JavaScript的学习。不过从我的经验看来,事实并不是这样,笔者正是由于jQuery,才对JavaScript这门语言感兴趣,直至爱上JavaScript。兴趣是最好的老师。现在我时不时会想:这个程序利用jQuery是这么实现,那么利用JavaScript怎么来实现呢。以前,我喜欢用jQuery去改写原生的JavaScript效果。现在,我更喜欢利用原生的JavaScript来改写jQuery的程序。对我来说,借鉴jQuery的编程思路来编写其它JavaScript程序已经让我乐此不疲。

曾经有朋友问我为什么最终选择jQuery。说实话,这个也说不上为什么,也许是当初jQuery给我的第一印象非常好的原因吧。它非常容易上手,它的大部分思想都是从HTML和CSS的结构中借鉴而来的,所以编程经验不多的设计师能够快速学会使用该库。记得那时候的我经常会在用jQuery做出的某种动态效果后而高兴不已,常常惊叹于jQuery如此小巧,却有如此强大的功能。

在以前学习jQuery的时候,互联网并没有现在这么多资料,完全是靠自己看国外的网站的资料,每看完一个方法后,我都会做一点笔记,然后发布到Blog(cssrain.cn)上,和网友们分享。时间一长,笔记的内容已经非常充足了。这本书的内容也就是从笔记衍生而来,相对于Blog的笔记,书的内容更加系统。
本书适合所有对jQuery技术感兴趣的Web设计者,前台编程人员。阅读此书需要有一定的HTML、CSS和JavaScript知识。
更多介绍:http://www.cssrain.cn/jquery/index.htm

2009年06月11日TeamWork

2条评论
85 views

细微处提高tab标签鼠标效果的用户体验.

作者:不羁虫
从事IT3年左右,专业前端工作2年左右,熟悉前端体验,Web标准(大侠很多,不敢自言精通),对jQuery的认识不到一年,jq很符合前端开发的习惯,努力学习中,也正是因为jquery认识了cssrain,这里的文章和插件都很不错,非常骄傲国内能有这样熬的交流的地方。
个人开发习惯:Firefox+Firebug+Fireworks+Editplus
博客:http://hi.baidu.com/bujichong(当记事本和收藏夹用,可观性不强…)
邮箱:bujichong[at]163.com
qq:347408820(欢迎同行加我交流)

细微处提高tab标签鼠标效果的用户体验

Tab标签的切换效果在网页里几乎是无所不在,只要做网站,就会有这个效果,当然,我不是想谈怎么去实现它(代码网上一抓一大把,水平参差不齐)

讨论:Tab效果,实现切换是鼠标经过切换好还是鼠标点击切换好?

从用户的使用角度来讲,通过越少的动作能达到获得更多的信息才是更好的,那么可以说鼠标经过就切换比鼠标点击要好。
附:
现在网站上这种标签样的东西非常多,也经常会给人迷惑感,设计做出来看上去是标签,点击以后却直接打开一个新页面,或者转跳,也许这不是浏览者的意愿,(这让我想起了很多论坛,或者新闻,在首页新闻里看到的明明是条新闻标题,点击以后进入的不是新闻,而是新闻的栏目首页,让我顿刻有受骗的感觉)所以点击效果的tab,只有用户不在乎是否跳转他才肯定的去点击。

提升用户体验:既然鼠标经过的效果好,有什么细微之处可以提高?

说到这个问题,还是那天客户提出的要求让我感觉到确实是个很细微的地方 ,
页面如:侏罗纪软件的首页:http://www.jurassic.com.cn/

他的下方有个tab切换的效果,当看到这个效果的时候,我当然就按平时的做法(具体不说了)马上做好,效果无非是鼠标放上去切换,代码上,如果客户要求鼠标是点击效果,只需要将mouseover改成click,然后里面的执行代码就一样一样。
但挑剔的客户客户突然提出:这个Tab效果切换的太快了,鼠标随便划拉一下就切换,感觉太灵敏了。
心里暗骂客户真是事儿多,但无奈还是改,将切换代码写成函数,再用settimeout来延迟400毫秒来实现切换的函数,改完这步,感觉是延迟了,但鼠标滑过每个标签还是切换,只是推迟函数执行,改变它,小问题!在mouseout里加个cleartimeout,这样,用户在Tab标签上鼠标停留时间不超过400毫秒的滑过,就不会引起tab内容的切换,这样真的就避免了无意的鼠标滑过引起切换。改完以后感觉客户的要求确实是对的,
虽然只是细微的一步,细微到我做了这么久的Tab效果都已经烂熟烂抄的效果,而没有注意过这个问题,细微到很多人在浏览网站上重来没有感觉到这是需要处理才能更好实现的效果(做完后又去看了一些门户和其他网站的Tab切换,发现很多切换都做了细微的延迟处理,以前怎么没有发现这个问题).
改完后,由于Tab标签上,客户没有要求加链接,干脆再加上一个点击效果,完成后就是点击直接切换,或者鼠标在标签上稍微停顿切换内容,这样算是用户体验达到了很好的提升,兼顾了各种用户习惯。

后感后言

一个优良的代码应该具备哪些条件,总结应该如下(自己的一些看法):
1,兼容能力强,逻辑合理,结构优化,执行效率高
能为更多的情况考虑,减少DOM访问,将代码尽量用于逻辑及自定义操作(这个和js网页脚本开发特点有关),多写几行甚至几十行代码是很值得的。
2,易读性,模块化,
所谓易读性,当然首先要有良好的代码习惯,书写习惯以及尽量在需要的地方留有注解说明,模块化的代码更便于调用,和避免同样的效果,仅仅是因为对象的id,class,标签名称而反复写,所以应该说,更推崇脚本库的使用,库不是万能的,但是有了库确实简化了很多不了解而需要很多步骤去实现的代码,或者不需要的重复代码。
3,扩展能力强,易于以后不可预料的修改,
扩展和易于维护,这个更应该在代码结构上,从一开始就想好,当然这个和自身水平以及经验有很多关系.
同样的,我认为以上几点也适用于web标准页面的书写,好的web页面代码应该充分掌握网站结构的特点,定义样式或者html代码的结构应该从整站出发,而只考虑当前页面,当前模块,往往我们会多写出许多重复的代码,重复的样式,而到最后自己也被绕糊涂了

Tab关键代码展示

function tabChange(tabHead,headAddClass,tabBox,boxAddClass){
var timeout;
function eachClass(){
jQuery(tabHead).each(function(i){
jQuery(tabHead).eq(i).removeClass(headAddClass);
jQuery(tabBox).eq(i).removeClass(boxAddClass);
});
}
window.addClass = function(a){
eachClass();
jQuery(tabHead).eq(a).addClass(headAddClass);
jQuery(tabBox).eq(a).addClass(boxAddClass);
}
jQuery(tabHead).each(function(i){
jQuery(tabHead).eq(i).mouseover(function(){
timeout =setTimeout("addClass("+i+")", 400);
});
jQuery(tabHead).eq(i).mouseout(function(){
clearTimeout(timeout);
});
jQuery(tabHead).eq(i).click(function(){
addClass(i);
return false;
});
});
2009年06月10日TeamWork

4条评论
118 views

JavaScript中的对象、函数和继承

作者:stefyang
大家好,我是cssrain的新的联合作者之一。在南开学了7年的数学,在腾讯做了近两年的web开发工程师,现在处于自由职业的阶段。在腾讯主要从事lamp方面的开发,对php框架开发和mysql的优化有少许的心得,但是个人一直非常钟情于前段开发,尤其是js方面。我是那种什么事情都喜欢追根溯源的人,所以相信会给大家带来一些源码分析的作品。当然我也是一个google reader的重度的使用者,所以我也会定期给大家带来一些国外经典技术博文的翻译。希望我的文章对大家能有所帮助,也希望在这里能够认识更多的对web开发感兴趣的童鞋。
我的QQ是549805380,邮箱是yangliang AT vip.qq.com.

JavaScript中的对象、函数和继承

前一段时间在看Extjs的源代码,起初打算从他的Widget开始看起,因为想借鉴一下并应用到自己的代码中,但是看了一段时间发现很难阅读进去,主要因为对他的整体如何组织对象和事件的方式不是很清楚。所以还是耐下性子从最基础的开始看起,什么是Extjs的基础,可以说是他的Ext.extend函数,因为之后的各个wdiget的扩展都用它来实现的。但是起初发现他的内容并不是那么容易就可以看明白的,有的时候觉得自己看明白了,但是再多问自己一个为什么,可能又答不上来了。

这个时候正好碰到一本很不错的讲JS原理书,周爱民的《Javascript语言精粹与编程实践》,如获至宝,赶紧买来阅读。在阅读的过程中又在我面前蹭蹭蹭,出现了几本很不错的js书籍,在这里也向大家推荐一下,一本是有Yahoo的js大牛Douglas Crockeord(后文称之为老道)所著,由淘宝UED的小马和秦歌翻译的 《Javascript语言精粹》,一本是《Javascript设计模式》。最早我读的这两本书都是英文版的,所以还被第二本书中的一些观点给误导了,但是幸好看到第二本书的译者很负责任,在批注中都已经修正过来了。最后一本,其实不是书,而是《ECMAScript Language Specification》,俗称ECMA-262,有两个值得看的版本,一个是第三版,一个是第五版;现在的大部分js实现都是基于第三版的规范,但是在有些问题上,第五版描述的更加清晰一些。废话少说,进入正题。

1、 Javascript中的对象

JavaScript可以说是一个基于对象的编程语言,为什么说是基于对象而不是面向对象,因为JavaScript自身只实现了封装,而没有实现继承和多态。既然他是基于对象的,那么我们就来说说js中的对象。有人说js中所有的都是对象,这句话不完全正确。正确的一方是他强调了对象在js中的重要性,对象在js中无处不在,包括可以构造对象的函数本身也是对象。但是另一方面,js中也有一些简单的数据类型,包括数字、字符串和布尔值、null值和undefined值,而这些不是对象。那为什么这些类型的值不是对象呢,毕竟他们也有方法。那让我们来看一下,JavaScript中对于对象的定义,有两种定义。
(1)JavaScript中的对象是可变的键控集合(keyed collections) (此定义来自老道的那本书的第三章)
(2)JavaScript中的对象是无序(unordered)的属性集合,这些属性可以含有简单的数据类型、对象、函数;保存在一个对象属性中的函数也被称为这个对象的方法。 (来自ECMA-262 的4.3.3)(注:这里所说的属性是可以在js脚本中创建和访问的(我们称之为显性属性),不包括系统为对象自动分配的内部属性)

那为什么那个简单的数据类型不是对象呢,主要是因为这些数据类型的值中拥有的方法是不可变的,而一个对象的属性是应当可以被改变的。

2、 对象中的原型链[[proto]]

JavaScript中的每个对象创建的时候系统都会自动为其分配一个原型属性[[proto]],用来连接到他的原型对象。在JavaScript中就是通过每个对象中的[[proto]]来实现对象的继承关系的。但是对象的[[proto]]属性在JavaScript是不能访问和修改的,他是作为一个内部的属性存在的,而且是在对象被创建的同时由系统自动设定的。

当访问一个对象的某一属性,如果这个属性在此对象中不存在,就在他的[[proto]]所指的原型对象的属性中寻找,如果找到则返回,否则继续沿着[[proto]]链一直找下去,直到[[proto]]的连接为null的时候停止。

3、 函数也是对象

JavaScript中的函数本身就是一个对象(所以我们经常称之为函数对象),而且可以说他是js中最重要的对象。之所以称之为最重要的对象,一方面他可以扮演像其他语言中的函数同样的角色,可以被调用,可以被传入参数;另一方面他还被作为对象的构造器(constructor)来使用,可以结合new操作符来创建对象。
既然函数就是对象,所以必然含有对象拥有的全部性质,包括对象在创建时设定的原型链[[proto]]属性。

让我们来看看函数对象和普通对象有什么区别。我们前面说过,对象就是无序的属性集合,那么函数的属性和普通对象的属性有什么不同呢。根据ECMA-262中的13.2节所述,在函数对象创建时,系统会默认为其创建两个属性[[call]]和[[constructor]],当函数对象被当做一个普通函数调用的时候(例如myFunc()),“()”操作符指明函数对象的[[call]]属性就被执行,当他被当做一个构造器被调用的时候(例如new myConst()),他的[[constructor]]属性就被执行,[[cosntructor]]的执行过程我们将在下一节中介绍。除此之外,当一个函数被创建时,系统会默认的再为其创建一个显示属性prototype,并为其赋值为
this.prototype = {constructor:this}

具体内容可以参加老道的那本书的第五章。这个函数对象的prototype属性也是为了js把函数当做构造器来实现继承是准备的,但是这个属性是可以在js脚本中访问和修改的。在这里要强调的一点是,大家一定要区分对象中的[[proto]]属性和函数对象中的prototype属性,我在刚开始学习的时候就是因为没有很好的区分这两个东西,走了很多的弯路。

4、 对象的创建

在js中有两种创建对象的方法,一种是通过字面量来实现,如
var Person = {
“first_name”:’liang’,
‘last_name’:’yang’
}
另一种方法是通过构造器来创建
var my = new Person(‘liang’,’yang’);
其实第一种方式的创建过程相当于调用Object构造器来实现,如下。
var Person = new Object();
Person.first_name = ‘liang’;
Person.last_name = ‘yang’
所以我们可以把js中所有对象的创建都合并到使用构造器来实现,下面我么来详细说明构造器创建对象的过程:
第一步,先创建一个空的对象(既没有任何属性),并将这个对象的[[proto]]指向这个构造器函数的prototype属性对象
第二步,将这个空的对象作为this指针传给构造器函数并执行
第三步,如果上面的函数返回一个对象,则返回这个对象,否则返回第一步创建的对象
第四步,把函数当做一个类来使用

由上面的步骤我们可以看出,一般来说函数对象的prototype指向的是一个普通对象,而不是一个函数对象,这个普通对象中的属在由此函数构造器创建的对象中也可以访问。由此可以如此设计我们的代码,假设一个函数就可以代表一个类,这个构造器函数生成的对象就是这个类的实例对象,那么实例对象中应有的属性和方法应该放在这个构造器函数的prototype中,这个类的静态方法就可以直接放到这个函数作为对象的属性中,最后这个函数体就是我们平时在面向对象语言中所说的构造函数(在这里我们要区分连个词“构造函数”和“构造器函数”,所谓构造函数是指普通的面向对象语言中的类的构造函数,而构造器函数是指javascript中的一个函数被当做构造器使用)。

在第3节我们说过每个函数的prototype对象中总是含有一个constructor属性,这个属性就是连接到我们的这个函数本身。再加之,有这个函数生成的每个对象的[[proto]]属性都是指向构造器函数的prototype对象,所以通过[[proto]]链,每个由构造器函数生成的对象,都有一个constructor属性,指向生成他的构造器函数,因此我们可以通过这个属性来判断这个对象是有哪个构造器函数生成的。

5、 函数继承(类继承)

说了这么多,终于到了我们可以在javascript中讨论继承的时候了,我们先来考虑一下要实现类的继承我们都要做些什么,假设我们要从superClass继承到子类subClass
为了使得由subClass生成的对象中能够访问superClass生成的对象中的属性,那么可以使subClass.prototype为一个superClass构造函数生成的对象。
subclass.prototye = new superClass();
但是问题来了,根据我们在第4节说的new superClass()不仅复制了superClass.prototype中的所有方法,而且还运行了superClass()这个函数,这个函数起到的作用是类中的构造函数。我们知道应该在子类的构造函数中调用父类的构造函数来实现初始化。为此我们可以创建一个构造函数为空的,但是原型和superClass原型一致的函数,并使subClass.prototype指向这个函数生成的对象。
var F = function() {};
F.prototype = superClass.prototype;
subClass.protptype = new F();

这样我们就可以再不调用构造函数的同时完成属性复制的工作。但是还有一个问题,那就是我们修改了subClass的prototype属性,从而也就删除了其中的constructor属性,这样我们就无法知道他是哪个构造器函数生成的对象了。我们可以再次给他赋值
subClass.prototype.constructor = subClass;
这样复制属性的问题就迎刃而解了。但是新的问题又出现了,在subClass中我们无法知道他的父类是哪个构造器函数,所以就无法在构造函数中调用父类的构造函数,为此我们可以为subClass添加一个属性,指明他的父类
subClass.superClass = superClass.prototype;
这样我么就可以在子类的构造函数中使用subClass.superClass.constructor来访问父类的构造函数了。最后我们把以上的思路写成一个函数
myPro.extend = function (subClass,superClass) {
var F = function() {};
F.prototype = superClass.prototype;
subClass.protptype = new F();
subClass.prototype.constructor = subClass;
subClass.superClass = superClass.prototype;
superClass.prototype.constructor = superClass;
}
大功告成。

文章下载:http://www.cssrain.cn/demo/javascript对象和函数.doc

 

Mashup–Google Map API与饭否API的整合应用

作者:karry
Hi,大家好,我是Karry,playGoogle(玩转谷歌)的博主。07年从武汉毕业后到上海工作,先后从事过.Net开发、前端开发。现在在巨人网络(GA)任JavaScript工程师一职。专注于JavaScript编写和用户体验改善。相信细节决定成败,欢迎志同道合的朋友一起交流。
msn: karry[at]live.cn。
blog: http://www.playgoogle.com

Mashup–Google Map API与饭否API的整合应用

这是一个通过JS 整合两个API 的混搭小应用。

先预览这个应用:http://www.playgoogle.com/demo/fanfou/default.htm

1.前提

(1), 什么是Mashup??
http://baike.baidu.com/view/241257.htm
(2)你必须对Google map API 比较了解。饭否的API 比较简单,在这个应用中,主要是是用了他开放的JSON数据。同时,你要知道什么是JSONP ,用来做跨域的访问。另外由于本文的代码书写风格,你必须知道什么是闭包.

2.引入GOOGLE MAP API

通过一个script标签引入google map api
< script type="text/javascript"
src="http://ditu.google.com/maps?file=api&v=2& key=ABQIAAAAOYVY-acpvTnhAhwAg94W7RQULNflpX8UqGwTaVYnmUlH28s8DBSBksAirhcPKVRiRFkFe4FWR65TaA">
< /script>
注意,key后面的字符串是根据域名在google 的网站上获取的,如果你要在自己的网站上使用,你需要用域名去获取一下API 密钥。
密钥地址:http://code.google.com/intl/zh-CN/apis/maps/signup.html

3.初始化MAP

通常,在body的onload事件里面去初始化地图,我是在KARRY.init函数里面初始化的。把地图的中心默认设置为中国洛阳。
map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(34.68491,112.47605), 6);
map.addControl(new GLargeMapControl());
map.addControl(new GOverviewMapControl());
map.addControl(new GMapTypeControl());

4.搜索关键词

我在 KARRY.JS 的顶部设置了一个默认的关键词 var keyword = "红酒"; 在初始化地图之后,立即去搜索饭否上包含该关键词的内容:
在scratchJson()这个方法中(由于采用了闭包,这个方法是私有方法。)这个方法在立即执行的同时会设置一个定时器,每隔600秒会重新执行一次。也就是10分钟后会重新搜索饭否的数据,看是否有更新。
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'http://api.fanfou.com/search/public_timeline.json?q='+keyword +'&' + Math.random() + '&count=30&callback=KARRY.callBack';
document.getElementsByTagName('head')[0].appendChild(s);
这里用到了JSONP,其实就是在页面上载入了一段饭否的js,同时有一个回调函数,callback=KARRY.callBack,也就是当数据载入完成之后,会立即执行KARRY.callBack函数。很显然,这个回调函数主要的目的是对载入的数据进行解析。

5.解析数据

要解析数据,首先要知道别人给的数据是什么格式:

[{"created_at":"Mon Jun 08 11:44:51 +0000 2009",
"id":"P5kJHLcHDbQ",
"text":"内容",
"source":"\u7f51\u9875",
"truncated":false,
"in_reply_to_status_id":"",
"in_reply_to_user_id":"",
"favorited":false,
"in_reply_to_screen_name":"",
"user":
{"id":"karryzhang",
"name":"karryzhang",
"screen_name":"karryzhang",
"location":null,
"location_en":null,
"description":"",
"profile_image_url":"http:\/\/avatar.fanfou.com\/s0\/00\/e0\/g6.jpg?1244277109",
"url":"http:\/\/fanfou.com\/karryzhang",
"protected":false,
"followers_count":1
},
"photo_url":""
}]

饭否搜索返回的JSON 就是上面那个数组的形式,进行重复。
既然是数组,那就循环去读数据,然后逐条解析,获取需要的内容就行了。
由于数据要在地图上一条一条的显示,而不是一次都显示出来,
这里就需要另外一个定时器,每隔10秒往下读一条数据了。

var p = 0;
if(innerInterval!=null){
clearInterval(innerInterval);
}
innerInterval = setInterval(function(){
if (/海外/.exec(j[p].user.location)){
map.setZoom(3);
} else {
map.setZoom(curlevel);
}
//弹出框
map.openInfoWindowHtml(getPoint(j[p].user.location), parseDataToHTML(j[p]));
counter.innerHTML = j.length - p;
p++;
if(p==j.length){
clearInterval(innerInterval);
return;
}},10000);

注意里面调用的两个私有方法:getPoint(j[p].user.location) parseDataToHTML(j[p]),
getPoint前面一个是通过地址名获取对应的经纬度。parseDataToHTML是把内容拼装成DOM,
插入到对应的框中。 在页面上你可以看到,最开始引入了一个
< script type="text/javascript" src="karry/geocode.js">< /script>
就是用来做地址解析的。也就是先把具体地址和其对应的经纬度存在一个文件里。
用的时候根据具体地址获取经纬度就可以了。
我写过一个专门获取经纬度的工具:经纬度查询工具
地址如下:http://www.playgoogle.com/googlemap/tool1.html

 

6.获取饭否上的热门关键词

在初始化地图,搜索了默认关键词的同时,就通过getHotWords()方法开始获取热门关键词了.
饭否热词也是一个JSON格式的数据,路径:http://api.fanfou.com/trends.json同样的,还是通过JSONP,
把它通过< script>标签载入到页面中来,载入完成后通过回调函数来格式化数据,拼装成DOM格式,让其出现在右侧。

7.点击热词或者点击搜索按钮的处理

在右侧的热门关键词和搜索按钮上都绑定了一个事件,KARRY.setKeyWord(),功能其实很简单,重新设置关键词,并清除当前的定时器,重新执行第四步,搜索关键词。

if(keyword==str){
alert("当前显示的是"+keyword+"相关的内容");
return;
}
keyword = str;
if(!interval){
clearInterval(interval);
}
if(!innerInterval){
clearInterval(innerInterval);
}
scratchJson();
interval = setInterval(scratchJson, 600000);
alert("正在从饭否上获取有关"+keyword+"的信息,请稍后");

 

8.总结

这个应用的原理很简单。我通过获取饭否的API中的热词,在用户点击热词之后,会把热词作为关键词去载入饭否API中的公开搜索,搜索出包含该关键词的内容。再解析内容,根据用户的地址,在google map找到对应的经纬度并把内容展示出来,这里使用了setInterval 来定时获取。
查看这个应用的地址:http://www.playgoogle.com/demo/fanfou/default.htm

返回顶部