Skip to content

Commit

Permalink
add support to HTMLFeatures and the default feature detail for `style…
Browse files Browse the repository at this point in the history
…->label` and `style->description` configuration variables that can be set to callbacks. references #9
  • Loading branch information
rbuels committed Feb 21, 2013
1 parent 76cc2ed commit 8ef1963
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 34 deletions.
6 changes: 5 additions & 1 deletion docs/tutorial/conf_files/volvox.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@
"track" : "Motifs",
"class" : "feature3",
"description" : 1,
"key" : "Example motifs"
"key" : "Example motifs",
"style": {
"label": "function(feature) { return feature.get('Name')+' (via JS callback)' }",
"description": "function(feature) { return feature.get('Name')+': '+feature.get('Note'); }"
}
},
{
"feature" : [
Expand Down
5 changes: 5 additions & 0 deletions release-notes.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{{$NEXT}}

* HTMLFeatures tracks now accept `style->label` and
`style->description` configuration variables variable that can be
set to a function callback that returns a string with the feature's
label or long description, respectively (issue #9).

* Wiggle/XYPlot tracks now accept an array for their `variance_band`
argument, allowing users to set the position of the variance bands
to show (issue #133).
Expand Down
34 changes: 34 additions & 0 deletions src/JBrowse/View/Track/BlockBased.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ return declare( null,
this.empty = false;
this.browser = args.browser;
this.store = args.store;

this.compiledConfig = {};
},

/**
Expand Down Expand Up @@ -810,6 +812,38 @@ return declare( null,
: confVal;
},

_compileConfigurationPath: function( path ) {
var confVal = this.config;

if( typeof path == 'string' )
path = path.split('.');
while( path.length && confVal )
confVal = confVal[ path.shift() ];

if( path.length )
return function() { return null; };

return typeof confVal == 'function'
? confVal
: function() { return confVal; };
},

/**
* Given a dot-separated string configuration path into the config
* (e.g. "style.bg_color"), get the value of the configuration.
* If args are given, evaluate the configuration using them.
* Otherwise, return a function that returns the value of the
* configuration when called.
*/
getConf: function( path, args ) {
var func = this.compiledConfig[path];
if( ! func ) {
func = this.compiledConfig[path] = this._compileConfigurationPath( path );
}

return args ? func.apply( this, args ) : func;
},

_openDialog: function( spec, evt, context ) {
context = context || {};
var type = spec.action;
Expand Down
4 changes: 3 additions & 1 deletion src/JBrowse/View/Track/CanvasFeatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ return declare( [CanvasTrack,FeatureDetailMixin], {
mouseovercolor: 'rgba(0,0,0,0.3)',
border_color: null,
height: 11,
marginBottom: 1
marginBottom: 1,
label: function( feature ) { return feature.get('Name') || feature.get('ID'); },
description: 'note, description'
}
};
},
Expand Down
4 changes: 2 additions & 2 deletions src/JBrowse/View/Track/FeatureDetailMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ return declare(null,{
container = container || dojo.create('div', { className: 'detail feature-detail feature-detail-'+track.name, innerHTML: '' } );
var coreDetails = dojo.create('div', { className: 'core' }, container );
coreDetails.innerHTML += '<h2 class="sectiontitle">Primary Data</h2>';
coreDetails.innerHTML += fmt( 'Name', f.get('name') );
coreDetails.innerHTML += fmt( 'Name', this.getConf( 'style.label', [f] ) );
coreDetails.innerHTML += fmt( 'Type', f.get('type') );
coreDetails.innerHTML += fmt( 'Description', f.get('note') );
coreDetails.innerHTML += fmt( 'Description', this._getDescription ? this._getDescription( f ) : (f.get('note') || f.get('description') ));
coreDetails.innerHTML += fmt(
'Position',
Util.assembleLocString({ start: f.get('start'),
Expand Down
73 changes: 43 additions & 30 deletions src/JBrowse/View/Track/HTMLFeatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ var HTMLFeatures = declare( [ BlockBased, YScaleMixin, ExportMixin, FeatureDetai
*/
_defaultConfig: function() {
return {
description: 'note, description',

maxFeatureScreenDensity: 0.5,
blockDisplayTimeout: 5000,

Expand All @@ -98,6 +96,10 @@ var HTMLFeatures = declare( [ BlockBased, YScaleMixin, ExportMixin, FeatureDetai
minSubfeatureWidth: 6,
maxDescriptionLength: 70,
showLabels: true,

label: function( feature ) { return feature.get('name') || feature.get('ID'); },
description: 'note, description',

centerChildrenVertically: true // by default use feature child centering
},
hooks: {
Expand Down Expand Up @@ -675,8 +677,8 @@ var HTMLFeatures = declare( [ BlockBased, YScaleMixin, ExportMixin, FeatureDetai

// if the label extends beyond the feature, use the
// label end position as the end position for layout
var name = feature.get('name') || feature.get('ID');
var description = this.config.description && scale > descriptionScale && this._getDescription(feature);
var name = this.getConf( 'style.label', [feature] );
var description = scale > descriptionScale && this._getDescription(feature);
if( description && description.length > this.config.style.maxDescriptionLength )
description = description.substr(0, this.config.style.maxDescriptionLength+1 ).replace(/(\s+\S+|\s*)$/,'')+String.fromCharCode(8230);

Expand Down Expand Up @@ -771,13 +773,13 @@ var HTMLFeatures = declare( [ BlockBased, YScaleMixin, ExportMixin, FeatureDetai
case 1:
case '+':
ah.className = "plus-" + this.config.style.arrowheadClass;
ah.style.cssText = "left: 100%;"
ah.style.cssText = "left: 100%;";
featDiv.appendChild(ah);
break;
case -1:
case '-':
ah.className = "minus-" + this.config.style.arrowheadClass;
ah.style.cssText = "left: " + (-this.minusArrowWidth) + "px;"
ah.style.cssText = "left: " + (-this.minusArrowWidth) + "px;";
featDiv.appendChild(ah);
break;
}
Expand Down Expand Up @@ -826,35 +828,46 @@ var HTMLFeatures = declare( [ BlockBased, YScaleMixin, ExportMixin, FeatureDetai
// get the description string for a feature, based on the setting
// of this.config.description
_getDescription: function( feature ) {
var dConf = this.config.style.description || this.config.description;

if( ! dConf )
return null;

// if the description is a function, just call it
if( typeof dConf == 'function' ) {
return dConf.call( this, feature );
}
// otherwise try to parse it as a field list
else {

// parse our description varname conf if necessary
var fields = this.descriptionFields || function() {
var f = this.config.description;
if( f ) {
if( lang.isArray( f ) ) {
f = f.join(',');
// parse our description varname conf if necessary
var fields = this.descriptionFields || function() {
var f = dConf;
if( f ) {
if( lang.isArray( f ) ) {
f = f.join(',');
}
else if( typeof f != 'string' ) {
console.warn( 'invalid `description` setting ('+f+') for "'+this.name+'" track, falling back to "note,description"' );
f = 'note,description';
}
f = f.toLowerCase().split(/\s*\,\s*/);
}
else if( typeof f != 'string' ) {
console.warn( 'invalid `description` setting for "'+this.name+'" track, falling back to "note,description"' );
f = 'note,description';
else {
f = [];
}
f = f.toLowerCase().split(/\s*\,\s*/);
}
else {
f = [];
this.descriptionFields = f;
return f;
}.call(this);

// return the value of the first field that contains something
for( var i=0; i<fields.length; i++ ) {
var d = feature.get( fields[i] );
if( d )
return d;
}
this.descriptionFields = f;
return f;
}.call(this);


// return the value of the first field that contains something
for( var i=0; i<fields.length; i++ ) {
var d = feature.get( fields[i] );
if( d )
return d;
return null;
}
return null;
},

handleSubFeatures: function( feature, featDiv,
Expand Down

0 comments on commit 8ef1963

Please sign in to comment.