diff --git a/CHANGELOG.md b/CHANGELOG.md
index f785b7a..b0ccdfb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+# 3.3.0 (Oct 15, 2018)
+
+## Added
+- Context menu now emits events when opened and closed ([issue #10](https://github.com/rawilk/vue-context/issues/10))
+
# 3.2.0 (Sep 12, 2018)
### Added
@@ -47,4 +52,4 @@
- Bottom border from context menu line items.
## 2.0.0 (Aug 17, 2017)
-- Initial release
\ No newline at end of file
+- Initial release
diff --git a/README.md b/README.md
index c91a56b..324b6f1 100644
--- a/README.md
+++ b/README.md
@@ -146,10 +146,17 @@ new Vue({
## Props
-| Property | Type | Default | Description
-| -------- | ---- | ------- | -----------
-| `closeOnClick` | Boolean | `true` | If set to false, context menu will not automatically close when clicked on.
-| `closeOnScroll` | Boolean | `true` | If set to true, context menu will automatically close on window scroll.
+| Property | Type | Default | Description |
+| --- | --- | --- | --- |
+| `closeOnClick` | Boolean | `true` | If set to false, context menu will not automatically close when clicked on. |
+| `closeOnScroll` | Boolean | `true` | If set to true, context menu will automatically close on window scroll. |
+
+## Events
+
+| Event | Params | Description |
+| --- | --- | --- |
+| close | none | Emits when the context menu is closed |
+| open | `event`, `data`, `top`, `left` | Emits when the menu is opened. The event, context menu data, top and left position are all sent through as parameters as well. |
## Credits
@@ -159,4 +166,4 @@ vue-context is intended to provide a simple and lightweight context menu for Vue
## License
-The MIT License (MIT). Please see the [License file](https://github.com/rawilk/vue-context/blob/master/LICENSE) for more information.
\ No newline at end of file
+The MIT License (MIT). Please see the [License file](https://github.com/rawilk/vue-context/blob/master/LICENSE) for more information.
diff --git a/dist/vue-context.js b/dist/vue-context.js
index 230b4b3..a232988 100644
--- a/dist/vue-context.js
+++ b/dist/vue-context.js
@@ -1 +1 @@
-!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var o in n)("object"==typeof exports?exports:e)[o]=n[o]}}("undefined"!=typeof self?self:this,function(){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:o})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(2),r=n.n(o);n.d(t,"VueContext",function(){return r.a})},function(e,t,n){var o=n(8)(n(9),n(10),!1,function(e){n(3)},"data-v-22758dc4",null);e.exports=o.exports},function(e,t,n){var o=n(4);"string"==typeof o&&(o=[[e.i,o,""]]),o.locals&&(e.exports=o.locals);n(6)("727e60ce",o,!0,{})},function(e,t,n){(e.exports=n(5)(!1)).push([e.i,".v-context[data-v-22758dc4]{background:#fafafa;border:1px solid #bdbdbd;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);display:block;margin:0;padding:0;position:fixed;width:250px;z-index:99999}.v-context ul[data-v-22758dc4]{list-style:none;padding:10px 0;margin:0;font-size:12px;font-weight:600}.v-context ul li[data-v-22758dc4]{margin:0;padding:10px 35px;cursor:pointer}.v-context ul li[data-v-22758dc4]:hover{background:#1e88e5;color:#fafafa}",""])},function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var n=function(e,t){var n=e[1]||"",o=e[3];if(!o)return n;if(t&&"function"==typeof btoa){var r=(s=o,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(s))))+" */"),i=o.sources.map(function(e){return"/*# sourceURL="+o.sourceRoot+e+" */"});return[n].concat(i).concat([r]).join("\n")}var s;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n}).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var o={},r=0;rn.parts.length&&(o.parts.length=n.parts.length)}else{var s=[];for(r=0;rn&&(e=n),t>o&&(t=o),this.top=e,this.left=t},removeScrollEventListener:function(){window.removeEventListener("scroll",this.close)}},watch:{closeOnScroll:function(e,t){e!==t&&(e?this.addScrollEventListener():this.removeScrollEventListener())}}}},function(e,t){e.exports={render:function(){var e=this.$createElement;return(this._self._c||e)("div",{directives:[{name:"show",rawName:"v-show",value:this.show,expression:"show"}],staticClass:"v-context",style:this.style,attrs:{tabindex:"-1"},on:{blur:this.close,click:this.onClick,"!contextmenu":function(e){e.preventDefault()}}},[this._t("default",null,{data:this.data})],2)},staticRenderFns:[]}}])});
\ No newline at end of file
+!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var o in n)("object"==typeof exports?exports:e)[o]=n[o]}}("undefined"!=typeof self?self:this,function(){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:o})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(2),r=n.n(o);n.d(t,"VueContext",function(){return r.a})},function(e,t,n){var o=n(8)(n(9),n(10),!1,function(e){n(3)},"data-v-18aeaae6",null);e.exports=o.exports},function(e,t,n){var o=n(4);"string"==typeof o&&(o=[[e.i,o,""]]),o.locals&&(e.exports=o.locals);n(6)("50ad4866",o,!0,{})},function(e,t,n){(e.exports=n(5)(!1)).push([e.i,".v-context[data-v-18aeaae6]{background:#fafafa;border:1px solid #bdbdbd;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);display:block;margin:0;padding:0;position:fixed;width:250px;z-index:99999}.v-context ul[data-v-18aeaae6]{list-style:none;padding:10px 0;margin:0;font-size:12px;font-weight:600}.v-context ul li[data-v-18aeaae6]{margin:0;padding:10px 35px;cursor:pointer}.v-context ul li[data-v-18aeaae6]:hover{background:#1e88e5;color:#fafafa}",""])},function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var n=function(e,t){var n=e[1]||"",o=e[3];if(!o)return n;if(t&&"function"==typeof btoa){var r=(s=o,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(s))))+" */"),i=o.sources.map(function(e){return"/*# sourceURL="+o.sourceRoot+e+" */"});return[n].concat(i).concat([r]).join("\n")}var s;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n}).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var o={},r=0;rn.parts.length&&(o.parts.length=n.parts.length)}else{var s=[];for(r=0;r0&&void 0!==arguments[0])||arguments[0];this.top=null,this.left=null,this.data=null,this.show=!1,e&&this.$emit("close")},onClick:function(){this.closeOnClick&&this.close(!1)},open:function(e,t){var n=this;this.data=t,this.show=!0,this.$nextTick(function(){n.positionMenu(e.clientY,e.clientX),n.$el.focus(),n.$emit("open",e,n.data,n.top,n.left)})},positionMenu:function(e,t){var n=window.innerHeight-this.$el.offsetHeight-25,o=window.innerWidth-this.$el.offsetWidth-25;e>n&&(e=n),t>o&&(t=o),this.top=e,this.left=t},removeScrollEventListener:function(){window.removeEventListener("scroll",this.close)}},watch:{closeOnScroll:function(e,t){e!==t&&(e?this.addScrollEventListener():this.removeScrollEventListener())}}}},function(e,t){e.exports={render:function(){var e=this.$createElement;return(this._self._c||e)("div",{directives:[{name:"show",rawName:"v-show",value:this.show,expression:"show"}],staticClass:"v-context",style:this.style,attrs:{tabindex:"-1"},on:{blur:this.close,click:this.onClick,"!contextmenu":function(e){e.preventDefault()}}},[this._t("default",null,{data:this.data})],2)},staticRenderFns:[]}}])});
\ No newline at end of file
diff --git a/src/vue-context.vue b/src/vue-context.vue
index daa7a4a..b30b268 100644
--- a/src/vue-context.vue
+++ b/src/vue-context.vue
@@ -45,7 +45,7 @@
return this.show
? { top: `${this.top}px`, left: `${this.left}px` }
: null;
- },
+ }
},
data () {
@@ -77,22 +77,28 @@
window.addEventListener('scroll', this.close);
},
- /**
- * Close the context menu.
- */
- close () {
- this.top = null;
- this.left = null;
- this.data = null;
- this.show = false;
- },
+ /**
+ * Close the context menu.
+ *
+ * @param {boolean|Event} emit Used to prevent event being emitted twice from when menu is clicked and closed
+ */
+ close (emit = true) {
+ this.top = null;
+ this.left = null;
+ this.data = null;
+ this.show = false;
+
+ if (emit) {
+ this.$emit('close');
+ }
+ },
/**
* Close the menu if `closeOnClick` is set to true.
*/
onClick () {
if (this.closeOnClick) {
- this.close();
+ this.close(false);
}
},
@@ -109,6 +115,8 @@
this.$nextTick(() => {
this.positionMenu(event.clientY, event.clientX);
this.$el.focus();
+
+ this.$emit('open', event, this.data, this.top, this.left);
});
},
@@ -200,4 +208,4 @@
}
}
}
-
\ No newline at end of file
+
diff --git a/test/index.html b/test/index.html
index aebc1a6..b367a66 100644
--- a/test/index.html
+++ b/test/index.html
@@ -10,7 +10,10 @@
Right click on me
-
+
- Option 1 {{ child.data && child.data.foo }}
- Option 2
@@ -20,4 +23,4 @@