UNPKG

@gmod/jbrowse

Version:

JBrowse - client-side genome browser

280 lines (248 loc) 10.7 kB
define( [ 'dojo/_base/declare', 'dojo/_base/array', 'dojo/aspect', 'dojo/on', 'dijit/focus', 'dijit/form/Button', 'dijit/form/RadioButton', 'dojo/dom-construct', 'dijit/Dialog', 'dojox/form/Uploader', './FileDialog/TrackList/BAMDriver', './FileDialog/TrackList/CRAMDriver', './FileDialog/TrackList/BigWigDriver', './FileDialog/TrackList/GFF3Driver', './FileDialog/TrackList/GTFDriver', './FileDialog/TrackList/VCFTabixDriver', './FileDialog/TrackList/VCFTribbleDriver', './FileDialog/TrackList/BEDTabixDriver', './FileDialog/TrackList/GFF3TabixDriver', './FileDialog/TrackList/BEDDriver', './FileDialog/TrackList/BigBedDriver', './FileDialog/ResourceList', './FileDialog/TrackList', 'JBrowse/Util' ], function( declare, array, aspect, on, dijitFocus, Button, RadioButton, dom, Dialog, Uploaded, BAMDriver, CRAMDriver, BigWigDriver, GFF3Driver, GTFDriver, VCFTabixDriver, VCFTribbleDriver, BEDTabixDriver, GFF3TabixDriver, BEDDriver, BigBedDriver, ResourceList, TrackList, Util ) { return declare( null, { constructor: function( args ) { this.browser = args.browser; this.config = dojo.clone( args.config || {} ); this.browserSupports = { dnd: 'draggable' in document.createElement('span') }; this._fileTypeDrivers = [ new BAMDriver(), new CRAMDriver(), new BigWigDriver(), new GFF3Driver(), new GTFDriver(), new VCFTabixDriver(), new VCFTribbleDriver(), new BEDTabixDriver(), new GFF3TabixDriver(), new BEDDriver(), new BigBedDriver() ]; }, addFileTypeDriver: function( d ) { this._fileTypeDrivers.unshift( d ); }, getFileTypeDrivers: function() { return this._fileTypeDrivers.slice(); }, _makeActionBar: function( openCallback, cancelCallback ) { var actionBar = dom.create( 'div', { className: 'dijitDialogPaneActionBar' }); var disChoices = this.trackDispositionChoice = [ new RadioButton({ id: 'openImmediately', value: 'openImmediately', checked: true }), new RadioButton({ id: 'addToTrackList', value: 'addToTrackList' }) ]; var aux = dom.create('div',{className:'aux'},actionBar); disChoices[0].placeAt(aux); dom.create('label', { "for": 'openImmediately', innerHTML: 'Open immediately' }, aux ), disChoices[1].placeAt(aux); dom.create('label', { "for": 'addToTrackList', innerHTML: 'Add to tracks' }, aux ); new Button({ iconClass: 'dijitIconDelete', label: 'Cancel', onClick: dojo.hitch( this, function() { cancelCallback && cancelCallback(); this.dialog.hide(); }) }) .placeAt( actionBar ); new Button({ iconClass: 'dijitIconFolderOpen', label: 'Open', onClick: dojo.hitch( this, function() { openCallback && openCallback({ trackConfs: this.trackList.getTrackConfigurations(), trackDisposition: this.trackDispositionChoice[0].checked ? this.trackDispositionChoice[0].value : this.trackDispositionChoice[1].checked ? this.trackDispositionChoice[1].value : undefined }); this.dialog.hide(); }) }) .placeAt( actionBar ); return { domNode: actionBar }; }, show: function( args ) { var dialog = this.dialog = new Dialog( { title: "Open files", className: 'fileDialog' } ); var localFilesControl = this._makeLocalFilesControl(); var remoteURLsControl = this._makeRemoteURLsControl(); var resourceListControl = this._makeResourceListControl(); var trackListControl = this._makeTrackListControl(); var actionBar = this._makeActionBar( args.openCallback, args.cancelCallback ); // connect the local files control to the resource list dojo.connect( localFilesControl.uploader, 'onChange', function() { if(Util.isElectron()) { const arr = [...localFilesControl.uploader._files].map((file) => Util.replacePath(file.path)); resourceListControl.addURLs(arr); } else { resourceListControl.addLocalFiles( localFilesControl.uploader._files ); } }); // connect the remote URLs control to the resource list dojo.connect( remoteURLsControl, 'onChange', function( urls ) { resourceListControl.clearURLs(); resourceListControl.addURLs( urls ); }); // connect the resource list to the track list dojo.connect( resourceListControl, 'onChange', function( resources ) { trackListControl.update( resources ); }); var div = function( attr, children ) { var d = dom.create('div', attr ); array.forEach( children, dojo.hitch( d, 'appendChild' )); return d; }; var content = [ dom.create( 'div', { className: 'intro', innerHTML: args.introMsg||'Add any combination of data files and URLs, and JBrowse will automatically suggest tracks to display their contents.' } ), div( { className: 'resourceControls' }, [ localFilesControl.domNode, remoteURLsControl.domNode ] ), resourceListControl.domNode, trackListControl.domNode, actionBar.domNode ]; dialog.set( 'content', content ); dialog.show(); aspect.after( dialog, 'hide', dojo.hitch( this, function() { dijitFocus.curNode && dijitFocus.curNode.blur(); setTimeout( function() { dialog.destroyRecursive(); }, 500 ); })); }, _makeLocalFilesControl: function() { var container = dom.create('div', { className: 'localFilesControl' }); dom.create('h3', { innerHTML: 'Local files' }, container ); var dragArea = dom.create('div', { className: 'dragArea' }, container ); var fileBox; fileBox = new dojox.form.Uploader({ multiple: true }); fileBox.placeAt( dragArea ); if( this.browserSupports.dnd ) { // let the uploader process any files dragged into the dialog fileBox.addDropTarget( this.dialog.domNode ); // add a message saying you can drag files in dom.create( 'div', { className: 'dragMessage', innerHTML: 'Select or drag files here.' }, dragArea ); } // little elements used to show pipeline-like connections between the controls dom.create( 'div', { className: 'connector', innerHTML: '&nbsp;'}, container ); return { domNode: container, uploader: fileBox }; }, _makeRemoteURLsControl: function() { var container = dom.create('div', { className: 'remoteURLsControl' }); // make the input elements dom.create('h3', { innerHTML: 'Remote URLs - <smaller>one per line</smaller>' }, container ); // the onChange here will be connected to by the other parts // of the dialog to propagate changes to the text in the box var self = { domNode: container, onChange: function(urls) { //console.log('urls changed'); } }; self.input = dom.create( 'textarea', { className: 'urlInput', placeHolder: "http://paste.urls.here/example.bam", cols: 25, rows: 5, spellcheck: false }, container ); // set up the handlers to propagate changes var realChange = function() { var text = dojo.trim( self.input.value ); var urls = text.length ? text.split( /\s+/ ) : []; self.onChange( urls ); }; // watch the input text for changes. just do it every 900ms // because there are many ways that text can get changed (like // pasting), not all of which fire the same events. not using // the onchange event, because that doesn't fire until the // textarea loses focus. var previousText = ''; var checkFrequency = 900; var checkForChange = function() { // compare with all whitespace changed to commas so that // we are insensitive to changes in whitespace if( self.input.value.replace(/\s+/g,',') != previousText ) { realChange(); previousText = self.input.value.replace(/\s+/g,','); } window.setTimeout( checkForChange, checkFrequency ); }; window.setTimeout( checkForChange, checkFrequency ); // little elements used to show pipeline-like connections between the controls dom.create( 'div', { className: 'connector', innerHTML: '&nbsp;'}, container ); return self; }, _makeResourceListControl: function () { var rl = new ResourceList({ dialog: this }); return rl; }, _makeTrackListControl: function() { var tl = new TrackList({ browser: this.browser, fileDialog: this }); this.trackList = tl; return tl; } }); });