Heim > Web-Frontend > js-Tutorial > jQuery插件-jRating评分插件源码分析及使用方法_jquery

jQuery插件-jRating评分插件源码分析及使用方法_jquery

WBOY
Freigeben: 2016-05-16 17:44:50
Original
1178 Leute haben es durchsucht

该插件被广泛应用于各种需要评分的页面当中,今天作为学习,把源码拿出来分析一下,顺便学习其使用方法。
一、插件使用一览

复制代码 代码如下:


第一个例子




复制代码 代码如下:






执行效果

可以看到,上面的例子中,有10颗星,是参数length的作用。其中,默认总分是20分,就是10颗星都选择。这里我们着重注意
的id16_1,其中16被用来初始化评分插件默认选择的比例,16/20 * 10。所以我们上面有8颗星是黄色的。

当我们把鼠标放到插件上时,小星星会随着鼠标移动而增加或减少(红色会覆盖黄色或白色),表示评分的从0至20,但点击鼠标时,评分结束,插件不能再编辑了,同时,通过Ajax向指定的路径POST数据,用后台数据将评分数据持久化。

在分析源代码之前,我们先看一下使用该插件时有哪些可选参数:
 
二、插件源码分析

按照jQuery插件开发的推荐方法,为了避免快捷符号“$”与其他JavaScript插件产生冲突,源码开头采用了下面技术:
复制代码 代码如下:

(function($) {
$.fn.jRating = function(op) {
//这里为插件代码
}
})(jQurery)

接下来,我们分析的所有代码都将出现在上面绿色区域部分,首先设置默认参数。
复制代码 代码如下:

var defaults = {
/** String vars **/
bigStarsPath : 'icons/stars.png', // 设置大星星(默认显示)的相对路径
smallStarsPath : 'icons/small.png', // 小星星
phpPath : 'php/jRating.php', // 点击鼠标,评分确定后,将POST数据的地址,接下来我们会采用ASP.Net技术进行处理
type : 'big', // 可以看出,默认是使用大星星
/** Boolean vars **/
step:false, // 如果设置为True,则星星要么全变色,要么不全变,当然这也适和选择分数是同步的。
isDisabled:false, //如果设置为True,则插件不能编辑,当点击鼠标过后,默认是True的状态
showRateInfo: true, //当鼠标放到星星上时,是否在鼠标下方显示选择比例信息,例如16/20
/** Integer vars **/
length:5, // 星星的个数
decimalLength : 0, // 选择的数字其后的小数位,最多为3位,如果设置为1,可能出现的情况为16.3/20
rateMax : 20, // 比例中的分母,整数0-9999
rateInfosX : -45, // 信息提示框相对于鼠标位置的横坐标位置
rateInfosY : 5, // 同上,纵坐标位置
/** Functions **/
onSuccess : null, //成功后的回调函数
onError : null //出错处理函数
};

通过上面绿色部分的解释,我们可以看到所有参数的默认值,同时,我们可以在插件使用中,根据需求确定适合的配置,插件的使用不就是这些参数的搭配组合吗?
接下来我们再看一个函数作用域:
复制代码 代码如下:

