Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move thumbnail list view to shared ui elements, revise tabs, add test cases #3079

Merged
merged 6 commits into from Oct 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
352 changes: 144 additions & 208 deletions client/galaxy/scripts/mvc/ui/ui-tabs.js
@@ -1,213 +1,149 @@
/**
* Renders tabs e.g. used in the Charts editor, behaves similar to repeat and section rendering
* Renders tabs e.g. used in the charts editor, behaves similar to repeat and section rendering
*/
define( [ 'utils/utils' ], function( Utils ) {
var View = Backbone.View.extend({
initialize : function( options ) {
var self = this;
this.visible = false;
this.$nav = null;
this.$content = null;
this.first_tab = null;
this.current_id = null;
this.list = {};
this.options = Utils.merge( options, {
title_new : '',
operations : null,
onnew : null,
max : null,
onchange : null
});
this.setElement( $( this._template( this.options ) ) );
this.$nav = this.$( '.tab-navigation' );
this.$content = this.$( '.tab-content' );
this.$operations = this.$nav.find( '.tab-operations' );

// Renders tab operations
if ( this.options.operations ) {
$.each( this.options.operations, function( name, item ) {
item.$el.prop( 'id', name );
self.$operations.append( item.$el );
});
var View = Backbone.View.extend({
initialize : function( options ) {
var self = this;
this.collection = new Backbone.Collection();
this.model = options && options.model || new Backbone.Model( {
onchange : null,
visible : true
}).set( options );
this.setElement( $( this._template() ) );
this.$nav = this.$( '.tab-navigation' );
this.$content = this.$( '.tab-content' );
this.$el.on( 'click', function() { $( '.tooltip' ).hide() } );
this.render();
this.listenTo( this.model, 'change', this.render, this );
this.listenTo( this.collection, 'add', this._add, this );
this.listenTo( this.collection, 'remove', this._remove, this );
this.listenTo( this.collection, 'change', this._change, this );
this.listenTo( this.collection, 'reset', this._reset, this );
this.listenTo( this.collection, 'add remove reset', this.render, this );
},

render: function() {
var id = this.model.get( 'current' );
id = this.$( '#' + id ).length > 0 ? id : this.first();
if ( id ) {
this.$nav.children().removeClass('active' );
this.$content.children().removeClass('active' );
this.$( '#tab-' + id ).addClass( 'active' );
this.$( '#' + id ).addClass( 'active' );
}
this.$el[ this.model.get( 'visible' ) ? 'fadeIn' : 'fadeOut' ]( 'fast' );
this.$nav[ this.size() > 1 ? 'show' : 'hide' ]();
},

/** Returns tab id for currently shown tab */
current: function() {
return this.model.get( 'current' );
},

/** Show tab view and highlight a tab by id */
show: function( id ) {
if ( id ) {
this.model.set( { 'current': id, 'visible': true } );
this.model.get( 'onchange' ) && this.model.get( 'onchange' )( id );
}
},

/** Hide tab view */
hide: function(){
this.model.set( 'visible', false );
},

/** Returns first tab */
first: function() {
var model = this.collection.first();
return model && model.id;
},

/** Returns current number of tabs */
size: function() {
return this.collection.length;
},

/** Adds a new tab */
add: function( options ) {
this.collection.add( options );
},

/** Delete tab */
del: function( id ) {
this.collection.remove( id );
},

/** Delete all tabs */
delAll: function() {
this.collection.reset();
},

/** Show tab */
showTab: function( id ) {
this.collection.get( id ).set( 'hidden', false );
},

/** Hide tab */
hideTab: function( id ) {
this.collection.get( id ).set( 'hidden', true );
},

/** Adds a new tab */
_add: function( tab_model ) {
var self = this;
var options = tab_model.attributes;
this.$content.append( $( '<div/>' ).attr( 'id', options.id ).addClass( 'tab-pane' ).append( options.$el ) );
this.$nav.append( $( this._template_tab( options ) )
.show()
.tooltip( { title: options.tooltip, placement: 'bottom', container: self.$el } )
.on( 'click', function( e ) {
e.preventDefault();
self.show( options.id );
}));
if ( this.size() == 1 ) {
this.show( options.id );
}
},

/** Delete tab */
_remove: function( tab_model ) {
this.$( '#tab-' + tab_model.id ).remove();
this.$( '#' + tab_model.id ).remove();
},

/** Reset collection */
_reset: function() {
this.$nav.empty();
this.$content.empty();
},

/** Change tab */
_change: function( tab_model ) {
this.$( '#tab-' + tab_model.id )[ tab_model.get( 'hidden' ) ? 'hide' : 'show' ]();
},

/** Main template */
_template: function() {
return $( '<div/>' ).addClass( 'ui-tabs tabbable tabs-left' )
.append( $( '<ul/>' ).addClass( 'tab-navigation nav nav-tabs' ) )
.append( $( '<div/>' ).addClass( 'tab-content' ) );
},

/** Tab template */
_template_tab: function( options ) {
var $tmpl = $( '<li/>' ).addClass( 'tab-element' )
.attr( 'id', 'tab-' + options.id )
.append( $( '<a/>' ).attr( 'id', 'tab-title-link-' + options.id ) );
var $href = $tmpl.find( 'a' );
options.icon && $href.append( $( '<i/>' ).addClass( 'tab-icon fa' ).addClass( options.icon ) );
$href.append( $( '<span/>' ).attr( 'id', 'tab-title-text-' + options.id )
.addClass( 'tab-title-text' )
.append( options.title ) );
return $tmpl;
}
});

// Allows user to add new tabs
this.options.onnew && this.$nav.append( $( this._template_tab_new( this.options ) )
.tooltip( { title: 'Add a new tab', placement: 'bottom', container: self.$el } )
.on( 'click', function( e ) { self.options.onnew() } )
);
this.$tabnew = this.$nav.find( '.tab-new' );

// Remove all tooltips on click
this.$el.on( 'click', function() { $( '.tooltip' ).hide() } );
},

/** Returns current number of tabs */
size: function() {
return _.size( this.list );
},

/** Returns tab id for currently shown tab */
current: function() {
return this.$el.find( '.tab-pane.active' ).attr( 'id' );
},

/** Adds a new tab */
add: function( options ) {
var self = this;
var id = options.id;
var $tab_title = $( this._template_tab( options ) );
var $tab_content = $( '<div/>' ).attr( 'id', options.id ).addClass( 'tab-pane' );

// hide new tab if maximum number of tabs has been reached
this.list[ id ] = true;
if ( this.options.max && this.size() >= this.options.max ) {
this.$tabnew.hide();
}

// insert tab before new tab or as last tab
if ( this.options.onnew ) {
this.$tabnew.before( $tab_title );
} else {
this.$nav.append( $tab_title );
}

// assing delete callback if provided
if ( options.ondel ) {
$tab_title.find( '.tab-delete' ).tooltip( { title: 'Delete this tab', placement: 'bottom', container: self.$el } )
.on( 'click', function() { options.ondel() } );
} else {
$tab_title.tooltip( { title: options.tooltip, placement: 'bottom', container: self.$el } );
}
$tab_title.on( 'click', function( e ) {
e.preventDefault();
options.onclick ? options.onclick() : self.show( id );
});
this.$content.append( $tab_content.append( options.$el ) );

// assign current/first tab
if ( this.size() == 1 ) {
$tab_title.addClass( 'active' );
$tab_content.addClass( 'active' );
this.first_tab = id;
}
if ( !this.current_id ) {
this.current_id = id;
}
},

/** Delete tab */
del: function( id ) {
this.$( '#tab-' + id ).remove();
this.$( '#' + id ).remove();
this.first_tab = this.first_tab == id ? null : this.first_tab;
this.first_tab != null && this.show( this.first_tab );
this.list[ id ] && delete this.list[ id ];
if ( this.size() < this.options.max ) {
this.$el.find( '.ui-tabs-new' ).show();
}
},

/** Delete all tabs */
delAll: function() {
for ( var id in this.list ) {
this.del( id );
}
},

/** Show tab view and highlight a tab by id */
show: function( id ){
this.$el.fadeIn( 'fast' );
this.visible = true;
if ( id ) {
this.$( '#tab-' + this.current_id ).removeClass('active' );
this.$( '#' + this.current_id ).removeClass('active' );
this.$( '#tab-' + id ).addClass( 'active' );
this.$( '#' + id ).addClass( 'active' );
this.current_id = id;
}
this.options.onchange && this.options.onchange( id );
},

/** Hide tab view */
hide: function(){
this.$el.fadeOut( 'fast' );
this.visible = false;
},

/** Show tab */
showTab: function( id ) {
this.$( '#tab-' + id ).show();
},

/** hide tab */
hideTab: function( id ) {
this.$( '#tab-' + id ).hide();
},

/** Hide operation by id */
hideOperation: function( id ) {
this.$nav.find( '#' + id ).hide();
},

/** Show operation by id */
showOperation: function( id ) {
this.$nav.find( '#' + id ).show();
},

/** Reassign an operation to a new callback */
setOperation: function( id, callback ) {
this.$nav.find( '#' + id ).off('click').on( 'click', callback );
},

/** Set/Get title */
title: function( id, new_title ) {
var $el = this.$( '#tab-title-text-' + id );
new_title && $el.html( new_title );
return $el.html();
},

/** Enumerate titles */
retitle: function( new_title ) {
var index = 0;
for ( var id in this.list ) {
this.title( id, ++index + ': ' + new_title );
}
},

/** Main template */
_template: function( options ) {
return $( '<div/>' ).addClass( 'ui-tabs tabbable tabs-left' )
.append( $( '<ul/>' ).addClass( 'tab-navigation nav nav-tabs' )
.append( $( '<div/>' ).addClass( 'tab-operations' ) ) )
.append( $( '<div/>' ).addClass( 'tab-content' ) );
},

/** Default tab templates */
_template_tab: function( options ) {
var $tmpl = $( '<li/>' ).addClass( 'tab-element' )
.attr( 'id', 'tab-' + options.id )
.append( $( '<a/>' ).attr( 'id', 'tab-title-link-' + options.id ) );
var $href = $tmpl.find( 'a' );
options.icon && $href.append( $( '<i/>' ).addClass( 'tab-icon fa' ).addClass( options.icon ) );
$href.append( $( '<span/>' ).attr( 'id', 'tab-title-text-' + options.id )
.addClass( 'tab-title-text' )
.append( options.title ) );
options.ondel && $href.append( $( '<i/>' ).addClass( 'tab-delete fa fa-minus-circle' ) );
return $tmpl;
},

/** Template for 'new' tab */
_template_tab_new: function( options ) {
return $( '<li/>' ).addClass( 'tab-new' )
.append( $( '<a/>' ).attr( 'href', 'javascript:void(0);' )
.append( $( '<i/>' ).addClass( 'tab-icon fa fa-plus-circle' ) )
.append( options.title_new ) );
}
});

return {
View : View
}

});
return { View : View }
});