GithubHelp home page GithubHelp logo

johndatserakis / vue-simple-context-menu Goto Github PK

View Code? Open in Web Editor NEW
235.0 5.0 54.0 1.81 MB

๐Ÿ“Œ Simple context-menu component built for Vue. Works well with both left and right clicks. Nothing too fancy, just works and is simple to use.

Home Page: https://johndatserakis.github.io/vue-simple-context-menu/

License: MIT License

JavaScript 31.88% Vue 62.81% HTML 5.31%
vue simple content menu right click vue3 vue2 vuejs

vue-simple-context-menu's Introduction

vue-simple-context-menu

Simple context-menu component built for Vue. Works well with both left and right clicks. Nothing too fancy, just works and is simple to use.

NPM Version NPM Downloads License Tweet

Vue 3 Support

Vue 3 is supported from v4.0.0 and beyond (current master). To use vue-simple-context-menu with Vue 2, use v3.4.2.

Install

yarn add vue-simple-context-menu

About

Just a simple little menu to be shown where a click happens - closes after use automatically by clicking an option or outside of the menu. Multiple menus are supported - just make sure to use a unique string as your element-id prop value.

A nice feature that comes baked in is the menu placement after a click - it sits just ever so slightly under your click location - so that any hover style you had on the item that was clicked gets removed nicely. I modeled it after the macOS right click menu.

Usage

import { createApp } from 'vue';
import VueSimpleContextMenu from 'vue-simple-context-menu';
import 'vue-simple-context-menu/dist/vue-simple-context-menu.css';

const app = createApp(App);

app.component('vue-simple-context-menu', VueSimpleContextMenu);
<!-- This is a basic use case where you have an array of items that you want
to allow to be clicked. In this case, `items` is an array of objects.
Each item has a click event that ties to a function. See the demo for a full example (with multiple menus as well). -->
<div class="item-wrapper">
  <div
    v-for="item in items"
    @click.prevent.stop="handleClick($event, item)"
    class="item-wrapper__item"
  >
    {{item.name}}
  </div>
</div>

<!-- Make sure you add the `ref` attribute, as that is what gives you the ability
to open the menu. -->
<vue-simple-context-menu
  element-id="myUniqueId"
  :options="options"
  ref="vueSimpleContextMenu"
  @option-clicked="optionClicked"
/>
handleClick (event, item) {
  this.$refs.vueSimpleContextMenu.showMenu(event, item)
}


optionClicked (event) {
  window.alert(JSON.stringify(event))
}

Note - you must pass the click event-info variable to the showMenu() function because that's how we know where to show the menu.

Note - make sure to use @click.prevent.stop (or @contextmenu.prevent.stop for right click) when setting up the click handler.

Props

prop type description required
elementId String Unique String that acts as the id of your menu. Yes
options Array Array of menu options to show. Component will use the name parameter as the label. Yes
options.name String Label for the option. Yes
options.class String A custom class that will be applied to the option. No
options.type String Only one possible value at the moment - divider. Pass this to set the object as a divider. No
ref String Unique String that allows you to show the menu on command. Yes

Methods

method parameters description
showMenu event (MouseEvent), item (Object) Used to show the menu. Make sure to pass a MouseEvent and an Object.

Events

event value description
option-clicked Object When a menu item is clicked the component will emit an event with a value containing the clicked item and the menu option that was clicked. Register for this event to capture the selection result.
menu-closed Emitted when the menu is closed

SASS Structure

.vue-simple-context-menu {
  &--active {
  }

  &__item {
    &:hover {
    }
  }

  &__divider {
  }
}

Development

# Install dependencies
yarn

# Serve with hot reload
yarn dev

# Run the tests
yarn test

# Build demo page
yarn build:example

# Build library
yarn build:library

# Build everything and run tests
yarn build

Other

Go ahead and fork the project! Submit an issue if needed. Have fun!

Thank You

Influenced by Lucas Calazans's pen. Go ahead and check out his other work.

License

MIT

vue-simple-context-menu's People

Contributors

ansidev avatar danielelkington avatar dependabot[bot] avatar john-devil avatar johndatserakis avatar tchoupinax avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

vue-simple-context-menu's Issues

Inline Template issues?

It seems this doesn't play well with inline-templates? Have you tested it out in inline-templates? Just breaks the render with no errors in console for me unfortunately.

