1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/5b5dde05d21f/ Changeset: 5b5dde05d21f User: carlfeberhard Date: 2014-12-09 18:06:41+00:00 Summary: Client build: modularize popup menu from ui.js Affected #: 15 files diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 client/galaxy/scripts/mvc/grid/grid-view.js --- a/client/galaxy/scripts/mvc/grid/grid-view.js +++ b/client/galaxy/scripts/mvc/grid/grid-view.js @@ -3,7 +3,11 @@ jQuery.ajaxSettings.traditional = true; // dependencies -define(['mvc/grid/grid-model', 'mvc/grid/grid-template', 'mvc/ui'], function(GridModel, Templates) { +define([ + 'mvc/grid/grid-model', + 'mvc/grid/grid-template', + "mvc/ui/popup-menu" +], function(GridModel, Templates, PopupMenu) { // grid view return Backbone.View.extend({ @@ -661,4 +665,4 @@ } }); -}); \ No newline at end of file +}); diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 client/galaxy/scripts/mvc/history/history-panel-edit.js --- a/client/galaxy/scripts/mvc/history/history-panel-edit.js +++ b/client/galaxy/scripts/mvc/history/history-panel-edit.js @@ -8,6 +8,7 @@ "mvc/tags", "mvc/annotations", "jq-plugins/ui/fa-icon-button", + "mvc/ui/popup-menu", "utils/localization" ], function( HPANEL, @@ -19,6 +20,7 @@ TAGS, ANNOTATIONS, faIconButton, + PopupMenu, _l ){ /* ============================================================================= diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 client/galaxy/scripts/mvc/history/options-menu.js --- a/client/galaxy/scripts/mvc/history/options-menu.js +++ b/client/galaxy/scripts/mvc/history/options-menu.js @@ -1,7 +1,8 @@ define([ + "mvc/ui/popup-menu", "mvc/base-mvc", "utils/localization" -], function( BASE_MVC, _l ){ +], function( PopupMenu, BASE_MVC, _l ){ // ============================================================================ var menu = [ { diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 client/galaxy/scripts/mvc/ui.js --- a/client/galaxy/scripts/mvc/ui.js +++ b/client/galaxy/scripts/mvc/ui.js @@ -169,320 +169,3 @@ // return menu return new IconButtonMenuView( {collection: buttons} ); }; - -// ============================================================================= -/** - * - */ -var Grid = Backbone.Collection.extend({ - -}); - -/** - * - */ -var GridView = Backbone.View.extend({ - -}); - -// ============================================================================= -/** - * view for a popup menu - */ -var PopupMenu = Backbone.View.extend({ -//TODO: maybe better as singleton off the Galaxy obj - /** Cache the desired button element and options, set up the button click handler - * NOTE: attaches this view as HTML/jQ data on the button for later use. - */ - initialize: function( $button, options ){ - // default settings - this.$button = $button; - if( !this.$button.size() ){ - this.$button = $( '<div/>' ); - } - this.options = options || []; - - // set up button click -> open menu behavior - var menu = this; - this.$button.click( function( event ){ - // if there's already a menu open, remove it - $( '.popmenu-wrapper' ).remove(); - menu._renderAndShow( event ); - return false; - }); - }, - - // render the menu, append to the page body at the click position, and set up the 'click-away' handlers, show - _renderAndShow: function( clickEvent ){ - this.render(); - this.$el.appendTo( 'body' ).css( this._getShownPosition( clickEvent )).show(); - this._setUpCloseBehavior(); - }, - - // render the menu - // this menu doesn't attach itself to the DOM ( see _renderAndShow ) - render: function(){ - // render the menu body absolute and hidden, fill with template - this.$el.addClass( 'popmenu-wrapper' ).hide() - .css({ position : 'absolute' }) - .html( this.template( this.$button.attr( 'id' ), this.options )); - - // set up behavior on each link/anchor elem - if( this.options.length ){ - var menu = this; - //precondition: there should be one option per li - this.$el.find( 'li' ).each( function( i, li ){ - var option = menu.options[i]; - - // if the option has 'func', call that function when the anchor is clicked - if( option.func ){ - $( this ).children( 'a.popupmenu-option' ).click( function( event ){ - option.func.call( menu, event, option ); - // bubble up so that an option click will call the close behavior - //return false; - }); - } - }); - } - return this; - }, - - template : function( id, options ){ - return [ - '<ul id="', id, '-menu" class="dropdown-menu">', this._templateOptions( options ), '</ul>' - ].join( '' ); - }, - - _templateOptions : function( options ){ - if( !options.length ){ - return '<li>(no options)</li>'; - } - return _.map( options, function( option ){ - if( option.divider ){ - return '<li class="divider"></li>'; - } else if( option.header ){ - return [ '<li class="head"><a href="javascript:void(0);">', option.html, '</a></li>' ].join( '' ); - } - var href = option.href || 'javascript:void(0);', - target = ( option.target )?( ' target="' + option.target + '"' ):( '' ), - check = ( option.checked )?( '<span class="fa fa-check"></span>' ):( '' ); - return [ - '<li><a class="popupmenu-option" href="', href, '"', target, '>', - check, option.html, - '</a></li>' - ].join( '' ); - }).join( '' ); - }, - - // get the absolute position/offset for the menu - _getShownPosition : function( clickEvent ){ - - // display menu horiz. centered on click... - var menuWidth = this.$el.width(); - var x = clickEvent.pageX - menuWidth / 2 ; - - // adjust to handle horiz. scroll and window dimensions ( draw entirely on visible screen area ) - x = Math.min( x, $( document ).scrollLeft() + $( window ).width() - menuWidth - 5 ); - x = Math.max( x, $( document ).scrollLeft() + 5 ); - return { - top: clickEvent.pageY, - left: x - }; - }, - - // bind an event handler to all available frames so that when anything is clicked - // the menu is removed from the DOM and the event handler unbinds itself - _setUpCloseBehavior: function(){ - var menu = this; -//TODO: alternately: focus hack, blocking overlay, jquery.blockui - - // function to close popup and unbind itself - function closePopup( event ){ - $( document ).off( 'click.close_popup' ); - if( window.parent !== window ){ - try { - $( window.parent.document ).off( "click.close_popup" ); - } catch( err ){} - } else { - try { - $( 'iframe#galaxy_main' ).contents().off( "click.close_popup" ); - } catch( err ){} - } - menu.remove(); - } - - $( 'html' ).one( "click.close_popup", closePopup ); - if( window.parent !== window ){ - try { - $( window.parent.document ).find( 'html' ).one( "click.close_popup", closePopup ); - } catch( err ){} - } else { - try { - $( 'iframe#galaxy_main' ).contents().one( "click.close_popup", closePopup ); - } catch( err ){} - } - }, - - // add a menu option/item at the given index - addItem: function( item, index ){ - // append to end if no index - index = ( index >= 0 ) ? index : this.options.length; - this.options.splice( index, 0, item ); - return this; - }, - - // remove a menu option/item at the given index - removeItem: function( index ){ - if( index >=0 ){ - this.options.splice( index, 1 ); - } - return this; - }, - - // search for a menu option by its html - findIndexByHtml: function( html ){ - for( var i = 0; i < this.options.length; i++ ){ - if( _.has( this.options[i], 'html' ) && ( this.options[i].html === html )){ - return i; - } - } - return null; - }, - - // search for a menu option by its html - findItemByHtml: function( html ){ - return this.options[( this.findIndexByHtml( html ))]; - }, - - // string representation - toString: function(){ - return 'PopupMenu'; - } -}); -/** shortcut to new for when you don't need to preserve the ref */ -PopupMenu.create = function _create( $button, options ){ - return new PopupMenu( $button, options ); -}; - -// ----------------------------------------------------------------------------- -// the following class functions are bridges from the original make_popupmenu and make_popup_menus -// to the newer backbone.js PopupMenu - -/** Create a PopupMenu from simple map initial_options activated by clicking button_element. - * Converts initial_options to object array used by PopupMenu. - * @param {jQuery|DOMElement} button_element element which, when clicked, activates menu - * @param {Object} initial_options map of key -> values, where - * key is option text, value is fn to call when option is clicked - * @returns {PopupMenu} the PopupMenu created - */ -PopupMenu.make_popupmenu = function( button_element, initial_options ){ - var convertedOptions = []; - _.each( initial_options, function( optionVal, optionKey ){ - var newOption = { html: optionKey }; - - // keys with null values indicate: header - if( optionVal === null ){ // !optionVal? (null only?) - newOption.header = true; - - // keys with function values indicate: a menu option - } else if( jQuery.type( optionVal ) === 'function' ){ - newOption.func = optionVal; - } - //TODO:?? any other special optionVals? - // there was no divider option originally - convertedOptions.push( newOption ); - }); - return new PopupMenu( $( button_element ), convertedOptions ); -}; - -/** Find all anchors in $parent (using selector) and covert anchors into a PopupMenu options map. - * @param {jQuery} $parent the element that contains the links to convert to options - * @param {String} selector jq selector string to find links - * @returns {Object[]} the options array to initialize a PopupMenu - */ -//TODO: lose parent and selector, pass in array of links, use map to return options -PopupMenu.convertLinksToOptions = function( $parent, selector ){ - $parent = $( $parent ); - selector = selector || 'a'; - var options = []; - $parent.find( selector ).each( function( elem, i ){ - var option = {}, $link = $( elem ); - - // convert link text to the option text (html) and the href into the option func - option.html = $link.text(); - if( $link.attr( 'href' ) ){ - var linkHref = $link.attr( 'href' ), - linkTarget = $link.attr( 'target' ), - confirmText = $link.attr( 'confirm' ); - - option.func = function(){ - // if there's a "confirm" attribute, throw up a confirmation dialog, and - // if the user cancels - do nothing - if( ( confirmText ) && ( !confirm( confirmText ) ) ){ return; } - - // if there's no confirm attribute, or the user accepted the confirm dialog: - switch( linkTarget ){ - // relocate the center panel - case '_parent': - window.parent.location = linkHref; - break; - - // relocate the entire window - case '_top': - window.top.location = linkHref; - break; - - // relocate this panel - default: - window.location = linkHref; - } - }; - } - options.push( option ); - }); - return options; -}; - -/** Create a single popupmenu from existing DOM button and anchor elements - * @param {jQuery} $buttonElement the element that when clicked will open the menu - * @param {jQuery} $menuElement the element that contains the anchors to convert into a menu - * @param {String} menuElementLinkSelector jq selector string used to find anchors to be made into menu options - * @returns {PopupMenu} the PopupMenu (Backbone View) that can render, control the menu - */ -PopupMenu.fromExistingDom = function( $buttonElement, $menuElement, menuElementLinkSelector ){ - $buttonElement = $( $buttonElement ); - $menuElement = $( $menuElement ); - var options = PopupMenu.convertLinksToOptions( $menuElement, menuElementLinkSelector ); - // we're done with the menu (having converted it to an options map) - $menuElement.remove(); - return new PopupMenu( $buttonElement, options ); -}; - -/** Create all popupmenus within a document or a more specific element - * @param {DOMElement} parent the DOM element in which to search for popupmenus to build (defaults to document) - * @param {String} menuSelector jq selector string to find popupmenu menu elements (defaults to "div[popupmenu]") - * @param {Function} buttonSelectorBuildFn the function to build the jq button selector. - * Will be passed $menuElement, parent. - * (Defaults to return '#' + $menuElement.attr( 'popupmenu' ); ) - * @returns {PopupMenu[]} array of popupmenus created - */ -PopupMenu.make_popup_menus = function( parent, menuSelector, buttonSelectorBuildFn ){ - parent = parent || document; - // orig. Glx popupmenu menus have a (non-std) attribute 'popupmenu' - // which contains the id of the button that activates the menu - menuSelector = menuSelector || 'div[popupmenu]'; - // default to (orig. Glx) matching button to menu by using the popupmenu attr of the menu as the id of the button - buttonSelectorBuildFn = buttonSelectorBuildFn || function( $menuElement, parent ){ - return '#' + $menuElement.attr( 'popupmenu' ); - }; - - // aggregate and return all PopupMenus - var popupMenusCreated = []; - $( parent ).find( menuSelector ).each( function(){ - var $menuElement = $( this ), - $buttonElement = $( parent ).find( buttonSelectorBuildFn( $menuElement, parent ) ); - popupMenusCreated.push( PopupMenu.fromDom( $buttonElement, $menuElement ) ); - $buttonElement.addClass( 'popup' ); - }); - return popupMenusCreated; -}; diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 client/galaxy/scripts/mvc/ui/popup-menu.js --- /dev/null +++ b/client/galaxy/scripts/mvc/ui/popup-menu.js @@ -0,0 +1,311 @@ +define([ + //jquery + //backbone +], function(){ +// ============================================================================= +/** + * view for a popup menu + */ +var PopupMenu = Backbone.View.extend({ +//TODO: maybe better as singleton off the Galaxy obj + /** Cache the desired button element and options, set up the button click handler + * NOTE: attaches this view as HTML/jQ data on the button for later use. + */ + initialize: function( $button, options ){ + // default settings + this.$button = $button; + if( !this.$button.size() ){ + this.$button = $( '<div/>' ); + } + this.options = options || []; + + // set up button click -> open menu behavior + var menu = this; + this.$button.click( function( event ){ + // if there's already a menu open, remove it + $( '.popmenu-wrapper' ).remove(); + menu._renderAndShow( event ); + return false; + }); + }, + + // render the menu, append to the page body at the click position, and set up the 'click-away' handlers, show + _renderAndShow: function( clickEvent ){ + this.render(); + this.$el.appendTo( 'body' ).css( this._getShownPosition( clickEvent )).show(); + this._setUpCloseBehavior(); + }, + + // render the menu + // this menu doesn't attach itself to the DOM ( see _renderAndShow ) + render: function(){ + // render the menu body absolute and hidden, fill with template + this.$el.addClass( 'popmenu-wrapper' ).hide() + .css({ position : 'absolute' }) + .html( this.template( this.$button.attr( 'id' ), this.options )); + + // set up behavior on each link/anchor elem + if( this.options.length ){ + var menu = this; + //precondition: there should be one option per li + this.$el.find( 'li' ).each( function( i, li ){ + var option = menu.options[i]; + + // if the option has 'func', call that function when the anchor is clicked + if( option.func ){ + $( this ).children( 'a.popupmenu-option' ).click( function( event ){ + option.func.call( menu, event, option ); + // bubble up so that an option click will call the close behavior + //return false; + }); + } + }); + } + return this; + }, + + template : function( id, options ){ + return [ + '<ul id="', id, '-menu" class="dropdown-menu">', this._templateOptions( options ), '</ul>' + ].join( '' ); + }, + + _templateOptions : function( options ){ + if( !options.length ){ + return '<li>(no options)</li>'; + } + return _.map( options, function( option ){ + if( option.divider ){ + return '<li class="divider"></li>'; + } else if( option.header ){ + return [ '<li class="head"><a href="javascript:void(0);">', option.html, '</a></li>' ].join( '' ); + } + var href = option.href || 'javascript:void(0);', + target = ( option.target )?( ' target="' + option.target + '"' ):( '' ), + check = ( option.checked )?( '<span class="fa fa-check"></span>' ):( '' ); + return [ + '<li><a class="popupmenu-option" href="', href, '"', target, '>', + check, option.html, + '</a></li>' + ].join( '' ); + }).join( '' ); + }, + + // get the absolute position/offset for the menu + _getShownPosition : function( clickEvent ){ + + // display menu horiz. centered on click... + var menuWidth = this.$el.width(); + var x = clickEvent.pageX - menuWidth / 2 ; + + // adjust to handle horiz. scroll and window dimensions ( draw entirely on visible screen area ) + x = Math.min( x, $( document ).scrollLeft() + $( window ).width() - menuWidth - 5 ); + x = Math.max( x, $( document ).scrollLeft() + 5 ); + return { + top: clickEvent.pageY, + left: x + }; + }, + + // bind an event handler to all available frames so that when anything is clicked + // the menu is removed from the DOM and the event handler unbinds itself + _setUpCloseBehavior: function(){ + var menu = this; +//TODO: alternately: focus hack, blocking overlay, jquery.blockui + + // function to close popup and unbind itself + function closePopup( event ){ + $( document ).off( 'click.close_popup' ); + if( window.parent !== window ){ + try { + $( window.parent.document ).off( "click.close_popup" ); + } catch( err ){} + } else { + try { + $( 'iframe#galaxy_main' ).contents().off( "click.close_popup" ); + } catch( err ){} + } + menu.remove(); + } + + $( 'html' ).one( "click.close_popup", closePopup ); + if( window.parent !== window ){ + try { + $( window.parent.document ).find( 'html' ).one( "click.close_popup", closePopup ); + } catch( err ){} + } else { + try { + $( 'iframe#galaxy_main' ).contents().one( "click.close_popup", closePopup ); + } catch( err ){} + } + }, + + // add a menu option/item at the given index + addItem: function( item, index ){ + // append to end if no index + index = ( index >= 0 ) ? index : this.options.length; + this.options.splice( index, 0, item ); + return this; + }, + + // remove a menu option/item at the given index + removeItem: function( index ){ + if( index >=0 ){ + this.options.splice( index, 1 ); + } + return this; + }, + + // search for a menu option by its html + findIndexByHtml: function( html ){ + for( var i = 0; i < this.options.length; i++ ){ + if( _.has( this.options[i], 'html' ) && ( this.options[i].html === html )){ + return i; + } + } + return null; + }, + + // search for a menu option by its html + findItemByHtml: function( html ){ + return this.options[( this.findIndexByHtml( html ))]; + }, + + // string representation + toString: function(){ + return 'PopupMenu'; + } +}); +/** shortcut to new for when you don't need to preserve the ref */ +PopupMenu.create = function _create( $button, options ){ + return new PopupMenu( $button, options ); +}; + +// ----------------------------------------------------------------------------- +// the following class functions are bridges from the original make_popupmenu and make_popup_menus +// to the newer backbone.js PopupMenu + +/** Create a PopupMenu from simple map initial_options activated by clicking button_element. + * Converts initial_options to object array used by PopupMenu. + * @param {jQuery|DOMElement} button_element element which, when clicked, activates menu + * @param {Object} initial_options map of key -> values, where + * key is option text, value is fn to call when option is clicked + * @returns {PopupMenu} the PopupMenu created + */ +PopupMenu.make_popupmenu = function( button_element, initial_options ){ + var convertedOptions = []; + _.each( initial_options, function( optionVal, optionKey ){ + var newOption = { html: optionKey }; + + // keys with null values indicate: header + if( optionVal === null ){ // !optionVal? (null only?) + newOption.header = true; + + // keys with function values indicate: a menu option + } else if( jQuery.type( optionVal ) === 'function' ){ + newOption.func = optionVal; + } + //TODO:?? any other special optionVals? + // there was no divider option originally + convertedOptions.push( newOption ); + }); + return new PopupMenu( $( button_element ), convertedOptions ); +}; + +/** Find all anchors in $parent (using selector) and covert anchors into a PopupMenu options map. + * @param {jQuery} $parent the element that contains the links to convert to options + * @param {String} selector jq selector string to find links + * @returns {Object[]} the options array to initialize a PopupMenu + */ +//TODO: lose parent and selector, pass in array of links, use map to return options +PopupMenu.convertLinksToOptions = function( $parent, selector ){ + $parent = $( $parent ); + selector = selector || 'a'; + var options = []; + $parent.find( selector ).each( function( elem, i ){ + var option = {}, $link = $( elem ); + + // convert link text to the option text (html) and the href into the option func + option.html = $link.text(); + if( $link.attr( 'href' ) ){ + var linkHref = $link.attr( 'href' ), + linkTarget = $link.attr( 'target' ), + confirmText = $link.attr( 'confirm' ); + + option.func = function(){ + // if there's a "confirm" attribute, throw up a confirmation dialog, and + // if the user cancels - do nothing + if( ( confirmText ) && ( !confirm( confirmText ) ) ){ return; } + + // if there's no confirm attribute, or the user accepted the confirm dialog: + switch( linkTarget ){ + // relocate the center panel + case '_parent': + window.parent.location = linkHref; + break; + + // relocate the entire window + case '_top': + window.top.location = linkHref; + break; + + // relocate this panel + default: + window.location = linkHref; + } + }; + } + options.push( option ); + }); + return options; +}; + +/** Create a single popupmenu from existing DOM button and anchor elements + * @param {jQuery} $buttonElement the element that when clicked will open the menu + * @param {jQuery} $menuElement the element that contains the anchors to convert into a menu + * @param {String} menuElementLinkSelector jq selector string used to find anchors to be made into menu options + * @returns {PopupMenu} the PopupMenu (Backbone View) that can render, control the menu + */ +PopupMenu.fromExistingDom = function( $buttonElement, $menuElement, menuElementLinkSelector ){ + $buttonElement = $( $buttonElement ); + $menuElement = $( $menuElement ); + var options = PopupMenu.convertLinksToOptions( $menuElement, menuElementLinkSelector ); + // we're done with the menu (having converted it to an options map) + $menuElement.remove(); + return new PopupMenu( $buttonElement, options ); +}; + +/** Create all popupmenus within a document or a more specific element + * @param {DOMElement} parent the DOM element in which to search for popupmenus to build (defaults to document) + * @param {String} menuSelector jq selector string to find popupmenu menu elements (defaults to "div[popupmenu]") + * @param {Function} buttonSelectorBuildFn the function to build the jq button selector. + * Will be passed $menuElement, parent. + * (Defaults to return '#' + $menuElement.attr( 'popupmenu' ); ) + * @returns {PopupMenu[]} array of popupmenus created + */ +PopupMenu.make_popup_menus = function( parent, menuSelector, buttonSelectorBuildFn ){ + parent = parent || document; + // orig. Glx popupmenu menus have a (non-std) attribute 'popupmenu' + // which contains the id of the button that activates the menu + menuSelector = menuSelector || 'div[popupmenu]'; + // default to (orig. Glx) matching button to menu by using the popupmenu attr of the menu as the id of the button + buttonSelectorBuildFn = buttonSelectorBuildFn || function( $menuElement, parent ){ + return '#' + $menuElement.attr( 'popupmenu' ); + }; + + // aggregate and return all PopupMenus + var popupMenusCreated = []; + $( parent ).find( menuSelector ).each( function(){ + var $menuElement = $( this ), + $buttonElement = $( parent ).find( buttonSelectorBuildFn( $menuElement, parent ) ); + popupMenusCreated.push( PopupMenu.fromDom( $buttonElement, $menuElement ) ); + $buttonElement.addClass( 'popup' ); + }); + return popupMenusCreated; +}; + + +// ============================================================================= + return PopupMenu; +}); + diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/mvc/grid/grid-view.js --- a/static/scripts/mvc/grid/grid-view.js +++ b/static/scripts/mvc/grid/grid-view.js @@ -3,7 +3,11 @@ jQuery.ajaxSettings.traditional = true; // dependencies -define(['mvc/grid/grid-model', 'mvc/grid/grid-template', 'mvc/ui'], function(GridModel, Templates) { +define([ + 'mvc/grid/grid-model', + 'mvc/grid/grid-template', + "mvc/ui/popup-menu" +], function(GridModel, Templates, PopupMenu) { // grid view return Backbone.View.extend({ @@ -661,4 +665,4 @@ } }); -}); \ No newline at end of file +}); diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/mvc/history/history-panel-edit.js --- a/static/scripts/mvc/history/history-panel-edit.js +++ b/static/scripts/mvc/history/history-panel-edit.js @@ -8,6 +8,7 @@ "mvc/tags", "mvc/annotations", "jq-plugins/ui/fa-icon-button", + "mvc/ui/popup-menu", "utils/localization" ], function( HPANEL, @@ -19,6 +20,7 @@ TAGS, ANNOTATIONS, faIconButton, + PopupMenu, _l ){ /* ============================================================================= diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/mvc/history/options-menu.js --- a/static/scripts/mvc/history/options-menu.js +++ b/static/scripts/mvc/history/options-menu.js @@ -1,7 +1,8 @@ define([ + "mvc/ui/popup-menu", "mvc/base-mvc", "utils/localization" -], function( BASE_MVC, _l ){ +], function( PopupMenu, BASE_MVC, _l ){ // ============================================================================ var menu = [ { diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/mvc/ui.js --- a/static/scripts/mvc/ui.js +++ b/static/scripts/mvc/ui.js @@ -169,320 +169,3 @@ // return menu return new IconButtonMenuView( {collection: buttons} ); }; - -// ============================================================================= -/** - * - */ -var Grid = Backbone.Collection.extend({ - -}); - -/** - * - */ -var GridView = Backbone.View.extend({ - -}); - -// ============================================================================= -/** - * view for a popup menu - */ -var PopupMenu = Backbone.View.extend({ -//TODO: maybe better as singleton off the Galaxy obj - /** Cache the desired button element and options, set up the button click handler - * NOTE: attaches this view as HTML/jQ data on the button for later use. - */ - initialize: function( $button, options ){ - // default settings - this.$button = $button; - if( !this.$button.size() ){ - this.$button = $( '<div/>' ); - } - this.options = options || []; - - // set up button click -> open menu behavior - var menu = this; - this.$button.click( function( event ){ - // if there's already a menu open, remove it - $( '.popmenu-wrapper' ).remove(); - menu._renderAndShow( event ); - return false; - }); - }, - - // render the menu, append to the page body at the click position, and set up the 'click-away' handlers, show - _renderAndShow: function( clickEvent ){ - this.render(); - this.$el.appendTo( 'body' ).css( this._getShownPosition( clickEvent )).show(); - this._setUpCloseBehavior(); - }, - - // render the menu - // this menu doesn't attach itself to the DOM ( see _renderAndShow ) - render: function(){ - // render the menu body absolute and hidden, fill with template - this.$el.addClass( 'popmenu-wrapper' ).hide() - .css({ position : 'absolute' }) - .html( this.template( this.$button.attr( 'id' ), this.options )); - - // set up behavior on each link/anchor elem - if( this.options.length ){ - var menu = this; - //precondition: there should be one option per li - this.$el.find( 'li' ).each( function( i, li ){ - var option = menu.options[i]; - - // if the option has 'func', call that function when the anchor is clicked - if( option.func ){ - $( this ).children( 'a.popupmenu-option' ).click( function( event ){ - option.func.call( menu, event, option ); - // bubble up so that an option click will call the close behavior - //return false; - }); - } - }); - } - return this; - }, - - template : function( id, options ){ - return [ - '<ul id="', id, '-menu" class="dropdown-menu">', this._templateOptions( options ), '</ul>' - ].join( '' ); - }, - - _templateOptions : function( options ){ - if( !options.length ){ - return '<li>(no options)</li>'; - } - return _.map( options, function( option ){ - if( option.divider ){ - return '<li class="divider"></li>'; - } else if( option.header ){ - return [ '<li class="head"><a href="javascript:void(0);">', option.html, '</a></li>' ].join( '' ); - } - var href = option.href || 'javascript:void(0);', - target = ( option.target )?( ' target="' + option.target + '"' ):( '' ), - check = ( option.checked )?( '<span class="fa fa-check"></span>' ):( '' ); - return [ - '<li><a class="popupmenu-option" href="', href, '"', target, '>', - check, option.html, - '</a></li>' - ].join( '' ); - }).join( '' ); - }, - - // get the absolute position/offset for the menu - _getShownPosition : function( clickEvent ){ - - // display menu horiz. centered on click... - var menuWidth = this.$el.width(); - var x = clickEvent.pageX - menuWidth / 2 ; - - // adjust to handle horiz. scroll and window dimensions ( draw entirely on visible screen area ) - x = Math.min( x, $( document ).scrollLeft() + $( window ).width() - menuWidth - 5 ); - x = Math.max( x, $( document ).scrollLeft() + 5 ); - return { - top: clickEvent.pageY, - left: x - }; - }, - - // bind an event handler to all available frames so that when anything is clicked - // the menu is removed from the DOM and the event handler unbinds itself - _setUpCloseBehavior: function(){ - var menu = this; -//TODO: alternately: focus hack, blocking overlay, jquery.blockui - - // function to close popup and unbind itself - function closePopup( event ){ - $( document ).off( 'click.close_popup' ); - if( window.parent !== window ){ - try { - $( window.parent.document ).off( "click.close_popup" ); - } catch( err ){} - } else { - try { - $( 'iframe#galaxy_main' ).contents().off( "click.close_popup" ); - } catch( err ){} - } - menu.remove(); - } - - $( 'html' ).one( "click.close_popup", closePopup ); - if( window.parent !== window ){ - try { - $( window.parent.document ).find( 'html' ).one( "click.close_popup", closePopup ); - } catch( err ){} - } else { - try { - $( 'iframe#galaxy_main' ).contents().one( "click.close_popup", closePopup ); - } catch( err ){} - } - }, - - // add a menu option/item at the given index - addItem: function( item, index ){ - // append to end if no index - index = ( index >= 0 ) ? index : this.options.length; - this.options.splice( index, 0, item ); - return this; - }, - - // remove a menu option/item at the given index - removeItem: function( index ){ - if( index >=0 ){ - this.options.splice( index, 1 ); - } - return this; - }, - - // search for a menu option by its html - findIndexByHtml: function( html ){ - for( var i = 0; i < this.options.length; i++ ){ - if( _.has( this.options[i], 'html' ) && ( this.options[i].html === html )){ - return i; - } - } - return null; - }, - - // search for a menu option by its html - findItemByHtml: function( html ){ - return this.options[( this.findIndexByHtml( html ))]; - }, - - // string representation - toString: function(){ - return 'PopupMenu'; - } -}); -/** shortcut to new for when you don't need to preserve the ref */ -PopupMenu.create = function _create( $button, options ){ - return new PopupMenu( $button, options ); -}; - -// ----------------------------------------------------------------------------- -// the following class functions are bridges from the original make_popupmenu and make_popup_menus -// to the newer backbone.js PopupMenu - -/** Create a PopupMenu from simple map initial_options activated by clicking button_element. - * Converts initial_options to object array used by PopupMenu. - * @param {jQuery|DOMElement} button_element element which, when clicked, activates menu - * @param {Object} initial_options map of key -> values, where - * key is option text, value is fn to call when option is clicked - * @returns {PopupMenu} the PopupMenu created - */ -PopupMenu.make_popupmenu = function( button_element, initial_options ){ - var convertedOptions = []; - _.each( initial_options, function( optionVal, optionKey ){ - var newOption = { html: optionKey }; - - // keys with null values indicate: header - if( optionVal === null ){ // !optionVal? (null only?) - newOption.header = true; - - // keys with function values indicate: a menu option - } else if( jQuery.type( optionVal ) === 'function' ){ - newOption.func = optionVal; - } - //TODO:?? any other special optionVals? - // there was no divider option originally - convertedOptions.push( newOption ); - }); - return new PopupMenu( $( button_element ), convertedOptions ); -}; - -/** Find all anchors in $parent (using selector) and covert anchors into a PopupMenu options map. - * @param {jQuery} $parent the element that contains the links to convert to options - * @param {String} selector jq selector string to find links - * @returns {Object[]} the options array to initialize a PopupMenu - */ -//TODO: lose parent and selector, pass in array of links, use map to return options -PopupMenu.convertLinksToOptions = function( $parent, selector ){ - $parent = $( $parent ); - selector = selector || 'a'; - var options = []; - $parent.find( selector ).each( function( elem, i ){ - var option = {}, $link = $( elem ); - - // convert link text to the option text (html) and the href into the option func - option.html = $link.text(); - if( $link.attr( 'href' ) ){ - var linkHref = $link.attr( 'href' ), - linkTarget = $link.attr( 'target' ), - confirmText = $link.attr( 'confirm' ); - - option.func = function(){ - // if there's a "confirm" attribute, throw up a confirmation dialog, and - // if the user cancels - do nothing - if( ( confirmText ) && ( !confirm( confirmText ) ) ){ return; } - - // if there's no confirm attribute, or the user accepted the confirm dialog: - switch( linkTarget ){ - // relocate the center panel - case '_parent': - window.parent.location = linkHref; - break; - - // relocate the entire window - case '_top': - window.top.location = linkHref; - break; - - // relocate this panel - default: - window.location = linkHref; - } - }; - } - options.push( option ); - }); - return options; -}; - -/** Create a single popupmenu from existing DOM button and anchor elements - * @param {jQuery} $buttonElement the element that when clicked will open the menu - * @param {jQuery} $menuElement the element that contains the anchors to convert into a menu - * @param {String} menuElementLinkSelector jq selector string used to find anchors to be made into menu options - * @returns {PopupMenu} the PopupMenu (Backbone View) that can render, control the menu - */ -PopupMenu.fromExistingDom = function( $buttonElement, $menuElement, menuElementLinkSelector ){ - $buttonElement = $( $buttonElement ); - $menuElement = $( $menuElement ); - var options = PopupMenu.convertLinksToOptions( $menuElement, menuElementLinkSelector ); - // we're done with the menu (having converted it to an options map) - $menuElement.remove(); - return new PopupMenu( $buttonElement, options ); -}; - -/** Create all popupmenus within a document or a more specific element - * @param {DOMElement} parent the DOM element in which to search for popupmenus to build (defaults to document) - * @param {String} menuSelector jq selector string to find popupmenu menu elements (defaults to "div[popupmenu]") - * @param {Function} buttonSelectorBuildFn the function to build the jq button selector. - * Will be passed $menuElement, parent. - * (Defaults to return '#' + $menuElement.attr( 'popupmenu' ); ) - * @returns {PopupMenu[]} array of popupmenus created - */ -PopupMenu.make_popup_menus = function( parent, menuSelector, buttonSelectorBuildFn ){ - parent = parent || document; - // orig. Glx popupmenu menus have a (non-std) attribute 'popupmenu' - // which contains the id of the button that activates the menu - menuSelector = menuSelector || 'div[popupmenu]'; - // default to (orig. Glx) matching button to menu by using the popupmenu attr of the menu as the id of the button - buttonSelectorBuildFn = buttonSelectorBuildFn || function( $menuElement, parent ){ - return '#' + $menuElement.attr( 'popupmenu' ); - }; - - // aggregate and return all PopupMenus - var popupMenusCreated = []; - $( parent ).find( menuSelector ).each( function(){ - var $menuElement = $( this ), - $buttonElement = $( parent ).find( buttonSelectorBuildFn( $menuElement, parent ) ); - popupMenusCreated.push( PopupMenu.fromDom( $buttonElement, $menuElement ) ); - $buttonElement.addClass( 'popup' ); - }); - return popupMenusCreated; -}; diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/mvc/ui/popup-menu.js --- /dev/null +++ b/static/scripts/mvc/ui/popup-menu.js @@ -0,0 +1,311 @@ +define([ + //jquery + //backbone +], function(){ +// ============================================================================= +/** + * view for a popup menu + */ +var PopupMenu = Backbone.View.extend({ +//TODO: maybe better as singleton off the Galaxy obj + /** Cache the desired button element and options, set up the button click handler + * NOTE: attaches this view as HTML/jQ data on the button for later use. + */ + initialize: function( $button, options ){ + // default settings + this.$button = $button; + if( !this.$button.size() ){ + this.$button = $( '<div/>' ); + } + this.options = options || []; + + // set up button click -> open menu behavior + var menu = this; + this.$button.click( function( event ){ + // if there's already a menu open, remove it + $( '.popmenu-wrapper' ).remove(); + menu._renderAndShow( event ); + return false; + }); + }, + + // render the menu, append to the page body at the click position, and set up the 'click-away' handlers, show + _renderAndShow: function( clickEvent ){ + this.render(); + this.$el.appendTo( 'body' ).css( this._getShownPosition( clickEvent )).show(); + this._setUpCloseBehavior(); + }, + + // render the menu + // this menu doesn't attach itself to the DOM ( see _renderAndShow ) + render: function(){ + // render the menu body absolute and hidden, fill with template + this.$el.addClass( 'popmenu-wrapper' ).hide() + .css({ position : 'absolute' }) + .html( this.template( this.$button.attr( 'id' ), this.options )); + + // set up behavior on each link/anchor elem + if( this.options.length ){ + var menu = this; + //precondition: there should be one option per li + this.$el.find( 'li' ).each( function( i, li ){ + var option = menu.options[i]; + + // if the option has 'func', call that function when the anchor is clicked + if( option.func ){ + $( this ).children( 'a.popupmenu-option' ).click( function( event ){ + option.func.call( menu, event, option ); + // bubble up so that an option click will call the close behavior + //return false; + }); + } + }); + } + return this; + }, + + template : function( id, options ){ + return [ + '<ul id="', id, '-menu" class="dropdown-menu">', this._templateOptions( options ), '</ul>' + ].join( '' ); + }, + + _templateOptions : function( options ){ + if( !options.length ){ + return '<li>(no options)</li>'; + } + return _.map( options, function( option ){ + if( option.divider ){ + return '<li class="divider"></li>'; + } else if( option.header ){ + return [ '<li class="head"><a href="javascript:void(0);">', option.html, '</a></li>' ].join( '' ); + } + var href = option.href || 'javascript:void(0);', + target = ( option.target )?( ' target="' + option.target + '"' ):( '' ), + check = ( option.checked )?( '<span class="fa fa-check"></span>' ):( '' ); + return [ + '<li><a class="popupmenu-option" href="', href, '"', target, '>', + check, option.html, + '</a></li>' + ].join( '' ); + }).join( '' ); + }, + + // get the absolute position/offset for the menu + _getShownPosition : function( clickEvent ){ + + // display menu horiz. centered on click... + var menuWidth = this.$el.width(); + var x = clickEvent.pageX - menuWidth / 2 ; + + // adjust to handle horiz. scroll and window dimensions ( draw entirely on visible screen area ) + x = Math.min( x, $( document ).scrollLeft() + $( window ).width() - menuWidth - 5 ); + x = Math.max( x, $( document ).scrollLeft() + 5 ); + return { + top: clickEvent.pageY, + left: x + }; + }, + + // bind an event handler to all available frames so that when anything is clicked + // the menu is removed from the DOM and the event handler unbinds itself + _setUpCloseBehavior: function(){ + var menu = this; +//TODO: alternately: focus hack, blocking overlay, jquery.blockui + + // function to close popup and unbind itself + function closePopup( event ){ + $( document ).off( 'click.close_popup' ); + if( window.parent !== window ){ + try { + $( window.parent.document ).off( "click.close_popup" ); + } catch( err ){} + } else { + try { + $( 'iframe#galaxy_main' ).contents().off( "click.close_popup" ); + } catch( err ){} + } + menu.remove(); + } + + $( 'html' ).one( "click.close_popup", closePopup ); + if( window.parent !== window ){ + try { + $( window.parent.document ).find( 'html' ).one( "click.close_popup", closePopup ); + } catch( err ){} + } else { + try { + $( 'iframe#galaxy_main' ).contents().one( "click.close_popup", closePopup ); + } catch( err ){} + } + }, + + // add a menu option/item at the given index + addItem: function( item, index ){ + // append to end if no index + index = ( index >= 0 ) ? index : this.options.length; + this.options.splice( index, 0, item ); + return this; + }, + + // remove a menu option/item at the given index + removeItem: function( index ){ + if( index >=0 ){ + this.options.splice( index, 1 ); + } + return this; + }, + + // search for a menu option by its html + findIndexByHtml: function( html ){ + for( var i = 0; i < this.options.length; i++ ){ + if( _.has( this.options[i], 'html' ) && ( this.options[i].html === html )){ + return i; + } + } + return null; + }, + + // search for a menu option by its html + findItemByHtml: function( html ){ + return this.options[( this.findIndexByHtml( html ))]; + }, + + // string representation + toString: function(){ + return 'PopupMenu'; + } +}); +/** shortcut to new for when you don't need to preserve the ref */ +PopupMenu.create = function _create( $button, options ){ + return new PopupMenu( $button, options ); +}; + +// ----------------------------------------------------------------------------- +// the following class functions are bridges from the original make_popupmenu and make_popup_menus +// to the newer backbone.js PopupMenu + +/** Create a PopupMenu from simple map initial_options activated by clicking button_element. + * Converts initial_options to object array used by PopupMenu. + * @param {jQuery|DOMElement} button_element element which, when clicked, activates menu + * @param {Object} initial_options map of key -> values, where + * key is option text, value is fn to call when option is clicked + * @returns {PopupMenu} the PopupMenu created + */ +PopupMenu.make_popupmenu = function( button_element, initial_options ){ + var convertedOptions = []; + _.each( initial_options, function( optionVal, optionKey ){ + var newOption = { html: optionKey }; + + // keys with null values indicate: header + if( optionVal === null ){ // !optionVal? (null only?) + newOption.header = true; + + // keys with function values indicate: a menu option + } else if( jQuery.type( optionVal ) === 'function' ){ + newOption.func = optionVal; + } + //TODO:?? any other special optionVals? + // there was no divider option originally + convertedOptions.push( newOption ); + }); + return new PopupMenu( $( button_element ), convertedOptions ); +}; + +/** Find all anchors in $parent (using selector) and covert anchors into a PopupMenu options map. + * @param {jQuery} $parent the element that contains the links to convert to options + * @param {String} selector jq selector string to find links + * @returns {Object[]} the options array to initialize a PopupMenu + */ +//TODO: lose parent and selector, pass in array of links, use map to return options +PopupMenu.convertLinksToOptions = function( $parent, selector ){ + $parent = $( $parent ); + selector = selector || 'a'; + var options = []; + $parent.find( selector ).each( function( elem, i ){ + var option = {}, $link = $( elem ); + + // convert link text to the option text (html) and the href into the option func + option.html = $link.text(); + if( $link.attr( 'href' ) ){ + var linkHref = $link.attr( 'href' ), + linkTarget = $link.attr( 'target' ), + confirmText = $link.attr( 'confirm' ); + + option.func = function(){ + // if there's a "confirm" attribute, throw up a confirmation dialog, and + // if the user cancels - do nothing + if( ( confirmText ) && ( !confirm( confirmText ) ) ){ return; } + + // if there's no confirm attribute, or the user accepted the confirm dialog: + switch( linkTarget ){ + // relocate the center panel + case '_parent': + window.parent.location = linkHref; + break; + + // relocate the entire window + case '_top': + window.top.location = linkHref; + break; + + // relocate this panel + default: + window.location = linkHref; + } + }; + } + options.push( option ); + }); + return options; +}; + +/** Create a single popupmenu from existing DOM button and anchor elements + * @param {jQuery} $buttonElement the element that when clicked will open the menu + * @param {jQuery} $menuElement the element that contains the anchors to convert into a menu + * @param {String} menuElementLinkSelector jq selector string used to find anchors to be made into menu options + * @returns {PopupMenu} the PopupMenu (Backbone View) that can render, control the menu + */ +PopupMenu.fromExistingDom = function( $buttonElement, $menuElement, menuElementLinkSelector ){ + $buttonElement = $( $buttonElement ); + $menuElement = $( $menuElement ); + var options = PopupMenu.convertLinksToOptions( $menuElement, menuElementLinkSelector ); + // we're done with the menu (having converted it to an options map) + $menuElement.remove(); + return new PopupMenu( $buttonElement, options ); +}; + +/** Create all popupmenus within a document or a more specific element + * @param {DOMElement} parent the DOM element in which to search for popupmenus to build (defaults to document) + * @param {String} menuSelector jq selector string to find popupmenu menu elements (defaults to "div[popupmenu]") + * @param {Function} buttonSelectorBuildFn the function to build the jq button selector. + * Will be passed $menuElement, parent. + * (Defaults to return '#' + $menuElement.attr( 'popupmenu' ); ) + * @returns {PopupMenu[]} array of popupmenus created + */ +PopupMenu.make_popup_menus = function( parent, menuSelector, buttonSelectorBuildFn ){ + parent = parent || document; + // orig. Glx popupmenu menus have a (non-std) attribute 'popupmenu' + // which contains the id of the button that activates the menu + menuSelector = menuSelector || 'div[popupmenu]'; + // default to (orig. Glx) matching button to menu by using the popupmenu attr of the menu as the id of the button + buttonSelectorBuildFn = buttonSelectorBuildFn || function( $menuElement, parent ){ + return '#' + $menuElement.attr( 'popupmenu' ); + }; + + // aggregate and return all PopupMenus + var popupMenusCreated = []; + $( parent ).find( menuSelector ).each( function(){ + var $menuElement = $( this ), + $buttonElement = $( parent ).find( buttonSelectorBuildFn( $menuElement, parent ) ); + popupMenusCreated.push( PopupMenu.fromDom( $buttonElement, $menuElement ) ); + $buttonElement.addClass( 'popup' ); + }); + return popupMenusCreated; +}; + + +// ============================================================================= + return PopupMenu; +}); + diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/packed/mvc/grid/grid-view.js --- a/static/scripts/packed/mvc/grid/grid-view.js +++ b/static/scripts/packed/mvc/grid/grid-view.js @@ -1,1 +1,1 @@ -jQuery.ajaxSettings.traditional=true;define(["mvc/grid/grid-model","mvc/grid/grid-template","mvc/ui"],function(b,a){return Backbone.View.extend({grid:null,initialize:function(c){this.setElement("#grid-container");if(c.use_panels){$("#center").css({padding:"10px",overflow:"auto"})}this.init_grid(c)},handle_refresh:function(c){if(c){if($.inArray("history",c)>-1){if(top.Galaxy&&top.Galaxy.currHistoryPanel){top.Galaxy.currHistoryPanel.loadCurrentHistory()}}}},init_grid:function(f){this.grid=new b(f);var e=this.grid.attributes;this.handle_refresh(e.refresh_frames);var d=this.grid.get("url_base");d=d.replace(/^.*\/\/[^\/]+/,"");this.grid.set("url_base",d);this.$el.html(a.grid(e));this.$el.find("#grid-table-header").html(a.header(e));this.$el.find("#grid-table-body").html(a.body(e));this.$el.find("#grid-table-footer").html(a.footer(e));if(e.message){this.$el.find("#grid-message").html(a.message(e));var c=this;if(e.use_hide_message){setTimeout(function(){c.$el.find("#grid-message").html("")},5000)}}this.init_grid_elements();this.init_grid_controls();init_refresh_on_change()},init_grid_controls:function(){var c=this;this.$el.find(".operation-button").each(function(){$(this).off();$(this).click(function(){c.submit_operation(this,operation.confirm);return false})});this.$el.find("input[type=text]").each(function(){$(this).off();$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})});this.$el.find(".sort-link").each(function(){$(this).off();$(this).click(function(){c.set_sort_condition($(this).attr("sort_key"));return false})});this.$el.find(".text-filter-form").each(function(){$(this).off();$(this).submit(function(){var g=$(this).attr("column_key");var f=$("#input-"+g+"-filter");var h=f.val();f.val("");c.add_filter_condition(g,h);return false})});this.$el.find(".text-filter-val > a").each(function(){$(this).off();$(this).click(function(){$(this).parent().remove();c.remove_filter_condition($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});this.$el.find(".categorical-filter > a").each(function(){$(this).off();$(this).click(function(){c.set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});var e=this.$el.find("#input-tags-filter");if(e.length){e.autocomplete(this.grid.history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var d=this.$el.find("#input-name-filter");if(d.length){d.autocomplete(this.grid.history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}this.$el.find(".advanced-search-toggle").each(function(){$(this).off();$(this).click(function(){c.$el.find("#standard-search").slideToggle("fast");c.$el.find("#advanced-search").slideToggle("fast");return false})});this.$el.find("#check_all").off();this.$el.find("#check_all").on("click",function(){c.check_all_items()})},init_grid_elements:function(){this.$el.find(".grid").each(function(){var j=$(this).find("input.grid-row-select-checkbox");var i=$(this).find("span.grid-selected-count");var r=function(){i.text($(j).filter(":checked").length)};$(j).each(function(){$(this).change(r)});r()});if(this.$el.find(".community_rating_star").length!==0){this.$el.find(".community_rating_star").rating({})}var q=this.grid.attributes;var p=this;this.$el.find(".page-link > a").each(function(){$(this).click(function(){p.set_page($(this).attr("page_num"));return false})});this.$el.find(".use-inbound").each(function(){$(this).click(function(i){p.execute({href:$(this).attr("href"),inbound:true});return false})});this.$el.find(".use-outbound").each(function(){$(this).click(function(i){p.execute({href:$(this).attr("href")});return false})});var f=q.items.length;if(f==0){return}for(var k in q.items){var o=q.items[k];var l=this.$el.find("#grid-"+k+"-popup");l.off();var d=new PopupMenu(l);for(var h in q.operations){var e=q.operations[h];var m=e.label;var c=o.operation_config[m];var g=o.encode_id;if(c.allowed&&e.allow_popup){var n={html:e.label,href:c.url_args,target:c.target,confirmation_text:e.confirm,inbound:e.inbound};n.func=function(r){r.preventDefault();var j=$(r.target).html();var i=this.findItemByHtml(j);p.execute(i)};d.addItem(n)}}}},add_filter_condition:function(e,g){if(g===""){return false}this.grid.add_filter(e,g,true);var f=$(a.filter_element(e,g));var d=this;f.click(function(){$(this).remove();d.remove_filter_condition(e,g)});var c=this.$el.find("#"+e+"-filtering-criteria");c.append(f);this.go_page_one();this.execute()},remove_filter_condition:function(c,d){this.grid.remove_filter(c,d);this.go_page_one();this.execute()},set_sort_condition:function(g){var f=this.grid.get("sort_key");var e=g;if(f.indexOf(g)!==-1){if(f.substring(0,1)!=="-"){e="-"+g}}this.$el.find(".sort-arrow").remove();var d=(e.substring(0,1)=="-")?"↑":"↓";var c=$("<span>"+d+"</span>").addClass("sort-arrow");this.$el.find("#"+g+"-header").append(c);this.grid.set("sort_key",e);this.go_page_one();this.execute()},set_categorical_filter:function(e,g){var d=this.grid.get("categorical_filters")[e],f=this.grid.get("filters")[e];var c=this;this.$el.find("."+e+"-filter").each(function(){var k=$.trim($(this).text());var i=d[k];var j=i[e];if(j==g){$(this).empty();$(this).addClass("current-filter");$(this).append(k)}else{if(j==f){$(this).empty();var h=$('<a href="#">'+k+"</a>");h.click(function(){c.set_categorical_filter(e,j)});$(this).removeClass("current-filter");$(this).append(h)}}});this.grid.add_filter(e,g);this.go_page_one();this.execute()},set_page:function(c){var d=this;this.$el.find(".page-link").each(function(){var i=$(this).attr("id"),g=parseInt(i.split("-")[2],10),e=d.grid.get("cur_page"),h;if(g===c){h=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(h)}else{if(g===e){h=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var f=$('<a href="#">'+h+"</a>");f.click(function(){d.set_page(g)});$(this).append(f)}}});if(c==="all"){this.grid.set("cur_page",c)}else{this.grid.set("cur_page",parseInt(c,10))}this.execute()},submit_operation:function(d,g){var e=$(d).val();var f=this.$el.find('input[name="id"]:checked').length;if(!f>0){return false}var c=[];this.$el.find("input[name=id]:checked").each(function(){c.push($(this).val())});this.execute({operation:e,id:c,confirmation_text:g});return true},check_all_items:function(){var c=document.getElementById("check_all"),d=document.getElementsByTagName("input"),f=0,e;if(c.checked===true){for(e=0;e<d.length;e++){if(d[e].name.indexOf("id")!==-1){d[e].checked=true;f++}}}else{for(e=0;e<d.length;e++){if(d[e].name.indexOf("id")!==-1){d[e].checked=false}}}this.init_grid_elements()},go_page_one:function(){var c=this.grid.get("cur_page");if(c!==null&&c!==undefined&&c!=="all"){this.grid.set("cur_page",1)}},execute:function(l){var f=null;var e=null;var g=null;var c=null;var k=null;if(l){e=l.href;g=l.operation;f=l.id;c=l.confirmation_text;k=l.inbound;if(e!==undefined&&e.indexOf("operation=")!=-1){var j=e.split("?");if(j.length>1){var i=j[1];var d=i.split("&");for(var h=0;h<d.length;h++){if(d[h].indexOf("operation")!=-1){g=d[h].split("=")[1];g=g.replace(/\+/g," ")}else{if(d[h].indexOf("id")!=-1){f=d[h].split("=")[1]}}}}}}if(g&&f){if(c&&c!=""&&c!="None"&&c!="null"){if(!confirm(c)){return false}}g=g.toLowerCase();this.grid.set({operation:g,item_ids:f});if(this.grid.can_async_op(g)){this.update_grid()}else{this.go_to(k,e)}return false}if(e){this.go_to(k,e);return false}if(this.grid.get("async")){this.update_grid()}else{this.go_to(k,e)}return false},go_to:function(f,d){var e=this.grid.get("async");this.grid.set("async",false);advanced_search=this.$el.find("#advanced-search").is(":visible");this.grid.set("advanced_search",advanced_search);if(!d){d=this.grid.get("url_base")+"?"+$.param(this.grid.get_url_data())}this.grid.set({operation:undefined,item_ids:undefined,async:e});if(f){var c=$(".grid-header").closest(".inbound");if(c.length!==0){c.load(d);return}}window.location=d},update_grid:function(){var d=(this.grid.get("operation")?"POST":"GET");this.$el.find(".loading-elt-overlay").show();var c=this;$.ajax({type:d,url:c.grid.get("url_base"),data:c.grid.get_url_data(),error:function(e){alert("Grid refresh failed")},success:function(e){var g=c.grid.get("embedded");var h=c.grid.get("insert");var f=$.parseJSON(e);f.embedded=g;f.insert=h;c.init_grid(f);c.$el.find(".loading-elt-overlay").hide()},complete:function(){c.grid.set({operation:undefined,item_ids:undefined})}})}})}); \ No newline at end of file +jQuery.ajaxSettings.traditional=true;define(["mvc/grid/grid-model","mvc/grid/grid-template","mvc/ui/popup-menu"],function(c,b,a){return Backbone.View.extend({grid:null,initialize:function(d){this.setElement("#grid-container");if(d.use_panels){$("#center").css({padding:"10px",overflow:"auto"})}this.init_grid(d)},handle_refresh:function(d){if(d){if($.inArray("history",d)>-1){if(top.Galaxy&&top.Galaxy.currHistoryPanel){top.Galaxy.currHistoryPanel.loadCurrentHistory()}}}},init_grid:function(g){this.grid=new c(g);var f=this.grid.attributes;this.handle_refresh(f.refresh_frames);var e=this.grid.get("url_base");e=e.replace(/^.*\/\/[^\/]+/,"");this.grid.set("url_base",e);this.$el.html(b.grid(f));this.$el.find("#grid-table-header").html(b.header(f));this.$el.find("#grid-table-body").html(b.body(f));this.$el.find("#grid-table-footer").html(b.footer(f));if(f.message){this.$el.find("#grid-message").html(b.message(f));var d=this;if(f.use_hide_message){setTimeout(function(){d.$el.find("#grid-message").html("")},5000)}}this.init_grid_elements();this.init_grid_controls();init_refresh_on_change()},init_grid_controls:function(){var d=this;this.$el.find(".operation-button").each(function(){$(this).off();$(this).click(function(){d.submit_operation(this,operation.confirm);return false})});this.$el.find("input[type=text]").each(function(){$(this).off();$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})});this.$el.find(".sort-link").each(function(){$(this).off();$(this).click(function(){d.set_sort_condition($(this).attr("sort_key"));return false})});this.$el.find(".text-filter-form").each(function(){$(this).off();$(this).submit(function(){var h=$(this).attr("column_key");var g=$("#input-"+h+"-filter");var i=g.val();g.val("");d.add_filter_condition(h,i);return false})});this.$el.find(".text-filter-val > a").each(function(){$(this).off();$(this).click(function(){$(this).parent().remove();d.remove_filter_condition($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});this.$el.find(".categorical-filter > a").each(function(){$(this).off();$(this).click(function(){d.set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});var f=this.$el.find("#input-tags-filter");if(f.length){f.autocomplete(this.grid.history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var e=this.$el.find("#input-name-filter");if(e.length){e.autocomplete(this.grid.history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}this.$el.find(".advanced-search-toggle").each(function(){$(this).off();$(this).click(function(){d.$el.find("#standard-search").slideToggle("fast");d.$el.find("#advanced-search").slideToggle("fast");return false})});this.$el.find("#check_all").off();this.$el.find("#check_all").on("click",function(){d.check_all_items()})},init_grid_elements:function(){this.$el.find(".grid").each(function(){var j=$(this).find("input.grid-row-select-checkbox");var i=$(this).find("span.grid-selected-count");var s=function(){i.text($(j).filter(":checked").length)};$(j).each(function(){$(this).change(s)});s()});if(this.$el.find(".community_rating_star").length!==0){this.$el.find(".community_rating_star").rating({})}var r=this.grid.attributes;var q=this;this.$el.find(".page-link > a").each(function(){$(this).click(function(){q.set_page($(this).attr("page_num"));return false})});this.$el.find(".use-inbound").each(function(){$(this).click(function(i){q.execute({href:$(this).attr("href"),inbound:true});return false})});this.$el.find(".use-outbound").each(function(){$(this).click(function(i){q.execute({href:$(this).attr("href")});return false})});var g=r.items.length;if(g==0){return}for(var l in r.items){var p=r.items[l];var m=this.$el.find("#grid-"+l+"-popup");m.off();var e=new a(m);for(var k in r.operations){var f=r.operations[k];var n=f.label;var d=p.operation_config[n];var h=p.encode_id;if(d.allowed&&f.allow_popup){var o={html:f.label,href:d.url_args,target:d.target,confirmation_text:f.confirm,inbound:f.inbound};o.func=function(s){s.preventDefault();var j=$(s.target).html();var i=this.findItemByHtml(j);q.execute(i)};e.addItem(o)}}}},add_filter_condition:function(f,h){if(h===""){return false}this.grid.add_filter(f,h,true);var g=$(b.filter_element(f,h));var e=this;g.click(function(){$(this).remove();e.remove_filter_condition(f,h)});var d=this.$el.find("#"+f+"-filtering-criteria");d.append(g);this.go_page_one();this.execute()},remove_filter_condition:function(d,e){this.grid.remove_filter(d,e);this.go_page_one();this.execute()},set_sort_condition:function(h){var g=this.grid.get("sort_key");var f=h;if(g.indexOf(h)!==-1){if(g.substring(0,1)!=="-"){f="-"+h}}this.$el.find(".sort-arrow").remove();var e=(f.substring(0,1)=="-")?"↑":"↓";var d=$("<span>"+e+"</span>").addClass("sort-arrow");this.$el.find("#"+h+"-header").append(d);this.grid.set("sort_key",f);this.go_page_one();this.execute()},set_categorical_filter:function(f,h){var e=this.grid.get("categorical_filters")[f],g=this.grid.get("filters")[f];var d=this;this.$el.find("."+f+"-filter").each(function(){var l=$.trim($(this).text());var j=e[l];var k=j[f];if(k==h){$(this).empty();$(this).addClass("current-filter");$(this).append(l)}else{if(k==g){$(this).empty();var i=$('<a href="#">'+l+"</a>");i.click(function(){d.set_categorical_filter(f,k)});$(this).removeClass("current-filter");$(this).append(i)}}});this.grid.add_filter(f,h);this.go_page_one();this.execute()},set_page:function(d){var e=this;this.$el.find(".page-link").each(function(){var j=$(this).attr("id"),h=parseInt(j.split("-")[2],10),f=e.grid.get("cur_page"),i;if(h===d){i=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(i)}else{if(h===f){i=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var g=$('<a href="#">'+i+"</a>");g.click(function(){e.set_page(h)});$(this).append(g)}}});if(d==="all"){this.grid.set("cur_page",d)}else{this.grid.set("cur_page",parseInt(d,10))}this.execute()},submit_operation:function(e,h){var f=$(e).val();var g=this.$el.find('input[name="id"]:checked').length;if(!g>0){return false}var d=[];this.$el.find("input[name=id]:checked").each(function(){d.push($(this).val())});this.execute({operation:f,id:d,confirmation_text:h});return true},check_all_items:function(){var d=document.getElementById("check_all"),e=document.getElementsByTagName("input"),g=0,f;if(d.checked===true){for(f=0;f<e.length;f++){if(e[f].name.indexOf("id")!==-1){e[f].checked=true;g++}}}else{for(f=0;f<e.length;f++){if(e[f].name.indexOf("id")!==-1){e[f].checked=false}}}this.init_grid_elements()},go_page_one:function(){var d=this.grid.get("cur_page");if(d!==null&&d!==undefined&&d!=="all"){this.grid.set("cur_page",1)}},execute:function(m){var g=null;var f=null;var h=null;var d=null;var l=null;if(m){f=m.href;h=m.operation;g=m.id;d=m.confirmation_text;l=m.inbound;if(f!==undefined&&f.indexOf("operation=")!=-1){var k=f.split("?");if(k.length>1){var j=k[1];var e=j.split("&");for(var i=0;i<e.length;i++){if(e[i].indexOf("operation")!=-1){h=e[i].split("=")[1];h=h.replace(/\+/g," ")}else{if(e[i].indexOf("id")!=-1){g=e[i].split("=")[1]}}}}}}if(h&&g){if(d&&d!=""&&d!="None"&&d!="null"){if(!confirm(d)){return false}}h=h.toLowerCase();this.grid.set({operation:h,item_ids:g});if(this.grid.can_async_op(h)){this.update_grid()}else{this.go_to(l,f)}return false}if(f){this.go_to(l,f);return false}if(this.grid.get("async")){this.update_grid()}else{this.go_to(l,f)}return false},go_to:function(g,e){var f=this.grid.get("async");this.grid.set("async",false);advanced_search=this.$el.find("#advanced-search").is(":visible");this.grid.set("advanced_search",advanced_search);if(!e){e=this.grid.get("url_base")+"?"+$.param(this.grid.get_url_data())}this.grid.set({operation:undefined,item_ids:undefined,async:f});if(g){var d=$(".grid-header").closest(".inbound");if(d.length!==0){d.load(e);return}}window.location=e},update_grid:function(){var e=(this.grid.get("operation")?"POST":"GET");this.$el.find(".loading-elt-overlay").show();var d=this;$.ajax({type:e,url:d.grid.get("url_base"),data:d.grid.get_url_data(),error:function(f){alert("Grid refresh failed")},success:function(f){var h=d.grid.get("embedded");var i=d.grid.get("insert");var g=$.parseJSON(f);g.embedded=h;g.insert=i;d.init_grid(g);d.$el.find(".loading-elt-overlay").hide()},complete:function(){d.grid.set({operation:undefined,item_ids:undefined})}})}})}); \ No newline at end of file diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/packed/mvc/history/history-panel-edit.js --- a/static/scripts/packed/mvc/history/history-panel-edit.js +++ b/static/scripts/packed/mvc/history/history-panel-edit.js @@ -1,1 +1,1 @@ -define(["mvc/history/history-panel","mvc/history/history-contents","mvc/dataset/states","mvc/history/hda-model","mvc/history/hda-li-edit","mvc/history/hdca-li-edit","mvc/tags","mvc/annotations","jq-plugins/ui/fa-icon-button","utils/localization"],function(g,i,l,e,d,h,k,b,a,c){var j=g.HistoryPanel;var f=j.extend({HDAViewClass:d.HDAListItemEdit,HDCAViewClass:h.HDCAListItemEdit,initialize:function(m){m=m||{};j.prototype.initialize.call(this,m);this.tagsEditor=null;this.annotationEditor=null;this.purgeAllowed=m.purgeAllowed||false;this.annotationEditorShown=m.annotationEditorShown||false;this.tagsEditorShown=m.tagsEditorShown||false;this.multiselectActions=m.multiselectActions||this._getActions()},_setUpListeners:function(){j.prototype._setUpListeners.call(this);this.on("drop",function(m,n){this.dataDropped(n);this.dropTargetOff()})},_setUpCollectionListeners:function(){j.prototype._setUpCollectionListeners.call(this);this.collection.on("change:deleted",this._handleHdaDeletionChange,this);this.collection.on("change:visible",this._handleHdaVisibleChange,this);this.collection.on("change:purged",function(m){this.model.fetch()},this);return this},_setUpModelListeners:function(){j.prototype._setUpModelListeners.call(this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);return this},_buildNewRender:function(){var m=j.prototype._buildNewRender.call(this);if(!this.model){return m}if(Galaxy&&Galaxy.currUser&&Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(m);this._renderAnnotation(m)}return m},renderItems:function(n){var m=j.prototype.renderItems.call(this,n);this._renderCounts(n);return m},_renderCounts:function(o){function n(r,s){return['<a class="',r,'" href="javascript:void(0);">',s,"</a>"].join("")}o=o||this.$el;var m=this.collection.where({deleted:true}),q=this.collection.where({visible:false}),p=[];if(this.views.length){p.push([this.views.length,c("shown")].join(" "))}if(m.length){p.push((!this.showDeleted)?([m.length,n("toggle-deleted-link",c("deleted"))].join(" ")):(n("toggle-deleted-link",c("hide deleted"))))}if(q.length){p.push((!this.showHidden)?([q.length,n("toggle-hidden-link",c("hidden"))].join(" ")):(n("toggle-hidden-link",c("hide hidden"))))}return o.find("> .controls .subtitle").html(p.join(", "))},_renderTags:function(m){var n=this;this.tagsEditor=new k.TagsEditor({model:this.model,el:m.find(".controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){n.toggleHDATagEditors(true,n.fxSpeed)},onhide:function(){n.toggleHDATagEditors(false,n.fxSpeed)},$activator:a({title:c("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(m.find(".controls .actions"))})},_renderAnnotation:function(m){var n=this;this.annotationEditor=new b.AnnotationEditor({model:this.model,el:m.find(".controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){n.toggleHDAAnnotationEditors(true,n.fxSpeed)},onhide:function(){n.toggleHDAAnnotationEditors(false,n.fxSpeed)},$activator:a({title:c("Edit history annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(m.find(".controls .actions"))})},_setUpBehaviors:function(m){m=m||this.$el;j.prototype._setUpBehaviors.call(this,m);if(!this.model){return}if(this.multiselectActions.length){this.actionsPopup=new PopupMenu(m.find(".list-action-popup-btn"),this.multiselectActions)}if((!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var n=this,o=".controls .name";m.find(o).attr("title",c("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(p){var q=n.model.get("name");if(p&&p!==q){n.$el.find(o).text(p);n.model.save({name:p}).fail(function(){n.$el.find(o).text(n.model.previous("name"))})}else{n.$el.find(o).text(q)}}})},_getActions:function(){var m=this,n=[{html:c("Hide datasets"),func:function(){var o=e.HistoryDatasetAssociation.prototype.hide;m.getSelectedModels().ajaxQueue(o)}},{html:c("Unhide datasets"),func:function(){var o=e.HistoryDatasetAssociation.prototype.unhide;m.getSelectedModels().ajaxQueue(o)}},{html:c("Delete datasets"),func:function(){var o=e.HistoryDatasetAssociation.prototype["delete"];m.getSelectedModels().ajaxQueue(o)}},{html:c("Undelete datasets"),func:function(){var o=e.HistoryDatasetAssociation.prototype.undelete;m.getSelectedModels().ajaxQueue(o)}}];if(m.purgeAllowed){n.push({html:c("Permanently delete datasets"),func:function(){if(confirm(c("This will permanently remove the data in your datasets. Are you sure?"))){var o=e.HistoryDatasetAssociation.prototype.purge;m.getSelectedModels().ajaxQueue(o)}}})}n.push({html:c("Build Dataset List"),func:function(){m.getSelectedModels().promoteToHistoryDatasetCollection(m.model,"list")}});n.push({html:c("Build Dataset Pair"),func:function(){m.getSelectedModels().promoteToHistoryDatasetCollection(m.model,"paired")}});n.push({html:c("Build List of Dataset Pairs"),func:_.bind(m._showPairedCollectionModal,m)});return n},_showPairedCollectionModal:function(){var m=this,n=m.getSelectedModels().toJSON().filter(function(o){return o.history_content_type==="dataset"&&o.state===l.OK});if(n.length){require(["mvc/collection/paired-collection-creator"],function(o){window.creator=o.pairedCollectionCreatorModal(n,{historyId:m.model.id})})}else{}},_attachItems:function(m){this.$list(m).append(this.views.reverse().map(function(n){return n.$el}));return this},_attachView:function(n){var m=this;m.views.unshift(n);m.$list().prepend(n.render(0).$el.hide());n.$el.slideDown(m.fxSpeed)},_getItemViewOptions:function(n){var m=j.prototype._getItemViewOptions.call(this,n);_.extend(m,{purgeAllowed:this.purgeAllowed,tagsEditorShown:(this.tagsEditor&&!this.tagsEditor.hidden),annotationEditorShown:(this.annotationEditor&&!this.annotationEditor.hidden)});return m},_handleHdaDeletionChange:function(m){if(m.get("deleted")&&!this.showDeleted){this.removeItemView(m)}this._renderCounts()},_handleHdaVisibleChange:function(m){if(m.hidden()&&!this.storage.showHidden){this.removeItemView(m)}this._renderCounts()},toggleHDATagEditors:function(m){var n=Array.prototype.slice.call(arguments,1);_.each(this.views,function(o){if(o.tagsEditor){o.tagsEditor.toggle.apply(o.tagsEditor,n)}})},toggleHDAAnnotationEditors:function(m){var n=Array.prototype.slice.call(arguments,1);_.each(this.views,function(o){if(o.annotationEditor){o.annotationEditor.toggle.apply(o.annotationEditor,n)}})},events:_.extend(_.clone(j.prototype.events),{"click .show-selectors-btn":"toggleSelectors","click .toggle-deleted-link":function(m){this.toggleShowDeleted()},"click .toggle-hidden-link":function(m){this.toggleShowHidden()}}),updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},dropTargetOn:function(){if(this.dropTarget){return this}this.dropTarget=true;var n={dragenter:_.bind(this.dragenter,this),dragover:_.bind(this.dragover,this),dragleave:_.bind(this.dragleave,this),drop:_.bind(this.drop,this)};var o=this._renderDropTarget();this.$list().before([this._renderDropTargetHelp(),o]);for(var m in n){if(n.hasOwnProperty(m)){o.on(m,n[m])}}return this},_renderDropTarget:function(){return $("<div/>").addClass("history-drop-target").css({height:"64px",margin:"0px 10px 10px 10px",border:"1px dashed black","border-radius":"3px"})},_renderDropTargetHelp:function(){return $("<div/>").addClass("history-drop-target-help").css({margin:"10px 10px 4px 10px",color:"grey","font-size":"80%","font-style":"italic"}).text(c("Drag datasets here to copy them to the current history"))},dropTargetOff:function(){if(!this.dropTarget){return this}this.dropTarget=false;this.$(".history-drop-target").remove();this.$(".history-drop-target-help").remove();return this},dropTargetToggle:function(){if(this.dropTarget){this.dropTargetOff()}else{this.dropTargetOn()}return this},dragenter:function(m){m.preventDefault();m.stopPropagation();this.$(".history-drop-target").css("border","2px solid black")},dragover:function(m){m.preventDefault();m.stopPropagation()},dragleave:function(m){m.preventDefault();m.stopPropagation();this.$(".history-drop-target").css("border","1px dashed black")},drop:function(o){o.preventDefault();o.dataTransfer.dropEffect="move";var m=this,p=o.dataTransfer.getData("text");try{p=JSON.parse(p)}catch(n){this.warn("error parsing JSON from drop:",p)}this.trigger("droptarget:drop",o,p,m);return false},dataDropped:function(n){var m=this;if(_.isObject(n)&&n.model_class==="HistoryDatasetAssociation"&&n.id){return m.model.contents.copy(n.id)}return jQuery.when()},toString:function(){return"HistoryPanelEdit("+((this.model)?(this.model.get("name")):(""))+")"}});return{HistoryPanelEdit:f}}); \ No newline at end of file +define(["mvc/history/history-panel","mvc/history/history-contents","mvc/dataset/states","mvc/history/hda-model","mvc/history/hda-li-edit","mvc/history/hdca-li-edit","mvc/tags","mvc/annotations","jq-plugins/ui/fa-icon-button","mvc/ui/popup-menu","utils/localization"],function(h,j,m,f,e,i,l,c,b,a,d){var k=h.HistoryPanel;var g=k.extend({HDAViewClass:e.HDAListItemEdit,HDCAViewClass:i.HDCAListItemEdit,initialize:function(n){n=n||{};k.prototype.initialize.call(this,n);this.tagsEditor=null;this.annotationEditor=null;this.purgeAllowed=n.purgeAllowed||false;this.annotationEditorShown=n.annotationEditorShown||false;this.tagsEditorShown=n.tagsEditorShown||false;this.multiselectActions=n.multiselectActions||this._getActions()},_setUpListeners:function(){k.prototype._setUpListeners.call(this);this.on("drop",function(n,o){this.dataDropped(o);this.dropTargetOff()})},_setUpCollectionListeners:function(){k.prototype._setUpCollectionListeners.call(this);this.collection.on("change:deleted",this._handleHdaDeletionChange,this);this.collection.on("change:visible",this._handleHdaVisibleChange,this);this.collection.on("change:purged",function(n){this.model.fetch()},this);return this},_setUpModelListeners:function(){k.prototype._setUpModelListeners.call(this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);return this},_buildNewRender:function(){var n=k.prototype._buildNewRender.call(this);if(!this.model){return n}if(Galaxy&&Galaxy.currUser&&Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(n);this._renderAnnotation(n)}return n},renderItems:function(o){var n=k.prototype.renderItems.call(this,o);this._renderCounts(o);return n},_renderCounts:function(p){function o(s,t){return['<a class="',s,'" href="javascript:void(0);">',t,"</a>"].join("")}p=p||this.$el;var n=this.collection.where({deleted:true}),r=this.collection.where({visible:false}),q=[];if(this.views.length){q.push([this.views.length,d("shown")].join(" "))}if(n.length){q.push((!this.showDeleted)?([n.length,o("toggle-deleted-link",d("deleted"))].join(" ")):(o("toggle-deleted-link",d("hide deleted"))))}if(r.length){q.push((!this.showHidden)?([r.length,o("toggle-hidden-link",d("hidden"))].join(" ")):(o("toggle-hidden-link",d("hide hidden"))))}return p.find("> .controls .subtitle").html(q.join(", "))},_renderTags:function(n){var o=this;this.tagsEditor=new l.TagsEditor({model:this.model,el:n.find(".controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){o.toggleHDATagEditors(true,o.fxSpeed)},onhide:function(){o.toggleHDATagEditors(false,o.fxSpeed)},$activator:b({title:d("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(n.find(".controls .actions"))})},_renderAnnotation:function(n){var o=this;this.annotationEditor=new c.AnnotationEditor({model:this.model,el:n.find(".controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){o.toggleHDAAnnotationEditors(true,o.fxSpeed)},onhide:function(){o.toggleHDAAnnotationEditors(false,o.fxSpeed)},$activator:b({title:d("Edit history annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(n.find(".controls .actions"))})},_setUpBehaviors:function(n){n=n||this.$el;k.prototype._setUpBehaviors.call(this,n);if(!this.model){return}if(this.multiselectActions.length){this.actionsPopup=new a(n.find(".list-action-popup-btn"),this.multiselectActions)}if((!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var o=this,p=".controls .name";n.find(p).attr("title",d("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(q){var r=o.model.get("name");if(q&&q!==r){o.$el.find(p).text(q);o.model.save({name:q}).fail(function(){o.$el.find(p).text(o.model.previous("name"))})}else{o.$el.find(p).text(r)}}})},_getActions:function(){var n=this,o=[{html:d("Hide datasets"),func:function(){var p=f.HistoryDatasetAssociation.prototype.hide;n.getSelectedModels().ajaxQueue(p)}},{html:d("Unhide datasets"),func:function(){var p=f.HistoryDatasetAssociation.prototype.unhide;n.getSelectedModels().ajaxQueue(p)}},{html:d("Delete datasets"),func:function(){var p=f.HistoryDatasetAssociation.prototype["delete"];n.getSelectedModels().ajaxQueue(p)}},{html:d("Undelete datasets"),func:function(){var p=f.HistoryDatasetAssociation.prototype.undelete;n.getSelectedModels().ajaxQueue(p)}}];if(n.purgeAllowed){o.push({html:d("Permanently delete datasets"),func:function(){if(confirm(d("This will permanently remove the data in your datasets. Are you sure?"))){var p=f.HistoryDatasetAssociation.prototype.purge;n.getSelectedModels().ajaxQueue(p)}}})}o.push({html:d("Build Dataset List"),func:function(){n.getSelectedModels().promoteToHistoryDatasetCollection(n.model,"list")}});o.push({html:d("Build Dataset Pair"),func:function(){n.getSelectedModels().promoteToHistoryDatasetCollection(n.model,"paired")}});o.push({html:d("Build List of Dataset Pairs"),func:_.bind(n._showPairedCollectionModal,n)});return o},_showPairedCollectionModal:function(){var n=this,o=n.getSelectedModels().toJSON().filter(function(p){return p.history_content_type==="dataset"&&p.state===m.OK});if(o.length){require(["mvc/collection/paired-collection-creator"],function(p){window.creator=p.pairedCollectionCreatorModal(o,{historyId:n.model.id})})}else{}},_attachItems:function(n){this.$list(n).append(this.views.reverse().map(function(o){return o.$el}));return this},_attachView:function(o){var n=this;n.views.unshift(o);n.$list().prepend(o.render(0).$el.hide());o.$el.slideDown(n.fxSpeed)},_getItemViewOptions:function(o){var n=k.prototype._getItemViewOptions.call(this,o);_.extend(n,{purgeAllowed:this.purgeAllowed,tagsEditorShown:(this.tagsEditor&&!this.tagsEditor.hidden),annotationEditorShown:(this.annotationEditor&&!this.annotationEditor.hidden)});return n},_handleHdaDeletionChange:function(n){if(n.get("deleted")&&!this.showDeleted){this.removeItemView(n)}this._renderCounts()},_handleHdaVisibleChange:function(n){if(n.hidden()&&!this.storage.showHidden){this.removeItemView(n)}this._renderCounts()},toggleHDATagEditors:function(n){var o=Array.prototype.slice.call(arguments,1);_.each(this.views,function(p){if(p.tagsEditor){p.tagsEditor.toggle.apply(p.tagsEditor,o)}})},toggleHDAAnnotationEditors:function(n){var o=Array.prototype.slice.call(arguments,1);_.each(this.views,function(p){if(p.annotationEditor){p.annotationEditor.toggle.apply(p.annotationEditor,o)}})},events:_.extend(_.clone(k.prototype.events),{"click .show-selectors-btn":"toggleSelectors","click .toggle-deleted-link":function(n){this.toggleShowDeleted()},"click .toggle-hidden-link":function(n){this.toggleShowHidden()}}),updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},dropTargetOn:function(){if(this.dropTarget){return this}this.dropTarget=true;var o={dragenter:_.bind(this.dragenter,this),dragover:_.bind(this.dragover,this),dragleave:_.bind(this.dragleave,this),drop:_.bind(this.drop,this)};var p=this._renderDropTarget();this.$list().before([this._renderDropTargetHelp(),p]);for(var n in o){if(o.hasOwnProperty(n)){p.on(n,o[n])}}return this},_renderDropTarget:function(){return $("<div/>").addClass("history-drop-target").css({height:"64px",margin:"0px 10px 10px 10px",border:"1px dashed black","border-radius":"3px"})},_renderDropTargetHelp:function(){return $("<div/>").addClass("history-drop-target-help").css({margin:"10px 10px 4px 10px",color:"grey","font-size":"80%","font-style":"italic"}).text(d("Drag datasets here to copy them to the current history"))},dropTargetOff:function(){if(!this.dropTarget){return this}this.dropTarget=false;this.$(".history-drop-target").remove();this.$(".history-drop-target-help").remove();return this},dropTargetToggle:function(){if(this.dropTarget){this.dropTargetOff()}else{this.dropTargetOn()}return this},dragenter:function(n){n.preventDefault();n.stopPropagation();this.$(".history-drop-target").css("border","2px solid black")},dragover:function(n){n.preventDefault();n.stopPropagation()},dragleave:function(n){n.preventDefault();n.stopPropagation();this.$(".history-drop-target").css("border","1px dashed black")},drop:function(p){p.preventDefault();p.dataTransfer.dropEffect="move";var n=this,q=p.dataTransfer.getData("text");try{q=JSON.parse(q)}catch(o){this.warn("error parsing JSON from drop:",q)}this.trigger("droptarget:drop",p,q,n);return false},dataDropped:function(o){var n=this;if(_.isObject(o)&&o.model_class==="HistoryDatasetAssociation"&&o.id){return n.model.contents.copy(o.id)}return jQuery.when()},toString:function(){return"HistoryPanelEdit("+((this.model)?(this.model.get("name")):(""))+")"}});return{HistoryPanelEdit:g}}); \ No newline at end of file diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/packed/mvc/history/options-menu.js --- a/static/scripts/packed/mvc/history/options-menu.js +++ b/static/scripts/packed/mvc/history/options-menu.js @@ -1,1 +1,1 @@ -define(["mvc/base-mvc","utils/localization"],function(a,d){var e=[{html:d("History Lists"),header:true},{html:d("Saved Histories"),href:"history/list"},{html:d("Histories Shared with Me"),href:"history/list_shared"},{html:d("Current History"),header:true,anon:true},{html:d("Create New"),func:function(){if(Galaxy&&Galaxy.currHistoryPanel){Galaxy.currHistoryPanel.createNewHistory()}}},{html:d("Copy History"),href:"history/copy"},{html:d("Copy Datasets"),href:"dataset/copy_datasets"},{html:d("Share or Publish"),href:"history/sharing"},{html:d("Extract Workflow"),href:"workflow/build_from_current_history"},{html:d("Dataset Security"),href:"root/history_set_default_permissions"},{html:d("Resume Paused Jobs"),href:"history/resume_paused_jobs?current=True",anon:true},{html:d("Collapse Expanded Datasets"),func:function(){if(Galaxy&&Galaxy.currHistoryPanel){Galaxy.currHistoryPanel.collapseAll()}}},{html:d("Unhide Hidden Datasets"),confirm:d("Really unhide all hidden datasets?"),href:"history/unhide_datasets?current=True",anon:true},{html:d("Delete Hidden Datasets"),confirm:d("Really delete all hidden datasets?"),href:"history/delete_hidden_datasets",anon:true},{html:d("Purge Deleted Datasets"),confirm:d("Really delete all deleted datasets permanently? This cannot be undone."),href:"history/purge_deleted_datasets",purge:true,anon:true},{html:d("Show Structure"),href:"history/display_structured",anon:true},{html:d("Export Citations"),href:"history/citations",anon:true},{html:d("Export to File"),href:"history/export_archive?preview=True",anon:true},{html:d("Delete"),confirm:d("Really delete the current history?"),href:"history/delete_current"},{html:d("Delete Permanently"),confirm:d("Really delete the current history permanently? This cannot be undone."),href:"history/delete_current?purge=True",purge:true,anon:true},{html:d("Other Actions"),header:true},{html:d("Import from File"),href:"history/import_archive"}];function c(h,g,f){return _.clone(e).filter(function(i){if(h&&!i.anon){return false}if(!g&&i.purge){return false}if(i.href){i.href=f+i.href;i.target="galaxy_main"}if(i.confirm){i.func=function(){if(confirm(i.confirm)){galaxy_main.location=i.href}}}return true})}var b=function(i,g){g=g||{};var j=g.anonymous===undefined?true:g.anonymous,h=g.purgeAllowed||false,f=g.root||((Galaxy&&Galaxy.options)?Galaxy.options.root:"/"),k=c(j,h,f);return new PopupMenu(i,k)};return b}); \ No newline at end of file +define(["mvc/ui/popup-menu","mvc/base-mvc","utils/localization"],function(b,a,e){var f=[{html:e("History Lists"),header:true},{html:e("Saved Histories"),href:"history/list"},{html:e("Histories Shared with Me"),href:"history/list_shared"},{html:e("Current History"),header:true,anon:true},{html:e("Create New"),func:function(){if(Galaxy&&Galaxy.currHistoryPanel){Galaxy.currHistoryPanel.createNewHistory()}}},{html:e("Copy History"),href:"history/copy"},{html:e("Copy Datasets"),href:"dataset/copy_datasets"},{html:e("Share or Publish"),href:"history/sharing"},{html:e("Extract Workflow"),href:"workflow/build_from_current_history"},{html:e("Dataset Security"),href:"root/history_set_default_permissions"},{html:e("Resume Paused Jobs"),href:"history/resume_paused_jobs?current=True",anon:true},{html:e("Collapse Expanded Datasets"),func:function(){if(Galaxy&&Galaxy.currHistoryPanel){Galaxy.currHistoryPanel.collapseAll()}}},{html:e("Unhide Hidden Datasets"),confirm:e("Really unhide all hidden datasets?"),href:"history/unhide_datasets?current=True",anon:true},{html:e("Delete Hidden Datasets"),confirm:e("Really delete all hidden datasets?"),href:"history/delete_hidden_datasets",anon:true},{html:e("Purge Deleted Datasets"),confirm:e("Really delete all deleted datasets permanently? This cannot be undone."),href:"history/purge_deleted_datasets",purge:true,anon:true},{html:e("Show Structure"),href:"history/display_structured",anon:true},{html:e("Export Citations"),href:"history/citations",anon:true},{html:e("Export to File"),href:"history/export_archive?preview=True",anon:true},{html:e("Delete"),confirm:e("Really delete the current history?"),href:"history/delete_current"},{html:e("Delete Permanently"),confirm:e("Really delete the current history permanently? This cannot be undone."),href:"history/delete_current?purge=True",purge:true,anon:true},{html:e("Other Actions"),header:true},{html:e("Import from File"),href:"history/import_archive"}];function d(i,h,g){return _.clone(f).filter(function(j){if(i&&!j.anon){return false}if(!h&&j.purge){return false}if(j.href){j.href=g+j.href;j.target="galaxy_main"}if(j.confirm){j.func=function(){if(confirm(j.confirm)){galaxy_main.location=j.href}}}return true})}var c=function(j,h){h=h||{};var k=h.anonymous===undefined?true:h.anonymous,i=h.purgeAllowed||false,g=h.root||((Galaxy&&Galaxy.options)?Galaxy.options.root:"/"),l=d(k,i,g);return new b(j,l)};return c}); \ No newline at end of file diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/packed/mvc/ui.js --- a/static/scripts/packed/mvc/ui.js +++ b/static/scripts/packed/mvc/ui.js @@ -1,1 +1,1 @@ -var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a}; \ No newline at end of file +var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})}; \ No newline at end of file diff -r 6c9848ad6d02691c7c68cd8faada68753126b472 -r 5b5dde05d21f02afa23cfe1c98396002d907de21 static/scripts/packed/mvc/ui/popup-menu.js --- /dev/null +++ b/static/scripts/packed/mvc/ui/popup-menu.js @@ -0,0 +1,1 @@ +define([],function(){var a=Backbone.View.extend({initialize:function(d,c){this.$button=d;if(!this.$button.size()){this.$button=$("<div/>")}this.options=c||[];var e=this;this.$button.click(function(f){$(".popmenu-wrapper").remove();e._renderAndShow(f);return false})},_renderAndShow:function(c){this.render();this.$el.appendTo("body").css(this._getShownPosition(c)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var c=this;this.$el.find("li").each(function(e,d){var f=c.options[e];if(f.func){$(this).children("a.popupmenu-option").click(function(g){f.func.call(c,g,f)})}})}return this},template:function(d,c){return['<ul id="',d,'-menu" class="dropdown-menu">',this._templateOptions(c),"</ul>"].join("")},_templateOptions:function(c){if(!c.length){return"<li>(no options)</li>"}return _.map(c,function(f){if(f.divider){return'<li class="divider"></li>'}else{if(f.header){return['<li class="head"><a href="javascript:void(0);">',f.html,"</a></li>"].join("")}}var e=f.href||"javascript:void(0);",g=(f.target)?(' target="'+f.target+'"'):(""),d=(f.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',e,'"',g,">",d,f.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(d){var e=this.$el.width();var c=d.pageX-e/2;c=Math.min(c,$(document).scrollLeft()+$(window).width()-e-5);c=Math.max(c,$(document).scrollLeft()+5);return{top:d.pageY,left:c}},_setUpCloseBehavior:function(){var e=this;function c(g){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(f){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(f){}}e.remove()}$("html").one("click.close_popup",c);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",c)}catch(d){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",c)}catch(d){}}},addItem:function(d,c){c=(c>=0)?c:this.options.length;this.options.splice(c,0,d);return this},removeItem:function(c){if(c>=0){this.options.splice(c,1)}return this},findIndexByHtml:function(d){for(var c=0;c<this.options.length;c++){if(_.has(this.options[c],"html")&&(this.options[c].html===d)){return c}}return null},findItemByHtml:function(c){return this.options[(this.findIndexByHtml(c))]},toString:function(){return"PopupMenu"}});a.create=function b(d,c){return new a(d,c)};a.make_popupmenu=function(d,e){var c=[];_.each(e,function(h,f){var g={html:f};if(h===null){g.header=true}else{if(jQuery.type(h)==="function"){g.func=h}}c.push(g)});return new a($(d),c)};a.convertLinksToOptions=function(e,c){e=$(e);c=c||"a";var d=[];e.find(c).each(function(j,g){var h={},f=$(j);h.html=f.text();if(f.attr("href")){var l=f.attr("href"),m=f.attr("target"),k=f.attr("confirm");h.func=function(){if((k)&&(!confirm(k))){return}switch(m){case"_parent":window.parent.location=l;break;case"_top":window.top.location=l;break;default:window.location=l}}}d.push(h)});return d};a.fromExistingDom=function(f,e,c){f=$(f);e=$(e);var d=a.convertLinksToOptions(e,c);e.remove();return new a(f,d)};a.make_popup_menus=function(e,d,f){e=e||document;d=d||"div[popupmenu]";f=f||function(g,h){return"#"+g.attr("popupmenu")};var c=[];$(e).find(d).each(function(){var g=$(this),h=$(e).find(f(g,e));c.push(a.fromDom(h,g));h.addClass("popup")});return c};return a}); \ No newline at end of file Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.