Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Update the code to better handle the dropdown menus #299

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions saltgui/static/scripts/Character.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class Character {
Character.BLACK_RIGHT_POINTING_POINTER = "\u25BA";
Character.WHITE_DOWN_POINTING_TRIANGLE = "\u25BD";
Character.BLACK_DIAMOND = "\u25C6";
Character.WHITE_CIRCLE = "\u25CB";
Character.BLACK_CIRCLE = "\u25CF";
Character.GEAR = "\u2699";
Character.WARNING_SIGN = "\u26A0" + Character._VARIATION_SELECTOR_16;
Expand Down
21 changes: 11 additions & 10 deletions saltgui/static/scripts/CommandBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import {Character} from "./Character.js";
import {Documentation} from "./Documentation.js";
import {DropDownMenu} from "./DropDown.js";
import {DropDownMenuCmd} from "./DropDownCmd.js";
import {Output} from "./output/Output.js";
import {ParseCommandLine} from "./ParseCommandLine.js";
import {Router} from "./Router.js";
Expand All @@ -18,14 +18,15 @@ export class CommandBox {
this.api = pApi;

const cmdbox = document.getElementById("cmd-box");
this.cmdmenu = new DropDownMenu(cmdbox);
this.cmdmenu = new DropDownMenuCmd(cmdbox);

this.documentation = new Documentation(this.router, this);
this._registerCommandBoxEventListeners();

RunType.createMenu();
TargetType.createMenu();

this.documentation = new Documentation(pRouter, this);

const manualRun = document.getElementById("popup-run-command");
Utils.addTableHelp(manualRun, "Click for help", "bottom-center");
const helpButton = manualRun.querySelector("#help");
Expand Down Expand Up @@ -58,7 +59,7 @@ export class CommandBox {
CommandBox.templateCatMenu.setTitle("");
return;
}
const menu = new DropDownMenu(titleElement);
const menu = new DropDownMenuCmd(titleElement);
menu.setTitle("");
menu.menuButton.classList.add("small-button-left");
CommandBox.templateCatMenu = menu;
Expand All @@ -70,7 +71,7 @@ export class CommandBox {
}
categories.unshift(null);
for (const category of categories) {
menu.addMenuItem(
menu.addMenuItemCmd(
() => CommandBox._templateCatMenuItemTitle(category),
() => {
CommandBox.templateTmplMenu._templateCategory = category;
Expand Down Expand Up @@ -120,7 +121,7 @@ export class CommandBox {
CommandBox.templateTmplMenu._templateCategory = null;
return;
}
const menu = new DropDownMenu(titleElement);
const menu = new DropDownMenuCmd(titleElement);
menu.menuButton.classList.add("small-button-left");
CommandBox.templateTmplMenu = menu;
CommandBox.templateTmplMenu._templateCategory = null;
Expand All @@ -132,7 +133,7 @@ export class CommandBox {
if (!description) {
description = "(" + key + ")";
}
menu.addMenuItem(
menu.addMenuItemCmd(
() => CommandBox._templateTmplMenuItemTitle(template),
() => {
CommandBox.applyTemplateByTemplate(template);
Expand Down Expand Up @@ -267,7 +268,7 @@ export class CommandBox {
TargetType.setTargetType(pTargetType);
} else {
// not in the template, revert to default
TargetType.setTargetTypeDefault();
TargetType.setTargetType(null);
}

if (pTarget) {
Expand Down Expand Up @@ -341,7 +342,7 @@ export class CommandBox {
const commandField = document.getElementById("command");
const commandValue = commandField.value;

const targetType = TargetType.menuTargetType._value;
const targetType = TargetType.menuTargetType.getValue();

const patWhitespaceAll = /\s/g;
const commandValueNoTabs = commandValue.replace(patWhitespaceAll, " ");
Expand Down Expand Up @@ -492,7 +493,7 @@ export class CommandBox {

// reset to default, so that its value is initially hidden
RunType.setRunTypeDefault();
TargetType.setTargetTypeDefault();
TargetType.setTargetType(null);

if (Router.currentPage) {
Router.currentPage.refreshPage();
Expand Down
20 changes: 10 additions & 10 deletions saltgui/static/scripts/Documentation.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ export class Documentation {
this.router = pRouter;
this.commandbox = pCommandBox;

pCommandBox.cmdmenu.addMenuItem(
Documentation.DOCUMENTATION_URL = "https://docs.saltproject.io/en/latest/ref/";
Documentation.EXTERNAL_LINK = Character.NO_BREAK_SPACE + Character.EXTERNAL_LINK_IMG;

Documentation.PROVIDERS = { };

pCommandBox.cmdmenu.addMenuItemCmd(
() => Documentation._manualRunMenuSysDocPrepare(),
() => this._manualRunMenuSysDocRun());
pCommandBox.cmdmenu.addMenuItem(
pCommandBox.cmdmenu.addMenuItemCmd(
() => Documentation._manualRunMenuHtmlDocPrepare(),
() => Documentation._manualRunMenuHtmlDocRun());
pCommandBox.cmdmenu.addMenuItem(
pCommandBox.cmdmenu.addMenuItemCmd(
() => Documentation._manualRunMenuBeaconNamePrepare(),
() => Documentation._manualRunMenuBeaconNameRun());
pCommandBox.cmdmenu.addMenuItem(
pCommandBox.cmdmenu.addMenuItemCmd(
() => Documentation._manualRunMenuCustomHelpPrepare(),
() => Documentation._manualRunMenuCustomHelpRun());

Documentation.DOCUMENTATION_URL = "https://docs.saltproject.io/en/latest/ref/";
Documentation.EXTERNAL_LINK = Character.NO_BREAK_SPACE + Character.EXTERNAL_LINK_IMG;

Documentation.PROVIDERS = { };
}

// INTERNAL DOCUMENTATION
Expand Down Expand Up @@ -120,7 +120,7 @@ export class Documentation {
dummyCommand = "sys.doc " + cmd;
}

const targetType = TargetType.menuTargetType._value;
const targetType = TargetType.menuTargetType.getValue();

const func = this.commandbox.getRunParams(targetType, target, docCommand, true, false);
if (func === null) {
Expand Down
68 changes: 38 additions & 30 deletions saltgui/static/scripts/DropDown.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {Utils} from "./Utils.js";
// a) sets the title using pMenuItem.innerText = "xyz"
// b) arranges the visibility using pMenuItem.style.display = true/false
// 2: the callback function
// called when the menu item is selected: (pClickEvent) => { ... }
// called when the menu item is selected: () => { ... }
// all menu items are re-validated when the menu pops up
// when all menu items are invisible, the menu-button must be made invisible
// since this can happen at any time, this cannot be done when the menu is shown
Expand All @@ -20,6 +20,8 @@ import {Utils} from "./Utils.js";
// the menu. when at least one item is visible, the menu is visible
// remember to call verifyApp() when that is potentially the case

// superclass for DropDownMenuRadio, DropDownMenuCheckBox and DropDownMenuCmd

export class DropDownMenu {

// Creates an empty dropdown menu
Expand Down Expand Up @@ -87,10 +89,10 @@ export class DropDownMenu {
continue;
}

const verifyCallBack = chld.verifyCallBack;
if (verifyCallBack) {
const title = verifyCallBack(chld);
if (title === null) {
const titleCallBack = chld._titleCallBack;
if (titleCallBack) {
const title = titleCallBack.bind(this)(chld);
if (!title) {
chld.style.display = "none";
continue;
}
Expand All @@ -106,6 +108,7 @@ export class DropDownMenu {
itemsBeforeSeparator += 1;
}
}

// hide the menu when it has no visible menu-items
const displayVisible = this.menuDropdown.tagName === "TD" ? "table-cell" : "inline-block";
const displayInvisible = "none";
Expand All @@ -125,25 +128,49 @@ export class DropDownMenu {
// function is called each time the menu opens
// This allows dynamic menuitem titles (use menuitem.innerText)
// or visibility (use menuitem.style.display = "none"/"inline-block")
addMenuItem (pTitle, pCallBack, pValue) {
addMenuItem (pValue, pTitle, pSystemCallBack, pUserCallBack) {

const button = Utils.createDiv("run-command-button", Character.HORIZONTAL_ELLIPSIS);
if (pValue) {
button._value = pValue;
}

button._value = pValue;

if (typeof pTitle === "string") {
button.innerText = DropDownMenu._sanitizeMenuItemTitle(pTitle);
} else {
button.verifyCallBack = pTitle;
button._titleCallBack = pTitle;
}

button.addEventListener("click", (pClickEvent) => {

// hide the menu
pClickEvent.target.parentElement.style.display = "none";

// "show" the menu again after a short delay
// but because the mouse is no longer hovering it,
// it will actually remain invisible
window.setTimeout(() => {
pClickEvent.target.parentElement.style.display = "";
}, 500);
this._callback(pClickEvent, pCallBack, pValue);

this._value = pValue;

if (pSystemCallBack) {
pSystemCallBack.bind(this)(pClickEvent.target);
}

if (pUserCallBack) {
pUserCallBack.bind(this)(pClickEvent.target);
}

// all menu items may have become invisible
this.verifyAll();

pClickEvent.stopPropagation();
});

this.menuDropdownContent.appendChild(button);

// the menu might have become populated enough to get visible
this.verifyAll();
return button;
}
Expand All @@ -157,11 +184,6 @@ export class DropDownMenu {
this.menuDropdownContent.appendChild(div);
}

_callback (pClickEvent, pCallBack, pValue) {
this._value = pValue;
pCallBack(pClickEvent);
}

setTitle (pTitle) {
// Setting the title implies that we are interested
// in the menu values, rather than their actions.
Expand All @@ -172,18 +194,4 @@ export class DropDownMenu {
pTitle += Character.GEAR;
this.menuButton.innerText = DropDownMenu._sanitizeMenuItemTitle(pTitle);
}

__showMenu () {
this.menuDropdown.style.display = "inline-block";
}

__hideMenu () {
this.menuDropdown.style.display = "none";
}

clearMenu () {
while (this.menuDropdownContent.firstChild) {
this.menuDropdownContent.removeChild(this.menuDropdownContent.firstChild);
}
}
}
38 changes: 38 additions & 0 deletions saltgui/static/scripts/DropDownCheckBox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* global */

import {Character} from "./Character.js";
import {DropDownMenu} from "./DropDown.js";

export class DropDownMenuCheckBox extends DropDownMenu {

static _menuItemTitleCallBack (pMenuItem) {
let prefix = "";
if (pMenuItem._selected === true) {
prefix = Character.HEAVY_CHECK_MARK + Character.NO_BREAK_SPACE;
}
return prefix + pMenuItem._title;
}

static _menuItemActionCallBack (pMenuItem) {
pMenuItem._selected = !pMenuItem._selected;
}

addMenuItemCheckBox (pValue, pTitle, pUserCallBack) {
const menuItem = super.addMenuItem(
pValue,
DropDownMenuCheckBox._menuItemTitleCallBack,
DropDownMenuCheckBox._menuItemActionCallBack,
pUserCallBack);
menuItem._title = pTitle;
return menuItem;
}

isSet (pValue) {
for (const menuItem of this.menuDropdownContent.childNodes) {
if (menuItem._selected === true && menuItem._value === pValue) {
return true;
}
}
return false;
}
}
14 changes: 14 additions & 0 deletions saltgui/static/scripts/DropDownCmd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* global */

import {DropDownMenu} from "./DropDown.js";

export class DropDownMenuCmd extends DropDownMenu {

addMenuItemCmd (pTitle, pUserCallBack) {
return super.addMenuItem(
null,
pTitle,
pUserCallBack
);
}
}
67 changes: 67 additions & 0 deletions saltgui/static/scripts/DropDownRadio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* global */

import {Character} from "./Character.js";
import {DropDownMenu} from "./DropDown.js";

export class DropDownMenuRadio extends DropDownMenu {
constructor (pParentElement) {
super(pParentElement);
this._value = null;
this._defaultValue = null;
}

getValue () {
if (this._value === null) {
return this._defaultValue;
}
return this._value;
}

setValue (pValue) {
this._value = pValue;
}

setDefaultValue (pDefaultValue) {
this._defaultValue = pDefaultValue;
}

_menuItemTitleCallBack (pMenuItem) {
let title;
if (!pMenuItem._title) {
title = "...";
} else if (typeof pMenuItem._title === "string") {
title = pMenuItem._title;
} else {
title = pMenuItem._title.bind(this)(pMenuItem);
}

if (title === null) {
// menu item will be hidden
} else if (pMenuItem._value === this._value) {
title = Character.BLACK_CIRCLE + Character.NO_BREAK_SPACE + title;
} else if (this._value === null && pMenuItem._value === this._defaultValue) {
title = Character.WHITE_CIRCLE + Character.NO_BREAK_SPACE + title;
}
return title;
}

_menuItemActionCallBack (pMenuItem) {
this._value = pMenuItem._value;
let menuTitle = pMenuItem._title;
if (menuTitle && typeof menuTitle !== "string") {
menuTitle = menuTitle.bind(this)(pMenuItem);
}
this.setTitle(menuTitle);
}

addMenuItemRadio (pValue, pTitle, pUserCallBack) {
const menuItem = super.addMenuItem(
pValue,
this._menuItemTitleCallBack,
this._menuItemActionCallBack,
pUserCallBack);
menuItem._value = pValue;
menuItem._title = pTitle;
return menuItem;
}
}
2 changes: 2 additions & 0 deletions saltgui/static/scripts/ParseCommandLine.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* global */

// Function to parse a commandline
// The line is broken into individual tokens
// Each token that is recognized as a JS type will get that type
Expand Down
Loading
Loading