if(this.length>0)
return this.each(function() { //接下来出现的代码,都将在此处!!!}

这段代码很简单,我们要在选中的集合上执行jRating()函数,而上面的代码首先判断该集合是否长度大于0,如果为1或者更多,则在该集合上执行each()函数,对集合中的每一个元素(div)进行单独处理。
该插件的核心代码其实都在上面的each()函数中,我们首先看几个函数,这几个函数都定义在each()函数中,并被其他语句调用。
复制代码 代码如下:

function findRealLeft(obj) {
if( !obj ) return 0;
return obj.offsetLeft + findRealLeft( obj.offsetParent );
};

首先关注findRealLeft()函数,该函数接收名为obj的对象参数,最后返回该元素对象相对于浏览器左边界的距离。注:offsetParent是指元素最近的定位(relative,absolute)祖先元素,如果没有祖先元素是定位的话,会指向body元素。offsetLeft返回相对于offsetParent的位置。
复制代码 代码如下:

function getNote(relativeX) {
var noteBrut = parseFloat((relativeX*100/widthRatingContainer)*opts.rateMax/100); //两个100是否可以去掉,表示选择的比例,如16 或 16.1
switch(opts.decimalLength) { //根据参数确定要输去比例需要的小数位,例如16.1 16.12 16.123
case 1 :
var note = Math.round(noteBrut*10)/10;
break;
case 2 :
var note = Math.round(noteBrut*100)/100;
break;
case 3 :
var note = Math.round(noteBrut*1000)/1000;
break;
default :
var note = Math.round(noteBrut*1)/1;
}
return note;
};

接着关注getNote函数,首先我们看以下relativeX是一个什么东西:
复制代码 代码如下:

var realOffsetLeft = findRealLeft(this);
var relativeX = e.pageX - realOffsetLeft;

上面两行代码是调用getNote函数前,定义relativeX变量用的,我们可以分析出relativeX的作用。这里的this是我们应用jRating()函数的某个div,首先获得其相对于浏览器的左边距,因为上面两行代码是出现在鼠标移动处理函数mouseenter中(稍后我们会看到),因此这里的e.pageX表示鼠标相对于浏览器的横向距离。因此,这里的relativeX表示的是鼠标相对于
左边界的横向距离。
我们再次关注getNote函数,由widthRatingContainer = starWidth*opts.length可以看出,widthRatingContainer是左右星星图片加起来的宽度。因此,var noteBrut = parseFloat((relativeX*100/widthRatingContainer)*opts.rateMax/100);可以把分母与分子上的两个100去掉,即(relativeX/widthRatingContainer)*opts.rateMax),noteBrut变量最后存储的是鼠标选择的比例,如果rateMax设为20,则noteBrut的范围可以通过鼠标来确定(0—20)。
switch函数,是通过decimalLength参数(用来设定显示比例的小数位),最终确定(比例)显示的位数。读到这里,我们可以发现,getNote函数就是通过relativX来返回鼠标选择的比例,这个比例是什么,见下图用笔刷框起来的部分:
 
接下来,我们再关注一个函数
复制代码 代码如下:

function getStarWidth(){
switch(opts.type) {
case 'small' :
starWidth = 12; // small.png小星星图片的宽度
starHeight = 10; // 高度
bgPath = opts.smallStarsPath; //图片相对地址
break;
default :
starWidth = 23; // 大星星的宽度,可以看到,这是默认值
starHeight = 20; // 高度
bgPath = opts.bigStarsPath; //星图片相对地址
}
};

这个是一个比较简单的用于初始化变量的函数,根据type属性,初始化三个变量,分别是starWidth、starHeight、bgPath,绿色的注释信息已能够说明一切,不再赘述!
each()中定义的函数看完了,接下来,我们还在each()函数中进行游荡,按照从上到下的顺序,先截取了几行代码如下:
复制代码 代码如下:

var opts = $.extend(defaults, op), //利用extend()函数将默认参数与输入参数进行合并,最后存储在opts变量中。
newWidth = 0, //定义变量,该变量用于存储relativeX,但会根据step属性进行相应调整
starWidth = 0, //定义变量,星星的宽度
starHeight = 0, //高度
bgPath = ''; //星星图片地址
if($(this).hasClass('jDisabled') || opts.isDisabled) //确定jDisabled变量,表示是否能对div进行操作
var jDisabled = true;
else
var jDisabled = false;
getStarWidth(); //这个函数不赘述,上面分析过
$(this).height(starHeight); //根据星星的高度,确定此div的高度。

接着往下看
复制代码 代码如下:

var average = parseFloat($(this).attr('id').split('_')[0]), //通过
的id(例如16_2),获取下划线前面的数字,把该数字作为默认的选择比例
idBox = parseInt($(this).attr('id').split('_')[1]), // 下划线后面的部分,作为辨别评分插件的id
widthRatingContainer = starWidth*opts.length, // 星星图片宽度总和,并作为外围容器的宽度
widthColor = average/opts.rateMax*widthRatingContainer, // 颜色块占用的宽度

接下来,我们将看到新建的三个
,并插入到主div中
复制代码 代码如下:

quotient =
$('
',
{
'class' : 'jRatingColor',
css:{
width:widthColor
}
}).appendTo($(this)),
average =
$('
',
{
'class' : 'jRatingAverage',
css:{
width:0,
top:- starHeight
}
}).appendTo($(this)),
jstar =
$('
',
{
'class' : 'jStar',
css:{
width:widthRatingContainer,
height:starHeight,
top:- (starHeight*2),
background: 'url('+bgPath+') repeat-x'
}
}).appendTo($(this));

首先我们分析第一个
,它的类名为jRatingColor,它表示默认比例,用黄色表示,它的长度为withColor,这里主要看一下它的样式表:
复制代码 代码如下:

.jRatingColor {
background-color:#f4c239; /* bgcolor of the stars*/
position:relative; //相对定位
top:0;
left:0;
z-index:2; //这里需注意,该div的祖先即我们each函数中的this 的z-index是1,下面我们将马上看到。
height:100%;
}

第二个
样式表如下:
复制代码 代码如下:

.jRatingAverage {
background-color:#f62929; //红色
position:relative;
top:0;
left:0;
z-index:2;
height:100%;
}

但在上面的程序中,初始化时,把宽度设为0(因为鼠标还没选嘛),同时改变了top值:- 星高度,这样它就和上面添加的div在纵方向上重合了。
接下来看第三个
,主要用来放小星星。
复制代码 代码如下:

/** Div containing the stars **/
.jStar {
position:relative;
left:0;
z-index:3;
}

这个样式表比较简单,我们着重看一下JS中动态添加的几个属性值:
复制代码 代码如下:

width:widthRatingContainer, //设置宽度
height:starHeight, //高度
top:- (starHeight*2), //改变纵方向的值,和上面两个
重合
background: 'url('+bgPath+') repeat-x' //设置背景为小星星

属性的值设置了,但也许有人会问,问什么只看到小星星颜色是彩色的,而上面添加的前两个
不是具有高度的长方形颜色条吗?下面我们看一下小星星的图片就明白为什么了!

不用多说,旁边用不透明的背景,中间小星星是透明的,下面的颜色自然就显示出来了!!
接下来的语句很简单,就是设置一下最外层div容器的样式,注意z-Index属性:
复制代码 代码如下:

$(this).css({width: widthRatingContainer,overflow:'hidden',zIndex:1,position:'relative'});

接下来会进入相对复杂的部分,我们将关注鼠标动作及其响应效果,首先关注一个小逻辑:
if(!jDisabled)
//接下来的代码
可以看出,前面我们设置的jDisable变量在这里用上了,如果jDisabled为true,就表示插件禁用了,那么接下来的鼠标操作将不会被执行。
接下来看鼠标操作是如何添加到插件中的:
$(this).unbind().bind({//鼠标事件处理代码,下面将分别进行讨论。
});
首先看以一下鼠标进入事件处理代码
复制代码 代码如下:

mouseenter : function(e){
var realOffsetLeft = findRealLeft(this);
var relativeX = e.pageX - realOffsetLeft; //首先计算出relativeX,它表示的是鼠标相对于外层
左边界的横向距离
if (opts.showRateInfo)
var tooltip =
$('

',{
'class' : 'jRatingInfos',
html : getNote(relativeX)+' / '+opts.rateMax+'', //注意这里用了getNote方法,前面已讲了它的用途。
css : {
top: (e.pageY + opts.rateInfosY),
left: (e.pageX + opts.rateInfosX)
}
}).appendTo('body').show();
},