Cannot read properties of undefined (reading 'showMenu')

Hi, my code is a Vue3 Typescript Vite project with composition API with script setup on top, then I have not this.$refs
I would attach a right click menu on a div named box.
Right clicking on the box container I have this error: Cannot read properties of undefined (reading 'showMenu')

Can you suggest me please a solution ? Thanks in advance.

<script setup lang="ts">
import { ref } from 'vue'
const box = ref(null)
const optionsArray = [
  {  name: 'Edit node',   slug: 'edit'  }
]
function optionClicked(event) {
  window.alert(JSON.stringify(event))
}
function handleRightClick(event: any, item: any) {
  console.log('Right click on', item)
  box.value.vueSimpleContextMenu1.showMenu(event, item)       <<<--- Here I have a problem Object box.value is possibly 'null'.ts(2531) 
}
</script>
<template>
  <div ref="box" @contextmenu.prevent.stop="handleRightClick($event, 'a text')">
   <vue-simple-context-menu
      ref="box"
      element-id="myFirstMenu"
      :options="optionsArray"
      @option-clicked="optionClicked"
    />
  </div>
</template>

The Vite plugin :

import VueSimpleContextMenu from 'vue-simple-context-menu'
import 'vue-simple-context-menu/dist/vue-simple-context-menu.css'
import type { UserModule } from '../types'

export const install: UserModule = ({ app }) => {
  console.log('loading context menu')
  app.component('VueSimpleContextMenu', VueSimpleContextMenu)
}

Feature: Divider Line Support

Curious if there has been thought of adding divider line support? I am thinking it could be added into menu definition

...
menuOptions: {
{
  name: "New Contact",
  slug: "new-contact",
},
{
  name: "-",
  slug: "divider",
},
{
  name: "New Company",
  slug: "new-company",
},
}
...

Conditional suppress options in contextmenu?

Is it possible with this menu to somehow show an option in the contextmenu only, when a certain condition is met?

In my case, i have an audio wave (on a canvas) where users can add markers of different "degrees" (1, 2 or 3, let's say). Via rightclick it shall be possible to change a marker to another degree. However, if the marker is of degree 1, only 2 menu options shall be shown: those that change the marker to degree 2 or 3, but not 1.

Thank you! :-)

Uncaught TypeError: Cannot read property 'classList' of null

vue-simple-context-menu.esm.js?2560:60 Uncaught TypeError: Cannot read property 'classList' of null
at VueComponent.hideContextMenu (vue-simple-context-menu.esm.js?2560:60)
at VueComponent.onClickOutside (vue-simple-context-menu.esm.js?2560:63)
at eval (v-click-outside.min.js?81a8:1)
at Array.forEach ()
at HTMLDocument.n.onEvent (v-click-outside.min.js?81a8:1)

selection_021

Menu not staying displayed on Firefox 66+ (macOS)

Hi there โ€“ On macOS, since Firefox 66 (66.0.1 - 66.0.5, and 67.0), contextual menu does not stay displayed after the right-click. The problem also occurs on the demo page, if you right-click on Jim, Dwight, or Pam. I have no problem on Safari, and as far as I know it is working correctly on Windows with Firefox 66+.

Nuxt and simple context menu

Hi! I am trying to implement this component with Nuxt and got it working so far โ€“ just not the click on the dropdown (yet).

I wanted to point out, that Nuxt's eslint checks for props and emits and it complains that "elementId" should be hyphenated, while "@option-clicked" could be written camelcase. So the exact opposite of what this extension shows in the example and the documentation.
Not sure if this influences the functionality somehow, but I thought I'll report my observation.

Not firing option-clicked handler?

I have used this component a number of times in various applications and all has worked out fine.

however, I have a situation in a new application where the @option-clicked handler method is not executed when selecting an item?

I am not sure where this has gone wrong? Any tips on how to track this down?

<vue-simple-context-menu :elementId="'sidebarMenuContextId'" ref="sidebarMenuContext" :options="sidebarMenu" @option-clicked="test"></vue-simple-context-menu>

Then in my component method

...
        test(data) {
            // this is never executed
            console.log('test')
            console.log(data)
        },
...

Using jQuery Event as event...

I am using a Vue Grid Component (jqWidget) which passes all events as jQuery Events (the Vue Component is a wrapper over their jQuery project).

