From 9cdf3f95d484213c33b13fc2c75b1b27feda4e22 Mon Sep 17 00:00:00 2001 From: William Wall Date: Thu, 6 Feb 2020 16:28:49 -0700 Subject: [PATCH] feat(menu): add link menu item option Adds a link option to menu items which is either a string (the URL) or an object of {href, target, opener, referrer} such as {href: 'somepage.html', target: '_blank'}. The openener and referrer options are only needed to open windows in the same process, which gives that page access to window.opener and window.opener.document (those should be omitted for any external links for security reasons). --- .../ui/columnactions/abstractcolumnaction.js | 1 - src/os/ui/help/help.js | 10 +-- src/os/ui/menu/menuitem.js | 61 +++++++++++++++++++ src/plugin/weather/weatherplugin.js | 49 ++++++--------- 4 files changed, 80 insertions(+), 41 deletions(-) diff --git a/src/os/ui/columnactions/abstractcolumnaction.js b/src/os/ui/columnactions/abstractcolumnaction.js index 6121fdb57..d34af6575 100644 --- a/src/os/ui/columnactions/abstractcolumnaction.js +++ b/src/os/ui/columnactions/abstractcolumnaction.js @@ -1,5 +1,4 @@ goog.provide('os.ui.columnactions.AbstractColumnAction'); -goog.require('goog.structs.Map'); diff --git a/src/os/ui/help/help.js b/src/os/ui/help/help.js index f6a504e6d..cda22d7f2 100644 --- a/src/os/ui/help/help.js +++ b/src/os/ui/help/help.js @@ -134,11 +134,11 @@ os.ui.help.HelpCtrl.prototype.initialize = function() { root.addChild({ eventType: os.ui.help.EventType.HELP_VIDEO, label: 'Help Videos', + link: videoUrl, tooltip: 'View help videos for ' + appName, icons: [''], sort: 20 }); - this.menu.listen(os.ui.help.EventType.HELP_VIDEO, this.onHelpAction_, false, this); } root.addChild({ @@ -172,13 +172,11 @@ os.ui.help.HelpCtrl.prototype.initialize = function() { root.addChild({ eventType: os.ui.help.EventType.VIDEO_CARD, label: 'Graphics Card Help', + link: videoCardUrl, tooltip: 'Troubleshoot 3D view', icons: [''], sort: 120 }); - this.menu.listen(os.ui.help.EventType.VIDEO_CARD, function() { - window.open(videoCardUrl); - }, false, this); } if (os.settings.get('onboarding') && os.settings.get('onboarding')['hideTips'] !== true) { @@ -247,10 +245,6 @@ os.ui.help.HelpCtrl.prototype.onHelpAction_ = function(event) { case os.ui.help.EventType.VIEW_ALERTS: this.scope.$emit(os.ui.help.EventType.VIEW_ALERTS); break; - case os.ui.help.EventType.HELP_VIDEO: - var videoUrl = /** @type {string} */ (os.settings.get('helpVideoUrl')); - window.open(videoUrl); - break; case os.ui.help.EventType.CONTROLS: os.ui.help.ControlsCtrl.launch(); break; diff --git a/src/os/ui/menu/menuitem.js b/src/os/ui/menu/menuitem.js index 7a39e3d38..fb53b72d6 100644 --- a/src/os/ui/menu/menuitem.js +++ b/src/os/ui/menu/menuitem.js @@ -31,11 +31,23 @@ os.ui.menu.UnclickableTypes = [ os.ui.menu.MenuItemType.SEPARATOR]; +/** + * @typedef {{ + * href: !string, + * target: (string|undefined), + * opener: (boolean|undefined), + * referrer: (boolean|undefined) + * }} + */ +os.ui.menu.MenuItemLink; + + /** * @typedef {{ * type: (os.ui.menu.MenuItemType|undefined), * eventType: (string|undefined), * label: (string|undefined), + * link: (string|os.ui.menu.MenuItemLink|undefined), * metricKey: (string|undefined), * visible: (boolean|undefined), * enabled: (boolean|undefined), @@ -71,6 +83,7 @@ os.ui.menu.MenuItem = function(options) { this.shortcut = options.shortcut; this.sort = options.sort || 0; this.closeOnSelect = options.closeOnSelect != null ? options.closeOnSelect : true; + this.link = options.link; /** * @type {Array>|undefined} @@ -275,6 +288,8 @@ os.ui.menu.MenuItem.prototype.render = function(context, opt_target) { // start wrapper div (required by jquery-ui 1.12+) html += '
'; + html += this.renderLinkOpen_(); + // hotkey/shortcut if (this.shortcut) { html += '' + this.shortcut + ''; @@ -300,6 +315,8 @@ os.ui.menu.MenuItem.prototype.render = function(context, opt_target) { // label html += '' + this.label + ''; + html += this.renderLinkClose_(); + // end wrapper div (required by jquery-ui 1.12+) html += '
'; @@ -317,6 +334,50 @@ os.ui.menu.MenuItem.prototype.render = function(context, opt_target) { }; +/** + * @return {!string} + */ +os.ui.menu.MenuItem.prototype.renderLinkOpen_ = function() { + let html = ''; + + if (this.link) { + if (typeof this.link === 'string') { + html += ''; + } else { + html += '' : ''; +}; + + /** * @param {!os.ui.menu.MenuItem} a The first item * @param {!os.ui.menu.MenuItem} b The second item diff --git a/src/plugin/weather/weatherplugin.js b/src/plugin/weather/weatherplugin.js index c06bbf584..f3fb58749 100644 --- a/src/plugin/weather/weatherplugin.js +++ b/src/plugin/weather/weatherplugin.js @@ -40,12 +40,26 @@ plugin.weather.WeatherPlugin.prototype.init = function() { if (group) { group.addChild({ label: 'Weather Forecast', + link: url, eventType: plugin.weather.WeatherPlugin.ID, tooltip: 'Open the weather forecast for this location', - icons: [''] + icons: [''], + beforeRender: + /** + * @param {ol.Coordinate} coord + * @this {os.ui.menu.MenuItem} + */ + function(coord) { + var url = plugin.weather.getUrl_(); + + if (url) { + url = url.replace('{lon}', coord[0].toString()); + url = url.replace('{lat}', coord[1].toString()); + } + + this.link = url; + } }); - - menu.listen(plugin.weather.WeatherPlugin.ID, plugin.weather.onLookup_); } } }; @@ -64,32 +78,3 @@ plugin.weather.getUrl_ = function() { return null; }; - - -/** - * Forecast menu option listener - * - * @param {os.ui.menu.MenuEvent} evt The menu event - * @private - */ -plugin.weather.onLookup_ = function(evt) { - plugin.weather.launchForecast(evt.getContext()); -}; - - -/** - * Opens a weather forecast for the given location - * - * @param {ol.Coordinate} coord - */ -plugin.weather.launchForecast = function(coord) { - var url = plugin.weather.getUrl_(); - coord = ol.proj.toLonLat(coord, os.map.PROJECTION); - - if (url) { - url = url.replace('{lon}', coord[0].toString()); - url = url.replace('{lat}', coord[1].toString()); - - window.open(url, '_blank'); - } -};