From: <fxp...@us...> - 2011-10-14 15:52:10
|
Revision: 8281 http://geonetwork.svn.sourceforge.net/geonetwork/?rev=8281&view=rev Author: fxprunayre Date: 2011-10-14 15:52:02 +0000 (Fri, 14 Oct 2011) Log Message: ----------- Add multi select combo for simple combo box field or autocompletion fields. #630 Remove unused BoxSelect Ext.ux. Minor layout improvements. Modified Paths: -------------- trunk/web-client/pom.xml trunk/web-client/src/main/resources/apps/css/gnmetadatadefault.css trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/opensearch-suggestion.html trunk/web-client/src/main/resources/apps/js/GeoNetwork/lib/GeoNetwork/util/INSPIRESearchFormTools.js trunk/web-client/src/main/resources/apps/js/GeoNetwork/lib/GeoNetwork/util/SearchFormTools.js trunk/web-client/src/main/resources/apps/search/index.html trunk/web-client/src/main/resources/apps/search/index_debug.html trunk/web-client/src/main/resources/apps/search/js/App.js Added Paths: ----------- trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/search-combo-multi.html trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/search-combo-multi.js trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/ trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/SuperBoxSelect.js trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/clear.png trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/close.png trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/expand.png trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/superboxselect.css Removed Paths: ------------- trunk/web-client/src/main/resources/apps/js/ext-ux/BoxSelect/ Modified: trunk/web-client/pom.xml =================================================================== --- trunk/web-client/pom.xml 2011-10-14 12:50:27 UTC (rev 8280) +++ trunk/web-client/pom.xml 2011-10-14 15:52:02 UTC (rev 8281) @@ -100,8 +100,8 @@ <include>${project.build.directory}/classes/apps/js/ext-ux/MultiselectItemSelector-3.0/DDView.js</include> <include>${project.build.directory}/classes/apps/js/ext-ux/MultiselectItemSelector-3.0/Multiselect.js</include> <include>${project.build.directory}/classes/apps/js/ext-ux/LightBox/lightbox.js</include> + <include>${project.build.directory}/classes/apps/js/ext-ux/SuperBoxSelect/SuperBoxSelect.js</include> - <include>${project.build.directory}/classes/apps/js/proj4js-compressed.js</include> @@ -283,6 +283,7 @@ <include>${project.build.directory}/classes/apps/js/GeoNetwork/lib/GeoNetwork/util/SearchTools.js</include> <include>${project.build.directory}/classes/apps/js/GeoNetwork/lib/GeoNetwork/util/Old.js</include> + <include>${project.build.directory}/classes/apps/js/GeoNetwork/lib/GeoNetwork/util/INSPIRESearchFormTools.js</include> <include>${project.build.directory}/classes/apps/js/GeoNetwork/lib/GeoNetwork/util/SearchFormTools.js</include> <include>${project.build.directory}/classes/apps/js/GeoNetwork/lib/GeoNetwork/util/CSWSearchTools.js</include> Modified: trunk/web-client/src/main/resources/apps/css/gnmetadatadefault.css =================================================================== --- trunk/web-client/src/main/resources/apps/css/gnmetadatadefault.css 2011-10-14 12:50:27 UTC (rev 8280) +++ trunk/web-client/src/main/resources/apps/css/gnmetadatadefault.css 2011-10-14 15:52:02 UTC (rev 8281) @@ -129,7 +129,7 @@ clear : both; } .metadata * div.el label { - margin-right: 2px; + margin-right: 5px; } .metadata * label { color : #767676; @@ -250,6 +250,7 @@ } .metadata * table.gn > tbody > tr > td.col { padding : 0px; + width: 50%; } .metadata * table.gn > tbody > tr > td.main, Modified: trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/opensearch-suggestion.html =================================================================== --- trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/opensearch-suggestion.html 2011-10-14 12:50:27 UTC (rev 8280) +++ trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/opensearch-suggestion.html 2011-10-14 15:52:02 UTC (rev 8281) @@ -7,7 +7,6 @@ <script type="text/javascript" src="../../ext/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../../ext/ext-all-debug.js"></script> - <script type="text/javascript" src="../../ext-ux/BoxSelect/Ext.ux.BoxSelect.js"></script> <script type="text/javascript" src="../../OpenLayers/lib/OpenLayers.js"></script> <script type="text/javascript" src="../../GeoExt/script/GeoExt.js"></script> <script type="text/javascript" src="../lib/GeoNetwork.js"></script> Added: trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/search-combo-multi.html =================================================================== --- trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/search-combo-multi.html (rev 0) +++ trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/search-combo-multi.html 2011-10-14 15:52:02 UTC (rev 8281) @@ -0,0 +1,26 @@ +<!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><title>Search form</title> + <link rel="stylesheet" type="text/css" href="../../ext/resources/css/ext-all.css" /> + <link rel="stylesheet" type="text/css" href="../../ext-ux/SuperBoxSelect/superboxselect.css" /> + <link rel="stylesheet" type="text/css" href="../resources/css/metadata-view.css" /> + + <script type="text/javascript" src="../../ext/adapter/ext/ext-base.js"></script> + <script type="text/javascript" src="../../ext/ext-all-debug.js"></script> + <script type="text/javascript" src="../../OpenLayers/lib/OpenLayers.js"></script> + <script type="text/javascript" src="../../ext-ux/SuperBoxSelect/SuperBoxSelect.js"></script> + <script type="text/javascript" src="../../GeoExt/script/GeoExt.js"></script> + <script type="text/javascript" src="../lib/GeoNetwork.js"></script> + <script type="text/javascript" src="example.js"></script> + <script type="text/javascript" src="search-combo-multi.js"></script> + </head> + <body> + <h1>Search form fields with multi selection combo</h1> + <p>This example shows how to build a search form for a GeoNetwork catalogue with multi selection combo box.</p> + <div id="search-form" style="float:left;"></div> + + <div style="width:70%;float:right;"> + <div id="metadata-view-full" class="md-view"></div> + </div> + </body> +</html> \ No newline at end of file Added: trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/search-combo-multi.js =================================================================== --- trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/search-combo-multi.js (rev 0) +++ trunk/web-client/src/main/resources/apps/js/GeoNetwork/examples/search-combo-multi.js 2011-10-14 15:52:02 UTC (rev 8281) @@ -0,0 +1,76 @@ +var searchForm; +var metadataStore; +var catalogue; + +Ext.onReady(function(){ + catalogue = new GeoNetwork.Catalogue({ + servlet: GeoNetwork.URL + }); + + catalogue.metadataStore = GeoNetwork.data.MetadataResultsStore(); + + new GeoNetwork.MetadataResultsView({ + tpl: GeoNetwork.Templates.FULL, + renderTo: 'metadata-view-full', + catalogue: catalogue + }); + + // Load store for the combo + var store = GeoNetwork.data.CategoryStore(catalogue.services.getCategories); + store.load(); + + // Optional template + var imgUrl = '../../../images/default/category/'; + var tpl = (imgUrl ? + '<tpl for="."><div class="x-combo-list-item"><img src="' + imgUrl + '{name}.png"/>{[values.label.' + OpenLayers.Lang.getCode() + ']}</div></tpl>': + '<tpl for="."><div class="x-combo-list-item">{[values.label.' + OpenLayers.Lang.getCode() + ']}</div></tpl>'); + var displaytpl = (imgUrl ? + '<img src="' + imgUrl + '{name}.png"/>{[values.label.' + OpenLayers.Lang.getCode() + ']}': + '{[values.label.' + OpenLayers.Lang.getCode() + ']}'); + + + var multiCb = new Ext.ux.form.SuperBoxSelect ({ + name: 'E_category', + mode: 'local', + fieldLabel: OpenLayers.i18n('category'), + triggerAction: 'all', + store: store, + stackItems: true, + valueField: 'name', + valueDelimiter: ' or ', + displayField: 'name', + tpl: tpl, + displayFieldTpl: displaytpl + }); + searchForm = new Ext.FormPanel({ + border: false, + id: 'searchForm', + renderTo: 'search-form', + width: 350, + defaults: { + width: 230 + }, + defaultType: 'textfield', + items: multiCb, + buttons: [{ + text: 'Search', + id: 'searchBt', + iconCls: 'md-mn md-mn-find', + iconAlign: 'right', + listeners: { + click: function(){ + catalogue.search('searchForm', null, null); + } + } + }] + }); + + // Launch search when enter key press + var map = new Ext.KeyMap("searchForm", [{ + key: [10, 13], + fn: function(){ + Ext.getCmp('searchBt').fireEvent('click'); + } + }]); +}); + Modified: trunk/web-client/src/main/resources/apps/js/GeoNetwork/lib/GeoNetwork/util/INSPIRESearchFormTools.js =================================================================== --- trunk/web-client/src/main/resources/apps/js/GeoNetwork/lib/GeoNetwork/util/INSPIRESearchFormTools.js 2011-10-14 12:50:27 UTC (rev 8280) +++ trunk/web-client/src/main/resources/apps/js/GeoNetwork/lib/GeoNetwork/util/INSPIRESearchFormTools.js 2011-10-14 15:52:02 UTC (rev 8281) @@ -36,24 +36,32 @@ * :return: Annex I, II, III combo box * */ - getAnnexField : function () { - var annexes = [ [ 'i', 'I' ], [ 'ii', 'II' ], [ 'iii', 'III' ] ], inspireannex = new Ext.form.ComboBox({ - id : 'inspireannex', - name : 'E_inspireannex', - mode : 'local', - triggerAction : 'all', - fieldLabel : OpenLayers.i18n('inspireannex'), - // value: annexes[1], // Set arbitrarily the second value of the - // array as the default one. - store : new Ext.data.ArrayStore({ - id : 0, - fields : [ 'id', 'label' ], - data : annexes - }), - valueField : 'id', - displayField : 'label' - }); - return inspireannex; + getAnnexField : function (multi) { + var annexes = [ [ 'i', 'I' ], [ 'ii', 'II' ], [ 'iii', 'III' ] ], + config = { + id : 'inspireannex', + name : 'E_inspireannex', + mode : 'local', + triggerAction : 'all', + fieldLabel : OpenLayers.i18n('inspireannex'), + // value: annexes[1], // Set arbitrarily the second value of the + // array as the default one. + store : new Ext.data.ArrayStore({ + id : 0, + fields : [ 'id', 'label' ], + data : annexes + }), + valueField : 'id', + displayField : 'label' + }; + if (multi) { + Ext.apply(config, { + valueDelimiter: ' or ' + }); + return new Ext.ux.form.SuperBoxSelect(config); + } else { + return new Ext.form.ComboBox(config); + } }, /** api:method[getRelatedField] * :return: Checkbox for dataset related to @@ -93,7 +101,7 @@ * * TODO : Improve support of multilingual search for INSPIRE themes */ - getThemesField : function (services) { + getThemesField : function (services, multi) { var Keyword, themesStore, inspiretheme; Keyword = Ext.data.Record.create([ { @@ -131,28 +139,34 @@ }); themesStore.load(); - - inspiretheme = new Ext.form.ComboBox({ - id : 'inspiretheme', - name : 'E_inspiretheme', - mode : 'local', - triggerAction : 'all', - fieldLabel : OpenLayers.i18n('inspiretheme'), - store : themesStore, - valueField : 'value', - displayField : 'value' - }); - - return inspiretheme; + var config = { + id : 'inspiretheme', + name : 'E_inspiretheme', + mode : 'local', + triggerAction : 'all', + fieldLabel : OpenLayers.i18n('inspiretheme'), + store : themesStore, + valueField : 'value', + displayField : 'value' + }; + if (multi) { + Ext.apply(config, { + valueDelimiter: ' or ', + stackItems: true + }); + return new Ext.ux.form.SuperBoxSelect(config); + } else { + return new Ext.form.ComboBox(config); + } }, /** api:method[getINSPIREFields] * :return: An INSPIRE form * * Create an INSPIRE form */ - getINSPIREFields : function (services) { - return [this.getAnnexField(), - this.getThemesField(services), + getINSPIREFields : function (services, multi) { + return [this.getAnnexField(multi), + this.getThemesField(services, multi), this.getRelatedField()]; } }; Modified: trunk/web-client/src/main/resources/apps/js/GeoNetwork/lib/GeoNetwork/util/SearchFormTools.js =================================================================== --- trunk/web-client/src/main/resources/apps/js/GeoNetwork/lib/GeoNetwork/util/SearchFormTools.js 2011-10-14 12:50:27 UTC (rev 8280) +++ trunk/web-client/src/main/resources/apps/js/GeoNetwork/lib/GeoNetwork/util/SearchFormTools.js 2011-10-14 15:52:02 UTC (rev 8281) @@ -67,7 +67,7 @@ } if (withTypes) { - fields.push(GeoNetwork.util.SearchFormTools.getTypesField(typeCodelist)); + fields.push(GeoNetwork.util.SearchFormTools.getTypesField(typeCodelist, true)); } if (layers) { @@ -205,7 +205,7 @@ var catalogueField = GeoNetwork.util.SearchFormTools.getCatalogueField(services.getSources, services.logoUrl); var groupField = GeoNetwork.util.SearchFormTools.getGroupField(services.getGroups); var metadataTypeField = GeoNetwork.util.SearchFormTools.getMetadataTypeField(); - var categoryField = GeoNetwork.util.SearchFormTools.getCategoryField(services.getCategories); + var categoryField = GeoNetwork.util.SearchFormTools.getCategoryField(services.getCategories, null, true); var options = GeoNetwork.util.SearchFormTools.getOptions(); @@ -398,68 +398,90 @@ /** api:method[getCatalogueField] * :return: * - * Create catalogue combo - * DataView - * TODO : list from server + * Create a combo for catalogue field */ - getCatalogueField: function(url, logoUrl){ - // TODO : make multiple selection - - var catStore = GeoNetwork.data.CatalogueSourceStore(url); + getCatalogueField: function(url, logoUrl, multi){ + var catStore = GeoNetwork.data.CatalogueSourceStore(url), + tpl = '<tpl for="."><div class="x-combo-list-item logo"><img src="' + logoUrl + '{id}.gif"/>{name}</div></tpl>'; catStore.load(); - return new Ext.form.ComboBox({ - name: 'E_siteId', - mode: 'local', - triggerAction: 'all', - fieldLabel: OpenLayers.i18n('catalogue'), - store: catStore, - valueField: 'id', - displayField: 'name', - tpl: '<tpl for="."><div class="x-combo-list-item logo"><img src="' + logoUrl + '{id}.gif"/>{name}</div></tpl>' - }); + var config = { + name: 'E_siteId', + mode: 'local', + triggerAction: 'all', + fieldLabel: OpenLayers.i18n('catalogue'), + store: catStore, + valueField: 'id', + displayField: 'name', + tpl: tpl + }; + + if (multi) { + Ext.apply(config, { + valueDelimiter: ' or ', + stackItems: true, + displayFieldTpl: '<img style="max-width:16px;" src="' + logoUrl + '{id}.gif"/>{name}'}); + return new Ext.ux.form.SuperBoxSelect(config); + } else { + return new Ext.form.ComboBox(config); + } }, /** api:method[getGroupField] * :return: A group combo * - * Create a list of group - * - * TODO : list from server + * Create a combo for group field */ - getGroupField: function(url){ - var groupStore = GeoNetwork.data.GroupStore(url); + getGroupField: function(url, multi){ + var groupStore = GeoNetwork.data.GroupStore(url), + tpl = '<tpl for="."><div class="x-combo-list-item">{[values.label.' + OpenLayers.Lang.getCode() + ']}</div></tpl>'; groupStore.load(); - - return new Ext.form.ComboBox({ - name: 'E_group', - mode: 'local', - triggerAction: 'all', - fieldLabel: OpenLayers.i18n('group'), - store: groupStore, - valueField: 'id', - displayField: 'name', - tpl: '<tpl for="."><div class="x-combo-list-item">{[values.label.' + OpenLayers.Lang.getCode() + ']}</div></tpl>' - }); + var config = { + name: 'E_group', + mode: 'local', + triggerAction: 'all', + fieldLabel: OpenLayers.i18n('group'), + store: groupStore, + valueField: 'id', + displayField: 'name', + tpl: tpl + }; + if (multi) { + Ext.apply(config, { + valueDelimiter: ' or ', + stackItems: true, + displayFieldTpl: '{[values.label.' + OpenLayers.Lang.getCode() + ']}'}); + return new Ext.ux.form.SuperBoxSelect(config); + } else { + return new Ext.form.ComboBox(config); + } }, /** api:method[getMetadataTypeField] * :return: A metadata type combo * * Create a combo with template or metadata options */ - getMetadataTypeField: function(){ - return new Ext.form.ComboBox({ - name: 'E_template', - mode: 'local', - triggerAction: 'all', - fieldLabel: OpenLayers.i18n('kind'), - store: new Ext.data.ArrayStore({ - id: 0, - fields: ['id', 'name'], - data: [['n', OpenLayers.i18n('md')], ['y', OpenLayers.i18n('tpl')]] - }), - valueField: 'id', - displayField: 'name' - }); + getMetadataTypeField: function(multi){ + var config = { + name: 'E_template', + mode: 'local', + triggerAction: 'all', + fieldLabel: OpenLayers.i18n('kind'), + store: new Ext.data.ArrayStore({ + id: 0, + fields: ['id', 'name'], + data: [['n', OpenLayers.i18n('md')], ['y', OpenLayers.i18n('tpl')]] + }), + valueField: 'id', + displayField: 'name' + }; + if (multi) { + Ext.apply(config, { + valueDelimiter: ' or ' + }); + return new Ext.ux.form.SuperBoxSelect(config); + } else { + return new Ext.form.ComboBox(config); + } }, /** api:method[getCategoryField] * :return: A category combobox @@ -468,12 +490,16 @@ * * TODO : retrieve from server */ - getCategoryField: function(url, imgUrl){ + getCategoryField: function(url, imgUrl, multi){ var store = GeoNetwork.data.CategoryStore(url); store.load(); - return new Ext.form.ComboBox({ + var tpl = (imgUrl ? + '<tpl for="."><div class="x-combo-list-item"><img src="' + imgUrl + '{name}.png"/>{[values.label.' + OpenLayers.Lang.getCode() + ']}</div></tpl>': + '<tpl for="."><div class="x-combo-list-item">{[values.label.' + OpenLayers.Lang.getCode() + ']}</div></tpl>'); + + var config = { name: 'E_category', mode: 'local', fieldLabel: OpenLayers.i18n('category'), @@ -481,10 +507,20 @@ store: store, valueField: 'name', displayField: 'name', - tpl: (imgUrl ? - '<tpl for="."><div class="x-combo-list-item"><img src="' + imgUrl + '{name}.png"/>{[values.label.' + OpenLayers.Lang.getCode() + ']}</div></tpl>': - '<tpl for="."><div class="x-combo-list-item">{[values.label.' + OpenLayers.Lang.getCode() + ']}</div></tpl>') - }); + tpl: tpl + }; + if (multi) { + var displaytpl = (imgUrl ? + '<img src="' + imgUrl + '{name}.png"/>{[values.label.' + OpenLayers.Lang.getCode() + ']}': + '{[values.label.' + OpenLayers.Lang.getCode() + ']}'); + Ext.apply(config, { + valueDelimiter: ' or ', + stackItems: true, + displayFieldTpl: displaytpl}); + return new Ext.ux.form.SuperBoxSelect (config); + } else { + return new Ext.form.ComboBox(config); + } }, /** api:method[getAdvancedTextFields] * :return: A fieldset with advanced text search @@ -803,7 +839,7 @@ * */ getMapTypesField: function(){ - var spatialTypes = GeoNetwork.util.SearchFormTools.getSpatialRepresentationTypeField(); + var spatialTypes = GeoNetwork.util.SearchFormTools.getSpatialRepresentationTypeField(null, true); return [{ hideLabel: true, @@ -828,51 +864,63 @@ * :return: Validation status field * */ - getValidField: function(){ - var metadataType = new Ext.form.ComboBox({ - name: 'E__valid', - mode: 'local', - autoSelect: false, - triggerAction: 'all', - fieldLabel: OpenLayers.i18n('validationStatus'), - store: new Ext.data.ArrayStore({ - id: 0, - fields: ['id', 'name'], - data: [['1', OpenLayers.i18n('valid')], - ['0', OpenLayers.i18n('notValid')], - ['-1', OpenLayers.i18n('notDetermined')]] - }), - valueField: 'id', - displayField: 'name' - }); - return metadataType; - + getValidField: function(multi){ + var config = { + name: 'E__valid', + mode: 'local', + autoSelect: false, + triggerAction: 'all', + fieldLabel: OpenLayers.i18n('validationStatus'), + store: new Ext.data.ArrayStore({ + id: 0, + fields: ['id', 'name'], + data: [['1', OpenLayers.i18n('valid')], + ['0', OpenLayers.i18n('notValid')], + ['-1', OpenLayers.i18n('notDetermined')]] + }), + valueField: 'id', + displayField: 'name' + }; + if (multi) { + Ext.apply(config, { + valueDelimiter: ' or ' + }); + return new Ext.ux.form.SuperBoxSelect(config); + } else { + return new Ext.form.ComboBox(config); + } }, /** api:method[getTypesField] * :return: Type selection using combo box based * on hierarchy level values. */ - getTypesField: function(codeList){ + getTypesField: function(codeList, multi){ var defaultCodeList = [['dataset', OpenLayers.i18n('dataset')], ['series', OpenLayers.i18n('series')], - ['service', OpenLayers.i18n('service')]]; + ['service', OpenLayers.i18n('service')]], + config = { + name: 'E_type', + mode: 'local', + autoSelect: false, + triggerAction: 'all', + fieldLabel: OpenLayers.i18n('resourceType'), + store: new Ext.data.ArrayStore({ + id: 0, + fields: ['id', 'name'], + data: codeList || defaultCodeList + }), + valueField: 'id', + displayField: 'name' + }; - var metadataType = new Ext.form.ComboBox({ - name: 'E_type', - mode: 'local', - autoSelect: false, - triggerAction: 'all', - fieldLabel: OpenLayers.i18n('resourceType'), - store: new Ext.data.ArrayStore({ - id: 0, - fields: ['id', 'name'], - data: codeList || defaultCodeList - }), - valueField: 'id', - displayField: 'name' - }); - return metadataType; - + if (multi) { + Ext.apply(config, { + valueDelimiter: ' or ' + }); + return new Ext.ux.form.SuperBoxSelect(config); + } else { + return new Ext.form.ComboBox(config); + } }, /** api:method[getSpatialRepresentationTypeField] * :param codeList: ``Array`` of values @@ -882,30 +930,35 @@ * gmd:spatialRepresentationType/gmd:MD_SpatialRepresentationTypeCode/@codeListValue * ISO19115 codelist. Applying such a filter will not return non ISO records. */ - getSpatialRepresentationTypeField: function(codeList){ + getSpatialRepresentationTypeField: function(codeList, multi){ var defaultCodeList = [['grid', OpenLayers.i18n('grid')], ['stereoModel', OpenLayers.i18n('stereoModel')], ['tin', OpenLayers.i18n('tin')], ['textTabled', OpenLayers.i18n('textTable')], ['vector', OpenLayers.i18n('vector')], - ['video', OpenLayers.i18n('video')]]; + ['video', OpenLayers.i18n('video')]], + config = { + name: 'E_spatialRepresentationType', + mode: 'local', + autoSelect: false, + triggerAction: 'all', + fieldLabel: OpenLayers.i18n('spatialRepType'), + store: new Ext.data.ArrayStore({ + id: 0, + fields: ['id', 'name'], + data: codeList || defaultCodeList + }), + valueField: 'id', + displayField: 'name' + }; - var spatialRepresentationType = new Ext.form.ComboBox({ - name: 'E_spatialRepresentationType', - mode: 'local', - autoSelect: false, - triggerAction: 'all', - fieldLabel: OpenLayers.i18n('spatialRepType'), - store: new Ext.data.ArrayStore({ - id: 0, - fields: ['id', 'name'], - data: codeList || defaultCodeList - }), - valueField: 'id', - displayField: 'name' - }); - - return spatialRepresentationType; - + if (multi) { + Ext.apply(config, { + valueDelimiter: ' or ' + }); + return new Ext.ux.form.SuperBoxSelect(config); + } else { + return new Ext.form.ComboBox(config); + } } }; Added: trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/SuperBoxSelect.js =================================================================== --- trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/SuperBoxSelect.js (rev 0) +++ trunk/web-client/src/main/resources/apps/js/ext-ux/SuperBoxSelect/SuperBoxSelect.js 2011-10-14 15:52:02 UTC (rev 8281) @@ -0,0 +1,1889 @@ +Ext.namespace('Ext.ux.form'); +/** + * <p>SuperBoxSelect is an extension of the ComboBox component that displays selected items as labelled boxes within the form field. As seen on facebook, hotmail and other sites.</p> + * + * @author <a href="mailto:dan...@te...">Dan Humphrey</a> + * @class Ext.ux.form.SuperBoxSelect + * @extends Ext.form.ComboBox + * @constructor + * @component + * @version 1.0 + * @license TBA (To be announced) + * + */ +Ext.ux.form.SuperBoxSelect = function(config) { + Ext.ux.form.SuperBoxSelect.superclass.constructor.call(this,config); + this.addEvents( + /** + * Fires before an item is added to the component via user interaction. Return false from the callback function to prevent the item from being added. + * @event beforeadditem + * @memberOf Ext.ux.form.SuperBoxSelect + * @param {SuperBoxSelect} this + * @param {Mixed} value The value of the item to be added + * @param {Record} rec The record being added + * @param {Mixed} filtered Any filtered query data (if using queryFilterRe) + */ + 'beforeadditem', + + /** + * Fires after a new item is added to the component. + * @event additem + * @memberOf Ext.ux.form.SuperBoxSelect + * @param {SuperBoxSelect} this + * @param {Mixed} value The value of the item which was added + * @param {Record} record The store record which was added + */ + 'additem', + + /** + * Fires when the allowAddNewData config is set to true, and a user attempts to add an item that is not in the data store. + * @event newitem + * @memberOf Ext.ux.form.SuperBoxSelect + * @param {SuperBoxSelect} this + * @param {Mixed} value The new item's value + * @param {Mixed} filtered Any filtered query data (if using queryFilterRe) + */ + 'newitem', + + /** + * Fires when an item's remove button is clicked. Return false from the callback function to prevent the item from being removed. + * @event beforeremoveitem + * @memberOf Ext.ux.form.SuperBoxSelect + * @param {SuperBoxSelect} this + * @param {Mixed} value The value of the item to be removed + */ + 'beforeremoveitem', + + /** + * Fires after an item has been removed. + * @event removeitem + * @memberOf Ext.ux.form.SuperBoxSelect + * @param {SuperBoxSelect} this + * @param {Mixed} value The value of the item which was removed + * @param {Record} record The store record which was removed + */ + 'removeitem', + /** + * Fires after the component values have been cleared. + * @event clear + * @memberOf Ext.ux.form.SuperBoxSelect + * @param {SuperBoxSelect} this + */ + 'clear' + ); + +}; +/** + * @private hide from doc gen + */ +Ext.ux.form.SuperBoxSelect = Ext.extend(Ext.ux.form.SuperBoxSelect,Ext.form.ComboBox,{ + /** + * @cfg {Boolean} addNewDataOnBlur Allows adding new items when the user tabs from the input element. + */ + addNewDataOnBlur : false, + /** + * @cfg {Boolean} allowAddNewData When set to true, allows items to be added (via the setValueEx and addItem methods) that do not already exist in the data store. Defaults to false. + */ + allowAddNewData: false, + /** + * @cfg {Boolean} allowQueryAll When set to false, prevents the trigger arrow from rendering, and the DOWN key from triggering a query all. Defaults to true. + */ + allowQueryAll : true, + /** + * @cfg {Boolean} backspaceDeletesLastItem When set to false, the BACKSPACE key will focus the last selected item. When set to true, the last item will be immediately deleted. Defaults to true. + */ + backspaceDeletesLastItem: true, + /** + * @cfg {String} classField The underlying data field that will be used to supply an additional class to each item. + */ + classField: null, + + /** + * @cfg {String} clearBtnCls An additional class to add to the in-field clear button. + */ + clearBtnCls: '', + /** + * @cfg {Boolean} clearLastQueryOnEscape When set to true, the escape key will clear the lastQuery, enabling the previous query to be repeated. + */ + clearLastQueryOnEscape : false, + /** + * @cfg {Boolean} clearOnEscape When set to true, the escape key will clear the input text when the component is not expanded. + */ + clearOnEscape : false, + + /** + * @cfg {String/XTemplate} displayFieldTpl A template for rendering the displayField in each selected item. Defaults to null. + */ + displayFieldTpl: null, + + /** + * @cfg {String} extraItemCls An additional css class to apply to each item. + */ + extraItemCls: '', + + /** + * @cfg {String/Object/Function} extraItemStyle Additional css style(s) to apply to each item. Should be a valid argument to Ext.Element.applyStyles. + */ + extraItemStyle: '', + + /** + * @cfg {String} expandBtnCls An additional class to add to the in-field expand button. + */ + expandBtnCls: '', + + /** + * @cfg {Boolean} fixFocusOnTabSelect When set to true, the component will not lose focus when a list item is selected with the TAB key. Defaults to true. + */ + fixFocusOnTabSelect: true, + /** + * @cfg {Boolean} forceFormValue When set to true, the component will always return a value to the parent form getValues method, and when the parent form is submitted manually. Defaults to false, meaning the component will only be included in the parent form submission (or getValues) if at least 1 item has been selected. + */ + forceFormValue: true, + /** + * @cfg {Boolean} forceSameValueQuery When set to true, the component will always query the server even when the last query was the same. Defaults to false. + */ + forceSameValueQuery : false, + /** + * @cfg {Number} itemDelimiterKey A key code which terminates keying in of individual items, and adds the current + * item to the list. Defaults to the ENTER key. + */ + itemDelimiterKey: Ext.EventObject.ENTER, + /** + * @cfg {Boolean} navigateItemsWithTab When set to true the tab key will navigate between selected items. Defaults to true. + */ + navigateItemsWithTab: true, + /** + * @cfg {Boolean} pinList When set to true and the list is opened via the arrow button, the select list will be pinned to allow for multiple selections. Defaults to true. + */ + pinList: true, + + /** + * @cfg {Boolean} preventDuplicates When set to true unique item values will be enforced. Defaults to true. + */ + preventDuplicates: true, + /** + * @cfg {String|Regex} queryFilterRe Used to filter input values before querying the server, specifically useful when allowAddNewData is true as the filtered portion of the query will be passed to the newItem callback. + */ + queryFilterRe: '', + /** + * @cfg {String} queryValuesDelimiter Used to delimit multiple values queried from the server when mode is remote. + */ + queryValuesDelimiter: '|', + + /** + * @cfg {String} queryValuesIndicator A request variable that is sent to the server (as true) to indicate that we are querying values rather than display data (as used in autocomplete) when mode is remote. + */ + queryValuesIndicator: 'valuesqry', + + /** + * @cfg {Boolean} removeValuesFromStore When set to true, selected records will be removed from the store. Defaults to true. + */ + removeValuesFromStore: true, + + /** + * @cfg {String} renderFieldBtns When set to true, will render in-field buttons for clearing the component, and displaying the list for selection. Defaults to true. + */ + renderFieldBtns: true, + + /** + * @cfg {Boolean} stackItems When set to true, the items will be stacked 1 per line. Defaults to false which displays the items inline. + */ + stackItems: false, + + /** + * @cfg {String} styleField The underlying data field that will be used to supply additional css styles to each item. + */ + styleField : null, + + /** + * @cfg {Boolean} supressClearValueRemoveEvents When true, the removeitem event will not be fired for each item when the clearValue method is called, or when the clear button is used. Defaults to false. + */ + supressClearValueRemoveEvents : false, + + /** + * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable automatic validation (defaults to 'blur'). + */ + validationEvent : 'blur', + + /** + * @cfg {String} valueDelimiter The delimiter to use when joining and splitting value arrays and strings. + */ + valueDelimiter: ',', + initComponent:function() { + Ext.apply(this, { + items : new Ext.util.MixedCollection(false), + usedRecords : new Ext.util.MixedCollection(false), + addedRecords : [], + remoteLookup : [], + hideTrigger : true, + grow : false, + resizable : false, + multiSelectMode : false, + preRenderValue : null, + filteredQueryData: '' + + }); + if(this.queryFilterRe){ + if(Ext.isString(this.queryFilterRe)){ + this.queryFilterRe = new RegExp(this.queryFilterRe); + } + } + if(this.transform){ + this.doTransform(); + } + if(this.forceFormValue){ + this.items.on({ + add: this.manageNameAttribute, + remove: this.manageNameAttribute, + clear: this.manageNameAttribute, + scope: this + }); + } + + Ext.ux.form.SuperBoxSelect.superclass.initComponent.call(this); + if(this.mode === 'remote' && this.store){ + this.store.on('load', this.onStoreLoad, this); + } + }, + onRender:function(ct, position) { + var h = this.hiddenName; + this.hiddenName = null; + Ext.ux.form.SuperBoxSelect.superclass.onRender.call(this, ct, position); + this.hiddenName = h; + this.manageNameAttribute(); + + var extraClass = (this.stackItems === true) ? 'x-superboxselect-stacked' : ''; + if(this.renderFieldBtns){ + extraClass += ' x-superboxselect-display-btns'; + } + this.el.removeClass('x-form-text').addClass('x-superboxselect-input-field'); + + this.wrapEl = this.el.wrap({ + tag : 'ul' + }); + + this.outerWrapEl = this.wrapEl.wrap({ + tag : 'div', + cls: 'x-form-text x-superboxselect ' + extraClass + }); + + this.inputEl = this.el.wrap({ + tag : 'li', + cls : 'x-superboxselect-input' + }); + + if(this.renderFieldBtns){ + this.setupFieldButtons().manageClearBtn(); + } + + this.setupFormInterception(); + }, + doTransform : function() { + var s = Ext.getDom(this.transform), transformValues = []; + if(!this.store){ + this.mode = 'local'; + var d = [], opts = s.options; + for(var i = 0, len = opts.length;i < len; i++){ + var o = opts[i], oe = Ext.get(o), + value = oe.getAttributeNS(null,'value') || '', + cls = oe.getAttributeNS(null,'className') || '', + style = oe.getAttributeNS(null,'style') || ''; + if(o.selected) { + transformValues.push(value); + } + d.push([value, o.text, cls, typeof(style) === "string" ? style : style.cssText]); + } + this.store = new Ext.data.SimpleStore({ + 'id': 0, + fields: ['value', 'text', 'cls', 'style'], + data : d + }); + Ext.apply(this,{ + valueField: 'value', + displayField: 'text', + classField: 'cls', + styleField: 'style' + }); + } + + if(transformValues.length){ + this.value = transformValues.join(','); + } + }, + setupFieldButtons : function(){ + this.buttonWrap = this.outerWrapEl.createChild({ + cls: 'x-superboxselect-btns' + }); + + this.buttonClear = this.buttonWrap.createChild({ + tag:'div', + cls: 'x-superboxselect-btn-clear ' + this.clearBtnCls + }); + + if(this.allowQueryAll){ + this.buttonExpand = this.buttonWrap.createChild({ + tag:'div', + cls: 'x-superboxselect-btn-expand ' + this.expandBtnCls + }); + } + + this.initButtonEvents(); + + return this; + }, + initButtonEvents : function() { + this.buttonClear.addClassOnOver('x-superboxselect-btn-over').on('click', function(e) { + e.stopEvent(); + if (this.disabled) { + return; + } + this.clearValue(); + this.el.focus(); + }, this); + + if(this.allowQueryAll){ + this.buttonExpand.addClassOnOver('x-superboxselect-btn-over').on('click', function(e) { + e.stopEvent(); + if (this.disabled) { + return; + } + if (this.isExpanded()) { + this.multiSelectMode = false; + } else if (this.pinList) { + this.multiSelectMode = true; + } + this.onTriggerClick(); + }, this); + } + }, + removeButtonEvents : function() { + this.buttonClear.removeAllListeners(); + if(this.allowQueryAll){ + this.buttonExpand.removeAllListeners(); + } + return this; + }, + clearCurrentFocus : function(){ + if(this.currentFocus){ + this.currentFocus.onLnkBlur(); + this.currentFocus = null; + } + return this; + }, + initEvents : function() { + var el = this.el; + el.on({ + click : this.onClick, + focus : this.clearCurrentFocus, + blur : this.onBlur, + keydown : this.onKeyDownHandler, + keyup : this.onKeyUpBuffered, + scope : this + }); + + this.on({ + collapse: this.onCollapse, + expand: this.clearCurrentFocus, + scope: this + }); + + this.wrapEl.on('click', this.onWrapClick, this); + this.outerWrapEl.on('click', this.onWrapClick, this); + + this.inputEl.focus = function() { + el.focus(); + }; + + Ext.ux.form.SuperBoxSelect.superclass.initEvents.call(this); + + Ext.apply(this.keyNav, { + tab: function(e) { + if (this.fixFocusOnTabSelect && this.isExpanded()) { + e.stopEvent(); + el.blur(); + this.onViewClick(false); + this.focus(false, 10); + return true; + } + + this.onViewClick(false); + if (el.dom.value !== '') { + this.setRawValue(''); + } + + return true; + }, + + down: function(e) { + if (!this.isExpanded() && !this.currentFocus) { + if(this.allowQueryAll){ + this.onTriggerClick(); + } + } else { + this.inKeyMode = true; + this.selectNext(); + } + }, + + enter: function(){} + }); + }, + + onClick: function() { + this.clearCurrentFocus(); + this.collapse(); + this.autoSize(); + }, + + beforeBlur: function(){ + if(this.allowAddNewData && this.addNewDataOnBlur){ + var v = this.el.dom.value; + if(v !== ''){ + this.fireNewItemEvent(v); + } + } + Ext.form.ComboBox.superclass.beforeBlur.call(this); + }, + + onFocus: function() { + this.outerWrapEl.addClass(this.focusClass); + + Ext.ux.form.SuperBoxSelect.superclass.onFocus.call(this); + }, + + onBlur: function() { + this.outerWrapEl.removeClass(this.focusClass); + + this.clearCurrentFocus(); + + if (this.el.dom.value !== '') { + this.applyEmptyText(); + this.autoSize(); + } + + Ext.ux.form.SuperBoxSelect.superclass.onBlur.call(this); + }, + + onCollapse: function() { + this.view.clearSelections(); + this.multiSelectMode = false; + }, + + onWrapClick: function(e) { + e.stopEvent(); + this.collapse(); + this.el.focus(); + this.clearCurrentFocus(); + }, + markInvalid : function(msg) { + var elp, t; + + if (!this.rendered || this.preventMark ) { + return; + } + this.outerWrapEl.addClass(this.invalidClass); + msg = msg || this.invalidText; + + switch (this.msgTarget) { + case 'qtip': + Ext.apply(this.el.dom, { + qtip : msg, + qclass : 'x-form-invalid-tip' + }); + Ext.apply(this.wrapEl.dom, { + qtip : msg, + qclass : 'x-form-invalid-tip' + }); + if (Ext.QuickTips) { // fix for floating editors interacting with DND + Ext.QuickTips.enable(); + } + break; + case 'title': + this.el.dom.title = msg; + this.wrapEl.dom.title = msg; + this.outerWrapEl.dom.title = msg; + break; + case 'under': + if (!this.errorEl) { + elp = this.getErrorCt(); + if (!elp) { // field has no container el + this.el.dom.title = msg; + break; + } + this.errorEl = elp.createChild({cls:'x-form-invalid-msg'}); + this.errorEl.setWidth(elp.getWidth(true) - 20); + } + this.errorEl.update(msg); + Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this); + break; + case 'side': + if (!this.errorIcon) { + elp = this.getErrorCt(); + if (!elp) { // field has no container el + this.el.dom.title = msg; + break; + } + this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'}); + } + this.alignErrorIcon(); + Ext.apply(this.errorIcon.dom, { + qtip : msg, + qclass : 'x-form-invalid-tip' + }); + this.errorIcon.show(); + this.on('resize', this.alignErrorIcon, this); + break; + default: + t = Ext.getDom(this.msgTarget); + t.innerHTML = msg; + t.style.display = this.msgDisplay; + break; + } + this.fireEvent('invalid', this, msg); + }, + clearInvalid : function(){ + if(!this.rendered || this.preventMark){ // not rendered + return; + } + this.outerWrapEl.removeClass(this.invalidClass); + switch(this.msgTarget){ + case 'qtip': + this.el.dom.qtip = ''; + this.wrapEl.dom.qtip =''; + break; + case 'title': + this.el.dom.title = ''; + this.wrapEl.dom.title = ''; + this.outerWrapEl.dom.title = ''; + break; + case 'under': + if(this.errorEl){ + Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this); + } + break; + case 'side': + if(this.errorIcon){ + this.errorIcon.dom.qtip = ''; + this.errorIcon.hide(); + this.un('resize', this.alignErrorIcon, this); + } + break; + default: + var t = Ext.getDom(this.msgTarget); + t.innerHTML = ''; + t.style.display = 'none'; + break; + } + this.fireEvent('valid', this); + }, + alignErrorIcon : function(){ + if(this.wrap){ + this.errorIcon.alignTo(this.wrap, 'tl-tr', [Ext.isIE ? 5 : 2, 3]); + } + }, + expand : function(){ + if (this.isExpanded() || !this.hasFocus) { + return; + } + if(this.bufferSize){ + this.doResize(this.bufferSize); + delete this.bufferSize; + } + this.list.alignTo(this.outerWrapEl, this.listAlign).show(); + this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac + this.mon(Ext.getDoc(), { + scope: this, + mousewheel: this.collapseIf, + mousedown: this.collapseIf + }); + this.fireEvent('expand', this); + }, + restrictHeight : function(){ + var inner = this.innerList.dom, + st = inner.scrollTop, + list = this.list; + + inner.style.height = ''; + + var pad = list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight, + h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight), + ha = this.getPosition()[1]-Ext.getBody().getScroll().top, + hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height, + space = Math.max(ha, hb, this.minHeight || 0)-list.shadowOffset-pad-5; + + h = Math.min(h, space, this.maxHeight); + this.innerList.setHeight(h); + + list.beginUpdate(); + list.setHeight(h+pad); + list.alignTo(this.outerWrapEl, this.listAlign); + list.endUpdate(); + + if(this.multiSelectMode){ + inner.scrollTop = st; + } + }, + validateValue: function(val){ + if(this.items.getCount() === 0){ + if(this.allowBlank){ + this.clearInvalid(); + return true; + }else{ + this.markInvalid(this.blankText); + return false; + } + } + this.clearInvalid(); + return true; + }, + manageNameAttribute : function(){ + if(this.items.getCount() === 0 && this.forceFormValue){ + this.el.dom.setAttribute('name', this.hiddenName || this.name); + }else{ + this.el.dom.removeAttribute('name'); + } + }, + setupFormInterception : function(){ + var form; + this.findParentBy(function(p){ + if(p.getForm){ + form = p.getForm(); + } + }); + if(form){ + var formGet = form.getValues; + form.getValues = function(asString){ + this.el.dom.disabled = true; + var oldVal = this.el.dom.value; + this.setRawValue(''); + var vals = formGet.call(form); + this.el.dom.disabled = false; + this.setRawValue(oldVal); + if(this.forceFormValue && this.items.getCount() === 0){ + vals[this.name] = ''; + } + return asString ? Ext.urlEncode(vals) : vals ; + }.createDelegate(this); + } + }, + onResize : function(w, h, rw, rh) { + var reduce = Ext.isIE6 ? 4 : Ext.isIE7 ? 1 : Ext.isIE8 ? 1 : 0; + if(this.wrapEl){ + this._width = w; + this.outerWrapEl.setWidth(w - reduce); + if (this.renderFieldBtns) { + reduce += (this.buttonWrap.getWidth() + 20); + this.wrapEl.setWidth(w - reduce); + } + } + Ext.ux.form.SuperBoxSelect.superclass.onResize.call(this, w, h, rw, rh); + this.autoSize(); + }, + onEnable: function(){ + Ext.ux.form.SuperBoxSelect.superclass.onEnable.call(this); + this.items.each(function(item){ + item.enable(); + }); + if (this.renderFieldBtns) { + this.initButtonEvents(); + } + }, + onDisable: function(){ + Ext.ux.form.SuperBoxSelect.superclass.onDisable.call(this); + this.items.each(function(item){ + item.disable(); + }); + if(this.renderFieldBtns){ + this.removeButtonEvents(); + } + }, + /** + * Clears all values from the component. + * @methodOf Ext.ux.form.SuperBoxSelect + * @name clearValue + * @param {Boolean} supressRemoveEvent [Optional] When true, the 'removeitem' event will not fire for each item that is removed. + */ + clearValue : function(supressRemoveEvent){ + Ext.ux.form.SuperBoxSelect.superclass.clearValue.call(this); + this.preventMultipleRemoveEvents = supressRemoveEvent || this.supressClearValueRemoveEvents || false; + this.removeAllItems(); + this.preventMultipleRemoveEvents = false; + this.fireEvent('clear',this); + return this; + }, + fireNewItemEvent : function(val){ + this.view.clearSelections(); + this.collapse(); + this.setRawValue(''); + if(this.queryFilterRe){ + val = val.replace(this.queryFilterRe, ''); + if(!val){ + return; + } + } + this.fireEvent('newitem', this, val, this.filteredQueryData); + }, + onKeyUp : function(e) { + if (this.editable !== false && (!e.isSpecialKey() || e.getKey() === e.BACKSPACE) && this.itemDelimiterKey.indexOf !== e.getKey() && (!e.hasModifier() || e.shiftKey)) { + this.lastKey = e.getKey(); + this.dqTask.delay(this.queryDelay); + } + }, + onKeyDownHandler : function(e,t) { + + var toDestroy,nextFocus,idx; + + if(e.getKey() === e.ESC){ + if(!this.isExpanded()){ + if(this.el.dom.value != '' && (this.clearOnEscape || this.clearLastQueryOnEscape)){ + if(this.clearOnEscape){ + this.el.dom.value = ''; + } + if(this.clearLastQueryOnEscape){ + this.lastQuery = ''; + } + e.stopEvent(); + } + } + } + if ((e.getKey() === e.DELETE || e.getKey() === e.SPACE) && this.currentFocus){ + e.stopEvent(); + toDestroy = this.currentFocus; + this.on('expand',function(){this.collapse();},this,{single: true}); + idx = this.items.indexOfKey(this.currentFocus.key); + this.clearCurrentFocus(); + + if(idx < (this.items.getCount() -1)){ + nextFocus = this.items.itemAt(idx+1); + } + + toDestroy.preDestroy(true); + if(nextFocus){ + (function(){ + nextFocus.onLnkFocus(); + this.currentFocus = nextFocus; + }).defer(200,this); + } + + return true; + } + + var val = this.el.dom.value, it, ctrl = e.ctrlKey; + + if(this.itemDelimiterKey === e.getKey()){ + e.stopEvent(); + if (val !== "") { + if (ctrl || !this.isExpanded()) { //ctrl+enter for new items + this.fireNewItemEvent(val); + } else { + this.onViewClick(); + //removed from 3.0.1 + if(this.unsetDelayCheck){ + this.delayedCheck = true; + this.unsetDelayCheck.defer(10, this); + } + } + }else{ + if(!this.isExpanded()){ + return; + } + this.onViewClick(); + //removed from 3.0.1 + if(this.unsetDelayCheck){ + this.delayedCheck = true; + this.unsetDelayCheck.defer(10, this); + } + } + return true; + } + + if(val !== '') { + this.autoSize(); + return; + } + + //select first item + if(e.getKey() === e.HOME){ + e.stopEvent(); + if(this.items.getCount() > 0){ + this.collapse(); + it = this.items.get(0); + it.el.focus(); + + } + return true; + } + //backspace remove + if(e.getKey() === e.BACKSPACE){ + e.stopEvent(); + if(this.currentFocus) { + toDestroy = this.currentFocus; + this.on('expand',function(){ + this.collapse(); + },this,{single: true}); + + idx = this.items.indexOfKey(toDestroy.key); + + this.clearCurrentFocus(); + if(idx < (this.items.getCount() -1)){ + nextFocus = this.items.itemAt(idx+1); + } + + toDestroy.preDestroy(true); + + if(nextFocus){ + (function(){ + nextFocus.onLnkFocus(); + this.currentFocus = nextFocus; + }).defer(200,this); + } + + return; + }else{ + it = this.items.get(this.items.getCount() -1); + if(it){ + if(this.backspaceDeletesLastItem){ + this.on('expand',function(){this.collapse();},this,{single: true}); + it.preDestroy(true); + }else{ + if(this.navigateItemsWithTab){ + it.onElClick(); + }else{ + this.on('expand',function(){ + this.collapse(); + this.currentFocus = it; + this.currentFocus.onLnkFocus.defer(20,this.currentFocus); + },this,{single: true}); + } + } + } + return true; + } + } + + if(!e.isNavKeyPress()){ + this.multiSelectMode = false; + this.cle... [truncated message content] |