3 if( ! SGN
.Search
) SGN
.Search
= {};
7 set_up_feature_search: function( args
) {
8 var maximum_export_size
= args
.maximum_export_size
|| 10000;
10 Ext
.Loader
.setConfig({enabled
: true});
16 'Ext.grid.PagingScroller'
19 // make the feature grid
20 Ext
.onReady(function(){
24 Ext
.define('Feature', {
25 extend
: 'Ext.data.Model',
35 idProperty
: 'feature_id'
38 function get_search_query( store
) {
39 // get the filtering data from the store
40 var post_vars
= Ext
.clone( store
.proxy
.extraParams
);
42 // filter out any form fields that are empty or just whitespace
43 for( var name
in post_vars
) {
44 var value
= post_vars
[name
];
45 if( value
== null || typeof value
== 'string' && ! value
.match(/[^\s]/) ) {
46 delete post_vars
[name
];
50 // get the sort settings from the store
51 var sorter
= store
.sorters
.first();
52 post_vars
.sort
= sorter
.property
;
53 post_vars
.dir
= sorter
.direction
;
58 // create the Data Store
59 var feature_store
= Ext
.create('Ext.data.Store', {
67 // enable or disable the export and save
68 // toolbar based on how many features matched
69 datachanged: function( store
) {
70 var toolbar
= Ext
.getCmp('feature_export_toolbar');
71 var label
= Ext
.getCmp('feature_export_toolbar_disabled_label');
72 if( store
.getTotalCount() <= maximum_export_size
) {
73 // enable the export toolbar
77 // disable the export toolbar
86 url
: '/search/features/search_service',
90 totalProperty
: 'totalCount',
91 successProperty
: 'success'
93 // sends single sort as multi parameter
97 property
: 'feature_id',
102 function hyphen_if_empty( value
) {
103 return value
.length
> 0 ? value
: '-';
106 function export_to_bulk( bulk_url
) {
107 var search_query
= get_search_query( feature_store
);
108 search_query
.fields
= 'name';
110 url
: '/search/features/search_service',
112 params
: search_query
,
113 success: function( response
) {
114 // make a bulk-download URL populated with these IDs
115 var features
= Ext
.JSON
.decode( response
.responseText
).data
;
117 for( var i
= 0; i
< features
.length
; i
++ ) {
118 names
.push( features
[i
].name
);
120 names
= names
.join("\n");
122 Ext
.create( 'Ext.form.Panel', {
124 standardSubmit
: true,
125 defaultType
: 'textfield',
127 items
: [{ name
: 'ids', value
: names
}]
133 var feature_grid
= Ext
.create('Ext.grid.Panel', {
136 //title: 'Matching Features',
137 store
: feature_store
,
144 id
: 'feature_export_toolbar',
148 id
: 'feature_export_toolbar_disabled_label',
149 text
: 'Exporting limited to '+ Ext
.util
.Format
.number( maximum_export_size
, '0,000' )+' features.',
154 icon
: '/img/icons/oxygen/16x16/media-floppy.png',
159 icon
: '/img/icons/oxygen/16x16/text-csv.png',
160 handler: function() {
161 var search_query_vars
= get_search_query( feature_store
);
162 var csv_url
= '/search/features/export_csv?' + Ext
.Object
.toQueryString( search_query_vars
);
163 location
.href
= csv_url
;
171 icon
: '/img/icons/oxygen/16x16/document-export.png',
175 text
: 'bulk feature download',
176 icon
: '/img/icons/oxygen/16x16/document-export-table.png',
177 handler: function() {
178 export_to_bulk( '/bulk/feature' );
181 text
: 'bulk gene download',
182 icon
: '/img/icons/oxygen/16x16/document-export-table.png',
183 handler: function() {
184 export_to_bulk( '/bulk/gene' );
192 xtype
: 'pagingtoolbar',
193 store
: feature_store
, // same store GridPanel is using
196 emptyMsg
: 'No matching features'
208 dataIndex
: 'organism',
225 renderer: function(value
,p
,record
) {
226 return Ext
.String
.format(
227 '<a href="/feature/{0}/details" target="_blank">{1}</a>',
234 dataIndex
: 'description',
239 renderer
: hyphen_if_empty
242 dataIndex
: 'locations',
247 renderer
: hyphen_if_empty
250 renderTo
: document
.getElementById('search_grid')
253 // make the form for feature filtering
254 var feature_types_store
=
255 Ext
.create('Ext.data.Store', {
256 fields
: ['type_id', 'name'],
260 url
: '/search/features/feature_types_service',
263 totalProperty
: 'totalCount',
264 successProperty
: 'success'
269 var featureprop_types_store
=
270 Ext
.create('Ext.data.Store', {
271 fields
: ['type_id', 'name'],
275 url
: '/search/features/featureprop_types_service',
278 totalProperty
: 'totalCount',
279 successProperty
: 'success'
284 var srcfeatures_store
=
285 Ext
.create('Ext.data.Store', {
290 url
: '/search/features/srcfeatures_service',
293 totalProperty
: 'totalCount',
294 successProperty
: 'success'
299 function applyFeatureFilters( form
) {
300 var data
= form
.getFieldValues();
301 // filter out any form fields that are just whitespace
302 for( var name
in data
) {
303 if( data
[name
] == null || typeof data
[name
] == 'string' && ! data
[name
].match(/[^\s]/) ) {
307 feature_store
.proxy
.extraParams
= data
;
308 feature_store
.load( function(records
,operation
,success
) {
310 feature_store
.removeAll();
315 // default field settings for the text fields that make the
316 // enter key submit the form
318 var feature_search_field_defaults
= {
323 specialkey: function(field
, e
){
324 if (e
.getKey() == e
.ENTER
) {
325 applyFeatureFilters( field
.up('form').getForm() );
331 var feature_filter_form
= Ext
.create('Ext.form.Panel', {
334 defaultType
: 'textfield',
335 renderTo
: document
.getElementById('search_form'),
338 fieldLabel
: 'Name contains',
342 fieldLabel
: 'Organism contains',
347 fieldLabel
: 'Type is',
348 id
: 'feature_type_select',
350 store
: feature_types_store
,
351 disabled
: true, // enabled when feature_types_store finishes loading
353 displayField
: 'name',
354 valueField
: 'type_id',
356 listeners
: {} // don't override the combobox's enter key
359 fieldLabel
: 'Description contains',
364 title
: 'Overlaps range',
367 defaults
: feature_search_field_defaults
,
371 name
: 'srcfeature_id',
372 store
: srcfeatures_store
,
373 disabled
: true, // enabled when srcfeatures_store finishes load
374 id
: 'srcfeature_select',
376 displayField
: 'name',
377 valueField
: 'feature_id',
380 // when the srcfeature is set, set the
381 // max values of the range numbers to
382 // the srcfeature's length
383 change: function( cbox
, newValue
, oldValue
) {
384 var feature
= cbox
.getStore().getById( newValue
);
386 var len
= feature
.raw
.seqlen
;
387 var srcfeature_start
= Ext
.getCmp('srcfeature_start');
388 var srcfeature_end
= Ext
.getCmp('srcfeature_end');
389 srcfeature_start
.setMaxValue( len
);
390 srcfeature_end
.setMaxValue( len
);
391 if( ! srcfeature_start
.getValue() )
392 srcfeature_start
.setValue( 1 );
393 if( ! srcfeature_end
.getValue() || srcfeature_end
.getValue() > len
)
394 srcfeature_end
.setValue( len
);
399 { xtype
: 'numberfield',
400 id
: 'srcfeature_start',
401 name
: 'srcfeature_start',
406 { xtype
: 'numberfield',
407 id
: 'srcfeature_end',
408 name
: 'srcfeature_end',
417 title
: 'Has property',
420 defaultType
: 'textfield',
421 defaults
: feature_search_field_defaults
,
426 id
: 'featureprop_type_select',
428 store
: featureprop_types_store
,
429 disabled
: true, // enabled when featureprop_types_store finishes loading
431 displayField
: 'name',
432 valueField
: 'type_id',
434 listeners
: {} // don't override the combobox's enter key
436 fieldLabel
: 'containing',
445 // make the ENTER key submit the form by default for all form fields
446 defaults
: feature_search_field_defaults
,
450 handler: function() {
451 var form
= this.up('form').getForm();
456 handler: function() {
457 applyFeatureFilters( this.up('form').getForm() );
464 // only enable the various comboboxes in the filtering
465 // form when their associated data stores finish
467 feature_types_store
.load(
468 function( recs
, op
, success
) {
469 if( success
) Ext
.getCmp('feature_type_select').enable();
472 featureprop_types_store
.load(
473 function( recs
, op
, success
) {
474 if( success
) Ext
.getCmp('featureprop_type_select').enable();
477 srcfeatures_store
.load(
478 function( recs
, op
, success
) {
479 if( success
) Ext
.getCmp('srcfeature_select').enable();