Changing the default right-click functionality on a website with JavaScript

When using a web application, the default behavior is to display a context menu when right-clicking. However, in my case, I want to replace this default context menu with a custom one. Despite writing code to achieve this, both menus are currently being displayed simultaneously. My goal is to show only my custom context menu and not the default one.

document.addEventListener("DOMContentLoaded", function () {
    window.showContextMenu = (id, name, width, height, locationX, locationY) => {
        var contextMenu = document.getElementById("contextMenu");
        contextMenu.style.position = "absolute";
        contextMenu.style.left = locationX + "px";
        contextMenu.style.top = locationY + "px";
        contextMenu.style.display = "block";

        contextMenu.innerHTML = `
            <ul>
                <li>Id: ${id}</li>
                <li>Name: ${name}</li>
                <li>Width: ${width}</li>
                <li>Height: ${height}</li>
                <li>LocationX: ${locationX}</li>
                <li>LocationY: ${locationY}</li>
            </ul>
        `;

        // Create the close button element
        const closeButton = document.createElement("button");
        closeButton.textContent = "Close";
        closeButton.id = "closeButton";

        // Add a click event listener to the close button
        closeButton.addEventListener("click", function () {
            contextMenu.style.display = "none";
        });

        // Append the close button to the context menu
        contextMenu.appendChild(closeButton);
    };


    const contextMenu = document.getElementById("contextMenu");
    contextMenu.addEventListener("contextmenu", function (e) {
        e.preventDefault();
    });
});



const contextMenu = document.getElementById("contextMenu");
contextMenu.addEventListener("contextmenu", function (e) {
    e.preventDefault();
});

Despite trying to use e.preventDefault(), it does not work as intended. This code snippet is part of a Blazor WebAssembly App where showContextMenu() is triggered from the razor template when an image is clicked.

Answer №1

The issue arises from only preventing the default behavior on a custom context menu rather than on the entire document or intended target element for right-clicking. To stop the default context menu from appearing, it is best to attach the contextmenu event listener to the whole document or the specific target element and invoke e.preventDefault() there. Make sure that the listener is added before the right-click action happens on the desired element.

Here is a suggested approach:

document.addEventListener("DOMContentLoaded", function () {
    document.addEventListener("contextmenu", function (e) {
        e.preventDefault();  // Stop default context menu
        showContextMenu();
    });
});

function showContextMenu() {
    var contextMenu = document.getElementById("contextMenu");
    
    // ... 

    contextMenu.style.display = "block";
}

Answer №2

Here is some code for a HTML file:

<div id="rmenu" class="hide">
<ul>
            <li>Id: ${id}</li>
            <li>Name: ${name}</li>
            <li>Width: ${width}</li>
            <li>Height: ${height}</li>
            <li>LocationX: ${locationX}</li>
            <li>LocationY: ${locationY}</li>
        </ul>
</div>

Also, here is some CSS code:

.hide {
opacity: 0;
}

.show {
  z-index: 1000;
  position: absolute;
  background-color: #5c5e63;
  color: #ECECEC;
  border-radius: 5px;
}

Lastly, here is the JS code:

document.addEventListener('contextmenu', contextMenu);
document.addEventListener('click', () => {
        document.getElementById("rmenu").className = "hide";
 })

const contextMenu = (e) => {
        document.getElementById("rmenu").className = "show";
        document.getElementById("rmenu").style.top = mouseY(e) + 'px';
        document.getElementById("rmenu").style.left = mouseX(e) + 'px';
        findSelected(e.target.getAttribute('id'));
        window.event.returnValue = false;
    }

export function mouseX(evt) {
    if (evt.pageX) {
        return evt.pageX;
    } else if (evt.clientX) {
        return evt.clientX + (document.documentElement.scrollLeft ?
            document.documentElement.scrollLeft :
            document.div.scrollLeft);
    } else {
        return null;
    }
}

