mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Fix bad commit (adding files)
This commit is contained in:
+169
-159
@@ -1,171 +1,181 @@
|
||||
module.exports = function(grunt) {
|
||||
var DEV_PATH = './galaxy/scripts',
|
||||
DIST_PATH = '../static/scripts',
|
||||
MAPS_PATH = '../static/maps',
|
||||
// this symlink allows us to serve uncompressed scripts in DEV_PATH for use with sourcemaps
|
||||
SRC_SYMLINK = '../static/src';
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON( 'package.json' ),
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON( 'package.json' ),
|
||||
|
||||
// default task
|
||||
// use 'grunt copy' to copy the entire <galaxy>/client/galaxy/scripts dir into <galaxy>/static/scripts
|
||||
copy: {
|
||||
main: {
|
||||
files: [
|
||||
{
|
||||
uglify: {
|
||||
target : {
|
||||
files: [{
|
||||
expand : true,
|
||||
cwd : SRC_SYMLINK,
|
||||
src : '**/*.js',
|
||||
dest : DIST_PATH
|
||||
}],
|
||||
options : {
|
||||
sourceMap : true,
|
||||
sourceMapName : function( path ){
|
||||
// rewrite name to have all source maps in 'static/maps'
|
||||
return path.replace( DIST_PATH, MAPS_PATH ) + '.map';
|
||||
}
|
||||
}
|
||||
},
|
||||
options : {
|
||||
mangle : {
|
||||
screw_ie8 : true
|
||||
},
|
||||
compress : {
|
||||
// high compression options
|
||||
screw_ie8 : true,
|
||||
sequences: true,
|
||||
dead_code : true,
|
||||
drop_debugger : true,
|
||||
comparisons : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
drop_console : true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// use 'grunt watch' (from a new tab in your terminal) to have grunt re-copy changed files automatically
|
||||
watch: {
|
||||
// watch for changes in the src dir
|
||||
files: [ SRC_SYMLINK + '/**' ],
|
||||
tasks: [ 'uglify' ],
|
||||
// tasks: [ 'copy', 'pack' ],
|
||||
options: {
|
||||
spawn: false
|
||||
}
|
||||
},
|
||||
|
||||
// call bower to install libraries and other external resources
|
||||
"bower-install-simple" : {
|
||||
options: {
|
||||
color: true
|
||||
},
|
||||
"prod": {
|
||||
options: {
|
||||
production: true
|
||||
}
|
||||
},
|
||||
"dev": {
|
||||
options: {
|
||||
production: false
|
||||
}
|
||||
}
|
||||
},
|
||||
// where to move fetched bower components into the build structure (libName: [ bower-location, libs-location ])
|
||||
libraryLocations : {
|
||||
"jquery": [ "dist/jquery.js", "jquery/jquery.js" ],
|
||||
"jquery-migrate": [ "jquery-migrate.js", "jquery/jquery.migrate.js" ],
|
||||
"traceKit": [ "tracekit.js", "tracekit.js" ],
|
||||
"ravenjs": [ "dist/raven.js", "raven.js" ],
|
||||
"underscore": [ "underscore.js", "underscore.js" ],
|
||||
"handlebars": [ "handlebars.runtime.js", "handlebars.runtime.js" ],
|
||||
"lunr.js": [ "lunr.js", "lunr.js" ],
|
||||
"backbone": [ "backbone.js", "backbone/backbone.js" ],
|
||||
|
||||
// these need to be updated and tested
|
||||
//"require": [ "build/require.js", "require.js" ],
|
||||
//"d3": [ "d3.js", "d3.js" ],
|
||||
//"farbtastic": [ "src/farbtastic.js", "farbtastic.js" ],
|
||||
//"jQTouch": [ "src/reference/jqtouch.js", "jquery/jqtouch.js" ],
|
||||
//"bib2json": [ "Parser.js", "bibtex.js" ],
|
||||
//"jquery-form": [ "jquery.form.js", "jquery/jquery.form.js" ],
|
||||
//"jquery-autocomplete": [ "src/jquery.autocomplete.js", "jquery/jquery.autocomplete.js" ],
|
||||
//"select2": [ "select2.js", "jquery/select2.js" ],
|
||||
//"jStorage": [ "jstorage.js", "jquery/jstorage.js" ],
|
||||
//"jquery.cookie": [ "", "jquery/jquery.cookie.js" ],
|
||||
//"dynatree": [ "dist/jquery.dynatree.js", "jquery/jquery.dynatree.js" ],
|
||||
//"jquery-mousewheel": [ "jquery.mousewheel.js", "jquery/jquery.mousewheel.js" ],
|
||||
//"jquery.event.drag-drop": [
|
||||
// [ "event.drag/jquery.event.drag.js", "jquery/jquery.event.drag.js" ],
|
||||
// [ "event.drag/jquery.event.drop.js", "jquery/jquery.event.drop.js" ]
|
||||
//],
|
||||
|
||||
// these are complicated by additional css/less
|
||||
//"toastr": [ "toastr.js", "toastr.js" ],
|
||||
//"wymeditor": [ "dist/wymeditor/jquery.wymeditor.js", "jquery/jquery.wymeditor.js" ],
|
||||
//"jstree": [ "jstree.js", "jquery/jstree.js" ],
|
||||
|
||||
// these have been customized by Galaxy
|
||||
//"bootstrap": [ "dist/js/bootstrap.js", "bootstrap.js" ],
|
||||
//"jquery-ui": [
|
||||
// // multiple components now
|
||||
// [ "", "jquery/jquery-ui.js" ]
|
||||
//],
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks( 'grunt-contrib-watch' );
|
||||
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
|
||||
grunt.loadNpmTasks( 'grunt-bower-install-simple');
|
||||
|
||||
grunt.registerTask( 'default', [ 'uglify' ] );
|
||||
|
||||
// -------------------------------------------------------------------------- copy,pack only those changed
|
||||
// adapted from grunt-contrib-watch jslint example
|
||||
//TODO: a bit hacky and there's prob. a better way
|
||||
//NOTE: copy will fail silently if a file isn't found
|
||||
|
||||
// outer scope variable for the event handler and onChange fn - begin with empty hash
|
||||
var changedFiles = Object.create(null);
|
||||
|
||||
// when files are changed, set the copy src and packScripts target to the filenames of the updated files
|
||||
var onChange = grunt.util._.debounce(function() {
|
||||
grunt.log.writeln( 'onChange, changedFiles:', Object.keys( changedFiles ) );
|
||||
grunt.config( 'uglify.target.files', [{
|
||||
expand : true,
|
||||
cwd : 'galaxy/scripts/',
|
||||
src : '**',
|
||||
dest : '../static/scripts'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
cwd : SRC_SYMLINK,
|
||||
src : Object.keys( changedFiles ),
|
||||
dest : DIST_PATH
|
||||
}]);
|
||||
changedFiles = Object.create(null);
|
||||
}, 200);
|
||||
|
||||
// use 'grunt pack' to call pack_scripts.py to pack all or selected files in static/scripts
|
||||
exec: {
|
||||
packScripts: {
|
||||
cwd: '../static/scripts',
|
||||
target: [],
|
||||
cmd: function(){
|
||||
var targets = grunt.config( 'exec.packScripts.target' );
|
||||
// if nothing was passed in pack all scripts
|
||||
if( !targets.length ){
|
||||
return './pack_scripts.py';
|
||||
}
|
||||
grunt.event.on( 'watch', function( action, filepath ) {
|
||||
// store each filepath in a Files obj, the debounced fn above will use it as an aggregate list for copying
|
||||
// we need to take galaxy/scripts out of the filepath or it will be copied to the wrong loc
|
||||
filepath = filepath.replace( SRC_SYMLINK + '/', '' );
|
||||
grunt.log.writeln( 'on.watch, filepath:', filepath );
|
||||
changedFiles[filepath] = action;
|
||||
onChange();
|
||||
});
|
||||
|
||||
grunt.log.write( 'packing: ' + targets + '\n' );
|
||||
return targets.map( function( target ){
|
||||
return './pack_scripts.py ' + target;
|
||||
}).join( '; ' );
|
||||
// -------------------------------------------------------------------------- fetch/update external libraries
|
||||
/** copy external libraries from bower components to scripts/libs */
|
||||
function copyLibs(){
|
||||
var LIB_PATH = DEV_PATH + '/libs/',
|
||||
libraryLocations = grunt.config( 'libraryLocations' );
|
||||
for( var libName in libraryLocations ){
|
||||
if( libraryLocations.hasOwnProperty( libName ) ){
|
||||
var BOWER_DIR = 'bower_components',
|
||||
location = libraryLocations[ libName ],
|
||||
source = [ BOWER_DIR, libName, location[0] ].join( '/' ),
|
||||
destination = LIB_PATH + location[1];
|
||||
grunt.log.writeln( source + ' -> ' + destination );
|
||||
grunt.file.copy( source, destination );
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// use 'grunt watch' (from a new tab in your terminal) to have grunt re-copy changed files automatically
|
||||
watch: {
|
||||
// watch for changes in the src dir
|
||||
files: [ 'galaxy/scripts/**' ],
|
||||
tasks: [ 'copy', 'pack' ],
|
||||
options: {
|
||||
spawn: false
|
||||
}
|
||||
},
|
||||
|
||||
// call bower to install libraries and other external resources
|
||||
"bower-install-simple" : {
|
||||
options: {
|
||||
color: true
|
||||
},
|
||||
"prod": {
|
||||
options: {
|
||||
production: true
|
||||
}
|
||||
},
|
||||
"dev": {
|
||||
options: {
|
||||
production: false
|
||||
}
|
||||
}
|
||||
},
|
||||
// where to move fetched bower components into the build structure (libName: [ bower-location, libs-location ])
|
||||
libraryLocations : {
|
||||
"jquery": [ "dist/jquery.js", "jquery/jquery.js" ],
|
||||
"jquery-migrate": [ "jquery-migrate.js", "jquery/jquery.migrate.js" ],
|
||||
"traceKit": [ "tracekit.js", "tracekit.js" ],
|
||||
"ravenjs": [ "dist/raven.js", "raven.js" ],
|
||||
"underscore": [ "underscore.js", "underscore.js" ],
|
||||
"handlebars": [ "handlebars.runtime.js", "handlebars.runtime.js" ],
|
||||
"lunr.js": [ "lunr.js", "lunr.js" ],
|
||||
"backbone": [ "backbone.js", "backbone/backbone.js" ],
|
||||
|
||||
// these need to be updated and tested
|
||||
//"require": [ "build/require.js", "require.js" ],
|
||||
//"d3": [ "d3.js", "d3.js" ],
|
||||
//"farbtastic": [ "src/farbtastic.js", "farbtastic.js" ],
|
||||
//"jQTouch": [ "src/reference/jqtouch.js", "jquery/jqtouch.js" ],
|
||||
//"bib2json": [ "Parser.js", "bibtex.js" ],
|
||||
//"jquery-form": [ "jquery.form.js", "jquery/jquery.form.js" ],
|
||||
//"jquery-autocomplete": [ "src/jquery.autocomplete.js", "jquery/jquery.autocomplete.js" ],
|
||||
//"select2": [ "select2.js", "jquery/select2.js" ],
|
||||
//"jStorage": [ "jstorage.js", "jquery/jstorage.js" ],
|
||||
//"jquery.cookie": [ "", "jquery/jquery.cookie.js" ],
|
||||
//"dynatree": [ "dist/jquery.dynatree.js", "jquery/jquery.dynatree.js" ],
|
||||
//"jquery-mousewheel": [ "jquery.mousewheel.js", "jquery/jquery.mousewheel.js" ],
|
||||
//"jquery.event.drag-drop": [
|
||||
// [ "event.drag/jquery.event.drag.js", "jquery/jquery.event.drag.js" ],
|
||||
// [ "event.drag/jquery.event.drop.js", "jquery/jquery.event.drop.js" ]
|
||||
//],
|
||||
|
||||
// these are complicated by additional css/less
|
||||
//"toastr": [ "toastr.js", "toastr.js" ],
|
||||
//"wymeditor": [ "dist/wymeditor/jquery.wymeditor.js", "jquery/jquery.wymeditor.js" ],
|
||||
//"jstree": [ "jstree.js", "jquery/jstree.js" ],
|
||||
|
||||
// these have been customized by Galaxy
|
||||
//"bootstrap": [ "dist/js/bootstrap.js", "bootstrap.js" ],
|
||||
//"jquery-ui": [
|
||||
// // multiple components now
|
||||
// [ "", "jquery/jquery-ui.js" ]
|
||||
//],
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks( 'grunt-contrib-watch' );
|
||||
grunt.loadNpmTasks( 'grunt-contrib-copy');
|
||||
grunt.loadNpmTasks( 'grunt-bower-install-simple');
|
||||
grunt.loadNpmTasks( 'grunt-exec' );
|
||||
|
||||
grunt.registerTask( 'pack', [ 'exec' ] );
|
||||
grunt.registerTask( 'default', [ 'copy:main', 'pack' ] );
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------- copy,pack only those changed
|
||||
// adapted from grunt-contrib-watch jslint example
|
||||
//TODO: a bit hacky and there's prob. a better way
|
||||
//NOTE: copy will fail silently if a file isn't found
|
||||
|
||||
// outer scope variable for the event handler and onChange fn - begin with empty hash
|
||||
var changedFiles = Object.create(null);
|
||||
|
||||
// when files are changed, set the copy src and packScripts target to the filenames of the updated files
|
||||
var onChange = grunt.util._.debounce(function() {
|
||||
grunt.config( 'copy.main.files', [{
|
||||
expand: true,
|
||||
cwd: 'galaxy/scripts',
|
||||
src: Object.keys( changedFiles ),
|
||||
dest: '../static/scripts/'
|
||||
}]);
|
||||
grunt.config( 'exec.packScripts.target', Object.keys( changedFiles ) );
|
||||
changedFiles = Object.create(null);
|
||||
}, 200);
|
||||
|
||||
grunt.event.on('watch', function(action, filepath) {
|
||||
// store each filepath in a Files obj, the debounced fn above will use it as an aggregate list for copying
|
||||
// we need to take galaxy/scripts out of the filepath or it will be copied to the wrong loc
|
||||
filepath = filepath.replace( /galaxy\/scripts\//, '' );
|
||||
changedFiles[filepath] = action;
|
||||
onChange();
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------- fetch/update external libraries
|
||||
/** copy external libraries from bower components to scripts/libs */
|
||||
function copyLibs(){
|
||||
var libraryLocations = grunt.config( 'libraryLocations' );
|
||||
for( var libName in libraryLocations ){
|
||||
if( libraryLocations.hasOwnProperty( libName ) ){
|
||||
|
||||
var BOWER_DIR = 'bower_components',
|
||||
location = libraryLocations[ libName ],
|
||||
source = [ BOWER_DIR, libName, location[0] ].join( '/' ),
|
||||
destination = 'galaxy/scripts/libs/' + location[1];
|
||||
grunt.log.writeln( source + ' -> ' + destination );
|
||||
grunt.file.copy( source, destination );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grunt.registerTask( 'copy-libs', 'copy external libraries to src', copyLibs );
|
||||
grunt.registerTask( 'install-libs', 'fetch external libraries and copy to src',
|
||||
grunt.registerTask( 'copy-libs', 'copy external libraries to src', copyLibs );
|
||||
grunt.registerTask( 'install-libs', 'fetch external libraries and copy to src',
|
||||
[ 'bower-install-simple:prod', 'copy-libs' ] );
|
||||
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-bower-install-simple": "^1.1.0",
|
||||
"grunt-contrib-copy": "^0.5.0",
|
||||
"grunt-contrib-uglify": "^0.8.0",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-exec": "^0.4.6",
|
||||
"grunt-webpack": "^1.0.8",
|
||||
|
||||
@@ -523,12 +523,6 @@ nglims_config_file = tool-data/nglims.yaml
|
||||
#static_style_dir = static/june_2007_style/blue
|
||||
#static_robots_txt = static/robots.txt
|
||||
|
||||
# Pack javascript at launch (/static/scripts/*.js)
|
||||
# This only happens if the modified timestamp of the source .js is newer
|
||||
# than the version (if it exists) in /static/scripts/packed/
|
||||
# Note that this requires java > 1.4 for executing yuicompressor.jar
|
||||
#pack_scripts = False
|
||||
|
||||
# Cloud Launch
|
||||
|
||||
#enable_cloud_launch = False
|
||||
@@ -798,7 +792,7 @@ use_interactive = True
|
||||
|
||||
# Expose user list. Setting this to true will expose the user list to authenticated users. This
|
||||
# makes sharing datasets in smaller galaxy instances much easier as they can type a name/email and
|
||||
# have the correct user show up. This makes less sense on large public galaxy instances where
|
||||
# have the correct user show up. This makes less sense on large public galaxy instances where
|
||||
# that data shouldn't be exposed. For semi-public galaxies, it may make sense to expose just the
|
||||
# username and not email, or vice versa.
|
||||
#expose_user_name = False
|
||||
|
||||
@@ -101,9 +101,6 @@ def app_factory( global_conf, **kwargs ):
|
||||
log.error("Static middleware is enabled in your configuration but this is a uwsgi process. Refusing to wrap in static middleware.")
|
||||
else:
|
||||
webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=[ app.visualizations_registry ], **kwargs )
|
||||
if asbool(kwargs.get('pack_scripts', False)):
|
||||
log.warn( "The 'pack_scripts' option is deprecated" )
|
||||
pack_scripts()
|
||||
# Close any pooled database connections before forking
|
||||
try:
|
||||
galaxy.model.mapping.metadata.engine.connection_provider._pool.dispose()
|
||||
@@ -530,21 +527,6 @@ def populate_api_routes( webapp, app ):
|
||||
webapp.mapper.connect( "create", "/api/metrics", controller="metrics",
|
||||
action="create", conditions=dict( method=["POST"] ) )
|
||||
|
||||
|
||||
def pack_scripts():
|
||||
from glob import glob
|
||||
from subprocess import call
|
||||
cmd = "java -jar scripts/yuicompressor.jar --type js static/scripts/%(fname)s -o static/scripts/packed/%(fname)s"
|
||||
raw_js = [os.path.basename(g) for g in glob( "static/scripts/*.js" )]
|
||||
for fname in raw_js:
|
||||
if os.path.exists('static/scripts/packed/%s' % fname):
|
||||
if os.path.getmtime('static/scripts/packed/%s' % fname) > os.path.getmtime('static/scripts/%s' % fname):
|
||||
continue # Skip, packed is newer than source.
|
||||
d = dict( fname=fname )
|
||||
log.info("%(fname)s --> packed/%(fname)s" % d)
|
||||
call( cmd % d, shell=True )
|
||||
|
||||
|
||||
def _add_item_tags_controller( webapp, name_prefix, path_prefix, **kwd ):
|
||||
# Not just using map.resources because actions should be based on name not id
|
||||
controller = "%stags" % name_prefix
|
||||
|
||||
+2
-15
@@ -1,15 +1,2 @@
|
||||
define( ["libs/backbone/backbone"], function( Backbone ) {
|
||||
|
||||
var Base = function() {
|
||||
if( this.initialize ) {
|
||||
this.initialize.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
Base.extend = Backbone.Model.extend;
|
||||
|
||||
return {
|
||||
Base: Base,
|
||||
Backbone: Backbone
|
||||
};
|
||||
|
||||
});
|
||||
define(["libs/backbone/backbone"],function(a){var b=function(){this.initialize&&this.initialize.apply(this,arguments)};return b.extend=a.Model.extend,{Base:b,Backbone:a}});
|
||||
//# sourceMappingURL=../maps/base.js.map
|
||||
@@ -1,160 +1,2 @@
|
||||
define([
|
||||
'mvc/user/user-model',
|
||||
'utils/metrics-logger',
|
||||
'utils/add-logging',
|
||||
'utils/localization',
|
||||
'bootstrapped-data'
|
||||
], function( userModel, metricsLogger, addLogging, localize, bootstrapped ){
|
||||
// ============================================================================
|
||||
/** Base galaxy client-side application.
|
||||
* Iniitializes:
|
||||
* logger : the logger/metrics-logger
|
||||
* localize : the string localizer
|
||||
* config : the current configuration (any k/v in
|
||||
* galaxy.ini available from the configuration API)
|
||||
* user : the current user (as a mvc/user/user-model)
|
||||
*/
|
||||
function GalaxyApp( options ){
|
||||
var self = this;
|
||||
return self._init( options || {} );
|
||||
}
|
||||
|
||||
// add logging shortcuts for this object
|
||||
addLogging( GalaxyApp, 'GalaxyApp' );
|
||||
|
||||
/** default options */
|
||||
GalaxyApp.prototype.defaultOptions = {
|
||||
/** monkey patch attributes from existing window.Galaxy object? */
|
||||
patchExisting : true,
|
||||
/** root url of this app */
|
||||
// move to self.root?
|
||||
root : '/'
|
||||
};
|
||||
|
||||
/** initalize options and sub-components */
|
||||
GalaxyApp.prototype._init = function init( options ){
|
||||
var self = this;
|
||||
_.extend( self, Backbone.Events );
|
||||
|
||||
self._processOptions( options );
|
||||
self.debug( 'GalaxyApp.options: ', self.options );
|
||||
|
||||
self._patchGalaxy( window.Galaxy );
|
||||
|
||||
self._initLogger( options.loggerOptions || {} );
|
||||
self.debug( 'GalaxyApp.logger: ', self.logger );
|
||||
|
||||
self._initLocale();
|
||||
self.debug( 'GalaxyApp.localize: ', self.localize );
|
||||
|
||||
self.config = options.config || bootstrapped.config || {};
|
||||
self.debug( 'GalaxyApp.config: ', self.config );
|
||||
|
||||
self._initUser( options.user || bootstrapped.user || {} );
|
||||
self.debug( 'GalaxyApp.user: ', self.user );
|
||||
|
||||
//TODO: temp
|
||||
self.trigger( 'ready', self );
|
||||
//if( typeof options.onload === 'function' ){
|
||||
// options.onload();
|
||||
//}
|
||||
|
||||
self._setUpListeners();
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
/** add an option from options if the key matches an option in defaultOptions */
|
||||
GalaxyApp.prototype._processOptions = function _processOptions( options ){
|
||||
var self = this,
|
||||
defaults = self.defaultOptions;
|
||||
self.debug( '_processOptions: ', options );
|
||||
|
||||
self.options = {};
|
||||
for( var k in defaults ){
|
||||
if( defaults.hasOwnProperty( k ) ){
|
||||
self.options[ k ] = ( options.hasOwnProperty( k ) )?( options[ k ] ):( defaults[ k ] );
|
||||
}
|
||||
}
|
||||
return self;
|
||||
};
|
||||
|
||||
/** add an option from options if the key matches an option in defaultOptions */
|
||||
GalaxyApp.prototype._patchGalaxy = function _processOptions( patchWith ){
|
||||
var self = this;
|
||||
// in case req or plain script tag order has created a prev. version of the Galaxy obj...
|
||||
if( self.options.patchExisting && patchWith ){
|
||||
self.debug( 'found existing Galaxy object:', patchWith );
|
||||
// ...(for now) monkey patch any added attributes that the previous Galaxy may have had
|
||||
//TODO: move those attributes to more formal assignment in GalaxyApp
|
||||
for( var k in patchWith ){
|
||||
if( patchWith.hasOwnProperty( k ) ){
|
||||
self.debug( '\t patching in ' + k + ' to Galaxy' );
|
||||
self[ k ] = patchWith[ k ];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** set up the metrics logger (utils/metrics-logger) and pass loggerOptions */
|
||||
GalaxyApp.prototype._initLogger = function _initLogger( loggerOptions ){
|
||||
var self = this;
|
||||
self.debug( '_initLogger:', loggerOptions );
|
||||
self.logger = new metricsLogger.MetricsLogger( loggerOptions );
|
||||
return self;
|
||||
};
|
||||
|
||||
/** add the localize fn to this object and the window namespace (as '_l') */
|
||||
GalaxyApp.prototype._initLocale = function _initLocale( options ){
|
||||
var self = this;
|
||||
self.debug( '_initLocale:', options );
|
||||
self.localize = localize;
|
||||
// add to window as global shortened alias
|
||||
window._l = self.localize;
|
||||
return self;
|
||||
};
|
||||
|
||||
/** set up the current user as a Backbone model (mvc/user/user-model) */
|
||||
GalaxyApp.prototype._initUser = function _initUser( userJSON ){
|
||||
var self = this;
|
||||
self.debug( '_initUser:', userJSON );
|
||||
self.user = new userModel.User( userJSON );
|
||||
//TODO: temp - old alias
|
||||
self.currUser = self.user;
|
||||
return self;
|
||||
};
|
||||
|
||||
/** Set up DOM/jQuery/Backbone event listeners enabled for all pages */
|
||||
GalaxyApp.prototype._setUpListeners = function _setUpListeners(){
|
||||
var self = this;
|
||||
|
||||
// hook to jq beforeSend to record the most recent ajax call and cache some data about it
|
||||
/** cached info about the last ajax call made through jQuery */
|
||||
self.lastAjax = {};
|
||||
$( document ).bind( 'ajaxSend', function( ev, xhr, options ){
|
||||
var data = options.data;
|
||||
try {
|
||||
data = JSON.parse( data );
|
||||
} catch( err ){}
|
||||
|
||||
self.lastAjax = {
|
||||
url : location.href.slice( 0, -1 ) + options.url,
|
||||
data : data
|
||||
};
|
||||
//TODO:?? we might somehow manage to *retry* ajax using either this hook or Backbone.sync
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/** string rep */
|
||||
GalaxyApp.prototype.toString = function toString(){
|
||||
var userEmail = this.user.get( 'email' ) || '(anonymous)';
|
||||
return 'GalaxyApp(' + userEmail + ')';
|
||||
};
|
||||
|
||||
|
||||
// ============================================================================
|
||||
return {
|
||||
GalaxyApp : GalaxyApp
|
||||
};
|
||||
});
|
||||
define(["mvc/user/user-model","utils/metrics-logger","utils/add-logging","utils/localization","bootstrapped-data"],function(a,b,c,d,e){function f(a){var b=this;return b._init(a||{})}return c(f,"GalaxyApp"),f.prototype.defaultOptions={patchExisting:!0,root:"/"},f.prototype._init=function(a){var b=this;return _.extend(b,Backbone.Events),b._processOptions(a),b.debug("GalaxyApp.options: ",b.options),b._patchGalaxy(window.Galaxy),b._initLogger(a.loggerOptions||{}),b.debug("GalaxyApp.logger: ",b.logger),b._initLocale(),b.debug("GalaxyApp.localize: ",b.localize),b.config=a.config||e.config||{},b.debug("GalaxyApp.config: ",b.config),b._initUser(a.user||e.user||{}),b.debug("GalaxyApp.user: ",b.user),b.trigger("ready",b),b._setUpListeners(),b},f.prototype._processOptions=function(a){var b=this,c=b.defaultOptions;b.debug("_processOptions: ",a),b.options={};for(var d in c)c.hasOwnProperty(d)&&(b.options[d]=a.hasOwnProperty(d)?a[d]:c[d]);return b},f.prototype._patchGalaxy=function(a){var b=this;if(b.options.patchExisting&&a){b.debug("found existing Galaxy object:",a);for(var c in a)a.hasOwnProperty(c)&&(b.debug(" patching in "+c+" to Galaxy"),b[c]=a[c])}},f.prototype._initLogger=function(a){var c=this;return c.debug("_initLogger:",a),c.logger=new b.MetricsLogger(a),c},f.prototype._initLocale=function(a){var b=this;return b.debug("_initLocale:",a),b.localize=d,window._l=b.localize,b},f.prototype._initUser=function(b){var c=this;return c.debug("_initUser:",b),c.user=new a.User(b),c.currUser=c.user,c},f.prototype._setUpListeners=function(){var a=this;a.lastAjax={},$(document).bind("ajaxSend",function(b,c,d){var e=d.data;try{e=JSON.parse(e)}catch(f){}a.lastAjax={url:location.href.slice(0,-1)+d.url,data:e}})},f.prototype.toString=function(){var a=this.user.get("email")||"(anonymous)";return"GalaxyApp("+a+")"},{GalaxyApp:f}});
|
||||
//# sourceMappingURL=../maps/galaxy-app-base.js.map
|
||||
@@ -1,368 +1,2 @@
|
||||
/**
|
||||
* JQuery extension for tagging with autocomplete.
|
||||
* @author: Jeremy Goecks
|
||||
* @require: jquery.autocomplete plugin
|
||||
*/
|
||||
//
|
||||
// Initialize "tag click functions" for tags.
|
||||
//
|
||||
function init_tag_click_function(tag_elt, click_func) {
|
||||
$(tag_elt).find('.tag-name').each( function() {
|
||||
$(this).click( function() {
|
||||
var tag_str = $(this).text();
|
||||
var tag_name_and_value = tag_str.split(":");
|
||||
click_func(tag_name_and_value[0], tag_name_and_value[1]);
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
jQuery.fn.autocomplete_tagging = function(options) {
|
||||
|
||||
var defaults = {
|
||||
get_toggle_link_text_fn: function(tags) {
|
||||
var text = "";
|
||||
var num_tags = obj_length(tags);
|
||||
if (num_tags > 0) {
|
||||
text = num_tags + (num_tags > 1 ? " Tags" : " Tag");
|
||||
} else {
|
||||
text = "Add tags";
|
||||
}
|
||||
return text;
|
||||
},
|
||||
tag_click_fn : function (name, value) {},
|
||||
editable: true,
|
||||
input_size: 20,
|
||||
in_form: false,
|
||||
tags : {},
|
||||
use_toggle_link: true,
|
||||
item_id: "",
|
||||
add_tag_img: "",
|
||||
add_tag_img_rollover: "",
|
||||
delete_tag_img: "",
|
||||
ajax_autocomplete_tag_url: "",
|
||||
ajax_retag_url: "",
|
||||
ajax_delete_tag_url: "",
|
||||
ajax_add_tag_url: ""
|
||||
};
|
||||
|
||||
var settings = jQuery.extend(defaults, options);
|
||||
|
||||
//
|
||||
// Initalize object's elements.
|
||||
//
|
||||
|
||||
// Get elements for this object. For this_obj, assume the last element with the id is the "this"; this is somewhat of a hack to address the problem
|
||||
// that there may be two tagging elements for a single item if there are both community and individual tags for an element.
|
||||
var this_obj = $(this);
|
||||
var tag_area = this_obj.find('.tag-area');
|
||||
var toggle_link = this_obj.find('.toggle-link');
|
||||
var tag_input_field = this_obj.find('.tag-input');
|
||||
var add_tag_button = this_obj.find('.add-tag-button');
|
||||
|
||||
// Initialize toggle link.
|
||||
toggle_link.click( function() {
|
||||
// Take special actions depending on whether toggle is showing or hiding link.
|
||||
var after_toggle_fn;
|
||||
if (tag_area.is(":hidden")) {
|
||||
after_toggle_fn = function() {
|
||||
// If there are no tags, go right to editing mode by generating a click on the area.
|
||||
var num_tags = $(this).find('.tag-button').length;
|
||||
if (num_tags === 0) {
|
||||
tag_area.click();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
after_toggle_fn = function() {
|
||||
tag_area.blur();
|
||||
};
|
||||
}
|
||||
tag_area.slideToggle("fast", after_toggle_fn);
|
||||
return $(this);
|
||||
});
|
||||
|
||||
// Initialize tag input field.
|
||||
if (settings.editable) {
|
||||
tag_input_field.hide();
|
||||
}
|
||||
tag_input_field.keyup( function(e) {
|
||||
if ( e.keyCode === 27 ) {
|
||||
// Escape key
|
||||
$(this).trigger( "blur" );
|
||||
} else if (
|
||||
( e.keyCode === 13 ) || // Return Key
|
||||
( e.keyCode === 188 ) || // Comma
|
||||
( e.keyCode === 32 ) // Space
|
||||
) {
|
||||
//
|
||||
// Check input.
|
||||
//
|
||||
|
||||
var new_value = this.value;
|
||||
|
||||
// Suppress space after a ":"
|
||||
if ( new_value.indexOf(": ", new_value.length - 2) !== -1) {
|
||||
this.value = new_value.substring(0, new_value.length-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove trigger keys from input.
|
||||
if ( (e.keyCode === 188) || (e.keyCode === 32) ) {
|
||||
new_value = new_value.substring( 0 , new_value.length - 1 );
|
||||
}
|
||||
|
||||
// Trim whitespace.
|
||||
new_value = $.trim(new_value);
|
||||
|
||||
// Too short?
|
||||
if (new_value.length < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// New tag OK - apply it.
|
||||
//
|
||||
|
||||
this.value = ""; // Reset text field now that tag is being added
|
||||
|
||||
// Add button for tag after all other tag buttons.
|
||||
var new_tag_button = build_tag_button(new_value);
|
||||
var tag_buttons = tag_area.children(".tag-button");
|
||||
if (tag_buttons.length !== 0) {
|
||||
var last_tag_button = tag_buttons.slice(tag_buttons.length-1);
|
||||
last_tag_button.after(new_tag_button);
|
||||
} else {
|
||||
tag_area.prepend(new_tag_button);
|
||||
}
|
||||
|
||||
// Add tag to internal list.
|
||||
var tag_name_and_value = new_value.split(":");
|
||||
settings.tags[tag_name_and_value[0]] = tag_name_and_value[1];
|
||||
|
||||
// Update toggle link text.
|
||||
var new_text = settings.get_toggle_link_text_fn(settings.tags);
|
||||
toggle_link.text(new_text);
|
||||
|
||||
// Commit tag to server.
|
||||
var zz = $(this);
|
||||
$.ajax({
|
||||
url: settings.ajax_add_tag_url,
|
||||
data: { new_tag: new_value },
|
||||
error: function() {
|
||||
// Failed. Roll back changes and show alert.
|
||||
new_tag_button.remove();
|
||||
delete settings.tags[tag_name_and_value[0]];
|
||||
var new_text = settings.get_toggle_link_text_fn(settings.tags);
|
||||
toggle_link.text(new_text);
|
||||
alert( "Add tag failed" );
|
||||
},
|
||||
success: function() {
|
||||
// Flush autocomplete cache because it's not out of date.
|
||||
// TODO: in the future, we could remove the particular item
|
||||
// that was chosen from the cache rather than flush it.
|
||||
zz.data('autocompleter').cacheFlush();
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Add autocomplete to input.
|
||||
var format_item_func = function(key, row_position, num_rows, value, search_term) {
|
||||
var tag_name_and_value = value.split(":");
|
||||
return (tag_name_and_value.length === 1 ? tag_name_and_value[0] : tag_name_and_value[1]);
|
||||
};
|
||||
var autocomplete_options = { selectFirst: false, formatItem: format_item_func,
|
||||
autoFill: false, highlight: false };
|
||||
tag_input_field.autocomplete(settings.ajax_autocomplete_tag_url, autocomplete_options);
|
||||
|
||||
|
||||
// Initialize delete tag images for current tags.
|
||||
this_obj.find('.delete-tag-img').each(function() {
|
||||
init_delete_tag_image( $(this) );
|
||||
});
|
||||
|
||||
|
||||
// Initialize tag click function.
|
||||
init_tag_click_function($(this), settings.tag_click_fn);
|
||||
|
||||
// Initialize "add tag" button.
|
||||
add_tag_button.click( function() {
|
||||
$(this).hide();
|
||||
|
||||
// Clicking on button is the same as clicking on the tag area.
|
||||
tag_area.click();
|
||||
return false;
|
||||
});
|
||||
|
||||
//
|
||||
// Set up tag area interactions; these are needed only if tags are editable.
|
||||
//
|
||||
if (settings.editable) {
|
||||
// When the tag area blurs, go to "view tag" mode.
|
||||
tag_area.bind("blur", function(e) {
|
||||
if (obj_length(settings.tags) > 0) {
|
||||
add_tag_button.show();
|
||||
tag_input_field.hide();
|
||||
tag_area.removeClass("active-tag-area");
|
||||
// tag_area.addClass("tooltip");
|
||||
} else {
|
||||
// No tags, so do nothing to ensure that input is still visible.
|
||||
}
|
||||
});
|
||||
|
||||
// On click, enable user to add tags.
|
||||
tag_area.click( function(e) {
|
||||
var is_active = $(this).hasClass("active-tag-area");
|
||||
|
||||
// If a "delete image" object was pressed and area is inactive, do nothing.
|
||||
if ($(e.target).hasClass("delete-tag-img") && !is_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a "tag name" object was pressed and area is inactive, do nothing.
|
||||
if ($(e.target).hasClass("tag-name") && !is_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove tooltip.
|
||||
// $(this).removeClass("tooltip");
|
||||
|
||||
// Hide add tag button, show tag_input field. Change background to show
|
||||
// area is active.
|
||||
$(this).addClass("active-tag-area");
|
||||
add_tag_button.hide();
|
||||
tag_input_field.show();
|
||||
tag_input_field.focus();
|
||||
|
||||
// Add handler to document that will call blur when the tag area is blurred;
|
||||
// a tag area is blurred when a user clicks on an element outside the area.
|
||||
var handle_document_click = function(e) {
|
||||
var check_click = function(tag_area, target) {
|
||||
var tag_area_id = tag_area.attr("id");
|
||||
// Blur the tag area if the element clicked on is not in the tag area.
|
||||
if (target !== tag_area) {
|
||||
tag_area.blur();
|
||||
$(window).unbind("click.tagging_blur");
|
||||
$(this).addClass("tooltip");
|
||||
}
|
||||
};
|
||||
check_click(tag_area, $(e.target));
|
||||
};
|
||||
// TODO: we should attach the click handler to all frames in order to capture
|
||||
// clicks outside the frame that this element is in.
|
||||
//window.parent.document.onclick = handle_document_click;
|
||||
//var temp = $(window.parent.document.body).contents().find("iframe").html();
|
||||
//alert(temp);
|
||||
//$(document).parent().click(handle_document_click);
|
||||
$(window).bind("click.tagging_blur", handle_document_click);
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// If using toggle link, hide the tag area. Otherwise, show the tag area.
|
||||
if (settings.use_toggle_link) {
|
||||
tag_area.hide();
|
||||
}
|
||||
|
||||
//
|
||||
// Helper functions.
|
||||
//
|
||||
|
||||
//
|
||||
// Collapse tag name + value into a single string.
|
||||
//
|
||||
function build_tag_str(tag_name, tag_value) {
|
||||
return tag_name + ( tag_value ? ":" + tag_value : "");
|
||||
}
|
||||
|
||||
|
||||
// Initialize a "delete tag image": when click, delete tag from UI and send delete request to server.
|
||||
function init_delete_tag_image(delete_img) {
|
||||
$(delete_img).mouseenter( function () {
|
||||
$(this).attr("src", settings.delete_tag_img_rollover);
|
||||
});
|
||||
$(delete_img).mouseleave( function () {
|
||||
$(this).attr("src", settings.delete_tag_img);
|
||||
});
|
||||
$(delete_img).click( function () {
|
||||
// Tag button is image's parent.
|
||||
var tag_button = $(this).parent();
|
||||
|
||||
// Get tag name, value.
|
||||
var tag_name_elt = tag_button.find(".tag-name").eq(0);
|
||||
var tag_str = tag_name_elt.text();
|
||||
var tag_name_and_value = tag_str.split(":");
|
||||
var tag_name = tag_name_and_value[0];
|
||||
var tag_value = tag_name_and_value[1];
|
||||
|
||||
var prev_button = tag_button.prev();
|
||||
tag_button.remove();
|
||||
|
||||
// Remove tag from local list for consistency.
|
||||
delete settings.tags[tag_name];
|
||||
|
||||
// Update toggle link text.
|
||||
var new_text = settings.get_toggle_link_text_fn(settings.tags);
|
||||
toggle_link.text(new_text);
|
||||
|
||||
// Delete tag.
|
||||
$.ajax({
|
||||
url: settings.ajax_delete_tag_url,
|
||||
data: { tag_name: tag_name },
|
||||
error: function() {
|
||||
// Failed. Roll back changes and show alert.
|
||||
settings.tags[tag_name] = tag_value;
|
||||
if (prev_button.hasClass("tag-button")) {
|
||||
prev_button.after(tag_button);
|
||||
} else {
|
||||
tag_area.prepend(tag_button);
|
||||
}
|
||||
alert( "Remove tag failed" );
|
||||
|
||||
toggle_link.text(settings.get_toggle_link_text_fn(settings.tags));
|
||||
|
||||
// TODO: no idea why it's necessary to set this up again.
|
||||
delete_img.mouseenter( function () {
|
||||
$(this).attr("src", settings.delete_tag_img_rollover);
|
||||
});
|
||||
delete_img.mouseleave( function () {
|
||||
$(this).attr("src", settings.delete_tag_img);
|
||||
});
|
||||
},
|
||||
success: function() {}
|
||||
});
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Function that builds a tag button.
|
||||
//
|
||||
function build_tag_button(tag_str) {
|
||||
// Build "delete tag" image.
|
||||
var delete_img = $("<img/>").attr("src", settings.delete_tag_img).addClass("delete-tag-img");
|
||||
init_delete_tag_image(delete_img);
|
||||
|
||||
// Build tag button.
|
||||
var tag_name_elt = $("<span>").text(tag_str).addClass("tag-name");
|
||||
tag_name_elt.click( function() {
|
||||
var tag_name_and_value = tag_str.split(":");
|
||||
settings.tag_click_fn(tag_name_and_value[0], tag_name_and_value[1]);
|
||||
return true;
|
||||
});
|
||||
|
||||
var tag_button = $("<span></span>").addClass("tag-button");
|
||||
tag_button.append(tag_name_elt);
|
||||
// Allow delete only if element is editable.
|
||||
if (settings.editable) {
|
||||
tag_button.append(delete_img);
|
||||
}
|
||||
|
||||
return tag_button;
|
||||
}
|
||||
|
||||
};
|
||||
function init_tag_click_function(a,b){$(a).find(".tag-name").each(function(){$(this).click(function(){var a=$(this).text(),c=a.split(":");return b(c[0],c[1]),!0})})}jQuery.fn.autocomplete_tagging=function(a){function b(a){$(a).mouseenter(function(){$(this).attr("src",e.delete_tag_img_rollover)}),$(a).mouseleave(function(){$(this).attr("src",e.delete_tag_img)}),$(a).click(function(){var b=$(this).parent(),c=b.find(".tag-name").eq(0),d=c.text(),f=d.split(":"),i=f[0],j=f[1],k=b.prev();b.remove(),delete e.tags[i];var l=e.get_toggle_link_text_fn(e.tags);return h.text(l),$.ajax({url:e.ajax_delete_tag_url,data:{tag_name:i},error:function(){e.tags[i]=j,k.hasClass("tag-button")?k.after(b):g.prepend(b),alert("Remove tag failed"),h.text(e.get_toggle_link_text_fn(e.tags)),a.mouseenter(function(){$(this).attr("src",e.delete_tag_img_rollover)}),a.mouseleave(function(){$(this).attr("src",e.delete_tag_img)})},success:function(){}}),!0})}function c(a){var c=$("<img/>").attr("src",e.delete_tag_img).addClass("delete-tag-img");b(c);var d=$("<span>").text(a).addClass("tag-name");d.click(function(){var b=a.split(":");return e.tag_click_fn(b[0],b[1]),!0});var f=$("<span></span>").addClass("tag-button");return f.append(d),e.editable&&f.append(c),f}var d={get_toggle_link_text_fn:function(a){var b="",c=obj_length(a);return b=c>0?c+(c>1?" Tags":" Tag"):"Add tags"},tag_click_fn:function(){},editable:!0,input_size:20,in_form:!1,tags:{},use_toggle_link:!0,item_id:"",add_tag_img:"",add_tag_img_rollover:"",delete_tag_img:"",ajax_autocomplete_tag_url:"",ajax_retag_url:"",ajax_delete_tag_url:"",ajax_add_tag_url:""},e=jQuery.extend(d,a),f=$(this),g=f.find(".tag-area"),h=f.find(".toggle-link"),i=f.find(".tag-input"),j=f.find(".add-tag-button");h.click(function(){var a;return a=g.is(":hidden")?function(){var a=$(this).find(".tag-button").length;0===a&&g.click()}:function(){g.blur()},g.slideToggle("fast",a),$(this)}),e.editable&&i.hide(),i.keyup(function(a){if(27===a.keyCode)$(this).trigger("blur");else if(13===a.keyCode||188===a.keyCode||32===a.keyCode){var b=this.value;if(-1!==b.indexOf(": ",b.length-2))return this.value=b.substring(0,b.length-1),!1;if((188===a.keyCode||32===a.keyCode)&&(b=b.substring(0,b.length-1)),b=$.trim(b),b.length<2)return!1;this.value="";var d=c(b),f=g.children(".tag-button");if(0!==f.length){var i=f.slice(f.length-1);i.after(d)}else g.prepend(d);var j=b.split(":");e.tags[j[0]]=j[1];var k=e.get_toggle_link_text_fn(e.tags);h.text(k);var l=$(this);return $.ajax({url:e.ajax_add_tag_url,data:{new_tag:b},error:function(){d.remove(),delete e.tags[j[0]];var a=e.get_toggle_link_text_fn(e.tags);h.text(a),alert("Add tag failed")},success:function(){l.data("autocompleter").cacheFlush()}}),!1}});var k=function(a,b,c,d){var e=d.split(":");return 1===e.length?e[0]:e[1]},l={selectFirst:!1,formatItem:k,autoFill:!1,highlight:!1};i.autocomplete(e.ajax_autocomplete_tag_url,l),f.find(".delete-tag-img").each(function(){b($(this))}),init_tag_click_function($(this),e.tag_click_fn),j.click(function(){return $(this).hide(),g.click(),!1}),e.editable&&(g.bind("blur",function(){obj_length(e.tags)>0&&(j.show(),i.hide(),g.removeClass("active-tag-area"))}),g.click(function(a){var b=$(this).hasClass("active-tag-area");if($(a.target).hasClass("delete-tag-img")&&!b)return!1;if($(a.target).hasClass("tag-name")&&!b)return!1;$(this).addClass("active-tag-area"),j.hide(),i.show(),i.focus();var c=function(a){var b=function(a,b){a.attr("id");b!==a&&(a.blur(),$(window).unbind("click.tagging_blur"),$(this).addClass("tooltip"))};b(g,$(a.target))};return $(window).bind("click.tagging_blur",c),!1})),e.use_toggle_link&&g.hide()};
|
||||
//# sourceMappingURL=../maps/galaxy.autocom_tagging.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -1,259 +1,2 @@
|
||||
// dependencies
|
||||
define(["galaxy.masthead", "mvc/ui/ui-frames"], function(mod_masthead, Frames) {
|
||||
|
||||
/** Frame manager uses the ui-frames to create the scratch book masthead icon and functionality **/
|
||||
var GalaxyFrame = Backbone.View.extend({
|
||||
// base element
|
||||
el_main: 'body',
|
||||
|
||||
// frame active/disabled
|
||||
active: false,
|
||||
|
||||
// button active
|
||||
button_active: null,
|
||||
|
||||
// button load
|
||||
button_load : null,
|
||||
|
||||
// initialize
|
||||
initialize : function(options) {
|
||||
// add to masthead menu
|
||||
var self = this;
|
||||
|
||||
// create frames
|
||||
this.frames = new Frames.View({
|
||||
visible: false,
|
||||
});
|
||||
|
||||
// add activate icon
|
||||
this.button_active = new mod_masthead.GalaxyMastheadIcon({
|
||||
icon : 'fa-th',
|
||||
tooltip : 'Enable/Disable Scratchbook',
|
||||
onclick : function() { self._activate(); },
|
||||
onunload : function() {
|
||||
if (self.frames.length() > 0) {
|
||||
return "You opened " + self.frames.length() + " frame(s) which will be lost.";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// add to masthead
|
||||
Galaxy.masthead.append(this.button_active);
|
||||
|
||||
// add load icon
|
||||
this.button_load = new mod_masthead.GalaxyMastheadIcon({
|
||||
icon : 'fa-eye',
|
||||
tooltip : 'Show/Hide Scratchbook',
|
||||
onclick : function(e) {
|
||||
if (self.frames.visible) {
|
||||
self.frames.hide();
|
||||
} else {
|
||||
self.frames.show();
|
||||
}
|
||||
},
|
||||
with_number : true
|
||||
});
|
||||
|
||||
// add to masthead
|
||||
Galaxy.masthead.append(this.button_load);
|
||||
|
||||
// create
|
||||
this.setElement(this.frames.$el);
|
||||
|
||||
// append to main
|
||||
$(this.el_main).append(this.$el);
|
||||
|
||||
// refresh menu
|
||||
this.frames.setOnChange(function() {
|
||||
self._refresh();
|
||||
});
|
||||
this._refresh();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a dataset to the frames.
|
||||
*/
|
||||
add_dataset: function(dataset_id) {
|
||||
var self = this;
|
||||
require(['mvc/data'], function(DATA) {
|
||||
var dataset = new DATA.Dataset({ id: dataset_id });
|
||||
$.when( dataset.fetch() ).then( function() {
|
||||
// Construct frame config based on dataset's type.
|
||||
var frame_config = {
|
||||
title: dataset.get('name')
|
||||
},
|
||||
// HACK: For now, assume 'tabular' and 'interval' are the only
|
||||
// modules that contain tabular files. This needs to be replaced
|
||||
// will a is_datatype() function.
|
||||
is_tabular = _.find(['tabular', 'interval'], function(data_type) {
|
||||
return dataset.get('data_type').indexOf(data_type) !== -1;
|
||||
});
|
||||
|
||||
// Use tabular chunked display if dataset is tabular; otherwise load via URL.
|
||||
if (is_tabular) {
|
||||
var tabular_dataset = new DATA.TabularDataset(dataset.toJSON());
|
||||
_.extend(frame_config, {
|
||||
type: 'other',
|
||||
content: function( parent_elt ) {
|
||||
DATA.createTabularDatasetChunkedView({
|
||||
model: tabular_dataset,
|
||||
parent_elt: parent_elt,
|
||||
embedded: true,
|
||||
height: '100%'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
_.extend(frame_config, {
|
||||
type: 'url',
|
||||
content: galaxy_config.root + 'datasets/' +
|
||||
dataset.id + '/display/?preview=True'
|
||||
});
|
||||
}
|
||||
|
||||
self.add(frame_config);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a trackster visualization to the frames.
|
||||
*/
|
||||
add_trackster_viz: function(viz_id) {
|
||||
var self = this;
|
||||
require(['viz/visualization', 'viz/trackster'], function(visualization, trackster) {
|
||||
var viz = new visualization.Visualization({id: viz_id});
|
||||
$.when( viz.fetch() ).then( function() {
|
||||
var ui = new trackster.TracksterUI(galaxy_config.root);
|
||||
|
||||
// Construct frame config based on dataset's type.
|
||||
var frame_config = {
|
||||
title: viz.get('name'),
|
||||
type: 'other',
|
||||
content: function(parent_elt) {
|
||||
// Create view config.
|
||||
var view_config = {
|
||||
container: parent_elt,
|
||||
name: viz.get('title'),
|
||||
id: viz.id,
|
||||
// FIXME: this will not work with custom builds b/c the dbkey needed to be encoded.
|
||||
dbkey: viz.get('dbkey'),
|
||||
stand_alone: false
|
||||
},
|
||||
latest_revision = viz.get('latest_revision'),
|
||||
drawables = latest_revision.config.view.drawables;
|
||||
|
||||
// Set up datasets in drawables.
|
||||
_.each(drawables, function(d) {
|
||||
d.dataset = {
|
||||
hda_ldda: d.hda_ldda,
|
||||
id: d.dataset_id
|
||||
};
|
||||
});
|
||||
|
||||
view = ui.create_visualization(view_config,
|
||||
latest_revision.config.viewport,
|
||||
latest_revision.config.view.drawables,
|
||||
latest_revision.config.bookmarks,
|
||||
false);
|
||||
}
|
||||
};
|
||||
|
||||
self.add(frame_config);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Add and display a new frame/window based on options.
|
||||
*/
|
||||
add: function(options){
|
||||
// open new tab
|
||||
if (options.target == '_blank'){
|
||||
window.open(options.content);
|
||||
return;
|
||||
}
|
||||
|
||||
// reload entire window
|
||||
if (options.target == '_top' || options.target == '_parent' || options.target == '_self'){
|
||||
window.location = options.content;
|
||||
return;
|
||||
}
|
||||
|
||||
// validate
|
||||
if (!this.active){
|
||||
// fix url if main frame is unavailable
|
||||
var $galaxy_main = $(window.parent.document).find('#galaxy_main');
|
||||
if (options.target == 'galaxy_main' || options.target == 'center'){
|
||||
if ($galaxy_main.length === 0){
|
||||
var href = options.content;
|
||||
if (href.indexOf('?') == -1)
|
||||
href += '?';
|
||||
else
|
||||
href += '&';
|
||||
href += 'use_panels=True';
|
||||
window.location = href;
|
||||
} else {
|
||||
$galaxy_main.attr('src', options.content);
|
||||
}
|
||||
} else
|
||||
window.location = options.content;
|
||||
|
||||
// stop
|
||||
return;
|
||||
}
|
||||
|
||||
// add to frames view
|
||||
this.frames.add(options);
|
||||
},
|
||||
|
||||
// activate/disable panel
|
||||
_activate: function (){
|
||||
// check
|
||||
if (this.active){
|
||||
// disable
|
||||
this.active = false;
|
||||
|
||||
// toggle
|
||||
this.button_active.untoggle();
|
||||
|
||||
// hide panel
|
||||
this.frames.hide();
|
||||
} else {
|
||||
// activate
|
||||
this.active = true;
|
||||
|
||||
// untoggle
|
||||
this.button_active.toggle();
|
||||
}
|
||||
},
|
||||
|
||||
// update frame counter
|
||||
_refresh: function(){
|
||||
// update on screen counter
|
||||
this.button_load.number(this.frames.length());
|
||||
|
||||
// check
|
||||
if(this.frames.length() === 0)
|
||||
this.button_load.hide();
|
||||
else
|
||||
this.button_load.show();
|
||||
|
||||
// check
|
||||
if (this.frames.visible) {
|
||||
this.button_load.toggle();
|
||||
} else {
|
||||
this.button_load.untoggle();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// return
|
||||
return {
|
||||
GalaxyFrame: GalaxyFrame
|
||||
};
|
||||
|
||||
});
|
||||
define(["galaxy.masthead","mvc/ui/ui-frames"],function(a,b){var c=Backbone.View.extend({el_main:"body",active:!1,button_active:null,button_load:null,initialize:function(){var c=this;this.frames=new b.View({visible:!1}),this.button_active=new a.GalaxyMastheadIcon({icon:"fa-th",tooltip:"Enable/Disable Scratchbook",onclick:function(){c._activate()},onunload:function(){return c.frames.length()>0?"You opened "+c.frames.length()+" frame(s) which will be lost.":void 0}}),Galaxy.masthead.append(this.button_active),this.button_load=new a.GalaxyMastheadIcon({icon:"fa-eye",tooltip:"Show/Hide Scratchbook",onclick:function(){c.frames.visible?c.frames.hide():c.frames.show()},with_number:!0}),Galaxy.masthead.append(this.button_load),this.setElement(this.frames.$el),$(this.el_main).append(this.$el),this.frames.setOnChange(function(){c._refresh()}),this._refresh()},add_dataset:function(a){var b=this;require(["mvc/data"],function(c){var d=new c.Dataset({id:a});$.when(d.fetch()).then(function(){var a={title:d.get("name")},e=_.find(["tabular","interval"],function(a){return-1!==d.get("data_type").indexOf(a)});if(e){var f=new c.TabularDataset(d.toJSON());_.extend(a,{type:"other",content:function(a){c.createTabularDatasetChunkedView({model:f,parent_elt:a,embedded:!0,height:"100%"})}})}else _.extend(a,{type:"url",content:galaxy_config.root+"datasets/"+d.id+"/display/?preview=True"});b.add(a)})})},add_trackster_viz:function(a){var b=this;require(["viz/visualization","viz/trackster"],function(c,d){var e=new c.Visualization({id:a});$.when(e.fetch()).then(function(){var a=new d.TracksterUI(galaxy_config.root),c={title:e.get("name"),type:"other",content:function(b){var c={container:b,name:e.get("title"),id:e.id,dbkey:e.get("dbkey"),stand_alone:!1},d=e.get("latest_revision"),f=d.config.view.drawables;_.each(f,function(a){a.dataset={hda_ldda:a.hda_ldda,id:a.dataset_id}}),view=a.create_visualization(c,d.config.viewport,d.config.view.drawables,d.config.bookmarks,!1)}};b.add(c)})})},add:function(a){if("_blank"==a.target)return void window.open(a.content);if("_top"==a.target||"_parent"==a.target||"_self"==a.target)return void(window.location=a.content);if(this.active)this.frames.add(a);else{var b=$(window.parent.document).find("#galaxy_main");if("galaxy_main"==a.target||"center"==a.target)if(0===b.length){var c=a.content;c+=-1==c.indexOf("?")?"?":"&",c+="use_panels=True",window.location=c}else b.attr("src",a.content);else window.location=a.content}},_activate:function(){this.active?(this.active=!1,this.button_active.untoggle(),this.frames.hide()):(this.active=!0,this.button_active.toggle())},_refresh:function(){this.button_load.number(this.frames.length()),0===this.frames.length()?this.button_load.hide():this.button_load.show(),this.frames.visible?this.button_load.toggle():this.button_load.untoggle()}});return{GalaxyFrame:c}});
|
||||
//# sourceMappingURL=../maps/galaxy.frame.js.map
|
||||
@@ -1,59 +1,2 @@
|
||||
/**
|
||||
* Internal function to remove content from the main area and add the notebook.
|
||||
* Not idempotent
|
||||
*/
|
||||
function append_notebook(url){
|
||||
clear_main_area();
|
||||
$('#main').append('<iframe frameBorder="0" seamless="seamless" style="width: 100%; height: 100%; overflow:hidden;" scrolling="no" src="'+ url +'"></iframe>'
|
||||
);
|
||||
}
|
||||
|
||||
function clear_main_area(){
|
||||
$('#spinner').remove();
|
||||
$('#main').children().remove();
|
||||
}
|
||||
|
||||
function display_spinner(){
|
||||
$('#main').append('<img id="spinner" src="' + galaxy_root + '/static/style/largespinner.gif" style="position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;">');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test availability of a URL, and call a callback when done.
|
||||
* http://stackoverflow.com/q/25390206/347368
|
||||
* @param {String} url: URL to test availability of. Must return a 200 (302->200 is OK).
|
||||
* @param {String} callback: function to call once successfully connected.
|
||||
*
|
||||
*/
|
||||
function test_ie_availability(url, success_callback){
|
||||
var request_count = 0;
|
||||
display_spinner();
|
||||
interval = setInterval(function(){
|
||||
$.ajax({
|
||||
url: url,
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
},
|
||||
type: "GET",
|
||||
timeout: 500,
|
||||
success: function(){
|
||||
console.log("Connected to IE, returning");
|
||||
clearInterval(interval);
|
||||
success_callback();
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
request_count++;
|
||||
console.log("Request " + request_count);
|
||||
if(request_count > 30){
|
||||
clearInterval(interval);
|
||||
clear_main_area();
|
||||
toastr.error(
|
||||
"Could not connect to IE, contact your administrator",
|
||||
"Error",
|
||||
{'closeButton': true, 'timeOut': 20000, 'tapToDismiss': false}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
function append_notebook(a){clear_main_area(),$("#main").append('<iframe frameBorder="0" seamless="seamless" style="width: 100%; height: 100%; overflow:hidden;" scrolling="no" src="'+a+'"></iframe>')}function clear_main_area(){$("#spinner").remove(),$("#main").children().remove()}function display_spinner(){$("#main").append('<img id="spinner" src="'+galaxy_root+'/static/style/largespinner.gif" style="position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;">')}function test_ie_availability(a,b){var c=0;display_spinner(),interval=setInterval(function(){$.ajax({url:a,xhrFields:{withCredentials:!0},type:"GET",timeout:500,success:function(){clearInterval(interval),b()},error:function(){c++,c>30&&(clearInterval(interval),clear_main_area(),toastr.error("Could not connect to IE, contact your administrator","Error",{closeButton:!0,timeOut:2e4,tapToDismiss:!1}))}})},1e3)}
|
||||
//# sourceMappingURL=../maps/galaxy.interactive_environments.js.map
|
||||
@@ -1,193 +1,2 @@
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// === MAIN GALAXY LIBRARY MODULE ====
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
|
||||
define([
|
||||
"galaxy.masthead",
|
||||
"utils/utils",
|
||||
"libs/toastr",
|
||||
"mvc/base-mvc",
|
||||
"mvc/library/library-model",
|
||||
"mvc/library/library-folderlist-view",
|
||||
"mvc/library/library-librarylist-view",
|
||||
"mvc/library/library-librarytoolbar-view",
|
||||
"mvc/library/library-foldertoolbar-view",
|
||||
"mvc/library/library-dataset-view",
|
||||
"mvc/library/library-library-view",
|
||||
"mvc/library/library-folder-view"
|
||||
],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
mod_toastr,
|
||||
mod_baseMVC,
|
||||
mod_library_model,
|
||||
mod_folderlist_view,
|
||||
mod_librarylist_view,
|
||||
mod_librarytoolbar_view,
|
||||
mod_foldertoolbar_view,
|
||||
mod_library_dataset_view,
|
||||
mod_library_library_view,
|
||||
mod_library_folder_view
|
||||
) {
|
||||
|
||||
// ============================================================================
|
||||
// ROUTER
|
||||
var LibraryRouter = Backbone.Router.extend({
|
||||
initialize: function() {
|
||||
this.routesHit = 0;
|
||||
//keep count of number of routes handled by the application
|
||||
Backbone.history.on( 'route', function() { this.routesHit++; }, this );
|
||||
},
|
||||
|
||||
routes: {
|
||||
"" : "libraries",
|
||||
"page/:show_page" : "libraries_page",
|
||||
"library/:library_id/permissions" : "library_permissions",
|
||||
"folders/:folder_id/permissions" : "folder_permissions",
|
||||
"folders/:id" : "folder_content",
|
||||
"folders/:id/page/:show_page" : "folder_page",
|
||||
"folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
|
||||
"folders/:folder_id/datasets/:dataset_id/permissions" : "dataset_permissions",
|
||||
"folders/:folder_id/datasets/:dataset_id/versions/:ldda_id" : "dataset_version",
|
||||
"folders/:folder_id/download/:format" : "download",
|
||||
"folders/:folder_id/import/:source" : "import_datasets"
|
||||
},
|
||||
|
||||
back: function() {
|
||||
if( this.routesHit > 1 ) {
|
||||
//more than one route hit -> user did not land to current page directly
|
||||
window.history.back();
|
||||
} else {
|
||||
//otherwise go to the home page. Use replaceState if available so
|
||||
//the navigation doesn't create an extra history entry
|
||||
this.navigate( '#', { trigger:true, replace:true } );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
/** session storage for library preferences */
|
||||
var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({
|
||||
defaults : {
|
||||
with_deleted : false,
|
||||
sort_order : 'asc',
|
||||
sort_by : 'name',
|
||||
library_page_size : 20,
|
||||
folder_page_size : 15
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Main controller of Galaxy Library
|
||||
var GalaxyLibrary = Backbone.View.extend({
|
||||
|
||||
libraryToolbarView: null,
|
||||
libraryListView: null,
|
||||
library_router: null,
|
||||
libraryView: null,
|
||||
folderToolbarView: null,
|
||||
folderListView: null,
|
||||
datasetView: null,
|
||||
|
||||
initialize : function(){
|
||||
Galaxy.libraries = this;
|
||||
|
||||
this.preferences = new LibraryPrefs( { id: 'global-lib-prefs' } );
|
||||
|
||||
this.library_router = new LibraryRouter();
|
||||
|
||||
this.library_router.on( 'route:libraries', function() {
|
||||
Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView();
|
||||
Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView();
|
||||
});
|
||||
|
||||
this.library_router.on('route:libraries_page', function( show_page ) {
|
||||
if ( Galaxy.libraries.libraryToolbarView === null ){
|
||||
Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView();
|
||||
Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView( { show_page: show_page } );
|
||||
} else {
|
||||
Galaxy.libraries.libraryListView.render( { show_page: show_page } )
|
||||
}
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:folder_content', function( id ) {
|
||||
if (Galaxy.libraries.folderToolbarView){
|
||||
Galaxy.libraries.folderToolbarView.$el.unbind( 'click' );
|
||||
}
|
||||
Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView( { id: id } );
|
||||
Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView( { id: id } );
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:folder_page', function( id, show_page ) {
|
||||
if ( Galaxy.libraries.folderToolbarView === null ){
|
||||
Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView( {id: id} );
|
||||
Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView( { id: id, show_page: show_page } );
|
||||
} else {
|
||||
Galaxy.libraries.folderListView.render( { id: id, show_page: parseInt( show_page ) } )
|
||||
}
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:download', function( folder_id, format ) {
|
||||
if ( $( '#folder_list_body' ).find( ':checked' ).length === 0 ) {
|
||||
mod_toastr.info( 'You must select at least one dataset to download' );
|
||||
Galaxy.libraries.library_router.navigate( 'folders/' + folder_id, { trigger: true, replace: true } );
|
||||
} else {
|
||||
Galaxy.libraries.folderToolbarView.download( folder_id, format );
|
||||
Galaxy.libraries.library_router.navigate( 'folders/' + folder_id, { trigger: false, replace: true } );
|
||||
}
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:dataset_detail', function(folder_id, dataset_id){
|
||||
if (Galaxy.libraries.datasetView){
|
||||
Galaxy.libraries.datasetView.$el.unbind('click');
|
||||
}
|
||||
Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id});
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:dataset_version', function(folder_id, dataset_id, ldda_id){
|
||||
if (Galaxy.libraries.datasetView){
|
||||
Galaxy.libraries.datasetView.$el.unbind('click');
|
||||
}
|
||||
Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, ldda_id: ldda_id, show_version: true});
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:dataset_permissions', function(folder_id, dataset_id){
|
||||
if (Galaxy.libraries.datasetView){
|
||||
Galaxy.libraries.datasetView.$el.unbind('click');
|
||||
}
|
||||
Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true});
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:library_permissions', function(library_id){
|
||||
if (Galaxy.libraries.libraryView){
|
||||
Galaxy.libraries.libraryView.$el.unbind('click');
|
||||
}
|
||||
Galaxy.libraries.libraryView = new mod_library_library_view.LibraryView({id: library_id, show_permissions: true});
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:folder_permissions', function(folder_id){
|
||||
if (Galaxy.libraries.folderView){
|
||||
Galaxy.libraries.folderView.$el.unbind('click');
|
||||
}
|
||||
Galaxy.libraries.folderView = new mod_library_folder_view.FolderView({id: folder_id, show_permissions: true});
|
||||
});
|
||||
|
||||
this.library_router.on( 'route:import_datasets', function( folder_id, source ){
|
||||
if ( Galaxy.libraries.folderToolbarView && Galaxy.libraries.folderListView ){
|
||||
Galaxy.libraries.folderToolbarView.showImportModal( { source:source } );
|
||||
} else {
|
||||
Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView( { id: folder_id } );
|
||||
Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView( { id: folder_id } );
|
||||
Galaxy.libraries.folderToolbarView.showImportModal( { source: source } );
|
||||
}
|
||||
});
|
||||
|
||||
Backbone.history.start({pushState: false});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
GalaxyApp: GalaxyLibrary
|
||||
};
|
||||
|
||||
});
|
||||
define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view","mvc/library/library-dataset-view","mvc/library/library-library-view","mvc/library/library-folder-view"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m=Backbone.Router.extend({initialize:function(){this.routesHit=0,Backbone.history.on("route",function(){this.routesHit++},this)},routes:{"":"libraries","page/:show_page":"libraries_page","library/:library_id/permissions":"library_permissions","folders/:folder_id/permissions":"folder_permissions","folders/:id":"folder_content","folders/:id/page/:show_page":"folder_page","folders/:folder_id/datasets/:dataset_id":"dataset_detail","folders/:folder_id/datasets/:dataset_id/permissions":"dataset_permissions","folders/:folder_id/datasets/:dataset_id/versions/:ldda_id":"dataset_version","folders/:folder_id/download/:format":"download","folders/:folder_id/import/:source":"import_datasets"},back:function(){this.routesHit>1?window.history.back():this.navigate("#",{trigger:!0,replace:!0})}}),n=d.SessionStorageModel.extend({defaults:{with_deleted:!1,sort_order:"asc",sort_by:"name",library_page_size:20,folder_page_size:15}}),o=Backbone.View.extend({libraryToolbarView:null,libraryListView:null,library_router:null,libraryView:null,folderToolbarView:null,folderListView:null,datasetView:null,initialize:function(){Galaxy.libraries=this,this.preferences=new n({id:"global-lib-prefs"}),this.library_router=new m,this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new h.LibraryToolbarView,Galaxy.libraries.libraryListView=new g.LibraryListView}),this.library_router.on("route:libraries_page",function(a){null===Galaxy.libraries.libraryToolbarView?(Galaxy.libraries.libraryToolbarView=new h.LibraryToolbarView,Galaxy.libraries.libraryListView=new g.LibraryListView({show_page:a})):Galaxy.libraries.libraryListView.render({show_page:a})}),this.library_router.on("route:folder_content",function(a){Galaxy.libraries.folderToolbarView&&Galaxy.libraries.folderToolbarView.$el.unbind("click"),Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:a}),Galaxy.libraries.folderListView=new f.FolderListView({id:a})}),this.library_router.on("route:folder_page",function(a,b){null===Galaxy.libraries.folderToolbarView?(Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:a}),Galaxy.libraries.folderListView=new f.FolderListView({id:a,show_page:b})):Galaxy.libraries.folderListView.render({id:a,show_page:parseInt(b)})}),this.library_router.on("route:download",function(a,b){0===$("#folder_list_body").find(":checked").length?(c.info("You must select at least one dataset to download"),Galaxy.libraries.library_router.navigate("folders/"+a,{trigger:!0,replace:!0})):(Galaxy.libraries.folderToolbarView.download(a,b),Galaxy.libraries.library_router.navigate("folders/"+a,{trigger:!1,replace:!0}))}),this.library_router.on("route:dataset_detail",function(a,b){Galaxy.libraries.datasetView&&Galaxy.libraries.datasetView.$el.unbind("click"),Galaxy.libraries.datasetView=new j.LibraryDatasetView({id:b})}),this.library_router.on("route:dataset_version",function(a,b,c){Galaxy.libraries.datasetView&&Galaxy.libraries.datasetView.$el.unbind("click"),Galaxy.libraries.datasetView=new j.LibraryDatasetView({id:b,ldda_id:c,show_version:!0})}),this.library_router.on("route:dataset_permissions",function(a,b){Galaxy.libraries.datasetView&&Galaxy.libraries.datasetView.$el.unbind("click"),Galaxy.libraries.datasetView=new j.LibraryDatasetView({id:b,show_permissions:!0})}),this.library_router.on("route:library_permissions",function(a){Galaxy.libraries.libraryView&&Galaxy.libraries.libraryView.$el.unbind("click"),Galaxy.libraries.libraryView=new k.LibraryView({id:a,show_permissions:!0})}),this.library_router.on("route:folder_permissions",function(a){Galaxy.libraries.folderView&&Galaxy.libraries.folderView.$el.unbind("click"),Galaxy.libraries.folderView=new l.FolderView({id:a,show_permissions:!0})}),this.library_router.on("route:import_datasets",function(a,b){Galaxy.libraries.folderToolbarView&&Galaxy.libraries.folderListView?Galaxy.libraries.folderToolbarView.showImportModal({source:b}):(Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:a}),Galaxy.libraries.folderListView=new f.FolderListView({id:a}),Galaxy.libraries.folderToolbarView.showImportModal({source:b}))}),Backbone.history.start({pushState:!1})}});return{GalaxyApp:o}});
|
||||
//# sourceMappingURL=../maps/galaxy.library.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -1,343 +1,2 @@
|
||||
// dependencies
|
||||
define(["galaxy.masthead"], function(mod_masthead) {
|
||||
|
||||
/** GalaxyMenu uses the GalaxyMasthead class in order to add menu items and icons to the Masthead **/
|
||||
var GalaxyMenu = Backbone.Model.extend({
|
||||
// options
|
||||
options: null,
|
||||
|
||||
// link masthead class
|
||||
masthead: null,
|
||||
|
||||
// initialize
|
||||
initialize: function(options) {
|
||||
this.options = options.config;
|
||||
this.masthead = options.masthead;
|
||||
this.create();
|
||||
},
|
||||
|
||||
// default menu
|
||||
create: function(){
|
||||
//
|
||||
// Analyze data tab.
|
||||
//
|
||||
var tab_analysis = new mod_masthead.GalaxyMastheadTab({
|
||||
id : "analysis",
|
||||
title : "Analyze Data",
|
||||
content : "",
|
||||
title_attribute : 'Analysis home view'
|
||||
});
|
||||
this.masthead.append(tab_analysis);
|
||||
|
||||
//
|
||||
// Workflow tab.
|
||||
//
|
||||
|
||||
var workflow_options = {
|
||||
id : "workflow",
|
||||
title : "Workflow",
|
||||
content : "workflow",
|
||||
title_attribute : 'Chain tools into workflows'
|
||||
}
|
||||
if (!this.options.user.valid){
|
||||
workflow_options.disabled = true; // disable workflows for anonymous users
|
||||
}
|
||||
|
||||
var tab_workflow = new mod_masthead.GalaxyMastheadTab(workflow_options);
|
||||
this.masthead.append(tab_workflow);
|
||||
|
||||
//
|
||||
// 'Shared Items' or Libraries tab.
|
||||
//
|
||||
var tab_shared = new mod_masthead.GalaxyMastheadTab({
|
||||
id : "shared",
|
||||
title : "Shared Data",
|
||||
content : "library/index",
|
||||
title_attribute : 'Access published resources'
|
||||
});
|
||||
|
||||
tab_shared.add({
|
||||
title : "Data Libraries",
|
||||
content : "library/index"
|
||||
});
|
||||
|
||||
tab_shared.add({
|
||||
title : "Data Libraries Beta",
|
||||
content : "library/list",
|
||||
divider : true
|
||||
});
|
||||
|
||||
tab_shared.add({
|
||||
title : "Published Histories",
|
||||
content : "history/list_published"
|
||||
});
|
||||
|
||||
tab_shared.add({
|
||||
title : "Published Workflows",
|
||||
content : "workflow/list_published"
|
||||
|
||||
});
|
||||
|
||||
tab_shared.add({
|
||||
title : "Published Visualizations",
|
||||
content : "visualization/list_published"
|
||||
});
|
||||
|
||||
tab_shared.add({
|
||||
title : "Published Pages",
|
||||
content : "page/list_published"
|
||||
});
|
||||
|
||||
this.masthead.append(tab_shared);
|
||||
|
||||
//
|
||||
// Lab menu.
|
||||
//
|
||||
if (this.options.user.requests)
|
||||
{
|
||||
var tab_lab = new mod_masthead.GalaxyMastheadTab({
|
||||
id : "lab",
|
||||
title : "Lab"
|
||||
});
|
||||
tab_lab.add({
|
||||
title : "Sequencing Requests",
|
||||
content : "requests/index"
|
||||
});
|
||||
tab_lab.add({
|
||||
title : "Find Samples",
|
||||
content : "requests/find_samples_index"
|
||||
});
|
||||
tab_lab.add({
|
||||
title : "Help",
|
||||
content : this.options.lims_doc_url
|
||||
});
|
||||
this.masthead.append(tab_lab);
|
||||
}
|
||||
|
||||
//
|
||||
// Visualization tab.
|
||||
//
|
||||
|
||||
var visualization_options = {
|
||||
id : "visualization",
|
||||
title : "Visualization",
|
||||
content : "visualization/list",
|
||||
title_attribute : 'Visualize datasets'
|
||||
}
|
||||
if (!this.options.user.valid){
|
||||
visualization_options.disabled = true; // disable visualizations for anonymous users
|
||||
}
|
||||
|
||||
var tab_visualization = new mod_masthead.GalaxyMastheadTab(visualization_options);
|
||||
|
||||
if (this.options.user.valid){ //add submenu only when user is logged in
|
||||
tab_visualization.add({
|
||||
title : "New Track Browser",
|
||||
content : "visualization/trackster",
|
||||
target : "_frame"
|
||||
});
|
||||
tab_visualization.add({
|
||||
title : "Saved Visualizations",
|
||||
content : "visualization/list",
|
||||
target : "_frame"
|
||||
});
|
||||
}
|
||||
this.masthead.append(tab_visualization);
|
||||
|
||||
//
|
||||
// Cloud menu.
|
||||
//
|
||||
if (this.options.enable_cloud_launch){
|
||||
var tab_cloud = new mod_masthead.GalaxyMastheadTab({
|
||||
id : "cloud",
|
||||
title : "Cloud",
|
||||
content : "cloudlaunch/index"
|
||||
});
|
||||
tab_cloud.add({
|
||||
title : "New Cloud Cluster",
|
||||
content : "cloudlaunch/index"
|
||||
});
|
||||
this.masthead.append(tab_cloud);
|
||||
}
|
||||
|
||||
//
|
||||
// Admin.
|
||||
//
|
||||
if (this.options.is_admin_user) {
|
||||
var tab_admin = new mod_masthead.GalaxyMastheadTab({
|
||||
id : "admin",
|
||||
title : "Admin",
|
||||
content : "admin",
|
||||
extra_class : "admin-only",
|
||||
title_attribute : 'Administer this Galaxy'
|
||||
});
|
||||
this.masthead.append(tab_admin);
|
||||
}
|
||||
|
||||
//
|
||||
// Help tab.
|
||||
//
|
||||
var tab_help = new mod_masthead.GalaxyMastheadTab({
|
||||
id : "help",
|
||||
title : "Help",
|
||||
title_attribute : 'Support, contact, and community hubs'
|
||||
});
|
||||
if (this.options.biostar_url){
|
||||
tab_help.add({
|
||||
title : "Galaxy Biostar",
|
||||
content : this.options.biostar_url_redirect,
|
||||
target : "_blank"
|
||||
});
|
||||
tab_help.add({
|
||||
title : "Ask a question",
|
||||
content : "biostar/biostar_question_redirect",
|
||||
target : "_blank"
|
||||
});
|
||||
}
|
||||
tab_help.add({
|
||||
title : "Support",
|
||||
content : this.options.support_url,
|
||||
target : "_blank"
|
||||
});
|
||||
tab_help.add({
|
||||
title : "Search",
|
||||
content : this.options.search_url,
|
||||
target : "_blank"
|
||||
});
|
||||
tab_help.add({
|
||||
title : "Mailing Lists",
|
||||
content : this.options.mailing_lists,
|
||||
target : "_blank"
|
||||
});
|
||||
tab_help.add({
|
||||
title : "Videos",
|
||||
content : this.options.screencasts_url,
|
||||
target : "_blank"
|
||||
});
|
||||
tab_help.add({
|
||||
title : "Wiki",
|
||||
content : this.options.wiki_url,
|
||||
target : "_blank"
|
||||
});
|
||||
tab_help.add({
|
||||
title : "How to Cite Galaxy",
|
||||
content : this.options.citation_url,
|
||||
target : "_blank"
|
||||
});
|
||||
if (this.options.terms_url){
|
||||
tab_help.add({
|
||||
title : "Terms and Conditions",
|
||||
content : this.options.terms_url,
|
||||
target : "_blank"
|
||||
});
|
||||
}
|
||||
this.masthead.append(tab_help);
|
||||
|
||||
//
|
||||
// User tab.
|
||||
//
|
||||
if (!this.options.user.valid){
|
||||
var tab_user = new mod_masthead.GalaxyMastheadTab({
|
||||
id : "user",
|
||||
title : "User",
|
||||
extra_class : "loggedout-only",
|
||||
title_attribute : 'Account registration or login'
|
||||
});
|
||||
|
||||
// login
|
||||
tab_user.add({
|
||||
title : "Login",
|
||||
content : "user/login",
|
||||
target : "galaxy_main"
|
||||
});
|
||||
|
||||
// register
|
||||
if (this.options.allow_user_creation){
|
||||
tab_user.add({
|
||||
title : "Register",
|
||||
content : "user/create",
|
||||
target : "galaxy_main"
|
||||
});
|
||||
}
|
||||
|
||||
// add to masthead
|
||||
this.masthead.append(tab_user);
|
||||
} else {
|
||||
var tab_user = new mod_masthead.GalaxyMastheadTab({
|
||||
id : "user",
|
||||
title : "User",
|
||||
extra_class : "loggedin-only",
|
||||
title_attribute : 'Account preferences and saved data'
|
||||
});
|
||||
|
||||
// show user logged in info
|
||||
tab_user.add({
|
||||
title : "Logged in as " + this.options.user.email
|
||||
});
|
||||
|
||||
tab_user.add({
|
||||
title : "Preferences",
|
||||
content : "user?cntrller=user",
|
||||
target : "galaxy_main"
|
||||
});
|
||||
|
||||
tab_user.add({
|
||||
title : "Custom Builds",
|
||||
content : "user/dbkeys",
|
||||
target : "galaxy_main"
|
||||
});
|
||||
|
||||
tab_user.add({
|
||||
title : "Logout",
|
||||
content : "user/logout",
|
||||
target : "_top",
|
||||
divider : true
|
||||
});
|
||||
|
||||
// default tabs
|
||||
tab_user.add({
|
||||
title : "Saved Histories",
|
||||
content : "history/list",
|
||||
target : "galaxy_main"
|
||||
});
|
||||
tab_user.add({
|
||||
title : "Saved Datasets",
|
||||
content : "dataset/list",
|
||||
target : "galaxy_main"
|
||||
});
|
||||
tab_user.add({
|
||||
title : "Saved Pages",
|
||||
content : "page/list",
|
||||
target : "_top"
|
||||
});
|
||||
|
||||
tab_user.add({
|
||||
title : "API Keys",
|
||||
content : "user/api_keys?cntrller=user",
|
||||
target : "galaxy_main"
|
||||
});
|
||||
|
||||
if (this.options.use_remote_user){
|
||||
tab_user.add({
|
||||
title : "Public Name",
|
||||
content : "user/edit_username?cntrller=user",
|
||||
target : "galaxy_main"
|
||||
});
|
||||
}
|
||||
|
||||
// add to masthead
|
||||
this.masthead.append(tab_user);
|
||||
}
|
||||
|
||||
// identify active tab
|
||||
if (this.options.active_view)
|
||||
this.masthead.highlight(this.options.active_view);
|
||||
}
|
||||
});
|
||||
|
||||
// return
|
||||
return {
|
||||
GalaxyMenu: GalaxyMenu
|
||||
};
|
||||
|
||||
});
|
||||
define(["galaxy.masthead"],function(a){var b=Backbone.Model.extend({options:null,masthead:null,initialize:function(a){this.options=a.config,this.masthead=a.masthead,this.create()},create:function(){var b=new a.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"",title_attribute:"Analysis home view"});this.masthead.append(b);var c={id:"workflow",title:"Workflow",content:"workflow",title_attribute:"Chain tools into workflows"};this.options.user.valid||(c.disabled=!0);var d=new a.GalaxyMastheadTab(c);this.masthead.append(d);var e=new a.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index",title_attribute:"Access published resources"});if(e.add({title:"Data Libraries",content:"library/index"}),e.add({title:"Data Libraries Beta",content:"library/list",divider:!0}),e.add({title:"Published Histories",content:"history/list_published"}),e.add({title:"Published Workflows",content:"workflow/list_published"}),e.add({title:"Published Visualizations",content:"visualization/list_published"}),e.add({title:"Published Pages",content:"page/list_published"}),this.masthead.append(e),this.options.user.requests){var f=new a.GalaxyMastheadTab({id:"lab",title:"Lab"});f.add({title:"Sequencing Requests",content:"requests/index"}),f.add({title:"Find Samples",content:"requests/find_samples_index"}),f.add({title:"Help",content:this.options.lims_doc_url}),this.masthead.append(f)}var g={id:"visualization",title:"Visualization",content:"visualization/list",title_attribute:"Visualize datasets"};this.options.user.valid||(g.disabled=!0);var h=new a.GalaxyMastheadTab(g);if(this.options.user.valid&&(h.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"}),h.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"})),this.masthead.append(h),this.options.enable_cloud_launch){var i=new a.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});i.add({title:"New Cloud Cluster",content:"cloudlaunch/index"}),this.masthead.append(i)}if(this.options.is_admin_user){var j=new a.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin",extra_class:"admin-only",title_attribute:"Administer this Galaxy"});this.masthead.append(j)}var k=new a.GalaxyMastheadTab({id:"help",title:"Help",title_attribute:"Support, contact, and community hubs"});if(this.options.biostar_url&&(k.add({title:"Galaxy Biostar",content:this.options.biostar_url_redirect,target:"_blank"}),k.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})),k.add({title:"Support",content:this.options.support_url,target:"_blank"}),k.add({title:"Search",content:this.options.search_url,target:"_blank"}),k.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"}),k.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"}),k.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"}),k.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"}),this.options.terms_url&&k.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"}),this.masthead.append(k),this.options.user.valid){var l=new a.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only",title_attribute:"Account preferences and saved data"});l.add({title:"Logged in as "+this.options.user.email}),l.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"}),l.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"}),l.add({title:"Logout",content:"user/logout",target:"_top",divider:!0}),l.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"}),l.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"}),l.add({title:"Saved Pages",content:"page/list",target:"_top"}),l.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"}),this.options.use_remote_user&&l.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"}),this.masthead.append(l)}else{var l=new a.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only",title_attribute:"Account registration or login"});l.add({title:"Login",content:"user/login",target:"galaxy_main"}),this.options.allow_user_creation&&l.add({title:"Register",content:"user/create",target:"galaxy_main"}),this.masthead.append(l)}this.options.active_view&&this.masthead.highlight(this.options.active_view)}});return{GalaxyMenu:b}});
|
||||
//# sourceMappingURL=../maps/galaxy.menu.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,158 +1,2 @@
|
||||
// dependencies
|
||||
define([ "libs/underscore", "mvc/tools" ], function( _, Tools ) {
|
||||
|
||||
var checkUncheckAll = function( name, check ) {
|
||||
$("input[name='" + name + "'][type='checkbox']").attr('checked', !!check);
|
||||
}
|
||||
|
||||
$(".tool-share-link").each( function() {
|
||||
var href = $(this).attr("href");
|
||||
var href = $(this).attr("data-link");
|
||||
$(this).click(function() {
|
||||
window.prompt("Copy to clipboard: Ctrl+C, Enter", href);
|
||||
});
|
||||
});
|
||||
|
||||
// Inserts the Select All / Unselect All buttons for checkboxes
|
||||
$("div.checkUncheckAllPlaceholder").each( function() {
|
||||
var check_name = $(this).attr("checkbox_name");
|
||||
select_link = $("<a class='action-button'></a>").text("Select All").click(function() {
|
||||
checkUncheckAll(check_name, true);
|
||||
});
|
||||
unselect_link = $("<a class='action-button'></a>").text("Unselect All").click(function() {
|
||||
checkUncheckAll(check_name, false);
|
||||
});
|
||||
$(this).append(select_link).append(" ").append(unselect_link);
|
||||
});
|
||||
|
||||
var SELECTION_TYPE = {
|
||||
'select_single': {
|
||||
'icon_class': 'fa-file-o',
|
||||
'select_by': 'Run tool on single input',
|
||||
'allow_remap': true
|
||||
},
|
||||
'select_multiple': {
|
||||
'icon_class': 'fa-files-o',
|
||||
'select_by': 'Run tool in parallel across multiple datasets',
|
||||
'allow_remap': false,
|
||||
'min_option_count': 2 // Don't show multiple select switch if only
|
||||
// one dataset available.
|
||||
},
|
||||
'select_collection': {
|
||||
'icon_class': 'fa-folder-o',
|
||||
'select_by': 'Run tool in parallel across dataset collection',
|
||||
'allow_remap': false
|
||||
},
|
||||
'multiselect_single': {
|
||||
'icon_class': 'fa-list-alt',
|
||||
'select_by': 'Run tool over multiple datasets',
|
||||
'allow_remap': true
|
||||
},
|
||||
'multiselect_collection': {
|
||||
'icon_class': 'fa-folder-o',
|
||||
'select_by': 'Run tool over dataset collection',
|
||||
'allow_remap': false,
|
||||
},
|
||||
'select_single_collection': {
|
||||
'icon_class': 'fa-file-o',
|
||||
'select_by': 'Run tool on single collection',
|
||||
'allow_remap': true
|
||||
},
|
||||
'select_map_over_collections': {
|
||||
'icon_class': 'fa-folder-o',
|
||||
'select_by': 'Map tool over compontents of nested collection',
|
||||
'allow_remap': false,
|
||||
}
|
||||
};
|
||||
|
||||
var SwitchSelectView = Backbone.View.extend({
|
||||
initialize: function( data ) {
|
||||
var defaultOption = data.default_option;
|
||||
var defaultIndex = null;
|
||||
var switchOptions = data.switch_options;
|
||||
this.switchOptions = switchOptions;
|
||||
this.prefix = data.prefix;
|
||||
var el = this.$el;
|
||||
var view = this;
|
||||
|
||||
var index = 0;
|
||||
var visibleCount = 0;
|
||||
_.each( this.switchOptions, function( option, onValue ) {
|
||||
var numValues = _.size( option.options );
|
||||
var selectionType = SELECTION_TYPE[ onValue ];
|
||||
var iIndex = index++;
|
||||
var hidden = false;
|
||||
if( defaultOption == onValue ) {
|
||||
defaultIndex = iIndex;
|
||||
} else if( numValues < ( selectionType.min_option_count || 1 ) ) {
|
||||
hidden = true;
|
||||
}
|
||||
if( ! hidden ) {
|
||||
visibleCount++;
|
||||
var button = $('<i class="fa ' + selectionType['icon_class'] + ' runOptionIcon" style="padding-left: 5px; padding-right: 2px;"></i>').click(function() {
|
||||
view.enableSelectBy( iIndex, onValue );
|
||||
}).attr(
|
||||
'title',
|
||||
selectionType['select_by']
|
||||
).data( "index", iIndex );
|
||||
view.formRow().find( "label" ).append( button );
|
||||
}
|
||||
});
|
||||
if( visibleCount < 2 ) {
|
||||
// Don't show buttons to switch options...
|
||||
view.formRow().find("i.runOptionIcon").hide();
|
||||
}
|
||||
|
||||
if( defaultIndex != null) {
|
||||
view.enableSelectBy( defaultIndex, defaultOption );
|
||||
}
|
||||
},
|
||||
|
||||
formRow: function() {
|
||||
return this.$el.closest( ".form-row" );
|
||||
},
|
||||
|
||||
render: function() {
|
||||
},
|
||||
|
||||
enableSelectBy: function( enableIndex, onValue ) {
|
||||
var selectionType = SELECTION_TYPE[onValue];
|
||||
if(selectionType["allow_remap"]) {
|
||||
$("div#remap-row").css("display", "inherit");
|
||||
} else {
|
||||
$("div#remap-row").css("display", "none");
|
||||
}
|
||||
this.formRow().find( "i" ).each(function(_, iElement) {
|
||||
var $iElement = $(iElement);
|
||||
var index = $iElement.data("index");
|
||||
if(index == enableIndex) {
|
||||
$iElement.css('color', 'black');
|
||||
} else {
|
||||
$iElement.css('color', 'Gray');
|
||||
}
|
||||
});
|
||||
var $select = this.$( "select" );
|
||||
var options = this.switchOptions[ onValue ];
|
||||
$select.attr( "name", this.prefix + options.name );
|
||||
$select.attr( "multiple", options.multiple );
|
||||
// Replace options regardless.
|
||||
var select2ed = this.$(".select2-container").length > 0;
|
||||
$select.html(""); // clear out select list
|
||||
_.each( options.options, function( option ) {
|
||||
var text = option[0];
|
||||
var value = option[1];
|
||||
var selected = option[2];
|
||||
$select.append($("<option />", {text: text, val: value, selected: selected}));
|
||||
});
|
||||
if( select2ed ) {
|
||||
// Without this select2 does not update options.
|
||||
$select.select2();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
SwitchSelectView: SwitchSelectView
|
||||
};
|
||||
|
||||
});
|
||||
define(["libs/underscore","mvc/tools"],function(a){var b=function(a,b){$("input[name='"+a+"'][type='checkbox']").attr("checked",!!b)};$(".tool-share-link").each(function(){var a=$(this).attr("href"),a=$(this).attr("data-link");$(this).click(function(){window.prompt("Copy to clipboard: Ctrl+C, Enter",a)})}),$("div.checkUncheckAllPlaceholder").each(function(){var a=$(this).attr("checkbox_name");select_link=$("<a class='action-button'></a>").text("Select All").click(function(){b(a,!0)}),unselect_link=$("<a class='action-button'></a>").text("Unselect All").click(function(){b(a,!1)}),$(this).append(select_link).append(" ").append(unselect_link)});var c={select_single:{icon_class:"fa-file-o",select_by:"Run tool on single input",allow_remap:!0},select_multiple:{icon_class:"fa-files-o",select_by:"Run tool in parallel across multiple datasets",allow_remap:!1,min_option_count:2},select_collection:{icon_class:"fa-folder-o",select_by:"Run tool in parallel across dataset collection",allow_remap:!1},multiselect_single:{icon_class:"fa-list-alt",select_by:"Run tool over multiple datasets",allow_remap:!0},multiselect_collection:{icon_class:"fa-folder-o",select_by:"Run tool over dataset collection",allow_remap:!1},select_single_collection:{icon_class:"fa-file-o",select_by:"Run tool on single collection",allow_remap:!0},select_map_over_collections:{icon_class:"fa-folder-o",select_by:"Map tool over compontents of nested collection",allow_remap:!1}},d=Backbone.View.extend({initialize:function(b){var d=b.default_option,e=null,f=b.switch_options;this.switchOptions=f,this.prefix=b.prefix;var g=(this.$el,this),h=0,i=0;a.each(this.switchOptions,function(b,f){var j=a.size(b.options),k=c[f],l=h++,m=!1;if(d==f?e=l:j<(k.min_option_count||1)&&(m=!0),!m){i++;var n=$('<i class="fa '+k.icon_class+' runOptionIcon" style="padding-left: 5px; padding-right: 2px;"></i>').click(function(){g.enableSelectBy(l,f)}).attr("title",k.select_by).data("index",l);g.formRow().find("label").append(n)}}),2>i&&g.formRow().find("i.runOptionIcon").hide(),null!=e&&g.enableSelectBy(e,d)},formRow:function(){return this.$el.closest(".form-row")},render:function(){},enableSelectBy:function(b,d){var e=c[d];e.allow_remap?$("div#remap-row").css("display","inherit"):$("div#remap-row").css("display","none"),this.formRow().find("i").each(function(a,c){var d=$(c),e=d.data("index");e==b?d.css("color","black"):d.css("color","Gray")});var f=this.$("select"),g=this.switchOptions[d];f.attr("name",this.prefix+g.name),f.attr("multiple",g.multiple);var h=this.$(".select2-container").length>0;f.html(""),a.each(g.options,function(a){var b=a[0],c=a[1],d=a[2];f.append($("<option />",{text:b,val:c,selected:d}))}),h&&f.select2()}});return{SwitchSelectView:d}});
|
||||
//# sourceMappingURL=../maps/galaxy.tools.js.map
|
||||
@@ -1,88 +1,2 @@
|
||||
// This is an extension to jQuery UI draggable
|
||||
// When dragging move the parent element ("panel") relative to its parent
|
||||
// ("viewport") so that the draggable is always visible.
|
||||
|
||||
$.ui.plugin.add("draggable", "scrollPanel", {
|
||||
drag: function(e, ui) {
|
||||
var instance = $(this).data("draggable");
|
||||
clearTimeout( instance.timeout );
|
||||
var o = ui.options,
|
||||
element = instance.element,
|
||||
panel = o.panel,
|
||||
panel_pos = panel.position(),
|
||||
panel_w = panel.width(),
|
||||
panel_h = panel.height()
|
||||
viewport = panel.parent();
|
||||
viewport_w = viewport.width(),
|
||||
viewport_h = viewport.height(),
|
||||
element_w = element.width(),
|
||||
element_h = element.height(),
|
||||
moved = false,
|
||||
close_dist = 5,
|
||||
nudge = 23,
|
||||
// Legal panel range
|
||||
p_min_x = - ( panel_w - viewport_w ),
|
||||
p_min_y = - ( panel_h - viewport_h ),
|
||||
p_max_x = 0,
|
||||
p_max_y = 0,
|
||||
// Visible
|
||||
min_vis_x = - panel_pos.left,
|
||||
max_vis_x = min_vis_x + viewport_w,
|
||||
min_vis_y = - panel_pos.top,
|
||||
max_vis_y = min_vis_y + viewport_h,
|
||||
// Mouse
|
||||
mouse_x = ui.position.left + instance.offset.click.left;
|
||||
mouse_y = ui.position.top + instance.offset.click.top;
|
||||
// Move it
|
||||
if ( ( panel_pos.left < p_max_x ) && ( mouse_x - close_dist < min_vis_x ) ) {
|
||||
var t = Math.min( nudge, p_max_x - panel_pos.left );
|
||||
panel.css( "left", panel_pos.left + t );
|
||||
moved = true;
|
||||
instance.offset.parent.left += t;
|
||||
ui.position.left -= t
|
||||
}
|
||||
if ( ( ! moved ) && ( panel_pos.left > p_min_x ) && ( mouse_x + close_dist > max_vis_x ) ) {
|
||||
var t = Math.min( nudge, panel_pos.left - p_min_x );
|
||||
panel.css( "left", panel_pos.left - t );
|
||||
moved = true;
|
||||
instance.offset.parent.left -= t;
|
||||
ui.position.left += t;
|
||||
}
|
||||
if ( ( ! moved ) && ( panel_pos.top < p_max_y ) && ( mouse_y - close_dist < min_vis_y ) ) {
|
||||
var t = Math.min( nudge, p_max_y - panel_pos.top );
|
||||
panel.css( "top", panel_pos.top + t );
|
||||
// Firefox sometimes moves by less, so we need to check. Yuck.
|
||||
var amount_moved = panel.position().top - panel_pos.top;
|
||||
instance.offset.parent.top += amount_moved;
|
||||
ui.position.top -= amount_moved;
|
||||
moved = true;
|
||||
}
|
||||
if ( ( ! moved ) && ( panel_pos.top > p_min_y ) && ( mouse_y + close_dist > max_vis_y ) ) {
|
||||
var t = Math.min( nudge, panel_pos.top - p_min_x );
|
||||
panel.css( "top", ( panel_pos.top - t ) + "px" );
|
||||
// Firefox sometimes moves by less, so we need to check. Yuck.
|
||||
var amount_moved = panel_pos.top - panel.position().top;
|
||||
instance.offset.parent.top -= amount_moved;
|
||||
ui.position.top += amount_moved;
|
||||
moved = true;
|
||||
}
|
||||
// Still contain in panel
|
||||
ui.position.left = Math.max( ui.position.left, 0 );
|
||||
ui.position.top = Math.max( ui.position.top, 0 );
|
||||
ui.position.left = Math.min( ui.position.left, panel_w - element_w );
|
||||
ui.position.top = Math.min( ui.position.top, panel_h - element_h );
|
||||
// Update offsets
|
||||
if ( moved ) {
|
||||
$.ui.ddmanager.prepareOffsets( instance, e );
|
||||
}
|
||||
// Keep moving even if mouse doesn't move
|
||||
if ( moved ) {
|
||||
instance.old_e = e;
|
||||
instance.timeout = setTimeout( function() { instance.mouseMove( e ) }, 50 );
|
||||
}
|
||||
},
|
||||
stop: function( e, ui ) {
|
||||
var instance = $(this).data("draggable");
|
||||
clearTimeout( instance.timeout );
|
||||
}
|
||||
});
|
||||
$.ui.plugin.add("draggable","scrollPanel",{drag:function(a,b){var c=$(this).data("draggable");clearTimeout(c.timeout);var d=b.options,e=c.element,f=d.panel,g=f.position(),h=f.width(),i=f.height();if(viewport=f.parent(),viewport_w=viewport.width(),viewport_h=viewport.height(),element_w=e.width(),element_h=e.height(),moved=!1,close_dist=5,nudge=23,p_min_x=-(h-viewport_w),p_min_y=-(i-viewport_h),p_max_x=0,p_max_y=0,min_vis_x=-g.left,max_vis_x=min_vis_x+viewport_w,min_vis_y=-g.top,max_vis_y=min_vis_y+viewport_h,mouse_x=b.position.left+c.offset.click.left,mouse_y=b.position.top+c.offset.click.top,g.left<p_max_x&&mouse_x-close_dist<min_vis_x){var j=Math.min(nudge,p_max_x-g.left);f.css("left",g.left+j),moved=!0,c.offset.parent.left+=j,b.position.left-=j}if(!moved&&g.left>p_min_x&&mouse_x+close_dist>max_vis_x){var j=Math.min(nudge,g.left-p_min_x);f.css("left",g.left-j),moved=!0,c.offset.parent.left-=j,b.position.left+=j}if(!moved&&g.top<p_max_y&&mouse_y-close_dist<min_vis_y){var j=Math.min(nudge,p_max_y-g.top);f.css("top",g.top+j);var k=f.position().top-g.top;c.offset.parent.top+=k,b.position.top-=k,moved=!0}if(!moved&&g.top>p_min_y&&mouse_y+close_dist>max_vis_y){var j=Math.min(nudge,g.top-p_min_x);f.css("top",g.top-j+"px");var k=g.top-f.position().top;c.offset.parent.top-=k,b.position.top+=k,moved=!0}b.position.left=Math.max(b.position.left,0),b.position.top=Math.max(b.position.top,0),b.position.left=Math.min(b.position.left,h-element_w),b.position.top=Math.min(b.position.top,i-element_h),moved&&$.ui.ddmanager.prepareOffsets(c,a),moved&&(c.old_e=a,c.timeout=setTimeout(function(){c.mouseMove(a)},50))},stop:function(){var a=$(this).data("draggable");clearTimeout(a.timeout)}});
|
||||
//# sourceMappingURL=../maps/galaxy.ui.scrollPanel.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-183
@@ -1,183 +1,2 @@
|
||||
/**
|
||||
* @license RequireJS i18n 2.0.4 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/requirejs/i18n for details
|
||||
*/
|
||||
/*jslint regexp: true */
|
||||
/*global require: false, navigator: false, define: false */
|
||||
|
||||
/**
|
||||
* This plugin handles i18n! prefixed modules. It does the following:
|
||||
*
|
||||
* 1) A regular module can have a dependency on an i18n bundle, but the regular
|
||||
* module does not want to specify what locale to load. So it just specifies
|
||||
* the top-level bundle, like "i18n!nls/colors".
|
||||
*
|
||||
* This plugin will load the i18n bundle at nls/colors, see that it is a root/master
|
||||
* bundle since it does not have a locale in its name. It will then try to find
|
||||
* the best match locale available in that master bundle, then request all the
|
||||
* locale pieces for that best match locale. For instance, if the locale is "en-us",
|
||||
* then the plugin will ask for the "en-us", "en" and "root" bundles to be loaded
|
||||
* (but only if they are specified on the master bundle).
|
||||
*
|
||||
* Once all the bundles for the locale pieces load, then it mixes in all those
|
||||
* locale pieces into each other, then finally sets the context.defined value
|
||||
* for the nls/colors bundle to be that mixed in locale.
|
||||
*
|
||||
* 2) A regular module specifies a specific locale to load. For instance,
|
||||
* i18n!nls/fr-fr/colors. In this case, the plugin needs to load the master bundle
|
||||
* first, at nls/colors, then figure out what the best match locale is for fr-fr,
|
||||
* since maybe only fr or just root is defined for that locale. Once that best
|
||||
* fit is found, all of its locale pieces need to have their bundles loaded.
|
||||
*
|
||||
* Once all the bundles for the locale pieces load, then it mixes in all those
|
||||
* locale pieces into each other, then finally sets the context.defined value
|
||||
* for the nls/fr-fr/colors bundle to be that mixed in locale.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
//regexp for reconstructing the master bundle name from parts of the regexp match
|
||||
//nlsRegExp.exec("foo/bar/baz/nls/en-ca/foo") gives:
|
||||
//["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
|
||||
//nlsRegExp.exec("foo/bar/baz/nls/foo") gives:
|
||||
//["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
|
||||
//so, if match[5] is blank, it means this is the top bundle definition.
|
||||
var nlsRegExp = /(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/;
|
||||
|
||||
//Helper function to avoid repeating code. Lots of arguments in the
|
||||
//desire to stay functional and support RequireJS contexts without having
|
||||
//to know about the RequireJS contexts.
|
||||
function addPart(locale, master, needed, toLoad, prefix, suffix) {
|
||||
if (master[locale]) {
|
||||
needed.push(locale);
|
||||
if (master[locale] === true || master[locale] === 1) {
|
||||
toLoad.push(prefix + locale + '/' + suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addIfExists(req, locale, toLoad, prefix, suffix) {
|
||||
var fullName = prefix + locale + '/' + suffix;
|
||||
if (require._fileExists(req.toUrl(fullName + '.js'))) {
|
||||
toLoad.push(fullName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple function to mix in properties from source into target,
|
||||
* but only if target does not already have a property of the same name.
|
||||
* This is not robust in IE for transferring methods that match
|
||||
* Object.prototype names, but the uses of mixin here seem unlikely to
|
||||
* trigger a problem related to that.
|
||||
*/
|
||||
function mixin(target, source, force) {
|
||||
var prop;
|
||||
for (prop in source) {
|
||||
if (source.hasOwnProperty(prop) && (!target.hasOwnProperty(prop) || force)) {
|
||||
target[prop] = source[prop];
|
||||
} else if (typeof source[prop] === 'object') {
|
||||
if (!target[prop] && source[prop]) {
|
||||
target[prop] = {};
|
||||
}
|
||||
mixin(target[prop], source[prop], force);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define(['module'], function (module) {
|
||||
var masterConfig = module.config ? module.config() : {};
|
||||
|
||||
return {
|
||||
version: '2.0.4',
|
||||
/**
|
||||
* Called when a dependency needs to be loaded.
|
||||
*/
|
||||
load: function (name, req, onLoad, config) {
|
||||
config = config || {};
|
||||
|
||||
if (config.locale) {
|
||||
masterConfig.locale = config.locale;
|
||||
}
|
||||
|
||||
var masterName,
|
||||
match = nlsRegExp.exec(name),
|
||||
prefix = match[1],
|
||||
locale = match[4],
|
||||
suffix = match[5],
|
||||
parts = locale.split("-"),
|
||||
toLoad = [],
|
||||
value = {},
|
||||
i, part, current = "";
|
||||
|
||||
//If match[5] is blank, it means this is the top bundle definition,
|
||||
//so it does not have to be handled. Locale-specific requests
|
||||
//will have a match[4] value but no match[5]
|
||||
if (match[5]) {
|
||||
//locale-specific bundle
|
||||
prefix = match[1];
|
||||
masterName = prefix + suffix;
|
||||
} else {
|
||||
//Top-level bundle.
|
||||
masterName = name;
|
||||
suffix = match[4];
|
||||
locale = masterConfig.locale;
|
||||
if (!locale) {
|
||||
locale = masterConfig.locale =
|
||||
typeof navigator === "undefined" ? "root" :
|
||||
(navigator.language ||
|
||||
navigator.userLanguage || "root").toLowerCase();
|
||||
}
|
||||
parts = locale.split("-");
|
||||
}
|
||||
|
||||
if (config.isBuild) {
|
||||
//Check for existence of all locale possible files and
|
||||
//require them if exist.
|
||||
toLoad.push(masterName);
|
||||
addIfExists(req, "root", toLoad, prefix, suffix);
|
||||
for (i = 0; i < parts.length; i++) {
|
||||
part = parts[i];
|
||||
current += (current ? "-" : "") + part;
|
||||
addIfExists(req, current, toLoad, prefix, suffix);
|
||||
}
|
||||
|
||||
req(toLoad, function () {
|
||||
onLoad();
|
||||
});
|
||||
} else {
|
||||
//First, fetch the master bundle, it knows what locales are available.
|
||||
req([masterName], function (master) {
|
||||
//Figure out the best fit
|
||||
var needed = [],
|
||||
part;
|
||||
|
||||
//Always allow for root, then do the rest of the locale parts.
|
||||
addPart("root", master, needed, toLoad, prefix, suffix);
|
||||
for (i = 0; i < parts.length; i++) {
|
||||
part = parts[i];
|
||||
current += (current ? "-" : "") + part;
|
||||
addPart(current, master, needed, toLoad, prefix, suffix);
|
||||
}
|
||||
|
||||
//Load all the parts missing.
|
||||
req(toLoad, function () {
|
||||
var i, partBundle, part;
|
||||
for (i = needed.length - 1; i > -1 && needed[i]; i--) {
|
||||
part = needed[i];
|
||||
partBundle = master[part];
|
||||
if (partBundle === true || partBundle === 1) {
|
||||
partBundle = req(prefix + part + '/' + suffix);
|
||||
}
|
||||
mixin(value, partBundle);
|
||||
}
|
||||
|
||||
//All done, notify the loader.
|
||||
onLoad(value);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}());
|
||||
!function(){"use strict";function a(a,b,c,d,e,f){b[a]&&(c.push(a),(b[a]===!0||1===b[a])&&d.push(e+a+"/"+f))}function b(a,b,c,d,e){var f=d+b+"/"+e;require._fileExists(a.toUrl(f+".js"))&&c.push(f)}function c(a,b,d){var e;for(e in b)!b.hasOwnProperty(e)||a.hasOwnProperty(e)&&!d?"object"==typeof b[e]&&(!a[e]&&b[e]&&(a[e]={}),c(a[e],b[e],d)):a[e]=b[e]}var d=/(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/;define(["module"],function(e){var f=e.config?e.config():{};return{version:"2.0.4",load:function(e,g,h,i){i=i||{},i.locale&&(f.locale=i.locale);var j,k,l,m=d.exec(e),n=m[1],o=m[4],p=m[5],q=o.split("-"),r=[],s={},t="";if(m[5]?(n=m[1],j=n+p):(j=e,p=m[4],o=f.locale,o||(o=f.locale="undefined"==typeof navigator?"root":(navigator.language||navigator.userLanguage||"root").toLowerCase()),q=o.split("-")),i.isBuild){for(r.push(j),b(g,"root",r,n,p),k=0;k<q.length;k++)l=q[k],t+=(t?"-":"")+l,b(g,t,r,n,p);g(r,function(){h()})}else g([j],function(b){var d,e=[];for(a("root",b,e,r,n,p),k=0;k<q.length;k++)d=q[k],t+=(t?"-":"")+d,a(t,b,e,r,n,p);g(r,function(){var a,d,f;for(a=e.length-1;a>-1&&e[a];a--)f=e[a],d=b[f],(d===!0||1===d)&&(d=g(n+f+"/"+p)),c(s,d);h(s)})})}}})}();
|
||||
//# sourceMappingURL=../maps/i18n.js.map
|
||||
+3
-2204
File diff suppressed because one or more lines are too long
+3
-2601
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,166 +1,2 @@
|
||||
|
||||
// =========================================================================
|
||||
// ie7-recalc.js
|
||||
// =========================================================================
|
||||
|
||||
(function() {
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
This allows refreshing of IE7 style rules. If you modify the DOM
|
||||
you can update IE7 by calling document.recalc().
|
||||
|
||||
This should be the LAST module included.
|
||||
|
||||
--------------------------------------------------------------------- */
|
||||
|
||||
if (!IE7.loaded) return;
|
||||
|
||||
// remove all IE7 classes from an element
|
||||
CLASSES = /\sie7_class\d+/g;
|
||||
|
||||
IE7.CSS.extend({
|
||||
// store for elements that have style properties calculated
|
||||
elements: {},
|
||||
handlers: [],
|
||||
|
||||
// clear IE7 classes and styles
|
||||
reset: function() {
|
||||
this.removeEventHandlers();
|
||||
// reset IE7 classes here
|
||||
var elements = this.elements;
|
||||
for (var i in elements) elements[i].runtimeStyle.cssText = "";
|
||||
this.elements = {};
|
||||
// reset runtimeStyle here
|
||||
var elements = IE7.Rule.elements;
|
||||
for (var i in elements) {
|
||||
with (elements[i]) className = className.replace(CLASSES, "");
|
||||
}
|
||||
IE7.Rule.elements = {};
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
this.rules = [];
|
||||
this.getInlineStyles();
|
||||
this.screen.load();
|
||||
if (this.print) this.print.load();
|
||||
this.refresh();
|
||||
this.trash();
|
||||
},
|
||||
|
||||
addRecalc: function(propertyName, test, handler, replacement) {
|
||||
// call the ancestor method to add a wrapped recalc method
|
||||
this.base(propertyName, test, function(element) {
|
||||
// execute the original recalc method
|
||||
handler(element);
|
||||
// store a reference to this element so we can clear its style later
|
||||
IE7.CSS.elements[element.uniqueID] = element;
|
||||
}, replacement);
|
||||
},
|
||||
|
||||
recalc: function() {
|
||||
// clear IE7 styles and classes
|
||||
this.reset();
|
||||
// execute the ancestor method to perform recalculations
|
||||
this.base();
|
||||
},
|
||||
|
||||
addEventHandler: function(element, type, handler) {
|
||||
element.attachEvent(type, handler);
|
||||
// store the handler so it can be detached later
|
||||
this.handlers.push(arguments);
|
||||
},
|
||||
|
||||
removeEventHandlers: function() {
|
||||
var handler;
|
||||
while (handler = this.handlers.pop()) {
|
||||
handler[0].detachEvent(handler[1], handler[2]);
|
||||
}
|
||||
},
|
||||
|
||||
getInlineStyles: function() {
|
||||
// load inline styles
|
||||
var styleSheets = document.getElementsByTagName("style"), styleSheet;
|
||||
for (var i = styleSheets.length - 1; (styleSheet = styleSheets[i]); i--) {
|
||||
if (!styleSheet.disabled && !styleSheet.ie7) {
|
||||
var cssText = styleSheet.cssText || styleSheet.innerHTML;
|
||||
this.styles.push(cssText);
|
||||
styleSheet.cssText = cssText;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
trash: function() {
|
||||
// trash the old style sheets
|
||||
var styleSheets = document.styleSheets, styleSheet, i;
|
||||
for (i = 0; i < styleSheets.length; i++) {
|
||||
styleSheet = styleSheets[i];
|
||||
if (!styleSheet.ie7 && !styleSheet.cssText) {
|
||||
styleSheet.cssText = styleSheet.cssText;
|
||||
}
|
||||
}
|
||||
this.base();
|
||||
},
|
||||
|
||||
getText: function(styleSheet) {
|
||||
return styleSheet.cssText || this.base(styleSheet);
|
||||
}
|
||||
});
|
||||
|
||||
// remove event handlers (they eat memory)
|
||||
IE7.CSS.addEventHandler(window, "onunload", function() {
|
||||
IE7.CSS.removeEventHandlers();
|
||||
});
|
||||
|
||||
// store all elements with an IE7 class assigned
|
||||
IE7.Rule.elements = {};
|
||||
|
||||
IE7.Rule.prototype.extend({
|
||||
add: function(element) {
|
||||
// execute the ancestor "add" method
|
||||
this.base(element);
|
||||
// store a reference to this element so we can clear its classes later
|
||||
IE7.Rule.elements[element.uniqueID] = element;
|
||||
}
|
||||
});
|
||||
|
||||
// store created pseudo elements
|
||||
if (IE7.PseudoElement) {
|
||||
IE7.PseudoElement.hash = {};
|
||||
|
||||
IE7.PseudoElement.prototype.extend({
|
||||
create: function(target) {
|
||||
var key = this.selector + ":" + target.uniqueID;
|
||||
if (!IE7.PseudoElement.hash[key]) {
|
||||
IE7.PseudoElement.hash[key] = true;
|
||||
this.base(target);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
IE7.HTML.extend({
|
||||
elements: {},
|
||||
|
||||
addRecalc: function(selector, handler) {
|
||||
// call the ancestor method to add a wrapped recalc method
|
||||
this.base(selector, function(element) {
|
||||
if (!this.elements[element.uniqueID]) {
|
||||
// execute the original recalc method
|
||||
handler(element);
|
||||
// store a reference to this element so that
|
||||
// it is not "fixed" again
|
||||
this.elements[element.uniqueID] = element;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// allow refreshing of IE7 fixes
|
||||
document.recalc = function(reload) {
|
||||
if (IE7.CSS.screen) {
|
||||
if (reload) IE7.CSS.reload();
|
||||
IE7.recalc();
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
!function(){IE7.loaded&&(CLASSES=/\sie7_class\d+/g,IE7.CSS.extend({elements:{},handlers:[],reset:function(){this.removeEventHandlers();var elements=this.elements;for(var i in elements)elements[i].runtimeStyle.cssText="";this.elements={};var elements=IE7.Rule.elements;for(var i in elements)with(elements[i])className=className.replace(CLASSES,"");IE7.Rule.elements={}},reload:function(){this.rules=[],this.getInlineStyles(),this.screen.load(),this.print&&this.print.load(),this.refresh(),this.trash()},addRecalc:function(a,b,c,d){this.base(a,b,function(a){c(a),IE7.CSS.elements[a.uniqueID]=a},d)},recalc:function(){this.reset(),this.base()},addEventHandler:function(a,b,c){a.attachEvent(b,c),this.handlers.push(arguments)},removeEventHandlers:function(){for(var a;a=this.handlers.pop();)a[0].detachEvent(a[1],a[2])},getInlineStyles:function(){for(var a,b=document.getElementsByTagName("style"),c=b.length-1;a=b[c];c--)if(!a.disabled&&!a.ie7){var d=a.cssText||a.innerHTML;this.styles.push(d),a.cssText=d}},trash:function(){var a,b,c=document.styleSheets;for(b=0;b<c.length;b++)a=c[b],a.ie7||a.cssText||(a.cssText=a.cssText);this.base()},getText:function(a){return a.cssText||this.base(a)}}),IE7.CSS.addEventHandler(window,"onunload",function(){IE7.CSS.removeEventHandlers()}),IE7.Rule.elements={},IE7.Rule.prototype.extend({add:function(a){this.base(a),IE7.Rule.elements[a.uniqueID]=a}}),IE7.PseudoElement&&(IE7.PseudoElement.hash={},IE7.PseudoElement.prototype.extend({create:function(a){var b=this.selector+":"+a.uniqueID;IE7.PseudoElement.hash[b]||(IE7.PseudoElement.hash[b]=!0,this.base(a))}})),IE7.HTML.extend({elements:{},addRecalc:function(a,b){this.base(a,function(a){this.elements[a.uniqueID]||(b(a),this.elements[a.uniqueID]=a)})}}),document.recalc=function(a){IE7.CSS.screen&&(a&&IE7.CSS.reload(),IE7.recalc())})}();
|
||||
//# sourceMappingURL=../../../maps/libs/IE/ie7-recalc.js.map
|
||||
File diff suppressed because one or more lines are too long
+3
-1867
File diff suppressed because one or more lines are too long
Vendored
+2
-850
File diff suppressed because one or more lines are too long
Vendored
+6
-9247
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-420
File diff suppressed because one or more lines are too long
+3
-5
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,97 +1,2 @@
|
||||
/**
|
||||
* Cookie plugin
|
||||
*
|
||||
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a cookie with the given name and value and other optional parameters.
|
||||
*
|
||||
* @example $.cookie('the_cookie', 'the_value');
|
||||
* @desc Set the value of a cookie.
|
||||
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
|
||||
* @desc Create a cookie with all available options.
|
||||
* @example $.cookie('the_cookie', 'the_value');
|
||||
* @desc Create a session cookie.
|
||||
* @example $.cookie('the_cookie', null);
|
||||
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
|
||||
* used when the cookie was set.
|
||||
*
|
||||
* @param String name The name of the cookie.
|
||||
* @param String value The value of the cookie.
|
||||
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
|
||||
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
|
||||
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
|
||||
* If set to null or omitted, the cookie will be a session cookie and will not be retained
|
||||
* when the the browser exits.
|
||||
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
|
||||
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
|
||||
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
|
||||
* require a secure protocol (like HTTPS).
|
||||
* @type undefined
|
||||
*
|
||||
* @name $.cookie
|
||||
* @cat Plugins/Cookie
|
||||
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the value of a cookie with the given name.
|
||||
*
|
||||
* @example $.cookie('the_cookie');
|
||||
* @desc Get the value of a cookie.
|
||||
*
|
||||
* @param String name The name of the cookie.
|
||||
* @return The value of the cookie.
|
||||
* @type String
|
||||
*
|
||||
* @name $.cookie
|
||||
* @cat Plugins/Cookie
|
||||
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||
*/
|
||||
jQuery.cookie = function(name, value, options) {
|
||||
if (typeof value != 'undefined') { // name and value given, set cookie
|
||||
options = options || {};
|
||||
if (value === null) {
|
||||
value = '';
|
||||
options = $.extend({}, options); // clone object since it's unexpected behavior if the expired property were changed
|
||||
options.expires = -1;
|
||||
}
|
||||
var expires = '';
|
||||
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
|
||||
var date;
|
||||
if (typeof options.expires == 'number') {
|
||||
date = new Date();
|
||||
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
|
||||
} else {
|
||||
date = options.expires;
|
||||
}
|
||||
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
|
||||
}
|
||||
// NOTE Needed to parenthesize options.path and options.domain
|
||||
// in the following expressions, otherwise they evaluate to undefined
|
||||
// in the packed version for some reason...
|
||||
var path = options.path ? '; path=' + (options.path) : '';
|
||||
var domain = options.domain ? '; domain=' + (options.domain) : '';
|
||||
var secure = options.secure ? '; secure' : '';
|
||||
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
|
||||
} else { // only name given, get cookie
|
||||
var cookieValue = null;
|
||||
if (document.cookie && document.cookie != '') {
|
||||
var cookies = document.cookie.split(';');
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var cookie = jQuery.trim(cookies[i]);
|
||||
// Does this cookie string begin with the name we want?
|
||||
if (cookie.substring(0, name.length + 1) == (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
};
|
||||
jQuery.cookie=function(a,b,c){if("undefined"==typeof b){var d=null;if(document.cookie&&""!=document.cookie)for(var e=document.cookie.split(";"),f=0;f<e.length;f++){var g=jQuery.trim(e[f]);if(g.substring(0,a.length+1)==a+"="){d=decodeURIComponent(g.substring(a.length+1));break}}return d}c=c||{},null===b&&(b="",c=$.extend({},c),c.expires=-1);var h="";if(c.expires&&("number"==typeof c.expires||c.expires.toUTCString)){var i;"number"==typeof c.expires?(i=new Date,i.setTime(i.getTime()+24*c.expires*60*60*1e3)):i=c.expires,h="; expires="+i.toUTCString()}var j=c.path?"; path="+c.path:"",k=c.domain?"; domain="+c.domain:"",l=c.secure?"; secure":"";document.cookie=[a,"=",encodeURIComponent(b),h,j,k,l].join("")};
|
||||
//# sourceMappingURL=../../../maps/libs/jquery/jquery.cookie.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,302 +1,2 @@
|
||||
/*!
|
||||
* jquery.event.drop - v 2.2
|
||||
* Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
|
||||
* Open Source MIT License - http://threedubmedia.com/code/license
|
||||
*/
|
||||
// Created: 2008-06-04
|
||||
// Updated: 2012-05-21
|
||||
// REQUIRES: jquery 1.7.x, event.drag 2.2
|
||||
|
||||
;(function($){ // secure $ jQuery alias
|
||||
|
||||
// Events: drop, dropstart, dropend
|
||||
|
||||
// add the jquery instance method
|
||||
$.fn.drop = function( str, arg, opts ){
|
||||
// figure out the event type
|
||||
var type = typeof str == "string" ? str : "",
|
||||
// figure out the event handler...
|
||||
fn = $.isFunction( str ) ? str : $.isFunction( arg ) ? arg : null;
|
||||
// fix the event type
|
||||
if ( type.indexOf("drop") !== 0 )
|
||||
type = "drop"+ type;
|
||||
// were options passed
|
||||
opts = ( str == fn ? arg : opts ) || {};
|
||||
// trigger or bind event handler
|
||||
return fn ? this.bind( type, opts, fn ) : this.trigger( type );
|
||||
};
|
||||
|
||||
// DROP MANAGEMENT UTILITY
|
||||
// returns filtered drop target elements, caches their positions
|
||||
$.drop = function( opts ){
|
||||
opts = opts || {};
|
||||
// safely set new options...
|
||||
drop.multi = opts.multi === true ? Infinity :
|
||||
opts.multi === false ? 1 : !isNaN( opts.multi ) ? opts.multi : drop.multi;
|
||||
drop.delay = opts.delay || drop.delay;
|
||||
drop.tolerance = $.isFunction( opts.tolerance ) ? opts.tolerance :
|
||||
opts.tolerance === null ? null : drop.tolerance;
|
||||
drop.mode = opts.mode || drop.mode || 'intersect';
|
||||
};
|
||||
|
||||
// local refs (increase compression)
|
||||
var $event = $.event,
|
||||
$special = $event.special,
|
||||
// configure the drop special event
|
||||
drop = $.event.special.drop = {
|
||||
|
||||
// these are the default settings
|
||||
multi: 1, // allow multiple drop winners per dragged element
|
||||
delay: 20, // async timeout delay
|
||||
mode: 'overlap', // drop tolerance mode
|
||||
|
||||
// internal cache
|
||||
targets: [],
|
||||
|
||||
// the key name for stored drop data
|
||||
datakey: "dropdata",
|
||||
|
||||
// prevent bubbling for better performance
|
||||
noBubble: true,
|
||||
|
||||
// count bound related events
|
||||
add: function( obj ){
|
||||
// read the interaction data
|
||||
var data = $.data( this, drop.datakey );
|
||||
// count another realted event
|
||||
data.related += 1;
|
||||
},
|
||||
|
||||
// forget unbound related events
|
||||
remove: function(){
|
||||
$.data( this, drop.datakey ).related -= 1;
|
||||
},
|
||||
|
||||
// configure the interactions
|
||||
setup: function(){
|
||||
// check for related events
|
||||
if ( $.data( this, drop.datakey ) )
|
||||
return;
|
||||
// initialize the drop element data
|
||||
var data = {
|
||||
related: 0,
|
||||
active: [],
|
||||
anyactive: 0,
|
||||
winner: 0,
|
||||
location: {}
|
||||
};
|
||||
// store the drop data on the element
|
||||
$.data( this, drop.datakey, data );
|
||||
// store the drop target in internal cache
|
||||
drop.targets.push( this );
|
||||
},
|
||||
|
||||
// destroy the configure interaction
|
||||
teardown: function(){
|
||||
var data = $.data( this, drop.datakey ) || {};
|
||||
// check for related events
|
||||
if ( data.related )
|
||||
return;
|
||||
// remove the stored data
|
||||
$.removeData( this, drop.datakey );
|
||||
// reference the targeted element
|
||||
var element = this;
|
||||
// remove from the internal cache
|
||||
drop.targets = $.grep( drop.targets, function( target ){
|
||||
return ( target !== element );
|
||||
});
|
||||
},
|
||||
|
||||
// shared event handler
|
||||
handler: function( event, dd ){
|
||||
// local vars
|
||||
var results, $targets;
|
||||
// make sure the right data is available
|
||||
if ( !dd )
|
||||
return;
|
||||
// handle various events
|
||||
switch ( event.type ){
|
||||
// draginit, from $.event.special.drag
|
||||
case 'mousedown': // DROPINIT >>
|
||||
case 'touchstart': // DROPINIT >>
|
||||
// collect and assign the drop targets
|
||||
$targets = $( drop.targets );
|
||||
if ( typeof dd.drop == "string" )
|
||||
$targets = $targets.filter( dd.drop );
|
||||
// reset drop data winner properties
|
||||
$targets.each(function(){
|
||||
var data = $.data( this, drop.datakey );
|
||||
data.active = [];
|
||||
data.anyactive = 0;
|
||||
data.winner = 0;
|
||||
});
|
||||
// set available target elements
|
||||
dd.droppable = $targets;
|
||||
// activate drop targets for the initial element being dragged
|
||||
$special.drag.hijack( event, "dropinit", dd );
|
||||
break;
|
||||
// drag, from $.event.special.drag
|
||||
case 'mousemove': // TOLERATE >>
|
||||
case 'touchmove': // TOLERATE >>
|
||||
drop.event = event; // store the mousemove event
|
||||
if ( !drop.timer )
|
||||
// monitor drop targets
|
||||
drop.tolerate( dd );
|
||||
break;
|
||||
// dragend, from $.event.special.drag
|
||||
case 'mouseup': // DROP >> DROPEND >>
|
||||
case 'touchend': // DROP >> DROPEND >>
|
||||
drop.timer = clearTimeout( drop.timer ); // delete timer
|
||||
if ( dd.propagates ){
|
||||
$special.drag.hijack( event, "drop", dd );
|
||||
$special.drag.hijack( event, "dropend", dd );
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
// returns the location positions of an element
|
||||
locate: function( elem, index ){
|
||||
var data = $.data( elem, drop.datakey ),
|
||||
$elem = $( elem ),
|
||||
posi = $elem.offset() || {},
|
||||
height = $elem.outerHeight(),
|
||||
width = $elem.outerWidth(),
|
||||
location = {
|
||||
elem: elem,
|
||||
width: width,
|
||||
height: height,
|
||||
top: posi.top,
|
||||
left: posi.left,
|
||||
right: posi.left + width,
|
||||
bottom: posi.top + height
|
||||
};
|
||||
// drag elements might not have dropdata
|
||||
if ( data ){
|
||||
data.location = location;
|
||||
data.index = index;
|
||||
data.elem = elem;
|
||||
}
|
||||
return location;
|
||||
},
|
||||
|
||||
// test the location positions of an element against another OR an X,Y coord
|
||||
contains: function( target, test ){ // target { location } contains test [x,y] or { location }
|
||||
return ( ( test[0] || test.left ) >= target.left && ( test[0] || test.right ) <= target.right
|
||||
&& ( test[1] || test.top ) >= target.top && ( test[1] || test.bottom ) <= target.bottom );
|
||||
},
|
||||
|
||||
// stored tolerance modes
|
||||
modes: { // fn scope: "$.event.special.drop" object
|
||||
// target with mouse wins, else target with most overlap wins
|
||||
'intersect': function( event, proxy, target ){
|
||||
return this.contains( target, [ event.pageX, event.pageY ] ) ? // check cursor
|
||||
1e9 : this.modes.overlap.apply( this, arguments ); // check overlap
|
||||
},
|
||||
// target with most overlap wins
|
||||
'overlap': function( event, proxy, target ){
|
||||
// calculate the area of overlap...
|
||||
return Math.max( 0, Math.min( target.bottom, proxy.bottom ) - Math.max( target.top, proxy.top ) )
|
||||
* Math.max( 0, Math.min( target.right, proxy.right ) - Math.max( target.left, proxy.left ) );
|
||||
},
|
||||
// proxy is completely contained within target bounds
|
||||
'fit': function( event, proxy, target ){
|
||||
return this.contains( target, proxy ) ? 1 : 0;
|
||||
},
|
||||
// center of the proxy is contained within target bounds
|
||||
'middle': function( event, proxy, target ){
|
||||
return this.contains( target, [ proxy.left + proxy.width * .5, proxy.top + proxy.height * .5 ] ) ? 1 : 0;
|
||||
}
|
||||
},
|
||||
|
||||
// sort drop target cache by by winner (dsc), then index (asc)
|
||||
sort: function( a, b ){
|
||||
return ( b.winner - a.winner ) || ( a.index - b.index );
|
||||
},
|
||||
|
||||
// async, recursive tolerance execution
|
||||
tolerate: function( dd ){
|
||||
// declare local refs
|
||||
var i, drp, drg, data, arr, len, elem,
|
||||
// interaction iteration variables
|
||||
x = 0, ia, end = dd.interactions.length,
|
||||
// determine the mouse coords
|
||||
xy = [ drop.event.pageX, drop.event.pageY ],
|
||||
// custom or stored tolerance fn
|
||||
tolerance = drop.tolerance || drop.modes[ drop.mode ];
|
||||
// go through each passed interaction...
|
||||
do if ( ia = dd.interactions[x] ){
|
||||
// check valid interaction
|
||||
if ( !ia )
|
||||
return;
|
||||
// initialize or clear the drop data
|
||||
ia.drop = [];
|
||||
// holds the drop elements
|
||||
arr = [];
|
||||
len = ia.droppable.length;
|
||||
// determine the proxy location, if needed
|
||||
if ( tolerance )
|
||||
drg = drop.locate( ia.proxy );
|
||||
// reset the loop
|
||||
i = 0;
|
||||
// loop each stored drop target
|
||||
do if ( elem = ia.droppable[i] ){
|
||||
data = $.data( elem, drop.datakey );
|
||||
drp = data.location;
|
||||
if ( !drp ) continue;
|
||||
// find a winner: tolerance function is defined, call it
|
||||
data.winner = tolerance ? tolerance.call( drop, drop.event, drg, drp )
|
||||
// mouse position is always the fallback
|
||||
: drop.contains( drp, xy ) ? 1 : 0;
|
||||
arr.push( data );
|
||||
} while ( ++i < len ); // loop
|
||||
// sort the drop targets
|
||||
arr.sort( drop.sort );
|
||||
// reset the loop
|
||||
i = 0;
|
||||
// loop through all of the targets again
|
||||
do if ( data = arr[ i ] ){
|
||||
// winners...
|
||||
if ( data.winner && ia.drop.length < drop.multi ){
|
||||
// new winner... dropstart
|
||||
if ( !data.active[x] && !data.anyactive ){
|
||||
// check to make sure that this is not prevented
|
||||
if ( $special.drag.hijack( drop.event, "dropstart", dd, x, data.elem )[0] !== false ){
|
||||
data.active[x] = 1;
|
||||
data.anyactive += 1;
|
||||
}
|
||||
// if false, it is not a winner
|
||||
else
|
||||
data.winner = 0;
|
||||
}
|
||||
// if it is still a winner
|
||||
if ( data.winner )
|
||||
ia.drop.push( data.elem );
|
||||
}
|
||||
// losers...
|
||||
else if ( data.active[x] && data.anyactive == 1 ){
|
||||
// former winner... dropend
|
||||
$special.drag.hijack( drop.event, "dropend", dd, x, data.elem );
|
||||
data.active[x] = 0;
|
||||
data.anyactive -= 1;
|
||||
}
|
||||
} while ( ++i < len ); // loop
|
||||
} while ( ++x < end ) // loop
|
||||
// check if the mouse is still moving or is idle
|
||||
if ( drop.last && xy[0] == drop.last.pageX && xy[1] == drop.last.pageY )
|
||||
delete drop.timer; // idle, don't recurse
|
||||
else // recurse
|
||||
drop.timer = setTimeout(function(){
|
||||
drop.tolerate( dd );
|
||||
}, drop.delay );
|
||||
// remember event, to compare idleness
|
||||
drop.last = drop.event;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// share the same special event configuration with related events...
|
||||
$special.dropinit = $special.dropstart = $special.dropend = drop;
|
||||
|
||||
})(jQuery); // confine scope
|
||||
!function(a){a.fn.drop=function(b,c,d){var e="string"==typeof b?b:"",f=a.isFunction(b)?b:a.isFunction(c)?c:null;return 0!==e.indexOf("drop")&&(e="drop"+e),d=(b==f?c:d)||{},f?this.bind(e,d,f):this.trigger(e)},a.drop=function(b){b=b||{},d.multi=b.multi===!0?1/0:b.multi===!1?1:isNaN(b.multi)?d.multi:b.multi,d.delay=b.delay||d.delay,d.tolerance=a.isFunction(b.tolerance)?b.tolerance:null===b.tolerance?null:d.tolerance,d.mode=b.mode||d.mode||"intersect"};var b=a.event,c=b.special,d=a.event.special.drop={multi:1,delay:20,mode:"overlap",targets:[],datakey:"dropdata",noBubble:!0,add:function(){var b=a.data(this,d.datakey);b.related+=1},remove:function(){a.data(this,d.datakey).related-=1},setup:function(){if(!a.data(this,d.datakey)){var b={related:0,active:[],anyactive:0,winner:0,location:{}};a.data(this,d.datakey,b),d.targets.push(this)}},teardown:function(){var b=a.data(this,d.datakey)||{};if(!b.related){a.removeData(this,d.datakey);var c=this;d.targets=a.grep(d.targets,function(a){return a!==c})}},handler:function(b,e){var f;if(e)switch(b.type){case"mousedown":case"touchstart":f=a(d.targets),"string"==typeof e.drop&&(f=f.filter(e.drop)),f.each(function(){var b=a.data(this,d.datakey);b.active=[],b.anyactive=0,b.winner=0}),e.droppable=f,c.drag.hijack(b,"dropinit",e);break;case"mousemove":case"touchmove":d.event=b,d.timer||d.tolerate(e);break;case"mouseup":case"touchend":d.timer=clearTimeout(d.timer),e.propagates&&(c.drag.hijack(b,"drop",e),c.drag.hijack(b,"dropend",e))}},locate:function(b,c){var e=a.data(b,d.datakey),f=a(b),g=f.offset()||{},h=f.outerHeight(),i=f.outerWidth(),j={elem:b,width:i,height:h,top:g.top,left:g.left,right:g.left+i,bottom:g.top+h};return e&&(e.location=j,e.index=c,e.elem=b),j},contains:function(a,b){return(b[0]||b.left)>=a.left&&(b[0]||b.right)<=a.right&&(b[1]||b.top)>=a.top&&(b[1]||b.bottom)<=a.bottom},modes:{intersect:function(a,b,c){return this.contains(c,[a.pageX,a.pageY])?1e9:this.modes.overlap.apply(this,arguments)},overlap:function(a,b,c){return Math.max(0,Math.min(c.bottom,b.bottom)-Math.max(c.top,b.top))*Math.max(0,Math.min(c.right,b.right)-Math.max(c.left,b.left))},fit:function(a,b,c){return this.contains(c,b)?1:0},middle:function(a,b,c){return this.contains(c,[b.left+.5*b.width,b.top+.5*b.height])?1:0}},sort:function(a,b){return b.winner-a.winner||a.index-b.index},tolerate:function(b){var e,f,g,h,i,j,k,l,m=0,n=b.interactions.length,o=[d.event.pageX,d.event.pageY],p=d.tolerance||d.modes[d.mode];do if(l=b.interactions[m]){if(!l)return;l.drop=[],i=[],j=l.droppable.length,p&&(g=d.locate(l.proxy)),e=0;do if(k=l.droppable[e]){if(h=a.data(k,d.datakey),f=h.location,!f)continue;h.winner=p?p.call(d,d.event,g,f):d.contains(f,o)?1:0,i.push(h)}while(++e<j);i.sort(d.sort),e=0;do(h=i[e])&&(h.winner&&l.drop.length<d.multi?(h.active[m]||h.anyactive||(c.drag.hijack(d.event,"dropstart",b,m,h.elem)[0]!==!1?(h.active[m]=1,h.anyactive+=1):h.winner=0),h.winner&&l.drop.push(h.elem)):h.active[m]&&1==h.anyactive&&(c.drag.hijack(d.event,"dropend",b,m,h.elem),h.active[m]=0,h.anyactive-=1));while(++e<j)}while(++m<n);d.last&&o[0]==d.last.pageX&&o[1]==d.last.pageY?delete d.timer:d.timer=setTimeout(function(){d.tolerate(b)},d.delay),d.last=d.event}};c.dropinit=c.dropstart=c.dropend=d}(jQuery);
|
||||
//# sourceMappingURL=../../../maps/libs/jquery/jquery.event.drop.js.map
|
||||
@@ -1,84 +1,2 @@
|
||||
;(function($){ // secure $ jQuery alias
|
||||
/*******************************************************************************************/
|
||||
// jquery.event.hover.js
|
||||
// Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
|
||||
// Licensed under the MIT License (MIT-LICENSE.txt)
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
// JQuery 1.9+ compatible version
|
||||
//
|
||||
// Optional settings :
|
||||
// $.event.special.hover.delay = 100;
|
||||
// Defines the delay (msec) while mouse is inside the element before checking the speed
|
||||
// $.event.special.hover.speed = 100;
|
||||
// Defines the maximum speed (px/sec) the mouse may be moving to trigger the hover event
|
||||
/*******************************************************************************************/
|
||||
|
||||
// save the old jquery "hover" method
|
||||
$.fn._hover = $.fn.hover;
|
||||
|
||||
// jquery method
|
||||
$.fn.hover = function( fn1, fn2, fn3 ) {
|
||||
if ( fn3 ) this.bind('hoverstart', fn1 ); // 3 args
|
||||
if ( fn2 ) this.bind('hoverend', fn3 ? fn3 : fn2 ); // 2+ args
|
||||
return !fn1 ? this.trigger('hover') // 0 args
|
||||
: this.bind('hover', fn3 ? fn2 : fn1 ); // 1+ args
|
||||
};
|
||||
|
||||
// special event configuration
|
||||
var hover = $.event.special.hover = {
|
||||
delay: 100, // milliseconds
|
||||
speed: 100, // pixels per second
|
||||
setup: function( data ){
|
||||
data = $.extend({ speed: hover.speed, delay: hover.delay, hovered:0 }, data||{} );
|
||||
$.event.add( this, "mouseenter mouseleave", hoverHandler, data );
|
||||
},
|
||||
teardown: function(){
|
||||
$.event.remove( this, "mouseenter mouseleave", hoverHandler );
|
||||
}
|
||||
};
|
||||
|
||||
// shared event handler
|
||||
function hoverHandler( event ){
|
||||
var data = event.data || event;
|
||||
switch ( event.type ){
|
||||
case 'mouseenter': // mouseover
|
||||
data.dist2 = 0; // init mouse distance²
|
||||
data.event = event; // store the event
|
||||
event.type = "hoverstart"; // hijack event
|
||||
if($.event.dispatch.call(this, event) !== false) {
|
||||
data.elem = this; // ref to the current element
|
||||
$.event.add( this, "mousemove", hoverHandler, data ); // track the mouse
|
||||
data.timer = setTimeout( compare, data.delay ); // start async compare
|
||||
}
|
||||
break;
|
||||
case 'mousemove': // track the event, mouse distance² = x² + y²
|
||||
data.dist2 += Math.pow( event.pageX-data.event.pageX, 2 )
|
||||
+ Math.pow( event.pageY-data.event.pageY, 2 );
|
||||
data.event = event; // store current event
|
||||
break;
|
||||
case 'mouseleave': // mouseout
|
||||
clearTimeout( data.timer ); // uncompare
|
||||
if ( data.hovered ){
|
||||
event.type = "hoverend"; // hijack event
|
||||
$.event.dispatch.call(this, event); // handle "hoverend"
|
||||
data.hovered--; // reset flag
|
||||
}
|
||||
else $.event.remove( data.elem, "mousemove", hoverHandler ); // untrack
|
||||
break;
|
||||
default: // timeout compare // distance² = x² + y² = ( speed * time )²
|
||||
if ( data.dist2 <= Math.pow( data.speed*( data.delay/1e3 ), 2 ) ){ // speed acceptable
|
||||
$.event.remove( data.elem, "mousemove", hoverHandler ); // untrack
|
||||
data.event.type = "hover"; // hijack event
|
||||
if($.event.dispatch.call(data.elem, data.event) !== false) // handle "hover"
|
||||
data.hovered++; // flag for "hoverend"
|
||||
}
|
||||
else data.timer = setTimeout( compare, data.delay ); // async recurse
|
||||
data.dist2 = 0; // reset distance² for next compare
|
||||
break;
|
||||
}
|
||||
function compare(){ hoverHandler( data ); }; // timeout/recursive function
|
||||
};
|
||||
|
||||
/*******************************************************************************************/
|
||||
})(jQuery); // confine scope
|
||||
!function(a){function b(c){function d(){b(e)}var e=c.data||c;switch(c.type){case"mouseenter":e.dist2=0,e.event=c,c.type="hoverstart",a.event.dispatch.call(this,c)!==!1&&(e.elem=this,a.event.add(this,"mousemove",b,e),e.timer=setTimeout(d,e.delay));break;case"mousemove":e.dist2+=Math.pow(c.pageX-e.event.pageX,2)+Math.pow(c.pageY-e.event.pageY,2),e.event=c;break;case"mouseleave":clearTimeout(e.timer),e.hovered?(c.type="hoverend",a.event.dispatch.call(this,c),e.hovered--):a.event.remove(e.elem,"mousemove",b);break;default:e.dist2<=Math.pow(e.speed*(e.delay/1e3),2)?(a.event.remove(e.elem,"mousemove",b),e.event.type="hover",a.event.dispatch.call(e.elem,e.event)!==!1&&e.hovered++):e.timer=setTimeout(d,e.delay),e.dist2=0}}a.fn._hover=a.fn.hover,a.fn.hover=function(a,b,c){return c&&this.bind("hoverstart",a),b&&this.bind("hoverend",c?c:b),a?this.bind("hover",c?b:a):this.trigger("hover")};var c=a.event.special.hover={delay:100,speed:100,setup:function(d){d=a.extend({speed:c.speed,delay:c.delay,hovered:0},d||{}),a.event.add(this,"mouseenter mouseleave",b,d)},teardown:function(){a.event.remove(this,"mouseenter mouseleave",b)}}}(jQuery);
|
||||
//# sourceMappingURL=../../../maps/libs/jquery/jquery.event.hover.js.map
|
||||
File diff suppressed because one or more lines are too long
Vendored
+5
-10345
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,125 +1,2 @@
|
||||
/*! Copyright (c) 2013 Brandon Aaron (http://brandonaaron.net)
|
||||
* Licensed under the MIT License (LICENSE.txt).
|
||||
*
|
||||
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
|
||||
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
|
||||
* Thanks to: Seamus Leahy for adding deltaX and deltaY
|
||||
*
|
||||
* Version: 3.1.3
|
||||
*
|
||||
* Requires: 1.2.2+
|
||||
*/
|
||||
|
||||
(function (factory) {
|
||||
// GALAXY HACK
|
||||
// (JG): Galaxy's mixing of a global jQuery and require modules doesn't work with
|
||||
// the logic below. Instead, do the right thing for this configuration without any checks.
|
||||
factory(jQuery);
|
||||
// END HACK
|
||||
|
||||
/*
|
||||
if ( typeof define === 'function' && define.amd ) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS style for Browserify
|
||||
module.exports = factory;
|
||||
} else {
|
||||
// Browser globals
|
||||
factory(jQuery);
|
||||
}
|
||||
*/
|
||||
}(function ($) {
|
||||
|
||||
var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
|
||||
var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
|
||||
var lowestDelta, lowestDeltaXY;
|
||||
|
||||
if ( $.event.fixHooks ) {
|
||||
for ( var i = toFix.length; i; ) {
|
||||
$.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
|
||||
}
|
||||
}
|
||||
|
||||
$.event.special.mousewheel = {
|
||||
setup: function() {
|
||||
if ( this.addEventListener ) {
|
||||
for ( var i = toBind.length; i; ) {
|
||||
this.addEventListener( toBind[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = handler;
|
||||
}
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
if ( this.removeEventListener ) {
|
||||
for ( var i = toBind.length; i; ) {
|
||||
this.removeEventListener( toBind[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.extend({
|
||||
mousewheel: function(fn) {
|
||||
return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
|
||||
},
|
||||
|
||||
unmousewheel: function(fn) {
|
||||
return this.unbind("mousewheel", fn);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function handler(event) {
|
||||
var orgEvent = event || window.event,
|
||||
args = [].slice.call(arguments, 1),
|
||||
delta = 0,
|
||||
deltaX = 0,
|
||||
deltaY = 0,
|
||||
absDelta = 0,
|
||||
absDeltaXY = 0,
|
||||
fn;
|
||||
event = $.event.fix(orgEvent);
|
||||
event.type = "mousewheel";
|
||||
|
||||
// Old school scrollwheel delta
|
||||
if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
|
||||
if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
|
||||
|
||||
// New school wheel delta (wheel event)
|
||||
if ( orgEvent.deltaY ) {
|
||||
deltaY = orgEvent.deltaY * -1;
|
||||
delta = deltaY;
|
||||
}
|
||||
if ( orgEvent.deltaX ) {
|
||||
deltaX = orgEvent.deltaX;
|
||||
delta = deltaX * -1;
|
||||
}
|
||||
|
||||
// Webkit
|
||||
if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
|
||||
if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }
|
||||
|
||||
// Look for lowest delta to normalize the delta values
|
||||
absDelta = Math.abs(delta);
|
||||
if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
|
||||
absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
|
||||
if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
|
||||
|
||||
// Get a whole value for the deltas
|
||||
fn = delta > 0 ? 'floor' : 'ceil';
|
||||
delta = Math[fn](delta / lowestDelta);
|
||||
deltaX = Math[fn](deltaX / lowestDeltaXY);
|
||||
deltaY = Math[fn](deltaY / lowestDeltaXY);
|
||||
|
||||
// Add event and delta to the front of the arguments
|
||||
args.unshift(event, delta, deltaX, deltaY);
|
||||
|
||||
return ($.event.dispatch || $.event.handle).apply(this, args);
|
||||
}
|
||||
|
||||
}));
|
||||
!function(a){a(jQuery)}(function(a){function b(b){var e,f=b||window.event,g=[].slice.call(arguments,1),h=0,i=0,j=0,k=0,l=0;return b=a.event.fix(f),b.type="mousewheel",f.wheelDelta&&(h=f.wheelDelta),f.detail&&(h=-1*f.detail),f.deltaY&&(j=-1*f.deltaY,h=j),f.deltaX&&(i=f.deltaX,h=-1*i),void 0!==f.wheelDeltaY&&(j=f.wheelDeltaY),void 0!==f.wheelDeltaX&&(i=-1*f.wheelDeltaX),k=Math.abs(h),(!c||c>k)&&(c=k),l=Math.max(Math.abs(j),Math.abs(i)),(!d||d>l)&&(d=l),e=h>0?"floor":"ceil",h=Math[e](h/c),i=Math[e](i/d),j=Math[e](j/d),g.unshift(b,h,i,j),(a.event.dispatch||a.event.handle).apply(this,g)}var c,d,e=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],f="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"];if(a.event.fixHooks)for(var g=e.length;g;)a.event.fixHooks[e[--g]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=f.length;a;)this.addEventListener(f[--a],b,!1);else this.onmousewheel=b},teardown:function(){if(this.removeEventListener)for(var a=f.length;a;)this.removeEventListener(f[--a],b,!1);else this.onmousewheel=null}},a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
|
||||
//# sourceMappingURL=../../../maps/libs/jquery/jquery.mousewheel.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
-933
File diff suppressed because one or more lines are too long
Vendored
+5
-6742
File diff suppressed because one or more lines are too long
+3
-3507
File diff suppressed because one or more lines are too long
+2
-1910
File diff suppressed because one or more lines are too long
+2
-1838
File diff suppressed because one or more lines are too long
+2
-2053
File diff suppressed because one or more lines are too long
@@ -1,307 +1,2 @@
|
||||
/*
|
||||
* Toastr
|
||||
* Version 2.0.1
|
||||
* Copyright 2012 John Papa and Hans Fjällemark.
|
||||
* All Rights Reserved.
|
||||
* Use, reproduction, distribution, and modification of this code is subject to the terms and
|
||||
* conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Author: John Papa and Hans Fjällemark
|
||||
* Project: https://github.com/CodeSeven/toastr
|
||||
*/
|
||||
; (function (define) {
|
||||
define([], function () {
|
||||
var $ = jQuery;
|
||||
return (function () {
|
||||
var version = '2.0.1';
|
||||
var $container;
|
||||
var listener;
|
||||
var toastId = 0;
|
||||
var toastType = {
|
||||
error: 'error',
|
||||
info: 'info',
|
||||
success: 'success',
|
||||
warning: 'warning'
|
||||
};
|
||||
|
||||
var toastr = {
|
||||
clear: clear,
|
||||
error: error,
|
||||
getContainer: getContainer,
|
||||
info: info,
|
||||
options: {},
|
||||
subscribe: subscribe,
|
||||
success: success,
|
||||
version: version,
|
||||
warning: warning
|
||||
};
|
||||
|
||||
return toastr;
|
||||
|
||||
//#region Accessible Methods
|
||||
function error(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.error,
|
||||
iconClass: getOptions().iconClasses.error,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function info(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.info,
|
||||
iconClass: getOptions().iconClasses.info,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function subscribe(callback) {
|
||||
listener = callback;
|
||||
}
|
||||
|
||||
function success(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.success,
|
||||
iconClass: getOptions().iconClasses.success,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function warning(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.warning,
|
||||
iconClass: getOptions().iconClasses.warning,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function clear($toastElement) {
|
||||
var options = getOptions();
|
||||
if (!$container) { getContainer(options); }
|
||||
if ($toastElement && $(':focus', $toastElement).length === 0) {
|
||||
$toastElement[options.hideMethod]({
|
||||
duration: options.hideDuration,
|
||||
easing: options.hideEasing,
|
||||
complete: function () { removeToast($toastElement); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
if ($container.children().length) {
|
||||
$container[options.hideMethod]({
|
||||
duration: options.hideDuration,
|
||||
easing: options.hideEasing,
|
||||
complete: function () { $container.remove(); }
|
||||
});
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Internal Methods
|
||||
|
||||
function getDefaults() {
|
||||
return {
|
||||
tapToDismiss: true,
|
||||
toastClass: 'toast',
|
||||
containerId: 'toast-container',
|
||||
debug: false,
|
||||
|
||||
showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
|
||||
showDuration: 300,
|
||||
showEasing: 'swing', //swing and linear are built into jQuery
|
||||
onShown: undefined,
|
||||
hideMethod: 'fadeOut',
|
||||
hideDuration: 1000,
|
||||
hideEasing: 'swing',
|
||||
onHidden: undefined,
|
||||
|
||||
extendedTimeOut: 1000,
|
||||
iconClasses: {
|
||||
error: 'toast-error',
|
||||
info: 'toast-info',
|
||||
success: 'toast-success',
|
||||
warning: 'toast-warning'
|
||||
},
|
||||
iconClass: 'toast-info',
|
||||
positionClass: 'toast-top-right',
|
||||
timeOut: 5000, // Set timeOut and extendedTimeout to 0 to make it sticky
|
||||
titleClass: 'toast-title',
|
||||
messageClass: 'toast-message',
|
||||
target: 'body',
|
||||
closeHtml: '<button>×</button>',
|
||||
newestOnTop: true
|
||||
};
|
||||
}
|
||||
|
||||
function publish(args) {
|
||||
if (!listener) {
|
||||
return;
|
||||
}
|
||||
listener(args);
|
||||
}
|
||||
|
||||
function notify(map) {
|
||||
var
|
||||
options = getOptions(),
|
||||
iconClass = map.iconClass || options.iconClass;
|
||||
|
||||
if (typeof (map.optionsOverride) !== 'undefined') {
|
||||
options = $.extend(options, map.optionsOverride);
|
||||
iconClass = map.optionsOverride.iconClass || iconClass;
|
||||
}
|
||||
|
||||
toastId++;
|
||||
|
||||
$container = getContainer(options);
|
||||
var
|
||||
intervalId = null,
|
||||
$toastElement = $('<div/>'),
|
||||
$titleElement = $('<div/>'),
|
||||
$messageElement = $('<div/>'),
|
||||
$closeElement = $(options.closeHtml),
|
||||
response = {
|
||||
toastId: toastId,
|
||||
state: 'visible',
|
||||
startTime: new Date(),
|
||||
options: options,
|
||||
map: map
|
||||
};
|
||||
|
||||
if (map.iconClass) {
|
||||
$toastElement.addClass(options.toastClass).addClass(iconClass);
|
||||
}
|
||||
|
||||
if (map.title) {
|
||||
$titleElement.append(map.title).addClass(options.titleClass);
|
||||
$toastElement.append($titleElement);
|
||||
}
|
||||
|
||||
if (map.message) {
|
||||
$messageElement.append(map.message).addClass(options.messageClass);
|
||||
$toastElement.append($messageElement);
|
||||
}
|
||||
|
||||
if (options.closeButton) {
|
||||
$closeElement.addClass('toast-close-button');
|
||||
$toastElement.prepend($closeElement);
|
||||
}
|
||||
|
||||
$toastElement.hide();
|
||||
if (options.newestOnTop) {
|
||||
$container.prepend($toastElement);
|
||||
} else {
|
||||
$container.append($toastElement);
|
||||
}
|
||||
|
||||
|
||||
$toastElement[options.showMethod](
|
||||
{ duration: options.showDuration, easing: options.showEasing, complete: options.onShown }
|
||||
);
|
||||
if (options.timeOut > 0) {
|
||||
intervalId = setTimeout(hideToast, options.timeOut);
|
||||
}
|
||||
|
||||
$toastElement.hover(stickAround, delayedhideToast);
|
||||
if (!options.onclick && options.tapToDismiss) {
|
||||
$toastElement.click(hideToast);
|
||||
}
|
||||
if (options.closeButton && $closeElement) {
|
||||
$closeElement.click(function (event) {
|
||||
event.stopPropagation();
|
||||
hideToast(true);
|
||||
});
|
||||
}
|
||||
|
||||
if (options.onclick) {
|
||||
$toastElement.click(function () {
|
||||
options.onclick();
|
||||
hideToast();
|
||||
});
|
||||
}
|
||||
|
||||
publish(response);
|
||||
|
||||
if (options.debug && console) {
|
||||
console.log(response);
|
||||
}
|
||||
|
||||
return $toastElement;
|
||||
|
||||
function hideToast(override) {
|
||||
if ($(':focus', $toastElement).length && !override) {
|
||||
return;
|
||||
}
|
||||
return $toastElement[options.hideMethod]({
|
||||
duration: options.hideDuration,
|
||||
easing: options.hideEasing,
|
||||
complete: function () {
|
||||
removeToast($toastElement);
|
||||
if (options.onHidden) {
|
||||
options.onHidden();
|
||||
}
|
||||
response.state = 'hidden';
|
||||
response.endTime = new Date(),
|
||||
publish(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function delayedhideToast() {
|
||||
if (options.timeOut > 0 || options.extendedTimeOut > 0) {
|
||||
intervalId = setTimeout(hideToast, options.extendedTimeOut);
|
||||
}
|
||||
}
|
||||
|
||||
function stickAround() {
|
||||
clearTimeout(intervalId);
|
||||
$toastElement.stop(true, true)[options.showMethod](
|
||||
{ duration: options.showDuration, easing: options.showEasing }
|
||||
);
|
||||
}
|
||||
}
|
||||
function getContainer(options) {
|
||||
if (!options) { options = getOptions(); }
|
||||
$container = $('#' + options.containerId);
|
||||
if ($container.length) {
|
||||
return $container;
|
||||
}
|
||||
$container = $('<div/>')
|
||||
.attr('id', options.containerId)
|
||||
.addClass(options.positionClass);
|
||||
$container.appendTo($(options.target));
|
||||
return $container;
|
||||
}
|
||||
|
||||
function getOptions() {
|
||||
return $.extend({}, getDefaults(), toastr.options);
|
||||
}
|
||||
|
||||
function removeToast($toastElement) {
|
||||
if (!$container) { $container = getContainer(); }
|
||||
if ($toastElement.is(':visible')) {
|
||||
return;
|
||||
}
|
||||
$toastElement.remove();
|
||||
$toastElement = null;
|
||||
if ($container.children().length === 0) {
|
||||
$container.remove();
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
})();
|
||||
});
|
||||
}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
|
||||
if (typeof module !== 'undefined' && module.exports) { //Node
|
||||
module.exports = factory(require(deps[0]));
|
||||
} else {
|
||||
window['toastr'] = factory(window['jQuery']);
|
||||
}
|
||||
}));
|
||||
!function(a){a([],function(){var a=jQuery;return function(){function b(a,b,c){return j({type:r.error,iconClass:l().iconClasses.error,message:a,optionsOverride:c,title:b})}function c(a,b,c){return j({type:r.info,iconClass:l().iconClasses.info,message:a,optionsOverride:c,title:b})}function d(a){o=a}function e(a,b,c){return j({type:r.success,iconClass:l().iconClasses.success,message:a,optionsOverride:c,title:b})}function f(a,b,c){return j({type:r.warning,iconClass:l().iconClasses.warning,message:a,optionsOverride:c,title:b})}function g(b){var c=l();return n||k(c),b&&0===a(":focus",b).length?void b[c.hideMethod]({duration:c.hideDuration,easing:c.hideEasing,complete:function(){m(b)}}):void(n.children().length&&n[c.hideMethod]({duration:c.hideDuration,easing:c.hideEasing,complete:function(){n.remove()}}))}function h(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body",closeHtml:"<button>×</button>",newestOnTop:!0}}function i(a){o&&o(a)}function j(b){function c(b){return!a(":focus",j).length||b?j[f.hideMethod]({duration:f.hideDuration,easing:f.hideEasing,complete:function(){m(j),f.onHidden&&f.onHidden(),s.state="hidden",s.endTime=new Date,i(s)}}):void 0}function d(){(f.timeOut>0||f.extendedTimeOut>0)&&(h=setTimeout(c,f.extendedTimeOut))}function e(){clearTimeout(h),j.stop(!0,!0)[f.showMethod]({duration:f.showDuration,easing:f.showEasing})}var f=l(),g=b.iconClass||f.iconClass;"undefined"!=typeof b.optionsOverride&&(f=a.extend(f,b.optionsOverride),g=b.optionsOverride.iconClass||g),q++,n=k(f);var h=null,j=a("<div/>"),o=a("<div/>"),p=a("<div/>"),r=a(f.closeHtml),s={toastId:q,state:"visible",startTime:new Date,options:f,map:b};return b.iconClass&&j.addClass(f.toastClass).addClass(g),b.title&&(o.append(b.title).addClass(f.titleClass),j.append(o)),b.message&&(p.append(b.message).addClass(f.messageClass),j.append(p)),f.closeButton&&(r.addClass("toast-close-button"),j.prepend(r)),j.hide(),f.newestOnTop?n.prepend(j):n.append(j),j[f.showMethod]({duration:f.showDuration,easing:f.showEasing,complete:f.onShown}),f.timeOut>0&&(h=setTimeout(c,f.timeOut)),j.hover(e,d),!f.onclick&&f.tapToDismiss&&j.click(c),f.closeButton&&r&&r.click(function(a){a.stopPropagation(),c(!0)}),f.onclick&&j.click(function(){f.onclick(),c()}),i(s),f.debug&&console,j}function k(b){return b||(b=l()),n=a("#"+b.containerId),n.length?n:(n=a("<div/>").attr("id",b.containerId).addClass(b.positionClass),n.appendTo(a(b.target)),n)}function l(){return a.extend({},h(),s.options)}function m(a){n||(n=k()),a.is(":visible")||(a.remove(),a=null,0===n.children().length&&n.remove())}var n,o,p="2.0.1",q=0,r={error:"error",info:"info",success:"success",warning:"warning"},s={clear:g,error:b,getContainer:k,info:c,options:{},subscribe:d,success:e,version:p,warning:f};return s}()})}("function"==typeof define&&define.amd?define:function(a,b){"undefined"!=typeof module&&module.exports?module.exports=b(require(a[0])):window.toastr=b(window.jQuery)});
|
||||
//# sourceMappingURL=../../maps/libs/toastr.js.map
|
||||
+2
-1112
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,83 +1,2 @@
|
||||
define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( baseMVC, _l ){
|
||||
// =============================================================================
|
||||
/** A view on any model that has a 'annotation' attribute
|
||||
*/
|
||||
var AnnotationEditor = Backbone.View
|
||||
.extend( baseMVC.LoggableMixin )
|
||||
.extend( baseMVC.HiddenUntilActivatedViewMixin ).extend({
|
||||
|
||||
tagName : 'div',
|
||||
className : 'annotation-display',
|
||||
|
||||
/** Set up listeners, parse options */
|
||||
initialize : function( options ){
|
||||
options = options || {};
|
||||
this.tooltipConfig = options.tooltipConfig || { placement: 'bottom' };
|
||||
//console.debug( this, options );
|
||||
// only listen to the model only for changes to annotations
|
||||
this.listenTo( this.model, 'change:annotation', function(){
|
||||
this.render();
|
||||
});
|
||||
this.hiddenUntilActivated( options.$activator, options );
|
||||
},
|
||||
|
||||
/** Build the DOM elements, call select to on the created input, and set up behaviors */
|
||||
render : function(){
|
||||
var view = this;
|
||||
this.$el.html( this._template() );
|
||||
this.$el.find( "[title]" ).tooltip( this.tooltipConfig );
|
||||
|
||||
//TODO: handle empties better
|
||||
this.$annotation().make_text_editable({
|
||||
use_textarea: true,
|
||||
on_finish: function( newAnnotation ){
|
||||
view.$annotation().text( newAnnotation );
|
||||
view.model.save({ annotation: newAnnotation }, { silent: true })
|
||||
.fail( function(){
|
||||
view.$annotation().text( view.model.previous( 'annotation' ) );
|
||||
});
|
||||
}
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
/** @returns {String} the html text used to build the view's DOM */
|
||||
_template : function(){
|
||||
var annotation = this.model.get( 'annotation' );
|
||||
//if( !annotation ){
|
||||
// //annotation = [ '<em class="annotation-empty">', _l( 'Click to add an annotation' ), '</em>' ].join( '' );
|
||||
// annotation = [ '<em class="annotation-empty"></em>' ].join( '' );
|
||||
//}
|
||||
return [
|
||||
//TODO: make prompt optional
|
||||
'<label class="prompt">', _l( 'Annotation' ), '</label>',
|
||||
// set up initial tags by adding as CSV to input vals (necc. to init select2)
|
||||
'<div class="annotation" title="', _l( 'Edit annotation' ), '">',
|
||||
_.escape( annotation ),
|
||||
'</div>'
|
||||
].join( '' );
|
||||
},
|
||||
|
||||
/** @returns {jQuery} the main element for this view */
|
||||
$annotation : function(){
|
||||
return this.$el.find( '.annotation' );
|
||||
},
|
||||
|
||||
/** shut down event listeners and remove this view's DOM */
|
||||
remove : function(){
|
||||
this.$annotation.off();
|
||||
this.stopListening( this.model );
|
||||
Backbone.View.prototype.remove.call( this );
|
||||
},
|
||||
|
||||
/** string rep */
|
||||
toString : function(){ return [ 'AnnotationEditor(', this.model + '', ')' ].join(''); }
|
||||
});
|
||||
// =============================================================================
|
||||
return {
|
||||
AnnotationEditor : AnnotationEditor
|
||||
};
|
||||
});
|
||||
define(["mvc/base-mvc","utils/localization"],function(a,b){var c=Backbone.View.extend(a.LoggableMixin).extend(a.HiddenUntilActivatedViewMixin).extend({tagName:"div",className:"annotation-display",initialize:function(a){a=a||{},this.tooltipConfig=a.tooltipConfig||{placement:"bottom"},this.listenTo(this.model,"change:annotation",function(){this.render()}),this.hiddenUntilActivated(a.$activator,a)},render:function(){var a=this;return this.$el.html(this._template()),this.$el.find("[title]").tooltip(this.tooltipConfig),this.$annotation().make_text_editable({use_textarea:!0,on_finish:function(b){a.$annotation().text(b),a.model.save({annotation:b},{silent:!0}).fail(function(){a.$annotation().text(a.model.previous("annotation"))})}}),this},_template:function(){var a=this.model.get("annotation");return['<label class="prompt">',b("Annotation"),"</label>",'<div class="annotation" title="',b("Edit annotation"),'">',_.escape(a),"</div>"].join("")},$annotation:function(){return this.$el.find(".annotation")},remove:function(){this.$annotation.off(),this.stopListening(this.model),Backbone.View.prototype.remove.call(this)},toString:function(){return["AnnotationEditor(",this.model+"",")"].join("")}});return{AnnotationEditor:c}});
|
||||
//# sourceMappingURL=../../maps/mvc/annotations.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -1,73 +1,2 @@
|
||||
define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( baseMVC, _l ){
|
||||
/* global Backbone */
|
||||
|
||||
//==============================================================================
|
||||
/** @class model for tool citations.
|
||||
* @name Citation
|
||||
*
|
||||
* @augments Backbone.Model
|
||||
* @borrows LoggableMixin#logger as #logger
|
||||
* @borrows LoggableMixin#log as #log
|
||||
* @constructs
|
||||
*/
|
||||
var Citation = Backbone.Model.extend( baseMVC.LoggableMixin ).extend( {
|
||||
initialize: function( ) {
|
||||
var bibtex = this.attributes.content;
|
||||
var entry = new BibtexParser(bibtex).entries[0];
|
||||
this.entry = entry;
|
||||
this._fields = {};
|
||||
var rawFields = entry.Fields;
|
||||
for(key in rawFields) {
|
||||
var value = rawFields[ key ];
|
||||
var lowerKey = key.toLowerCase();
|
||||
this._fields[ lowerKey ] = value;
|
||||
}
|
||||
},
|
||||
entryType: function() {
|
||||
return this.entry.EntryType;
|
||||
},
|
||||
fields: function() {
|
||||
return this._fields;
|
||||
}
|
||||
} );
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone collection of citations.
|
||||
*
|
||||
* @borrows LoggableMixin#logger as #logger
|
||||
* @borrows LoggableMixin#log as #log
|
||||
* @constructs
|
||||
*/
|
||||
var BaseCitationCollection = Backbone.Collection.extend( baseMVC.LoggableMixin ).extend( {
|
||||
/** root api url */
|
||||
urlRoot : galaxy_config.root + 'api',
|
||||
partial : true, // Assume some tools in history/workflow may not be properly annotated yet.
|
||||
model : Citation,
|
||||
} );
|
||||
|
||||
var HistoryCitationCollection = BaseCitationCollection.extend( {
|
||||
/** complete api url */
|
||||
url : function() {
|
||||
return this.urlRoot + '/histories/' + this.history_id + '/citations';
|
||||
}
|
||||
} );
|
||||
|
||||
var ToolCitationCollection = BaseCitationCollection.extend( {
|
||||
/** complete api url */
|
||||
url : function() {
|
||||
return this.urlRoot + '/tools/' + this.tool_id + '/citations';
|
||||
},
|
||||
partial : false, // If a tool has citations, assume they are complete.
|
||||
} );
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
Citation : Citation,
|
||||
HistoryCitationCollection : HistoryCitationCollection,
|
||||
ToolCitationCollection: ToolCitationCollection
|
||||
};
|
||||
|
||||
});
|
||||
define(["mvc/base-mvc","utils/localization"],function(a){var b=Backbone.Model.extend(a.LoggableMixin).extend({initialize:function(){var a=this.attributes.content,b=new BibtexParser(a).entries[0];this.entry=b,this._fields={};var c=b.Fields;for(key in c){var d=c[key],e=key.toLowerCase();this._fields[e]=d}},entryType:function(){return this.entry.EntryType},fields:function(){return this._fields}}),c=Backbone.Collection.extend(a.LoggableMixin).extend({urlRoot:galaxy_config.root+"api",partial:!0,model:b}),d=c.extend({url:function(){return this.urlRoot+"/histories/"+this.history_id+"/citations"}}),e=c.extend({url:function(){return this.urlRoot+"/tools/"+this.tool_id+"/citations"},partial:!1});return{Citation:b,HistoryCitationCollection:d,ToolCitationCollection:e}});
|
||||
//# sourceMappingURL=../../../maps/mvc/citation/citation-model.js.map
|
||||
@@ -1,188 +1,2 @@
|
||||
define([
|
||||
"mvc/base-mvc",
|
||||
"mvc/citation/citation-model",
|
||||
"utils/localization"
|
||||
], function( baseMVC, citationModel, _l ){
|
||||
|
||||
var CitationView = Backbone.View.extend({
|
||||
tagName: 'div',
|
||||
className: 'citations',
|
||||
render: function() {
|
||||
this.$el.append( "<p>" + this.formattedReference() + "</p>" );
|
||||
return this;
|
||||
},
|
||||
formattedReference: function() {
|
||||
var model = this.model;
|
||||
var entryType = model.entryType();
|
||||
var fields = model.fields();
|
||||
|
||||
var ref = "";
|
||||
// Code inspired by...
|
||||
// https://github.com/vkaravir/bib-publication-list/blob/master/src/bib-publication-list.js
|
||||
var authorsAndYear = this._asSentence( (fields.author ? fields.author : "") + (fields.year ? (" (" + fields.year + ")") : "") ) + " ";
|
||||
var title = fields.title || "";
|
||||
var pages = fields.pages ? ("pp. " + fields.pages) : "";
|
||||
var address = fields.address;
|
||||
if( entryType == "article" ) {
|
||||
var volume = (fields.volume ? fields.volume : "") +
|
||||
(fields.number ? ( " (" + fields.number + ")" ) : "") +
|
||||
(pages ? ", " + pages : "");
|
||||
ref = authorsAndYear + this._asSentence(title) +
|
||||
(fields.journal ? ("In <em>" + fields.journal + ", ") : "") +
|
||||
this._asSentence(volume) +
|
||||
this._asSentence(fields.address) +
|
||||
"<\/em>";
|
||||
} else if( entryType == "inproceedings" || entryType == "proceedings" ) {
|
||||
ref = authorsAndYear +
|
||||
this._asSentence(title) +
|
||||
(fields.booktitle ? ("In <em>" + fields.booktitle + ", ") : "") +
|
||||
(pages ? pages : "") +
|
||||
(address ? ", " + address : "") +
|
||||
".<\/em>";
|
||||
} else if( entryType == "mastersthesis" || entryType == "phdthesis" ) {
|
||||
ref = authorsAndYear + this._asSentence(title) +
|
||||
(fields.howpublished ? fields.howpublished + ". " : "") +
|
||||
(fields.note ? fields.note + "." : "");
|
||||
} else if( entryType == "techreport" ) {
|
||||
ref = authorsAndYear + this._asSentence(title) +
|
||||
this._asSentence(fields.institution) +
|
||||
this._asSentence(fields.number) +
|
||||
this._asSentence(fields.type);
|
||||
} else if( entryType == "book" || entryType == "inbook" || entryType == "incollection" ) {
|
||||
ref = authorsAndYear + " " + this._formatBookInfo(fields);
|
||||
} else {
|
||||
ref = authorsAndYear + " " + this._asSentence(title) +
|
||||
this._asSentence(fields.howpublished) +
|
||||
this._asSentence(fields.note);
|
||||
}
|
||||
var doiUrl = "";
|
||||
if( fields.doi ) {
|
||||
doiUrl = 'http://dx.doi.org/' + fields.doi;
|
||||
ref += '[<a href="' + doiUrl + '" target="_blank">doi:' + fields.doi + "</a>]";
|
||||
}
|
||||
var url = fields.url || doiUrl;
|
||||
if( url ) {
|
||||
ref += '[<a href="' + url + '" target="_blank">Link</a>]';
|
||||
}
|
||||
return ref;
|
||||
},
|
||||
_formatBookInfo: function(fields) {
|
||||
var info = "";
|
||||
if( fields.chapter ) {
|
||||
info += fields.chapter + " in ";
|
||||
}
|
||||
if( fields.title ) {
|
||||
info += "<em>" + fields.title + "<\/em>";
|
||||
}
|
||||
if( fields.editor ) {
|
||||
info += ", Edited by " + fields.editor + ", ";
|
||||
}
|
||||
if( fields.publisher) {
|
||||
info += ", " + fields.publisher;
|
||||
}
|
||||
if( fields.pages ) {
|
||||
info += ", pp. " + fields.pages + "";
|
||||
}
|
||||
if( fields.series ) {
|
||||
info += ", <em>" + fields.series + "<\/em>";
|
||||
}
|
||||
if( fields.volume ) {
|
||||
info += ", Vol." + fields.volume;
|
||||
}
|
||||
if( fields.issn ) {
|
||||
info += ", ISBN: " + fields.issn;
|
||||
}
|
||||
return info + ".";
|
||||
},
|
||||
_asSentence: function(str) {
|
||||
return (str && str.trim()) ? str + ". " : "";
|
||||
}
|
||||
});
|
||||
|
||||
var CitationListView = Backbone.View.extend({
|
||||
el: '#citations',
|
||||
/**
|
||||
* Set up view.
|
||||
*/
|
||||
initialize: function() {
|
||||
this.listenTo( this.collection, 'add', this.renderCitation );
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .citations-to-bibtex': 'showBibtex',
|
||||
'click .citations-to-formatted': 'showFormatted'
|
||||
},
|
||||
|
||||
renderCitation: function( citation ) {
|
||||
var citationView = new CitationView( { model: citation } );
|
||||
this.$(".citations-formatted").append( citationView.render().el );
|
||||
var rawTextarea = this.$(".citations-bibtex-text");
|
||||
rawTextarea.val( rawTextarea.val() + "\n\r" + citation.attributes.content );
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.citationsElement());
|
||||
this.collection.each(function( item ){
|
||||
this.renderCitation( item );
|
||||
}, this);
|
||||
this.showFormatted();
|
||||
},
|
||||
|
||||
showBibtex: function() {
|
||||
this.$(".citations-to-formatted").show();
|
||||
this.$(".citations-to-bibtex").hide();
|
||||
this.$(".citations-bibtex").show();
|
||||
this.$(".citations-formatted").hide();
|
||||
this.$(".citations-bibtex-text").select();
|
||||
},
|
||||
|
||||
showFormatted: function() {
|
||||
this.$(".citations-to-formatted").hide();
|
||||
this.$(".citations-to-bibtex").show();
|
||||
this.$(".citations-bibtex").hide();
|
||||
this.$(".citations-formatted").show();
|
||||
},
|
||||
|
||||
partialWarningElement: function() {
|
||||
if( this.collection.partial ) {
|
||||
return [
|
||||
'<div style="padding:5px 10px">',
|
||||
'<b>Warning: This is a experimental feature.</b> Most Galaxy tools will not annotate',
|
||||
' citations explicitly at this time. When writing up your analysis, please manually',
|
||||
' review your histories and find all references',
|
||||
' that should be cited in order to completely describe your work. Also, please remember to',
|
||||
' <a href="https://wiki.galaxyproject.org/CitingGalaxy">cite Galaxy</a>.',
|
||||
'</div>',
|
||||
].join('');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
||||
citationsElement: function() {
|
||||
return [
|
||||
'<div class="toolForm">',
|
||||
'<div class="toolFormTitle">',
|
||||
_l("Citations"),
|
||||
' <button type="button" class="btn btn-xs citations-to-bibtex" title="Show all in BibTeX format."><i class="fa fa-pencil-square-o"></i> Show BibTeX</button>',
|
||||
' <button type="button" class="btn btn-xs citations-to-formatted" title="Return to formatted citation list."><i class="fa fa-times"></i> Hide BibTeX</button>',
|
||||
'</div>',
|
||||
'<div class="toolFormBody" style="padding:5px 10px">',
|
||||
this.partialWarningElement(),
|
||||
'<span class="citations-formatted" style="word-wrap: break-word;"></span>',
|
||||
'</div>',
|
||||
'<div class="citations-bibtex toolFormBody" style="padding:5px 10px">',
|
||||
'<textarea style="width: 100%; height: 500px;" class="citations-bibtex-text"></textarea>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join( '' );
|
||||
}
|
||||
});
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
CitationView : CitationView,
|
||||
CitationListView : CitationListView
|
||||
};
|
||||
|
||||
});
|
||||
define(["mvc/base-mvc","mvc/citation/citation-model","utils/localization"],function(a,b,c){var d=Backbone.View.extend({tagName:"div",className:"citations",render:function(){return this.$el.append("<p>"+this.formattedReference()+"</p>"),this},formattedReference:function(){var a=this.model,b=a.entryType(),c=a.fields(),d="",e=this._asSentence((c.author?c.author:"")+(c.year?" ("+c.year+")":""))+" ",f=c.title||"",g=c.pages?"pp. "+c.pages:"",h=c.address;if("article"==b){var i=(c.volume?c.volume:"")+(c.number?" ("+c.number+")":"")+(g?", "+g:"");d=e+this._asSentence(f)+(c.journal?"In <em>"+c.journal+", ":"")+this._asSentence(i)+this._asSentence(c.address)+"</em>"}else d="inproceedings"==b||"proceedings"==b?e+this._asSentence(f)+(c.booktitle?"In <em>"+c.booktitle+", ":"")+(g?g:"")+(h?", "+h:"")+".</em>":"mastersthesis"==b||"phdthesis"==b?e+this._asSentence(f)+(c.howpublished?c.howpublished+". ":"")+(c.note?c.note+".":""):"techreport"==b?e+this._asSentence(f)+this._asSentence(c.institution)+this._asSentence(c.number)+this._asSentence(c.type):"book"==b||"inbook"==b||"incollection"==b?e+" "+this._formatBookInfo(c):e+" "+this._asSentence(f)+this._asSentence(c.howpublished)+this._asSentence(c.note);var j="";c.doi&&(j="http://dx.doi.org/"+c.doi,d+='[<a href="'+j+'" target="_blank">doi:'+c.doi+"</a>]");var k=c.url||j;return k&&(d+='[<a href="'+k+'" target="_blank">Link</a>]'),d},_formatBookInfo:function(a){var b="";return a.chapter&&(b+=a.chapter+" in "),a.title&&(b+="<em>"+a.title+"</em>"),a.editor&&(b+=", Edited by "+a.editor+", "),a.publisher&&(b+=", "+a.publisher),a.pages&&(b+=", pp. "+a.pages),a.series&&(b+=", <em>"+a.series+"</em>"),a.volume&&(b+=", Vol."+a.volume),a.issn&&(b+=", ISBN: "+a.issn),b+"."},_asSentence:function(a){return a&&a.trim()?a+". ":""}}),e=Backbone.View.extend({el:"#citations",initialize:function(){this.listenTo(this.collection,"add",this.renderCitation)},events:{"click .citations-to-bibtex":"showBibtex","click .citations-to-formatted":"showFormatted"},renderCitation:function(a){var b=new d({model:a});this.$(".citations-formatted").append(b.render().el);var c=this.$(".citations-bibtex-text");c.val(c.val()+"\n\r"+a.attributes.content)},render:function(){this.$el.html(this.citationsElement()),this.collection.each(function(a){this.renderCitation(a)},this),this.showFormatted()},showBibtex:function(){this.$(".citations-to-formatted").show(),this.$(".citations-to-bibtex").hide(),this.$(".citations-bibtex").show(),this.$(".citations-formatted").hide(),this.$(".citations-bibtex-text").select()},showFormatted:function(){this.$(".citations-to-formatted").hide(),this.$(".citations-to-bibtex").show(),this.$(".citations-bibtex").hide(),this.$(".citations-formatted").show()},partialWarningElement:function(){return this.collection.partial?['<div style="padding:5px 10px">',"<b>Warning: This is a experimental feature.</b> Most Galaxy tools will not annotate"," citations explicitly at this time. When writing up your analysis, please manually"," review your histories and find all references"," that should be cited in order to completely describe your work. Also, please remember to",' <a href="https://wiki.galaxyproject.org/CitingGalaxy">cite Galaxy</a>.',"</div>"].join(""):""},citationsElement:function(){return['<div class="toolForm">','<div class="toolFormTitle">',c("Citations"),' <button type="button" class="btn btn-xs citations-to-bibtex" title="Show all in BibTeX format."><i class="fa fa-pencil-square-o"></i> Show BibTeX</button>',' <button type="button" class="btn btn-xs citations-to-formatted" title="Return to formatted citation list."><i class="fa fa-times"></i> Hide BibTeX</button>',"</div>",'<div class="toolFormBody" style="padding:5px 10px">',this.partialWarningElement(),'<span class="citations-formatted" style="word-wrap: break-word;"></span>',"</div>",'<div class="citations-bibtex toolFormBody" style="padding:5px 10px">','<textarea style="width: 100%; height: 500px;" class="citations-bibtex-text"></textarea>',"</div>","</div>"].join("")}});return{CitationView:d,CitationListView:e}});
|
||||
//# sourceMappingURL=../../../maps/mvc/citation/citation-view.js.map
|
||||
@@ -1,34 +1,2 @@
|
||||
define([
|
||||
"mvc/collection/collection-li",
|
||||
"utils/localization"
|
||||
], function( DC_LI, _l ){
|
||||
//==============================================================================
|
||||
/*
|
||||
|
||||
NOTE: not much going on here. Until we find out what operations a user will need
|
||||
to perform on their own DC's, we'll leave this empty.
|
||||
|
||||
*/
|
||||
//==============================================================================
|
||||
var _super = DC_LI.DCListItemView;
|
||||
/** @class Editing view for DatasetCollectionElement.
|
||||
*/
|
||||
var DCEListItemEdit = _super.extend(
|
||||
/** @lends DCEListItemEdit.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
// ......................................................................... misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'DCEListItemEdit(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
DCEListItemEdit : DCEListItemEdit
|
||||
};
|
||||
});
|
||||
define(["mvc/collection/collection-li","utils/localization"],function(a){var b=a.DCListItemView,c=b.extend({toString:function(){var a=this.model?this.model+"":"(no model)";return"DCEListItemEdit("+a+")"}});return{DCEListItemEdit:c}});
|
||||
//# sourceMappingURL=../../../maps/mvc/collection/collection-li-edit.js.map
|
||||
@@ -1,227 +1,2 @@
|
||||
define([
|
||||
"mvc/list/list-item",
|
||||
"mvc/dataset/dataset-li",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( LIST_ITEM, DATASET_LI, BASE_MVC, _l ){
|
||||
/* global Backbone, LoggableMixin */
|
||||
//==============================================================================
|
||||
var FoldoutListItemView = LIST_ITEM.FoldoutListItemView,
|
||||
ListItemView = LIST_ITEM.ListItemView;
|
||||
/** @class Read only view for DatasetCollection.
|
||||
*/
|
||||
var DCListItemView = FoldoutListItemView.extend(
|
||||
/** @lends DCListItemView.prototype */{
|
||||
//TODO: may not be needed
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
className : FoldoutListItemView.prototype.className + " dataset-collection",
|
||||
id : function(){
|
||||
return [ 'dataset_collection', this.model.get( 'id' ) ].join( '-' );
|
||||
},
|
||||
|
||||
/** override to add linkTarget */
|
||||
initialize : function( attributes ){
|
||||
FoldoutListItemView.prototype.initialize.call( this, attributes );
|
||||
this.linkTarget = attributes.linkTarget || '_blank';
|
||||
},
|
||||
|
||||
// ......................................................................... rendering
|
||||
//TODO:?? possibly move to listItem
|
||||
/** render a subtitle to show the user what sort of collection this is */
|
||||
_renderSubtitle : function(){
|
||||
var $subtitle = $( '<div class="subtitle"></div>' );
|
||||
//TODO: would be good to get this in the subtitle
|
||||
//var len = this.model.elements.length;
|
||||
switch( this.model.get( 'collection_type' ) ){
|
||||
case 'list':
|
||||
return $subtitle.text( _l( 'a list of datasets' ) );
|
||||
case 'paired':
|
||||
return $subtitle.text( _l( 'a pair of datasets' ) );
|
||||
case 'list:paired':
|
||||
return $subtitle.text( _l( 'a list of paired datasets' ) );
|
||||
}
|
||||
return $subtitle;
|
||||
},
|
||||
|
||||
// ......................................................................... foldout
|
||||
/** override to add linktarget to sub-panel */
|
||||
_getFoldoutPanelOptions : function(){
|
||||
var options = FoldoutListItemView.prototype._getFoldoutPanelOptions.call( this );
|
||||
return _.extend( options, {
|
||||
linkTarget : this.linkTarget
|
||||
});
|
||||
},
|
||||
|
||||
/** override to not catch sub-panel selectors */
|
||||
$selector : function(){
|
||||
return this.$( '> .selector' );
|
||||
},
|
||||
|
||||
// ......................................................................... misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'DCListItemView(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
// ............................................................................ TEMPLATES
|
||||
/** underscore templates */
|
||||
DCListItemView.prototype.templates = (function(){
|
||||
|
||||
// use element identifier
|
||||
var titleBarTemplate = BASE_MVC.wrapTemplate([
|
||||
'<div class="title-bar clear" tabindex="0">',
|
||||
'<div class="title">',
|
||||
'<span class="name"><%- collection.element_identifier || collection.name %></span>',
|
||||
'</div>',
|
||||
'<div class="subtitle"></div>',
|
||||
'</div>'
|
||||
], 'collection' );
|
||||
|
||||
return _.extend( {}, FoldoutListItemView.prototype.templates, {
|
||||
titleBar : titleBarTemplate
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Read only view for DatasetCollectionElement.
|
||||
*/
|
||||
var DCEListItemView = ListItemView.extend(
|
||||
/** @lends DCEListItemView.prototype */{
|
||||
//TODO: this might be expendable - compacted with HDAListItemView
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** add the DCE class to the list item */
|
||||
className : ListItemView.prototype.className + " dataset-collection-element",
|
||||
|
||||
/** set up */
|
||||
initialize : function( attributes ){
|
||||
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
|
||||
this.log( 'DCEListItemView.initialize:', attributes );
|
||||
ListItemView.prototype.initialize.call( this, attributes );
|
||||
},
|
||||
|
||||
// ......................................................................... misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'DCEListItemView(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
// ............................................................................ TEMPLATES
|
||||
/** underscore templates */
|
||||
DCEListItemView.prototype.templates = (function(){
|
||||
|
||||
// use the element identifier here - since that will persist and the user will need it
|
||||
var titleBarTemplate = BASE_MVC.wrapTemplate([
|
||||
'<div class="title-bar clear" tabindex="0">',
|
||||
'<div class="title">',
|
||||
'<span class="name"><%- element.element_identifier %></span>',
|
||||
'</div>',
|
||||
'<div class="subtitle"></div>',
|
||||
'</div>'
|
||||
], 'element' );
|
||||
|
||||
return _.extend( {}, ListItemView.prototype.templates, {
|
||||
titleBar : titleBarTemplate
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Read only view for a DatasetCollectionElement that is also an DatasetAssociation
|
||||
* (a dataset contained in a dataset collection).
|
||||
*/
|
||||
var DatasetDCEListItemView = DATASET_LI.DatasetListItemView.extend(
|
||||
/** @lends DatasetDCEListItemView.prototype */{
|
||||
|
||||
className : DATASET_LI.DatasetListItemView.prototype.className + " dataset-collection-element",
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** set up */
|
||||
initialize : function( attributes ){
|
||||
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
|
||||
this.log( 'DatasetDCEListItemView.initialize:', attributes );
|
||||
DATASET_LI.DatasetListItemView.prototype.initialize.call( this, attributes );
|
||||
},
|
||||
|
||||
// ......................................................................... misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'DatasetDCEListItemView(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
// ............................................................................ TEMPLATES
|
||||
/** underscore templates */
|
||||
DatasetDCEListItemView.prototype.templates = (function(){
|
||||
|
||||
// use the element identifier here and not the dataset name
|
||||
//TODO:?? can we steal the DCE titlebar?
|
||||
var titleBarTemplate = BASE_MVC.wrapTemplate([
|
||||
'<div class="title-bar clear" tabindex="0">',
|
||||
'<span class="state-icon"></span>',
|
||||
'<div class="title">',
|
||||
'<span class="name"><%- element.element_identifier %></span>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
], 'element' );
|
||||
|
||||
return _.extend( {}, DATASET_LI.DatasetListItemView.prototype.templates, {
|
||||
titleBar : titleBarTemplate
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Read only view for a DatasetCollectionElement that is also a DatasetCollection
|
||||
* (a nested DC).
|
||||
*/
|
||||
var NestedDCDCEListItemView = DCListItemView.extend(
|
||||
/** @lends NestedDCDCEListItemView.prototype */{
|
||||
|
||||
className : DCListItemView.prototype.className + " dataset-collection-element",
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
// comment this out to suppress log output
|
||||
//logger : console,
|
||||
|
||||
/** In this override, add the state as a class for use with state-based CSS */
|
||||
_swapNewRender : function( $newRender ){
|
||||
DCListItemView.prototype._swapNewRender.call( this, $newRender );
|
||||
//TODO: model currently has no state
|
||||
var state = this.model.get( 'state' ) || 'ok';
|
||||
//if( this.model.has( 'state' ) ){
|
||||
this.$el.addClass( 'state-' + state );
|
||||
//}
|
||||
return this.$el;
|
||||
},
|
||||
|
||||
// ......................................................................... misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'NestedDCDCEListItemView(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
DCListItemView : DCListItemView,
|
||||
DCEListItemView : DCEListItemView,
|
||||
DatasetDCEListItemView : DatasetDCEListItemView,
|
||||
NestedDCDCEListItemView : NestedDCDCEListItemView
|
||||
};
|
||||
});
|
||||
define(["mvc/list/list-item","mvc/dataset/dataset-li","mvc/base-mvc","utils/localization"],function(a,b,c,d){var e=a.FoldoutListItemView,f=a.ListItemView,g=e.extend({className:e.prototype.className+" dataset-collection",id:function(){return["dataset_collection",this.model.get("id")].join("-")},initialize:function(a){e.prototype.initialize.call(this,a),this.linkTarget=a.linkTarget||"_blank"},_renderSubtitle:function(){var a=$('<div class="subtitle"></div>');switch(this.model.get("collection_type")){case"list":return a.text(d("a list of datasets"));case"paired":return a.text(d("a pair of datasets"));case"list:paired":return a.text(d("a list of paired datasets"))}return a},_getFoldoutPanelOptions:function(){var a=e.prototype._getFoldoutPanelOptions.call(this);return _.extend(a,{linkTarget:this.linkTarget})},$selector:function(){return this.$("> .selector")},toString:function(){var a=this.model?this.model+"":"(no model)";return"DCListItemView("+a+")"}});g.prototype.templates=function(){var a=c.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- collection.element_identifier || collection.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"collection");return _.extend({},e.prototype.templates,{titleBar:a})}();var h=f.extend({className:f.prototype.className+" dataset-collection-element",initialize:function(a){a.logger&&(this.logger=this.model.logger=a.logger),this.log("DCEListItemView.initialize:",a),f.prototype.initialize.call(this,a)},toString:function(){var a=this.model?this.model+"":"(no model)";return"DCEListItemView("+a+")"}});h.prototype.templates=function(){var a=c.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");return _.extend({},f.prototype.templates,{titleBar:a})}();var i=b.DatasetListItemView.extend({className:b.DatasetListItemView.prototype.className+" dataset-collection-element",initialize:function(a){a.logger&&(this.logger=this.model.logger=a.logger),this.log("DatasetDCEListItemView.initialize:",a),b.DatasetListItemView.prototype.initialize.call(this,a)},toString:function(){var a=this.model?this.model+"":"(no model)";return"DatasetDCEListItemView("+a+")"}});i.prototype.templates=function(){var a=c.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>","</div>"],"element");return _.extend({},b.DatasetListItemView.prototype.templates,{titleBar:a})}();var j=g.extend({className:g.prototype.className+" dataset-collection-element",_swapNewRender:function(a){g.prototype._swapNewRender.call(this,a);var b=this.model.get("state")||"ok";return this.$el.addClass("state-"+b),this.$el},toString:function(){var a=this.model?this.model+"":"(no model)";return"NestedDCDCEListItemView("+a+")"}});return{DCListItemView:g,DCEListItemView:h,DatasetDCEListItemView:i,NestedDCDCEListItemView:j}});
|
||||
//# sourceMappingURL=../../../maps/mvc/collection/collection-li.js.map
|
||||
@@ -1,483 +1,2 @@
|
||||
define([
|
||||
"mvc/dataset/dataset-model",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( DATASET_MODEL, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
/*
|
||||
Notes:
|
||||
|
||||
Terminology:
|
||||
DatasetCollection/DC : a container of datasets or nested DatasetCollections
|
||||
Element/DatasetCollectionElement/DCE : an item contained in a DatasetCollection
|
||||
HistoryDatasetCollectionAssociation/HDCA: a DatasetCollection contained in a history
|
||||
|
||||
|
||||
This all seems too complex unfortunately:
|
||||
|
||||
- Terminology collision between DatasetCollections (DCs) and Backbone Collections.
|
||||
- In the DatasetCollections API JSON, DC Elements use a 'Has A' stucture to *contain*
|
||||
either a dataset or a nested DC. This would make the hierarchy much taller. I've
|
||||
decided to merge the contained JSON with the DC element json - making the 'has a'
|
||||
relation into an 'is a' relation. This seems simpler to me and allowed a lot of
|
||||
DRY in both models and views, but may make tracking or tracing within these models
|
||||
more difficult (since DatasetCollectionElements are now *also* DatasetAssociations
|
||||
or DatasetCollections (nested)). This also violates the rule of thumb about
|
||||
favoring aggregation over inheritance.
|
||||
- Currently, there are three DatasetCollection subclasses: List, Pair, and ListPaired.
|
||||
These each should a) be usable on their own, b) be usable in the context of
|
||||
nesting within a collection model (at least in the case of ListPaired), and
|
||||
c) be usable within the context of other container models (like History or
|
||||
LibraryFolder, etc.). I've tried to separate/extract classes in order to
|
||||
handle those three situations, but it's proven difficult to do in a simple,
|
||||
readable manner.
|
||||
- Ideally, histories and libraries would inherit from the same server models as
|
||||
dataset collections do since they are (in essence) dataset collections themselves -
|
||||
making the whole nested structure simpler. This would be a large, error-prone
|
||||
refactoring and migration.
|
||||
|
||||
Many of the classes and heirarchy are meant as extension points so, while the
|
||||
relations and flow may be difficult to understand initially, they'll allow us to
|
||||
handle the growth or flux dataset collection in the future (w/o actually implementing
|
||||
any YAGNI).
|
||||
|
||||
*/
|
||||
//_________________________________________________________________________________________________ ELEMENTS
|
||||
/** @class mixin for Dataset collection elements.
|
||||
* When collection elements are passed from the API, the underlying element is
|
||||
* in a sub-object 'object' (IOW, a DCE representing an HDA will have HDA json in element.object).
|
||||
* This mixin uses the constructor and parse methods to merge that JSON with the DCE attribtues
|
||||
* effectively changing a DCE from a container to a subclass (has a --> is a).
|
||||
*/
|
||||
var DatasetCollectionElementMixin = {
|
||||
|
||||
/** default attributes used by elements in a dataset collection */
|
||||
defaults : {
|
||||
model_class : 'DatasetCollectionElement',
|
||||
element_identifier : null,
|
||||
element_index : null,
|
||||
element_type : null
|
||||
},
|
||||
|
||||
/** merge the attributes of the sub-object 'object' into this model */
|
||||
_mergeObject : function( attributes ){
|
||||
_.extend( attributes, attributes.object );
|
||||
delete attributes.object;
|
||||
return attributes;
|
||||
},
|
||||
|
||||
/** override to merge this.object into this */
|
||||
constructor : function( attributes, options ){
|
||||
this.debug( '\t DatasetCollectionElement.constructor:', attributes, options );
|
||||
attributes = this._mergeObject( attributes );
|
||||
Backbone.Model.apply( this, arguments );
|
||||
},
|
||||
|
||||
/** when the model is fetched, merge this.object into this */
|
||||
parse : function( response, options ){
|
||||
var attributes = response;
|
||||
attributes = this._mergeObject( attributes );
|
||||
return attributes;
|
||||
}
|
||||
};
|
||||
|
||||
//TODO: unused?
|
||||
/** @class Concrete class of Generic DatasetCollectionElement */
|
||||
var DatasetCollectionElement = Backbone.Model
|
||||
.extend( BASE_MVC.LoggableMixin )
|
||||
.extend( DatasetCollectionElementMixin );
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Base/Abstract Backbone collection for Generic DCEs. */
|
||||
var DCECollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
|
||||
/** @lends DCECollection.prototype */{
|
||||
model: DatasetCollectionElement,
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
//TODO: unused?
|
||||
/** Set up.
|
||||
* @see Backbone.Collection#initialize
|
||||
*/
|
||||
initialize : function( attributes, options ){
|
||||
this.debug( this + '(DCECollection).initialize:', attributes, options );
|
||||
options = options || {};
|
||||
//this._setUpListeners();
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'DatasetCollectionElementCollection(', this.length, ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone model for a dataset collection element that is a dataset (HDA).
|
||||
*/
|
||||
var DatasetDCE = DATASET_MODEL.DatasetAssociation.extend( BASE_MVC.mixin( DatasetCollectionElementMixin,
|
||||
/** @lends DatasetDCE.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
defaults : _.extend( {},
|
||||
DATASET_MODEL.DatasetAssociation.prototype.defaults,
|
||||
DatasetCollectionElementMixin.defaults
|
||||
),
|
||||
|
||||
// because all objects have constructors (as this hashmap would even if this next line wasn't present)
|
||||
// the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model
|
||||
// - re-apply manually it now
|
||||
/** call the mixin constructor */
|
||||
constructor : function( attributes, options ){
|
||||
this.debug( '\t DatasetDCE.constructor:', attributes, options );
|
||||
//DATASET_MODEL.DatasetAssociation.prototype.constructor.call( this, attributes, options );
|
||||
DatasetCollectionElementMixin.constructor.call( this, attributes, options );
|
||||
},
|
||||
|
||||
//TODO: unused?
|
||||
/** set up */
|
||||
initialize : function( attributes, options ){
|
||||
this.debug( this + '(DatasetDCE).initialize:', attributes, options );
|
||||
DATASET_MODEL.DatasetAssociation.prototype.initialize.call( this, attributes, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
var objStr = this.get( 'element_identifier' );
|
||||
return ([ 'DatasetDCE(', objStr, ')' ].join( '' ));
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class DCECollection of DatasetDCE's (a list of datasets, a pair of datasets).
|
||||
*/
|
||||
var DatasetDCECollection = DCECollection.extend(
|
||||
/** @lends DatasetDCECollection.prototype */{
|
||||
model: DatasetDCE,
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
//TODO: unused?
|
||||
/** set up */
|
||||
initialize : function( attributes, options ){
|
||||
this.debug( this + '(DatasetDCECollection).initialize:', attributes, options );
|
||||
DCECollection.prototype.initialize.call( this, attributes, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'DatasetDCECollection(', this.length, ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//_________________________________________________________________________________________________ COLLECTIONS
|
||||
/** @class Backbone model for Dataset Collections.
|
||||
* The DC API returns an array of JSON objects under the attribute elements.
|
||||
* This model:
|
||||
* - removes that array/attribute ('elements') from the model,
|
||||
* - creates a bbone collection (of the class defined in the 'collectionClass' attribute),
|
||||
* - passes that json onto the bbone collection
|
||||
* - caches the bbone collection in this.elements
|
||||
*/
|
||||
var DatasetCollection = Backbone.Model
|
||||
.extend( BASE_MVC.LoggableMixin )
|
||||
.extend( BASE_MVC.SearchableModelMixin )
|
||||
.extend(/** @lends DatasetCollection.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** default attributes for a model */
|
||||
defaults : {
|
||||
/* 'list', 'paired', or 'list:paired' */
|
||||
collection_type : null,
|
||||
//??
|
||||
deleted : false
|
||||
},
|
||||
|
||||
/** Which class to use for elements */
|
||||
collectionClass : DCECollection,
|
||||
|
||||
/** set up: create elements instance var and (on changes to elements) update them */
|
||||
initialize : function( model, options ){
|
||||
this.debug( this + '(DatasetCollection).initialize:', model, options, this );
|
||||
//historyContent.HistoryContent.prototype.initialize.call( this, attrs, options );
|
||||
this.elements = this._createElementsModel();
|
||||
this.on( 'change:elements', function(){
|
||||
this.log( 'change:elements' );
|
||||
//TODO: prob. better to update the collection instead of re-creating it
|
||||
this.elements = this._createElementsModel();
|
||||
});
|
||||
},
|
||||
|
||||
/** move elements model attribute to full collection */
|
||||
_createElementsModel : function(){
|
||||
this.debug( this + '._createElementsModel', this.collectionClass, this.get( 'elements' ), this.elements );
|
||||
//TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?
|
||||
var elements = this.get( 'elements' ) || [];
|
||||
this.unset( 'elements', { silent: true });
|
||||
this.elements = new this.collectionClass( elements );
|
||||
//this.debug( 'collectionClass:', this.collectionClass + '', this.elements );
|
||||
return this.elements;
|
||||
},
|
||||
|
||||
// ........................................................................ common queries
|
||||
/** pass the elements back within the model json when this is serialized */
|
||||
toJSON : function(){
|
||||
var json = Backbone.Model.prototype.toJSON.call( this );
|
||||
if( this.elements ){
|
||||
json.elements = this.elements.toJSON();
|
||||
}
|
||||
return json;
|
||||
},
|
||||
|
||||
/** is the collection done with updates and ready to be used? (finished running, etc.) */
|
||||
inReadyState : function(){
|
||||
//TODO: state currenly unimplemented for collections
|
||||
return true;
|
||||
},
|
||||
|
||||
//TODO:?? the following are the same interface as DatasetAssociation - can we combine?
|
||||
/** Does the DC contain any elements yet? Is a fetch() required? */
|
||||
hasDetails : function(){
|
||||
//TODO: this is incorrect for (accidentally) empty collections
|
||||
this.debug( 'hasDetails:', this.elements.length );
|
||||
return this.elements.length !== 0;
|
||||
},
|
||||
|
||||
/** Given the filters, what models in this.elements would be returned? */
|
||||
getVisibleContents : function( filters ){
|
||||
// filters unused for now
|
||||
return this.elements;
|
||||
},
|
||||
|
||||
// ........................................................................ ajax
|
||||
/** save this dataset, _Mark_ing it as deleted (just a flag) */
|
||||
'delete' : function( options ){
|
||||
if( this.get( 'deleted' ) ){ return jQuery.when(); }
|
||||
return this.save( { deleted: true }, options );
|
||||
},
|
||||
/** save this dataset, _Mark_ing it as undeleted */
|
||||
undelete : function( options ){
|
||||
if( !this.get( 'deleted' ) || this.get( 'purged' ) ){ return jQuery.when(); }
|
||||
return this.save( { deleted: false }, options );
|
||||
},
|
||||
|
||||
/** Is this collection deleted or purged? */
|
||||
isDeletedOrPurged : function(){
|
||||
return ( this.get( 'deleted' ) || this.get( 'purged' ) );
|
||||
},
|
||||
|
||||
// ........................................................................ searchable
|
||||
/** searchable attributes for collections */
|
||||
searchAttributes : [
|
||||
'name'
|
||||
],
|
||||
|
||||
// ........................................................................ misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var idAndName = [ this.get( 'id' ), this.get( 'name' ) || this.get( 'element_identifier' ) ];
|
||||
return 'DatasetCollection(' + ( idAndName.join(',') ) + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Model for a DatasetCollection containing datasets (non-nested).
|
||||
*/
|
||||
var ListDatasetCollection = DatasetCollection.extend(
|
||||
/** @lends ListDatasetCollection.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** override since we know the collection will only contain datasets */
|
||||
collectionClass : DatasetDCECollection,
|
||||
|
||||
//TODO: unused?
|
||||
initialize : function( attrs, options ){
|
||||
this.debug( this + '(ListDatasetCollection).initialize:', attrs, options );
|
||||
DatasetCollection.prototype.initialize.call( this, attrs, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'ListDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Model for a DatasetCollection containing fwd/rev datasets (a list of 2).
|
||||
*/
|
||||
var PairDatasetCollection = ListDatasetCollection.extend(
|
||||
/** @lends PairDatasetCollection.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
//TODO: unused?
|
||||
/** */
|
||||
initialize : function( attrs, options ){
|
||||
this.debug( this + '(PairDatasetCollection).initialize:', attrs, options );
|
||||
ListDatasetCollection.prototype.initialize.call( this, attrs, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'PairDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//_________________________________________________________________________________________________ NESTED COLLECTIONS
|
||||
// this is where things get weird, man. Weird.
|
||||
//TODO: it might be possible to compact all the following...I think.
|
||||
//==============================================================================
|
||||
/** @class Backbone model for a Generic DatasetCollectionElement that is also a DatasetCollection
|
||||
* (a nested collection). Currently only list:paired.
|
||||
*/
|
||||
var NestedDCDCE = DatasetCollection.extend( BASE_MVC.mixin( DatasetCollectionElementMixin,
|
||||
/** @lends NestedDCDCE.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
// because all objects have constructors (as this hashmap would even if this next line wasn't present)
|
||||
// the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model
|
||||
// - re-apply manually it now
|
||||
/** call the mixin constructor */
|
||||
constructor : function( attributes, options ){
|
||||
this.debug( '\t NestedDCDCE.constructor:', attributes, options );
|
||||
DatasetCollectionElementMixin.constructor.call( this, attributes, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
var objStr = ( this.object )?( '' + this.object ):( this.get( 'element_identifier' ) );
|
||||
return ([ 'NestedDCDCE(', objStr, ')' ].join( '' ));
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone collection containing Generic NestedDCDCE's (nested dataset collections).
|
||||
*/
|
||||
var NestedDCDCECollection = DCECollection.extend(
|
||||
/** @lends NestedDCDCECollection.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** This is a collection of nested collections */
|
||||
model: NestedDCDCE,
|
||||
|
||||
//TODO: unused?
|
||||
/** set up */
|
||||
initialize : function( attrs, options ){
|
||||
this.debug( this + '(NestedDCDCECollection).initialize:', attrs, options );
|
||||
DCECollection.prototype.initialize.call( this, attrs, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'NestedDCDCECollection(', this.length, ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone model for a paired dataset collection within a list:paired dataset collection.
|
||||
*/
|
||||
var NestedPairDCDCE = PairDatasetCollection.extend( BASE_MVC.mixin( DatasetCollectionElementMixin,
|
||||
/** @lends NestedPairDCDCE.prototype */{
|
||||
//TODO:?? possibly rename to NestedDatasetCollection?
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
// because all objects have constructors (as this hashmap would even if this next line wasn't present)
|
||||
// the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model
|
||||
// - re-apply manually it now
|
||||
/** This is both a collection and a collection element - call the constructor */
|
||||
constructor : function( attributes, options ){
|
||||
this.debug( '\t NestedPairDCDCE.constructor:', attributes, options );
|
||||
//DatasetCollection.constructor.call( this, attributes, options );
|
||||
DatasetCollectionElementMixin.constructor.call( this, attributes, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
var objStr = ( this.object )?( '' + this.object ):( this.get( 'element_identifier' ) );
|
||||
return ([ 'NestedPairDCDCE(', objStr, ')' ].join( '' ));
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone collection for a backbone collection containing paired dataset collections.
|
||||
*/
|
||||
var NestedPairDCDCECollection = NestedDCDCECollection.extend(
|
||||
/** @lends PairDCDCECollection.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** We know this collection is composed of only nested pair collections */
|
||||
model: NestedPairDCDCE,
|
||||
|
||||
//TODO: unused?
|
||||
/** set up */
|
||||
initialize : function( attrs, options ){
|
||||
this.debug( this + '(NestedPairDCDCECollection).initialize:', attrs, options );
|
||||
NestedDCDCECollection.prototype.initialize.call( this, attrs, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'NestedPairDCDCECollection(', this.length, ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone Model for a DatasetCollection (list) that contains DatasetCollections (pairs).
|
||||
*/
|
||||
var ListPairedDatasetCollection = DatasetCollection.extend(
|
||||
/** @lends ListPairedDatasetCollection.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** list:paired is the only collection that itself contains collections */
|
||||
collectionClass : NestedPairDCDCECollection,
|
||||
|
||||
//TODO: unused?
|
||||
/** set up */
|
||||
initialize : function( attributes, options ){
|
||||
this.debug( this + '(ListPairedDatasetCollection).initialize:', attributes, options );
|
||||
DatasetCollection.prototype.initialize.call( this, attributes, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'ListPairedDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
ListDatasetCollection : ListDatasetCollection,
|
||||
PairDatasetCollection : PairDatasetCollection,
|
||||
ListPairedDatasetCollection : ListPairedDatasetCollection
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/dataset-model","mvc/base-mvc","utils/localization"],function(a,b){var c={defaults:{model_class:"DatasetCollectionElement",element_identifier:null,element_index:null,element_type:null},_mergeObject:function(a){return _.extend(a,a.object),delete a.object,a},constructor:function(a,b){this.debug(" DatasetCollectionElement.constructor:",a,b),a=this._mergeObject(a),Backbone.Model.apply(this,arguments)},parse:function(a){var b=a;return b=this._mergeObject(b)}},d=Backbone.Model.extend(b.LoggableMixin).extend(c),e=Backbone.Collection.extend(b.LoggableMixin).extend({model:d,initialize:function(a,b){this.debug(this+"(DCECollection).initialize:",a,b),b=b||{}},toString:function(){return["DatasetCollectionElementCollection(",this.length,")"].join("")}}),f=a.DatasetAssociation.extend(b.mixin(c,{defaults:_.extend({},a.DatasetAssociation.prototype.defaults,c.defaults),constructor:function(a,b){this.debug(" DatasetDCE.constructor:",a,b),c.constructor.call(this,a,b)},initialize:function(b,c){this.debug(this+"(DatasetDCE).initialize:",b,c),a.DatasetAssociation.prototype.initialize.call(this,b,c)},toString:function(){var a=this.get("element_identifier");return["DatasetDCE(",a,")"].join("")}})),g=e.extend({model:f,initialize:function(a,b){this.debug(this+"(DatasetDCECollection).initialize:",a,b),e.prototype.initialize.call(this,a,b)},toString:function(){return["DatasetDCECollection(",this.length,")"].join("")}}),h=Backbone.Model.extend(b.LoggableMixin).extend(b.SearchableModelMixin).extend({defaults:{collection_type:null,deleted:!1},collectionClass:e,initialize:function(a,b){this.debug(this+"(DatasetCollection).initialize:",a,b,this),this.elements=this._createElementsModel(),this.on("change:elements",function(){this.log("change:elements"),this.elements=this._createElementsModel()})},_createElementsModel:function(){this.debug(this+"._createElementsModel",this.collectionClass,this.get("elements"),this.elements);var a=this.get("elements")||[];return this.unset("elements",{silent:!0}),this.elements=new this.collectionClass(a),this.elements},toJSON:function(){var a=Backbone.Model.prototype.toJSON.call(this);return this.elements&&(a.elements=this.elements.toJSON()),a},inReadyState:function(){return!0},hasDetails:function(){return this.debug("hasDetails:",this.elements.length),0!==this.elements.length},getVisibleContents:function(){return this.elements},"delete":function(a){return this.get("deleted")?jQuery.when():this.save({deleted:!0},a)},undelete:function(a){return!this.get("deleted")||this.get("purged")?jQuery.when():this.save({deleted:!1},a)},isDeletedOrPurged:function(){return this.get("deleted")||this.get("purged")},searchAttributes:["name"],toString:function(){var a=[this.get("id"),this.get("name")||this.get("element_identifier")];return"DatasetCollection("+a.join(",")+")"}}),i=h.extend({collectionClass:g,initialize:function(a,b){this.debug(this+"(ListDatasetCollection).initialize:",a,b),h.prototype.initialize.call(this,a,b)},toString:function(){return["ListDatasetCollection(",this.get("name"),")"].join("")}}),j=i.extend({initialize:function(a,b){this.debug(this+"(PairDatasetCollection).initialize:",a,b),i.prototype.initialize.call(this,a,b)},toString:function(){return["PairDatasetCollection(",this.get("name"),")"].join("")}}),k=h.extend(b.mixin(c,{constructor:function(a,b){this.debug(" NestedDCDCE.constructor:",a,b),c.constructor.call(this,a,b)},toString:function(){var a=this.object?""+this.object:this.get("element_identifier");return["NestedDCDCE(",a,")"].join("")}})),l=e.extend({model:k,initialize:function(a,b){this.debug(this+"(NestedDCDCECollection).initialize:",a,b),e.prototype.initialize.call(this,a,b)},toString:function(){return["NestedDCDCECollection(",this.length,")"].join("")}}),m=j.extend(b.mixin(c,{constructor:function(a,b){this.debug(" NestedPairDCDCE.constructor:",a,b),c.constructor.call(this,a,b)},toString:function(){var a=this.object?""+this.object:this.get("element_identifier");return["NestedPairDCDCE(",a,")"].join("")}})),n=l.extend({model:m,initialize:function(a,b){this.debug(this+"(NestedPairDCDCECollection).initialize:",a,b),l.prototype.initialize.call(this,a,b)},toString:function(){return["NestedPairDCDCECollection(",this.length,")"].join("")}}),o=h.extend({collectionClass:n,initialize:function(a,b){this.debug(this+"(ListPairedDatasetCollection).initialize:",a,b),h.prototype.initialize.call(this,a,b)},toString:function(){return["ListPairedDatasetCollection(",this.get("name"),")"].join("")}});return{ListDatasetCollection:i,PairDatasetCollection:j,ListPairedDatasetCollection:o}});
|
||||
//# sourceMappingURL=../../../maps/mvc/collection/collection-model.js.map
|
||||
@@ -1,222 +1,2 @@
|
||||
define([
|
||||
"mvc/list/list-panel",
|
||||
"mvc/collection/collection-model",
|
||||
"mvc/collection/collection-li",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( LIST_PANEL, DC_MODEL, DC_LI, BASE_MVC, _l ){
|
||||
/* =============================================================================
|
||||
TODO:
|
||||
|
||||
============================================================================= */
|
||||
/** @class non-editable, read-only View/Controller for a dataset collection.
|
||||
*/
|
||||
var _super = LIST_PANEL.ModelListPanel;
|
||||
var CollectionPanel = _super.extend(
|
||||
/** @lends CollectionPanel.prototype */{
|
||||
//MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
className : _super.prototype.className + ' dataset-collection-panel',
|
||||
|
||||
/** sub view class used for datasets */
|
||||
DatasetDCEViewClass : DC_LI.DatasetDCEListItemView,
|
||||
/** sub view class used for nested collections */
|
||||
NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView,
|
||||
/** key of attribute in model to assign to this.collection */
|
||||
modelCollectionKey : 'elements',
|
||||
|
||||
// ......................................................................... SET UP
|
||||
/** Set up the view, set up storage, bind listeners to HistoryContents events
|
||||
* @param {Object} attributes optional settings for the panel
|
||||
*/
|
||||
initialize : function( attributes ){
|
||||
_super.prototype.initialize.call( this, attributes );
|
||||
this.linkTarget = attributes.linkTarget || '_blank';
|
||||
|
||||
this.hasUser = attributes.hasUser;
|
||||
|
||||
/** */
|
||||
this.panelStack = [];
|
||||
/** */
|
||||
this.parentName = attributes.parentName;
|
||||
/** */
|
||||
this.foldoutStyle = attributes.foldoutStyle || 'foldout';
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ sub-views
|
||||
/** In this override, use model.getVisibleContents */
|
||||
_filterCollection : function(){
|
||||
//TODO: should *not* be model.getVisibleContents - visibility is not model related
|
||||
return this.model.getVisibleContents();
|
||||
},
|
||||
|
||||
/** override to return proper view class based on element_type */
|
||||
_getItemViewClass : function( model ){
|
||||
//this.debug( this + '._getItemViewClass:', model );
|
||||
//TODO: subclasses use DCEViewClass - but are currently unused - decide
|
||||
switch( model.get( 'element_type' ) ){
|
||||
case 'hda':
|
||||
return this.DatasetDCEViewClass;
|
||||
case 'dataset_collection':
|
||||
return this.NestedDCDCEViewClass;
|
||||
}
|
||||
throw new TypeError( 'Unknown element type:', model.get( 'element_type' ) );
|
||||
},
|
||||
|
||||
/** override to add link target and anon */
|
||||
_getItemViewOptions : function( model ){
|
||||
var options = _super.prototype._getItemViewOptions.call( this, model );
|
||||
return _.extend( options, {
|
||||
linkTarget : this.linkTarget,
|
||||
hasUser : this.hasUser,
|
||||
//TODO: could move to only nested: list:paired
|
||||
foldoutStyle : this.foldoutStyle
|
||||
});
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ collection sub-views
|
||||
/** In this override, add/remove expanded/collapsed model ids to/from web storage */
|
||||
_setUpItemViewListeners : function( view ){
|
||||
var panel = this;
|
||||
_super.prototype._setUpItemViewListeners.call( panel, view );
|
||||
|
||||
// use pub-sub to: handle drilldown expansion and collapse
|
||||
view.on( 'expanded:drilldown', function( v, drilldown ){
|
||||
this._expandDrilldownPanel( drilldown );
|
||||
}, this );
|
||||
view.on( 'collapsed:drilldown', function( v, drilldown ){
|
||||
this._collapseDrilldownPanel( drilldown );
|
||||
}, this );
|
||||
return this;
|
||||
},
|
||||
|
||||
/** Handle drill down by hiding this panels list and controls and showing the sub-panel */
|
||||
_expandDrilldownPanel : function( drilldown ){
|
||||
this.panelStack.push( drilldown );
|
||||
// hide this panel's controls and list, set the name for back navigation, and attach to the $el
|
||||
this.$( '> .controls' ).add( this.$list() ).hide();
|
||||
drilldown.parentName = this.model.get( 'name' );
|
||||
this.$el.append( drilldown.render().$el );
|
||||
},
|
||||
|
||||
/** Handle drilldown close by freeing the panel and re-rendering this panel */
|
||||
_collapseDrilldownPanel : function( drilldown ){
|
||||
this.panelStack.pop();
|
||||
this.render();
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ panel events
|
||||
/** event map */
|
||||
events : {
|
||||
'click .navigation .back' : 'close'
|
||||
},
|
||||
|
||||
/** close/remove this collection panel */
|
||||
close : function( event ){
|
||||
this.$el.remove();
|
||||
this.trigger( 'close' );
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
return 'CollectionPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------ TEMPLATES
|
||||
CollectionPanel.prototype.templates = (function(){
|
||||
|
||||
var controlsTemplate = BASE_MVC.wrapTemplate([
|
||||
'<div class="controls">',
|
||||
'<div class="navigation">',
|
||||
'<a class="back" href="javascript:void(0)">',
|
||||
'<span class="fa fa-icon fa-angle-left"></span>',
|
||||
_l( 'Back to ' ), '<%- view.parentName %>',
|
||||
'</a>',
|
||||
'</div>',
|
||||
|
||||
'<div class="title">',
|
||||
'<div class="name"><%- collection.name || collection.element_identifier %></div>',
|
||||
'<div class="subtitle">',
|
||||
//TODO: remove logic from template
|
||||
'<% if( collection.collection_type === "list" ){ %>',
|
||||
_l( 'a list of datasets' ),
|
||||
'<% } else if( collection.collection_type === "paired" ){ %>',
|
||||
_l( 'a pair of datasets' ),
|
||||
'<% } else if( collection.collection_type === "list:paired" ){ %>',
|
||||
_l( 'a list of paired datasets' ),
|
||||
'<% } %>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
], 'collection' );
|
||||
|
||||
return _.extend( _.clone( _super.prototype.templates ), {
|
||||
controls : controlsTemplate
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
|
||||
// =============================================================================
|
||||
/** @class non-editable, read-only View/Controller for a dataset collection. */
|
||||
var ListCollectionPanel = CollectionPanel.extend(
|
||||
/** @lends ListCollectionPanel.prototype */{
|
||||
|
||||
//TODO: not strictly needed - due to switch in CollectionPanel._getContentClass
|
||||
/** sub view class used for datasets */
|
||||
DatasetDCEViewClass : DC_LI.DatasetDCEListItemView,
|
||||
|
||||
// ........................................................................ misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
return 'ListCollectionPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// =============================================================================
|
||||
/** @class non-editable, read-only View/Controller for a dataset collection. */
|
||||
var PairCollectionPanel = ListCollectionPanel.extend(
|
||||
/** @lends PairCollectionPanel.prototype */{
|
||||
|
||||
// ........................................................................ misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
return 'PairCollectionPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// =============================================================================
|
||||
/** @class non-editable, read-only View/Controller for a dataset collection. */
|
||||
var ListOfPairsCollectionPanel = CollectionPanel.extend(
|
||||
/** @lends ListOfPairsCollectionPanel.prototype */{
|
||||
|
||||
//TODO: not strictly needed - due to switch in CollectionPanel._getContentClass
|
||||
/** sub view class used for nested collections */
|
||||
NestedDCDCEViewClass : DC_LI.NestedDCDCEListItemView.extend({
|
||||
foldoutPanelClass : PairCollectionPanel
|
||||
}),
|
||||
|
||||
// ........................................................................ misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
return 'ListOfPairsCollectionPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
CollectionPanel : CollectionPanel,
|
||||
ListCollectionPanel : ListCollectionPanel,
|
||||
PairCollectionPanel : PairCollectionPanel,
|
||||
ListOfPairsCollectionPanel : ListOfPairsCollectionPanel
|
||||
};
|
||||
});
|
||||
define(["mvc/list/list-panel","mvc/collection/collection-model","mvc/collection/collection-li","mvc/base-mvc","utils/localization"],function(a,b,c,d,e){var f=a.ModelListPanel,g=f.extend({className:f.prototype.className+" dataset-collection-panel",DatasetDCEViewClass:c.DatasetDCEListItemView,NestedDCDCEViewClass:c.NestedDCDCEListItemView,modelCollectionKey:"elements",initialize:function(a){f.prototype.initialize.call(this,a),this.linkTarget=a.linkTarget||"_blank",this.hasUser=a.hasUser,this.panelStack=[],this.parentName=a.parentName,this.foldoutStyle=a.foldoutStyle||"foldout"},_filterCollection:function(){return this.model.getVisibleContents()},_getItemViewClass:function(a){switch(a.get("element_type")){case"hda":return this.DatasetDCEViewClass;case"dataset_collection":return this.NestedDCDCEViewClass}throw new TypeError("Unknown element type:",a.get("element_type"))},_getItemViewOptions:function(a){var b=f.prototype._getItemViewOptions.call(this,a);return _.extend(b,{linkTarget:this.linkTarget,hasUser:this.hasUser,foldoutStyle:this.foldoutStyle})},_setUpItemViewListeners:function(a){var b=this;return f.prototype._setUpItemViewListeners.call(b,a),a.on("expanded:drilldown",function(a,b){this._expandDrilldownPanel(b)},this),a.on("collapsed:drilldown",function(a,b){this._collapseDrilldownPanel(b)},this),this},_expandDrilldownPanel:function(a){this.panelStack.push(a),this.$("> .controls").add(this.$list()).hide(),a.parentName=this.model.get("name"),this.$el.append(a.render().$el)},_collapseDrilldownPanel:function(){this.panelStack.pop(),this.render()},events:{"click .navigation .back":"close"},close:function(){this.$el.remove(),this.trigger("close")},toString:function(){return"CollectionPanel("+(this.model?this.model.get("name"):"")+")"}});g.prototype.templates=function(){var a=d.wrapTemplate(['<div class="controls">','<div class="navigation">','<a class="back" href="javascript:void(0)">','<span class="fa fa-icon fa-angle-left"></span>',e("Back to "),"<%- view.parentName %>","</a>","</div>",'<div class="title">','<div class="name"><%- collection.name || collection.element_identifier %></div>','<div class="subtitle">','<% if( collection.collection_type === "list" ){ %>',e("a list of datasets"),'<% } else if( collection.collection_type === "paired" ){ %>',e("a pair of datasets"),'<% } else if( collection.collection_type === "list:paired" ){ %>',e("a list of paired datasets"),"<% } %>","</div>","</div>","</div>"],"collection");return _.extend(_.clone(f.prototype.templates),{controls:a})}();var h=g.extend({DatasetDCEViewClass:c.DatasetDCEListItemView,toString:function(){return"ListCollectionPanel("+(this.model?this.model.get("name"):"")+")"}}),i=h.extend({toString:function(){return"PairCollectionPanel("+(this.model?this.model.get("name"):"")+")"}}),j=g.extend({NestedDCDCEViewClass:c.NestedDCDCEListItemView.extend({foldoutPanelClass:i}),toString:function(){return"ListOfPairsCollectionPanel("+(this.model?this.model.get("name"):"")+")"}});return{CollectionPanel:g,ListCollectionPanel:h,PairCollectionPanel:i,ListOfPairsCollectionPanel:j}});
|
||||
//# sourceMappingURL=../../../maps/mvc/collection/collection-panel.js.map
|
||||
File diff suppressed because one or more lines are too long
+2
-675
File diff suppressed because one or more lines are too long
@@ -1,442 +1,2 @@
|
||||
define([
|
||||
'mvc/dataset/dataset-model',
|
||||
'mvc/dataset/dataset-list',
|
||||
'mvc/ui/ui-modal',
|
||||
'mvc/base-mvc',
|
||||
'utils/localization'
|
||||
], function( DATASET, DATASET_LIST, MODAL, BASE_MVC, _l ){
|
||||
/* ============================================================================
|
||||
TODO:
|
||||
does this really work with mixed contents?
|
||||
Single dataset choice: allow none?
|
||||
tooltips rendered *behind* modal
|
||||
collection selector
|
||||
better handling when no results returned from filterDatasetJSON
|
||||
pass optional subtitle from choice display to modal
|
||||
onfirstclick
|
||||
drop target
|
||||
return modal with promise?
|
||||
|
||||
auto showing the modal may not be best
|
||||
|
||||
add hidden inputs
|
||||
// cut1 on single dataset (17 in the list)
|
||||
__switch_default__ select_single
|
||||
input 17
|
||||
|
||||
// cut1 on two datasets
|
||||
__switch_default__ select_single
|
||||
input|__multirun__ 13
|
||||
input|__multirun__ 15
|
||||
|
||||
// cut1 on a collection
|
||||
__switch_default__ select_collection
|
||||
input|__collection_multirun__ f2db41e1fa331b3e
|
||||
|
||||
============================================================================ */
|
||||
/** Filters an array of dataset plain JSON objs.
|
||||
*/
|
||||
function _filterDatasetJSON( datasetJSON, where, datasetsOnly ){
|
||||
//TODO: replace with _.matches (underscore 1.6.0)
|
||||
function matches( obj, toMatch ){
|
||||
for( var key in toMatch ){
|
||||
if( toMatch.hasOwnProperty( key ) ){
|
||||
if( obj[ key ] !== toMatch[ key ] ){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return datasetJSON.filter( function( json ){
|
||||
return ( !json.deleted && json.visible )
|
||||
&& ( !datasetsOnly || json.collection_type === undefined )
|
||||
&& ( matches( json, where ) );
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
/** Given an array of plain JSON objs rep. datasets, show a modal allowing a choice
|
||||
* of one or more of those datasets.
|
||||
*
|
||||
* Pass:
|
||||
* an array of plain JSON objects representing allowed dataset choices
|
||||
* a map of options (see below)
|
||||
*
|
||||
* Options:
|
||||
* datasetsOnly: T: display only datasets, F: datasets + dataset collections
|
||||
* where: a map of attributes available choices *must have* (defaults to { state: 'ok' })
|
||||
* multiselect: T: user can select more than one, F: only one
|
||||
* selected: array of dataset ids to make them selected by default
|
||||
*
|
||||
* @example:
|
||||
* var datasetJSON = // from ajax or bootstrap
|
||||
* // returns a jQuery promise (that 'fail's only if no datasets are found matching 'where' below)
|
||||
* var choice = new DatasetChoiceModal( datasetJSON, {
|
||||
* datasetsOnly : false,
|
||||
* where : { state: 'ok', file_ext: 'bed', ... },
|
||||
* multiselect : true,
|
||||
* selected : [ 'df7a1f0c02a5b08e', 'abcdef0123456789' ]
|
||||
*
|
||||
* }).done( function( json ){
|
||||
* if( json ){
|
||||
* console.debug( json );
|
||||
* // returned choice will always be an array (single or multi)
|
||||
* // [{ <selected dataset JSON 1>, <selected dataset JSON 2>, ... }]
|
||||
* // ... do stuff
|
||||
* } else {
|
||||
* // json will === null if the user cancelled selection
|
||||
* console.debug( 'cancelled' );
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
var DatasetChoiceModal = function( datasetJSON, options ){
|
||||
|
||||
// option defaults
|
||||
options = _.defaults( options || {}, {
|
||||
// show datasets or datasets and collections
|
||||
datasetsOnly : true,
|
||||
// map of attributes to filter datasetJSON by
|
||||
where : { state: 'ok' },
|
||||
// select more than one dataset?
|
||||
multiselect : false,
|
||||
// any dataset ids that will display as already selected
|
||||
selected : []
|
||||
});
|
||||
// default title should depend on multiselect
|
||||
options.title = options.title ||
|
||||
( options.multiselect? _l( 'Choose datasets:' ): _l( 'Choose a dataset:' ) );
|
||||
|
||||
var modal, list, buttons,
|
||||
promise = jQuery.Deferred(),
|
||||
filterFn = options.filter || _filterDatasetJSON;
|
||||
|
||||
// filter the given datasets and if none left return a rejected promise for use with fail()
|
||||
datasetJSON = filterFn( datasetJSON, options.where, options.datasetsOnly );
|
||||
if( !datasetJSON.length ){
|
||||
return promise.reject( 'No matches found' );
|
||||
}
|
||||
|
||||
// resolve the returned promise with the json of the selected datasets
|
||||
function resolveWithSelected(){
|
||||
promise.resolve( list.getSelectedModels().map( function( model ){
|
||||
return model.toJSON();
|
||||
}));
|
||||
}
|
||||
// if multiselect - add a button for the user to complete the changes
|
||||
if( options.multiselect ){
|
||||
buttons = {};
|
||||
buttons[ _l( 'Ok' ) ] = resolveWithSelected;
|
||||
}
|
||||
|
||||
// create a full-height modal that's cancellable, remove unneeded elements and styles
|
||||
modal = new MODAL.View({
|
||||
height : 'auto',
|
||||
buttons : buttons,
|
||||
closing_events : true,
|
||||
closing_callback : function(){ promise.resolve( null ); },
|
||||
body : [
|
||||
'<div class="list-panel"></div>'
|
||||
].join('')
|
||||
});
|
||||
modal.$( '.modal-header' ).remove();
|
||||
modal.$( '.modal-footer' ).css( 'margin-top', '0px' );
|
||||
|
||||
// attach a dataset list (of the filtered datasets) to that modal that's selectable
|
||||
list = new DATASET_LIST.DatasetList({
|
||||
title : options.title,
|
||||
subtitle : options.subtitle || _l([
|
||||
//TODO: as option
|
||||
'Click the checkboxes on the right to select datasets. ',
|
||||
'Click the datasets names to see their details. '
|
||||
].join('')),
|
||||
el : modal.$body.find( '.list-panel' ),
|
||||
selecting : true,
|
||||
selected : options.selected,
|
||||
collection : new DATASET.DatasetAssociationCollection( datasetJSON )
|
||||
});
|
||||
|
||||
// when the list is rendered, show the modal (also add a specifying class for css)
|
||||
list.once( 'rendered:initial', function(){
|
||||
modal.show();
|
||||
modal.$el.addClass( 'dataset-choice-modal' );
|
||||
});
|
||||
if( !options.multiselect ){
|
||||
// if single select, remove the all/none list actions from the panel
|
||||
list.on( 'rendered', function(){
|
||||
list.$( '.list-actions' ).hide();
|
||||
});
|
||||
// if single select, immediately resolve on a single selection
|
||||
list.on( 'view:selected', function( view ){
|
||||
promise.resolve([ view.model.toJSON() ]);
|
||||
});
|
||||
}
|
||||
list.render( 0 );
|
||||
|
||||
// return the promise, and on any resolution close the modal
|
||||
return promise.always( function(){
|
||||
modal.hide();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// ============================================================================
|
||||
/** Activator for single dataset selection modal and display of the selected dataset.
|
||||
* The activator/display will show as a single div and, when a dataset is selected,
|
||||
* show the name and details of the selected dataset.
|
||||
*
|
||||
* When clicked the div will generate a DatasetChoiceModal of the available choices.
|
||||
*
|
||||
* Options:
|
||||
* datasetJSON: array of plain json objects representing allowed choices
|
||||
* datasetsOnly: T: only show datasets in the allowed choices, F: datasets + collections
|
||||
* where: map of attributes to filter datasetJSON by (e.g. { file_ext: 'bed' })
|
||||
* label: the label/prompt displayed
|
||||
* selected: array of dataset ids that will show as already selected in the control
|
||||
*
|
||||
* @example:
|
||||
* var choice1 = new DATASET_CHOICE.DatasetChoice({
|
||||
* datasetJSON : datasetJSON,
|
||||
* label : 'Input dataset',
|
||||
* selected : [ 'df7a1f0c02a5b08e' ]
|
||||
* });
|
||||
* $( 'body' ).append( choice1.render().$el )
|
||||
*
|
||||
* Listen to the DatasetChoice to react to changes in the user's choice/selection:
|
||||
* @example:
|
||||
* choice1.on( 'selected', function( chooser, selectionJSONArray ){
|
||||
* // ... do stuff with new selections
|
||||
* });
|
||||
*/
|
||||
var DatasetChoice = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
|
||||
|
||||
//logger : console,
|
||||
|
||||
className : 'dataset-choice',
|
||||
|
||||
/** set up defaults, options, and listeners */
|
||||
initialize : function( attributes ){
|
||||
this.debug( this + '(DatasetChoice).initialize:', attributes );
|
||||
|
||||
this.label = attributes.label !== undefined? _l( attributes.label ) : '';
|
||||
this.where = attributes.where;
|
||||
this.datasetsOnly = attributes.datasetsOnly !== undefined? attributes.datasetsOnly: true;
|
||||
|
||||
this.datasetJSON = attributes.datasetJSON || [];
|
||||
this.selected = attributes.selected || [];
|
||||
|
||||
this._setUpListeners();
|
||||
},
|
||||
|
||||
/** add any (bbone) listeners */
|
||||
_setUpListeners : function(){
|
||||
//this.on( 'all', function(){
|
||||
// this.log( this + '', arguments );
|
||||
//});
|
||||
},
|
||||
|
||||
/** render the view */
|
||||
render : function(){
|
||||
var json = this.toJSON();
|
||||
this.$el.html( this._template( json ) );
|
||||
this.$( '.selected' ).replaceWith( this._renderSelected( json ) );
|
||||
return this;
|
||||
},
|
||||
|
||||
/** return plain html for the overall control */
|
||||
_template : function( json ){
|
||||
return _.template([
|
||||
'<label>',
|
||||
'<span class="prompt"><%= json.label %></span>',
|
||||
'<div class="selected"></div>',
|
||||
'</label>'
|
||||
].join(''), { json: json });
|
||||
},
|
||||
|
||||
/** return jQ DOM for the selected dataset (only one) */
|
||||
_renderSelected : function( json ){
|
||||
if( json.selected.length ){
|
||||
//TODO: break out?
|
||||
return $( _.template([
|
||||
'<div class="selected">',
|
||||
'<span class="title"><%= selected.hid %>: <%= selected.name %></span>',
|
||||
'<span class="subtitle">',
|
||||
'<i><%= selected.misc_blurb %></i>',
|
||||
'<i>', _l( 'format' ) + ': ', '<%= selected.file_ext %></i>',
|
||||
'<i><%= selected.misc_info %></i>',
|
||||
'</span>',
|
||||
'</div>'
|
||||
].join( '' ), { selected: json.selected[0] }));
|
||||
}
|
||||
return $([
|
||||
'<span class="none-selected-msg">(',
|
||||
_l( 'click to select a dataset' ),
|
||||
')</span>'
|
||||
].join( '' ));
|
||||
},
|
||||
|
||||
//TODO:?? why not just pass in view?
|
||||
/** return a plain JSON object with both the view and dataset attributes */
|
||||
toJSON : function(){
|
||||
var chooser = this;
|
||||
return {
|
||||
label : chooser.label,
|
||||
datasets : chooser.datasetJSON,
|
||||
selected : _.compact( _.map( chooser.selected, function( id ){
|
||||
return _.findWhere( chooser.datasetJSON, { id: id });
|
||||
}))
|
||||
};
|
||||
},
|
||||
|
||||
/** event map: when to open the modal */
|
||||
events : {
|
||||
// the whole thing functions as a button
|
||||
'click' : 'chooseWithModal'
|
||||
},
|
||||
|
||||
//TODO:?? modal to prop of this?
|
||||
//TODO:?? should be able to handle 'none selectable' on initialize
|
||||
/** open the modal and handle the promise representing the user's choice
|
||||
* @fires 'selected' when the user selects dataset(s) - passed full json of the selected datasets
|
||||
* @fires 'cancelled' when the user clicks away/closes the modal (no selection made) - passed this
|
||||
* @fires 'error' if the modal has no selectable datasets based on this.where - passed this and other args
|
||||
*/
|
||||
chooseWithModal : function(){
|
||||
var chooser = this;
|
||||
|
||||
return this._createModal()
|
||||
.done( function( json ){
|
||||
if( json ){
|
||||
chooser.selected = _.pluck( json, 'id' );
|
||||
chooser.trigger( 'selected', chooser, json );
|
||||
chooser.render();
|
||||
|
||||
} else {
|
||||
chooser.trigger( 'cancelled', chooser );
|
||||
}
|
||||
})
|
||||
|
||||
.fail( function(){
|
||||
chooser.trigger( 'error', chooser, arguments );
|
||||
});
|
||||
},
|
||||
|
||||
/** create and return the modal to use for choosing */
|
||||
_createModal : function(){
|
||||
return new DatasetChoiceModal( this.datasetJSON, this._getModalOptions() );
|
||||
},
|
||||
|
||||
/** return a plain JSON containing the options to pass to the modal */
|
||||
_getModalOptions : function(){
|
||||
return {
|
||||
title : this.label,
|
||||
multiselect : false,
|
||||
selected : this.selected,
|
||||
where : this.where,
|
||||
datasetsOnly : this.datasetsOnly
|
||||
};
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
return 'DatasetChoice(' + this.selected + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ============================================================================
|
||||
/** Activator for multiple dataset selection modal and display of the selected datasets.
|
||||
* The activator/display will show as a table of all choices.
|
||||
*
|
||||
* See DatasetChoice (above) for example usage.
|
||||
*
|
||||
* Additional options:
|
||||
* showHeaders: T: show headers for selected dataset attributes in the display table
|
||||
* cells: map of attribute keys -> Human readable/localized column headers
|
||||
* (e.g. { file_ext: _l( 'Format' ) }) - defaults are listed below
|
||||
*/
|
||||
var MultiDatasetChoice = DatasetChoice.extend({
|
||||
|
||||
className : DatasetChoice.prototype.className + ' multi',
|
||||
|
||||
/** default (dataset attribute key -> table header text) map of what cells to display in the table */
|
||||
cells : {
|
||||
hid : _l( 'History #' ),
|
||||
name : _l( 'Name' ),
|
||||
misc_blurb : _l( 'Summary' ),
|
||||
file_ext : _l( 'Format' ),
|
||||
genome_build : _l( 'Genome' ),
|
||||
tags : _l( 'Tags' ),
|
||||
annotation : _l( 'Annotation' )
|
||||
},
|
||||
|
||||
/** in this override, add the showHeaders and cells options */
|
||||
initialize : function( attributes ){
|
||||
this.showHeaders = attributes.showHeaders !== undefined? attributes.showHeaders : true;
|
||||
this.cells = attributes.cells || this.cells;
|
||||
DatasetChoice.prototype.initialize.call( this, attributes );
|
||||
},
|
||||
|
||||
/** in this override, display the selected datasets as a table with optional headers */
|
||||
_renderSelected : function( json ){
|
||||
if( json.selected.length ){
|
||||
return $( _.template([
|
||||
'<table class="selected">',
|
||||
'<% if( json.showHeaders ){ %>',
|
||||
'<thead><tr>',
|
||||
'<% _.map( json.cells, function( val, key ){ %>',
|
||||
'<th><%= val %></th>',
|
||||
'<% }); %>',
|
||||
'</tr></thead>',
|
||||
'<% } %>',
|
||||
'<tbody>',
|
||||
'<% _.map( json.selected, function( selected ){ %>',
|
||||
'<tr>',
|
||||
'<% _.map( json.cells, function( val, key ){ %>',
|
||||
'<td class="cell-<%= key %>"><%= selected[ key ] %></td>',
|
||||
'<% }) %>',
|
||||
'</tr>',
|
||||
'<% }); %>',
|
||||
'</tbody>',
|
||||
'</table>'
|
||||
].join( '' ), { json: json }));
|
||||
}
|
||||
return $([
|
||||
'<span class="none-selected-msg">(',
|
||||
_l( 'click to select a dataset' ),
|
||||
')</span>'
|
||||
].join( '' ));
|
||||
},
|
||||
|
||||
/** in this override, send the showHeaders and cells options as well */
|
||||
toJSON : function(){
|
||||
return _.extend( DatasetChoice.prototype.toJSON.call( this ), {
|
||||
showHeaders : this.showHeaders,
|
||||
cells : this.cells
|
||||
});
|
||||
},
|
||||
|
||||
/** in this override, set multiselect to true */
|
||||
_getModalOptions : function(){
|
||||
return _.extend( DatasetChoice.prototype._getModalOptions.call( this ), {
|
||||
multiselect : true
|
||||
});
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
return 'DatasetChoice(' + this.selected + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ============================================================================
|
||||
return {
|
||||
DatasetChoiceModal : DatasetChoiceModal,
|
||||
DatasetChoice : DatasetChoice,
|
||||
MultiDatasetChoice : MultiDatasetChoice
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/dataset-model","mvc/dataset/dataset-list","mvc/ui/ui-modal","mvc/base-mvc","utils/localization"],function(a,b,c,d,e){function f(a,b,c){function d(a,b){for(var c in b)if(b.hasOwnProperty(c)&&a[c]!==b[c])return!1;return!0}return a.filter(function(a){return!a.deleted&&a.visible&&(!c||void 0===a.collection_type)&&d(a,b)})}var g=function(d,g){function h(){l.resolve(j.getSelectedModels().map(function(a){return a.toJSON()}))}g=_.defaults(g||{},{datasetsOnly:!0,where:{state:"ok"},multiselect:!1,selected:[]}),g.title=g.title||e(g.multiselect?"Choose datasets:":"Choose a dataset:");var i,j,k,l=jQuery.Deferred(),m=g.filter||f;return d=m(d,g.where,g.datasetsOnly),d.length?(g.multiselect&&(k={},k[e("Ok")]=h),i=new c.View({height:"auto",buttons:k,closing_events:!0,closing_callback:function(){l.resolve(null)},body:['<div class="list-panel"></div>'].join("")}),i.$(".modal-header").remove(),i.$(".modal-footer").css("margin-top","0px"),j=new b.DatasetList({title:g.title,subtitle:g.subtitle||e(["Click the checkboxes on the right to select datasets. ","Click the datasets names to see their details. "].join("")),el:i.$body.find(".list-panel"),selecting:!0,selected:g.selected,collection:new a.DatasetAssociationCollection(d)}),j.once("rendered:initial",function(){i.show(),i.$el.addClass("dataset-choice-modal")}),g.multiselect||(j.on("rendered",function(){j.$(".list-actions").hide()}),j.on("view:selected",function(a){l.resolve([a.model.toJSON()])})),j.render(0),l.always(function(){i.hide()})):l.reject("No matches found")},h=Backbone.View.extend(d.LoggableMixin).extend({className:"dataset-choice",initialize:function(a){this.debug(this+"(DatasetChoice).initialize:",a),this.label=void 0!==a.label?e(a.label):"",this.where=a.where,this.datasetsOnly=void 0!==a.datasetsOnly?a.datasetsOnly:!0,this.datasetJSON=a.datasetJSON||[],this.selected=a.selected||[],this._setUpListeners()},_setUpListeners:function(){},render:function(){var a=this.toJSON();return this.$el.html(this._template(a)),this.$(".selected").replaceWith(this._renderSelected(a)),this},_template:function(a){return _.template(["<label>",'<span class="prompt"><%= json.label %></span>','<div class="selected"></div>',"</label>"].join(""),{json:a})},_renderSelected:function(a){return $(a.selected.length?_.template(['<div class="selected">','<span class="title"><%= selected.hid %>: <%= selected.name %></span>','<span class="subtitle">',"<i><%= selected.misc_blurb %></i>","<i>",e("format")+": ","<%= selected.file_ext %></i>","<i><%= selected.misc_info %></i>","</span>","</div>"].join(""),{selected:a.selected[0]}):['<span class="none-selected-msg">(',e("click to select a dataset"),")</span>"].join(""))},toJSON:function(){var a=this;return{label:a.label,datasets:a.datasetJSON,selected:_.compact(_.map(a.selected,function(b){return _.findWhere(a.datasetJSON,{id:b})}))}},events:{click:"chooseWithModal"},chooseWithModal:function(){var a=this;return this._createModal().done(function(b){b?(a.selected=_.pluck(b,"id"),a.trigger("selected",a,b),a.render()):a.trigger("cancelled",a)}).fail(function(){a.trigger("error",a,arguments)})},_createModal:function(){return new g(this.datasetJSON,this._getModalOptions())},_getModalOptions:function(){return{title:this.label,multiselect:!1,selected:this.selected,where:this.where,datasetsOnly:this.datasetsOnly}},toString:function(){return"DatasetChoice("+this.selected+")"}}),i=h.extend({className:h.prototype.className+" multi",cells:{hid:e("History #"),name:e("Name"),misc_blurb:e("Summary"),file_ext:e("Format"),genome_build:e("Genome"),tags:e("Tags"),annotation:e("Annotation")},initialize:function(a){this.showHeaders=void 0!==a.showHeaders?a.showHeaders:!0,this.cells=a.cells||this.cells,h.prototype.initialize.call(this,a)},_renderSelected:function(a){return $(a.selected.length?_.template(['<table class="selected">',"<% if( json.showHeaders ){ %>","<thead><tr>","<% _.map( json.cells, function( val, key ){ %>","<th><%= val %></th>","<% }); %>","</tr></thead>","<% } %>","<tbody>","<% _.map( json.selected, function( selected ){ %>","<tr>","<% _.map( json.cells, function( val, key ){ %>",'<td class="cell-<%= key %>"><%= selected[ key ] %></td>',"<% }) %>","</tr>","<% }); %>","</tbody>","</table>"].join(""),{json:a}):['<span class="none-selected-msg">(',e("click to select a dataset"),")</span>"].join(""))},toJSON:function(){return _.extend(h.prototype.toJSON.call(this),{showHeaders:this.showHeaders,cells:this.cells})},_getModalOptions:function(){return _.extend(h.prototype._getModalOptions.call(this),{multiselect:!0})},toString:function(){return"DatasetChoice("+this.selected+")"}});return{DatasetChoiceModal:g,DatasetChoice:h,MultiDatasetChoice:i}});
|
||||
//# sourceMappingURL=../../../maps/mvc/dataset/dataset-choice.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,45 +1,2 @@
|
||||
define([
|
||||
"mvc/list/list-panel",
|
||||
"mvc/dataset/dataset-li",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( LIST_PANEL, DATASET_LI, BASE_MVC, _l ){
|
||||
/* =============================================================================
|
||||
TODO:
|
||||
|
||||
============================================================================= */
|
||||
var _super = LIST_PANEL.ListPanel;
|
||||
/** @class non-editable, read-only View/Controller for a list of datasets.
|
||||
*/
|
||||
var DatasetList = _super.extend(
|
||||
/** @lends DatasetList.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** class to use for constructing the sub-views */
|
||||
viewClass : DATASET_LI.DatasetListItemView,
|
||||
className : _super.prototype.className + ' dataset-list',
|
||||
|
||||
/** string to no hdas match the search terms */
|
||||
noneFoundMsg : _l( 'No matching datasets found' ),
|
||||
|
||||
// ......................................................................... SET UP
|
||||
/** Set up the view, set up storage, bind listeners to HistoryContents events
|
||||
* @param {Object} attributes optional settings for the panel
|
||||
*/
|
||||
initialize : function( attributes ){
|
||||
_super.prototype.initialize.call( this, attributes );
|
||||
},
|
||||
|
||||
/** Return a string rep of the history */
|
||||
toString : function(){
|
||||
return 'DatasetList(' + this.collection + ')';
|
||||
}
|
||||
});
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
DatasetList : DatasetList
|
||||
};
|
||||
});
|
||||
define(["mvc/list/list-panel","mvc/dataset/dataset-li","mvc/base-mvc","utils/localization"],function(a,b,c,d){var e=a.ListPanel,f=e.extend({viewClass:b.DatasetListItemView,className:e.prototype.className+" dataset-list",noneFoundMsg:d("No matching datasets found"),initialize:function(a){e.prototype.initialize.call(this,a)},toString:function(){return"DatasetList("+this.collection+")"}});return{DatasetList:f}});
|
||||
//# sourceMappingURL=../../../maps/mvc/dataset/dataset-list.js.map
|
||||
@@ -1,341 +1,2 @@
|
||||
define([
|
||||
"mvc/dataset/states",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( STATES, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
var searchableMixin = BASE_MVC.SearchableModelMixin;
|
||||
/** @class base model for any DatasetAssociation (HDAs, LDDAs, DatasetCollectionDAs).
|
||||
* No knowledge of what type (HDA/LDDA/DCDA) should be needed here.
|
||||
* The DA's are made searchable (by attribute) by mixing in SearchableModelMixin.
|
||||
*/
|
||||
var DatasetAssociation = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
|
||||
BASE_MVC.mixin( searchableMixin, /** @lends DatasetAssociation.prototype */{
|
||||
|
||||
/** default attributes for a model */
|
||||
defaults : {
|
||||
state : STATES.NEW,
|
||||
deleted : false,
|
||||
purged : false,
|
||||
|
||||
// unreliable attribute
|
||||
name : '(unnamed dataset)',
|
||||
|
||||
//TODO: update to false when this is correctly passed from the API (when we have a security model for this)
|
||||
accessible : true,
|
||||
|
||||
// sniffed datatype (sam, tabular, bed, etc.)
|
||||
data_type : '',
|
||||
file_ext : '',
|
||||
|
||||
// size in bytes
|
||||
file_size : 0,
|
||||
|
||||
// array of associated file types (eg. [ 'bam_index', ... ])
|
||||
meta_files : [],
|
||||
|
||||
misc_blurb : '',
|
||||
misc_info : '',
|
||||
|
||||
tags : []
|
||||
// do NOT default on annotation, as this default is valid and will be passed on 'save'
|
||||
// which is incorrect behavior when the model is only partially fetched (annos are not passed in summary data)
|
||||
//annotation : ''
|
||||
},
|
||||
|
||||
/** instance vars and listeners */
|
||||
initialize : function( attributes, options ){
|
||||
this.debug( this + '(Dataset).initialize', attributes, options );
|
||||
|
||||
//!! this state is not in trans.app.model.Dataset.states - set it here -
|
||||
if( !this.get( 'accessible' ) ){
|
||||
this.set( 'state', STATES.NOT_VIEWABLE );
|
||||
}
|
||||
|
||||
/** Datasets rely/use some web controllers - have the model generate those URLs on startup */
|
||||
this.urls = this._generateUrls();
|
||||
|
||||
this._setUpListeners();
|
||||
},
|
||||
|
||||
/** returns misc. web urls for rendering things like re-run, display, etc. */
|
||||
_generateUrls : function(){
|
||||
//TODO: would be nice if the API did this
|
||||
var id = this.get( 'id' );
|
||||
if( !id ){ return {}; }
|
||||
var urls = {
|
||||
'purge' : 'datasets/' + id + '/purge_async',
|
||||
'display' : 'datasets/' + id + '/display/?preview=True',
|
||||
'edit' : 'datasets/' + id + '/edit',
|
||||
'download' : 'datasets/' + id + '/display?to_ext=' + this.get( 'file_ext' ),
|
||||
'report_error' : 'dataset/errors?id=' + id,
|
||||
'rerun' : 'tool_runner/rerun?id=' + id,
|
||||
'show_params' : 'datasets/' + id + '/show_params',
|
||||
'visualization' : 'visualization',
|
||||
'meta_download' : 'dataset/get_metadata_file?hda_id=' + id + '&metadata_name='
|
||||
};
|
||||
//TODO: global
|
||||
var root = ( window.galaxy_config && galaxy_config.root )?( galaxy_config.root ):( '/' );
|
||||
_.each( urls, function( value, key ){
|
||||
urls[ key ] = root + value;
|
||||
});
|
||||
this.urls = urls;
|
||||
return urls;
|
||||
},
|
||||
|
||||
/** set up any event listeners
|
||||
* event: state:ready fired when this DA moves into/is already in a ready state
|
||||
*/
|
||||
_setUpListeners : function(){
|
||||
// if the state has changed and the new state is a ready state, fire an event
|
||||
this.on( 'change:state', function( currModel, newState ){
|
||||
this.log( this + ' has changed state:', currModel, newState );
|
||||
if( this.inReadyState() ){
|
||||
this.trigger( 'state:ready', currModel, newState, this.previous( 'state' ) );
|
||||
}
|
||||
});
|
||||
// the download url (currently) relies on having a correct file extension
|
||||
this.on( 'change:id change:file_ext', function( currModel ){
|
||||
this._generateUrls();
|
||||
});
|
||||
},
|
||||
|
||||
// ........................................................................ common queries
|
||||
/** override to add urls */
|
||||
toJSON : function(){
|
||||
var json = Backbone.Model.prototype.toJSON.call( this );
|
||||
//console.warn( 'returning json?' );
|
||||
//return json;
|
||||
return _.extend( json, {
|
||||
urls : this.urls
|
||||
});
|
||||
},
|
||||
|
||||
/** Is this dataset deleted or purged? */
|
||||
isDeletedOrPurged : function(){
|
||||
return ( this.get( 'deleted' ) || this.get( 'purged' ) );
|
||||
},
|
||||
|
||||
/** Is this dataset in a 'ready' state; where 'Ready' states are states where no
|
||||
* processing (for the ds) is left to do on the server.
|
||||
*/
|
||||
inReadyState : function(){
|
||||
var ready = _.contains( STATES.READY_STATES, this.get( 'state' ) );
|
||||
return ( this.isDeletedOrPurged() || ready );
|
||||
},
|
||||
|
||||
/** Does this model already contain detailed data (as opposed to just summary level data)? */
|
||||
hasDetails : function(){
|
||||
//?? this may not be reliable
|
||||
return _.has( this.attributes, 'genome_build' );
|
||||
},
|
||||
|
||||
/** Convenience function to match dataset.has_data. */
|
||||
hasData : function(){
|
||||
return ( this.get( 'file_size' ) > 0 );
|
||||
},
|
||||
|
||||
// ........................................................................ ajax
|
||||
fetch : function( options ){
|
||||
var dataset = this;
|
||||
return Backbone.Model.prototype.fetch.call( this, options )
|
||||
.always( function(){
|
||||
dataset._generateUrls();
|
||||
});
|
||||
},
|
||||
|
||||
//NOTE: subclasses of DA's will need to implement url and urlRoot in order to have these work properly
|
||||
/** save this dataset, _Mark_ing it as deleted (just a flag) */
|
||||
'delete' : function( options ){
|
||||
if( this.get( 'deleted' ) ){ return jQuery.when(); }
|
||||
return this.save( { deleted: true }, options );
|
||||
},
|
||||
/** save this dataset, _Mark_ing it as undeleted */
|
||||
undelete : function( options ){
|
||||
if( !this.get( 'deleted' ) || this.get( 'purged' ) ){ return jQuery.when(); }
|
||||
return this.save( { deleted: false }, options );
|
||||
},
|
||||
|
||||
/** remove the file behind this dataset from the filesystem (if permitted) */
|
||||
purge : function _purge( options ){
|
||||
//TODO: use, override model.destroy, HDA.delete({ purge: true })
|
||||
if( this.get( 'purged' ) ){ return jQuery.when(); }
|
||||
options = options || {};
|
||||
//var hda = this,
|
||||
// //xhr = jQuery.ajax( this.url() + '?' + jQuery.param({ purge: true }), _.extend({
|
||||
// xhr = jQuery.ajax( this.url(), _.extend({
|
||||
// type : 'DELETE',
|
||||
// data : {
|
||||
// purge : true
|
||||
// }
|
||||
// }, options ));
|
||||
//
|
||||
//xhr.done( function( response ){
|
||||
// hda.debug( 'response', response );
|
||||
// //hda.set({ deleted: true, purged: true });
|
||||
// hda.set( response );
|
||||
//});
|
||||
//return xhr;
|
||||
|
||||
options.url = this.urls.purge;
|
||||
|
||||
//TODO: ideally this would be a DELETE call to the api
|
||||
// using purge async for now
|
||||
var hda = this,
|
||||
xhr = jQuery.ajax( options );
|
||||
xhr.done( function( message, status, responseObj ){
|
||||
hda.set({ deleted: true, purged: true });
|
||||
});
|
||||
xhr.fail( function( xhr, status, message ){
|
||||
// Exception messages are hidden within error page including: '...not allowed in this Galaxy instance.'
|
||||
// unbury and re-add to xhr
|
||||
var error = _l( "Unable to purge dataset" );
|
||||
var messageBuriedInUnfortunatelyFormattedError = ( 'Removal of datasets by users '
|
||||
+ 'is not allowed in this Galaxy instance' );
|
||||
if( xhr.responseJSON && xhr.responseJSON.error ){
|
||||
error = xhr.responseJSON.error;
|
||||
} else if( xhr.responseText.indexOf( messageBuriedInUnfortunatelyFormattedError ) !== -1 ){
|
||||
error = messageBuriedInUnfortunatelyFormattedError;
|
||||
}
|
||||
xhr.responseText = error;
|
||||
hda.trigger( 'error', hda, xhr, options, _l( error ), { error: error } );
|
||||
});
|
||||
return xhr;
|
||||
},
|
||||
|
||||
// ........................................................................ searching
|
||||
// see base-mvc, SearchableModelMixin
|
||||
|
||||
/** what attributes of an HDA will be used in a text search */
|
||||
searchAttributes : [
|
||||
'name', 'file_ext', 'genome_build', 'misc_blurb', 'misc_info', 'annotation', 'tags'
|
||||
],
|
||||
|
||||
/** our attr keys don't often match the labels we display to the user - so, when using
|
||||
* attribute specifiers ('name="bler"') in a term, allow passing in aliases for the
|
||||
* following attr keys.
|
||||
*/
|
||||
searchAliases : {
|
||||
title : 'name',
|
||||
format : 'file_ext',
|
||||
database : 'genome_build',
|
||||
blurb : 'misc_blurb',
|
||||
description : 'misc_blurb',
|
||||
info : 'misc_info',
|
||||
tag : 'tags'
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var nameAndId = this.get( 'id' ) || '';
|
||||
if( this.get( 'name' ) ){
|
||||
nameAndId = '"' + this.get( 'name' ) + '",' + nameAndId;
|
||||
}
|
||||
return 'Dataset(' + nameAndId + ')';
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone collection for dataset associations.
|
||||
*/
|
||||
var DatasetAssociationCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
|
||||
/** @lends HistoryContents.prototype */{
|
||||
model : DatasetAssociation,
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** root api url */
|
||||
urlRoot : (( window.galaxy_config && galaxy_config.root )?( galaxy_config.root ):( '/' ))
|
||||
+ 'api/datasets',
|
||||
|
||||
// ........................................................................ common queries
|
||||
/** Get the ids of every item in this collection
|
||||
* @returns array of encoded ids
|
||||
*/
|
||||
ids : function(){
|
||||
return this.map( function( item ){ return item.get('id'); });
|
||||
},
|
||||
|
||||
/** Get contents that are not ready
|
||||
* @returns array of content models
|
||||
*/
|
||||
notReady : function(){
|
||||
return this.filter( function( content ){
|
||||
return !content.inReadyState();
|
||||
});
|
||||
},
|
||||
|
||||
/** return true if any datasets don't have details */
|
||||
haveDetails : function(){
|
||||
return this.all( function( dataset ){ return dataset.hasDetails(); });
|
||||
},
|
||||
|
||||
// ........................................................................ ajax
|
||||
/** using a queue, perform ajaxFn on each of the models in this collection */
|
||||
ajaxQueue : function( ajaxFn, options ){
|
||||
var deferred = jQuery.Deferred(),
|
||||
startingLength = this.length,
|
||||
responses = [];
|
||||
|
||||
if( !startingLength ){
|
||||
deferred.resolve([]);
|
||||
return deferred;
|
||||
}
|
||||
|
||||
// use reverse order (stylistic choice)
|
||||
var ajaxFns = this.chain().reverse().map( function( dataset, i ){
|
||||
return function(){
|
||||
var xhr = ajaxFn.call( dataset, options );
|
||||
// if successful, notify using the deferred to allow tracking progress
|
||||
xhr.done( function( response ){
|
||||
deferred.notify({ curr: i, total: startingLength, response: response, model: dataset });
|
||||
});
|
||||
// (regardless of previous error or success) if not last ajax call, shift and call the next
|
||||
// if last fn, resolve deferred
|
||||
xhr.always( function( response ){
|
||||
responses.push( response );
|
||||
if( ajaxFns.length ){
|
||||
ajaxFns.shift()();
|
||||
} else {
|
||||
deferred.resolve( responses );
|
||||
}
|
||||
});
|
||||
};
|
||||
}).value();
|
||||
// start the queue
|
||||
ajaxFns.shift()();
|
||||
|
||||
return deferred;
|
||||
},
|
||||
|
||||
// ........................................................................ sorting/filtering
|
||||
/** return a new collection of datasets whose attributes contain the substring matchesWhat */
|
||||
matches : function( matchesWhat ){
|
||||
return this.filter( function( dataset ){
|
||||
return dataset.matches( matchesWhat );
|
||||
});
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
///** Convert this ad-hoc collection of hdas to a formal collection tracked
|
||||
// by the server.
|
||||
//**/
|
||||
//promoteToHistoryDatasetCollection : function _promote( history, collection_type, options ){
|
||||
//},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'DatasetAssociationCollection(', this.length, ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
DatasetAssociation : DatasetAssociation,
|
||||
DatasetAssociationCollection : DatasetAssociationCollection
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/states","mvc/base-mvc","utils/localization"],function(a,b,c){var d=b.SearchableModelMixin,e=Backbone.Model.extend(b.LoggableMixin).extend(b.mixin(d,{defaults:{state:a.NEW,deleted:!1,purged:!1,name:"(unnamed dataset)",accessible:!0,data_type:"",file_ext:"",file_size:0,meta_files:[],misc_blurb:"",misc_info:"",tags:[]},initialize:function(b,c){this.debug(this+"(Dataset).initialize",b,c),this.get("accessible")||this.set("state",a.NOT_VIEWABLE),this.urls=this._generateUrls(),this._setUpListeners()},_generateUrls:function(){var a=this.get("id");if(!a)return{};var b={purge:"datasets/"+a+"/purge_async",display:"datasets/"+a+"/display/?preview=True",edit:"datasets/"+a+"/edit",download:"datasets/"+a+"/display?to_ext="+this.get("file_ext"),report_error:"dataset/errors?id="+a,rerun:"tool_runner/rerun?id="+a,show_params:"datasets/"+a+"/show_params",visualization:"visualization",meta_download:"dataset/get_metadata_file?hda_id="+a+"&metadata_name="},c=window.galaxy_config&&galaxy_config.root?galaxy_config.root:"/";return _.each(b,function(a,d){b[d]=c+a}),this.urls=b,b},_setUpListeners:function(){this.on("change:state",function(a,b){this.log(this+" has changed state:",a,b),this.inReadyState()&&this.trigger("state:ready",a,b,this.previous("state"))}),this.on("change:id change:file_ext",function(){this._generateUrls()})},toJSON:function(){var a=Backbone.Model.prototype.toJSON.call(this);return _.extend(a,{urls:this.urls})},isDeletedOrPurged:function(){return this.get("deleted")||this.get("purged")},inReadyState:function(){var b=_.contains(a.READY_STATES,this.get("state"));return this.isDeletedOrPurged()||b},hasDetails:function(){return _.has(this.attributes,"genome_build")},hasData:function(){return this.get("file_size")>0},fetch:function(a){var b=this;return Backbone.Model.prototype.fetch.call(this,a).always(function(){b._generateUrls()})},"delete":function(a){return this.get("deleted")?jQuery.when():this.save({deleted:!0},a)},undelete:function(a){return!this.get("deleted")||this.get("purged")?jQuery.when():this.save({deleted:!1},a)},purge:function(a){if(this.get("purged"))return jQuery.when();a=a||{},a.url=this.urls.purge;var b=this,d=jQuery.ajax(a);return d.done(function(){b.set({deleted:!0,purged:!0})}),d.fail(function(d){var e=c("Unable to purge dataset"),f="Removal of datasets by users is not allowed in this Galaxy instance";d.responseJSON&&d.responseJSON.error?e=d.responseJSON.error:-1!==d.responseText.indexOf(f)&&(e=f),d.responseText=e,b.trigger("error",b,d,a,c(e),{error:e})}),d},searchAttributes:["name","file_ext","genome_build","misc_blurb","misc_info","annotation","tags"],searchAliases:{title:"name",format:"file_ext",database:"genome_build",blurb:"misc_blurb",description:"misc_blurb",info:"misc_info",tag:"tags"},toString:function(){var a=this.get("id")||"";return this.get("name")&&(a='"'+this.get("name")+'",'+a),"Dataset("+a+")"}})),f=Backbone.Collection.extend(b.LoggableMixin).extend({model:e,urlRoot:(window.galaxy_config&&galaxy_config.root?galaxy_config.root:"/")+"api/datasets",ids:function(){return this.map(function(a){return a.get("id")})},notReady:function(){return this.filter(function(a){return!a.inReadyState()})},haveDetails:function(){return this.all(function(a){return a.hasDetails()})},ajaxQueue:function(a,b){var c=jQuery.Deferred(),d=this.length,e=[];if(!d)return c.resolve([]),c;var f=this.chain().reverse().map(function(g,h){return function(){var i=a.call(g,b);i.done(function(a){c.notify({curr:h,total:d,response:a,model:g})}),i.always(function(a){e.push(a),f.length?f.shift()():c.resolve(e)})}}).value();return f.shift()(),c},matches:function(a){return this.filter(function(b){return b.matches(a)})},toString:function(){return["DatasetAssociationCollection(",this.length,")"].join("")}});return{DatasetAssociation:e,DatasetAssociationCollection:f}});
|
||||
//# sourceMappingURL=../../../maps/mvc/dataset/dataset-model.js.map
|
||||
@@ -1,60 +1,2 @@
|
||||
define([
|
||||
], function(){
|
||||
//==============================================================================
|
||||
/** Map of possible HDA/collection/job states to their string equivalents.
|
||||
* A port of galaxy.model.Dataset.states.
|
||||
*/
|
||||
var STATES = {
|
||||
// NOT ready states
|
||||
/** is uploading and not ready */
|
||||
UPLOAD : 'upload',
|
||||
/** the job that will produce the dataset queued in the runner */
|
||||
QUEUED : 'queued',
|
||||
/** the job that will produce the dataset is running */
|
||||
RUNNING : 'running',
|
||||
/** metadata for the dataset is being discovered/set */
|
||||
SETTING_METADATA : 'setting_metadata',
|
||||
|
||||
// ready states
|
||||
/** was created without a tool */
|
||||
NEW : 'new',
|
||||
/** has no data */
|
||||
EMPTY : 'empty',
|
||||
/** has successfully completed running */
|
||||
OK : 'ok',
|
||||
|
||||
/** the job that will produce the dataset paused */
|
||||
PAUSED : 'paused',
|
||||
/** metadata discovery/setting failed or errored (but otherwise ok) */
|
||||
FAILED_METADATA : 'failed_metadata',
|
||||
//TODO: not in trans.app.model.Dataset.states - is in database
|
||||
/** not accessible to the current user (i.e. due to permissions) */
|
||||
NOT_VIEWABLE : 'noPermission',
|
||||
/** deleted while uploading */
|
||||
DISCARDED : 'discarded',
|
||||
/** the tool producing this dataset failed */
|
||||
ERROR : 'error'
|
||||
};
|
||||
|
||||
STATES.READY_STATES = [
|
||||
STATES.OK,
|
||||
STATES.EMPTY,
|
||||
STATES.PAUSED,
|
||||
STATES.FAILED_METADATA,
|
||||
STATES.NOT_VIEWABLE,
|
||||
STATES.DISCARDED,
|
||||
STATES.ERROR
|
||||
];
|
||||
|
||||
STATES.NOT_READY_STATES = [
|
||||
STATES.UPLOAD,
|
||||
STATES.QUEUED,
|
||||
STATES.RUNNING,
|
||||
STATES.SETTING_METADATA,
|
||||
STATES.NEW
|
||||
];
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return STATES;
|
||||
});
|
||||
define([],function(){var a={UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",SETTING_METADATA:"setting_metadata",NEW:"new",EMPTY:"empty",OK:"ok",PAUSED:"paused",FAILED_METADATA:"failed_metadata",NOT_VIEWABLE:"noPermission",DISCARDED:"discarded",ERROR:"error"};return a.READY_STATES=[a.OK,a.EMPTY,a.PAUSED,a.FAILED_METADATA,a.NOT_VIEWABLE,a.DISCARDED,a.ERROR],a.NOT_READY_STATES=[a.UPLOAD,a.QUEUED,a.RUNNING,a.SETTING_METADATA,a.NEW],a});
|
||||
//# sourceMappingURL=../../../maps/mvc/dataset/states.js.map
|
||||
@@ -1,283 +1,2 @@
|
||||
/*
|
||||
This class maps the form dom to an api compatible javascript dictionary.
|
||||
*/
|
||||
define(['utils/utils'], function(Utils) {
|
||||
return Backbone.Model.extend({
|
||||
// initialize
|
||||
initialize: function(app) {
|
||||
this.app = app;
|
||||
},
|
||||
|
||||
/** Creates a checksum.
|
||||
*/
|
||||
checksum: function() {
|
||||
var sum = '';
|
||||
for (var i in this.app.field_list) {
|
||||
var field = this.app.field_list[i];
|
||||
sum += JSON.stringify(field.value && field.value());
|
||||
}
|
||||
return sum;
|
||||
},
|
||||
|
||||
/** Convert dom into dictionary.
|
||||
*/
|
||||
create: function() {
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// get raw dictionary from dom
|
||||
var dict = {};
|
||||
this._iterate(this.app.section.$el, dict);
|
||||
|
||||
// add to result dictionary
|
||||
var result_dict = {};
|
||||
this.map_dict = {};
|
||||
function add(job_input_id, input_id, input_value) {
|
||||
self.map_dict[job_input_id] = input_id;
|
||||
result_dict[job_input_id] = input_value;
|
||||
};
|
||||
|
||||
// converter between raw dictionary and job dictionary
|
||||
function convert(identifier, head) {
|
||||
for (var index in head) {
|
||||
var node = head[index];
|
||||
if (node.input) {
|
||||
// get node
|
||||
var input = node.input;
|
||||
|
||||
// create identifier
|
||||
var job_input_id = identifier;
|
||||
if (identifier != '') {
|
||||
job_input_id += '|';
|
||||
}
|
||||
job_input_id += input.name;
|
||||
|
||||
// process input type
|
||||
switch (input.type) {
|
||||
// handle repeats
|
||||
case 'repeat':
|
||||
// section identifier
|
||||
var section_label = 'section-';
|
||||
|
||||
// collect repeat block identifiers
|
||||
var block_indices = [];
|
||||
var block_prefix = null;
|
||||
for (var block_label in node) {
|
||||
var pos = block_label.indexOf(section_label);
|
||||
if (pos != -1) {
|
||||
pos += section_label.length;
|
||||
block_indices.push(parseInt(block_label.substr(pos)));
|
||||
if (!block_prefix) {
|
||||
block_prefix = block_label.substr(0, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort repeat blocks
|
||||
block_indices.sort(function(a,b) { return a - b; });
|
||||
|
||||
// add to response dictionary in created order
|
||||
var index = 0;
|
||||
for (var i in block_indices) {
|
||||
convert(job_input_id + '_' + index++, node[block_prefix + block_indices[i]]);
|
||||
}
|
||||
break;
|
||||
// handle conditionals
|
||||
case 'conditional':
|
||||
// get conditional value
|
||||
var value = self.app.field_list[input.id].value();
|
||||
|
||||
// add conditional value
|
||||
add (job_input_id + '|' + input.test_param.name, input.id, value);
|
||||
|
||||
// identify selected case
|
||||
var selectedCase = self.matchCase(input, value);
|
||||
if (selectedCase != -1) {
|
||||
convert(job_input_id, head[input.id + '-section-' + selectedCase]);
|
||||
}
|
||||
break;
|
||||
// handle custom sub sections
|
||||
case 'section':
|
||||
convert('', node);
|
||||
break;
|
||||
default:
|
||||
// get field
|
||||
var field = self.app.field_list[input.id];
|
||||
if (field && field.value) {
|
||||
// validate field value
|
||||
var value = field.value();
|
||||
|
||||
// ignore certain values
|
||||
if (input.ignore === undefined || input.ignore != value) {
|
||||
// add value to submission
|
||||
add (job_input_id, input.id, value);
|
||||
|
||||
// add payload to submission
|
||||
if (input.payload) {
|
||||
for (var p_id in input.payload) {
|
||||
add (p_id, input.id, input.payload[p_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start conversion
|
||||
convert('', dict);
|
||||
|
||||
// return result
|
||||
return result_dict;
|
||||
},
|
||||
|
||||
/** Match job definition identifier to input element identifier
|
||||
*/
|
||||
match: function (job_input_id) {
|
||||
return this.map_dict && this.map_dict[job_input_id];
|
||||
},
|
||||
|
||||
/** Match conditional values to selected cases
|
||||
*/
|
||||
matchCase: function(input, value) {
|
||||
// format value for boolean inputs
|
||||
if (input.test_param.type == 'boolean') {
|
||||
if (value == 'true') {
|
||||
value = input.test_param.truevalue || 'true';
|
||||
} else {
|
||||
value = input.test_param.falsevalue || 'false';
|
||||
}
|
||||
}
|
||||
|
||||
// find selected case
|
||||
for (var i in input.cases) {
|
||||
if (input.cases[i].value == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// selected case not found
|
||||
return -1;
|
||||
},
|
||||
|
||||
/** Matches identifier from api model to input elements
|
||||
*/
|
||||
matchModel: function(model, callback) {
|
||||
// final result dictionary
|
||||
var result = {};
|
||||
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// search throughout response
|
||||
function search (id, head) {
|
||||
for (var i in head) {
|
||||
var node = head[i];
|
||||
var index = node.name;
|
||||
if (id != '') {
|
||||
index = id + '|' + index;
|
||||
}
|
||||
switch (node.type) {
|
||||
case 'repeat':
|
||||
for (var j in node.cache) {
|
||||
search (index + '_' + j, node.cache[j]);
|
||||
}
|
||||
break;
|
||||
case 'conditional':
|
||||
var value = node.test_param && node.test_param.value;
|
||||
var selectedCase = self.matchCase(node, value);
|
||||
if (selectedCase != -1) {
|
||||
search (index, node.cases[selectedCase].inputs);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
var input_id = self.map_dict[index];
|
||||
if (input_id) {
|
||||
callback(input_id, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// match all ids and return messages
|
||||
search('', model.inputs);
|
||||
|
||||
// return matched results
|
||||
return result;
|
||||
},
|
||||
|
||||
/** Matches identifier from api response to input elements
|
||||
*/
|
||||
matchResponse: function(response) {
|
||||
// final result dictionary
|
||||
var result = {};
|
||||
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// search throughout response
|
||||
function search (id, head) {
|
||||
if (typeof head === 'string') {
|
||||
var input_id = self.map_dict[id];
|
||||
if (input_id) {
|
||||
result[input_id] = head;
|
||||
}
|
||||
} else {
|
||||
for (var i in head) {
|
||||
var new_id = i;
|
||||
if (id !== '') {
|
||||
var separator = '|';
|
||||
if (head instanceof Array) {
|
||||
separator = '_';
|
||||
}
|
||||
new_id = id + separator + new_id;
|
||||
}
|
||||
search (new_id, head[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// match all ids and return messages
|
||||
search('', response);
|
||||
|
||||
// return matched results
|
||||
return result;
|
||||
},
|
||||
|
||||
/** Iterate through the form dom and map it to the dictionary.
|
||||
*/
|
||||
_iterate: function(parent, dict) {
|
||||
// get child nodes
|
||||
var self = this;
|
||||
var children = $(parent).children();
|
||||
children.each(function() {
|
||||
// get child element
|
||||
var child = this;
|
||||
|
||||
// get id
|
||||
var id = $(child).attr('id');
|
||||
|
||||
// create new branch
|
||||
if ($(child).hasClass('section-row')) {
|
||||
// create sub dictionary
|
||||
dict[id] = {};
|
||||
|
||||
// add input element if it exists
|
||||
var input = self.app.input_list[id];
|
||||
if (input) {
|
||||
dict[id] = {
|
||||
input : input
|
||||
}
|
||||
}
|
||||
|
||||
// fill sub dictionary
|
||||
self._iterate(child, dict[id]);
|
||||
} else {
|
||||
self._iterate(child, dict);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
define(["utils/utils"],function(){return Backbone.Model.extend({initialize:function(a){this.app=a},checksum:function(){var a="";for(var b in this.app.field_list){var c=this.app.field_list[b];a+=JSON.stringify(c.value&&c.value())}return a},create:function(){function a(a,b,d){c.map_dict[a]=b,e[a]=d}function b(d,e){for(var f in e){var g=e[f];if(g.input){var h=g.input,i=d;switch(""!=d&&(i+="|"),i+=h.name,h.type){case"repeat":var j="section-",k=[],l=null;for(var m in g){var n=m.indexOf(j);-1!=n&&(n+=j.length,k.push(parseInt(m.substr(n))),l||(l=m.substr(0,n)))}k.sort(function(a,b){return a-b});var f=0;for(var o in k)b(i+"_"+f++,g[l+k[o]]);break;case"conditional":var p=c.app.field_list[h.id].value();a(i+"|"+h.test_param.name,h.id,p);var q=c.matchCase(h,p);-1!=q&&b(i,e[h.id+"-section-"+q]);break;case"section":b("",g);break;default:var r=c.app.field_list[h.id];if(r&&r.value){var p=r.value();if((void 0===h.ignore||h.ignore!=p)&&(a(i,h.id,p),h.payload))for(var s in h.payload)a(s,h.id,h.payload[s])}}}}}var c=this,d={};this._iterate(this.app.section.$el,d);var e={};return this.map_dict={},b("",d),e},match:function(a){return this.map_dict&&this.map_dict[a]},matchCase:function(a,b){"boolean"==a.test_param.type&&(b="true"==b?a.test_param.truevalue||"true":a.test_param.falsevalue||"false");for(var c in a.cases)if(a.cases[c].value==b)return c;return-1},matchModel:function(a,b){function c(a,d){for(var f in d){var g=d[f],h=g.name;switch(""!=a&&(h=a+"|"+h),g.type){case"repeat":for(var i in g.cache)c(h+"_"+i,g.cache[i]);break;case"conditional":var j=g.test_param&&g.test_param.value,k=e.matchCase(g,j);-1!=k&&c(h,g.cases[k].inputs);break;default:var l=e.map_dict[h];l&&b(l,g)}}}var d={},e=this;return c("",a.inputs),d},matchResponse:function(a){function b(a,e){if("string"==typeof e){var f=d.map_dict[a];f&&(c[f]=e)}else for(var g in e){var h=g;if(""!==a){var i="|";e instanceof Array&&(i="_"),h=a+i+h}b(h,e[g])}}var c={},d=this;return b("",a),c},_iterate:function(a,b){var c=this,d=$(a).children();d.each(function(){var a=this,d=$(a).attr("id");if($(a).hasClass("section-row")){b[d]={};var e=c.app.input_list[d];e&&(b[d]={input:e}),c._iterate(a,b[d])}else c._iterate(a,b)})}})});
|
||||
//# sourceMappingURL=../../../maps/mvc/form/form-data.js.map
|
||||
@@ -1,144 +1,2 @@
|
||||
/**
|
||||
This class creates a form input element wrapper
|
||||
*/
|
||||
define([], function() {
|
||||
return Backbone.View.extend({
|
||||
initialize: function(app, options) {
|
||||
// link app
|
||||
this.app = app;
|
||||
|
||||
// set text labels and icons for optional button
|
||||
this.text_enable = app.options.text_enable || 'Enable';
|
||||
this.text_disable = app.options.text_disable || 'Disable';
|
||||
this.cls_enable = app.options.cls_enable || 'fa fa-plus-square';
|
||||
this.cls_disable = app.options.cls_disable || 'fa fa-minus-square';
|
||||
|
||||
// link field
|
||||
this.field = options.field;
|
||||
this.default_value = options.default_value;
|
||||
|
||||
// set element
|
||||
this.setElement(this._template(options));
|
||||
|
||||
// link elements
|
||||
this.$field = this.$el.find('.ui-table-form-field');
|
||||
this.$optional = this.$el.find('.ui-table-form-optional');
|
||||
this.$optional_icon = this.$el.find('.ui-table-form-optional').find('.icon');
|
||||
this.$error_text = this.$el.find('.ui-table-form-error-text');
|
||||
this.$error = this.$el.find('.ui-table-form-error');
|
||||
|
||||
// add field element
|
||||
this.$field.prepend(this.field.$el);
|
||||
|
||||
// decide wether to expand or collapse optional fields
|
||||
this.field.skip = false;
|
||||
var v = this.field.value && this.field.value();
|
||||
this.field.skip = Boolean(options.optional &&
|
||||
(v === null || v === '' || v === this.default_value ||
|
||||
String(v) === String(this.default_value) ||
|
||||
Number(v) === Number(this.default_value) ||
|
||||
JSON.stringify(v) === JSON.stringify(this.default_value)));
|
||||
|
||||
// refresh view
|
||||
this._refresh();
|
||||
|
||||
// add optional hide/show
|
||||
var self = this;
|
||||
this.$optional.on('click', function() {
|
||||
// flip flag
|
||||
self.field.skip = !self.field.skip;
|
||||
|
||||
// refresh view
|
||||
self._refresh();
|
||||
|
||||
// refresh state
|
||||
self.app.trigger('change');
|
||||
});
|
||||
},
|
||||
|
||||
/** Set error text
|
||||
*/
|
||||
error: function(text) {
|
||||
this.$error_text.html(text);
|
||||
this.$error.show();
|
||||
this.$el.addClass('ui-error');
|
||||
},
|
||||
|
||||
/** Reset this view
|
||||
*/
|
||||
reset: function() {
|
||||
this.$error.hide();
|
||||
this.$el.removeClass('ui-error');
|
||||
},
|
||||
|
||||
/** Refresh element
|
||||
*/
|
||||
_refresh: function() {
|
||||
// reset optional button
|
||||
this.$optional_icon.removeClass().addClass('icon');
|
||||
|
||||
// identify state
|
||||
if (!this.field.skip) {
|
||||
// enable input field
|
||||
this.$field.fadeIn('fast');
|
||||
this._tooltip(this.text_disable, this.cls_disable);
|
||||
|
||||
} else {
|
||||
// disable input field
|
||||
this.$field.hide();
|
||||
this._tooltip(this.text_enable, this.cls_enable);
|
||||
// reset field value
|
||||
this.field.value && this.field.value(this.default_value);
|
||||
}
|
||||
},
|
||||
|
||||
/** Set tooltip text
|
||||
*/
|
||||
_tooltip: function(title, cls) {
|
||||
if (this.$optional.length) {
|
||||
this.$optional_icon.addClass(cls)
|
||||
.tooltip({ placement: 'bottom' })
|
||||
.attr('data-original-title', title)
|
||||
.tooltip('fixTitle').tooltip('hide');
|
||||
}
|
||||
},
|
||||
|
||||
/** Main Template
|
||||
*/
|
||||
_template: function(options) {
|
||||
// create table element
|
||||
var tmp = '<div class="ui-table-form-element">' +
|
||||
'<div class="ui-table-form-error ui-error">' +
|
||||
'<span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/>' +
|
||||
'</div>' +
|
||||
'<div class="ui-table-form-title">';
|
||||
|
||||
// is optional
|
||||
if (options.optional) {
|
||||
tmp += '<div class="ui-table-form-optional">' +
|
||||
'<i class="icon"/>' + options.label +
|
||||
'</div>';
|
||||
} else {
|
||||
tmp += options.label;
|
||||
}
|
||||
|
||||
// finalize title
|
||||
tmp += '</div>' +
|
||||
'<div class="ui-table-form-field">';
|
||||
|
||||
// add help
|
||||
tmp += '<div class="ui-table-form-info">';
|
||||
if (options.help) {
|
||||
tmp += options.help;
|
||||
}
|
||||
tmp += '</div>';
|
||||
|
||||
// finalize
|
||||
tmp += '</div>' +
|
||||
'</div>';
|
||||
|
||||
// return input element
|
||||
return tmp;
|
||||
}
|
||||
});
|
||||
});
|
||||
define([],function(){return Backbone.View.extend({initialize:function(a,b){this.app=a,this.text_enable=a.options.text_enable||"Enable",this.text_disable=a.options.text_disable||"Disable",this.cls_enable=a.options.cls_enable||"fa fa-plus-square",this.cls_disable=a.options.cls_disable||"fa fa-minus-square",this.field=b.field,this.default_value=b.default_value,this.setElement(this._template(b)),this.$field=this.$el.find(".ui-table-form-field"),this.$optional=this.$el.find(".ui-table-form-optional"),this.$optional_icon=this.$el.find(".ui-table-form-optional").find(".icon"),this.$error_text=this.$el.find(".ui-table-form-error-text"),this.$error=this.$el.find(".ui-table-form-error"),this.$field.prepend(this.field.$el),this.field.skip=!1;var c=this.field.value&&this.field.value();this.field.skip=Boolean(b.optional&&(null===c||""===c||c===this.default_value||String(c)===String(this.default_value)||Number(c)===Number(this.default_value)||JSON.stringify(c)===JSON.stringify(this.default_value))),this._refresh();var d=this;this.$optional.on("click",function(){d.field.skip=!d.field.skip,d._refresh(),d.app.trigger("change")})},error:function(a){this.$error_text.html(a),this.$error.show(),this.$el.addClass("ui-error")},reset:function(){this.$error.hide(),this.$el.removeClass("ui-error")},_refresh:function(){this.$optional_icon.removeClass().addClass("icon"),this.field.skip?(this.$field.hide(),this._tooltip(this.text_enable,this.cls_enable),this.field.value&&this.field.value(this.default_value)):(this.$field.fadeIn("fast"),this._tooltip(this.text_disable,this.cls_disable))},_tooltip:function(a,b){this.$optional.length&&this.$optional_icon.addClass(b).tooltip({placement:"bottom"}).attr("data-original-title",a).tooltip("fixTitle").tooltip("hide")},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title">';return b+=a.optional?'<div class="ui-table-form-optional"><i class="icon"/>'+a.label+"</div>":a.label,b+='</div><div class="ui-table-form-field">',b+='<div class="ui-table-form-info">',a.help&&(b+=a.help),b+="</div>",b+="</div></div>"}})});
|
||||
//# sourceMappingURL=../../../maps/mvc/form/form-input.js.map
|
||||
@@ -1,263 +1,2 @@
|
||||
/**
|
||||
This class creates input elements. New input parameter types should be added to the types dictionary.
|
||||
*/
|
||||
define(['utils/utils',
|
||||
'mvc/ui/ui-misc',
|
||||
'mvc/form/form-select-content',
|
||||
'mvc/ui/ui-color-picker'],
|
||||
function(Utils, Ui, SelectContent, ColorPicker) {
|
||||
|
||||
// create form view
|
||||
return Backbone.Model.extend({
|
||||
/** Available parameter types */
|
||||
types: {
|
||||
'text' : '_fieldText',
|
||||
'select' : '_fieldSelect',
|
||||
'data_column' : '_fieldSelect',
|
||||
'genomebuild' : '_fieldSelect',
|
||||
'data' : '_fieldData',
|
||||
'data_collection' : '_fieldData',
|
||||
'integer' : '_fieldSlider',
|
||||
'float' : '_fieldSlider',
|
||||
'boolean' : '_fieldBoolean',
|
||||
'drill_down' : '_fieldDrilldown',
|
||||
'color' : '_fieldColor',
|
||||
'hidden' : '_fieldHidden',
|
||||
'hidden_data' : '_fieldHidden',
|
||||
'baseurl' : '_fieldHidden'
|
||||
},
|
||||
|
||||
// initialize
|
||||
initialize: function(app, options) {
|
||||
this.app = app;
|
||||
},
|
||||
|
||||
/** Returns an input field for a given field type
|
||||
*/
|
||||
create: function(input_def) {
|
||||
// add regular/default value if missing
|
||||
if (input_def.value === undefined) {
|
||||
input_def.value = null;
|
||||
}
|
||||
if (input_def.default_value === undefined) {
|
||||
input_def.default_value = input_def.value;
|
||||
}
|
||||
|
||||
// field wrapper
|
||||
var field = null;
|
||||
|
||||
// get field class
|
||||
var fieldClass = this.types[input_def.type];
|
||||
if (fieldClass && typeof(this[fieldClass]) === 'function') {
|
||||
field = this[fieldClass].call(this, input_def);
|
||||
}
|
||||
|
||||
// identify field type
|
||||
if (!field) {
|
||||
// flag
|
||||
this.app.incompatible = true;
|
||||
|
||||
// with or without options
|
||||
if (input_def.options) {
|
||||
// assign select field
|
||||
field = this._fieldSelect(input_def);
|
||||
} else {
|
||||
// assign text field
|
||||
field = this._fieldText(input_def);
|
||||
}
|
||||
|
||||
// log
|
||||
console.debug('tools-form::_addRow() : Auto matched field type (' + input_def.type + ').');
|
||||
}
|
||||
|
||||
// set field value
|
||||
if (input_def.value !== undefined) {
|
||||
field.value(input_def.value);
|
||||
}
|
||||
|
||||
// return field element
|
||||
return field;
|
||||
},
|
||||
|
||||
/** Data input field
|
||||
*/
|
||||
_fieldData: function(input_def) {
|
||||
if (!this.app.options.is_dynamic) {
|
||||
input_def.info = 'Data input \'' + input_def.name + '\' (' + Utils.textify(input_def.extensions.toString()) + ')';
|
||||
input_def.value = null;
|
||||
return this._fieldHidden(input_def);
|
||||
}
|
||||
var self = this;
|
||||
return new SelectContent.View(this.app, {
|
||||
id : 'field-' + input_def.id,
|
||||
extensions : input_def.extensions,
|
||||
optional : input_def.optional,
|
||||
multiple : input_def.multiple,
|
||||
type : input_def.type,
|
||||
data : input_def.options,
|
||||
onchange : function() {
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Select/Checkbox/Radio options field
|
||||
*/
|
||||
_fieldSelect: function (input_def) {
|
||||
// show text field in if dynamic fields are disabled e.g. in workflow editor
|
||||
if (!this.app.options.is_dynamic && input_def.is_dynamic) {
|
||||
return this._fieldText(input_def);
|
||||
}
|
||||
|
||||
// customize properties
|
||||
if (input_def.type == 'data_column') {
|
||||
input_def.error_text = 'Missing columns in referenced dataset.'
|
||||
}
|
||||
if (input_def.type == 'genomebuild') {
|
||||
input_def.searchable = true;
|
||||
}
|
||||
|
||||
// configure options fields
|
||||
var options = [];
|
||||
for (var i in input_def.options) {
|
||||
var option = input_def.options[i];
|
||||
options.push({
|
||||
label: option[0],
|
||||
value: option[1]
|
||||
});
|
||||
}
|
||||
|
||||
// identify display type
|
||||
var SelectClass = Ui.Select;
|
||||
switch (input_def.display) {
|
||||
case 'checkboxes':
|
||||
SelectClass = Ui.Checkbox;
|
||||
break;
|
||||
case 'radio':
|
||||
SelectClass = Ui.Radio;
|
||||
break;
|
||||
}
|
||||
|
||||
// select field
|
||||
var self = this;
|
||||
return new SelectClass.View({
|
||||
id : 'field-' + input_def.id,
|
||||
data : options,
|
||||
error_text : input_def.error_text || 'No options available',
|
||||
multiple : input_def.multiple,
|
||||
searchable : input_def.searchable,
|
||||
onchange : function() {
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Drill down options field
|
||||
*/
|
||||
_fieldDrilldown: function (input_def) {
|
||||
// show text field in if dynamic fields are disabled e.g. in workflow editor
|
||||
if (!this.app.options.is_dynamic && input_def.is_dynamic) {
|
||||
return this._fieldText(input_def);
|
||||
}
|
||||
|
||||
// create drill down field
|
||||
var self = this;
|
||||
return new Ui.Drilldown.View({
|
||||
id : 'field-' + input_def.id,
|
||||
data : input_def.options,
|
||||
display : input_def.display,
|
||||
onchange : function() {
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Text input field
|
||||
*/
|
||||
_fieldText: function(input_def) {
|
||||
// field replaces e.g. a select field
|
||||
if (input_def.options) {
|
||||
// show text area if selecting multiple entries is allowed
|
||||
input_def.area = input_def.multiple;
|
||||
|
||||
// validate value
|
||||
if (!Utils.validate(input_def.value)) {
|
||||
input_def.value = '';
|
||||
} else {
|
||||
if (input_def.value instanceof Array) {
|
||||
input_def.value = value.toString();
|
||||
} else {
|
||||
input_def.value = String(input_def.value).replace(/[\[\]'"\s]/g, '');
|
||||
if (input_def.multiple) {
|
||||
input_def.value = input_def.value.replace(/,/g, '\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create input element
|
||||
var self = this;
|
||||
return new Ui.Input({
|
||||
id : 'field-' + input_def.id,
|
||||
area : input_def.area,
|
||||
onchange : function() {
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Slider field
|
||||
*/
|
||||
_fieldSlider: function(input_def) {
|
||||
var self = this;
|
||||
return new Ui.Slider.View({
|
||||
id : 'field-' + input_def.id,
|
||||
precise : input_def.type == 'float',
|
||||
min : input_def.min,
|
||||
max : input_def.max,
|
||||
onchange : function() {
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Hidden field
|
||||
*/
|
||||
_fieldHidden: function(input_def) {
|
||||
return new Ui.Hidden({
|
||||
id : 'field-' + input_def.id,
|
||||
info : input_def.info
|
||||
});
|
||||
},
|
||||
|
||||
/** Boolean field
|
||||
*/
|
||||
_fieldBoolean: function(input_def) {
|
||||
var self = this;
|
||||
return new Ui.RadioButton.View({
|
||||
id : 'field-' + input_def.id,
|
||||
data : [ { label : 'Yes', value : 'true' },
|
||||
{ label : 'No', value : 'false' }],
|
||||
onchange : function() {
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Color picker field
|
||||
*/
|
||||
_fieldColor: function(input_def) {
|
||||
var self = this;
|
||||
return new ColorPicker({
|
||||
id : 'field-' + input_def.id,
|
||||
onchange : function() {
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
View: View
|
||||
};
|
||||
});
|
||||
define(["utils/utils","mvc/ui/ui-misc","mvc/form/form-select-content","mvc/ui/ui-color-picker"],function(a,b,c,d){return Backbone.Model.extend({types:{text:"_fieldText",select:"_fieldSelect",data_column:"_fieldSelect",genomebuild:"_fieldSelect",data:"_fieldData",data_collection:"_fieldData",integer:"_fieldSlider","float":"_fieldSlider","boolean":"_fieldBoolean",drill_down:"_fieldDrilldown",color:"_fieldColor",hidden:"_fieldHidden",hidden_data:"_fieldHidden",baseurl:"_fieldHidden"},initialize:function(a){this.app=a},create:function(a){void 0===a.value&&(a.value=null),void 0===a.default_value&&(a.default_value=a.value);var b=null,c=this.types[a.type];return c&&"function"==typeof this[c]&&(b=this[c].call(this,a)),b||(this.app.incompatible=!0,b=a.options?this._fieldSelect(a):this._fieldText(a)),void 0!==a.value&&b.value(a.value),b},_fieldData:function(b){if(!this.app.options.is_dynamic)return b.info="Data input '"+b.name+"' ("+a.textify(b.extensions.toString())+")",b.value=null,this._fieldHidden(b);var d=this;return new c.View(this.app,{id:"field-"+b.id,extensions:b.extensions,optional:b.optional,multiple:b.multiple,type:b.type,data:b.options,onchange:function(){d.app.trigger("change")}})},_fieldSelect:function(a){if(!this.app.options.is_dynamic&&a.is_dynamic)return this._fieldText(a);"data_column"==a.type&&(a.error_text="Missing columns in referenced dataset."),"genomebuild"==a.type&&(a.searchable=!0);var c=[];for(var d in a.options){var e=a.options[d];c.push({label:e[0],value:e[1]})}var f=b.Select;switch(a.display){case"checkboxes":f=b.Checkbox;break;case"radio":f=b.Radio}var g=this;return new f.View({id:"field-"+a.id,data:c,error_text:a.error_text||"No options available",multiple:a.multiple,searchable:a.searchable,onchange:function(){g.app.trigger("change")}})},_fieldDrilldown:function(a){if(!this.app.options.is_dynamic&&a.is_dynamic)return this._fieldText(a);var c=this;return new b.Drilldown.View({id:"field-"+a.id,data:a.options,display:a.display,onchange:function(){c.app.trigger("change")}})},_fieldText:function(c){c.options&&(c.area=c.multiple,a.validate(c.value)?c.value instanceof Array?c.value=value.toString():(c.value=String(c.value).replace(/[\[\]'"\s]/g,""),c.multiple&&(c.value=c.value.replace(/,/g,"\n"))):c.value="");var d=this;return new b.Input({id:"field-"+c.id,area:c.area,onchange:function(){d.app.trigger("change")}})},_fieldSlider:function(a){var c=this;return new b.Slider.View({id:"field-"+a.id,precise:"float"==a.type,min:a.min,max:a.max,onchange:function(){c.app.trigger("change")}})},_fieldHidden:function(a){return new b.Hidden({id:"field-"+a.id,info:a.info})},_fieldBoolean:function(a){var c=this;return new b.RadioButton.View({id:"field-"+a.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:function(){c.app.trigger("change")}})},_fieldColor:function(a){var b=this;return new d({id:"field-"+a.id,onchange:function(){b.app.trigger("change")}})}})});
|
||||
//# sourceMappingURL=../../../maps/mvc/form/form-parameters.js.map
|
||||
@@ -1,167 +1,2 @@
|
||||
// dependencies
|
||||
define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc'],
|
||||
function(Utils, Table, Portlet, Ui) {
|
||||
|
||||
/** This class creates a ui component which enables the dynamic creation of portlets
|
||||
*/
|
||||
var View = Backbone.View.extend({
|
||||
// default options
|
||||
optionsDefault : {
|
||||
title : 'Section',
|
||||
max : null,
|
||||
min : null
|
||||
},
|
||||
|
||||
/** Initialize
|
||||
*/
|
||||
initialize : function(options) {
|
||||
// configure options
|
||||
this.options = Utils.merge(options, this.optionsDefault);
|
||||
|
||||
// create new element
|
||||
this.setElement('<div/>');
|
||||
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// create button
|
||||
this.button_new = new Ui.ButtonIcon({
|
||||
icon : 'fa-plus',
|
||||
title : 'Insert ' + options.title_new,
|
||||
tooltip : 'Add new ' + options.title_new + ' block',
|
||||
floating: 'clear',
|
||||
onclick : function() {
|
||||
if (options.onnew) {
|
||||
options.onnew();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// create table
|
||||
this.table = new Table.View({
|
||||
cls : 'ui-table-plain',
|
||||
content : ''
|
||||
});
|
||||
|
||||
// append button
|
||||
this.$el.append(this.table.$el);
|
||||
|
||||
// add button
|
||||
this.$el.append($('<div/>').append(this.button_new.$el));
|
||||
|
||||
// clear list
|
||||
this.list = {};
|
||||
|
||||
// number of available repeats
|
||||
this.n = 0;
|
||||
},
|
||||
|
||||
/** Number of repeat blocks
|
||||
*/
|
||||
size: function() {
|
||||
return this.n;
|
||||
},
|
||||
|
||||
/** Add new repeat block
|
||||
*/
|
||||
add: function(options) {
|
||||
// repeat block already exists
|
||||
if (!options.id || this.list[options.id]) {
|
||||
console.debug('form-repeat::add - Duplicate repeat block id.');
|
||||
return;
|
||||
}
|
||||
|
||||
// increase repeat block counter
|
||||
this.n++;
|
||||
|
||||
// delete button
|
||||
var button_delete = new Ui.ButtonIcon({
|
||||
icon : 'fa-trash-o',
|
||||
tooltip : 'Delete this repeat block',
|
||||
cls : 'ui-button-icon-plain',
|
||||
onclick : function() {
|
||||
if (options.ondel) {
|
||||
options.ondel();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// create portlet
|
||||
var portlet = new Portlet.View({
|
||||
id : options.id,
|
||||
title : 'placeholder',
|
||||
cls : 'ui-portlet-repeat',
|
||||
operations : {
|
||||
button_delete : button_delete
|
||||
}
|
||||
});
|
||||
|
||||
// append content
|
||||
portlet.append(options.$el);
|
||||
|
||||
// tag as section row
|
||||
portlet.$el.addClass('section-row');
|
||||
|
||||
// append to dom
|
||||
this.list[options.id] = portlet;
|
||||
|
||||
// append to dom
|
||||
this.table.add(portlet.$el);
|
||||
this.table.append('row_' + options.id, true);
|
||||
|
||||
// validate maximum
|
||||
if (this.options.max > 0 && this.n >= this.options.max) {
|
||||
this.button_new.disable();
|
||||
}
|
||||
|
||||
// refresh view
|
||||
this._refresh();
|
||||
},
|
||||
|
||||
/** Delete repeat block
|
||||
*/
|
||||
del: function(id) {
|
||||
// could not find element
|
||||
if (!this.list[id]) {
|
||||
console.debug('form-repeat::del - Invalid repeat block id.');
|
||||
return;
|
||||
}
|
||||
|
||||
// decrease repeat block counter
|
||||
this.n--;
|
||||
|
||||
// delete table row
|
||||
var table_row = this.table.get('row_' + id);
|
||||
table_row.remove();
|
||||
|
||||
// remove from list
|
||||
delete this.list[id];
|
||||
|
||||
// enable new button
|
||||
this.button_new.enable();
|
||||
|
||||
// refresh delete button visibility
|
||||
this._refresh();
|
||||
},
|
||||
|
||||
/** Refresh view
|
||||
*/
|
||||
_refresh: function() {
|
||||
var index = 0;
|
||||
for (var id in this.list) {
|
||||
var portlet = this.list[id];
|
||||
portlet.title(++index + ': ' + this.options.title);
|
||||
if (this.n > this.options.min) {
|
||||
portlet.showOperation('button_delete');
|
||||
} else {
|
||||
portlet.hideOperation('button_delete');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
View : View
|
||||
}
|
||||
|
||||
});
|
||||
define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-portlet","mvc/ui/ui-misc"],function(a,b,c,d){var e=Backbone.View.extend({optionsDefault:{title:"Section",max:null,min:null},initialize:function(c){this.options=a.merge(c,this.optionsDefault),this.setElement("<div/>");this.button_new=new d.ButtonIcon({icon:"fa-plus",title:"Insert "+c.title_new,tooltip:"Add new "+c.title_new+" block",floating:"clear",onclick:function(){c.onnew&&c.onnew()}}),this.table=new b.View({cls:"ui-table-plain",content:""}),this.$el.append(this.table.$el),this.$el.append($("<div/>").append(this.button_new.$el)),this.list={},this.n=0},size:function(){return this.n},add:function(a){if(a.id&&!this.list[a.id]){this.n++;var b=new d.ButtonIcon({icon:"fa-trash-o",tooltip:"Delete this repeat block",cls:"ui-button-icon-plain",onclick:function(){a.ondel&&a.ondel()}}),e=new c.View({id:a.id,title:"placeholder",cls:"ui-portlet-repeat",operations:{button_delete:b}});e.append(a.$el),e.$el.addClass("section-row"),this.list[a.id]=e,this.table.add(e.$el),this.table.append("row_"+a.id,!0),this.options.max>0&&this.n>=this.options.max&&this.button_new.disable(),this._refresh()}},del:function(a){if(this.list[a]){this.n--;var b=this.table.get("row_"+a);b.remove(),delete this.list[a],this.button_new.enable(),this._refresh()}},_refresh:function(){var a=0;for(var b in this.list){var c=this.list[b];c.title(++a+": "+this.options.title),this.n>this.options.min?c.showOperation("button_delete"):c.hideOperation("button_delete")}}});return{View:e}});
|
||||
//# sourceMappingURL=../../../maps/mvc/form/form-repeat.js.map
|
||||
@@ -1,343 +1,2 @@
|
||||
/**
|
||||
This class creates a form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections.
|
||||
*/
|
||||
define(['utils/utils',
|
||||
'mvc/ui/ui-table',
|
||||
'mvc/ui/ui-misc',
|
||||
'mvc/ui/ui-portlet',
|
||||
'mvc/form/form-repeat',
|
||||
'mvc/form/form-input',
|
||||
'mvc/form/form-parameters'],
|
||||
function(Utils, Table, Ui, Portlet, Repeat, InputElement, Parameters) {
|
||||
|
||||
// create form view
|
||||
var View = Backbone.View.extend({
|
||||
// initialize
|
||||
initialize: function(app, options) {
|
||||
// link app
|
||||
this.app = app;
|
||||
|
||||
// link inputs
|
||||
this.inputs = options.inputs;
|
||||
|
||||
// fix table style
|
||||
options.cls = 'ui-table-plain';
|
||||
|
||||
// add table class for tr tag
|
||||
// this assist in transforming the form into a json structure
|
||||
options.cls_tr = 'section-row';
|
||||
|
||||
// create table
|
||||
this.table = new Table.View(options);
|
||||
|
||||
// create parameter handler
|
||||
this.parameters = new Parameters(app, options);
|
||||
|
||||
// configure portlet and form table
|
||||
this.setElement(this.table.$el);
|
||||
|
||||
// render section
|
||||
this.render();
|
||||
},
|
||||
|
||||
/** Render section view
|
||||
*/
|
||||
render: function() {
|
||||
// reset table
|
||||
this.table.delAll();
|
||||
|
||||
// load settings elements into table
|
||||
for (var i in this.inputs) {
|
||||
this.add(this.inputs[i]);
|
||||
}
|
||||
},
|
||||
|
||||
/** Add a new input element
|
||||
*/
|
||||
add: function(input) {
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// clone definition
|
||||
var input_def = jQuery.extend(true, {}, input);
|
||||
|
||||
// create unique id
|
||||
input_def.id = input.id = Utils.uid();
|
||||
|
||||
// add to sequential list of inputs
|
||||
this.app.input_list[input_def.id] = input_def;
|
||||
|
||||
// identify field type
|
||||
var type = input_def.type;
|
||||
switch(type) {
|
||||
// conditional field
|
||||
case 'conditional':
|
||||
this._addConditional(input_def);
|
||||
break;
|
||||
// repeat block
|
||||
case 'repeat':
|
||||
this._addRepeat(input_def);
|
||||
break;
|
||||
// customized section
|
||||
case 'section':
|
||||
this._addSection(input_def);
|
||||
break;
|
||||
// default single element row
|
||||
default:
|
||||
this._addRow(input_def);
|
||||
}
|
||||
},
|
||||
|
||||
/** Add a conditional block
|
||||
*/
|
||||
_addConditional: function(input_def) {
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// copy identifier
|
||||
input_def.test_param.id = input_def.id;
|
||||
|
||||
// build test parameter
|
||||
var field = this._addRow(input_def.test_param);
|
||||
|
||||
// set onchange event for test parameter
|
||||
field.options.onchange = function(value) {
|
||||
// identify the selected case
|
||||
var selectedCase = self.app.data.matchCase(input_def, value);
|
||||
|
||||
// check value in order to hide/show options
|
||||
for (var i in input_def.cases) {
|
||||
// get case
|
||||
var case_def = input_def.cases[i];
|
||||
|
||||
// identify subsection name
|
||||
var section_id = input_def.id + '-section-' + i;
|
||||
|
||||
// identify row
|
||||
var section_row = self.table.get(section_id);
|
||||
|
||||
// check if non-hidden elements exist
|
||||
var nonhidden = false;
|
||||
for (var j in case_def.inputs) {
|
||||
if (!case_def.inputs[j].hidden) {
|
||||
nonhidden = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// show/hide sub form
|
||||
if (i == selectedCase && nonhidden) {
|
||||
section_row.fadeIn('fast');
|
||||
} else {
|
||||
section_row.hide();
|
||||
}
|
||||
}
|
||||
|
||||
// refresh form inputs
|
||||
self.app.trigger('change');
|
||||
};
|
||||
|
||||
// add conditional sub sections
|
||||
for (var i in input_def.cases) {
|
||||
// create id tag
|
||||
var sub_section_id = input_def.id + '-section-' + i;
|
||||
|
||||
// create sub section
|
||||
var sub_section = new View(this.app, {
|
||||
inputs : input_def.cases[i].inputs
|
||||
});
|
||||
|
||||
// displays as grouped subsection
|
||||
sub_section.$el.addClass('ui-table-section');
|
||||
|
||||
// create table row
|
||||
this.table.add(sub_section.$el);
|
||||
|
||||
// append to table
|
||||
this.table.append(sub_section_id);
|
||||
}
|
||||
|
||||
// trigger refresh on conditional input field after all input elements have been created
|
||||
field.trigger('change');
|
||||
},
|
||||
|
||||
/** Add a repeat block
|
||||
*/
|
||||
_addRepeat: function(input_def) {
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// block index
|
||||
var block_index = 0;
|
||||
|
||||
// create repeat block element
|
||||
var repeat = new Repeat.View({
|
||||
title : input_def.title,
|
||||
title_new : input_def.title,
|
||||
min : input_def.min,
|
||||
max : input_def.max,
|
||||
onnew : function() {
|
||||
// create
|
||||
create(input_def.inputs);
|
||||
|
||||
// trigger refresh
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
|
||||
// helper function to create new repeat blocks
|
||||
function create (inputs) {
|
||||
// create id tag
|
||||
var sub_section_id = input_def.id + '-section-' + (block_index++);
|
||||
|
||||
// create sub section
|
||||
var sub_section = new View(self.app, {
|
||||
inputs : inputs
|
||||
});
|
||||
|
||||
// add tab
|
||||
repeat.add({
|
||||
id : sub_section_id,
|
||||
$el : sub_section.$el,
|
||||
ondel : function() {
|
||||
// delete repeat block
|
||||
repeat.del(sub_section_id);
|
||||
|
||||
// trigger refresh
|
||||
self.app.trigger('change');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// add parsed/minimum number of repeat blocks
|
||||
//
|
||||
var n_min = input_def.min;
|
||||
var n_cache = _.size(input_def.cache);
|
||||
for (var i = 0; i < Math.max(n_cache, n_min); i++) {
|
||||
var inputs = null;
|
||||
if (i < n_cache) {
|
||||
inputs = input_def.cache[i];
|
||||
} else {
|
||||
inputs = input_def.inputs;
|
||||
}
|
||||
|
||||
// create repeat block
|
||||
create(inputs);
|
||||
}
|
||||
|
||||
// create input field wrapper
|
||||
var input_element = new InputElement(this.app, {
|
||||
label : input_def.title,
|
||||
help : input_def.help,
|
||||
field : repeat
|
||||
});
|
||||
|
||||
// create table row
|
||||
this.table.add(input_element.$el);
|
||||
|
||||
// append row to table
|
||||
this.table.append(input_def.id);
|
||||
},
|
||||
|
||||
/** Add a customized section
|
||||
*/
|
||||
_addSection: function(input_def) {
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// create sub section
|
||||
var sub_section = new View(self.app, {
|
||||
inputs : input_def.inputs
|
||||
});
|
||||
|
||||
// delete button
|
||||
var button_visible = new Ui.ButtonIcon({
|
||||
icon : 'fa-eye-slash',
|
||||
tooltip : 'Show/hide section',
|
||||
cls : 'ui-button-icon-plain'
|
||||
});
|
||||
|
||||
// create portlet for sub section
|
||||
var portlet = new Portlet.View({
|
||||
title : input_def.label,
|
||||
cls : 'ui-portlet-section',
|
||||
operations : {
|
||||
button_visible: button_visible
|
||||
}
|
||||
});
|
||||
portlet.append(sub_section.$el);
|
||||
portlet.append($('<div/>').addClass('ui-table-form-info').html(input_def.help));
|
||||
|
||||
// add event handler visibility button
|
||||
var visible = false;
|
||||
portlet.$content.hide();
|
||||
portlet.$header.css('cursor', 'pointer');
|
||||
portlet.$header.on('click', function() {
|
||||
if (visible) {
|
||||
visible = false;
|
||||
portlet.$content.hide();
|
||||
button_visible.setIcon('fa-eye-slash');
|
||||
} else {
|
||||
visible = true;
|
||||
portlet.$content.fadeIn('fast');
|
||||
button_visible.setIcon('fa-eye');
|
||||
}
|
||||
});
|
||||
|
||||
// show sub section if requested
|
||||
if (input_def.expand) {
|
||||
portlet.$header.trigger('click');
|
||||
}
|
||||
|
||||
// create table row
|
||||
this.table.add(portlet.$el);
|
||||
|
||||
// append row to table
|
||||
this.table.append(input_def.id);
|
||||
},
|
||||
|
||||
/** Add a single input field element
|
||||
*/
|
||||
_addRow: function(input_def) {
|
||||
// get id
|
||||
var id = input_def.id;
|
||||
|
||||
// create input field
|
||||
var field = this.parameters.create(input_def);
|
||||
|
||||
// add to field list
|
||||
this.app.field_list[id] = field;
|
||||
|
||||
// create input field wrapper
|
||||
var input_element = new InputElement(this.app, {
|
||||
label : input_def.label,
|
||||
default_value : input_def.default_value,
|
||||
optional : input_def.optional,
|
||||
help : input_def.help,
|
||||
field : field
|
||||
});
|
||||
|
||||
// add to element list
|
||||
this.app.element_list[id] = input_element;
|
||||
|
||||
// create table row
|
||||
this.table.add(input_element.$el);
|
||||
|
||||
// append to table
|
||||
this.table.append(id);
|
||||
|
||||
// hide row if neccessary
|
||||
if (input_def.hidden) {
|
||||
this.table.get(id).hide();
|
||||
}
|
||||
|
||||
// return created field
|
||||
return field;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
View: View
|
||||
};
|
||||
});
|
||||
define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/ui/ui-portlet","mvc/form/form-repeat","mvc/form/form-input","mvc/form/form-parameters"],function(a,b,c,d,e,f,g){var h=Backbone.View.extend({initialize:function(a,c){this.app=a,this.inputs=c.inputs,c.cls="ui-table-plain",c.cls_tr="section-row",this.table=new b.View(c),this.parameters=new g(a,c),this.setElement(this.table.$el),this.render()},render:function(){this.table.delAll();for(var a in this.inputs)this.add(this.inputs[a])},add:function(b){var c=jQuery.extend(!0,{},b);c.id=b.id=a.uid(),this.app.input_list[c.id]=c;var d=c.type;switch(d){case"conditional":this._addConditional(c);break;case"repeat":this._addRepeat(c);break;case"section":this._addSection(c);break;default:this._addRow(c)}},_addConditional:function(a){var b=this;a.test_param.id=a.id;var c=this._addRow(a.test_param);c.options.onchange=function(c){var d=b.app.data.matchCase(a,c);for(var e in a.cases){var f=a.cases[e],g=a.id+"-section-"+e,h=b.table.get(g),i=!1;for(var j in f.inputs)if(!f.inputs[j].hidden){i=!0;break}e==d&&i?h.fadeIn("fast"):h.hide()}b.app.trigger("change")};for(var d in a.cases){var e=a.id+"-section-"+d,f=new h(this.app,{inputs:a.cases[d].inputs});f.$el.addClass("ui-table-section"),this.table.add(f.$el),this.table.append(e)}c.trigger("change")},_addRepeat:function(a){function b(b){var e=a.id+"-section-"+d++,f=new h(c.app,{inputs:b});g.add({id:e,$el:f.$el,ondel:function(){g.del(e),c.app.trigger("change")}})}for(var c=this,d=0,g=new e.View({title:a.title,title_new:a.title,min:a.min,max:a.max,onnew:function(){b(a.inputs),c.app.trigger("change")}}),i=a.min,j=_.size(a.cache),k=0;k<Math.max(j,i);k++){var l=null;l=j>k?a.cache[k]:a.inputs,b(l)}var m=new f(this.app,{label:a.title,help:a.help,field:g});this.table.add(m.$el),this.table.append(a.id)},_addSection:function(a){var b=this,e=new h(b.app,{inputs:a.inputs}),f=new c.ButtonIcon({icon:"fa-eye-slash",tooltip:"Show/hide section",cls:"ui-button-icon-plain"}),g=new d.View({title:a.label,cls:"ui-portlet-section",operations:{button_visible:f}});g.append(e.$el),g.append($("<div/>").addClass("ui-table-form-info").html(a.help));var i=!1;g.$content.hide(),g.$header.css("cursor","pointer"),g.$header.on("click",function(){i?(i=!1,g.$content.hide(),f.setIcon("fa-eye-slash")):(i=!0,g.$content.fadeIn("fast"),f.setIcon("fa-eye"))}),a.expand&&g.$header.trigger("click"),this.table.add(g.$el),this.table.append(a.id)},_addRow:function(a){var b=a.id,c=this.parameters.create(a);this.app.field_list[b]=c;var d=new f(this.app,{label:a.label,default_value:a.default_value,optional:a.optional,help:a.help,field:c});return this.app.element_list[b]=d,this.table.add(d.$el),this.table.append(b),a.hidden&&this.table.get(b).hide(),c}});return{View:h}});
|
||||
//# sourceMappingURL=../../../maps/mvc/form/form-section.js.map
|
||||
@@ -1,343 +1,2 @@
|
||||
// dependencies
|
||||
define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'],
|
||||
function(Utils, Ui, Tabs, ToolTemplate) {
|
||||
|
||||
// track current history elements
|
||||
history = {};
|
||||
|
||||
// hda/hdca content selector ui element
|
||||
var View = Backbone.View.extend({
|
||||
// initialize
|
||||
initialize : function(app, options) {
|
||||
// link app and options
|
||||
this.app = app;
|
||||
this.options = options;
|
||||
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// add element
|
||||
this.setElement('<div class="ui-select-content"/>');
|
||||
|
||||
// list of select fieldsFormSection
|
||||
this.list = {};
|
||||
|
||||
// radio button options
|
||||
var radio_buttons = [];
|
||||
|
||||
// identify selector type
|
||||
if (options.type == 'data_collection') {
|
||||
this.mode = 'collection';
|
||||
} else {
|
||||
if (options.multiple) {
|
||||
this.mode = 'multiple';
|
||||
} else {
|
||||
this.mode = 'single';
|
||||
}
|
||||
}
|
||||
|
||||
// set initial state
|
||||
this.current = this.mode;
|
||||
this.list = {};
|
||||
|
||||
// error messages
|
||||
var extensions = Utils.textify(options.extensions);
|
||||
var hda_error = 'No dataset available.';
|
||||
if (extensions) {
|
||||
hda_error = 'No ' + extensions + ' dataset available.';
|
||||
}
|
||||
var hdca_error = 'No dataset list available.';
|
||||
if (extensions) {
|
||||
hdca_error = 'No ' + extensions + ' dataset collection available.';
|
||||
}
|
||||
|
||||
// add single dataset selector
|
||||
if (this.mode == 'single') {
|
||||
radio_buttons.push({
|
||||
icon : 'fa-file-o',
|
||||
value : 'single',
|
||||
tooltip : 'Single dataset'
|
||||
});
|
||||
this.select_single = new Ui.Select.View({
|
||||
optional : options.optional,
|
||||
error_text : hda_error,
|
||||
onchange : function() {
|
||||
self.trigger('change');
|
||||
}
|
||||
});
|
||||
this.list['single'] = {
|
||||
field: this.select_single,
|
||||
type : 'hda'
|
||||
};
|
||||
}
|
||||
|
||||
// add multiple dataset selector
|
||||
if (this.mode == 'single' || this.mode == 'multiple') {
|
||||
radio_buttons.push({
|
||||
icon : 'fa-files-o',
|
||||
value : 'multiple',
|
||||
tooltip : 'Multiple datasets'
|
||||
});
|
||||
this.select_multiple = new Ui.Select.View({
|
||||
multiple : true,
|
||||
searchable : false,
|
||||
error_text : hda_error,
|
||||
onchange : function() {
|
||||
self.trigger('change');
|
||||
}
|
||||
});
|
||||
this.list['multiple'] = {
|
||||
field: this.select_multiple,
|
||||
type : 'hda'
|
||||
};
|
||||
}
|
||||
|
||||
// add collection selector
|
||||
if (this.mode == 'single' || this.mode == 'multiple' || this.mode == 'collection') {
|
||||
radio_buttons.push({
|
||||
icon : 'fa-folder-o',
|
||||
value : 'collection',
|
||||
tooltip : 'Dataset collection'
|
||||
});
|
||||
this.select_collection = new Ui.Select.View({
|
||||
error_text : hdca_error,
|
||||
optional : options.optional,
|
||||
onchange : function() {
|
||||
self.trigger('change');
|
||||
}
|
||||
});
|
||||
this.list['collection'] = {
|
||||
field: this.select_collection,
|
||||
type : 'hdca'
|
||||
};
|
||||
}
|
||||
|
||||
// create button
|
||||
this.button_type = new Ui.RadioButton.View({
|
||||
value : this.current,
|
||||
data : radio_buttons,
|
||||
onchange: function(value) {
|
||||
self.current = value;
|
||||
self.refresh();
|
||||
self.trigger('change');
|
||||
}
|
||||
});
|
||||
|
||||
// add batch mode information
|
||||
this.$batch = $(this.template_batch());
|
||||
|
||||
// number of radio buttons
|
||||
var n_buttons = _.size(this.list);
|
||||
|
||||
// add button to dom
|
||||
var button_width = 0;
|
||||
if (n_buttons > 1) {
|
||||
this.$el.append(this.button_type.$el);
|
||||
button_width = Math.max(0, _.size(this.list) * 35) + 'px';
|
||||
}
|
||||
|
||||
// append field elements
|
||||
for (var i in this.list) {
|
||||
this.$el.append(this.list[i].field.$el.css({
|
||||
'margin-left': button_width
|
||||
}));
|
||||
}
|
||||
|
||||
// append batch message
|
||||
this.$el.append(this.$batch.css({
|
||||
'margin-left': button_width
|
||||
}));
|
||||
|
||||
// update options
|
||||
this.update(options.data);
|
||||
|
||||
// set initial value
|
||||
if (this.options.value !== undefined) {
|
||||
this.value(this.options.value);
|
||||
}
|
||||
|
||||
// refresh view
|
||||
this.refresh();
|
||||
|
||||
// add change event. fires on trigger
|
||||
this.on('change', function() {
|
||||
if (options.onchange) {
|
||||
options.onchange(self.value());
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Indicate that select fields are being updated */
|
||||
wait: function() {
|
||||
for (var i in this.list) {
|
||||
this.list[i].field.wait();
|
||||
}
|
||||
},
|
||||
|
||||
/** Indicate that the options update has been completed */
|
||||
unwait: function() {
|
||||
for (var i in this.list) {
|
||||
this.list[i].field.unwait();
|
||||
}
|
||||
},
|
||||
|
||||
/** Update content selector */
|
||||
update: function(options) {
|
||||
// update a particular select field
|
||||
var self = this;
|
||||
function _update(field, options) {
|
||||
if (field) {
|
||||
// identify available options
|
||||
var select_options = [];
|
||||
for (var i in options) {
|
||||
var item = options[i];
|
||||
select_options.push({
|
||||
label: item.hid + ': ' + item.name,
|
||||
value: item.id
|
||||
});
|
||||
// backup to local history
|
||||
history[item.id + '_' + item.src] = item;
|
||||
}
|
||||
// update field
|
||||
field.update(select_options);
|
||||
}
|
||||
}
|
||||
|
||||
// update available options
|
||||
_update(this.select_single, options.hda);
|
||||
_update(this.select_multiple, options.hda);
|
||||
_update(this.select_collection, options.hdca);
|
||||
},
|
||||
|
||||
/** Return the currently selected dataset values */
|
||||
value : function (new_value) {
|
||||
// update current value
|
||||
if (new_value !== undefined) {
|
||||
if (new_value && new_value.values) {
|
||||
try {
|
||||
// create list with values
|
||||
var list = [];
|
||||
for (var i in new_value.values) {
|
||||
list.push(new_value.values[i].id);
|
||||
}
|
||||
|
||||
// identify suitable select field
|
||||
if (new_value && new_value.values.length > 0 && new_value.values[0].src == 'hdca') {
|
||||
this.current = 'collection';
|
||||
this.select_collection.value(list[0]);
|
||||
} else {
|
||||
if (this.mode == 'multiple') {
|
||||
this.current = 'multiple';
|
||||
this.select_multiple.value(list);
|
||||
} else {
|
||||
this.current = 'single';
|
||||
this.select_single.value(list[0]);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.debug('tools-select-content::value() - Skipped.');
|
||||
}
|
||||
} else {
|
||||
for (var i in this.list) {
|
||||
this.list[i].field.value(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// refresh view
|
||||
this.refresh();
|
||||
|
||||
// validate value
|
||||
var id_list = this._select().value();
|
||||
if (id_list === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// transform into an array
|
||||
if (!(id_list instanceof Array)) {
|
||||
id_list = [id_list];
|
||||
}
|
||||
|
||||
// check if value exists
|
||||
if (id_list.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// prepare result dict
|
||||
var result = {
|
||||
batch : this._batch(),
|
||||
values : []
|
||||
}
|
||||
|
||||
// append to dataset ids
|
||||
for (var i in id_list) {
|
||||
var details = history[id_list[i] + '_' + this.list[this.current].type];
|
||||
if (details) {
|
||||
result.values.push(details);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// sort by history ids
|
||||
result.values.sort(function(a, b){
|
||||
return a.hid - b.hid;
|
||||
});
|
||||
|
||||
// return
|
||||
return result;
|
||||
},
|
||||
|
||||
/** Refreshes data selection view */
|
||||
refresh: function() {
|
||||
this.button_type.value(this.current);
|
||||
for (var i in this.list) {
|
||||
var $el = this.list[i].field.$el;
|
||||
if (this.current == i) {
|
||||
$el.show();
|
||||
} else {
|
||||
$el.hide();
|
||||
}
|
||||
}
|
||||
if (this._batch()) {
|
||||
this.$batch.show();
|
||||
} else {
|
||||
this.$batch.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/** Assists in selecting the current field */
|
||||
_select: function() {
|
||||
return this.list[this.current].field;
|
||||
},
|
||||
|
||||
/** Assists in identifying the batch mode */
|
||||
_batch: function() {
|
||||
if (this.current == 'collection') {
|
||||
var hdca = history[this._select().value() + '_hdca'];
|
||||
if (hdca && hdca.map_over_type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (this.current != 'single') {
|
||||
if (this.mode == 'single') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/** Batch message template */
|
||||
template_batch: function() {
|
||||
return '<div class="ui-table-form-info">' +
|
||||
'<i class="fa fa-sitemap" style="font-size: 1.2em; padding: 2px 5px;"/>' +
|
||||
'This is a batch mode input field. A separate job will be triggered for each dataset.' +
|
||||
'</div>';
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
View: View
|
||||
}
|
||||
|
||||
});
|
||||
define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(a,b){history={};var c=Backbone.View.extend({initialize:function(c,d){this.app=c,this.options=d;var e=this;this.setElement('<div class="ui-select-content"/>'),this.list={};var f=[];this.mode="data_collection"==d.type?"collection":d.multiple?"multiple":"single",this.current=this.mode,this.list={};var g=a.textify(d.extensions),h="No dataset available.";g&&(h="No "+g+" dataset available.");var i="No dataset list available.";g&&(i="No "+g+" dataset collection available."),"single"==this.mode&&(f.push({icon:"fa-file-o",value:"single",tooltip:"Single dataset"}),this.select_single=new b.Select.View({optional:d.optional,error_text:h,onchange:function(){e.trigger("change")}}),this.list.single={field:this.select_single,type:"hda"}),("single"==this.mode||"multiple"==this.mode)&&(f.push({icon:"fa-files-o",value:"multiple",tooltip:"Multiple datasets"}),this.select_multiple=new b.Select.View({multiple:!0,searchable:!1,error_text:h,onchange:function(){e.trigger("change")}}),this.list.multiple={field:this.select_multiple,type:"hda"}),("single"==this.mode||"multiple"==this.mode||"collection"==this.mode)&&(f.push({icon:"fa-folder-o",value:"collection",tooltip:"Dataset collection"}),this.select_collection=new b.Select.View({error_text:i,optional:d.optional,onchange:function(){e.trigger("change")}}),this.list.collection={field:this.select_collection,type:"hdca"}),this.button_type=new b.RadioButton.View({value:this.current,data:f,onchange:function(a){e.current=a,e.refresh(),e.trigger("change")}}),this.$batch=$(this.template_batch());var j=_.size(this.list),k=0;j>1&&(this.$el.append(this.button_type.$el),k=Math.max(0,35*_.size(this.list))+"px");for(var l in this.list)this.$el.append(this.list[l].field.$el.css({"margin-left":k}));this.$el.append(this.$batch.css({"margin-left":k})),this.update(d.data),void 0!==this.options.value&&this.value(this.options.value),this.refresh(),this.on("change",function(){d.onchange&&d.onchange(e.value())})},wait:function(){for(var a in this.list)this.list[a].field.wait()},unwait:function(){for(var a in this.list)this.list[a].field.unwait()},update:function(a){function b(a,b){if(a){var c=[];for(var d in b){var e=b[d];c.push({label:e.hid+": "+e.name,value:e.id}),history[e.id+"_"+e.src]=e}a.update(c)}}b(this.select_single,a.hda),b(this.select_multiple,a.hda),b(this.select_collection,a.hdca)},value:function(a){if(void 0!==a)if(a&&a.values)try{var b=[];for(var c in a.values)b.push(a.values[c].id);a&&a.values.length>0&&"hdca"==a.values[0].src?(this.current="collection",this.select_collection.value(b[0])):"multiple"==this.mode?(this.current="multiple",this.select_multiple.value(b)):(this.current="single",this.select_single.value(b[0]))}catch(d){}else for(var c in this.list)this.list[c].field.value(null);this.refresh();var e=this._select().value();if(null===e)return null;if(e instanceof Array||(e=[e]),0===e.length)return null;var f={batch:this._batch(),values:[]};for(var c in e){var g=history[e[c]+"_"+this.list[this.current].type];if(!g)return null;f.values.push(g)}return f.values.sort(function(a,b){return a.hid-b.hid}),f},refresh:function(){this.button_type.value(this.current);for(var a in this.list){var b=this.list[a].field.$el;this.current==a?b.show():b.hide()}this._batch()?this.$batch.show():this.$batch.hide()},_select:function(){return this.list[this.current].field},_batch:function(){if("collection"==this.current){var a=history[this._select().value()+"_hdca"];if(a&&a.map_over_type)return!0}return"single"!=this.current&&"single"==this.mode?!0:!1},template_batch:function(){return'<div class="ui-table-form-info"><i class="fa fa-sitemap" style="font-size: 1.2em; padding: 2px 5px;"/>This is a batch mode input field. A separate job will be triggered for each dataset.</div>'}});return{View:c}});
|
||||
//# sourceMappingURL=../../../maps/mvc/form/form-select-content.js.map
|
||||
@@ -1,235 +1,2 @@
|
||||
/**
|
||||
This is the main class of the form plugin. It is referenced as 'app' in all lower level modules.
|
||||
*/
|
||||
define(['utils/utils', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
|
||||
'mvc/form/form-section', 'mvc/form/form-data'],
|
||||
function(Utils, Portlet, Ui, FormSection, FormData) {
|
||||
|
||||
// create form view
|
||||
return Backbone.View.extend({
|
||||
// initialize
|
||||
initialize: function(options) {
|
||||
// options
|
||||
this.optionsDefault = {
|
||||
// uses dynamic fields instead of text fields
|
||||
is_dynamic : true,
|
||||
// shows form in narrow view mode
|
||||
narrow : false,
|
||||
// shows errors on start
|
||||
initial_errors : false,
|
||||
// portlet style
|
||||
cls : 'ui-portlet-limited'
|
||||
};
|
||||
|
||||
// configure options
|
||||
this.options = Utils.merge(options, this.optionsDefault);
|
||||
|
||||
// log options
|
||||
console.debug(this.options);
|
||||
|
||||
// link galaxy modal or create one
|
||||
var galaxy = parent.Galaxy;
|
||||
if (galaxy && galaxy.modal) {
|
||||
this.modal = galaxy.modal;
|
||||
} else {
|
||||
this.modal = new Ui.Modal.View();
|
||||
}
|
||||
|
||||
// set element
|
||||
this.setElement('<div/>');
|
||||
|
||||
// build this form
|
||||
this._build();
|
||||
},
|
||||
|
||||
/** Update available options */
|
||||
update: function(new_model){
|
||||
var self = this;
|
||||
this.data.matchModel(new_model, function(input_id, node) {
|
||||
var input = self.input_list[input_id];
|
||||
if (input && input.options) {
|
||||
if (!_.isEqual(input.options, node.options)) {
|
||||
// backup new options
|
||||
input.options = node.options;
|
||||
|
||||
// get/update field
|
||||
var field = self.field_list[input_id];
|
||||
if (field.update) {
|
||||
var new_options = [];
|
||||
if ((['data', 'data_collection', 'drill_down']).indexOf(input.type) != -1) {
|
||||
new_options = input.options;
|
||||
} else {
|
||||
for (var i in node.options) {
|
||||
var opt = node.options[i];
|
||||
if (opt.length > 2) {
|
||||
new_options.push({
|
||||
'label': opt[0],
|
||||
'value': opt[1]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
field.update(new_options);
|
||||
field.trigger('change');
|
||||
console.debug('Updating options for ' + input_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Set form into wait mode */
|
||||
wait: function(active) {
|
||||
for (var i in this.input_list) {
|
||||
var field = this.field_list[i];
|
||||
var input = this.input_list[i];
|
||||
if (input.is_dynamic && field.wait && field.unwait) {
|
||||
if (active) {
|
||||
field.wait();
|
||||
} else {
|
||||
field.unwait();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** Shows the final message (usually upon successful job submission)
|
||||
*/
|
||||
reciept: function($el) {
|
||||
this.$el.empty();
|
||||
this.$el.append($el);
|
||||
},
|
||||
|
||||
/** Highlight and scroll to input element (currently only used for error notifications)
|
||||
*/
|
||||
highlight: function (input_id, message, silent) {
|
||||
// get input field
|
||||
var input_element = this.element_list[input_id];
|
||||
|
||||
// check input element
|
||||
if (input_element) {
|
||||
// mark error
|
||||
input_element.error(message || 'Please verify this parameter.');
|
||||
|
||||
// scroll to first input element
|
||||
if (!silent) {
|
||||
$('html, body').animate({
|
||||
scrollTop: input_element.$el.offset().top - 20
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** Highlights errors
|
||||
*/
|
||||
errors: function(options) {
|
||||
// hide previous error statements
|
||||
this.trigger('reset');
|
||||
|
||||
// highlight all errors
|
||||
if (options && options.errors) {
|
||||
var error_messages = this.data.matchResponse(options.errors);
|
||||
for (var input_id in this.element_list) {
|
||||
var input = this.element_list[input_id];
|
||||
if (error_messages[input_id]) {
|
||||
this.highlight(input_id, error_messages[input_id], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** Main tool form build function. This function is called once a new model is available.
|
||||
*/
|
||||
_build: function() {
|
||||
// link this
|
||||
var self = this;
|
||||
|
||||
// reset events
|
||||
this.off('change');
|
||||
this.off('reset');
|
||||
|
||||
// reset field list, which contains the input field elements
|
||||
this.field_list = {};
|
||||
|
||||
// reset sequential input definition list, which contains the input definitions as provided from the api
|
||||
this.input_list = {};
|
||||
|
||||
// reset input element list, which contains the dom elements of each input element (includes also the input field)
|
||||
this.element_list = {};
|
||||
|
||||
// creates a json data structure from the input form
|
||||
this.data = new FormData(this);
|
||||
|
||||
// create ui elements
|
||||
this._renderForm();
|
||||
|
||||
// refresh data
|
||||
this.data.create();
|
||||
|
||||
// show errors on startup
|
||||
if (this.options.initial_errors) {
|
||||
this.errors(this.options);
|
||||
}
|
||||
|
||||
// add listener which triggers on checksum change
|
||||
var current_check = this.data.checksum();
|
||||
this.on('change', function() {
|
||||
var new_check = self.data.checksum();
|
||||
if (new_check != current_check) {
|
||||
current_check = new_check;
|
||||
self.options.onchange && self.options.onchange();
|
||||
}
|
||||
});
|
||||
|
||||
// add reset listener
|
||||
this.on('reset', function() {
|
||||
for (var i in this.element_list) {
|
||||
this.element_list[i].reset();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Renders the UI elements required for the form
|
||||
*/
|
||||
_renderForm: function() {
|
||||
// create message view
|
||||
this.message = new Ui.Message();
|
||||
|
||||
// create tool form section
|
||||
this.section = new FormSection.View(this, {
|
||||
inputs : this.options.inputs
|
||||
});
|
||||
|
||||
// create portlet
|
||||
this.portlet = new Portlet.View({
|
||||
icon : 'fa-wrench',
|
||||
title : this.options.title,
|
||||
cls : this.options.cls,
|
||||
operations : this.options.operations,
|
||||
buttons : this.options.buttons
|
||||
});
|
||||
|
||||
// append message
|
||||
this.portlet.append(this.message.$el.addClass('ui-margin-top'));
|
||||
|
||||
// append tool section
|
||||
this.portlet.append(this.section.$el);
|
||||
|
||||
// start form
|
||||
this.$el.empty();
|
||||
this.$el.append(this.portlet.$el);
|
||||
|
||||
// show message if available in model
|
||||
if (this.options.message) {
|
||||
this.message.update({
|
||||
persistent : true,
|
||||
status : 'warning',
|
||||
message : this.options.message
|
||||
});
|
||||
}
|
||||
|
||||
// log
|
||||
console.debug('tools-form-base::initialize() - Completed.');
|
||||
}
|
||||
});
|
||||
});
|
||||
define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/form/form-section","mvc/form/form-data"],function(a,b,c,d,e){return Backbone.View.extend({initialize:function(b){this.optionsDefault={is_dynamic:!0,narrow:!1,initial_errors:!1,cls:"ui-portlet-limited"},this.options=a.merge(b,this.optionsDefault);var d=parent.Galaxy;this.modal=d&&d.modal?d.modal:new c.Modal.View,this.setElement("<div/>"),this._build()},update:function(a){var b=this;this.data.matchModel(a,function(a,c){var d=b.input_list[a];if(d&&d.options&&!_.isEqual(d.options,c.options)){d.options=c.options;var e=b.field_list[a];if(e.update){var f=[];if(-1!=["data","data_collection","drill_down"].indexOf(d.type))f=d.options;else for(var g in c.options){var h=c.options[g];h.length>2&&f.push({label:h[0],value:h[1]})}e.update(f),e.trigger("change")}}})},wait:function(a){for(var b in this.input_list){var c=this.field_list[b],d=this.input_list[b];d.is_dynamic&&c.wait&&c.unwait&&(a?c.wait():c.unwait())}},reciept:function(a){this.$el.empty(),this.$el.append(a)},highlight:function(a,b,c){var d=this.element_list[a];d&&(d.error(b||"Please verify this parameter."),c||$("html, body").animate({scrollTop:d.$el.offset().top-20},500))},errors:function(a){if(this.trigger("reset"),a&&a.errors){var b=this.data.matchResponse(a.errors);for(var c in this.element_list){{this.element_list[c]}b[c]&&this.highlight(c,b[c],!0)}}},_build:function(){var a=this;this.off("change"),this.off("reset"),this.field_list={},this.input_list={},this.element_list={},this.data=new e(this),this._renderForm(),this.data.create(),this.options.initial_errors&&this.errors(this.options);var b=this.data.checksum();this.on("change",function(){var c=a.data.checksum();c!=b&&(b=c,a.options.onchange&&a.options.onchange())}),this.on("reset",function(){for(var a in this.element_list)this.element_list[a].reset()})},_renderForm:function(){this.message=new c.Message,this.section=new d.View(this,{inputs:this.options.inputs}),this.portlet=new b.View({icon:"fa-wrench",title:this.options.title,cls:this.options.cls,operations:this.options.operations,buttons:this.options.buttons}),this.portlet.append(this.message.$el.addClass("ui-margin-top")),this.portlet.append(this.section.$el),this.$el.empty(),this.$el.append(this.portlet.$el),this.options.message&&this.message.update({persistent:!0,status:"warning",message:this.options.message})}})});
|
||||
//# sourceMappingURL=../../../maps/mvc/form/form-view.js.map
|
||||
@@ -1,121 +1,2 @@
|
||||
// dependencies
|
||||
define([], function() {
|
||||
|
||||
// grid model
|
||||
return Backbone.Model.extend({
|
||||
defaults: {
|
||||
url_base: '',
|
||||
async: false,
|
||||
async_ops: [],
|
||||
categorical_filters: [],
|
||||
filters: {},
|
||||
sort_key: null,
|
||||
show_item_checkboxes: false,
|
||||
advanced_search: false,
|
||||
cur_page: 1,
|
||||
num_pages: 1,
|
||||
operation: undefined,
|
||||
item_ids: undefined
|
||||
},
|
||||
|
||||
/**
|
||||
* Return true if operation can be done asynchronously.
|
||||
*/
|
||||
can_async_op: function(op) {
|
||||
return _.indexOf(this.attributes.async_ops, op) !== -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add filtering criterion.
|
||||
*/
|
||||
add_filter: function(key, value, append) {
|
||||
// Update URL arg with new condition.
|
||||
if (append) {
|
||||
// Update or append value.
|
||||
var cur_val = this.attributes.filters[key],
|
||||
new_val;
|
||||
if (cur_val === null || cur_val === undefined) {
|
||||
new_val = value;
|
||||
}
|
||||
else if (typeof(cur_val) == 'string') {
|
||||
if (cur_val == 'All') {
|
||||
new_val = value;
|
||||
} else {
|
||||
// Replace string with array.
|
||||
var values = [];
|
||||
values[0] = cur_val;
|
||||
values[1] = value;
|
||||
new_val = values;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Current value is an array.
|
||||
new_val = cur_val;
|
||||
new_val.push(value);
|
||||
}
|
||||
this.attributes.filters[key] = new_val;
|
||||
}
|
||||
else {
|
||||
// Replace value.
|
||||
this.attributes.filters[key] = value;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove filtering criterion.
|
||||
*/
|
||||
remove_filter: function(key, condition) {
|
||||
var cur_val = this.attributes.filters[key];
|
||||
if (cur_val === null || cur_val === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof(cur_val) === 'string') {
|
||||
// overwrite/remove condition.
|
||||
this.attributes.filters[key] = '';
|
||||
} else {
|
||||
// filter contains an array of conditions.
|
||||
var condition_index = _.indexOf(cur_val, condition);
|
||||
if (condition_index !== -1) {
|
||||
cur_val[condition_index] = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns URL data for obtaining a new grid.
|
||||
*/
|
||||
get_url_data: function() {
|
||||
var url_data = {
|
||||
async: this.attributes.async,
|
||||
sort: this.attributes.sort_key,
|
||||
page: this.attributes.cur_page,
|
||||
show_item_checkboxes: this.attributes.show_item_checkboxes,
|
||||
advanced_search: this.attributes.advanced_search
|
||||
};
|
||||
|
||||
// Add operation, item_ids only if they have values.
|
||||
if (this.attributes.operation) {
|
||||
url_data.operation = this.attributes.operation;
|
||||
}
|
||||
if (this.attributes.item_ids) {
|
||||
url_data.id = this.attributes.item_ids;
|
||||
}
|
||||
|
||||
// Add filter arguments to data, placing "f-" in front of all arguments.
|
||||
var self = this;
|
||||
_.each(_.pairs(self.attributes.filters), function(k) {
|
||||
url_data['f-' + k[0]] = k[1];
|
||||
});
|
||||
|
||||
return url_data;
|
||||
},
|
||||
|
||||
// Return URL for obtaining a new grid
|
||||
get_url: function (args) {
|
||||
return this.get('url_base') + "?" + $.param(this.get_url_data()) + '&' + $.param(args);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
define([],function(){return Backbone.Model.extend({defaults:{url_base:"",async:!1,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:!1,advanced_search:!1,cur_page:1,num_pages:1,operation:void 0,item_ids:void 0},can_async_op:function(a){return-1!==_.indexOf(this.attributes.async_ops,a)},add_filter:function(a,b,c){if(c){var d,e=this.attributes.filters[a];if(null===e||void 0===e)d=b;else if("string"==typeof e)if("All"==e)d=b;else{var f=[];f[0]=e,f[1]=b,d=f}else d=e,d.push(b);this.attributes.filters[a]=d}else this.attributes.filters[a]=b},remove_filter:function(a,b){var c=this.attributes.filters[a];if(null===c||void 0===c)return!1;if("string"==typeof c)this.attributes.filters[a]="";else{var d=_.indexOf(c,b);-1!==d&&(c[d]="")}},get_url_data:function(){var a={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes,advanced_search:this.attributes.advanced_search};this.attributes.operation&&(a.operation=this.attributes.operation),this.attributes.item_ids&&(a.id=this.attributes.item_ids);var b=this;return _.each(_.pairs(b.attributes.filters),function(b){a["f-"+b[0]]=b[1]}),a},get_url:function(a){return this.get("url_base")+"?"+$.param(this.get_url_data())+"&"+$.param(a)}})});
|
||||
//# sourceMappingURL=../../../maps/mvc/grid/grid-model.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,63 +1,2 @@
|
||||
define([
|
||||
"mvc/dataset/dataset-li-edit",
|
||||
"mvc/history/hda-li",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( DATASET_LI_EDIT, HDA_LI, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
var _super = DATASET_LI_EDIT.DatasetListItemEdit;
|
||||
/** @class Editing view for HistoryDatasetAssociation.
|
||||
*/
|
||||
var HDAListItemEdit = _super.extend(
|
||||
/** @lends HDAListItemEdit.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
className : _super.prototype.className + " history-content",
|
||||
|
||||
// ......................................................................... events
|
||||
/** event map */
|
||||
events : _.extend( _.clone( _super.prototype.events ), {
|
||||
'click .unhide-link' : function( ev ){ this.model.unhide(); return false; }
|
||||
}),
|
||||
|
||||
// ......................................................................... misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'HDAListItemEdit(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ............................................................................ TEMPLATES
|
||||
/** underscore templates */
|
||||
HDAListItemEdit.prototype.templates = (function(){
|
||||
//TODO: move to require text! plugin
|
||||
|
||||
var warnings = _.extend( {}, _super.prototype.templates.warnings, {
|
||||
hidden : BASE_MVC.wrapTemplate([
|
||||
'<% if( !dataset.visible ){ %>',
|
||||
// add a link to unhide a dataset
|
||||
'<div class="hidden-msg warningmessagesmall">',
|
||||
_l( 'This dataset has been hidden' ),
|
||||
'<br /><a class="unhide-link" a href="javascript:void(0);">', _l( 'Unhide it' ), '</a>',
|
||||
'</div>',
|
||||
'<% } %>'
|
||||
], 'dataset' )
|
||||
});
|
||||
|
||||
return _.extend( {}, _super.prototype.templates, {
|
||||
//NOTE: *steal* the HDAListItemView titleBar
|
||||
titleBar : HDA_LI.HDAListItemView.prototype.templates.titleBar,
|
||||
warnings : warnings
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
HDAListItemEdit : HDAListItemEdit
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/dataset-li-edit","mvc/history/hda-li","mvc/base-mvc","utils/localization"],function(a,b,c,d){var e=a.DatasetListItemEdit,f=e.extend({className:e.prototype.className+" history-content",events:_.extend(_.clone(e.prototype.events),{"click .unhide-link":function(){return this.model.unhide(),!1}}),toString:function(){var a=this.model?this.model+"":"(no model)";return"HDAListItemEdit("+a+")"}});return f.prototype.templates=function(){var a=_.extend({},e.prototype.templates.warnings,{hidden:c.wrapTemplate(["<% if( !dataset.visible ){ %>",'<div class="hidden-msg warningmessagesmall">',d("This dataset has been hidden"),'<br /><a class="unhide-link" a href="javascript:void(0);">',d("Unhide it"),"</a>","</div>","<% } %>"],"dataset")});return _.extend({},e.prototype.templates,{titleBar:b.HDAListItemView.prototype.templates.titleBar,warnings:a})}(),{HDAListItemEdit:f}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/hda-li-edit.js.map
|
||||
@@ -1,74 +1,2 @@
|
||||
define([
|
||||
"mvc/dataset/dataset-li",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( DATASET_LI, BASE_MVC, _l ){
|
||||
/* global Backbone */
|
||||
//==============================================================================
|
||||
var _super = DATASET_LI.DatasetListItemView;
|
||||
/** @class Read only view for HistoryDatasetAssociation.
|
||||
* Since there are no controls on the HDAView to hide the dataset,
|
||||
* the primary thing this class does (currently) is override templates
|
||||
* to render the HID.
|
||||
*/
|
||||
var HDAListItemView = _super.extend(
|
||||
/** @lends HDAListItemView.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
className : _super.prototype.className + " history-content",
|
||||
|
||||
initialize : function( attributes, options ){
|
||||
_super.prototype.initialize.call( this, attributes, options );
|
||||
},
|
||||
|
||||
// ......................................................................... misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'HDAListItemView(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
// ............................................................................ TEMPLATES
|
||||
/** underscore templates */
|
||||
HDAListItemView.prototype.templates = (function(){
|
||||
//TODO: move to require text! plugin
|
||||
|
||||
var titleBarTemplate = BASE_MVC.wrapTemplate([
|
||||
// adding the hid display to the title
|
||||
'<div class="title-bar clear" tabindex="0">',
|
||||
'<span class="state-icon"></span>',
|
||||
'<div class="title">',
|
||||
//TODO: remove whitespace and use margin-right
|
||||
'<span class="hid"><%- dataset.hid %></span> ',
|
||||
'<span class="name"><%- dataset.name %></span>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
], 'dataset' );
|
||||
|
||||
var warnings = _.extend( {}, _super.prototype.templates.warnings, {
|
||||
hidden : BASE_MVC.wrapTemplate([
|
||||
// add a warning when hidden
|
||||
'<% if( !dataset.visible ){ %>',
|
||||
'<div class="hidden-msg warningmessagesmall">',
|
||||
_l( 'This dataset has been hidden' ),
|
||||
'</div>',
|
||||
'<% } %>'
|
||||
], 'dataset' )
|
||||
});
|
||||
|
||||
return _.extend( {}, _super.prototype.templates, {
|
||||
titleBar : titleBarTemplate,
|
||||
warnings : warnings
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
HDAListItemView : HDAListItemView
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/dataset-li","mvc/base-mvc","utils/localization"],function(a,b,c){var d=a.DatasetListItemView,e=d.extend({className:d.prototype.className+" history-content",initialize:function(a,b){d.prototype.initialize.call(this,a,b)},toString:function(){var a=this.model?this.model+"":"(no model)";return"HDAListItemView("+a+")"}});return e.prototype.templates=function(){var a=b.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="hid"><%- dataset.hid %></span> ','<span class="name"><%- dataset.name %></span>',"</div>","</div>"],"dataset"),e=_.extend({},d.prototype.templates.warnings,{hidden:b.wrapTemplate(["<% if( !dataset.visible ){ %>",'<div class="hidden-msg warningmessagesmall">',c("This dataset has been hidden"),"</div>","<% } %>"],"dataset")});return _.extend({},d.prototype.templates,{titleBar:a,warnings:e})}(),{HDAListItemView:e}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/hda-li.js.map
|
||||
@@ -1,53 +1,2 @@
|
||||
define([
|
||||
"mvc/dataset/dataset-model",
|
||||
"mvc/history/history-content-model",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( DATASET, HISTORY_CONTENT, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
var _super = DATASET.DatasetAssociation,
|
||||
hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;
|
||||
/** @class (HDA) model for a Galaxy dataset contained in and related to a history.
|
||||
*/
|
||||
var HistoryDatasetAssociation = _super.extend( BASE_MVC.mixin( hcontentMixin,
|
||||
/** @lends HistoryDatasetAssociation.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
// because all objects have constructors (as this hashmap would even if this next line wasn't present)
|
||||
// the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model
|
||||
// - re-apply manually it now
|
||||
/** call the mixin constructor */
|
||||
constructor : function( attrs, options ){
|
||||
hcontentMixin.constructor.call( this, attrs, options );
|
||||
},
|
||||
|
||||
/** default attributes for a model */
|
||||
defaults : _.extend( {}, _super.prototype.defaults, hcontentMixin.defaults, {
|
||||
model_class : 'HistoryDatasetAssociation'
|
||||
}),
|
||||
|
||||
/** Set up the model, determine if accessible, bind listeners
|
||||
*/
|
||||
initialize : function( attributes, options ){
|
||||
_super.prototype.initialize.call( this, attributes, options );
|
||||
hcontentMixin.initialize.call( this, attributes, options );
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var nameAndId = this.get( 'id' ) || '';
|
||||
if( this.get( 'name' ) ){
|
||||
nameAndId = this.get( 'hid' ) + ' :"' + this.get( 'name' ) + '",' + nameAndId;
|
||||
}
|
||||
return 'HDA(' + nameAndId + ')';
|
||||
}
|
||||
}));
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
HistoryDatasetAssociation : HistoryDatasetAssociation
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/dataset-model","mvc/history/history-content-model","mvc/base-mvc","utils/localization"],function(a,b,c){var d=a.DatasetAssociation,e=b.HistoryContentMixin,f=d.extend(c.mixin(e,{constructor:function(a,b){e.constructor.call(this,a,b)},defaults:_.extend({},d.prototype.defaults,e.defaults,{model_class:"HistoryDatasetAssociation"}),initialize:function(a,b){d.prototype.initialize.call(this,a,b),e.initialize.call(this,a,b)},toString:function(){var a=this.get("id")||"";return this.get("name")&&(a=this.get("hid")+' :"'+this.get("name")+'",'+a),"HDA("+a+")"}}));return{HistoryDatasetAssociation:f}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/hda-model.js.map
|
||||
@@ -1,57 +1,2 @@
|
||||
define([
|
||||
"mvc/dataset/states",
|
||||
"mvc/history/hdca-li",
|
||||
"ui/fa-icon-button",
|
||||
"utils/localization"
|
||||
], function( STATES, HDCA_LI, faIconButton, _l ){
|
||||
//==============================================================================
|
||||
var _super = HDCA_LI.HDCAListItemView;
|
||||
/** @class Editing view for HistoryDatasetCollectionAssociation.
|
||||
*/
|
||||
var HDCAListItemEdit = _super.extend(
|
||||
/** @lends HDCAListItemEdit.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
// ......................................................................... delete
|
||||
/** In this override, add the delete button. */
|
||||
_renderPrimaryActions : function(){
|
||||
this.log( this + '._renderPrimaryActions' );
|
||||
// render the display, edit attr and delete icon-buttons
|
||||
return _super.prototype._renderPrimaryActions.call( this )
|
||||
.concat([
|
||||
this._renderDeleteButton()
|
||||
]);
|
||||
},
|
||||
|
||||
/** Render icon-button to delete this collection. */
|
||||
_renderDeleteButton : function(){
|
||||
var self = this,
|
||||
deleted = this.model.get( 'deleted' );
|
||||
return faIconButton({
|
||||
title : deleted? _l( 'Dataset collection is already deleted' ): _l( 'Delete' ),
|
||||
classes : 'delete-btn',
|
||||
faIcon : 'fa-times',
|
||||
disabled : deleted,
|
||||
onclick : function() {
|
||||
// ...bler... tooltips being left behind in DOM (hover out never called on deletion)
|
||||
self.$el.find( '.icon-btn.delete-btn' ).trigger( 'mouseout' );
|
||||
self.model[ 'delete' ]();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ......................................................................... misc
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'HDCAListItemEdit(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
HDCAListItemEdit : HDCAListItemEdit
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/states","mvc/history/hdca-li","ui/fa-icon-button","utils/localization"],function(a,b,c,d){var e=b.HDCAListItemView,f=e.extend({_renderPrimaryActions:function(){return this.log(this+"._renderPrimaryActions"),e.prototype._renderPrimaryActions.call(this).concat([this._renderDeleteButton()])},_renderDeleteButton:function(){var a=this,b=this.model.get("deleted");return c({title:d(b?"Dataset collection is already deleted":"Delete"),classes:"delete-btn",faIcon:"fa-times",disabled:b,onclick:function(){a.$el.find(".icon-btn.delete-btn").trigger("mouseout"),a.model.delete()}})},toString:function(){var a=this.model?this.model+"":"(no model)";return"HDCAListItemEdit("+a+")"}});return{HDCAListItemEdit:f}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/hdca-li-edit.js.map
|
||||
@@ -1,79 +1,2 @@
|
||||
define([
|
||||
"mvc/dataset/states",
|
||||
"mvc/collection/collection-li",
|
||||
"mvc/collection/collection-panel",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( STATES, DC_LI, DC_PANEL, BASE_MVC, _l ){
|
||||
/* global Backbone */
|
||||
//==============================================================================
|
||||
var _super = DC_LI.DCListItemView;
|
||||
/** @class Read only view for HistoryDatasetCollectionAssociation (a dataset collection inside a history).
|
||||
*/
|
||||
var HDCAListItemView = _super.extend(
|
||||
/** @lends HDCAListItemView.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
className : _super.prototype.className + " history-content",
|
||||
|
||||
_getFoldoutPanelClass : function(){
|
||||
switch( this.model.get( 'collection_type' ) ){
|
||||
case 'list':
|
||||
return DC_PANEL.ListCollectionPanel;
|
||||
case 'paired':
|
||||
return DC_PANEL.PairCollectionPanel;
|
||||
case 'list:paired':
|
||||
return DC_PANEL.ListOfPairsCollectionPanel;
|
||||
}
|
||||
throw new TypeError( 'Uknown collection_type: ' + this.model.get( 'collection_type' ) );
|
||||
},
|
||||
|
||||
/** In this override, add the state as a class for use with state-based CSS */
|
||||
_swapNewRender : function( $newRender ){
|
||||
_super.prototype._swapNewRender.call( this, $newRender );
|
||||
//TODO: model currently has no state
|
||||
var state = this.model.get( 'state' ) || STATES.OK;
|
||||
//if( this.model.has( 'state' ) ){
|
||||
this.$el.addClass( 'state-' + state );
|
||||
//}
|
||||
return this.$el;
|
||||
},
|
||||
|
||||
// ......................................................................... misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
|
||||
return 'HDCAListItemView(' + modelString + ')';
|
||||
}
|
||||
});
|
||||
|
||||
/** underscore templates */
|
||||
HDCAListItemView.prototype.templates = (function(){
|
||||
|
||||
// could steal this from hda-base (or use mixed content)
|
||||
var titleBarTemplate = BASE_MVC.wrapTemplate([
|
||||
// adding the hid display to the title
|
||||
'<div class="title-bar clear" tabindex="0">',
|
||||
'<span class="state-icon"></span>',
|
||||
'<div class="title">',
|
||||
//TODO: remove whitespace and use margin-right
|
||||
'<span class="hid"><%- collection.hid %></span> ',
|
||||
'<span class="name"><%- collection.name %></span>',
|
||||
'</div>',
|
||||
'<div class="subtitle"></div>',
|
||||
'</div>'
|
||||
], 'collection' );
|
||||
|
||||
return _.extend( {}, _super.prototype.templates, {
|
||||
titleBar : titleBarTemplate
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
HDCAListItemView : HDCAListItemView
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/states","mvc/collection/collection-li","mvc/collection/collection-panel","mvc/base-mvc","utils/localization"],function(a,b,c,d){var e=b.DCListItemView,f=e.extend({className:e.prototype.className+" history-content",_getFoldoutPanelClass:function(){switch(this.model.get("collection_type")){case"list":return c.ListCollectionPanel;case"paired":return c.PairCollectionPanel;case"list:paired":return c.ListOfPairsCollectionPanel}throw new TypeError("Uknown collection_type: "+this.model.get("collection_type"))},_swapNewRender:function(b){e.prototype._swapNewRender.call(this,b);var c=this.model.get("state")||a.OK;return this.$el.addClass("state-"+c),this.$el},toString:function(){var a=this.model?this.model+"":"(no model)";return"HDCAListItemView("+a+")"}});return f.prototype.templates=function(){var a=d.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="hid"><%- collection.hid %></span> ','<span class="name"><%- collection.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"collection");return _.extend({},e.prototype.templates,{titleBar:a})}(),{HDCAListItemView:f}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/hdca-li.js.map
|
||||
@@ -1,94 +1,2 @@
|
||||
define([
|
||||
"mvc/collection/collection-model",
|
||||
"mvc/history/history-content-model",
|
||||
"utils/localization"
|
||||
], function( DC_MODEL, HISTORY_CONTENT, _l ){
|
||||
/*==============================================================================
|
||||
|
||||
Models for DatasetCollections contained within a history.
|
||||
|
||||
TODO:
|
||||
these might be compactable to one class if some duplication with
|
||||
collection-model is used.
|
||||
|
||||
==============================================================================*/
|
||||
var hcontentMixin = HISTORY_CONTENT.HistoryContentMixin,
|
||||
ListDC = DC_MODEL.ListDatasetCollection,
|
||||
PairDC = DC_MODEL.PairDatasetCollection,
|
||||
ListPairedDC = DC_MODEL.ListPairedDatasetCollection;
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone model for List Dataset Collection within a History.
|
||||
*/
|
||||
var HistoryListDatasetCollection = ListDC.extend( hcontentMixin ).extend(
|
||||
/** @lends HistoryListDatasetCollection.prototype */{
|
||||
|
||||
defaults : _.extend( _.clone( ListDC.prototype.defaults ), {
|
||||
model_class : 'HistoryDatasetCollectionAssociation'
|
||||
}),
|
||||
|
||||
initialize : function( model, options ){
|
||||
ListDC.prototype.initialize.call( this, model, options );
|
||||
hcontentMixin.initialize.call( this, model, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'HistoryListDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone model for Pair Dataset Collection within a History.
|
||||
* @constructs
|
||||
*/
|
||||
var HistoryPairDatasetCollection = PairDC.extend( hcontentMixin ).extend(
|
||||
/** @lends HistoryPairDatasetCollection.prototype */{
|
||||
|
||||
defaults : _.extend( _.clone( PairDC.prototype.defaults ), {
|
||||
model_class : 'HistoryDatasetCollectionAssociation'
|
||||
}),
|
||||
|
||||
initialize : function( model, options ){
|
||||
PairDC.prototype.initialize.call( this, model, options );
|
||||
hcontentMixin.initialize.call( this, model, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'HistoryPairDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone model for List of Pairs Dataset Collection within a History.
|
||||
* @constructs
|
||||
*/
|
||||
var HistoryListPairedDatasetCollection = ListPairedDC.extend( hcontentMixin ).extend(
|
||||
/** @lends HistoryListPairedDatasetCollection.prototype */{
|
||||
|
||||
defaults : _.extend( _.clone( ListPairedDC.prototype.defaults ), {
|
||||
model_class : 'HistoryDatasetCollectionAssociation'
|
||||
}),
|
||||
|
||||
initialize : function( model, options ){
|
||||
ListPairedDC.prototype.initialize.call( this, model, options );
|
||||
hcontentMixin.initialize.call( this, model, options );
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'HistoryListPairedDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
HistoryListDatasetCollection : HistoryListDatasetCollection,
|
||||
HistoryPairDatasetCollection : HistoryPairDatasetCollection,
|
||||
HistoryListPairedDatasetCollection : HistoryListPairedDatasetCollection
|
||||
};
|
||||
});
|
||||
define(["mvc/collection/collection-model","mvc/history/history-content-model","utils/localization"],function(a,b){var c=b.HistoryContentMixin,d=a.ListDatasetCollection,e=a.PairDatasetCollection,f=a.ListPairedDatasetCollection,g=d.extend(c).extend({defaults:_.extend(_.clone(d.prototype.defaults),{model_class:"HistoryDatasetCollectionAssociation"}),initialize:function(a,b){d.prototype.initialize.call(this,a,b),c.initialize.call(this,a,b)},toString:function(){return["HistoryListDatasetCollection(",this.get("name"),")"].join("")}}),h=e.extend(c).extend({defaults:_.extend(_.clone(e.prototype.defaults),{model_class:"HistoryDatasetCollectionAssociation"}),initialize:function(a,b){e.prototype.initialize.call(this,a,b),c.initialize.call(this,a,b)},toString:function(){return["HistoryPairDatasetCollection(",this.get("name"),")"].join("")}}),i=f.extend(c).extend({defaults:_.extend(_.clone(f.prototype.defaults),{model_class:"HistoryDatasetCollectionAssociation"}),initialize:function(a,b){f.prototype.initialize.call(this,a,b),c.initialize.call(this,a,b)},toString:function(){return["HistoryListPairedDatasetCollection(",this.get("name"),")"].join("")}});return{HistoryListDatasetCollection:g,HistoryPairDatasetCollection:h,HistoryListPairedDatasetCollection:i}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/hdca-model.js.map
|
||||
@@ -1,133 +1,2 @@
|
||||
define([
|
||||
"mvc/dataset/states",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( STATES, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
/** How the type_id attribute is built for the history's mixed contents collection */
|
||||
var typeIdStr = function _typeIdStr( type, id ){
|
||||
return [ type, id ].join( '-' );
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** @class Mixin for HistoryContents content (HDAs, HDCAs).
|
||||
*/
|
||||
var HistoryContentMixin = {
|
||||
//TODO:?? into true Backbone.Model?
|
||||
|
||||
/** default attributes for a model */
|
||||
defaults : {
|
||||
/** parent (containing) history */
|
||||
history_id : null,
|
||||
/** some content_type (HistoryContents can contain mixed model classes) */
|
||||
history_content_type: null,
|
||||
/** indicating when/what order the content was generated in the context of the history */
|
||||
hid : null,
|
||||
/** whether the user wants the content shown (visible) */
|
||||
visible : true
|
||||
},
|
||||
|
||||
// ........................................................................ mixed content element
|
||||
//TODO: there's got to be a way to move this into HistoryContents - if we can do that, this class might not be needed
|
||||
// In order to be part of a MIXED bbone collection, we can't rely on the id
|
||||
// (which may collide btwn models of different classes)
|
||||
// Build a new id (type_id) that prefixes the history_content_type so the bbone collection can differentiate
|
||||
idAttribute : 'type_id',
|
||||
|
||||
/** override constructor to build type_id and insert into original attributes */
|
||||
constructor : function( attrs, options ){
|
||||
attrs.type_id = typeIdStr( attrs.history_content_type, attrs.id );
|
||||
this.debug( 'HistoryContentMixin.constructor:', attrs.type_id );
|
||||
Backbone.Model.apply( this, arguments );
|
||||
},
|
||||
|
||||
/** object level fn for building the type_id string */
|
||||
_typeIdStr : function(){
|
||||
return typeIdStr( this.get( 'history_content_type' ), this.get( 'id' ) );
|
||||
},
|
||||
|
||||
/** add listener to re-create type_id when the id changes */
|
||||
initialize : function( attrs, options ){
|
||||
this.on( 'change:id', this._createTypeId );
|
||||
},
|
||||
|
||||
/** set the type_id in the model attributes */
|
||||
_createTypeId : function(){
|
||||
this.set( 'type_id', this._typeIdStr() );
|
||||
},
|
||||
|
||||
// ........................................................................ common queries
|
||||
/** the more common alias of visible */
|
||||
hidden : function(){
|
||||
return !this.get( 'visible' );
|
||||
},
|
||||
|
||||
/** based on show_deleted, show_hidden (gen. from the container control),
|
||||
* would this ds show in the list of ds's?
|
||||
* @param {Boolean} show_deleted are we showing deleted hdas?
|
||||
* @param {Boolean} show_hidden are we showing hidden hdas?
|
||||
*/
|
||||
isVisible : function( show_deleted, show_hidden ){
|
||||
//TODO:?? Another unfortunate name collision
|
||||
var isVisible = true;
|
||||
if( ( !show_deleted )
|
||||
&& ( this.get( 'deleted' ) || this.get( 'purged' ) ) ){
|
||||
isVisible = false;
|
||||
}
|
||||
if( ( !show_hidden )
|
||||
&& ( !this.get( 'visible' ) ) ){
|
||||
isVisible = false;
|
||||
}
|
||||
return isVisible;
|
||||
},
|
||||
|
||||
// ........................................................................ ajax
|
||||
//TODO: global
|
||||
//TODO: these are probably better done on the leaf classes
|
||||
/** history content goes through the 'api/histories' API */
|
||||
urlRoot: galaxy_config.root + 'api/histories/',
|
||||
|
||||
/** full url spec. for this content */
|
||||
url : function(){
|
||||
var url = this.urlRoot + this.get( 'history_id' ) + '/contents/'
|
||||
+ this.get('history_content_type') + 's/' + this.get( 'id' );
|
||||
return url;
|
||||
},
|
||||
|
||||
/** save this content as not visible */
|
||||
hide : function( options ){
|
||||
if( !this.get( 'visible' ) ){ return jQuery.when(); }
|
||||
return this.save( { visible: false }, options );
|
||||
},
|
||||
/** save this content as visible */
|
||||
unhide : function( options ){
|
||||
if( this.get( 'visible' ) ){ return jQuery.when(); }
|
||||
return this.save( { visible: true }, options );
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
var nameAndId = this.get( 'id' ) || '';
|
||||
if( this.get( 'name' ) ){
|
||||
nameAndId = this.get( 'hid' ) + ' :"' + this.get( 'name' ) + '",' + nameAndId;
|
||||
}
|
||||
return 'HistoryContent(' + nameAndId + ')';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//TODO: needed?
|
||||
/** @class (Concrete/non-mixin) base model for content items.
|
||||
*/
|
||||
var HistoryContent = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend( HistoryContentMixin );
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
typeIdStr : typeIdStr,
|
||||
HistoryContentMixin : HistoryContentMixin,
|
||||
HistoryContent : HistoryContent
|
||||
};
|
||||
});
|
||||
define(["mvc/dataset/states","mvc/base-mvc","utils/localization"],function(a,b){var c=function(a,b){return[a,b].join("-")},d={defaults:{history_id:null,history_content_type:null,hid:null,visible:!0},idAttribute:"type_id",constructor:function(a){a.type_id=c(a.history_content_type,a.id),this.debug("HistoryContentMixin.constructor:",a.type_id),Backbone.Model.apply(this,arguments)},_typeIdStr:function(){return c(this.get("history_content_type"),this.get("id"))},initialize:function(){this.on("change:id",this._createTypeId)},_createTypeId:function(){this.set("type_id",this._typeIdStr())},hidden:function(){return!this.get("visible")},isVisible:function(a,b){var c=!0;return a||!this.get("deleted")&&!this.get("purged")||(c=!1),b||this.get("visible")||(c=!1),c},urlRoot:galaxy_config.root+"api/histories/",url:function(){var a=this.urlRoot+this.get("history_id")+"/contents/"+this.get("history_content_type")+"s/"+this.get("id");return a},hide:function(a){return this.get("visible")?this.save({visible:!1},a):jQuery.when()},unhide:function(a){return this.get("visible")?jQuery.when():this.save({visible:!0},a)},toString:function(){var a=this.get("id")||"";return this.get("name")&&(a=this.get("hid")+' :"'+this.get("name")+'",'+a),"HistoryContent("+a+")"}},e=Backbone.Model.extend(b.LoggableMixin).extend(d);return{typeIdStr:c,HistoryContentMixin:d,HistoryContent:e}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/history-content-model.js.map
|
||||
@@ -1,351 +1,2 @@
|
||||
define([
|
||||
"mvc/history/history-content-model",
|
||||
"mvc/history/hda-model",
|
||||
"mvc/history/hdca-model",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( HISTORY_CONTENT, HDA_MODEL, HDCA_MODEL, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
/** @class Backbone collection for history content.
|
||||
* NOTE: history content seems like a dataset collection, but differs in that it is mixed:
|
||||
* each element can be either an HDA (dataset) or a DatasetCollection and co-exist on
|
||||
* the same level.
|
||||
* Dataset collections on the other hand are not mixed and (so far) can only contain either
|
||||
* HDAs or child dataset collections on one level.
|
||||
* This is why this does not inherit from any of the DatasetCollections (currently).
|
||||
*/
|
||||
var HistoryContents = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
|
||||
/** @lends HistoryContents.prototype */{
|
||||
//TODO:?? may want to inherit from some MixedModelCollection
|
||||
//TODO:?? also consider inheriting from a 'DatasetList'
|
||||
//TODO: can we decorate the mixed models using the model fn below (instead of having them build their own type_id)?
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** since history content is a mix, override model fn into a factory, creating based on history_content_type */
|
||||
model : function( attrs, options ) {
|
||||
|
||||
//TODO: can we move the type_id stuff here?
|
||||
//attrs.type_id = typeIdStr( attrs );
|
||||
|
||||
if( attrs.history_content_type === "dataset" ) {
|
||||
return new HDA_MODEL.HistoryDatasetAssociation( attrs, options );
|
||||
|
||||
} else if( attrs.history_content_type === "dataset_collection" ) {
|
||||
switch( attrs.collection_type ){
|
||||
case 'list':
|
||||
return new HDCA_MODEL.HistoryListDatasetCollection( attrs, options );
|
||||
case 'paired':
|
||||
return new HDCA_MODEL.HistoryPairDatasetCollection( attrs, options );
|
||||
case 'list:paired':
|
||||
return new HDCA_MODEL.HistoryListPairedDatasetCollection( attrs, options );
|
||||
}
|
||||
throw new TypeError( 'Unknown collection_type: ' + attrs.collection_type );
|
||||
}
|
||||
// TODO: Handle unknown history_content_type...
|
||||
throw new TypeError( 'Unknown history_content_type: ' + attrs.history_content_type );
|
||||
},
|
||||
|
||||
/** Set up.
|
||||
* @see Backbone.Collection#initialize
|
||||
*/
|
||||
initialize : function( models, options ){
|
||||
options = options || {};
|
||||
//TODO: could probably use the contents.history_id instead
|
||||
this.historyId = options.historyId;
|
||||
//this._setUpListeners();
|
||||
|
||||
// backbonejs uses collection.model.prototype.idAttribute to determine if a model is *already* in a collection
|
||||
// and either merged or replaced. In this case, our 'model' is a function so we need to add idAttribute
|
||||
// manually here - if we don't, contents will not merge but be replaced/swapped.
|
||||
this.model.prototype.idAttribute = 'type_id';
|
||||
|
||||
this.on( 'all', function(){
|
||||
this.debug( this + '.event:', arguments );
|
||||
});
|
||||
},
|
||||
|
||||
/** root api url */
|
||||
urlRoot : galaxy_config.root + 'api/histories',
|
||||
/** complete api url */
|
||||
url : function(){
|
||||
return this.urlRoot + '/' + this.historyId + '/contents';
|
||||
},
|
||||
|
||||
// ........................................................................ common queries
|
||||
/** Get the ids of every item in this collection
|
||||
* @returns array of encoded ids
|
||||
*/
|
||||
ids : function(){
|
||||
//TODO: is this still useful since type_id
|
||||
return this.map( function( item ){ return item.get('id'); });
|
||||
},
|
||||
|
||||
/** Get contents that are not ready
|
||||
* @returns array of content models
|
||||
*/
|
||||
notReady : function(){
|
||||
return this.filter( function( content ){
|
||||
return !content.inReadyState();
|
||||
});
|
||||
},
|
||||
|
||||
/** Get the id of every model in this collection not in a 'ready' state (running).
|
||||
* @returns an array of model ids
|
||||
* @see HistoryDatasetAssociation#inReadyState
|
||||
*/
|
||||
running : function(){
|
||||
var idList = [];
|
||||
this.each( function( item ){
|
||||
var isRunning = !item.inReadyState();
|
||||
if( isRunning ){
|
||||
//TODO: is this still correct since type_id
|
||||
idList.push( item.get( 'id' ) );
|
||||
}
|
||||
});
|
||||
return idList;
|
||||
},
|
||||
|
||||
/** Get the model with the given hid
|
||||
* @param {Int} hid the hid to search for
|
||||
* @returns {HistoryDatasetAssociation} the model with the given hid or undefined if not found
|
||||
*/
|
||||
getByHid : function( hid ){
|
||||
return _.first( this.filter( function( content ){ return content.get( 'hid' ) === hid; }) );
|
||||
},
|
||||
|
||||
//TODO:?? this may belong in the containing view
|
||||
/** Get every 'shown' model in this collection based on show_deleted/hidden
|
||||
* @param {Boolean} show_deleted are we showing deleted content?
|
||||
* @param {Boolean} show_hidden are we showing hidden content?
|
||||
* @returns array of content models
|
||||
* @see HistoryDatasetAssociation#isVisible
|
||||
*/
|
||||
getVisible : function( show_deleted, show_hidden, filters ){
|
||||
filters = filters || [];
|
||||
//this.debug( 'filters:', filters );
|
||||
// always filter by show deleted/hidden first
|
||||
this.debug( 'checking isVisible' );
|
||||
var filteredHdas = new HistoryContents( this.filter( function( item ){
|
||||
return item.isVisible( show_deleted, show_hidden );
|
||||
}));
|
||||
|
||||
_.each( filters, function( filter_fn ){
|
||||
if( !_.isFunction( filter_fn ) ){ return; }
|
||||
filteredHdas = new HistoryContents( filteredHdas.filter( filter_fn ) );
|
||||
});
|
||||
return filteredHdas;
|
||||
},
|
||||
|
||||
/** return true if any contents don't have details */
|
||||
haveDetails : function(){
|
||||
return this.all( function( content ){ return content.hasDetails(); });
|
||||
},
|
||||
|
||||
// ........................................................................ ajax
|
||||
/** fetch detailed model data for all contents in this collection */
|
||||
fetchAllDetails : function( options ){
|
||||
options = options || {};
|
||||
var detailsFlag = { details: 'all' };
|
||||
options.data = ( options.data )?( _.extend( options.data, detailsFlag ) ):( detailsFlag );
|
||||
return this.fetch( options );
|
||||
},
|
||||
|
||||
/** using a queue, perform ajaxFn on each of the models in this collection */
|
||||
ajaxQueue : function( ajaxFn, options ){
|
||||
var deferred = jQuery.Deferred(),
|
||||
startingLength = this.length,
|
||||
responses = [];
|
||||
|
||||
if( !startingLength ){
|
||||
deferred.resolve([]);
|
||||
return deferred;
|
||||
}
|
||||
|
||||
// use reverse order (stylistic choice)
|
||||
var ajaxFns = this.chain().reverse().map( function( content, i ){
|
||||
return function(){
|
||||
var xhr = ajaxFn.call( content, options );
|
||||
// if successful, notify using the deferred to allow tracking progress
|
||||
xhr.done( function( response ){
|
||||
deferred.notify({ curr: i, total: startingLength, response: response, model: content });
|
||||
});
|
||||
// (regardless of previous error or success) if not last ajax call, shift and call the next
|
||||
// if last fn, resolve deferred
|
||||
xhr.always( function( response ){
|
||||
responses.push( response );
|
||||
if( ajaxFns.length ){
|
||||
ajaxFns.shift()();
|
||||
} else {
|
||||
deferred.resolve( responses );
|
||||
}
|
||||
});
|
||||
};
|
||||
}).value();
|
||||
// start the queue
|
||||
ajaxFns.shift()();
|
||||
|
||||
return deferred;
|
||||
},
|
||||
|
||||
isCopyable : function( contentsJSON ){
|
||||
var copyableModelClasses = [
|
||||
'HistoryDatasetAssociation',
|
||||
'HistoryDatasetCollectionAssociation'
|
||||
];
|
||||
return ( ( _.isObject( contentsJSON ) && contentsJSON.id )
|
||||
&& ( _.contains( copyableModelClasses, contentsJSON.model_class ) ) );
|
||||
},
|
||||
|
||||
/** copy an existing, accessible hda into this collection */
|
||||
copy : function( json ){
|
||||
var id, type, contentType;
|
||||
if( _.isString( json ) ){
|
||||
id = json;
|
||||
contentType = 'hda';
|
||||
type = 'dataset';
|
||||
} else {
|
||||
id = json.id;
|
||||
contentType = ({
|
||||
'HistoryDatasetAssociation' : 'hda',
|
||||
'LibraryDatasetDatasetAssociation' : 'ldda',
|
||||
'HistoryDatasetCollectionAssociation' : 'hdca'
|
||||
})[ json.model_class ] || 'hda';
|
||||
type = ( contentType === 'hdca'? 'dataset_collection' : 'dataset' );
|
||||
}
|
||||
var collection = this,
|
||||
xhr = jQuery.post( this.url(), {
|
||||
content : id,
|
||||
source : contentType,
|
||||
type : type
|
||||
})
|
||||
.done( function( json ){
|
||||
collection.add([ json ]);
|
||||
})
|
||||
.fail( function( error, status, message ){
|
||||
collection.trigger( 'error', collection, xhr, {},
|
||||
'Error copying contents', { type: type, id: id, source: contentType });
|
||||
});
|
||||
return xhr;
|
||||
},
|
||||
|
||||
// ........................................................................ sorting/filtering
|
||||
/** return a new collection of contents whose attributes contain the substring matchesWhat */
|
||||
matches : function( matchesWhat ){
|
||||
return this.filter( function( content ){
|
||||
return content.matches( matchesWhat );
|
||||
});
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
/** override to get a correct/smarter merge when incoming data is partial */
|
||||
set : function( models, options ){
|
||||
_.each( models, function( model ){
|
||||
console.debug( 'type_id:', model.type_id )
|
||||
if( !model.type_id || !model.get( 'type_id' ) ){
|
||||
model.type_id = HISTORY_CONTENT.typeIdStr( model.history_content_type, model.id );
|
||||
}
|
||||
});
|
||||
Backbone.Collection.prototype.set.call( this, models, options );
|
||||
},
|
||||
|
||||
/** Convert this ad-hoc collection of hdas to a formal collection tracked
|
||||
by the server.
|
||||
**/
|
||||
promoteToHistoryDatasetCollection : function _promote( history, collection_type, options ){
|
||||
//TODO: seems like this would be better in mvc/collections
|
||||
options = options || {};
|
||||
options.url = this.url();
|
||||
options.type = "POST";
|
||||
var full_collection_type = collection_type;
|
||||
var element_identifiers = [],
|
||||
name = null;
|
||||
|
||||
// This mechanism is rough - no error handling, allows invalid selections, no way
|
||||
// for user to pick/override element identifiers. This is only really meant
|
||||
if( collection_type === "list" ) {
|
||||
this.chain().each( function( hda ) {
|
||||
// TODO: Handle duplicate names.
|
||||
var name = hda.attributes.name;
|
||||
var id = hda.get('id');
|
||||
var content_type = hda.attributes.history_content_type;
|
||||
if( content_type === "dataset" ) {
|
||||
if( full_collection_type !== "list" ) {
|
||||
this.log( "Invalid collection type" );
|
||||
}
|
||||
element_identifiers.push( { name: name, src: "hda", id: id } );
|
||||
} else {
|
||||
if( full_collection_type === "list" ) {
|
||||
full_collection_type = "list:" + hda.attributes.collection_type;
|
||||
} else {
|
||||
if( full_collection_type !== "list:" + hda.attributes.collection_type ) {
|
||||
this.log( "Invalid collection type" );
|
||||
}
|
||||
}
|
||||
element_identifiers.push( { name: name, src: "hdca", id: id } );
|
||||
}
|
||||
});
|
||||
name = "New Dataset List";
|
||||
} else if( collection_type === "paired" ) {
|
||||
var ids = this.ids();
|
||||
if( ids.length !== 2 ){
|
||||
// TODO: Do something...
|
||||
}
|
||||
element_identifiers.push( { name: "forward", src: "hda", id: ids[ 0 ] } );
|
||||
element_identifiers.push( { name: "reverse", src: "hda", id: ids[ 1 ] } );
|
||||
name = "New Dataset Pair";
|
||||
}
|
||||
options.data = {
|
||||
type: "dataset_collection",
|
||||
name: name,
|
||||
collection_type: full_collection_type,
|
||||
element_identifiers: JSON.stringify( element_identifiers )
|
||||
};
|
||||
|
||||
var xhr = jQuery.ajax( options );
|
||||
xhr.done( function( message, status, responseObj ){
|
||||
history.refresh( );
|
||||
});
|
||||
xhr.fail( function( xhr, status, message ){
|
||||
if( xhr.responseJSON && xhr.responseJSON.error ){
|
||||
error = xhr.responseJSON.error;
|
||||
} else {
|
||||
error = xhr.responseJSON;
|
||||
}
|
||||
xhr.responseText = error;
|
||||
// Do something?
|
||||
});
|
||||
return xhr;
|
||||
},
|
||||
|
||||
/** In this override, copy the historyId to the clone */
|
||||
clone : function(){
|
||||
var clone = Backbone.Collection.prototype.clone.call( this );
|
||||
clone.historyId = this.historyId;
|
||||
return clone;
|
||||
},
|
||||
|
||||
/** debugging */
|
||||
print : function(){
|
||||
var contents = this;
|
||||
contents.each( function( c ){
|
||||
contents.debug( c );
|
||||
if( c.elements ){
|
||||
contents.debug( '\t elements:', c.elements );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'HistoryContents(', [ this.historyId, this.length ].join(), ')' ].join( '' ));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
HistoryContents : HistoryContents
|
||||
};
|
||||
});
|
||||
define(["mvc/history/history-content-model","mvc/history/hda-model","mvc/history/hdca-model","mvc/base-mvc","utils/localization"],function(a,b,c,d){var e=Backbone.Collection.extend(d.LoggableMixin).extend({model:function(a,d){if("dataset"===a.history_content_type)return new b.HistoryDatasetAssociation(a,d);if("dataset_collection"===a.history_content_type){switch(a.collection_type){case"list":return new c.HistoryListDatasetCollection(a,d);case"paired":return new c.HistoryPairDatasetCollection(a,d);case"list:paired":return new c.HistoryListPairedDatasetCollection(a,d)}throw new TypeError("Unknown collection_type: "+a.collection_type)}throw new TypeError("Unknown history_content_type: "+a.history_content_type)},initialize:function(a,b){b=b||{},this.historyId=b.historyId,this.model.prototype.idAttribute="type_id",this.on("all",function(){this.debug(this+".event:",arguments)})},urlRoot:galaxy_config.root+"api/histories",url:function(){return this.urlRoot+"/"+this.historyId+"/contents"},ids:function(){return this.map(function(a){return a.get("id")})},notReady:function(){return this.filter(function(a){return!a.inReadyState()})},running:function(){var a=[];return this.each(function(b){var c=!b.inReadyState();c&&a.push(b.get("id"))}),a},getByHid:function(a){return _.first(this.filter(function(b){return b.get("hid")===a}))},getVisible:function(a,b,c){c=c||[],this.debug("checking isVisible");var d=new e(this.filter(function(c){return c.isVisible(a,b)}));return _.each(c,function(a){_.isFunction(a)&&(d=new e(d.filter(a)))}),d},haveDetails:function(){return this.all(function(a){return a.hasDetails()})},fetchAllDetails:function(a){a=a||{};var b={details:"all"};return a.data=a.data?_.extend(a.data,b):b,this.fetch(a)},ajaxQueue:function(a,b){var c=jQuery.Deferred(),d=this.length,e=[];if(!d)return c.resolve([]),c;var f=this.chain().reverse().map(function(g,h){return function(){var i=a.call(g,b);i.done(function(a){c.notify({curr:h,total:d,response:a,model:g})}),i.always(function(a){e.push(a),f.length?f.shift()():c.resolve(e)})}}).value();return f.shift()(),c},isCopyable:function(a){var b=["HistoryDatasetAssociation","HistoryDatasetCollectionAssociation"];return _.isObject(a)&&a.id&&_.contains(b,a.model_class)},copy:function(a){var b,c,d;_.isString(a)?(b=a,d="hda",c="dataset"):(b=a.id,d={HistoryDatasetAssociation:"hda",LibraryDatasetDatasetAssociation:"ldda",HistoryDatasetCollectionAssociation:"hdca"}[a.model_class]||"hda",c="hdca"===d?"dataset_collection":"dataset");var e=this,f=jQuery.post(this.url(),{content:b,source:d,type:c}).done(function(a){e.add([a])}).fail(function(){e.trigger("error",e,f,{},"Error copying contents",{type:c,id:b,source:d})});return f},matches:function(a){return this.filter(function(b){return b.matches(a)})},set:function(b,c){_.each(b,function(b){b.type_id&&b.get("type_id")||(b.type_id=a.typeIdStr(b.history_content_type,b.id))}),Backbone.Collection.prototype.set.call(this,b,c)},promoteToHistoryDatasetCollection:function(a,b,c){c=c||{},c.url=this.url(),c.type="POST";var d=b,e=[],f=null;if("list"===b)this.chain().each(function(a){var b=a.attributes.name,c=a.get("id"),f=a.attributes.history_content_type;"dataset"===f?("list"!==d&&this.log("Invalid collection type"),e.push({name:b,src:"hda",id:c})):("list"===d?d="list:"+a.attributes.collection_type:d!=="list:"+a.attributes.collection_type&&this.log("Invalid collection type"),e.push({name:b,src:"hdca",id:c}))}),f="New Dataset List";else if("paired"===b){var g=this.ids();2!==g.length,e.push({name:"forward",src:"hda",id:g[0]}),e.push({name:"reverse",src:"hda",id:g[1]}),f="New Dataset Pair"}c.data={type:"dataset_collection",name:f,collection_type:d,element_identifiers:JSON.stringify(e)};var h=jQuery.ajax(c);return h.done(function(){a.refresh()}),h.fail(function(a){error=a.responseJSON&&a.responseJSON.error?a.responseJSON.error:a.responseJSON,a.responseText=error}),h},clone:function(){var a=Backbone.Collection.prototype.clone.call(this);return a.historyId=this.historyId,a},print:function(){var a=this;a.each(function(b){a.debug(b),b.elements&&a.debug(" elements:",b.elements)})},toString:function(){return["HistoryContents(",[this.historyId,this.length].join(),")"].join("")}});return{HistoryContents:e}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/history-contents.js.map
|
||||
@@ -1,422 +1,2 @@
|
||||
define([
|
||||
"mvc/history/history-contents",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( HISTORY_CONTENTS, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
/** @class Model for a Galaxy history resource - both a record of user
|
||||
* tool use and a collection of the datasets those tools produced.
|
||||
* @name History
|
||||
*
|
||||
* @augments Backbone.Model
|
||||
* @borrows LoggableMixin#logger as #logger
|
||||
* @borrows LoggableMixin#log as #log
|
||||
* @constructs
|
||||
*/
|
||||
var History = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
|
||||
BASE_MVC.mixin( BASE_MVC.SearchableModelMixin, /** @lends History.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
// values from api (may need more)
|
||||
defaults : {
|
||||
model_class : 'History',
|
||||
id : null,
|
||||
name : 'Unnamed History',
|
||||
state : 'new',
|
||||
|
||||
diskSize : 0,
|
||||
deleted : false
|
||||
},
|
||||
|
||||
// ........................................................................ urls
|
||||
urlRoot: galaxy_config.root + 'api/histories',
|
||||
|
||||
// ........................................................................ set up/tear down
|
||||
/** Set up the model
|
||||
* @param {Object} historyJSON model data for this History
|
||||
* @param {Object[]} contentsJSON array of model data for this History's contents (hdas or collections)
|
||||
* @param {Object} options any extra settings including logger
|
||||
*/
|
||||
initialize : function( historyJSON, contentsJSON, options ){
|
||||
options = options || {};
|
||||
this.logger = options.logger || null;
|
||||
this.log( this + ".initialize:", historyJSON, contentsJSON, options );
|
||||
|
||||
/** HistoryContents collection of the HDAs contained in this history. */
|
||||
this.log( 'creating history contents:', contentsJSON );
|
||||
this.contents = new HISTORY_CONTENTS.HistoryContents( contentsJSON || [], { historyId: this.get( 'id' )});
|
||||
//// if we've got hdas passed in the constructor, load them
|
||||
//if( contentsJSON && _.isArray( contentsJSON ) ){
|
||||
// this.log( 'resetting history contents:', contentsJSON );
|
||||
// this.contents.reset( contentsJSON );
|
||||
//}
|
||||
|
||||
this._setUpListeners();
|
||||
|
||||
/** cached timeout id for the dataset updater */
|
||||
this.updateTimeoutId = null;
|
||||
// set up update timeout if needed
|
||||
//this.checkForUpdates();
|
||||
},
|
||||
|
||||
/** set up any event listeners for this history including those to the contained HDAs
|
||||
* events: error:contents if an error occurred with the contents collection
|
||||
*/
|
||||
_setUpListeners : function(){
|
||||
this.on( 'error', function( model, xhr, options, msg, details ){
|
||||
this.errorHandler( model, xhr, options, msg, details );
|
||||
});
|
||||
|
||||
// hda collection listening
|
||||
if( this.contents ){
|
||||
this.listenTo( this.contents, 'error', function(){
|
||||
this.trigger.apply( this, [ 'error:contents' ].concat( jQuery.makeArray( arguments ) ) );
|
||||
});
|
||||
}
|
||||
// if the model's id changes ('current' or null -> an actual id), update the contents history_id
|
||||
this.on( 'change:id', function( model, newId ){
|
||||
if( this.contents ){
|
||||
this.contents.historyId = newId;
|
||||
}
|
||||
}, this );
|
||||
},
|
||||
|
||||
//TODO: see base-mvc
|
||||
//onFree : function(){
|
||||
// if( this.contents ){
|
||||
// this.contents.free();
|
||||
// }
|
||||
//},
|
||||
|
||||
/** event listener for errors. Generally errors are handled outside this model */
|
||||
errorHandler : function( model, xhr, options, msg, details ){
|
||||
// clear update timeout on model err
|
||||
this.clearUpdateTimeout();
|
||||
},
|
||||
|
||||
// ........................................................................ common queries
|
||||
/** T/F is this history owned by the current user (Galaxy.currUser)
|
||||
* Note: that this will return false for an anon user even if the history is theirs.
|
||||
*/
|
||||
ownedByCurrUser : function(){
|
||||
// no currUser
|
||||
if( !Galaxy || !Galaxy.currUser ){
|
||||
return false;
|
||||
}
|
||||
// user is anon or history isn't owned
|
||||
if( Galaxy.currUser.isAnonymous() || Galaxy.currUser.id !== this.get( 'user_id' ) ){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/** */
|
||||
contentsCount : function(){
|
||||
return _.reduce( _.values( this.get( 'state_details' ) ), function( memo, num ){ return memo + num; }, 0 );
|
||||
},
|
||||
|
||||
// ........................................................................ search
|
||||
/** What model fields to search with */
|
||||
searchAttributes : [
|
||||
'name', 'annotation', 'tags'
|
||||
],
|
||||
|
||||
/** Adding title and singular tag */
|
||||
searchAliases : {
|
||||
title : 'name',
|
||||
tag : 'tags'
|
||||
},
|
||||
|
||||
// ........................................................................ updates
|
||||
/** does the contents collection indicate they're still running and need to be updated later?
|
||||
* delay + update if needed
|
||||
* @param {Function} onReadyCallback function to run when all contents are in the ready state
|
||||
* events: ready
|
||||
*/
|
||||
checkForUpdates : function( onReadyCallback ){
|
||||
//this.info( 'checkForUpdates' )
|
||||
|
||||
// get overall History state from collection, run updater if History has running/queued contents
|
||||
// boiling it down on the client to running/not
|
||||
if( this.contents.running().length ){
|
||||
this.setUpdateTimeout();
|
||||
|
||||
} else {
|
||||
this.trigger( 'ready' );
|
||||
if( _.isFunction( onReadyCallback ) ){
|
||||
onReadyCallback.call( this );
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
/** create a timeout (after UPDATE_DELAY or delay ms) to refetch the contents. Clear any prev. timeout */
|
||||
setUpdateTimeout : function( delay ){
|
||||
delay = delay || History.UPDATE_DELAY;
|
||||
var history = this;
|
||||
|
||||
// prevent buildup of updater timeouts by clearing previous if any, then set new and cache id
|
||||
this.clearUpdateTimeout();
|
||||
this.updateTimeoutId = setTimeout( function(){
|
||||
history.refresh();
|
||||
}, delay );
|
||||
return this.updateTimeoutId;
|
||||
},
|
||||
|
||||
/** clear the timeout and the cached timeout id */
|
||||
clearUpdateTimeout : function(){
|
||||
if( this.updateTimeoutId ){
|
||||
clearTimeout( this.updateTimeoutId );
|
||||
this.updateTimeoutId = null;
|
||||
}
|
||||
},
|
||||
|
||||
/* update the contents, getting full detailed model data for any whose id is in detailIds
|
||||
* set up to run this again in some interval of time
|
||||
* @param {String[]} detailIds list of content ids to get detailed model data for
|
||||
* @param {Object} options std. backbone fetch options map
|
||||
*/
|
||||
refresh : function( detailIds, options ){
|
||||
//this.info( 'refresh:', detailIds, this.contents );
|
||||
detailIds = detailIds || [];
|
||||
options = options || {};
|
||||
var history = this;
|
||||
|
||||
// add detailIds to options as CSV string
|
||||
options.data = options.data || {};
|
||||
if( detailIds.length ){
|
||||
options.data.details = detailIds.join( ',' );
|
||||
}
|
||||
var xhr = this.contents.fetch( options );
|
||||
xhr.done( function( models ){
|
||||
history.checkForUpdates( function(){
|
||||
// fetch the history inside onReadyCallback in order to recalc history size
|
||||
this.fetch();
|
||||
});
|
||||
});
|
||||
return xhr;
|
||||
},
|
||||
|
||||
// ........................................................................ ajax
|
||||
/** save this history, _Mark_ing it as deleted (just a flag) */
|
||||
_delete : function( options ){
|
||||
if( this.get( 'deleted' ) ){ return jQuery.when(); }
|
||||
return this.save( { deleted: true }, options );
|
||||
},
|
||||
/** purge this history, _Mark_ing it as purged and removing all dataset data from the server */
|
||||
purge : function( options ){
|
||||
if( this.get( 'purged' ) ){ return jQuery.when(); }
|
||||
return this.save( { deleted: true, purged: true }, options );
|
||||
},
|
||||
/** save this history, _Mark_ing it as undeleted */
|
||||
undelete : function( options ){
|
||||
if( !this.get( 'deleted' ) ){ return jQuery.when(); }
|
||||
return this.save( { deleted: false }, options );
|
||||
},
|
||||
|
||||
/** Make a copy of this history on the server
|
||||
* @param {Boolean} current if true, set the copy as the new current history (default: true)
|
||||
* @param {String} name name of new history (default: none - server sets to: Copy of <current name>)
|
||||
* @fires copied passed this history and the response JSON from the copy
|
||||
* @returns {xhr}
|
||||
*/
|
||||
copy : function( current, name ){
|
||||
current = ( current !== undefined )?( current ):( true );
|
||||
if( !this.id ){
|
||||
throw new Error( 'You must set the history ID before copying it.' );
|
||||
}
|
||||
|
||||
var postData = { history_id : this.id };
|
||||
if( current ){
|
||||
postData.current = true;
|
||||
}
|
||||
if( name ){
|
||||
postData.name = name;
|
||||
}
|
||||
|
||||
//TODO:?? all datasets?
|
||||
|
||||
var history = this,
|
||||
copy = jQuery.post( this.urlRoot, postData );
|
||||
// if current - queue to setAsCurrent before firing 'copied'
|
||||
if( current ){
|
||||
return copy.then( function( response ){
|
||||
var newHistory = new History( response );
|
||||
return newHistory.setAsCurrent()
|
||||
.done( function(){
|
||||
history.trigger( 'copied', history, response );
|
||||
});
|
||||
});
|
||||
}
|
||||
return copy.done( function( response ){
|
||||
history.trigger( 'copied', history, response );
|
||||
});
|
||||
},
|
||||
|
||||
setAsCurrent : function(){
|
||||
var history = this,
|
||||
xhr = jQuery.getJSON( '/history/set_as_current?id=' + this.id );
|
||||
|
||||
xhr.done( function(){
|
||||
history.trigger( 'set-as-current', history );
|
||||
});
|
||||
return xhr;
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
toString : function(){
|
||||
return 'History(' + this.get( 'id' ) + ',' + this.get( 'name' ) + ')';
|
||||
}
|
||||
}));
|
||||
|
||||
//------------------------------------------------------------------------------ CLASS VARS
|
||||
/** When the history has running hdas,
|
||||
* this is the amount of time between update checks from the server
|
||||
*/
|
||||
History.UPDATE_DELAY = 4000;
|
||||
|
||||
/** Get data for a history then its hdas using a sequential ajax call, return a deferred to receive both */
|
||||
History.getHistoryData = function getHistoryData( historyId, options ){
|
||||
options = options || {};
|
||||
var detailIdsFn = options.detailIdsFn || [];
|
||||
var hdcaDetailIds = options.hdcaDetailIds || [];
|
||||
//console.debug( 'getHistoryData:', historyId, options );
|
||||
|
||||
var df = jQuery.Deferred(),
|
||||
historyJSON = null;
|
||||
|
||||
function getHistory( id ){
|
||||
// get the history data
|
||||
if( historyId === 'current' ){
|
||||
return jQuery.getJSON( galaxy_config.root + 'history/current_history_json' );
|
||||
}
|
||||
return jQuery.ajax( galaxy_config.root + 'api/histories/' + historyId );
|
||||
}
|
||||
function isEmpty( historyData ){
|
||||
// get the number of hdas accrd. to the history
|
||||
return historyData && historyData.empty;
|
||||
}
|
||||
function getContents( historyData ){
|
||||
// get the hda data
|
||||
// if no hdas accrd. to history: return empty immed.
|
||||
if( isEmpty( historyData ) ){ return []; }
|
||||
// if there are hdas accrd. to history: get those as well
|
||||
if( _.isFunction( detailIdsFn ) ){
|
||||
detailIdsFn = detailIdsFn( historyData );
|
||||
}
|
||||
if( _.isFunction( hdcaDetailIds ) ){
|
||||
hdcaDetailIds = hdcaDetailIds( historyData );
|
||||
}
|
||||
var data = {};
|
||||
if( detailIdsFn.length ) {
|
||||
data.dataset_details = detailIdsFn.join( ',' );
|
||||
}
|
||||
if( hdcaDetailIds.length ) {
|
||||
// for symmetry, not actually used by backend of consumed
|
||||
// by frontend.
|
||||
data.dataset_collection_details = hdcaDetailIds.join( ',' );
|
||||
}
|
||||
return jQuery.ajax( galaxy_config.root + 'api/histories/' + historyData.id + '/contents', { data: data });
|
||||
}
|
||||
|
||||
// getting these concurrently is 400% slower (sqlite, local, vanilla) - so:
|
||||
// chain the api calls - getting history first then contents
|
||||
|
||||
var historyFn = options.historyFn || getHistory,
|
||||
contentsFn = options.contentsFn || getContents;
|
||||
|
||||
// chain ajax calls: get history first, then hdas
|
||||
var historyXHR = historyFn( historyId );
|
||||
historyXHR.done( function( json ){
|
||||
// set outer scope var here for use below
|
||||
historyJSON = json;
|
||||
df.notify({ status: 'history data retrieved', historyJSON: historyJSON });
|
||||
});
|
||||
historyXHR.fail( function( xhr, status, message ){
|
||||
// call reject on the outer deferred to allow its fail callback to run
|
||||
df.reject( xhr, 'loading the history' );
|
||||
});
|
||||
|
||||
var contentsXHR = historyXHR.then( contentsFn );
|
||||
contentsXHR.then( function( contentsJSON ){
|
||||
df.notify({ status: 'contents data retrieved', historyJSON: historyJSON, contentsJSON: contentsJSON });
|
||||
// we've got both: resolve the outer scope deferred
|
||||
df.resolve( historyJSON, contentsJSON );
|
||||
});
|
||||
contentsXHR.fail( function( xhr, status, message ){
|
||||
// call reject on the outer deferred to allow its fail callback to run
|
||||
df.reject( xhr, 'loading the contents', { history: historyJSON } );
|
||||
});
|
||||
|
||||
return df;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class A collection of histories (per user).
|
||||
* (stub) currently unused.
|
||||
*/
|
||||
var HistoryCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
|
||||
/** @lends HistoryCollection.prototype */{
|
||||
model : History,
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
urlRoot : ( window.galaxy_config? galaxy_config.root : '/' ) + 'api/histories',
|
||||
//url : function(){ return this.urlRoot; },
|
||||
|
||||
initialize : function( models, options ){
|
||||
options = options || {};
|
||||
this.log( 'HistoryCollection.initialize', arguments );
|
||||
this.includeDeleted = options.includeDeleted || false;
|
||||
|
||||
//this.on( 'all', function(){
|
||||
// console.info( 'event:', arguments );
|
||||
//});
|
||||
|
||||
this.setUpListeners();
|
||||
},
|
||||
|
||||
setUpListeners : function setUpListeners(){
|
||||
var collection = this;
|
||||
|
||||
// when a history is deleted, remove it from the collection (if optionally set to do so)
|
||||
this.on( 'change:deleted', function( history ){
|
||||
this.debug( 'change:deleted', collection.includeDeleted, history.get( 'deleted' ) );
|
||||
if( !collection.includeDeleted && history.get( 'deleted' ) ){
|
||||
collection.remove( history );
|
||||
}
|
||||
});
|
||||
|
||||
// listen for a history copy, adding it to the beginning of the collection
|
||||
this.on( 'copied', function( original, newData ){
|
||||
this.unshift( new History( newData, [] ) );
|
||||
});
|
||||
},
|
||||
|
||||
create : function create( data, hdas, historyOptions, xhrOptions ){
|
||||
var collection = this,
|
||||
xhr = jQuery.getJSON( galaxy_config.root + 'history/create_new_current' );
|
||||
return xhr.done( function( newData ){
|
||||
var history = new History( newData, [], historyOptions || {} );
|
||||
// new histories go in the front
|
||||
//TODO: (implicit ordering by update time...)
|
||||
collection.unshift( history );
|
||||
collection.trigger( 'new-current' );
|
||||
});
|
||||
//TODO: move back to using history.save (via Deferred.then w/ set_as_current)
|
||||
},
|
||||
|
||||
toString: function toString(){
|
||||
return 'HistoryCollection(' + this.length + ')';
|
||||
}
|
||||
});
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
History : History,
|
||||
HistoryCollection : HistoryCollection
|
||||
};});
|
||||
define(["mvc/history/history-contents","mvc/base-mvc","utils/localization"],function(a,b){var c=Backbone.Model.extend(b.LoggableMixin).extend(b.mixin(b.SearchableModelMixin,{defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:!1},urlRoot:galaxy_config.root+"api/histories",initialize:function(b,c,d){d=d||{},this.logger=d.logger||null,this.log(this+".initialize:",b,c,d),this.log("creating history contents:",c),this.contents=new a.HistoryContents(c||[],{historyId:this.get("id")}),this._setUpListeners(),this.updateTimeoutId=null},_setUpListeners:function(){this.on("error",function(a,b,c,d,e){this.errorHandler(a,b,c,d,e)}),this.contents&&this.listenTo(this.contents,"error",function(){this.trigger.apply(this,["error:contents"].concat(jQuery.makeArray(arguments)))}),this.on("change:id",function(a,b){this.contents&&(this.contents.historyId=b)},this)},errorHandler:function(){this.clearUpdateTimeout()},ownedByCurrUser:function(){return Galaxy&&Galaxy.currUser?Galaxy.currUser.isAnonymous()||Galaxy.currUser.id!==this.get("user_id")?!1:!0:!1},contentsCount:function(){return _.reduce(_.values(this.get("state_details")),function(a,b){return a+b},0)},searchAttributes:["name","annotation","tags"],searchAliases:{title:"name",tag:"tags"},checkForUpdates:function(a){return this.contents.running().length?this.setUpdateTimeout():(this.trigger("ready"),_.isFunction(a)&&a.call(this)),this},setUpdateTimeout:function(a){a=a||c.UPDATE_DELAY;var b=this;return this.clearUpdateTimeout(),this.updateTimeoutId=setTimeout(function(){b.refresh()},a),this.updateTimeoutId},clearUpdateTimeout:function(){this.updateTimeoutId&&(clearTimeout(this.updateTimeoutId),this.updateTimeoutId=null)},refresh:function(a,b){a=a||[],b=b||{};var c=this;b.data=b.data||{},a.length&&(b.data.details=a.join(","));var d=this.contents.fetch(b);return d.done(function(){c.checkForUpdates(function(){this.fetch()})}),d},_delete:function(a){return this.get("deleted")?jQuery.when():this.save({deleted:!0},a)},purge:function(a){return this.get("purged")?jQuery.when():this.save({deleted:!0,purged:!0},a)},undelete:function(a){return this.get("deleted")?this.save({deleted:!1},a):jQuery.when()},copy:function(a,b){if(a=void 0!==a?a:!0,!this.id)throw new Error("You must set the history ID before copying it.");var d={history_id:this.id};a&&(d.current=!0),b&&(d.name=b);var e=this,f=jQuery.post(this.urlRoot,d);return a?f.then(function(a){var b=new c(a);return b.setAsCurrent().done(function(){e.trigger("copied",e,a)})}):f.done(function(a){e.trigger("copied",e,a)})},setAsCurrent:function(){var a=this,b=jQuery.getJSON("/history/set_as_current?id="+this.id);return b.done(function(){a.trigger("set-as-current",a)}),b},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}}));c.UPDATE_DELAY=4e3,c.getHistoryData=function(a,b){function c(){return"current"===a?jQuery.getJSON(galaxy_config.root+"history/current_history_json"):jQuery.ajax(galaxy_config.root+"api/histories/"+a)}function d(a){return a&&a.empty}function e(a){if(d(a))return[];_.isFunction(f)&&(f=f(a)),_.isFunction(g)&&(g=g(a));var b={};return f.length&&(b.dataset_details=f.join(",")),g.length&&(b.dataset_collection_details=g.join(",")),jQuery.ajax(galaxy_config.root+"api/histories/"+a.id+"/contents",{data:b})}b=b||{};var f=b.detailIdsFn||[],g=b.hdcaDetailIds||[],h=jQuery.Deferred(),i=null,j=b.historyFn||c,k=b.contentsFn||e,l=j(a);l.done(function(a){i=a,h.notify({status:"history data retrieved",historyJSON:i})}),l.fail(function(a){h.reject(a,"loading the history")});var m=l.then(k);return m.then(function(a){h.notify({status:"contents data retrieved",historyJSON:i,contentsJSON:a}),h.resolve(i,a)}),m.fail(function(a){h.reject(a,"loading the contents",{history:i})}),h};var d=Backbone.Collection.extend(b.LoggableMixin).extend({model:c,urlRoot:(window.galaxy_config?galaxy_config.root:"/")+"api/histories",initialize:function(a,b){b=b||{},this.log("HistoryCollection.initialize",arguments),this.includeDeleted=b.includeDeleted||!1,this.setUpListeners()},setUpListeners:function(){var a=this;this.on("change:deleted",function(b){this.debug("change:deleted",a.includeDeleted,b.get("deleted")),!a.includeDeleted&&b.get("deleted")&&a.remove(b)}),this.on("copied",function(a,b){this.unshift(new c(b,[]))})},create:function(a,b,d){var e=this,f=jQuery.getJSON(galaxy_config.root+"history/create_new_current");return f.done(function(a){var b=new c(a,[],d||{});e.unshift(b),e.trigger("new-current")})},toString:function(){return"HistoryCollection("+this.length+")"}});return{History:c,HistoryCollection:d}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/history-model.js.map
|
||||
@@ -1,114 +1,2 @@
|
||||
define([
|
||||
"mvc/history/history-panel",
|
||||
"mvc/history/hda-li",
|
||||
"mvc/history/hdca-li",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( HPANEL, HDA_LI, HDCA_LI, BASE_MVC, _l ){
|
||||
/* =============================================================================
|
||||
TODO:
|
||||
|
||||
============================================================================= */
|
||||
var _super = HPANEL.HistoryPanel;
|
||||
// used in history/display.mako and history/embed.mako
|
||||
/** @class View/Controller for a tabular view of the history model.
|
||||
*
|
||||
* As ReadOnlyHistoryPanel, but with:
|
||||
* history annotation always shown
|
||||
* datasets displayed in a table:
|
||||
* datasets in left cells, dataset annotations in the right
|
||||
*/
|
||||
var AnnotatedHistoryPanel = _super.extend(
|
||||
/** @lends AnnotatedHistoryPanel.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
className : _super.prototype.className + ' annotated-history-panel',
|
||||
|
||||
// ------------------------------------------------------------------------ panel rendering
|
||||
/** In this override, add the history annotation
|
||||
*/
|
||||
_buildNewRender : function(){
|
||||
//TODO: shouldn't this display regardless (on all non-current panels)?
|
||||
var $newRender = _super.prototype._buildNewRender.call( this );
|
||||
this.renderHistoryAnnotation( $newRender );
|
||||
return $newRender;
|
||||
},
|
||||
|
||||
/** render the history's annotation as its own field */
|
||||
renderHistoryAnnotation : function( $newRender ){
|
||||
var annotation = this.model.get( 'annotation' );
|
||||
if( !annotation ){ return; }
|
||||
$newRender.find( '.controls .annotation-display' ).text( annotation );
|
||||
},
|
||||
|
||||
/** In this override, convert the list-items tag to a table
|
||||
* and add table header cells to indicate the dataset, annotation columns
|
||||
*/
|
||||
renderItems : function( $whereTo ){
|
||||
$whereTo = $whereTo || this.$el;
|
||||
|
||||
// convert to table
|
||||
$whereTo.find( '.list-items' )
|
||||
.replaceWith( $( '<table/>' ).addClass( 'list-items' ) );
|
||||
|
||||
// render rows/contents and prepend headers
|
||||
var views = _super.prototype.renderItems.call( this, $whereTo );
|
||||
this.$list( $whereTo )
|
||||
.prepend( $( '<tr/>' ).addClass( 'headers' ).append([
|
||||
$( '<th/>' ).text( _l( 'Dataset' ) ),
|
||||
$( '<th/>' ).text( _l( 'Annotation' ) )
|
||||
]));
|
||||
return views;
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ sub-views
|
||||
/** In this override, wrap the content view in a table row
|
||||
* with the content in the left td and annotation/extra-info in the right
|
||||
*/
|
||||
_attachItems : function( $whereTo ){
|
||||
this.$list( $whereTo ).append( this.views.map( function( view ){
|
||||
//TODO:?? possibly make this more flexible: instead of annotation use this._additionalInfo()
|
||||
// build a row around the dataset with the std itemView in the first cell and the annotation in the next
|
||||
var stateClass = _.find( view.el.classList, function( c ){ return ( /^state\-/ ).test( c ); }),
|
||||
annotation = view.model.get( 'annotation' ) || '',
|
||||
$tr = $( '<tr/>' ).append([
|
||||
$( '<td/>' ).addClass( 'contents-container' ).append( view.$el )
|
||||
// visually match the cell bg to the dataset at runtime (prevents the empty space)
|
||||
// (getting bg via jq on hidden elem doesn't work on chrome/webkit - so use states)
|
||||
//.css( 'background-color', view.$el.css( 'background-color' ) ),
|
||||
.addClass( stateClass? stateClass.replace( '-', '-color-' ): '' ),
|
||||
$( '<td/>' ).addClass( 'additional-info' ).text( annotation )
|
||||
]);
|
||||
return $tr;
|
||||
}));
|
||||
return this;
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ panel events
|
||||
/** event map */
|
||||
events : _.extend( _.clone( _super.prototype.events ), {
|
||||
// clicking on any part of the row will expand the items
|
||||
'click tr' : function( ev ){
|
||||
$( ev.currentTarget ).find( '.title-bar' ).click();
|
||||
},
|
||||
// prevent propagation on icon btns so they won't bubble up to tr and toggleBodyVisibility
|
||||
'click .icon-btn' : function( ev ){
|
||||
ev.stopPropagation();
|
||||
}
|
||||
}),
|
||||
|
||||
// ........................................................................ misc
|
||||
/** Return a string rep of the history */
|
||||
toString : function(){
|
||||
return 'AnnotatedHistoryPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
AnnotatedHistoryPanel : AnnotatedHistoryPanel
|
||||
};
|
||||
});
|
||||
define(["mvc/history/history-panel","mvc/history/hda-li","mvc/history/hdca-li","mvc/base-mvc","utils/localization"],function(a,b,c,d,e){var f=a.HistoryPanel,g=f.extend({className:f.prototype.className+" annotated-history-panel",_buildNewRender:function(){var a=f.prototype._buildNewRender.call(this);return this.renderHistoryAnnotation(a),a},renderHistoryAnnotation:function(a){var b=this.model.get("annotation");b&&a.find(".controls .annotation-display").text(b)},renderItems:function(a){a=a||this.$el,a.find(".list-items").replaceWith($("<table/>").addClass("list-items"));var b=f.prototype.renderItems.call(this,a);return this.$list(a).prepend($("<tr/>").addClass("headers").append([$("<th/>").text(e("Dataset")),$("<th/>").text(e("Annotation"))])),b},_attachItems:function(a){return this.$list(a).append(this.views.map(function(a){var b=_.find(a.el.classList,function(a){return/^state\-/.test(a)}),c=a.model.get("annotation")||"",d=$("<tr/>").append([$("<td/>").addClass("contents-container").append(a.$el).addClass(b?b.replace("-","-color-"):""),$("<td/>").addClass("additional-info").text(c)]);return d})),this},events:_.extend(_.clone(f.prototype.events),{"click tr":function(a){$(a.currentTarget).find(".title-bar").click()},"click .icon-btn":function(a){a.stopPropagation()}}),toString:function(){return"AnnotatedHistoryPanel("+(this.model?this.model.get("name"):"")+")"}});return{AnnotatedHistoryPanel:g}});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/history-panel-annotated.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,323 +1,2 @@
|
||||
define([
|
||||
'utils/graph',
|
||||
'utils/add-logging'
|
||||
],function( GRAPH, addLogging ){
|
||||
// ============================================================================
|
||||
var _super = GRAPH.Graph;
|
||||
/** A Directed acyclic Graph built from a history's job data.
|
||||
* Reads in job json, filters and process that json, and builds a graph
|
||||
* using the connections between job inputs and outputs.
|
||||
*/
|
||||
var JobDAG = function( options ){
|
||||
options = options || {};
|
||||
var self = this;
|
||||
//this.logger = console;
|
||||
|
||||
self.filters = [];
|
||||
|
||||
// instance vars
|
||||
//TODO: needed?
|
||||
self._jobsData = [];
|
||||
self._historyContentsMap = {};
|
||||
self._toolMap = {};
|
||||
|
||||
self._outputIdToJobMap = {};
|
||||
self.noInputJobs = [];
|
||||
self.noOutputJobs = [];
|
||||
|
||||
//TODO: save these?
|
||||
self.filteredSetMetadata = [];
|
||||
self.filteredErroredJobs = [];
|
||||
|
||||
self.dataKeys = [ 'jobs', 'historyContents', 'tools' ];
|
||||
_super.call( self, true,
|
||||
_.pick( options, self.dataKeys ),
|
||||
_.omit( options, self.dataKeys )
|
||||
);
|
||||
};
|
||||
JobDAG.prototype = new GRAPH.Graph();
|
||||
JobDAG.prototype.constructor = JobDAG;
|
||||
|
||||
// add logging ability - turn off/on using the this.logger statement above
|
||||
addLogging( JobDAG );
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** process jobs, options, filters, and any history data, then create the graph */
|
||||
JobDAG.prototype.init = function _init( options ){
|
||||
options = options || {};
|
||||
|
||||
var self = this;
|
||||
self.options = _.defaults( options, {
|
||||
excludeSetMetadata : false
|
||||
});
|
||||
self.filters = self._initFilters();
|
||||
|
||||
_super.prototype.init.call( self, options );
|
||||
return self;
|
||||
};
|
||||
|
||||
/** add job filters based on options */
|
||||
JobDAG.prototype._initFilters = function __initFilters(){
|
||||
var self = this,
|
||||
filters = [];
|
||||
|
||||
if( self.options.excludeSetMetadata ){
|
||||
self.filteredSetMetadata = [];
|
||||
filters.push( function filterSetMetadata( jobData ){
|
||||
if( jobData.job.tool_id !== '__SET_METADATA__' ){ return true; }
|
||||
self.filteredSetMetadata.push( jobData.job.id );
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if( self.options.excludeErroredJobs ){
|
||||
self.filteredErroredJobs = [];
|
||||
filters.push( function filterErrored( jobData ){
|
||||
if( jobData.job.state !== 'error' ){ return true; }
|
||||
self.filteredErroredJobs.push( jobData.job.id );
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// all outputs deleted
|
||||
// all outputs hidden
|
||||
|
||||
if( _.isArray( self.options.filters ) ){
|
||||
filters = filters.concat( self.options.filters );
|
||||
}
|
||||
self.debug( 'filters len:', filters.length );
|
||||
return filters;
|
||||
};
|
||||
|
||||
/** */
|
||||
JobDAG.prototype.read = function _read( data ){
|
||||
var self = this;
|
||||
if( _.has( data, 'historyContents' ) && _.has( data, 'jobs' ) && _.has( data, 'tools' ) ){
|
||||
// a job dag is composed of these three elements:
|
||||
// clone the 3 data sources into the DAG, processing the jobs finally using the history and tools
|
||||
self.preprocessHistoryContents( data.historyContents || [] )
|
||||
.preprocessTools( data.tools || {} )
|
||||
.preprocessJobs( data.jobs || [] );
|
||||
|
||||
// filter jobs and create the vertices and edges of the job DAG
|
||||
self.createGraph( self._filterJobs() );
|
||||
return self;
|
||||
}
|
||||
return _super.prototype.read.call( this, data );
|
||||
};
|
||||
|
||||
/** */
|
||||
JobDAG.prototype.preprocessHistoryContents = function _preprocessHistoryContents( historyContents ){
|
||||
this.info( 'processing history' );
|
||||
var self = this;
|
||||
self._historyContentsMap = {};
|
||||
|
||||
historyContents.forEach( function( content, i ){
|
||||
self._historyContentsMap[ content.id ] = _.clone( content );
|
||||
});
|
||||
return self;
|
||||
};
|
||||
|
||||
/** */
|
||||
JobDAG.prototype.preprocessTools = function _preprocessTools( tools ){
|
||||
this.info( 'processing tools' );
|
||||
var self = this;
|
||||
self._toolMap = {};
|
||||
|
||||
_.each( tools, function( tool, id ){
|
||||
self._toolMap[ id ] = _.clone( tool );
|
||||
});
|
||||
return self;
|
||||
};
|
||||
|
||||
/** sort the cloned jobs, decorate with tool and history contents info, and store in prop array */
|
||||
JobDAG.prototype.preprocessJobs = function _preprocessJobs( jobs ){
|
||||
this.info( 'processing jobs' );
|
||||
var self = this;
|
||||
self._outputIdToJobMap = {};
|
||||
|
||||
self._jobsData = self.sort( jobs ).map( function( job ){
|
||||
return self.preprocessJob( _.clone( job ) );
|
||||
});
|
||||
//console.debug( JSON.stringify( self._jobsData, null, ' ' ) );
|
||||
//console.debug( JSON.stringify( self._outputIdToJobMap, null, ' ' ) );
|
||||
return self;
|
||||
};
|
||||
|
||||
/** sort the jobs based on update time */
|
||||
JobDAG.prototype.sort = function _sort( jobs ){
|
||||
function cmpCreate( a, b ){
|
||||
if( a.create_time > b.create_time ){ return 1; }
|
||||
if( a.create_time < b.create_time ){ return -1; }
|
||||
return 0;
|
||||
}
|
||||
return jobs.sort( cmpCreate );
|
||||
};
|
||||
|
||||
/** decorate with input/output datasets and tool */
|
||||
JobDAG.prototype.preprocessJob = function _preprocessJob( job, index ){
|
||||
//this.info( 'preprocessJob', job, index );
|
||||
var self = this,
|
||||
jobData = { job: job };
|
||||
|
||||
jobData.inputs = self._processInputs( job );
|
||||
if( _.size( jobData.inputs ) === 0 ){
|
||||
self.noInputJobs.push( job.id );
|
||||
}
|
||||
jobData.outputs = self._processOutputs( job );
|
||||
if( _.size( jobData.outputs ) === 0 ){
|
||||
self.noOutputJobs.push( job.id );
|
||||
}
|
||||
|
||||
jobData.tool = self._toolMap[ job.tool_id ];
|
||||
|
||||
//self.info( '\t jobData:', jobData );
|
||||
return jobData;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
JobDAG.prototype._processInputs = function __processInputs( job ){
|
||||
var self = this,
|
||||
inputs = job.inputs,
|
||||
inputMap = {};
|
||||
_.each( inputs, function( input, nameInJob ){
|
||||
input = _.clone( self._validateInputOutput( input ) );
|
||||
input.name = nameInJob;
|
||||
// since this is a DAG and we're processing in order of create time,
|
||||
// the inputs for this job will already be listed in _outputIdToJobMap
|
||||
// TODO: we can possibly exploit this
|
||||
//console.debug( 'input in _outputIdToJobMap', self._outputIdToJobMap[ input.id ] );
|
||||
input.content = self._historyContentsMap[ input.id ];
|
||||
inputMap[ input.id ] = input;
|
||||
});
|
||||
return inputMap;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
JobDAG.prototype._validateInputOutput = function __validateInputOutput( inputOutput ){
|
||||
if( !inputOutput.id ){
|
||||
throw new Error( 'No id on job input/output: ', JSON.stringify( inputOutput ) );
|
||||
}
|
||||
if( !inputOutput.src || inputOutput.src !== 'hda' ){
|
||||
throw new Error( 'Bad src on job input/output: ', JSON.stringify( inputOutput ) );
|
||||
}
|
||||
return inputOutput;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
JobDAG.prototype._processOutputs = function __processOutputs( job ){
|
||||
var self = this,
|
||||
outputs = job.outputs,
|
||||
outputMap = {};
|
||||
_.each( outputs, function( output, nameInJob ){
|
||||
output = _.clone( self._validateInputOutput( output ) );
|
||||
output.name = nameInJob;
|
||||
// add dataset content to jobData
|
||||
output.content = self._historyContentsMap[ output.id ];
|
||||
outputMap[ output.id ] = output;
|
||||
|
||||
self._outputIdToJobMap[ output.id ] = job.id;
|
||||
});
|
||||
return outputMap;
|
||||
};
|
||||
|
||||
/** */
|
||||
JobDAG.prototype._filterJobs = function __filterJobs(){
|
||||
var self = this;
|
||||
return self._jobsData.filter( function( j, i ){ return self._filterJob( j, i ); });
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
JobDAG.prototype._filterJob = function _filterJob( jobData, index ){
|
||||
// apply filters after processing job allowing access to the additional data above inside the filters
|
||||
var self = this;
|
||||
for( var i=0; i<self.filters.length; i++ ){
|
||||
if( !self.filters[i].call( self, jobData ) ){
|
||||
self.debug( '\t job', jobData.job.id, ' has been filtered out by function:\n', self.filters[i] );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/** Walk all the jobs (vertices), attempting to find connections
|
||||
* between datasets used as both inputs and outputs (edges)
|
||||
*/
|
||||
JobDAG.prototype.createGraph = function _createGraph( jobsData ){
|
||||
var self = this;
|
||||
self.debug( 'connections:' );
|
||||
//console.debug( jobsData );
|
||||
|
||||
_.each( jobsData, function( jobData ){
|
||||
var id = jobData.job.id;
|
||||
self.debug( '\t', id, jobData );
|
||||
self.createVertex( id, jobData );
|
||||
});
|
||||
_.each( jobsData, function( jobData ){
|
||||
var targetId = jobData.job.id;
|
||||
_.each( jobData.inputs, function( input, inputId ){
|
||||
//console.debug( '\t\t target input:', inputId, input );
|
||||
var sourceId = self._outputIdToJobMap[ inputId ];
|
||||
//console.debug( '\t\t source job id:', sourceId );
|
||||
if( !sourceId ){
|
||||
var joblessVertex = self.createJobLessVertex( inputId );
|
||||
sourceId = joblessVertex.name;
|
||||
}
|
||||
//TODO:?? no checking here whether sourceId is actually in the vertex map
|
||||
//console.debug( '\t\t creating edge, source:', sourceId, self.vertices[ sourceId ] );
|
||||
//console.debug( '\t\t creating edge, target:', targetId, self.vertices[ targetId ] );
|
||||
self.createEdge( sourceId, targetId, self.directed, {
|
||||
dataset : inputId
|
||||
});
|
||||
});
|
||||
});
|
||||
//console.debug( self.toVerticesAndEdges().edges );
|
||||
|
||||
self.debug( 'final graph: ', JSON.stringify( self.toVerticesAndEdges(), null, ' ' ) );
|
||||
return self;
|
||||
};
|
||||
|
||||
/** Return a 'mangled' version of history contents id to prevent contents <-> job id collision */
|
||||
JobDAG.prototype.createJobLessVertex = function _createJobLessVertex( contentId ){
|
||||
// currently, copied contents are the only history contents without jobs (that I know of)
|
||||
//note: following needed to prevent id collision btwn content and jobs in vertex map
|
||||
var JOBLESS_ID_MANGLER = 'copy-',
|
||||
mangledId = JOBLESS_ID_MANGLER + contentId;
|
||||
return this.createVertex( mangledId, this._historyContentsMap[ contentId ] );
|
||||
};
|
||||
|
||||
/** Override to re-sort (ugh) jobs in each component by update time */
|
||||
JobDAG.prototype.weakComponentGraphArray = function(){
|
||||
var dag = this;
|
||||
return this.weakComponents().map( function( component ){
|
||||
//TODO: this seems to belong above (in sort) - why isn't it preserved?
|
||||
// note: using create_time (as opposed to update_time)
|
||||
// since update_time for jobless/copied datasets is changes more often
|
||||
component.vertices.sort( function cmpCreate( a, b ){
|
||||
var aCreateTime = a.data.job? a.data.job.create_time : a.data.create_time,
|
||||
bCreateTime = b.data.job? b.data.job.create_time : b.data.create_time;
|
||||
if( aCreateTime > bCreateTime ){ return 1; }
|
||||
if( aCreateTime < bCreateTime ){ return -1; }
|
||||
return 0;
|
||||
});
|
||||
return new Graph( dag.directed, component );
|
||||
});
|
||||
};
|
||||
|
||||
JobDAG.prototype._jobsDataMap = function(){
|
||||
var jobsDataMap = {};
|
||||
this._jobsData.forEach( function( jobData ){
|
||||
jobsDataMap[ jobData.job.id ] = jobData;
|
||||
});
|
||||
return jobsDataMap;
|
||||
};
|
||||
|
||||
|
||||
// ============================================================================
|
||||
return JobDAG;
|
||||
});
|
||||
define(["utils/graph","utils/add-logging"],function(a,b){var c=a.Graph,d=function(a){a=a||{};var b=this;b.filters=[],b._jobsData=[],b._historyContentsMap={},b._toolMap={},b._outputIdToJobMap={},b.noInputJobs=[],b.noOutputJobs=[],b.filteredSetMetadata=[],b.filteredErroredJobs=[],b.dataKeys=["jobs","historyContents","tools"],c.call(b,!0,_.pick(a,b.dataKeys),_.omit(a,b.dataKeys))};return d.prototype=new a.Graph,d.prototype.constructor=d,b(d),d.prototype.init=function(a){a=a||{};var b=this;return b.options=_.defaults(a,{excludeSetMetadata:!1}),b.filters=b._initFilters(),c.prototype.init.call(b,a),b},d.prototype._initFilters=function(){var a=this,b=[];return a.options.excludeSetMetadata&&(a.filteredSetMetadata=[],b.push(function(b){return"__SET_METADATA__"!==b.job.tool_id?!0:(a.filteredSetMetadata.push(b.job.id),!1)})),a.options.excludeErroredJobs&&(a.filteredErroredJobs=[],b.push(function(b){return"error"!==b.job.state?!0:(a.filteredErroredJobs.push(b.job.id),!1)})),_.isArray(a.options.filters)&&(b=b.concat(a.options.filters)),a.debug("filters len:",b.length),b},d.prototype.read=function(a){var b=this;return _.has(a,"historyContents")&&_.has(a,"jobs")&&_.has(a,"tools")?(b.preprocessHistoryContents(a.historyContents||[]).preprocessTools(a.tools||{}).preprocessJobs(a.jobs||[]),b.createGraph(b._filterJobs()),b):c.prototype.read.call(this,a)},d.prototype.preprocessHistoryContents=function(a){this.info("processing history");var b=this;return b._historyContentsMap={},a.forEach(function(a){b._historyContentsMap[a.id]=_.clone(a)}),b},d.prototype.preprocessTools=function(a){this.info("processing tools");var b=this;return b._toolMap={},_.each(a,function(a,c){b._toolMap[c]=_.clone(a)}),b},d.prototype.preprocessJobs=function(a){this.info("processing jobs");var b=this;return b._outputIdToJobMap={},b._jobsData=b.sort(a).map(function(a){return b.preprocessJob(_.clone(a))}),b},d.prototype.sort=function(a){function b(a,b){return a.create_time>b.create_time?1:a.create_time<b.create_time?-1:0}return a.sort(b)},d.prototype.preprocessJob=function(a){var b=this,c={job:a};return c.inputs=b._processInputs(a),0===_.size(c.inputs)&&b.noInputJobs.push(a.id),c.outputs=b._processOutputs(a),0===_.size(c.outputs)&&b.noOutputJobs.push(a.id),c.tool=b._toolMap[a.tool_id],c},d.prototype._processInputs=function(a){var b=this,c=a.inputs,d={};return _.each(c,function(a,c){a=_.clone(b._validateInputOutput(a)),a.name=c,a.content=b._historyContentsMap[a.id],d[a.id]=a}),d},d.prototype._validateInputOutput=function(a){if(!a.id)throw new Error("No id on job input/output: ",JSON.stringify(a));if(!a.src||"hda"!==a.src)throw new Error("Bad src on job input/output: ",JSON.stringify(a));return a},d.prototype._processOutputs=function(a){var b=this,c=a.outputs,d={};return _.each(c,function(c,e){c=_.clone(b._validateInputOutput(c)),c.name=e,c.content=b._historyContentsMap[c.id],d[c.id]=c,b._outputIdToJobMap[c.id]=a.id}),d},d.prototype._filterJobs=function(){var a=this;return a._jobsData.filter(function(b,c){return a._filterJob(b,c)})},d.prototype._filterJob=function(a){for(var b=this,c=0;c<b.filters.length;c++)if(!b.filters[c].call(b,a))return b.debug(" job",a.job.id," has been filtered out by function:\n",b.filters[c]),!1;return!0},d.prototype.createGraph=function(a){var b=this;return b.debug("connections:"),_.each(a,function(a){var c=a.job.id;b.debug(" ",c,a),b.createVertex(c,a)}),_.each(a,function(a){var c=a.job.id;_.each(a.inputs,function(a,d){var e=b._outputIdToJobMap[d];if(!e){var f=b.createJobLessVertex(d);e=f.name}b.createEdge(e,c,b.directed,{dataset:d})})}),b.debug("final graph: ",JSON.stringify(b.toVerticesAndEdges(),null," ")),b},d.prototype.createJobLessVertex=function(a){var b="copy-",c=b+a;return this.createVertex(c,this._historyContentsMap[a])},d.prototype.weakComponentGraphArray=function(){var a=this;return this.weakComponents().map(function(b){return b.vertices.sort(function(a,b){var c=a.data.job?a.data.job.create_time:a.data.create_time,d=b.data.job?b.data.job.create_time:b.data.create_time;return c>d?1:d>c?-1:0}),new Graph(a.directed,b)})},d.prototype._jobsDataMap=function(){var a={};return this._jobsData.forEach(function(b){a[b.job.id]=b}),a},d});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/job-dag.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -1,162 +1,2 @@
|
||||
define([
|
||||
"mvc/ui/popup-menu",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( PopupMenu, BASE_MVC, _l ){
|
||||
// ============================================================================
|
||||
var menu = [
|
||||
{
|
||||
html : _l( 'History Lists' ),
|
||||
header : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Saved Histories' ),
|
||||
href : 'history/list'
|
||||
},
|
||||
{
|
||||
html : _l( 'Histories Shared with Me' ),
|
||||
href : 'history/list_shared'
|
||||
},
|
||||
|
||||
{
|
||||
html : _l( 'Current History' ),
|
||||
header : true,
|
||||
anon : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Create New' ),
|
||||
func : function() {
|
||||
if( Galaxy && Galaxy.currHistoryPanel ){
|
||||
Galaxy.currHistoryPanel.createNewHistory();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
html : _l( 'Copy History' ),
|
||||
href : 'history/copy'
|
||||
},
|
||||
{
|
||||
html : _l( 'Copy Datasets' ),
|
||||
href : 'dataset/copy_datasets'
|
||||
},
|
||||
{
|
||||
html : _l( 'Share or Publish' ),
|
||||
href : 'history/sharing'
|
||||
},
|
||||
{
|
||||
html : _l( 'Extract Workflow' ),
|
||||
href : 'workflow/build_from_current_history'
|
||||
},
|
||||
{
|
||||
html : _l( 'Dataset Security' ),
|
||||
href : 'root/history_set_default_permissions'
|
||||
},
|
||||
{
|
||||
html : _l( 'Resume Paused Jobs' ),
|
||||
href : 'history/resume_paused_jobs?current=True',
|
||||
anon : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Collapse Expanded Datasets' ),
|
||||
func : function() {
|
||||
if( Galaxy && Galaxy.currHistoryPanel ){
|
||||
Galaxy.currHistoryPanel.collapseAll();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
html : _l( 'Unhide Hidden Datasets' ),
|
||||
confirm : _l( 'Really unhide all hidden datasets?' ),
|
||||
href : 'history/unhide_datasets?current=True',
|
||||
anon : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Delete Hidden Datasets' ),
|
||||
confirm : _l( 'Really delete all hidden datasets?' ),
|
||||
href : 'history/delete_hidden_datasets',
|
||||
anon : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Purge Deleted Datasets' ),
|
||||
confirm : _l( 'Really delete all deleted datasets permanently? This cannot be undone.' ),
|
||||
href : 'history/purge_deleted_datasets',
|
||||
purge : true,
|
||||
anon : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Show Structure' ),
|
||||
href : 'history/display_structured',
|
||||
anon : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Export Citations' ),
|
||||
href : 'history/citations',
|
||||
anon : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Export to File' ),
|
||||
href : 'history/export_archive?preview=True',
|
||||
anon : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Delete' ),
|
||||
confirm : _l( 'Really delete the current history?' ),
|
||||
href : 'history/delete_current'
|
||||
},
|
||||
{
|
||||
html : _l( 'Delete Permanently' ),
|
||||
confirm : _l( 'Really delete the current history permanently? This cannot be undone.' ),
|
||||
href : 'history/delete_current?purge=True',
|
||||
purge : true,
|
||||
anon : true
|
||||
},
|
||||
|
||||
{
|
||||
html : _l( 'Other Actions' ),
|
||||
header : true
|
||||
},
|
||||
{
|
||||
html : _l( 'Import from File' ),
|
||||
href : 'history/import_archive'
|
||||
}
|
||||
];
|
||||
|
||||
function buildMenu( isAnon, purgeAllowed, urlRoot ){
|
||||
return _.clone( menu ).filter( function( menuOption ){
|
||||
if( isAnon && !menuOption.anon ){
|
||||
return false;
|
||||
}
|
||||
if( !purgeAllowed && menuOption.purge ){
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO:?? hard-coded galaxy_main
|
||||
if( menuOption.href ){
|
||||
menuOption.href = urlRoot + menuOption.href;
|
||||
menuOption.target = 'galaxy_main';
|
||||
}
|
||||
if( menuOption.confirm ){
|
||||
menuOption.func = function(){
|
||||
if( confirm( menuOption.confirm ) ){
|
||||
galaxy_main.location = menuOption.href;
|
||||
}
|
||||
};
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
var create = function( $button, options ){
|
||||
options = options || {};
|
||||
var isAnon = options.anonymous === undefined? true : options.anonymous,
|
||||
purgeAllowed = options.purgeAllowed || false,
|
||||
root = options.root || ( ( Galaxy && Galaxy.options )? Galaxy.options.root: '/' ),
|
||||
menu = buildMenu( isAnon, purgeAllowed, root );
|
||||
//console.debug( 'menu:', menu );
|
||||
return new PopupMenu( $button, menu );
|
||||
};
|
||||
|
||||
|
||||
// ============================================================================
|
||||
return create;
|
||||
});
|
||||
define(["mvc/ui/popup-menu","mvc/base-mvc","utils/localization"],function(a,b,c){function d(a,b,c){return _.clone(e).filter(function(d){return a&&!d.anon?!1:!b&&d.purge?!1:(d.href&&(d.href=c+d.href,d.target="galaxy_main"),d.confirm&&(d.func=function(){confirm(d.confirm)&&(galaxy_main.location=d.href)}),!0)})}var e=[{html:c("History Lists"),header:!0},{html:c("Saved Histories"),href:"history/list"},{html:c("Histories Shared with Me"),href:"history/list_shared"},{html:c("Current History"),header:!0,anon:!0},{html:c("Create New"),func:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.createNewHistory()}},{html:c("Copy History"),href:"history/copy"},{html:c("Copy Datasets"),href:"dataset/copy_datasets"},{html:c("Share or Publish"),href:"history/sharing"},{html:c("Extract Workflow"),href:"workflow/build_from_current_history"},{html:c("Dataset Security"),href:"root/history_set_default_permissions"},{html:c("Resume Paused Jobs"),href:"history/resume_paused_jobs?current=True",anon:!0},{html:c("Collapse Expanded Datasets"),func:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.collapseAll()}},{html:c("Unhide Hidden Datasets"),confirm:c("Really unhide all hidden datasets?"),href:"history/unhide_datasets?current=True",anon:!0},{html:c("Delete Hidden Datasets"),confirm:c("Really delete all hidden datasets?"),href:"history/delete_hidden_datasets",anon:!0},{html:c("Purge Deleted Datasets"),confirm:c("Really delete all deleted datasets permanently? This cannot be undone."),href:"history/purge_deleted_datasets",purge:!0,anon:!0},{html:c("Show Structure"),href:"history/display_structured",anon:!0},{html:c("Export Citations"),href:"history/citations",anon:!0},{html:c("Export to File"),href:"history/export_archive?preview=True",anon:!0},{html:c("Delete"),confirm:c("Really delete the current history?"),href:"history/delete_current"},{html:c("Delete Permanently"),confirm:c("Really delete the current history permanently? This cannot be undone."),href:"history/delete_current?purge=True",purge:!0,anon:!0},{html:c("Other Actions"),header:!0},{html:c("Import from File"),href:"history/import_archive"}],f=function(b,c){c=c||{};var e=void 0===c.anonymous?!0:c.anonymous,f=c.purgeAllowed||!1,g=c.root||(Galaxy&&Galaxy.options?Galaxy.options.root:"/"),h=d(e,f,g);return new a(b,h)};return f});
|
||||
//# sourceMappingURL=../../../maps/mvc/history/options-menu.js.map
|
||||
@@ -1,206 +1,2 @@
|
||||
define([
|
||||
'mvc/list/list-item',
|
||||
'mvc/dataset/dataset-list',
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( LIST_ITEM, DATASET_LIST, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
var _super = LIST_ITEM.FoldoutListItemView;
|
||||
/** @class A job view used from within a larger list of jobs.
|
||||
* Each job itself is a foldout panel of history contents displaying the outputs of this job.
|
||||
*/
|
||||
var JobListItemView = _super.extend(/** @lends JobListItemView.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
className : _super.prototype.className + " job",
|
||||
id : function(){
|
||||
return [ 'job', this.model.get( 'id' ) ].join( '-' );
|
||||
},
|
||||
|
||||
foldoutPanelClass : DATASET_LIST.DatasetList,
|
||||
|
||||
/** Set up: instance vars, options, and event handlers */
|
||||
initialize : function( attributes ){
|
||||
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
|
||||
this.log( this + '.initialize:', attributes );
|
||||
_super.prototype.initialize.call( this, attributes );
|
||||
|
||||
this.tool = attributes.tool || {};
|
||||
this.jobData = attributes.jobData || {};
|
||||
|
||||
/** where should pages from links be displayed? (default to new tab/window) */
|
||||
this.linkTarget = attributes.linkTarget || '_blank';
|
||||
},
|
||||
|
||||
/** In this override, add the state as a class for use with state-based CSS */
|
||||
_swapNewRender : function( $newRender ){
|
||||
_super.prototype._swapNewRender.call( this, $newRender );
|
||||
if( this.model.has( 'state' ) ){
|
||||
this.$el.addClass( 'state-' + this.model.get( 'state' ) );
|
||||
}
|
||||
return this.$el;
|
||||
},
|
||||
|
||||
/** Stub to return proper foldout panel options */
|
||||
_getFoldoutPanelOptions : function(){
|
||||
var options = _super.prototype._getFoldoutPanelOptions.call( this );
|
||||
return _.extend( options, {
|
||||
collection : this.model.outputCollection,
|
||||
selecting : false
|
||||
});
|
||||
},
|
||||
|
||||
// ........................................................................ template helpers
|
||||
// all of these are ADAPTERs - in other words, it might be better if the API returned the final form
|
||||
// or something similar in order to remove some of the complexity here
|
||||
|
||||
/** Return tool.inputs that should/can be safely displayed */
|
||||
_labelParamMap : function(){
|
||||
//ADAPTER
|
||||
var params = this.model.get( 'params' ),
|
||||
labelParamMap = {};
|
||||
_.each( this.tool.inputs, function( i ){
|
||||
//console.debug( i.label, i.model_class );
|
||||
if( i.label && i.model_class !== 'DataToolParameter' ){
|
||||
labelParamMap[ i.label ] = params[ i.name ];
|
||||
}
|
||||
});
|
||||
return labelParamMap;
|
||||
},
|
||||
|
||||
_labelInputMap : function(){
|
||||
//ADAPTER
|
||||
var view = this,
|
||||
labelInputMap = {};
|
||||
_.each( this.jobData.inputs, function( input ){
|
||||
var toolInput = view._findToolInput( input.name );
|
||||
if( toolInput ){
|
||||
labelInputMap[ toolInput.label ] = input;
|
||||
}
|
||||
});
|
||||
return labelInputMap;
|
||||
},
|
||||
|
||||
/** Return a tool.inputs object that matches (or partially matches) the given (job input) name */
|
||||
_findToolInput : function( name ){
|
||||
//ADAPTER
|
||||
var toolInputs = this.tool.inputs,
|
||||
exactMatch = _.findWhere( toolInputs, { name : name });
|
||||
if( exactMatch ){ return exactMatch; }
|
||||
return this._findRepeatToolInput( name, toolInputs );
|
||||
},
|
||||
|
||||
/** Return a tool.inputs object that partially matches the given (job input) name (for repeat dataset inputs)*/
|
||||
_findRepeatToolInput : function( name, toolInputs ){
|
||||
//ADAPTER
|
||||
toolInputs = toolInputs || this.tool.inputs;
|
||||
var partialMatch = _.find( toolInputs, function( i ){
|
||||
return name.indexOf( i.name ) === 0;
|
||||
});
|
||||
if( !partialMatch ){ return undefined; }
|
||||
|
||||
var subMatch = _.find( partialMatch.inputs, function( i ){
|
||||
return name.indexOf( i.name ) !== -1;
|
||||
});
|
||||
return subMatch;
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
return 'JobListItemView(' + this.model + ')';
|
||||
}
|
||||
});
|
||||
|
||||
// ............................................................................ TEMPLATES
|
||||
/** underscore templates */
|
||||
JobListItemView.prototype.templates = (function(){
|
||||
//TODO: move to require text! plugin
|
||||
|
||||
var elTemplate = BASE_MVC.wrapTemplate([
|
||||
'<div class="list-element">',
|
||||
'<div class="id"><%= model.id %></div>',
|
||||
// errors, messages, etc.
|
||||
'<div class="warnings"></div>',
|
||||
|
||||
// multi-select checkbox
|
||||
'<div class="selector">',
|
||||
'<span class="fa fa-2x fa-square-o"></span>',
|
||||
'</div>',
|
||||
// space for title bar buttons - gen. floated to the right
|
||||
'<div class="primary-actions"></div>',
|
||||
'<div class="title-bar"></div>',
|
||||
|
||||
// expandable area for more details
|
||||
'<div class="details"></div>',
|
||||
'</div>'
|
||||
]);
|
||||
|
||||
var titleBarTemplate = BASE_MVC.wrapTemplate([
|
||||
// adding a tabindex here allows focusing the title bar and the use of keydown to expand the dataset display
|
||||
'<div class="title-bar clear" tabindex="0">',
|
||||
//'<span class="state-icon"></span>',
|
||||
'<div class="title">',
|
||||
'<span class="name"><%- view.tool.name %></span>',
|
||||
'</div>',
|
||||
'<div class="subtitle">',
|
||||
'<span class="description"><%- view.tool.description %></span',
|
||||
'<span class="create-time">',
|
||||
' ', _l( 'Created' ), ': <%= new Date( job.create_time ).toString() %>, ',
|
||||
'</span',
|
||||
'</div>',
|
||||
'</div>'
|
||||
], 'job' );
|
||||
|
||||
var subtitleTemplate = BASE_MVC.wrapTemplate([
|
||||
'<div class="subtitle">',
|
||||
'<span class="description"><%- view.tool.description %></span',
|
||||
//'<span class="create-time">',
|
||||
// ' ', _l( 'Created' ), ': <%= new Date( job.create_time ).toString() %>, ',
|
||||
//'</span',
|
||||
//'<span class="version">',
|
||||
// ' (', _l( 'version' ), ': <%= view.tool.version %>)',
|
||||
//'</span',
|
||||
'</div>'
|
||||
], 'job' );
|
||||
|
||||
var detailsTemplate = BASE_MVC.wrapTemplate([
|
||||
'<div class="details">',
|
||||
//'<div class="version">',
|
||||
// '<label class="prompt">', _l( 'Version' ), '</label>',
|
||||
// '<span class="value"><%= view.tool.version %></span>',
|
||||
//'</div>',
|
||||
'<div class="params">',
|
||||
'<% _.each( view._labelInputMap(), function( input, label ){ %>',
|
||||
'<div class="input" data-input-name="<%= input.name %>" data-input-id="<%= input.id %>">',
|
||||
'<label class="prompt"><%= label %></label>',
|
||||
//TODO: input dataset name
|
||||
'<span class="value"><%= input.content.name %></span>',
|
||||
'</div>',
|
||||
'<% }) %>',
|
||||
'<% _.each( view._labelParamMap(), function( param, label ){ %>',
|
||||
'<div class="param" data-input-name="<%= param.name %>">',
|
||||
'<label class="prompt"><%= label %></label>',
|
||||
'<span class="value"><%= param %></span>',
|
||||
'</div>',
|
||||
'<% }) %>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
], 'job' );
|
||||
|
||||
return _.extend( {}, _super.prototype.templates, {
|
||||
//el : elTemplate,
|
||||
titleBar : titleBarTemplate,
|
||||
subtitle : subtitleTemplate,
|
||||
details : detailsTemplate
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
//=============================================================================
|
||||
return {
|
||||
JobListItemView : JobListItemView
|
||||
};
|
||||
});
|
||||
define(["mvc/list/list-item","mvc/dataset/dataset-list","mvc/base-mvc","utils/localization"],function(a,b,c,d){var e=a.FoldoutListItemView,f=e.extend({className:e.prototype.className+" job",id:function(){return["job",this.model.get("id")].join("-")},foldoutPanelClass:b.DatasetList,initialize:function(a){a.logger&&(this.logger=this.model.logger=a.logger),this.log(this+".initialize:",a),e.prototype.initialize.call(this,a),this.tool=a.tool||{},this.jobData=a.jobData||{},this.linkTarget=a.linkTarget||"_blank"},_swapNewRender:function(a){return e.prototype._swapNewRender.call(this,a),this.model.has("state")&&this.$el.addClass("state-"+this.model.get("state")),this.$el},_getFoldoutPanelOptions:function(){var a=e.prototype._getFoldoutPanelOptions.call(this);return _.extend(a,{collection:this.model.outputCollection,selecting:!1})},_labelParamMap:function(){var a=this.model.get("params"),b={};return _.each(this.tool.inputs,function(c){c.label&&"DataToolParameter"!==c.model_class&&(b[c.label]=a[c.name])}),b},_labelInputMap:function(){var a=this,b={};return _.each(this.jobData.inputs,function(c){var d=a._findToolInput(c.name);d&&(b[d.label]=c)}),b},_findToolInput:function(a){var b=this.tool.inputs,c=_.findWhere(b,{name:a});return c?c:this._findRepeatToolInput(a,b)},_findRepeatToolInput:function(a,b){b=b||this.tool.inputs;var c=_.find(b,function(b){return 0===a.indexOf(b.name)});if(!c)return void 0;var d=_.find(c.inputs,function(b){return-1!==a.indexOf(b.name)});return d},toString:function(){return"JobListItemView("+this.model+")"}});return f.prototype.templates=function(){var a=(c.wrapTemplate(['<div class="list-element">','<div class="id"><%= model.id %></div>','<div class="warnings"></div>','<div class="selector">','<span class="fa fa-2x fa-square-o"></span>',"</div>",'<div class="primary-actions"></div>','<div class="title-bar"></div>','<div class="details"></div>',"</div>"]),c.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- view.tool.name %></span>',"</div>",'<div class="subtitle">','<span class="description"><%- view.tool.description %></span','<span class="create-time">'," ",d("Created"),": <%= new Date( job.create_time ).toString() %>, ","</span","</div>","</div>"],"job")),b=c.wrapTemplate(['<div class="subtitle">','<span class="description"><%- view.tool.description %></span',"</div>"],"job"),f=c.wrapTemplate(['<div class="details">','<div class="params">',"<% _.each( view._labelInputMap(), function( input, label ){ %>",'<div class="input" data-input-name="<%= input.name %>" data-input-id="<%= input.id %>">','<label class="prompt"><%= label %></label>','<span class="value"><%= input.content.name %></span>',"</div>","<% }) %>","<% _.each( view._labelParamMap(), function( param, label ){ %>",'<div class="param" data-input-name="<%= param.name %>">','<label class="prompt"><%= label %></label>','<span class="value"><%= param %></span>',"</div>","<% }) %>","</div>","</div>"],"job");return _.extend({},e.prototype.templates,{titleBar:a,subtitle:b,details:f})}(),{JobListItemView:f}});
|
||||
//# sourceMappingURL=../../../maps/mvc/job/job-li.js.map
|
||||
@@ -1,201 +1,2 @@
|
||||
define([
|
||||
"mvc/history/history-contents",
|
||||
"mvc/dataset/states",
|
||||
"utils/ajax-queue",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( HISTORY_CONTENTS, STATES, AJAX_QUEUE, BASE_MVC, _l ){
|
||||
//==============================================================================
|
||||
var searchableMixin = BASE_MVC.SearchableModelMixin;
|
||||
/** @class Represents a job running or ran on the server job handlers.
|
||||
*/
|
||||
var Job = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
|
||||
BASE_MVC.mixin( searchableMixin, /** @lends Job.prototype */{
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** default attributes for a model */
|
||||
defaults : {
|
||||
model_class : 'Job',
|
||||
|
||||
tool_id : null,
|
||||
exit_code : null,
|
||||
|
||||
inputs : {},
|
||||
outputs : {},
|
||||
params : {},
|
||||
|
||||
create_time : null,
|
||||
update_time : null,
|
||||
state : STATES.NEW
|
||||
},
|
||||
|
||||
/** override to parse params on incomming */
|
||||
parse : function( response, options ){
|
||||
response.params = this.parseParams( response.params );
|
||||
return response;
|
||||
},
|
||||
|
||||
/** override to treat param values as json */
|
||||
parseParams : function( params ){
|
||||
var newParams = {};
|
||||
_.each( params, function( value, key ){
|
||||
newParams[ key ] = JSON.parse( value );
|
||||
});
|
||||
return newParams;
|
||||
},
|
||||
|
||||
/** instance vars and listeners */
|
||||
initialize : function( attributes, options ){
|
||||
this.debug( this + '(Job).initialize', attributes, options );
|
||||
|
||||
this.set( 'params', this.parseParams( this.get( 'params' ) ), { silent: true });
|
||||
|
||||
this.outputCollection = attributes.outputCollection || new HISTORY_CONTENTS.HistoryContents([]);
|
||||
this._setUpListeners();
|
||||
},
|
||||
|
||||
/** set up any event listeners
|
||||
* event: state:ready fired when this DA moves into/is already in a ready state
|
||||
*/
|
||||
_setUpListeners : function(){
|
||||
// if the state has changed and the new state is a ready state, fire an event
|
||||
this.on( 'change:state', function( currModel, newState ){
|
||||
this.log( this + ' has changed state:', currModel, newState );
|
||||
if( this.inReadyState() ){
|
||||
this.trigger( 'state:ready', currModel, newState, this.previous( 'state' ) );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ........................................................................ common queries
|
||||
/** Is this job in a 'ready' state; where 'Ready' states are states where no
|
||||
* processing is left to do on the server.
|
||||
*/
|
||||
inReadyState : function(){
|
||||
return _.contains( STATES.READY_STATES, this.get( 'state' ) );
|
||||
},
|
||||
|
||||
/** Does this model already contain detailed data (as opposed to just summary level data)? */
|
||||
hasDetails : function(){
|
||||
//?? this may not be reliable
|
||||
return !_.isEmpty( this.get( 'outputs' ) );
|
||||
},
|
||||
|
||||
// ........................................................................ ajax
|
||||
/** root api url */
|
||||
urlRoot : (( window.galaxy_config && galaxy_config.root )?( galaxy_config.root ):( '/' )) + 'api/jobs',
|
||||
//url : function(){ return this.urlRoot; },
|
||||
|
||||
// ........................................................................ searching
|
||||
// see base-mvc, SearchableModelMixin
|
||||
/** what attributes of an Job will be used in a text search */
|
||||
//searchAttributes : [
|
||||
// 'tool'
|
||||
//],
|
||||
|
||||
// ........................................................................ misc
|
||||
/** String representation */
|
||||
toString : function(){
|
||||
return [ 'Job(', this.get( 'id' ), ':', this.get( 'tool_id' ), ')' ].join( '' );
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @class Backbone collection for Jobs.
|
||||
*/
|
||||
var JobCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
|
||||
/** @lends JobCollection.prototype */{
|
||||
model : Job,
|
||||
|
||||
/** logger used to record this.log messages, commonly set to console */
|
||||
//logger : console,
|
||||
|
||||
/** root api url */
|
||||
urlRoot : (( window.galaxy_config && galaxy_config.root )?( galaxy_config.root ):( '/' )) + 'api/jobs',
|
||||
url : function(){ return this.urlRoot; },
|
||||
|
||||
intialize : function( models, options ){
|
||||
console.debug( models, options );
|
||||
},
|
||||
|
||||
// ........................................................................ common queries
|
||||
/** Get the ids of every item in this collection
|
||||
* @returns array of encoded ids
|
||||
*/
|
||||
ids : function(){
|
||||
return this.map( function( item ){ return item.get( 'id' ); });
|
||||
},
|
||||
|
||||
/** Get jobs that are not ready
|
||||
* @returns array of content models
|
||||
*/
|
||||
notReady : function(){
|
||||
return this.filter( function( job ){
|
||||
return !job.inReadyState();
|
||||
});
|
||||
},
|
||||
|
||||
/** return true if any jobs don't have details */
|
||||
haveDetails : function(){
|
||||
return this.all( function( job ){ return job.hasDetails(); });
|
||||
},
|
||||
|
||||
// ........................................................................ ajax
|
||||
/** fetches all details for each job in the collection using a queue */
|
||||
queueDetailFetching : function(){
|
||||
var collection = this,
|
||||
queue = new AJAX_QUEUE.AjaxQueue( this.map( function( job ){
|
||||
return function(){
|
||||
return job.fetch({ silent: true });
|
||||
};
|
||||
}));
|
||||
queue.done( function(){
|
||||
collection.trigger( 'details-loaded' );
|
||||
});
|
||||
return queue;
|
||||
},
|
||||
|
||||
//toDAG : function(){
|
||||
// return new JobDAG( this.toJSON() );
|
||||
//},
|
||||
|
||||
// ........................................................................ sorting/filtering
|
||||
/** return a new collection of jobs whose attributes contain the substring matchesWhat */
|
||||
matches : function( matchesWhat ){
|
||||
return this.filter( function( job ){
|
||||
return job.matches( matchesWhat );
|
||||
});
|
||||
},
|
||||
|
||||
// ........................................................................ misc
|
||||
/** String representation. */
|
||||
toString : function(){
|
||||
return ([ 'JobCollection(', this.length, ')' ].join( '' ));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------- class vars
|
||||
}, {
|
||||
/** class level fn for fetching the job details for all jobs in a history */
|
||||
fromHistory : function( historyId ){
|
||||
console.debug( this );
|
||||
var Collection = this,
|
||||
collection = new Collection([]);
|
||||
collection.fetch({ data: { history_id: historyId }})
|
||||
.done( function(){
|
||||
window.queue = collection.queueDetailFetching();
|
||||
|
||||
});
|
||||
return collection;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//=============================================================================
|
||||
return {
|
||||
Job : Job,
|
||||
JobCollection : JobCollection
|
||||
};
|
||||
});
|
||||
define(["mvc/history/history-contents","mvc/dataset/states","utils/ajax-queue","mvc/base-mvc","utils/localization"],function(a,b,c,d){var e=d.SearchableModelMixin,f=Backbone.Model.extend(d.LoggableMixin).extend(d.mixin(e,{defaults:{model_class:"Job",tool_id:null,exit_code:null,inputs:{},outputs:{},params:{},create_time:null,update_time:null,state:b.NEW},parse:function(a){return a.params=this.parseParams(a.params),a},parseParams:function(a){var b={};return _.each(a,function(a,c){b[c]=JSON.parse(a)}),b},initialize:function(b,c){this.debug(this+"(Job).initialize",b,c),this.set("params",this.parseParams(this.get("params")),{silent:!0}),this.outputCollection=b.outputCollection||new a.HistoryContents([]),this._setUpListeners()},_setUpListeners:function(){this.on("change:state",function(a,b){this.log(this+" has changed state:",a,b),this.inReadyState()&&this.trigger("state:ready",a,b,this.previous("state"))})},inReadyState:function(){return _.contains(b.READY_STATES,this.get("state"))},hasDetails:function(){return!_.isEmpty(this.get("outputs"))},urlRoot:(window.galaxy_config&&galaxy_config.root?galaxy_config.root:"/")+"api/jobs",toString:function(){return["Job(",this.get("id"),":",this.get("tool_id"),")"].join("")}})),g=Backbone.Collection.extend(d.LoggableMixin).extend({model:f,urlRoot:(window.galaxy_config&&galaxy_config.root?galaxy_config.root:"/")+"api/jobs",url:function(){return this.urlRoot},intialize:function(a,b){},ids:function(){return this.map(function(a){return a.get("id")})},notReady:function(){return this.filter(function(a){return!a.inReadyState()})},haveDetails:function(){return this.all(function(a){return a.hasDetails()})},queueDetailFetching:function(){var a=this,b=new c.AjaxQueue(this.map(function(a){return function(){return a.fetch({silent:!0})}}));return b.done(function(){a.trigger("details-loaded")}),b},matches:function(a){return this.filter(function(b){return b.matches(a)})},toString:function(){return["JobCollection(",this.length,")"].join("")}},{fromHistory:function(a){var b=this,c=new b([]);return c.fetch({data:{history_id:a}}).done(function(){window.queue=c.queueDetailFetching()}),c}});return{Job:f,JobCollection:g}});
|
||||
//# sourceMappingURL=../../../maps/mvc/job/job-model.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user