(function( $, undefined ) {
$.widget = function( name, base, prototype )$.widget接受三个参数,
1. 第一个参数为插件的名称,其中ui是插件所属命名空间,progressbar为插件名字。
note:只允许有一层命名空间。wrong:jquery.ui.progressbar
原因如下:
var namespace = name.split( "." )[ 0 ],
fullName;
name = name.split( "." )[ 1 ];
fullName = namespace + "-" + name;
2.第二个参数为继承的类(mark:另外讲解)
3. 第三个参数包含所有实例方法的对象
在这我们传递两个参数,没有继承其他widget,但是我们传进的是name和base,不要担心
原因如下:
if ( !prototype ) {
prototype = base;
base = $.Widget;
}
这说明,如果我们这么传递时,默认继承$.Widget
另外可以看到 widget factory 给我们提供了两个属性。一是 this.element, 它指向一个只
包含一个元素的 jQuery 对象,如果插件是由包含多个元素的 jQuery 对象调用时,会给其中的
每一个元素都分配一个插件实例, 并让this.element 指向它;二是 this.options, 是包
含键值对形式的插件参数的 hash 对象,插件的参数就是像这样传递进来的。
$.widget( "ui.progressbar", {
//默认参数
options: {
value: 0,
max: 100
},
min: 0,
//_create函数可以看做是一个构造函数
_create: function() {
this.element
.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.attr({
role: "progressbar",
"aria-valuemin": this.min,
"aria-valuemax": this.options.max,
"aria-valuenow": this._value()
});
this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
.appendTo( this.element );
this.oldValue = this._value();
this._refreshValue();
},
//_destory函数可以看做是一个析构函数,当插件被移除remove时调用
destroy: function() {
this.element
.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.removeAttr( "role" )
.removeAttr( "aria-valuemin" )
.removeAttr( "aria-valuemax" )
.removeAttr( "aria-valuenow" );
this.valueDiv.remove();
$.Widget.prototype.destroy.apply( this, arguments );
},
//一个public函数
value: function( newValue ) {
if ( newValue === undefined ) {
return this._value();
}
this._setOption( "value", newValue );
return this;
},
//用来处理传进的参数options,默认调用
_setOption: function( key, value ) {
if ( key === "value" ) {
this.options.value = value;
this._refreshValue();
if ( this._value() === this.options.max ) {
this._trigger( "complete" );
}
}
$.Widget.prototype._setOption.apply( this, arguments );
},
你可能看到,$.Widget.prototype._setOption.apply( this, arguments );在此做以说明:
1. 在函数内部,有两个特殊的对象:arguments和this。其中arguments是一个类数组对象,包含着传入函数的所有参数
2. 每个函数都包含两个非继承而来的方法,apply()和call()。这两个方法的用途是在特定的作用域中调用函数,实际上等于
设置函数体内this的值
apply()接受两个参数,其一作用域,其二参数数组(可以是array实例或者arguments对象)
//此处调用的函数为
_setOptions: function( options ) {
var self = this;
$.each( options, function( key, value ) {
self._setOption( key, value );
});
return this;
},
//private函数
_value: function() {
var val = this.options.value;
// normalize invalid value
if ( typeof val !== "number" ) {
val = 0;
}
return Math.min( this.options.max, Math.max( this.min, val ) );
},
_percentage: function() {
return 100 * this._value() / this.options.max;
},
_refreshValue: function() {
var value = this.value();
var percentage = this._percentage();
if ( this.oldValue !== value ) {
this.oldValue = value;
this._trigger( "change" );
}
this.valueDiv
.toggle( value > this.min )
.toggleClass( "ui-corner-right", value === this.options.max )
.width( percentage.toFixed(0) + "%" );
this.element.attr( "aria-valuenow", value );
}
为你的插件添加回调功能:
扩展插件的一个最简单的办法就是添加回调功能, 这样使用者就可以根据插件状态的改变来采取行动。_trigger 方法介绍三个参数: 回调名称,触发回调的本地事件对象以及相关的数据。虽然其中只有回调名称是必须的, 不过其它参数对使用者来说挺有用的。比如说,创建一个可拖拽插件, 我们可以在触发回调时将原生的 mouseover 事件对象传递过去, 用户在回调函数里就可以根据这个对象中的 x/y 坐标对拖拽进行一些处理。
在这里你可能注意到,this._trigger( "change" ); 触发了change事件。那我们如何捕获change事件呢?
回调函数实际上只是另外一种参数,因此你也可以像其它参数一样进行查询和修改。 无论回调函数是否设置,事件都会触发。事件类型则是由插件名称和回调名称合并而成progressbarcomplete。
回调和事件被触发时会收到同样的两个参数:事件对象和相关数据。如果,我们绑定了change事件,改变progressbar进度的逻辑:
this.valueDiv
.toggle( value > this.min )
.toggleClass( "ui-corner-right", value === this.options.max )
.width( percentage.toFixed(0) + "%" );则可以放在回调函数中执行。
var bar = $("<div></div>")
.appendTo("body")
.progressbar()
.bind("progressbarchange", function(event, data) {
//do something……
});
bar.progressbar("option", "value", 10);
});
$.extend( $.ui.progressbar, {
version: "1.8.18"
});
})( jQuery );
//下面两部分援引自其他文章,有时间在补充