Vue - Dragenter/Dragover Bubbling

Demo to show how event bubbles up element tree. Note visual stack. Also shows difference of event.target and event.currentTarget

by Ben Clayton

HTML

<script src="https://unpkg.com/vue"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.16.0/vuedraggable.min.js"></script>
<div id="preview">
  <div id="outer" class="outer" @dragover.stop="dragover($event,'outer')">
    Outer


    <div id="inner" class="inner" @dragover.stop="dragover($event,'inner')">
      Inner
      <div id="subinner" class="subinner">
        sub Inner
      </div>
    </div>
    
     <div id="outerchild" class="outerchild">
        outer child
      </div>

  </div>


  <div class="dragme" draggable=true>
    Drag Me
  </div>

  <div class="status">
    <table cellpadding=0 cellspacing=0>
      <tr>
        <td width=200>element where handler is:</td>
        <td>{{status1}}</td>
      </tr>
      <tr>
        <td>event currentTarget:</td>
        <td> {{status2}}</td>
      </tr>
      <tr>
        <td>event target:</td>
        <td> {{status3}}</td>
      </tr>
      <tr>
        <td>event count:</td>
        <td>{{count}}</td>
      </tr>
     </table>
  </div>


</div>

CSS

.outer {

  display: block;
  position: relative;
  width: 400px;
  height: 200px;
  background-color: rgba(100, 100, 100, 0.3);
  margin: 20px;

}

.inner {

  display: block;
  position: absolute;
  width: 200px;
  height: 150px;
  background-color: rgba(200, 100, 100, 0.3);
  left: 20px;

}

.subinner {

  display: block;
  position: absolute;
  width: 200px;
  height: 100px;
  background-color: rgba(100, 200, 100, 0.5);
  left: 130px;

}
.outerchild {

  display: block;
  position: absolute;
  width: 100px;
  height: 60px;
  background-color: rgba(100, 200, 200, 0.5);
  top:50px;
  left: 30px;

}

.dragme {

  display: block;
  width: 70px;
  height: 30px;
  background-color: rgba(100, 100, 200, 0.3);
  margin: 20px;
  text-align: center;
}

.status {

  display: block;
  position: fixed;
  width: 400px;
  height: 100px;
  background-color: rgba(100, 100, 100, 0.3);
  left: 10px;
  bottom: 10px;
  padding: 10px;

}

tr, td {
  height:10px;
  padding:0;
}

JavaScript

var mainView = new Vue({
  el: '#preview',
  data: {
    status1: ">",
    status2: ">",
    status3: ">",
    count: 0
  },
  methods: {

    dragover: function(ev,who) {
      this.status1 = who ;
      this.status2 = ev.currentTarget.id ;
      this.status3 = ev.target.id ;
      this.count++
    }
  },
  computed: {
    options: function() {
      return global.options1
    }
  }
});