Цель.
Давайте добавим функциональности к 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.
Спасибо! Очень сайт понравился, очень интересные статьи. Автору — респект