relativeX变量不多解释,这里的注释和前面都有提到,接下来,判断showRateInfo参数是否为true,如果为true,表示要显示比例信息(例如鼠标下面显示16/20),tooltip变量就是这个信息框,最后通过appendTo方法添加到body中。代码逻辑很简单,这个函数主要用来显示提示框

,我们在这里可以重点关注一下

节点的样式,它是绝对定位的,并利用代码改变了top和Left值,看一下相关的样式表:

复制代码 代码如下:

p.jRatingInfos {
position: absolute;
z-index:9999;
background: transparent url('http://www.cnblogs.com/icons/bg_jRatingInfos.png') no-repeat;
color: #FFF;
display: none;
width: 91px;
height: 29px;
font-size:16px;
text-align:center;
padding-top:5px;
}
p.jRatingInfos span.maxRate {
color:#c9c9c9;
font-size:14px;
}

接下来我们看一下鼠标进来后的mousemove事件的处理函数:
复制代码 代码如下:

mousemove : function(e){
var realOffsetLeft = findRealLeft(this);
var relativeX = e.pageX - realOffsetLeft;
if(opts.step) newWidth = Math.floor(relativeX/starWidth)*starWidth + starWidth;
else newWidth = relativeX;
average.width(newWidth);
if (opts.showRateInfo)
$("p.jRatingInfos")
.css({
left: (e.pageX + opts.rateInfosX)
})
.html(getNote(newWidth) +' / '+opts.rateMax+'');
},

这个函数主要用来确定鼠标选择的比例,当然这个比例是通过getNote(newWidth)来得到的,那么,确定合适的newWidth值就成了这个函数的核心,如果opts.step为true,即比例只能是整数个星星(不能为15.3等等),那么我们看一下这个逻辑:Math.floor(relativeX/starWidth),starWidth是星星图片的宽度,Math.floor(-0.1)=-1,Math.floor(0.1) = 0,Math.floor(2.6)=2,知道这些,上面加红的代码就很容易理解了。
OK,Let's go on,看一下三个简单的处理函数
复制代码 代码如下:

mouseover : function(e){
$(this).css('cursor','pointer');
},
mouseout : function(){
$(this).css('cursor','default');
average.width(0);
},
mouseleave: function () {
$("p.jRatingInfos").remove();
},

