Getting Started
To write a jQuery plugin, start by adding a new function property to
the jQuery.fn object where the name of the property is the name of your
plugin:
jQuery.fn.myPlugin = function() {
// Do your awesome plugin stuff here
};
But wait! Where's my awesome dollar sign that I know and love? It's
still there, however to make sure that your plugin doesn't collide with
other libraries that might use the dollar sign, it's a best practice to
pass jQuery to an IIFE (Immediately Invoked Function Expression) that
maps it to the dollar sign so it can't be overwritten by another library
in the scope of its execution.
(function( $ ) {
$.fn.myPlugin = function() {
// Do your awesome plugin stuff here
};
})( jQuery );
Ah, that's better. Now within that closure, we can use the dollar sign in place of jQuery as much as we like.
Context
Now that we have our shell we can start writing our actual plugin
code. But before we do that, I'd like to say a word about context. In
the immediate scope of the plugin function, the this
keyword refers to the jQuery object the plugin was invoked on. This is a
common slip up due to the fact that in other instances where jQuery
accepts a callback, the this
keyword refers to the native DOM element. This often leads to developers unnecessarily wrapping the this
keyword (again) in the jQuery function.
(function( $ ){
$.fn.myPlugin = function() {
// there's no need to do $(this) because
// "this" is already a jquery object
// $(this) would be the same as $($('#element'));
this.fadeIn('normal', function(){
// the this keyword is a DOM element
});
};
})( jQuery );
$('#element').myPlugin();
The Basics
Now that we understand the context of jQuery plugins, let's write a plugin that actually does something.
(function( $ ){
$.fn.maxHeight = function() {
var max = 0;
this.each(function() {
max = Math.max( max, $(this).height() );
});
return max;
};
})( jQuery );
var tallest = $('div').maxHeight(); // Returns the height of the tallest div
This is a simple plugin that leverages .height()
to return the height of the tallest div in the page.
Maintaining Chainability
The previous example returns an integer value of the tallest div on
the page, but often times the intent of a plugin is simply modify the
collection of elements in some way, and pass them along to the next
method in the chain. This is the beauty of jQuery's design and is one of
the reasons jQuery is so popular. So to maintain chainability in a
plugin, you must make sure your plugin returns the this
keyword.
(function( $ ){
$.fn.lockDimensions = function( type ) {
return this.each(function() {
var $this = $(this);
if ( !type || type == 'width' ) {
$this.width( $this.width() );
}
if ( !type || type == 'height' ) {
$this.height( $this.height() );
}
});
};
})( jQuery );
$('div').lockDimensions('width').css('color', 'red');
Because the plugin returns the this
keyword in its
immediate scope, it maintains chainability and the jQuery collection can
continue to be manipulated by jQuery methods, such as .css
. So if your plugin doesn't return an intrinsic value, you should always return the this
keyword in the immediate scope of the plugin function. Also, as you
might assume, arguments you pass in your plugin invocation get passed to
the immediate scope of the plugin function. So in the previous example,
the string 'width' becomes the type argument for the plugin function.
Defaults and Options
For more complex and customizable plugins that provide many options,
it's a best practice to have default settings that can get extended
(using $.extend
)
when the plugin is invoked. So instead of calling a plugin with a large
number of arguments, you can call it with one argument which is an
object literal of the settings you would like to override. Here's how
you do it.
(function( $ ){
$.fn.tooltip = function( options ) {
// Create some defaults, extending them with any options that were provided
var settings = $.extend( {
'location' : 'top',
'background-color' : 'blue'
}, options);
return this.each(function() {
// Tooltip plugin code here
});
};
})( jQuery );
$('div').tooltip({
'location' : 'left'
});
In this example, after calling the tooltip plugin with the given
options, the default location setting gets overridden to become 'left'
, while the background-color setting remains the default 'blue'
. So the final settings object ends up looking like this:
{
'location' : 'left',
'background-color' : 'blue'
}
This is a great way to offer a highly configurable plugin without requiring the developer to define all available options.
Namespacing
Properly namespacing your plugin is a very important part of plugin
development. Namespacing correctly assures that your plugin will have a
very low chance of being overwritten by other plugins or code living on
the same page. Namespacing also makes your life easier as a plugin
developer because it helps you keep better track of your methods, events
and data.
Plugin Methods
Under no circumstance should a single plugin ever claim more than one namespace in the jQuery.fn
object.
(function( $ ){
$.fn.tooltip = function( options ) {
// THIS
};
$.fn.tooltipShow = function( ) {
// IS
};
$.fn.tooltipHide = function( ) {
// BAD
};
$.fn.tooltipUpdate = function( content ) {
// !!!
};
})( jQuery );
This is a discouraged because it clutters up the $.fn
namespace. To remedy this, you should collect all of your plugin's
methods in an object literal and call them by passing the string name of
the method to the plugin.
(function( $ ){
var methods = {
init : function( options ) {
// THIS
},
show : function( ) {
// IS
},
hide : function( ) {
// GOOD
},
update : function( content ) {
// !!!
}
};
$.fn.tooltip = function( method ) {
// Method calling logic
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
};
})( jQuery );
// calls the init method
$('div').tooltip();
// calls the init method
$('div').tooltip({
foo : 'bar'
});
// calls the hide method
$('div').tooltip('hide');
// calls the update method
$('div').tooltip('update', 'This is the new tooltip content!');
This type of plugin architecture allows you to encapsulate all of
your methods in the plugin's parent closure, and call them by first
passing the string name of the method, and then passing any additional
parameters you might need for that method. This type of method
encapsulation and architecture is a standard in the jQuery plugin
community and it used by countless plugins, including the plugins and
widgets in jQueryUI.
Events
A lesser known feature of the bind
method is that is allows for namespacing of bound events. If your
plugin binds an event, its a good practice to namespace it. This way, if
you need to unbind
it later, you can do so without interfering with other events that
might have been bound to the same type of event. You can namespace your
events by appending “.<namespace>” to the type of event you're
binding.
(function( $ ){
var methods = {
init : function( options ) {
return this.each(function(){
$(window).bind('resize.tooltip', methods.reposition);
});
},
destroy : function( ) {
return this.each(function(){
$(window).unbind('.tooltip');
})
},
reposition : function( ) {
// ...
},
show : function( ) {
// ...
},
hide : function( ) {
// ...
},
update : function( content ) {
// ...
}
};
$.fn.tooltip = function( method ) {
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
};
})( jQuery );
$('#fun').tooltip();
// Some time later...
$('#fun').tooltip('destroy');
In this example, when the tooltip is initialized with the init
method, it binds the reposition method to the resize event of the window
under the namespace 'tooltip'. Later, if the developer needs to destroy
the tooltip, we can unbind the events bound by the plugin by passing
its namespace, in this case 'tooltip', to the unbind method. This allows
us to safely unbind plugin events without accidentally unbinding events
that may have been bound outside of the plugin.
Data
Often times in plugin development, you may need to maintain state or
check if your plugin has already been initialized on a given element.
Using jQuery's data
method is a great way to keep track of variables on a per element
basis. However, rather than keeping track of a bunch of separate data
calls with different names, it's best to use a single object literal to
house all of your variables, and access that object by a single data
namespace.
(function( $ ){
var methods = {
init : function( options ) {
return this.each(function(){
var $this = $(this),
data = $this.data('tooltip'),
tooltip = $('<div />', {
text : $this.attr('title')
});
// If the plugin hasn't been initialized yet
if ( ! data ) {
/*
Do more setup stuff here
*/
$(this).data('tooltip', {
target : $this,
tooltip : tooltip
});
}
});
},
destroy : function( ) {
return this.each(function(){
var $this = $(this),
data = $this.data('tooltip');
// Namespacing FTW
$(window).unbind('.tooltip');
data.tooltip.remove();
$this.removeData('tooltip');
})
},
reposition : function( ) { // ... },
show : function( ) { // ... },
hide : function( ) { // ... },
update : function( content ) { // ...}
};
$.fn.tooltip = function( method ) {
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
};
})( jQuery );
Using data helps you keep track of variables and state across method
calls from your plugin. Namespacing your data into one object literal
makes it easy to access all of your plugin's properties from one central
location, as well as reducing the data namespace which allows for easy
removal if need be.
Summary and Best Practices
Writing jQuery plugins allows you to make the most out of the library
and abstract your most clever and useful functions out into reusable
code that can save you time and make your development even more
efficient. Here's a brief summary of the post and what to keep in mind
when developing your next jQuery plugin:
- Always wrap your plugin in a closure:
(function( $ ){ /* plugin goes here */ })( jQuery );
- Don't redundantly wrap the
this
keyword in the immediate scope of your plugin's function
- Unless you're returning an intrinsic value from your plugin, always have your plugin's function return the
this
keyword to maintain chainability.
- Rather than requiring a lengthy amount of arguments, pass your
plugin settings in an object literal that can be extended over the
plugin's defaults.
- Don't clutter the
jQuery.fn
object with more than one namespace per plugin.
- Always namespace your methods, events and data.
分享到:
相关推荐
教你如何做一个自己的jQuery插件,jQuery扩展
基于jQuery的计算器插件,外观简洁和美观,计算器的功能也很强大。有兴趣的同学可以继续为这款计算器扩展功能,应该也不是难事。
jQuery formValidator表单验证插件,它是基于jQuery类库,实现了js脚本于页面html代码的分离。你可以划分多个校验组,每个组的校验都是互不影响。对一个表单对象,你只需要写一行代码就可以轻松实现无数种(理论上)...
Datatables是一款jquery表格插件。它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能,包括排序、分页、扩展、主题、国际化等
(详情可以参见:jQuery.ajax文档) 此外,系统的可扩展性大大增强,可以附加各种数据处理器、过滤器和传输机制,为开发新的Ajax插件提供了方便。 2. 延迟对象 延迟对象(Deferred Object,jQuery.Deferred对象)是...
具体介绍 jquery插件之easing使用,适合移动开发的js使用
autocomplete插件原有功能,不能满足需求所以修改了增加了以下几点...4 增加插件赋值给一个隐藏域,就可以得到文本和值 (做asp.net的用起来比较方便) 博客说明 http://blog.csdn.net/spyking945/article/details/44775827
一个jQuery的分页插件,是在原来网上下载的jQuery的插件上扩展的,原来的是只有按钮的,扩展新增了可以选择用文本框或下拉框来选择跳转页面。因为出现过乱码问题,所以中文的那个里面的中文字符是用的Unicode的编码
jquery.easing.js 1.3 是一个配合jquery实现完美动画效果的扩展插件,比如我们在使用jquery制作一幅图片滚动或图片渐变,使用本插件可扩展或增强jquery性能,生成完美无缺兼容性更好的jquery动画来,它不仅可以用于...
jquery扩展插件,jquery提供的html()方法,只能获取标签内部内容,本插件进行了扩展实现了取得包含标签自身的html,并解决了input/radio/checkbox/select等输入后无法取值问题。
一个JqueryUI Tabs插件的扩展 可动态添加或关闭的Tabs插件 已经添加过的Tab,再次添加时候不添加新的,而是选中原来的Tab。
jquery菜单展开插件,里面有插件所用到的js库,css样式,以及典型的demo,有几种展开样式的代码各供开发者扩展。可快速实现菜单展开的效果。
Jquery扩展插件,图片异步分页浏览 Jquery扩展插件,图片异步分页浏览
为Dw CS5安装jQuery代码提示扩展插件. 本资料共包含以下附件: jQuery_api_for_dwcs5.rar
本Demo基于cropper插件整理的便捷源码,下载即可直接使用! 并且Demo中有详细的注释,通俗易懂,易于扩展、维护、个性化设置等! 还是那句话,谁下谁知道
jQuery formValidator表单验证插件,它是基于jQuery类库,实现了js脚本于页面html代码的分离。你可以划分多个校验组,每个组的校验都是互不影响。对一个表单对象,你只需要写一行代码就可以轻松实现无数种(理论上)...
全国 省份 城市 地区 Jquery插件 有能力的自己扩展
DataTables是提供了大量特性的强大jQuery表格插件。例如:你可以自动轻松筛选、Ajax预读取数据、分页、列排序、高亮排序列、扩展插件支持、使用CSS或jQuery UI ThemeRoller 定制主题和完整文档。
基于jquery+flash的一个上传插件,拥有超强的自定义扩展空间。
jQuery扩展插件和拓展函数的写法---代码