UNPKG

@gmod/jbrowse

Version:

JBrowse - client-side genome browser

177 lines (155 loc) 6.02 kB
define( [ 'dojo/_base/declare', 'dojo/_base/array', 'dojo/store/util/QueryResults', 'JBrowse/Util', 'JBrowse/Store/Hash', 'JBrowse/Model/Location' ], function( declare, array, QueryResults, Util, HashStore, Location ) { return declare( HashStore, { constructor: function( args ) { this.tooManyMatchesMessage = args.tooManyMatchesMessage || '(too many matches to display)'; // generate stopPrefixes var stopPrefixes = this.stopPrefixes = {}; // make our stopPrefixes an object as { prefix: true, ... } // with all possible prefixes of our stop prefixes if( args.stopPrefixes ) { var prefixesInput = typeof args.stopPrefixes == 'string' ? [ args.stopPrefixes ] : args.stopPrefixes; dojo.forEach( prefixesInput, function(prefix) { while( prefix.length ) { stopPrefixes[prefix] = true; prefix = prefix.substr( 0, prefix.length - 1 ); } }); } }, _nameRecordToItem: function( nameRecord ) { if( nameRecord.hitLimit ) { // it's a too-many-matches marker return { name: this.tooManyMatchesMessage, hitLimit: true }; } else { // it's an actual name record var item = {}; if( typeof nameRecord == 'object' ) { item.name = nameRecord[0]; var trackConfig = this._findTrackConfig( ((this.meta||{}).track_names||{})[ nameRecord[1] ] ); item.location = new Location({ ref: nameRecord[3], start: parseInt( nameRecord[4] ), end: parseInt( nameRecord[5] ), tracks: trackConfig ? [ trackConfig ] : null, objectName: nameRecord[0] }); } else { item.name = nameRecord; } return item; } }, // look in the browser's track configuration for the track with the given label _findTrackConfig: function( trackLabel ) { if( ! trackLabel ) return null; var track = null; var i = array.some( this.browser.config.tracks, function( t ) { if( t.label == trackLabel ) { track = t; return true; } return false; }); return track; }, _makeResults: function( nameRecords ) { // convert the name records into dojo.store-compliant data // items, sort them by name and location var results = array.map( nameRecords, dojo.hitch(this,'_nameRecordToItem') ) .sort( function( a, b ) { return a.name.localeCompare( b.name ) || a.location.localeCompare( b.location ); }); var last; var hitLimit; // aggregate them and make labels for them. for names with // multiple locations, make a multipleLocations member. results = array.filter( results, function( i ) { if( i.hitLimit ) { hitLimit = i; if( ! hitLimit.label ) hitLimit.label = hitLimit.name || 'too many matches'; return false; } else if( last && last.name == i.name ) { last.label = last.name + ' <span class="multipleLocations">multiple locations</span>'; if( last.multipleLocations ) { last.multipleLocations.push( i.location ); } else { last.multipleLocations = [last.location,i.location]; delete last.location; } return false; } last = i; last.label = last.name + ( last.location ? ' <span class="locString">'+last.location+'</span>' : '' ); return true; }); if( hitLimit ) results.push( hitLimit ); return QueryResults( results ); }, // case-insensitive, and supports prefix queries like 'foo*' query: function( query, options ) { // remove trailing asterisks from query.name var thisB = this; var name = ( query.name || '' ).toString(); // lowercase the name if the store is all-lowercase if( this.meta.lowercase_keys ) name = name.toLowerCase(); var trailingStar = /\*$/; if( trailingStar.test( name ) ) { name = name.replace( trailingStar, '' ); return this._getEntry( name ) .then( function( value ) { value = value || {}; return thisB._makeResults( ( value.exact || [] ).concat( value.prefix || [] ) ); }); } else { return this._getEntry( name ) .then( function( value ) { return thisB._makeResults( (value||{}).exact || [] ); }); } }, get: function( id ) { // lowercase the id if the store is all-lowercase if( this.meta.lowercase_keys ) id = id.toLowerCase(); return this._getEntry( id ) .then( function( bucket ) { var nameRec = (bucket.exact||[])[0]; return nameRec ? this._nameRecordToItem( nameRec ) : null; }); }, _getEntry: function( key ) { return this._getBucket(key) .then( function( bucket ) { return bucket[key]; }); } }); });