@gmod/jbrowse
Version:
JBrowse - client-side genome browser
95 lines (79 loc) • 3 kB
JavaScript
/**
* Mixin that dynamically defines and redefines a filterFeature()
* method, and supports a filtering hierarchy, and filter chaining at
* each level of the hierarchy. Designed to be really fast, because
* filterFeature() is going to be called many, many times.
*/
define([
'dojo/_base/declare',
'dojo/_base/array'
],
function(
declare,
array
) {
var serialNumber = 0;
return declare( null, {
filterFeature: function( feature ) {
return true;
},
_featureFilterChain: [],
addFeatureFilter: function( filter, uniqName ) {
uniqName = this._getFeatureFilterName( uniqName );
this._featureFilterChain.push({ name: uniqName, filter: filter });
this._buildFeatureFilter();
return uniqName;
},
// need to have a unique name for every function we're passed so
// that we can tell them apart. stringification and strict
// equality don't always work.
_getFeatureFilterName: function( uniqName ) {
if( uniqName === undefined )
return 'featureFilter_'+(++serialNumber);
return uniqName;
},
removeFeatureFilter: function( uniqName ) {
var newchain = [];
for( var i = 0; i < this._featureFilterChain.length; i++ ) {
if( this._featureFilterChain[i].name !== uniqName )
newchain.push( this._featureFilterChain[i] );
}
this._featureFilterChain = newchain;
this._buildFeatureFilter();
},
_buildFeatureFilter: function() {
var filterChain = this._featureFilterChain.slice();
if( ! filterChain.length )
this.filterFeature = function( feat ) {
return this.featureFilterParentComponent.filterFeature( feat );
};
else if( filterChain.length == 1 ) {
var single = filterChain[0].filter;
this.filterFeature = function(feat) {
return single.call(this,feat) && this.featureFilterParentComponent.filterFeature( feat );
};
} else
this.filterFeature = function( feat ) {
for( var i = 0; i<filterChain.length; i++ )
if( ! filterChain[i].filter.call( this, feat ) )
return false;
if( ! this.featureFilterParentComponent.filterFeature( feat ) )
return false;
return true;
};
},
featureFilterParentComponent: { filterFeature: function() { return true; } },
setFeatureFilter: function( filter, uniqName ) {
this._featureFilterChain = [];
this.addFeatureFilter( filter, uniqName );
},
clearFeatureFilter: function() {
this._featureFilterChain = [];
this._buildFeatureFilter();
},
setFeatureFilterParentComponent: function( parent ) {
this.featureFilterParentComponent = parent;
this._buildFeatureFilter();
}
});
});