Skip to content

Commit

Permalink
add csv-based track metadata, indexing of the facets, and generating …
Browse files Browse the repository at this point in the history
…selects for each facet
  • Loading branch information
rbuels committed May 2, 2012
1 parent e5e7a54 commit b051e52
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 27 deletions.
2 changes: 1 addition & 1 deletion js/Browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ Browser.prototype.createTrackList = function() {

// instantiate the tracklist
this.trackListView = new resolved_tl_class( {
trackMetaData: new JBrowse.Model.TrackMetaData({ trackConfigs: this.config.tracks }),
trackMetaData: new JBrowse.Model.TrackMetaData({ trackConfigs: this.config.tracks, browser: this }),
trackConfigs: this.config.tracks,
browser: this
});
Expand Down
121 changes: 109 additions & 12 deletions js/Model/TrackMetaData.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,119 @@
dojo.require('dojo.data.ItemFileWriteStore');

dojo.declare( 'JBrowse.Model.TrackMetaData', dojo.data.ItemFileWriteStore,
dojo.require('dojox.data.CsvStore');
dojo.declare( 'JBrowse.Model.TrackMetaData', dojox.data.CsvStore,
/**
* @lends JBrowse.Model.TrackMetaData.prototype
*/
{
/**
* Data store for track metadata, supporting faceted
* (parameterized) searching.
* @constructs
* @param args.trackConfigs {Array} array of track configuration
*/
constructor: function( args ) {
dojo.data.ItemFileWriteStore.call( this, {data: {
identifier: 'label',
items: dojo.map( args.trackConfigs, function(c){
var item = {};
dojo.forEach( ['key','label','type'], function(k) {item[k] = c[k];} );
return item;
})
}});
}
dojox.data.CsvStore.call( this, {
url: Util.resolveUrl( args.browser.config.sourceUrl, 'trackMeta.csv' )
});

this.filterFacets = args.filterFacets || function() {
return true;
};

// init our onReady callbacks
if( ! dojo.isArray( args.onReady ) ){
this.onReadyFuncs = args.onReady ? [ args.onReady ] : [];
} else {
this.onReadyFuncs = dojo.clone(args.onReady);
}

// fetch our items and calculate our facets
this.fetch({
scope: this,
onComplete: Util.debugHandler( this, function( items ) {
// build our facet indexes
this._initFacets( items );

this.ready = true;

// call our onReady callbacks
dojo.forEach( this.onReadyFuncs, function(f) {
f.call( this, this );
}, this );
this.onReadyFuncs = [];
})
});
},

_initFacets: function( items ) {

// get our (filtered) list of facets we will index for
var facets = this.facets =
dojo.filter( this.getAttributes( items[0] ),
this.filterFacets,
this
);

// initialize the empty indexes
this.facetIndexes = { count: 0, byFacetName: {} };
dojo.forEach( facets, function(facet) {
this.facetIndexes.byFacetName[facet] = { count: 0, byFacetValue: {} };
}, this);

// build an index of our items for each facet
dojo.forEach( items, function( item ) {
this.facetIndexes.count++;
dojo.forEach( facets, function( facet ) {
var value = this.getValue( item, facet, undefined );
if( typeof value == 'undefined' )
return;
var bucket = this.facetIndexes.byFacetName[facet].byFacetValue[value];
if( !bucket )
bucket = this.facetIndexes.byFacetName[facet].byFacetValue[value] = { count: 0, items: [] };
bucket.count++;
bucket.items.push(item);
},this);
}, this);
},

/**
* Get an array of the text names of the facets that are defined
* in this track metadata.
* @param callback {Function} called as callback( [facet,facet,...] )
*/
getFacets: function( callback ) {
return this.facets;
},

/**
* Get an Array of the distinct values for a given facet name.
* @param facetName {String} the facet name
* @returns {Array} distinct values for that facet
*/
getFacetValues: function( facetName ) {
var index = this.facetIndexes.byFacetName[facetName];
if( !index )
return [];

var values = [];
for( var v in index.byFacetValue ) {
if( index.byFacetValue.hasOwnProperty(v) )
values.push( v );
}
return values;
},

/**
* Add a callback to be called when this store is ready (loaded).
*/
onReady: function( callback ) {
if( this.ready ) {
callback.call( this, this );
}
else {
this.onReadyFuncs.push( callback );
}
},



});
45 changes: 31 additions & 14 deletions js/View/TrackList/Faceted.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ dojo.declare( 'JBrowse.View.TrackList.Faceted', null,
{

/**
* Drag-and-drop track selector with facets and text searching.
* Track selector with facets and text searching.
* @constructs
*/
constructor: function(args) {
Expand All @@ -26,32 +26,32 @@ dojo.declare( 'JBrowse.View.TrackList.Faceted', null,
document.body
);

// schedule the facet selectors to render once the data is loaded
this.facetsDiv = dojo.create( 'div',{ className: 'facetSelectorContainer' }, grid_div);
this.trackDataStore.onReady( dojo.hitch(this, 'renderFacetSelectors') );

// make the text input for text filtering
this.textFilterInput = dojo.create(
'input',
{ type: 'text', width: 30 },
dojo.create('label',{innerHTML: 'Containing text', id: 'tracklist_textfilter'}, grid_div )
);

// make a data grid that will hold the search results
this.dataGrid = new dojox.grid.DataGrid({
id: 'grid',
store: this.trackDataStore,
structure: [[
{'name': 'Type', 'field': 'type', 'width': '100px'},
{'name': 'Key', 'field': 'key', 'width': '100px'}
]],
rowSelector: '20px'
]]
//rowSelector: '20px'
},
document.createElement('div')
);
grid_div.appendChild(this.dataGrid.domNode);
this.dataGrid.startup();

// make the text input for text filtering
this.textFilterInput = dojo.create(
'input',
{
type: 'text',
width: 30,
id: 'tracklist_textfilter'
},
grid_div
);

// put it all in a dialog
this.dialog = new dijit.Dialog({
id: "faceted_tracksel",
Expand All @@ -65,6 +65,23 @@ dojo.declare( 'JBrowse.View.TrackList.Faceted', null,
);
},

/**
* Create selection boxes for each searchable facet.
*/
renderFacetSelectors: function( facets ) {
var store = this.trackDataStore;
dojo.forEach( store.getFacets() , function(facetName) {
var selector =
dojo.create( 'select', {},
dojo.create( 'label', {innerHTML: facetName},
this.facetsDiv ));

dojo.forEach( store.getFacetValues(facetName).sort(), function(val) {
dojo.create( 'option', { innerHTML: val, value: val }, selector );
},this);
},this);
},

/**
* Given an array of track configs, update the track list to show
* that they are turned on.
Expand Down

0 comments on commit b051e52

Please sign in to comment.