When passing this event to the .showMenu method, it opens the contextual window at the upper left portion of page. I am sure this is because the event passed to .showMenu is not a "normal" MouseEvent which is what is normally used from Vue event.

So, my question...

What is vue-simmple-context-menu use from the normal MouseEvent to determine where it should display the contextual menu?

I have tried to set the following properties on the event object which is passed to .showMenu

.screenX
.screenY
.clientX
.clientY

But that does make a difference, as the menu is still top/left (0,0)

 event.screenX = 100
 event.screenY = 100
 event.clientX = 100
 event.clientY = 100
 this.$refs.listContextualMenu.showMenu(event, 'test')

One context menu for the whole app.

Hi ฮ“ฮนฮฌฮฝฮฝฮท,

I cannot find out who to have only one context menu shown at a time. I have multiple right click-able elements many of which are embedded one on the other. Can you suggest a solution, as many context menus appear at the same time now.

Thanks

Deprecation warning

Seeing a deprecation warning in Chrome for use of Event.path (should move to Event.composedPath() at some point) which looks like it's only in bit for the click-outside dependency (vue-simple-context-menu.esm.js:10)

Webpack encore not build

Hi, i am using symfony, and webpack encore for script, but he did work if i a add vue-simple-context-menu tag on my template, please help me ! Thank for your reply

Menu item names needs to be trimmed

Hello,

I just noticed in my source code, that the strings of the context menu items contain lots of spaces or tabs and that messes up my source code. (not that it matters)

See the following image:
image

Feature: Disabled Menu Item

Back for another UI question / feature