export function mouseY(evt) {
    if (evt.pageY) {
        return evt.pageY;
    } else if (evt.clientY) {
        return evt.clientY + (document.documentElement.scrollTop ?
            document.documentElement.scrollTop :
            document.body.scrollTop);
    } else {
        return null;
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Google Maps: Customize infoWindow Layout

I'm having trouble figuring out how to change the default frame of an infoWindow in Google Maps. Here's my code where I create a marker and add a listener that opens an info window: var markerPosition = new google.maps.LatLng(lat, lng); ...

Ammap interfaces with an external JSON file to generate simulated lines

I am attempting to load external JSON data into my ammap using dataLoader, and then use that data to animate the lines on the map in the postProcess function var map = AmCharts.makeChart("chartdiv", { "type": "map", "theme": "light", "dataLoa ...

Guide on how to turn off cache in AngularJS + NodeJS CRUD application

I'm encountering an issue with cache in Internet Explorer, but everything seems to be working fine in Chrome. Whenever I try to add an item in my application, the data doesn't refresh automatically and I have to press Ctrl+R to manually refresh. ...

"Add a hover effect to fade the image and make it clickable for a

Is there a way to make the entire image a clickable link when it's hovered over, rather than just the text inside? I could use some assistance with this. Javascript: $('.thumbnail').hover(function() { $('.thumbnail img').stop ...

How can I pass the current value of an HTML.DropDownListFor to an ActionLink?

Is it feasible to transfer the current value of @Html.DropDownListFor to an action link? I am trying to send the template value to the Sample controller using the Create action. The code below is not functioning because @Model.SurveyTemplate does not retur ...

Continuous Scrolling of Div in jQuery

I have successfully implemented a jQuery slider that allows me to click on the next arrow and slide to the next image. However, I am now facing the challenge of making it scroll continuously. This means that when I reach the last image in the slider, the f ...

Store the checkbox's data in the database for safekeeping

Hey there, I'm working on saving the value of a checkbox using PHP. The twist is that the value is generated through JavaScript. How can I handle this scenario and save the value using PHP? Checkbox: <input type='checkbox' name='ca ...

Issues with toggling checkboxes using jQuery

I have a gridview with radio buttons in one of the columns, acting as true/false flags. Due to the requirements of my project, I need to use JavaScript to uncheck a radio button when another one is checked. Everything works fine, except when my gridview is ...

Is there a way to conceal JSON objects within a three.js scene using the loader.load function?

I am working with multiple JSON files in my three.js project and loading them using loader.load. The files are displayed when I click on the corresponding text content. How can I unload or hide an object with a second click? Below is the code I am curren ...

Accessing cell values within a table using JavaScript

I am having some trouble with extracting unique IDs from the input text areas in the first column of an HTML table. These IDs are dynamically assigned using JavaScript. Can someone help me with this issue? Below is the HTML code for my table: <table id ...

The scheme is not valid; the connection string should ideally begin with either "mongodb:" or "mongodb+srv://"

After deploying my API, I encountered an issue when trying to send a GET request to the database. The error message displayed was Runtime.UnhandledPromiseRejection with the additional note saying "Invalid scheme, expected connection string to start with &a ...

Retrieve information from the API every second

In my React Native app, I have a system where customer orders are fetched and displayed on the restaurant side in a specific screen. I'm using the Fetch API to retrieve this data. The workflow is as follows: the customer places an order, which is then ...

Is there a way to retrieve the data selected in my modal window when a button is clicked, depending on the v-for value?

As someone who is new to Vue and utilizing Bootstrap modals to showcase product information, I have grid containers that contain a product image, description, and two buttons. One of the buttons, labeled More details >>, is intended to trigger a moda ...

Complete my search input by utilizing ajax

It's only been 30 minutes since my last post, but I feel like I'm making progress with my search posts input: I've developed a model that resembles this: function matchPosts($keyword) { $this->db->get('posts'); ...

What are some strategies for boosting the efficiency of a recursive element in React?

Within my React Native Expo project, I've implemented a recursive comment component to facilitate the rendering of nested comment threads. However, as the number of comments grows, performance begins to suffer, resulting in a less-than-ideal user exp ...

What steps should I take to resolve the "Module Not Found" issue that occurs when I use the command "npm start" after setting up a new React project with npm?

Just starting out with React.js and npm and encountered an issue. After using the command: npm create react-app my-test-npm-react-app I waited for the project to be created successfully. However, when I tried running: npm start I received the followin ...

Does the reduce method work by default like this?

const product_list=[{id:1},{id:2}] const temp_products=[{id:1,quantity:10},{id:2,quantity:20}] product_list.map(prod=>{ console.log(temp_products.reduce((init,curr_prod)=>{ return curr_prod.id == prod.id ? curr_prod.quantity : null })) ...

Transforming text colors dynamically using Vue.js

Here is an Angular code snippet: <div [style.color]="'#' + prod.id.substring(0,6)"> <small>{{ prod.id }}</small> </div> Now I want to create a similar code using vue.js. ...

Concealing the presence of jquery and javascript

Currently developing a model-view-controller application (but this question can apply to any website). I'm contemplating whether it's acceptable to have exposed jQuery and JavaScript in a view. Essentially, when the program is run and source code ...

Render the React component asynchronously, only after the data has been successfully fetched

I am looking to display a component only after the necessary data has been fetched. If I try to load the data instantly, the component gets rendered but no information is displayed. class App extends React.Component { //typical construct fetchGameD ...