Using events in jQuery plugins
The main purpose of this article is to: show the differences between the traditional implementation of the jQuery plugin and the implementation using events. The article will be: about the traditional implementation of the jQuery plugin, about working with events in jQuery, and an attempt to replace the methods or callback functions of the plugin with events.
The article is primarily intended for beginners, but there is a desire to hear the professional opinion of people who are familiar with this issue, have a deeper understanding of the things described in the article.
Creating a traditional jQuery plugin is a fairly trivial task. To do this, add a new method to the $ .fn space.
This structure is great for creating simple plugins from which you do not need to receive data.
But often we need to get the data or the state of the plugin. A good example is DatePicker.
I know several solutions for getting data:
The problem in the implementation of the methods P.1.A and P.1.B is that the next time
But I ran into the problem of variable scopes.
Example 5: Demonstrating the scope problem
At this stage, everything is simple: create a plugin that displays the date from the options.
But the problem arises when it is necessary to place more than one plugin of a given type on a page.
Example 6: More than one plugin per page
As you can see from example 6, the options variable, which was moved outside the plugin, was overwritten with data when plugin 2 was initialized.
Using the jQuery library, we can both create “listeners” for events
We turn to the documentation, see the parameters of both functions:
In general, the on function has parameters:
The trigger function has parameters:
Example 7: Demonstrating the Operation of Events
To get rid of the problem with the scope of variables (described in Example A.6 ) and the problem of hanging multiple listeners (described in solution P.1.B ), I resorted to using events and wrappers implemented in jQuery (1.B).
Example 7: Implementing events in a plugin
What we got:
Example 8 Demonstrating the operation of several initializations of one plug-in A.7
Of course, this approach changes the usual approach to working with the plugin, I mean the lack of traditional methods for obtaining data, for example
For training and running in events, he wrote several small client applications:
Using examples, I showed how to create a jQuery plug-in, identified issues of data transfer and receiving data from a plug-in that are relevant for me, showed how to use jQuery events and wrappers, and touched upon the topic of creating an application that actively uses jQuery plugins and events.
I did not touch on the topic of event pop-ups in the DOM tree, and I also wanted to pay more attention to creating applications using events. But, if there is karma for that, I will definitely write a sequel.
Once again, I want to appeal to people who create professional client applications: I love criticism, and I want to hear an opinion about this approach, and in general I would like to know more about creating client applications first-hand. Therefore, write - I will be grateful.
Thanks for attention!
The article is primarily intended for beginners, but there is a desire to hear the professional opinion of people who are familiar with this issue, have a deeper understanding of the things described in the article.
1. Theory
1.A. Traditional jQuery
1.B plugin Scope of variables
1.V. Working with events in jQuery
1.G. Application events in plugins
1.D. Disadvantages of events
2. An example of a simple application with crushing into plug-ins
3. Conclusion, conclusion
4. References
1. Theory
1.A. Traditional jQuery plugin
Creating a traditional jQuery plugin is a fairly trivial task. To do this, add a new method to the $ .fn space.
Example 1 (creating the myPlugin plugin):
(function( $ ) {
$.fn.myPlugin = function(options) {
// Переменная options - настройки плагина// Объект $(this) - доступ к объекту jQuery с выбранным элементом, на который навешен плагин// Код плагина будет располагаться здесь
};
})( jQuery );
This structure is great for creating simple plugins from which you do not need to receive data.
But often we need to get the data or the state of the plugin. A good example is DatePicker.
I know several solutions for getting data:
- R.1.A. Calling a method (or function) .
Example 2$('input.date').datePicker('getDate');
$('input.date').datePicker('isDisabled')
.
Disadvantage: there is no way to track changes (for example, the user chose a different value); - R.1.B. Passing a callback function .
Example 3$('input.date').datePicker({onChange: onChangeCallback});
$('input.date').datePicker({onDisable: onDisableCallback})
.
Disadvantage: Complicating the implementation of the plugin: it is necessary to implement a callback function call, subscribing to an event of several listeners; - R.1.V. Events .
Example 4$('input.date').on('change', onChangeHandler);
$('input.date').on('disable', onDisableHandler)
.
More about the pros and cons further.
1.B. Variable Scope
The problem in the implementation of the methods P.1.A and P.1.B is that the next time
$(element).datePicker(...)
the “constructor” of the plugin is re-executed. Of course, this is easily monitored by checking the parameters passed: if the object (options) is passed, this is initialization; if a string is passed, a method call is necessary. As the saying goes, “this is a bug or feature” - while there is not enough experience to understand. But I ran into the problem of variable scopes.
Example 5: Demonstrating the scope problem
(function( $ ){
// Опцииvar options = {
date: '00-00-0000'
},
// Методы
methods = {
getDate: function(){
return options.date;
}
};
// Плагин
$.fn.myPlugin = function(o){
if (typeof o === 'string' && methods[o] !== null) {
return methods[o].apply();
}
options = o || options;
$(this).text(options.date);
};
// Инициализация плагина
$('[data-test]').myPlugin({
date: '10-10-2013'
});
// Получение данных
alert($('[data-test]').myPlugin('getDate'));
})( jQuery );
At this stage, everything is simple: create a plugin that displays the date from the options.
But the problem arises when it is necessary to place more than one plugin of a given type on a page.
Example 6: More than one plugin per page
As you can see from example 6, the options variable, which was moved outside the plugin, was overwritten with data when plugin 2 was initialized.
Solutions for example 6:
- R.2.A. In the options object, store data to initialize all plugins (code complication);
- R.2.B. Attach initialization data to a DOM object (from my point of view: a good solution);
- R.2.V. Use of events. Calling methods with
$(...).trigger(...)
. In the end I will give an example that is devoid of this drawback.
1.B. Working with events in jQuery
Using the jQuery library, we can both create “listeners” for events
$('.link').on('click', onClickHandler)
and call (trigger) events $('.link').trigger('click')
. We turn to the documentation, see the parameters of both functions:
In general, the on function has parameters:
- events - a list of events to listen to;
- handler - an event handler function that will be called when any event from the events list is committed.
The trigger function has parameters:
- eventType - name of the event to be called;
- extraParameters - an array or object containing parameters that must be passed to the event handler.
Example 7: Demonstrating the Operation of Events
$(function() {
$(document).on('myEvent', function(event, p) {
alert('a: ' + p.a + '; b: ' + p.b);
});
$(document).trigger('myEvent', {
a: '1',
b: '2'
});
});
1.G. Application events in plugins
To get rid of the problem with the scope of variables (described in Example A.6 ) and the problem of hanging multiple listeners (described in solution P.1.B ), I resorted to using events and wrappers implemented in jQuery (1.B).
Example 7: Implementing events in a plugin
(function( $ ) {
// Объявление плагина
$.fn.datePicker = function(options)
{
var self = $(this),
options = options || {
year: 2012,
month: 1,
day: 1
};
var date = newDate(options.year, options.month, options.day),
d = newDate(options.year, options.month, 1),
table = $('<table />'),
tr = $('<tr>');
tr.appendTo(table);
// Добавляем начало месяцаfor (i=0; i < d.getDay(); i++) {
tr.append('<td />');
}
// Добавляем датыwhile (d.getMonth() == date.getMonth()) {
if (i % 7 == 0) {
tr = $('<tr />');
tr.appendTo(table);
i = 0;
}
var td = $('<td>' + d.getDate() + '</td>');
td.data('date', d.toString());
tr.append(td);
d.setDate(d.getDate() + 1);
i++;
}
// Добавляем конец месяцаfor (i=0; i < 7 - d.getDay(); i++) {
tr.append('<td />');
}
table.appendTo(self);
// При клике на ячейку таблицы генерируем событие 'change' для плагина
table.find('td').on('click', function() {
// Вторым параметром передаем дату
self.trigger('change', $(this).data('date'));
});
return self;
};
// Инициализация плагина
$('[data-datePiceker]').datePicker();
// Навешивание слушателя для события
$('[data-datePiceker]').on('change', function(event, date) {
alert(date);
});
})( jQuery );
What we got:
- "Constructor" is called only once;
- we can hang a lot of "listeners" who will receive information about the status of the plugin;
- variables related to the plugin are located in the body of the function, and do not depend on other initializations of this plugin.
Example 8 Demonstrating the operation of several initializations of one plug-in A.7
1.D. Event flaws
Of course, this approach changes the usual approach to working with the plugin, I mean the lack of traditional methods for obtaining data, for example
$(...).datePicker('getDate')
, but nevertheless, at this stage of my personal development, as a programmer, this method solves some of my problems. I personally, I think this approach is quite universal, and have not yet encountered any flaws - if the reader knows about those, please do not be silent, and I also want to ask you to write as accessible and adequate as possible.2. An example of a simple application with crushing into plugins
For training and running in events, he wrote several small client applications:
- Appendix 1 (Twitter feed ): jsbin.com/afupej/1/edit
- Appendix 2 (TODO List): jsbin.com/urihar/16/edit
3. Conclusion, conclusion
Using examples, I showed how to create a jQuery plug-in, identified issues of data transfer and receiving data from a plug-in that are relevant for me, showed how to use jQuery events and wrappers, and touched upon the topic of creating an application that actively uses jQuery plugins and events.
I did not touch on the topic of event pop-ups in the DOM tree, and I also wanted to pay more attention to creating applications using events. But, if there is karma for that, I will definitely write a sequel.
Once again, I want to appeal to people who create professional client applications: I love criticism, and I want to hear an opinion about this approach, and in general I would like to know more about creating client applications first-hand. Therefore, write - I will be grateful.
Thanks for attention!
4. Used literature
5. Literature from commentators
- jQuery UI: Widget Factory
- A very large selection of diverse design patterns and examples from popular frameworks
- Judging by the English. the name of the Refactoring Patterns (not yet studied)
Only registered users can participate in the survey. Please come in.