Fix bad commit (adding files)

This commit is contained in:
Carl Eberhard
2015-03-17 10:47:31 -04:00
parent 9a7f5fc17b
commit ba20f5f6e1
185 changed files with 553 additions and 115988 deletions
+169 -159
View File
@@ -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' ] );
};
+1
View File
@@ -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",
+1 -7
View File
@@ -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
-18
View File
@@ -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
View File
@@ -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
+2 -160
View File
@@ -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
+2 -368
View File
@@ -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
+2 -259
View File
@@ -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
+2 -193
View File
@@ -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
+2 -343
View File
@@ -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
+2 -158
View File
@@ -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
+2 -88
View File
@@ -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
View File
@@ -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
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 -166
View File
@@ -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
File diff suppressed because one or more lines are too long
+2 -850
View File
File diff suppressed because one or more lines are too long
+6 -9247
View File
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
View File
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 -97
View File
@@ -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
+2 -302
View File
@@ -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
+5 -10345
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -125
View File
@@ -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
File diff suppressed because one or more lines are too long
+5 -6742
View File
File diff suppressed because one or more lines are too long
+3 -3507
View File
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
+2 -307
View File
@@ -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>&times;</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>&times;</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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -83
View File
@@ -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
+2 -73
View File
@@ -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
+2 -188
View File
@@ -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
+2 -227
View File
@@ -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
File diff suppressed because one or more lines are too long
+2 -442
View File
@@ -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
+2 -45
View File
@@ -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
+2 -341
View File
@@ -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
+2 -60
View File
@@ -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
+2 -283
View File
@@ -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
+2 -144
View File
@@ -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
+2 -263
View File
@@ -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
+2 -167
View File
@@ -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
+2 -343
View File
@@ -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
+2 -343
View File
@@ -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
+2 -235
View File
@@ -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
+2 -121
View File
@@ -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
+2 -63
View File
@@ -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
+2 -74
View File
@@ -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
+2 -53
View File
@@ -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
+2 -57
View File
@@ -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
+2 -79
View File
@@ -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
+2 -94
View File
@@ -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
+2 -351
View File
@@ -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
+2 -422
View File
@@ -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
+2 -323
View File
@@ -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
+2 -162
View File
@@ -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
+2 -206
View File
@@ -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
+2 -201
View File
@@ -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