/** * Ext.ux.LocationSelect для выбора локации вида Страна-Регион-Город * * @author Кирилл Петров * * @class Ext.ux.LocationSelect * @extends Ext.form.FieldSet */ Ext.ux.LocationSelect = Ext.extend(Ext.form.FieldSet, { /** * Вернет комбобокс выбора части локации * * @param {String} имя части локации ('country', 'region', 'city') * @return {Ext.form.ComboBox} */ getCombo: function(part){ return this.combo[part]; }, /** * Установит комбобокс выбора части локации в кеш компонента * * @param {String} имя части локации ('country', 'region', 'city') * @return {Ext.form.ComboBox} */ setCombo: function(part, combo){ return this.combo[part] = combo; }, /** * Вернет кешированные данные для локации * * @param {Integer} id локации * @return {Object} json данные локации в формате {rows: [{id: integer, name: string}]} */ getCache: function(id){ return this.cache[id]; }, /** * Установит в кеш данные data для локации * * @param {Integer} id локации */ setCache: function(id, data){ this.cache[id] = data; }, /** * Установит в кеш данные data для локации * * @param {Integer} id локации */ assign: function(combo, data, value){ combo.store.loadData(data); combo.setValue(value); }, /** * Создаст комбобокс для выбора части локации * * @param {String} label надпись рядом с контролом * @param {String} part имя части локации * @param {Array} partNext последующие части локации * @return {Ext.form.ComboBox} */ createLocationComboBox: function(part, partNext){ partNext = partNext || []; var ds = new Ext.data.Store({ url: this.url, autoLoad: part == 'country' ? {params: {parentId: 1}} : false, reader: new Ext.data.JsonReader({ root: 'rows', id: 'id' }, [{name: 'id'}, {name: 'name'}]) }); ds.on({ //загрузка из кеша, если возможно beforeload: function(store, options){ parentId = options.params.parentId || 1; var data; if (data = this.getCache(parentId)) { store.loadData(data); return false; } }.createDelegate(this), //кеширование load: function(store, records, options){ //активировать комбобоксы if (options.params && options.params.parentId && options.params.parentId != 1 || !options.params) { Ext.each(this.parts, function(part){ this.getCombo(part).enable(); }.createDelegate(this)); } //загрузка без параметров - нечего кешировать if (!options.params) return; this.setCache(options.params.parentId || 1, store.reader.jsonData); }.createDelegate(this) }); var comboConfig = { valueField: 'id', displayField: 'name', mode: 'local', triggerAction: 'all', selectOnFocus: true, store: ds, listeners: { select: function(combo, record){ if (partNext[0] && record.get('id') != 0) {//части стран или регионов и не "нулевая" опция //все комбобоксы задисаблить Ext.each(this.parts, function(part){ this.getCombo(part).disable(); }.createDelegate(this)); //сбросить в "нулевое" состоние все последующие комбобоксы Ext.each(partNext, function(part){ this.getCombo(part).setValue(0); }.createDelegate(this)); //выполнить загрузку по выбранной опции this.getCombo(partNext[0]).store.reload({ params: { parentId: record.get('id') } }); } else {//"нулевая" опция - обнулить все последующие комбобоксы Ext.each(partNext, function(part){ var combo = this.getCombo(part); combo.disable(); combo.setValue(0); }.createDelegate(this)); } this.validator(this); }.createDelegate(this) } }; Ext.applyIf(comboConfig, this.cc[part]); this.setCombo(part, new Ext.form.ComboBox(comboConfig)); return this.getCombo(part); }, /** * Выполнит загрузку локации * * @param {Object} локация заданная в формате {country: integer, region: integer, city: integer} */ loadLocation: function(config){ Ext.applyIf(config, { country: 0, region: 0, city: 0 }); if (!config.country) return; Ext.Ajax.request({ url: this.url, callback: function(options, success, response){ var result; if ((result = Ext.decode(response.responseText)) && success) { this.setCache(config.country, {rows: result.rows.region}); this.setCache(config.region, {rows: result.rows.city}); this.assign(this.getCombo('country'), this.getCache(1), config.country); this.assign(this.getCombo('region'), this.getCache(config.country), config.region); this.assign(this.getCombo('city'), this.getCache(config.region), config.city); } }.createDelegate(this), params: config }); }, /** * Инициализация: создание компонентов и начальная загрузка стран */ initComponent: function(){ this.parts = ['country', 'region', 'city']; this.labels = ['Страна', 'Регион', 'Город']; Ext.apply(this, this.initialConfig, { prefix: 'location_', url: '', labelWidth: 50, validator: Ext.emptyFn, cache: [], cc: {} }); Ext.each(this.parts, function(part, index){ this.cc[part] = this.cc[part] || {}; Ext.applyIf(this.cc[part], { name: this.prefix + part, hiddenName: '_' + this.prefix + part, editable: false, emptyText: 'Не имеет значения', valueNotFoundText: 'Не имеет значения', width: 180, fieldLabel: this.labels[index] }); }.createDelegate(this)); this.combo = {}; this.items = [{ layout: 'column', border: false, defaults: { labelWidth: this.labelWidth }, items: [{ columnWidth: 0.33, layout: 'form', border: false, items: this.createLocationComboBox('country', ['region', 'city']) }, { columnWidth: 0.33, layout: 'form', border: false, items: this.createLocationComboBox('region', ['city']) }, { columnWidth: 0.33, layout: 'form', border: false, items: this.createLocationComboBox('city') }] }]; Ext.ux.LocationSelect.superclass.initComponent.call(this); } }); Ext.reg('locationselect', Ext.ux.LocationSelect);