v-click-outside Vue directive

detect a click outside of an element

by Hugo Carneiro

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/0.7.10/vue-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.1.2/foundation.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.2/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.18/vue.js"></script>
<div id="app">
  <div class="callout" >
    <button @click.stop="show" class="button secondary">Click me</button>
    
    <div class="callout" v-if="showInside" v-click-outside="closeEvent">
      
      <p>This is the Inside. You can click inside of here and nothing happens. You close with the button below, or by clicking outside the box.</p>
      
      <p>If you click outside of this box, the event defined via the <i>v-click-outside</i> directive will be emitted.</p>
      
      <p>Caveat: The Event that makes this box show ("Click me") has to use the .stop modifier, otherwise the event set up by <i>v-click-outside</i> will catch it, and $emit the custom event prematurely </p>
      
      <button class="button" @click="hide">Close</button>
    
    </div>
    
  </div>
</div>

Babel + JSX

Vue.directive('click-outside', {
  priority: 700,
  bind () {
    let self  = this
    this.event = function (event) { 
    	console.log('emitting event')
    	self.vm.$emit(self.expression,event) 
 	  }
    this.el.addEventListener('click', this.stopProp)
    document.body.addEventListener('click',this.event)
  },
  
  unbind() {
  	console.log('unbind')
    this.el.removeEventListener('click', this.stopProp)
    document.body.removeEventListener('click',this.event)
  },
  stopProp(event) {event.stopPropagation() }
})

var App = new Vue({
  el: '#app',
  data() {
    return {
			showInside: false
    }
  },
  methods:{
    show: function () {
    	this.showInside = true 
    },
    hide: function () { 
    	console.log('hide')
    	this.showInside = false
    }
  }
})