diff --git a/docs/screenshots/views/maps/MapHelpPanel.png b/docs/screenshots/views/maps/MapHelpPanel.png new file mode 100644 index 000000000..7c277f4bb Binary files /dev/null and b/docs/screenshots/views/maps/MapHelpPanel.png differ diff --git a/src/css/map-view.css b/src/css/map-view.css index d3c9439e8..1812de6fe 100644 --- a/src/css/map-view.css +++ b/src/css/map-view.css @@ -126,7 +126,7 @@ /* ---- BADGE ---- */ -.map-view__badge{ +.map-view__badge { padding: 0.4em 0.5em 0.3em 0.55em; margin: 0 -0.2rem 0 0.3rem; font-size: 0.62rem; @@ -140,24 +140,25 @@ font-weight: 500; } -.map-view__badge--blue{ +.map-view__badge--blue { background-color: var(--map-col-blue); filter: none; } -.map-view__badge--green{ +.map-view__badge--green { background-color: var(--map-col-green); filter: none; } -.map-view__badge--yellow{ +.map-view__badge--yellow { background-color: var(--map-col-yellow); color: var(--map-col-bkg-lighter); filter: none; font-weight: 600; opacity: 0.9; } -.map-view__badge--contrast{ + +.map-view__badge--contrast { background-color: var(--map-col-text); color: var(--map-col-bkg); opacity: 0.8; @@ -612,23 +613,24 @@ represents 1 unit of the given distance measurement. */ border-radius: var(--map-border-radius); } -.layer-details__notification--blue{ +.layer-details__notification--blue { background-color: var(--map-col-blue); filter: none; } -.layer-details__notification--green{ +.layer-details__notification--green { background-color: var(--map-col-green); filter: none; } -.layer-details__notification--yellow{ +.layer-details__notification--yellow { background-color: var(--map-col-yellow); color: var(--map-col-bkg-lighter); filter: none; opacity: 0.9; } -.layer-details__notification--contrast{ + +.layer-details__notification--contrast { background-color: var(--map-col-text); color: var(--map-col-bkg); opacity: 0.95; @@ -972,3 +974,93 @@ other class: .ui-slider-range */ grid-auto-rows: min-content; grid-gap: 1rem; } + +/***************************************************************************************** + * + * Help panel + * + * Panel that shows navigation and other help information + * + */ + +.map-help-panel{ + width: 100%; +} + +.nav-help { + background-color: var(--map-col-bkg-lighter); + border-radius: var(--map-border-radius); +} + +.nav-help .map-view__button { + background-color: var(--map-col-bkg-lighter); + padding: 0.65rem 0.9rem; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + opacity: 0.8; +} + +.nav-help .map-view__button--active { + background-color: var(--map-col-bkg-lightest); + opacity: 1; +} + +.nav-help__img { + height: 48px; + width: 70px; +} + +.nav-help__instructions { + display: grid; + width: 100%; + gap: 0.8rem; + padding: 0.8rem 0.4rem; + background-color: var(--map-col-bkg-lightest); + border-radius: var(--map-border-radius); + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-help__instructions.hidden { + display: none; +} + +.cesium-navigation-help-pan { + color: #66ccff; + font-weight: bold; +} + +.cesium-navigation-help-zoom { + color: #65fd00; + font-weight: bold; +} + +.cesium-navigation-help-rotate { + color: #ffd800; + font-weight: bold; +} + +.cesium-navigation-help-tilt { + color: #d800d8; + font-weight: bold; +} + +.nav-help__instruction { + display: grid; + grid-template-columns: 70px auto; + gap: 0.5rem; + align-items: center; +} + +.map-help-panel__title{ + text-transform: uppercase; + font-size: 0.95rem; + font-weight: 600; + letter-spacing: 0.06em; + margin: 0 0 0.8rem 0; + line-height: normal; +} + +.map-help-panel__section:not(:first-child) { + margin-top: 2.5rem; +} \ No newline at end of file diff --git a/src/js/models/maps/Map.js b/src/js/models/maps/Map.js index f15cfe4a5..b832d4a8f 100644 --- a/src/js/models/maps/Map.js +++ b/src/js/models/maps/Map.js @@ -42,8 +42,8 @@ define([ * side bar with layer list, etc. If true, the {@link MapView} will render * a {@link ToolbarView}. * @property {Boolean} [showLayerList=true] - Whether or not to show the - * layer list in the toolbar. If true, the {@link ToolbarView} will - * render a {@link LayerListView}. + * layer list in the toolbar. If true, the {@link ToolbarView} will render + * a {@link LayerListView}. * @property {Boolean} [showHomeButton=true] - Whether or not to show the * home button in the toolbar. * @property {Boolean} [toolbarOpen=false] - Whether or not the toolbar is @@ -56,6 +56,17 @@ define([ * users to click on map features to show more information about them. If * true, the {@link MapView} will render a {@link FeatureInfoView} and * will initialize "picking" in the {@link CesiumWidgetView}. + * @property {String} [clickFeatureAction="showDetails"] - The default + * action to take when a user clicks on a feature on the map. The + * available options are "showDetails" (show the feature details in the + * sidebar) or "zoom" (zoom to the feature's location). + * @property {Boolean} [showNavHelp=true] - Whether or not to show + * navigation instructions in the toolbar. + * @property {Boolean} [showFeedback=false] - Whether or not to show a + * feedback section in the toolbar with the text specified in + * feedbackText. + * @property {String} [feedbackText=null] - The text to show in the + * feedback section. showFeedback must be true for this to be shown. * * @example * { @@ -159,6 +170,12 @@ define([ * action to take when a user clicks on a feature on the map. The * available options are "showDetails" (show the feature details in the * sidebar) or "zoom" (zoom to the feature's location). + * @property {Boolean} [showNavHelp=true] - Whether or not to show + * navigation instructions in the toolbar. + * @property {Boolean} [showFeedback=false] - Whether or not to show a + * feedback section in the toolbar. + * @property {String} [feedbackText=null] - The text to show in the + * feedback section. */ defaults: function () { return { @@ -184,6 +201,9 @@ define([ showScaleBar: true, showFeatureInfo: true, clickFeatureAction: "showDetails", + showNavHelp: true, + showFeedback: false, + feedbackText: null }; }, diff --git a/src/js/templates/maps/cesium-nav-help.html b/src/js/templates/maps/cesium-nav-help.html new file mode 100644 index 000000000..34025b34e --- /dev/null +++ b/src/js/templates/maps/cesium-nav-help.html @@ -0,0 +1,107 @@ +
diff --git a/src/js/views/maps/HelpPanelView.js b/src/js/views/maps/HelpPanelView.js new file mode 100644 index 000000000..8483958c0 --- /dev/null +++ b/src/js/views/maps/HelpPanelView.js @@ -0,0 +1,256 @@ +"use strict"; + +define(["backbone", "text!templates/maps/cesium-nav-help.html"], function ( + Backbone, + NavHelpTemplate +) { + /** + * @class MapHelpPanel + * @classdesc The MapHelpPanel view displays navigation instructions and other + * help information for the map. + * @classcategory Views/Maps + * @name MapHelpPanel + * @extends Backbone.View + * @screenshot views/maps/MapHelpPanel.png + * @since x.x.x + * @constructs MapHelpPanel + */ + var MapHelpPanel = Backbone.View.extend( + /** @lends MapHelpPanel.prototype */ { + /** + * The type of View this is + * @type {string} + */ + type: "MapHelpPanel", + + /** + * The HTML classes to use for this view's element + * @type {string} + */ + className: "map-help-panel", + + /** + * Initializes the MapHelpPanel + * @param {Object} options - A literal object with options to pass to the + * view + * @param {boolean} [options.showFeedback=true] - Set to false to hide the + * feedback section + * @param {boolean} [options.showNavHelp=true] - Set to false to hide the + * navigation instructions section + * @param {string} [options.feedbackText] - Text to show in the feedback + * section + */ + initialize: function (options) { + if (!options) options = {}; + + const validOptions = ["showFeedback", "feedbackText", "showNavHelp"]; + validOptions.forEach((option) => { + if (options.hasOwnProperty(option)) { + this[option] = options[option]; + } + }); + + }, + + /** + * The template to use to show the navigation instructions + * @type {function} + */ + navHelpTemplate: _.template(NavHelpTemplate), + + /** + * Set to false to hide the feedback section + * @type {boolean} + * @default true + */ + showFeedback: true, + + /** + * Set to false to hide the navigation instructions section + * @type {boolean} + * @default true + */ + showNavHelp: true, + + /** + * Text to show in the feedback section + * @type {string} + */ + feedbackText: `Please contact the administrator of this map for help.`, + + /** + * The sections to show in the help panel + * @type {Object[]} + * @property {string} id - The id of the section + * @property {string} title - The title of the section + * @property {string} render - The name of the method to call to render + * the section. The method will be passed the container within which to + * render the section. It should return the container element with the + * section added. Methods will be called with the view as the context. + */ + sections: [ + { + id: "nav-help", + title: "Navigation Instructions", + render: "renderNavHelp", + }, + { + id: "feedback", + title: "Feedback", + render: "renderFeedback", + }, + ], + + /** + * Renders the MapHelpPanel + * @returns {MapHelpPanel} Returns the view + */ + render: function () { + const view = this; + + let sections = JSON.parse(JSON.stringify(view.sections)); + + if (view.showFeedback === false) { + sections = sections.filter((section) => { + return section.id !== "feedback"; + }); + } + + if (view.showNavHelp === false) { + sections = sections.filter((section) => { + return section.id !== "nav-help"; + }); + } + + sections.forEach((section) => { + view.renderSection(section); + }); + + return view; + }, + + /** + * Renders a section of the help panel + * @param {Object} section - The options for the section, see + * {@link MapHelpPanel#sections} + */ + renderSection: function (section) { + try { + const view = this; + const renderMethod = view[section.render] || null; + if (!renderMethod) return; + + const contentContainerClass = "map-help-panel__content"; + + const sectionEl = document.createElement("section"); + sectionEl.classList.add("map-help-panel__section"); + sectionEl.innerHTML = `