mouseover函数确保鼠标进入插件后的显示样式,mouseout也是同样,但它将类名为average的div(红色的)宽度变成0,mouseleave函数让提示信息框消失。
最后一个函数,也是整个源码的结尾,当然也是最重要最复杂的——鼠标点击函数:
复制代码 代码如下:

click : function(e){
//接下来的代码都在此处。
}

我们分部来,先看第一部分:
复制代码 代码如下:

$(this).unbind().css('cursor','default').addClass('jDisabled');

为什么这里只列出一条语句,因为它很重要,但也很简单,我们这里一定要关注unbind()函数,它非常非常重要,当点击鼠标后,首先把其他所有绑定到外围
的事件都去掉了,这样就鼠标点击的瞬间,该插件的外观就固定显示在浏览器中,不再随着鼠标事件而出现变化。当然,最后给
添加jDisabled属性。
我们接着往后走:
复制代码 代码如下:

if (opts.showRateInfo) $("p.jRatingInfos").fadeOut('fast',function(){$(this).remove();});
e.preventDefault();
var rate = getNote(newWidth); //关注rate变量,后面要用到。
average.width(newWidth);

第一句不难理解,删除提示信息框,第二句取消鼠标点击的默认操作,后面两句很简单,不再赘述,要知道newWidth在前面已提到,表示鼠标选择的宽度。
最后一条语句,把选择的比例发送到服务器端进行持久化操作:
复制代码 代码如下:

$.post(
opts.phpPath, //利用Ajax技术,向服务端发送数据的地址
{ //Post过去的数据
idBox : idBox,
rate : rate,
action : 'rating'
},
function(data) { //回调函数,主要向插件自定义函数传递参数并执行。
if(!data.error)
{
if(opts.onSuccess) opts.onSuccess( element, rate );
}
else
{
if(opts.onError) opts.onError( element, rate );
}
},
'json' //确定如何理解返回的数据,它采用json.
);

利用jQuery做Ajax确实很简单,代码中做了必要注释,这里不再赘述,这个插件的源码就分析完了,比较粗,但整个逻辑也许体现了一些,希望该学习笔记对大家能有帮助。下面我们进入实战阶段。
三、实战jRating插件
为了更加逼近真实应用,我们先利用sql server建立一张数据库表,它是一个文章类型表,有id、标题、文章内容、评分四个字段,截图如下:
 
评分字段默认为-1,表示该文章还没有被评分。当然,现在有人会说,这个表设计的很不合理,因为一篇文章不会只评分一次吧,应该每个用户都能进行评论,是的,我们在这里只是为了演示jRating插件利用Ajax进行持久化操作,因为是演示,所以一切从俭。
新建一个Web页面,用来显示第一篇文章(id为1)的标题、内容及评分插件,见前台代码:
复制代码 代码如下:












  










后台CS代码如下:
复制代码 代码如下:

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
tempEntities cbx = new tempEntities(); //用了实体框架获取数据表
var page1 = cbx.jRatingArticles.Where(m => m.id == 1).SingleOrDefault();
page1_title.Text = page1.title;
page1_body.Text = page1.body;
}
}

为了减少数据库连接代码,我用了实体框架,只映射了一张表(jRatingArticle),就是上面我们看到的。获取id为1的文章对象,并把相应属性赋值到Label控件的Text属性中。
页面效果如下
 
我们可以看到上面前台页面的JS代码中,有这样一条语句:
phpPath: 'tempAjax.aspx/UpdateComment'
它指明了,当鼠标点击插件后,要通过Ajax发送数据的地址,这里我们用.net页面技术来处理这个异步请求。tempAjax.aspx的后台cs代码如下:
复制代码 代码如下:

[WebMethod()]
public static void UpdateComment(int idBox, int rate)
{
tempEntities cbx = new tempEntities();
var page1 = cbx.jRatingArticles.Where(m => m.id == 1).SingleOrDefault();
page1.is_comment = rate;
cbx.SaveChanges();
}

此时,我们还需修改jRating插件的原文件,把鼠标单击(click)处理函数中的$.post函数替换如下:
复制代码 代码如下:

$.ajax({
type: "POST",
url: opts.phpPath,
data: '{"idBox":"' + idBox + '","rate":"' + rate + '"}',
contentType: "application/json; charset=utf-8",
dataType: "json"
});

为什么要改变源文件,因为我想改变Ajax请求的contentType属性,利用json格式发送请求数据,默认是application/x-www-form-urlencoded
OK,万事俱备,看一下执行效果(选择比例为16,16颗红星嘛):
 
看看数据库的变化
 
试验成功!今天学习就到这里,希望此篇学习笔记对大家能有所帮助!
Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage