]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/form/GlobalSearchField.js
2 * This is a global search field
3 * it loads the /cluster/resources on focus
4 * and displays the result in a floating grid
6 * it filters and sorts the objects by the algorithm in
7 * the customFilter function
9 * also it does accept key up/down and enter for input
10 * and it opens to ctrl+shift+f and ctrl+space
12 Ext
.define('PVE.form.GlobalSearchField', {
13 extend
: 'Ext.form.field.Text',
14 alias
: 'widget.pveGlobalSearchField',
16 emptyText
: gettext('Search'),
17 enableKeyEvents
: true,
23 focusOnToFront
: false,
25 emptyText
: Proxmox
.Utils
.noneText
,
34 model
: 'PVEResources',
37 url
: '/api2/extjs/cluster/resources'
41 ptype
: 'bufferedrenderer',
42 trailingBufferZone
: 20,
48 if (typeof me
.ctxMenu
!== 'undefined' && me
.ctxMenu
.isVisible()) {
52 if (!me
.textfield
.hasFocus
) {
57 setFocus: function() {
63 rowclick: function(grid
, record
) {
65 me
.textfield
.selectAndHide(record
.id
);
67 itemcontextmenu: function(v
, record
, item
, index
, event
) {
69 me
.ctxMenu
= PVE
.Utils
.createCmdMenu(v
, record
, item
, index
, event
);
75 focusenter
: 'setFocus'
80 text
: gettext('Type'),
83 renderer
: PVE
.Utils
.render_resource_type
86 text
: gettext('Description'),
91 text
: gettext('Node'),
95 text
: gettext('Pool'),
101 customFilter: function(item
) {
107 // different types of objects have different fields to search
108 // for example, a node will never have a pool and vice versa
109 switch (item
.data
.type
) {
110 case 'pool': fieldArr
= ['type', 'pool', 'text']; break;
111 case 'node': fieldArr
= ['type', 'node', 'text']; break;
112 case 'storage': fieldArr
= ['type', 'pool', 'node', 'storage']; break;
113 default: fieldArr
= ['name', 'type', 'node', 'pool', 'vmid'];
115 if (me
.filterVal
=== '') {
116 item
.data
.relevance
= 0;
120 // all text is case insensitive and each word is
122 // for every partial match, the row gets
123 // 1 match point, for every exact match
126 // results gets sorted by points (descending)
127 fields
= me
.filterVal
.split(/\s+/);
128 for(i
= 0; i
< fieldArr
.length
; i
++) {
129 var v
= item
.data
[fieldArr
[i
]];
130 if (v
!== undefined) {
131 v
= v
.toString().toLowerCase();
132 for(j
= 0; j
< fields
.length
; j
++) {
133 if (v
.indexOf(fields
[j
]) !== -1) {
135 if(v
=== fields
[j
]) {
142 // give the row the 'relevance' value
143 item
.data
.relevance
= match
;
147 updateFilter: function(field
, newValue
, oldValue
) {
149 // parse input and filter store,
151 me
.grid
.store
.filterVal
= newValue
.toLowerCase().trim();
152 me
.grid
.store
.clearFilter(true);
153 me
.grid
.store
.filterBy(me
.customFilter
);
154 me
.grid
.getSelectionModel().select(0);
157 selectAndHide: function(id
) {
159 me
.tree
.selectById(id
);
165 onKey: function(field
, e
) {
167 var key
= e
.getKey();
170 case Ext
.event
.Event
.ENTER
:
171 // go to first entry if there is one
172 if (me
.grid
.store
.getCount() > 0) {
173 me
.selectAndHide(me
.grid
.getSelection()[0].data
.id
);
176 case Ext
.event
.Event
.UP
:
177 me
.grid
.getSelectionModel().selectPrevious();
179 case Ext
.event
.Event
.DOWN
:
180 me
.grid
.getSelectionModel().selectNext();
182 case Ext
.event
.Event
.ESC
:
189 loadValues: function(field
) {
194 me
.grid
.textfield
= me
;
195 me
.grid
.store
.load();
196 me
.grid
.showBy(me
, 'tl-bl');
199 hideGrid: function() {
203 if (!me
.grid
.hasFocus
) {
214 focusenter
: 'loadValues',
221 toggleFocus: function() {
230 initComponent: function() {
234 throw "no tree given";
237 me
.grid
= Ext
.create(me
.grid
);
241 /*jslint confusion: true*/
242 /*because shift is also a function*/
243 // bind ctrl+shift+f and ctrl+space
244 // to open/close the search
245 me
.keymap
= new Ext
.KeyMap({
246 target
: Ext
.get(document
),
261 // always select first item and
262 // sort by relevance after load
263 me
.mon(me
.grid
.store
, 'load', function() {
264 me
.grid
.getSelectionModel().select(0);
266 property
: 'relevance',