I am looking to disable menu items. When creating menus on macOS or Windows, one would do something like the following to define a disabled menuItem (see the left bracket at the end of the name property. Then apply a gray color as the menu item text.

{
  name: "New Contact(",
  slug: "new-contact",
},
{
  name: "New Company",
  slug: "new-company",
},

Or, if you want to be a bit more expressive, add a disabled property to menu definition object

{
  name: "New Contact",
  slug: "new-contact",
  disabled: true
},
{
  name: "New Company",
  slug: "new-company",
},

Now, much like you have done with the separator capability (thank you) when "selecting" a menuItem that is disabled, nothing should happen

Option click method not being executed

I have used this component a number of times in various applications and all has worked out fine.

however, I have a situation in a new application where the @option-clicked handler method is not executed when selecting an item?

I am not sure where this has gone wrong? Any tips on how to track this down?

<vue-simple-context-menu :elementId="'sidebarMenuContextId'" ref="sidebarMenuContext" :options="sidebarMenu" @option-clicked="test"></vue-simple-context-menu>

Then in my component method

...
        test(data) {
            // this is never executed
            console.log('test')
            console.log(data)
        },
...

Potential Offset Issue

Hi,

I have the example working in my application except the menu doesn't appear where i click.
I have the component on a view that is used by the rotuer view.
I used a chrome extension to verify the x and y co-ords of the event passed to showMenu() and it is all correct except the menu not displaying where i expect.
I manually edit the menu once it has appeared and set of the top and left to 0 and the menu then goes into the corner of my router view.
When i use chrome dev tool to cut and paste the menu and place it below the tag then it displays in the correct place.
Is there a way to specify which element the menu attaches it too? Or am i just doing something wrong??

"TypeError: this.$refs.vueSimpleContextMenu.showMenu is not a function"

[Vue warn]: Error in v-on handler: "TypeError: this.$refs.vueSimpleContextMenu.showMenu is not a function".

This happens to my application. I have just followed your installations instruction steps. But I have noticed in your example source code that it is totally different from your installation usage code example.
You have also used the "vue-click-outside" package but it is not mentioned anywhere in your installation and usage guide.
Please help me to get a solution.

Include fontawesome icons in contextual menu (use v-html)

Hey there

I am trying to display fontawesome icons in my contextual menu, but alas it seems you are using simple interpolation

<li
  v-for="(option, index) in options"
  :key="index"
  @click.stop="optionClicked(option)"
  class="vue-simple-context-menu__item"
  :class="[option.class, (option.type === 'divider' ? 'vue-simple-context-menu__divider' : '')]"
>
  {{option.name}}
</li>

image

Would you consider making a small adjustment?

<li
  v-for="(option, index) in options"
  :key="index"
  @click.stop="optionClicked(option)"
  class="vue-simple-context-menu__item"
  :class="[option.class, (option.type === 'divider' ? 'vue-simple-context-menu__divider' : '')]"
  v-html="option.name"
/>

type definition

Hi,

thank you for the neat context menu!
Are there any plans to have type definition? That would be really awesome!

Thanks in advance.

Menus showing up off screen

I'm trying to get your context menus working in a modal 'window' but they are not displaying where the right click occurs, instead they seem to be hanging off the bottom of the screen. It's not a z-index issue as yours (10000) is way higher than mine (1000). The following screenshot is the best way I can think of to illustrate what is going on:

context-menu-hiding

I'm quite certain I've set up my template as per your instructions.

<template>
  <div>
    <div class="item-wrapper" style="min-height: 500px;">
      <div class="fmgr-folder" v-for="folder in folders">
        <div @contextmenu.prevent.stop="handleClickFolder($event, folder)" class="item-wrapper__item">
          <img src="static/img/file-manager/icon-folder.png" />
          {{ folder.name }}
        </div>
      </div>
      <div class="fmgr-file" v-for="file in files">
        <div @contextmenu.prevent.stop="handleClickFile($event, file)" class="item-wrapper__item">
          <img :src="icon(file)" />
          {{ file.name }}
        </div>
      </div>
    </div>
    <vue-simple-context-menu
      elementId="folder-menu"
      :options="folderOptions()"
      ref="folderContextMenu"
      @optionClicked="optionClicked">
    </vue-simple-context-menu>
    <vue-simple-context-menu
      elementId="file-menu"
      :options="fileOptions()"
      ref="fileContextMenu"
      @optionClicked="optionClicked">
    </vue-simple-context-menu>
  </div>
</template>

CSS is imported and successfully hiding the content of :options

import VueSimpleContextMenu from 'vue-simple-context-menu'
import 'vue-simple-context-menu/dist/vue-simple-context-menu.css'

The showMenu function is being called as expected. Seems like a CSS conflict of some sort.

this.$refs.folderContextMenu.showMenu(event, item)

Any suggestions on where to poke at the CSS?

EDIT: If I manually change the top and left values in Chrome's Inspect window, I'm able to get move the menu on to the screen.

How to use on browser without npm

Hi i tried using unpkg to include the script at the bottom of my html.

<script src="https://unpkg.com/vue-simple-context-menu/dist/vue-simple-context-menu.min.js" ></script>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/vue-simple-context-menu/dist/vue-simple-context-menu.css" />

In web console, I got:

Uncaught TypeError: c.use is not a function
at vue-simple-context-menu.min.js?=1660744890769:1:4474
at vue-simple-context-menu.min.js?
=1660744890769:1:4507

Could somebody please put some example.html which demonstrate the usage of unpkg version?

Two context menus

Hi there, starting to try you component, and it works very well only if is one menu on the page since you have the ul id hardcoded. is there any way to have more than one menu? thank you!

import css not build with npm run build

Hello,

I am using this in vue 3.

Its works well on local when I run it with npm run serve command.

but when I create build for server with npm run build, css is not loading there.
import VueSimpleContextMenu from 'vue-simple-context-menu';
import 'vue-simple-context-menu/dist/vue-simple-context-menu.css';

above css is not loading, any idea how to fix this ?

Add a CSS-class per menu item

ENHANCEMENT:

It would be great to be able to add a CSS Class to each menu item. This would help me to style each item differently - with icons, colors, etc.

var options = [
     {name: "Menu Item 1", cssClass:"alert", ...}
]

problems overriding default CSS

I may be doing something wrong, but I'm having problems overriding the CSS styles. Everything working fine with the code, but I have the following in my project's home.css file, and the items in bold are not being reflected, but return to your defaults. I've tried this without the [data-v-a99b4df2] as well, but no luck. I'm sure it's something simple, but stumped.

Thanks.

.vue-simple-context-menu__item[data-v-a99b4df2] {
padding: 0px 10px 0px 5px;
background-color: lightblue;
font-family: 'Avenir', Helvetica, Arial, sans-serif;
font-size: 12px;
font-style: italic;
}
.vue-simple-context-menu li[data-v-a99b4df2]:first-of-type {
margin-top: 0px;
}
.vue-simple-context-menu li[data-v-a99b4df2]:last-of-type {
margin-bottom: 0px;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.