165 lines · 4.8 KB · JavaScript
RawDownload
////  entityListContextMenu.js////  exampleContextMenus.js was originally created by David Rowe on August 22nd, 2018.//  Modified to entityListContextMenu.js by Thijs Wenker on October 10th, 2018//  Copyright 2018 High Fidelity, Inc.//  Copyright 2024 Overte e.V.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// /* eslint-env browser */const CONTEXT_MENU_CLASS = "context-menu"; /** * ContextMenu class for EntityList * @constructor */function EntityListContextMenu() {    this._elContextMenu = null;    this._onSelectedCallback = null;    this._listItems = [];    this._initialize();} EntityListContextMenu.prototype = {     /**     * @private     */    _elContextMenu: null,     /**     * @private     */    _onSelectedCallback: null,     /**     * @private     */    _selectedEntityID: null,     /**     * @private     */    _listItems: null,     /**     * Close the context menu     */    close: function() {        if (this.isContextMenuOpen()) {            this._elContextMenu.style.display = "none";        }    },     isContextMenuOpen: function() {        return this._elContextMenu.style.display === "block";    },     /**     * Open the context menu     * @param clickEvent     * @param selectedEntityID     * @param enabledOptions     */    open: function(clickEvent, selectedEntityID, enabledOptions) {        this._selectedEntityID = selectedEntityID;         this._listItems.forEach(function(listItem) {            let enabled = enabledOptions.includes(listItem.label);            listItem.enabled = enabled;            listItem.element.setAttribute('class', enabled ? '' : 'disabled');        });         this._elContextMenu.style.display = "block";        this._elContextMenu.style.left            = Math.min(clickEvent.pageX, document.body.offsetWidth - this._elContextMenu.offsetWidth).toString() + "px";        this._elContextMenu.style.top            = Math.min(clickEvent.pageY, document.body.clientHeight - this._elContextMenu.offsetHeight).toString() + "px";        clickEvent.stopPropagation();    },     /**     * Set the callback for when a menu item is selected     * @param onSelectedCallback     */    setOnSelectedCallback: function(onSelectedCallback) {        this._onSelectedCallback = onSelectedCallback;    },     /**     * Add a labeled item to the context menu     * @param itemLabel     * @private     */    _addListItem: function(itemLabel) {        let elListItem = document.createElement("li");        elListItem.innerText = itemLabel;         let listItem = {            label: itemLabel,            element: elListItem,            enabled: false        };         elListItem.addEventListener("click", function () {            if (listItem.enabled && this._onSelectedCallback) {                this._onSelectedCallback.call(this, itemLabel, this._selectedEntityID);            }        }.bind(this), false);         elListItem.setAttribute('class', 'disabled');         this._listItems.push(listItem);        this._elContextMenu.appendChild(elListItem);    },     /**     * Add a separator item to the context menu     * @private     */    _addListSeparator: function() {        let elListItem = document.createElement("li");        elListItem.setAttribute('class', 'separator');        this._elContextMenu.appendChild(elListItem);    },     /**     * Initialize the context menu.     * @private     */    _initialize: function() {        this._elContextMenu = document.createElement("ul");        this._elContextMenu.setAttribute("class", CONTEXT_MENU_CLASS);        document.body.appendChild(this._elContextMenu);         this._addListItem("Cut");        this._addListItem("Copy");        this._addListItem("Copy ID(s)");        this._addListItem("Paste");        this._addListSeparator();        this._addListItem("Rename");        this._addListItem("Duplicate");        this._addListItem("Delete");         // Ignore clicks on context menu background or separator.        this._elContextMenu.addEventListener("click", function(event) {            // Sink clicks on context menu background or separator but let context menu item clicks through.            if (event.target.classList.contains(CONTEXT_MENU_CLASS)) {                event.stopPropagation();            }        });         // Provide means to close context menu without clicking menu item.        document.body.addEventListener("click", this.close.bind(this));        document.body.addEventListener("keydown", function(event) {            // Close context menu with Esc key.            if (this.isContextMenuOpen() && event.key === "Escape") {                this.close();            }        }.bind(this));    }};