UNPKG

@gmod/jbrowse

Version:

JBrowse - client-side genome browser

138 lines (114 loc) 4.14 kB
/** * A JBrowse component keeps a reference to the main browser object, and is configurable. */ define([ 'dojo/_base/declare', 'dojo/_base/lang', 'JBrowse/Util' ], function( declare, lang, Util ) { return declare( null, { constructor: function( args ) { args = args || {}; // merge our config with the config defaults this._finalizeConfig( args.config ); this.browser = args.browser; if( ! this.browser ) throw "a reference to the main browser is required by this constructor"; this.compiledConfig = {}; }, _finalizeConfig: function( config ) { this.config = this._mergeConfigs( dojo.clone( this._defaultConfig() ), config || {} ); }, _defaultConfig: function() { return { baseUrl: '/' }; }, resolveUrl: function( url, args ) { args = args || {}; return Util.resolveUrl( this.getConf('baseUrl',[]), this.fillTemplate( url, args ) ); }, _mergeConfigs: function(a, b) { if( b === null ) return null; if( a === null ) a = {}; for (var prop in b) { if ((prop in a) && ("object" == typeof b[prop]) && ("object" == typeof a[prop]) ) { a[prop] = this._mergeConfigs( a[prop], b[prop] ); } else if( typeof a[prop] == 'undefined' || typeof b[prop] != 'undefined' ){ a[prop] = b[prop]; } } return a; }, _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.call( this ); }, /** * Given a string with templating strings like {refseq}, fill them * in using the given values. * * With no additional values given, knows how to interpolate * {refseq}, {refSeq}, {refSeqNum}, and {refSeqNumNoLeadingZeroes}. * * @param {String} str string to interpolate values into * @param {Object} values optional object with additional values that can be interpolated * @returns new string with interpolations */ fillTemplate: function( str, values ) { // skip if it's not a string or the string has no interpolations if( typeof str != 'string' || str.indexOf('{') == -1 ) return str; // fill in a bunch of args for this.refSeq or this.ref var templateFillArgs = { 'refseq': (this.refSeq||{}).name || (this.ref||{}).name || this.ref || '' }; templateFillArgs.refSeq = templateFillArgs.refseq; if( templateFillArgs.refSeq ) { templateFillArgs.refSeqNum = ( /\d+/.exec( templateFillArgs.refSeq ) || [] )[0] || ''; } // make refseqNumNoLeadingZeroes if( templateFillArgs.refSeqNum ) { templateFillArgs.refSeqNumNoLeadingZeroes = ( /^0*(\d+)/.exec( templateFillArgs.refSeqNum ) || [] )[1] || ''; } if( values ) lang.mixin( templateFillArgs, values ); return Util.fillTemplate( str, templateFillArgs ); } }); });