Go from: Maintao: Writing jQueryUI plugin (widget)
Using jQueryUI widgets to write plugins has some advantages over basic jquery plugins:
* Easy to implement inheritance, code reuse
* Default is a single case
* Widgets have given you some common ways to achieve good, such as Destroy
Bring the benefits of the same time brought thorns and traps, the purpose of this article is to comb these thorns, mark where there is a trap.
Basics: Naming conventions, public, private, this, this.element
How do I start writing a widget? The template is as follows:
(function ($) { ///Utility functions (won ' t be inherited) function foo () {} $.widget ('/* Snip */});}) (jQuery);
Where namespaces are optional, it is also optional to inherit from other widgets. The big head is the snip part of the back, this is also the following to say.
It is generally appropriate to write tool functions outside of widgets, but if you want these tool functions to inherit from the quilt, you need to write them in the widget.
Written in the widget, there are public and private points, the rule is:
Public method first character is not _
Private method The first character is _
When a method is called, it first determines whether to start with _, and if so, does not execute the call.
What if I had to call the private method outside? There is no way to do it:
var instance = $ (' <div> '); Instance.mywidget (//Workinstance.mywidget (//silently Failinstance.data (// work
Within the widget, what does this mean? Let's use Console.log (this) in a widget's public function to see:
The log shows that this is a $.widget.$. (anonymous function). (anonymous function)
This.element is the jquery object that becomes the widget, and if you want to use jquery, it's often the first thing to get a jquery object.
This.options is the plugin option and is explained below.
THIS.__PROTO__ contains all the public and private functions defined in the plug-in, as well as the inherited methods.
Here is a brief introduction to __proto__: Each object Initializes a property within it, that is, __proto__, when we access the property of an object, if the object does not exist inside this property, then he will go to __proto__ to find this attribute, this __proto_ _ and will have their own __proto__, so have been looking down, which is what we usually say the concept of the prototype chain.
_create _init Destroy
Widget Factory implements a singleton pattern that does not allow multiple instantiation of the same jquery object.
When calling $ (XX) to initialize the Widgetname (), the following code is executed (source intercept from Jquery.ui.widget.js):
Remove the data if (instance) { instance.option (Options | |) from the widget itself. {}). _init (); Create a new instance and save the instance if the data is not yet}
When calling $ (XX) widgetname (' destroy ') for destruction, execute the following code (source intercepts from Jquery.ui.widget.js):
This.element this.widgetname )
There is a removedata operation, then the next call to $ (XX). Widgetname () will be re-instantiated.
It is important to note that the Destroy method is implemented by default in Jquery.ui.widget.js, and _create and _init are not implemented. So if you overwrite destroy in your own way, don't forget to call the default:
function () { console.log (' destory '); //Call the original Destroy method since we overwrote it $. Widget.prototype.destroy.call (this);}
The following sample code verifies the difference between _create and _init and the role of Destroy:
var MW = $ (///_create _INITMW = $ (///_initmw.mywidget (' destory '); mw = $ (//_create _init
So what should be done in _create and _init and destroy respectively:
_create: Generates HTML, event bindings.
_init: Performs the default initialization action, such as turning the page into its initial state.
Destory: Call $. Widget.prototype.destroy.call (this), delete the HTML.
Note: Binding events note the namespace suffix of the event name: for example. Bind (' MouseEnter. Mywidget', this._hover)
Options
option, which is defined in the widget, is the options, while the call is option, note that there is s at the time of definition, and no s at the time of the call.
Defined:
Option
S
: { ' default ', function () { console.log (' default option function1 ');} },
Call:
$ (' #test '). Mywidget ('field1 ', 2);
The widget implements two functions by default: the implementation of _setoptions and _setoption,_setoptions is to call _setoption for each option to be modified, that is, the actual modified action is in _setoption. Therefore, if you want to override the _setoption function, you must not forget to write:
$. Widget.prototype._setoption.apply (this, arguments);
When are the functions of _setoptions and _setoption called? Use the following example to illustrate.
For example, there are such _setoption and _setoptions:
function (key, value) { console.log (' _setoption:key=%s value=%s ', key, value); $. Widget.prototype._setoption.apply (options) { var key; Console.group (this;},
and a function printoptions to print the options value:
function () { console.group (' options '); Console.log (this.options.field1); Console.log (this.options.function1); Console.groupend ();},
We invoke the following as follows:
var instance = $ ( ' <div> '); //Create widget with default Optionsconsole.group (); Instance.mywidget (); Instance.mywidget ( ' printoptions '); Console.groupend (); //create widget with specified Optionsinstance.mywidget ( ' destroy '); Console.group (); var opts = {field1: ' specified ', function1: function () { Console.log ( ' specified option function1 ');},};instance.mywidget (opts); Instance.mywidget ( ' printoptions '); Console.log ( '-------------'); Instance.mywidget (opts); Console.groupend (); //modify Optionsconsole.group (); Instance.mywidget ( "option", ' field1 ', 2); Instance.mywidget ( ' printoptions '); Console.groupend ();
The log is typed as follows:
The log is divided into three chunks.
The first block is not initialized with options, and you can see that the default options in the definition are not called _setoption.
The second block is initialized with options, which is done in two experiments (the log is separated by a--------of two), the first experiment is completely rebuilt (_create, _init), and the _setoption is not called from the log, and the second experiment is just reinitialization (_ init), the options are all the same, from the log you can see that it called _setoption, and was called before _init.
The third block is not initialized, but simply modifies the option value, and it is clear to see that the _setoption is called.
when to invoke _setoption's conclusion:
1. Like Instance.mywidget (' option ', ' field1 ', 2); When you explicitly set option.
2. With options initialization:
If the instance does not exist, call _create is required, then _setoption is not called;
If the instance already exists and only needs to call _init, then _setoption is called before calling _init.
_trigger
Note that this _trigger is in the jQueryUI widget factory, and the trigger function under the $.fn namespace in jquery is not a thing (the latter is not underlined).
_trigger is generally used to callback the user into the options callback.
Calling _trigger (' MyEvent ') inside the plug-in is equivalent to invoking the MyEvent callback function inside the options.
What should I do to change the event handler in the options? Instead of using Bind/unbind, go to modify options:
Bind (Overwrite, not add event handler) Mw.mywidget (function (event, UI) { Console.log (' new Implement ');}); //Unbindmw.mywidget (null);
To summarize:
This._trigger (' EventName ') is a widget-specific, used to invoke the callback defined in the options.
This.element.trigger (' EventName ') is jquery and can refer to the use of jquery events. (where This.element is the jquery object that represents the plugin)
An example of a _trigger:
Template
"Callbackname", [EventObject], [UiObject])
callbackName
The name of the event want to dispatch eventObject
(Optional) A (mocked) event object. _trigger
wraps This object and stores it I n the event.originalEvent
user receives an object with Event.type = = this.widgetEventPrefix + "eventname"
uiObject
(Optional) An object containing useful properties the user may need to access. Protip: Use a method like to ._ui
generate objects with a consistent schema.
//Call example this._trigger ( "hover", E Span class= "rem" >/* e.type = = "MouseEnter" */, {hovered: $ (e.target)}); //the user can subscribe using an init option$ ( "#elem"). Filterable ({hover: function (E,ui) {}}); //Or with traditional event binding/delegation$ ( "#elem"). Bind ( "Filterablehover", function (E,ui) {});