From 0ad2148c7fa4f3c69a9eafa181cb19738cdbdd1d Mon Sep 17 00:00:00 2001 From: will Date: Fri, 17 May 2019 15:37:28 -0400 Subject: [PATCH] Don't close popup menu if header item is clicked, upgrade to es6 features, and removed unused functions. --- client/galaxy/scripts/mvc/ui/popup-menu.js | 172 +++------------------ 1 file changed, 22 insertions(+), 150 deletions(-) diff --git a/client/galaxy/scripts/mvc/ui/popup-menu.js b/client/galaxy/scripts/mvc/ui/popup-menu.js index 410166d607c..6166a6e078e 100644 --- a/client/galaxy/scripts/mvc/ui/popup-menu.js +++ b/client/galaxy/scripts/mvc/ui/popup-menu.js @@ -5,7 +5,7 @@ import $ from "jquery"; import _ from "underscore"; import Backbone from "backbone"; -var PopupMenu = Backbone.View.extend({ +const 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. @@ -20,11 +20,10 @@ var PopupMenu = Backbone.View.extend({ this.$button.data("popupmenu", this); // set up button click -> open menu behavior - var menu = this; this.$button.click(event => { // if there's already a menu open, remove it $(".popmenu-wrapper").remove(); - menu._renderAndShow(event); + this._renderAndShow(event); return false; }); }, @@ -51,13 +50,12 @@ var PopupMenu = Backbone.View.extend({ // set up behavior on each link/anchor elem if (this.options.length) { - var menu = this; - this.$(".popupmenu-option").each(function(i) { - var option = menu.options[i]; + this.$(".popupmenu-option").each((i, el) => { + const option = this.options[i]; // if the option has 'func', call that function when the anchor is clicked if (option.func) { - $(this).click(event => { - option.func.call(menu, event, option); + $(el).click(event => { + option.func.call(this, event, option); // We must preventDefault otherwise clicking "cancel" // on a purge or something still navigates and causes // the action. @@ -86,9 +84,9 @@ var PopupMenu = Backbone.View.extend({ } else if (option.header) { return ``; } - var href = option.href || "javascript:void(0);"; - var target = option.target ? `target="${option.target}"` : ""; - var check = option.checked ? '' : ""; + const href = option.href || "javascript:void(0);"; + const target = option.target ? `target="${option.target}"` : ""; + const check = option.checked ? '' : ""; return `${check}${option.html}`; }).join(""); }, @@ -96,8 +94,8 @@ var PopupMenu = Backbone.View.extend({ // 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; + const menuWidth = this.$el.width(); + let 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); @@ -111,11 +109,14 @@ var PopupMenu = Backbone.View.extend({ // 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) { + const closePopup = event => { + //do nothing if header item is clicked + if (event.target.classList.contains("dropdown-header")) { + return; + } $(document).off("click.close_popup"); try { if (window && window.parent !== window) { @@ -134,19 +135,19 @@ var PopupMenu = Backbone.View.extend({ console.debug(err); } } - menu.remove(); - } + this.remove(); + }; - $("html").one("click.close_popup", closePopup); + $("html").on("click.close_popup", closePopup); try { if (window && window.parent !== window) { $(window.parent.document) .find("html") - .one("click.close_popup", closePopup); + .on("click.close_popup", closePopup); } else { $("iframe#galaxy_main") .contents() - .one("click.close_popup", closePopup); + .on("click.close_popup", closePopup); } } catch (err) { if (err instanceof DOMException) { @@ -177,7 +178,7 @@ var PopupMenu = Backbone.View.extend({ // search for a menu option by its html findIndexByHtml: function(html) { - for (var i = 0; i < this.options.length; i++) { + for (let i = 0; i < this.options.length; i++) { if (_.has(this.options[i], "html") && this.options[i].html === html) { return i; } @@ -200,134 +201,5 @@ 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 = (button_element, initial_options) => { - var convertedOptions = []; - _.each(initial_options, (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 ($.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 = ($parent, selector) => { - $parent = $($parent); - selector = selector || "a"; - var options = []; - $parent.find(selector).each((elem, i) => { - var option = {}; - var $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"); - var linkTarget = $link.attr("target"); - var confirmText = $link.attr("confirm"); - - option.func = () => { - // 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 = ($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 = (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 || (($menuElement, parent) => `#${$menuElement.attr("popupmenu")}`); - - // aggregate and return all PopupMenus - var popupMenusCreated = []; - $(parent) - .find(menuSelector) - .each(function() { - var $menuElement = $(this); - - var $buttonElement = $(parent).find(buttonSelectorBuildFn($menuElement, parent)); - - popupMenusCreated.push(PopupMenu.fromDom($buttonElement, $menuElement)); - $buttonElement.addClass("popup"); - }); - return popupMenusCreated; -}; - // ============================================================================= export default PopupMenu;