Цель.
Давайте добавим функциональности к Ext.form.Combobox, сделаем так, чтобы перед каждым элементом списка отображалась иконка.
Давайте назовем наш плагин Ext.ux.IconCombo, а также зарегистрируем для него xtype iconcombo.
Создаем файлы.
Наш первый шаг заключается в том, чтобы подготовить файлы для нашего плагина.
- iconcombo.html: HTML код приложения, которое будет содержать наш плагин. Чтобы сделать этот пример более простым, этот файл также будет содержать Javascript код и CSS. В реальном приложении нужно хранить отдельно код и стили.
- Ext.ux.IconCombo.js: Javascript код нашего плагина.
iconcombo.html
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link rel="stylesheet" type="text/css" href="../extjs-2.0/resources/css/ext-all.css"> <script type="text/javascript" src="../extjs-2.0/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../extjs-2.0/ext-all-debug.js"></script> <script type="text/javascript" src="Ext.ux.IconCombo.js"></script> <style type="text/css"> .ux-flag-us { background-image:url(../img/flags/us.png) ! important; } .ux-flag-de { background-image:url(../img/flags/de.png) ! important; } .ux-flag-fr { background-image:url(../img/flags/fr.png) ! important; } .ux-icon-combo-icon { background-repeat: no-repeat; background-position: 0 50%; width: 18px; height: 14px; } /* X-BROWSER-WARNING: this is not being honored by Safari */ .ux-icon-combo-input { padding-left: 25px; } .x-form-field-wrap .ux-icon-combo-icon { top: 3px; left: 5px; } .ux-icon-combo-item { background-repeat: no-repeat ! important; background-position: 3px 50% ! important; padding-left: 24px ! important; } </style> <script type="text/javascript"> Ext.BLANK_IMAGE_URL = '../extjs-2.0/resources/images/default/s.gif'; Ext.onReady(function() { var win = new Ext.Window({ title:'Icon Combo Ext 2.0 Extension Class Example', width:400, height:300, layout:'form', bodyStyle:'padding:10px', labelWidth:70, defaults:{anchor:'100%'}, items:[{ xtype:'iconcombo', fieldLabel:'IconCombo', store: new Ext.data.SimpleStore({ fields: ['countryCode', 'countryName', 'countryFlag'], data: [ ['US', 'United States', 'ux-flag-us'], ['DE', 'Germany', 'ux-flag-de'], ['FR', 'France', 'ux-flag-fr'] ] }), valueField: 'countryCode', displayField: 'countryName', iconClsField: 'countryFlag', triggerAction: 'all', mode: 'local' }] }); win.show(); }); </script> <title>Icon Combo Ext 2.0 Extension Class Example</title> </head> <body> </body> </html>
Этот файл помимо html разметки содержит функцию фасад — onReady, которая создает окно с формой, а на ней единственный элемент наш iconcombo. Будьте внимательны, в этом примере реальной формы не создается (тега <form> нет). Хранилище (store) iconcombo содержит уже заполненые данные для тестирования.
Вам необходимо изменить пути к файлам ExtJS, если он установлен в другом месте.
Вам, возможно, также понадобится поменять пути к изображениям флагов.
Ext.ux.IconCombo.js
// vim: ts=4:sw=4:nu:fdc=2:nospell /** * Ext.ux.IconCombo Extension Class for Ext 2.x Library * * @author Ing. Jozef Sakalos * @version $Id: Ext.ux.IconCombo.js 617 2007-12-20 11:29:56Z jozo $ * * @class Ext.ux.IconCombo * @extends Ext.form.ComboBox */ Ext.ux.IconCombo = Ext.extend(Ext.form.ComboBox, { initComponent:function() { // call parent initComponent Ext.ux.IconCombo.superclass.initComponent.call(this); } // end of function initComponent }); // register xtype Ext.reg('iconcombo', Ext.ux.IconCombo); // end of file
Первый шаг в расширении класса, это создание дополнения, которое не изменяет функциональности родительского класса. Таким образом мы можем быть уверены, что родительский класс отлично работает, и добавленный нами функционал не затронет его работу.
Javascript файл выше делает именно это.
Теория.
Чтобы расширить класс в ExtJS мы не должны создавать функцию-конструктор. Нам просто нужно присвоить значение возвращаемое функцией Ext.extend при ее вызове в нашем пространстве имен. Ext.extend получает в качестве аргументов родительский класс и конфиг (функционал расширения) в качестве второго аргумента, и возвращает наш класс-раширение.
Все что мы раньше делали в конструкторе в старых версиях Ext 1.x, теперь делается в методе initComponent, который мы перезаписываем в родительском классе. initComponent это метод-конструктор родительского класса.
Тем не менее метод initComponent родительского класса содержит полезный код, который должен быть выполнен. Вы можете посмотреть как мы вызываем метод initComponent родительского класса в приведенном выше коде. Модель вызова метода родителя, одинакова для все функции, которые мы переопределяем в классе.
Регистрации xtype для нашего расширения не является обязательной, но это очень удобно, вы можете вызывать расширение просто набрав несколько символов имени его xtype. То есть точно также, как показано в этом примере.
Приступим.
Пока все хорошо. Теперь если открыть iconcombo.html, вы должны увидеть стандартный combobox с тремя значениями и выбранной Германией. Пока конечно же никаких иконок.
Теперь пришло время поработать. Добавьте следующие строки в Ext.ux.IconCombo.js перед вызовом родительского метода initComponent:
Ext.apply(this, { tpl: '<tpl for=".">' + '<divst0">'{' + this.iconClsField + '}">' + '{' + this.displayField + '}' + '</div></tpl>' });
В этом коде мы переопределяем стандартные элементы combobox нашими, которые будут использовать css класс iconClsField.
Отлично, готовы протестировать ? Обновите страницу, круто да ?
Замечательно у нас красивые значки при открытии списка, но мы также хотим видеть флаг, когда combobox закрыт, не так ли ?
Добавьте следующий код после окончания кода метода initComponent:
onRender:function(ct, position) { // call parent onRender Ext.ux.IconCombo.superclass.onRender.call(this, ct, position); // adjust styles this.wrap.applyStyles({position:'relative'}); this.el.addClass('ux-icon-combo-input'); // add div for icon this.icon = Ext.DomHelper.append(this.el.up('div.x-form-field-wrap'), { tag: 'div', style:'position:absolute' }); }, // end of function onRender setIconCls:function() { var rec = this.store.query(this.valueField, this.getValue()).itemAt(0); if(rec) { this.icon.className = 'ux-icon-combo-icon ' + rec.get(this.iconClsField); } }, // end of function setIconCls setValue: function(value) { Ext.ux.IconCombo.superclass.setValue.call(this, value); this.setIconCls(); } // end of function setValue
Вызов события onRender сначала вызывает родительский метод onRender, а потом добавляет стили и div’ы с иконками.
Мы также добавляем метод setIconCls и перезаписываем родительский метод setValue. Конечно мы хотим, чтобы родительский метод setValue тоже выполнился, поэтому мы сначала вызываем его, а потом выполняем наш метод setIconCls.
Окончание.
Теперь последние испытание: перезагрузите страницы. Если вы при копировании примера не сделали ошибок вы получили новое расширение Ext.ux.IconCombo. Конечно можно еще усовершенствовать наше расширение, но это только лишь пример, как раcширять классы в ExtJS.
Окончательный код.
Вот полный код того, что у нас получилось:
// vim: ts=4:sw=4:nu:fdc=2:nospell /** * Ext.ux.IconCombo Extension Class for Ext 2.x Library * * @author Ing. Jozef Sakalos * @version $Id: Ext.ux.IconCombo.js 617 2007-12-20 11:29:56Z jozo $ * * @class Ext.ux.IconCombo * @extends Ext.form.ComboBox */ Ext.ux.IconCombo = Ext.extend(Ext.form.ComboBox, { initComponent:function() { Ext.apply(this, { tpl: '<tpl for=".">' + '<divst0">'{' + this.iconClsField + '}">' + '{' + this.displayField + '}' + '</div></tpl>' }); // call parent initComponent Ext.ux.IconCombo.superclass.initComponent.call(this); }, // end of function initComponent onRender:function(ct, position) { // call parent onRender Ext.ux.IconCombo.superclass.onRender.call(this, ct, position); // adjust styles this.wrap.applyStyles({position:'relative'}); this.el.addClass('ux-icon-combo-input'); // add div for icon this.icon = Ext.DomHelper.append(this.el.up('div.x-form-field-wrap'), { tag: 'div', style:'position:absolute' }); }, // end of function onRender setIconCls:function() { var rec = this.store.query(this.valueField, this.getValue()).itemAt(0); if(rec) { this.icon.className = 'ux-icon-combo-icon ' + rec.get(this.iconClsField); } }, // end of function setIconCls setValue: function(value) { Ext.ux.IconCombo.superclass.setValue.call(this, value); this.setIconCls(); } // end of function setValue }); // register xtype Ext.reg('iconcombo', Ext.ux.IconCombo); // end of file
Источник: http://www.extjs.com/learn/Tutorial:Extending_Ext2_Class.
Спасибо! Очень сайт понравился, очень интересные статьи. Автору — респект