jQuery UI Расширение виджетов с помощью фабрики виджетов
Фабрика виджетов jQuery UI упрощает создание виджетов, расширяющих функциональность существующих виджетов. Так вы можете создавать мощные виджеты на основе существующих или вносить тонкие изменения в функциональность существующих виджетов.
Примечание:Прежде чем изучать эту главу, вам нужно понять, что такое фабрика виджетов и как она работает. Если вы не знакомы с этой темой, сначала прочитайтеКак использовать фабрику виджетовглаву.
Создание расширений виджетов
Создание виджетов с помощью фабрики виджетов выполняется путем передачи$.widget()имени виджета и объекта-прототипа. В примере создается виджет "superDialog" в пространстве имен "custom".
$.widget( "custom.superDialog", {} );
Для поддержки расширения,$.widget()опционально принимает конструктор виджета, который будет использоваться в качестве родительского виджета. При указании родительского виджета передайте его вторым параметром, после имени виджета и перед объектом-прототипом виджета.
Как и в примере выше, следующий код также создаёт виджет "superDialog" в пространстве имён "custom". Но на этот раз он передаёт конструкторвиджета dialog из jQuery UI($.ui.dialog), указывая на то, что виджет superDialog должен использовать виджет dialog из jQuery UI в качестве родительского виджета.
$.widget( "custom.superDialog", $.ui.dialog, {} );
Здесь виджеты superDialog и dialog по сути эквивалентны, только с разными именами и пространствами имён. Чтобы сделать наш новый виджет более отличимым, мы можем добавить несколько методов в его объект-прототип.
Объект-прототип виджета — это последний параметр, передаваемый в$.widget(). Пока что в нашем примере использовался пустой объект. Теперь давайте добавим метод в этот объект:
$.widget( "custom.superDialog", $.ui.dialog, {
red: function() {
this.element.css( "color", "red" );
}
});
// Create a new <div>, convert it into a superDialog, and call the red() method.
$( "<div>I am red</div>" )
.superDialog()
.superDialog( "red" );
ТеперьsuperDialogимеетred()метод, который меняет цвет его текста на красный. Обратите внимание, как Widget Factory автоматически устанавливаетthisв объект экземпляра виджета. Чтобы просмотреть список всех доступных методов и свойств экземпляра, посетитедокументацию API Widget Factory。
Расширение существующих методов
Иногда требуется настроить или добавить поведение к существующим методам виджета. Вы можете указать имя метода как имя метода для переопределения в объекте-прототипе. В следующем примере переопределяетсяopen()методdialog. Поскольку диалог по умолчанию открыт, когда этот код выполняется,"open"будет выведено в журнал.
$.widget( "custom.superDialog", $.ui.dialog, {
open: function() {
console.log( "open" );
}
});
// Create a new <div>, and convert it into a superDialog.
$( "<div>" ).superDialog();
При выполнении этого кода возникает проблема. Потому что мы переопределилиopen()поведение по умолчанию, диалог больше не отображается на экране.
Когда мы используем метод на объекте-прототипе, мы фактически переопределяем исходный метод, используя новый метод в цепочке прототипов.
Чтобы сделать методы родительского виджета доступными, Widget Factory предоставляет два метода -_super()и_superApply()。
Использование_super()и_superApply()для доступа к родительскому виджету
_super()и_superApply()и вызвать тот же метод у родительского виджета. См. пример ниже. Как и в предыдущем примере, этот пример также переопределяетopen()метод для логирования"open". Однако на этот раз выполнение_super()вызывает у диалогаopen(), и открывает диалог.
$.widget( "custom.superDialog", $.ui.dialog, {
open: function() {
console.log( "open" );
// Invoke the parent widget's open().
return this._super();
}
});
$( "<div>" ).superDialog();
_super()и_superApply()На самом деле это эквивалентно исходномуFunction.prototype.call()иFunction.prototype.apply()метод. Следовательно,_super()принимает список аргументов,_superApply()принимает массив в качестве аргумента. Следующий пример демонстрирует разницу между ними.
$.widget( "custom.superDialog", $.ui.dialog, {
_setOption: function( key, value ) {
// Both invoke dialog's setOption() method. _super() requires the arguments
// be passed as an argument list, _superApply() as a single array.
this._super( key, value );
this._superApply( arguments );
}
});
Переопределение виджетов
jQuery UI 1.9 добавил возможность переопределять виджеты. Поэтому вместо создания нового виджета нам нужно только передать$.widget()имя существующего виджета и конструктор. Следующий пример добавляетopen()такое же логирование в ..., но не путем создания нового виджета.
$.widget( "ui.dialog", $.ui.dialog, {
open: function() {
console.log( "open" );
return this._super();
}
});
$( "<div>" ).dialog();
С помощью этого метода мы можем расширить существующий метод виджета, но мы всё ещё можем использовать_super()для доступа к исходному методу - это делается не путем создания нового виджета, а путем прямого переопределения виджета.
Виджеты и полиморфизм
При взаимодействии между расширениями виджетов и их плагинами стоит отметить, что плагин родительского виджета нельзя использовать для вызова методов на элементах дочернего виджета. Следующий пример демонстрирует это.
$.widget( "custom.superDialog", $.ui.dialog, {} );
var dialog = $( "<div>" ).superDialog();
// This works.
dialog.superDialog( "close" );
// This doesn't.
dialog.dialog( "close" );
В примере выше плагин родительского виджета,dialog(), невозможно вызватьclose()метод для элемента superDialog. Чтобы узнать больше о вызове методов виджета, обратитесь кВызовы методов виджета。
Настройка отдельных экземпляров
До сих пор во всех примерах, которые мы видели, методы расширялись в прототипе виджета. Переопределение методов в прототипе влияет на все экземпляры виджета.
Чтобы продемонстрировать это, см. пример ниже. Оба экземпляра диалога используют один и тот жеopen()метод.
$.widget( "ui.dialog", $.ui.dialog, {
open: function() {
console.log( "open" );
return this._super();
}
});
// Create two dialogs, both use the same open(), therefore "open" is logged twice.
$( "<div>" ).dialog();
$( "<div>" ).dialog();
Иногда нужно изменить поведение только одного экземпляра виджета. Для этого нужно использовать обычное присваивание свойств JavaScript, получить ссылку на экземпляр и переопределить метод. Это показано в примере ниже.
var dialogInstance = $( "<div>" )
.dialog()
// Retrieve the dialog's instance and store it.
.data( "ui-dialog" );
// Override the close() method for this dialog
dialogInstance.close = function() {
console.log( "close" );
};
// Create a second dialog
$( "<div>" ).dialog();
// Select both dialogs and call close() on each of them.
// "close" will only be logged once.
$( ":data(ui-dialog)" ).dialog( "close" );
Техника переопределения методов в отдельном экземпляре идеально подходит для разовых настроек.
Другие расширения