Code Monkey home page Code Monkey logo

draggable-vue-directive's Introduction

draggable-vue-directive

GitHub open issues npm download npm download per month npm version Package Quality vue2 MIT License

Vue directive (Vue.js 2.x) for handling element drag & drop.

Installation

npm install draggable-vue-directive --save

Demo

demo gif

You can view the live demo here: https://israelzablianov.github.io/draggable-demo

Examples

Without Handler

<div v-draggable>
    classic draggable
</div>

.vue file:

  import { Draggable } from 'draggable-vue-directive'
  ...
  export default {
        directives: {
            Draggable,
        },
  ...

With Handler

<div v-draggable="draggableValue">
    <div :ref="handleId">
        <img src="../assets/move.svg" alt="move">
    </div>
    drag and drop using handler
</div>

.vue file:

  import { Draggable } from 'draggable-vue-directive'
  ...
  export default {
        directives: {
            Draggable,
        },
        data() {
            return {
                handleId: "handle-id",
                draggableValue: {
                    handle: undefined
                }
            };
        },
        mounted() {
            this.draggableValue.handle = this.$refs[this.handleId];
        }
  ...

draggable Value

The object passed to the directive is called the directive’s value.
For example, in v-draggable="draggableValue", draggableValue can be an object containing the folowing fields:

handle

Type: HtmlElement | Vue
Required: false

There are two ways to use the draggable directive, as shown in the demo above.

  1. The simple use. Just to put the directive on any Vue component or HTML element, and…boom! The element is draggable.
  2. Using a handler. If you choose to use a handler, the component itself will only be draggable using the handler.

onPositionChange

Type: Function
Required: false

Sometimes you need to know the element’s coordinates while it’s being dragged.
Passing a callback to draggableValue will achieve this goal; while dragging the element, the callback will be executed with 3 params:

  • positionDiff
  • absolutePosition (the current position; the first time the directive is added to the DOM or being initialized, the value will be undefined, unless the element has left and top values)
  • event (the event object)
  import { Draggable } from 'draggable-vue-directive'
  ...
  export default {
        directives: {
            Draggable,
        },
        data() {
            return {
                draggableValue: {
                    onPositionChange: this.onPosChanged
                }
            };
        },
        methods: {
            onPosChanged: function(positionDiff, absolutePosition, event) {
                console.log("left corner", absolutePosition.left);
                console.log("top corner", absolutePosition.top);
            }
        }
  ...

onDragEnd

Type: Function
Required: false

Emits only when dragging ends. Has the same functionality as onPositionChange.

onDragStart

Type: Function
Required: false

Emits only when dragging starts. Has the same functionality as onPositionChange.

resetInitialPos

Type: Boolean
Required: false
default: undefined

Returns to the initial position of the element, before it is mounted.

initialPosition

Type: Position
Required: false
default: undefined

Sets the absolute starting position of this element.
Will be applied when resetInitialPos is true.

stopDragging

Type: Boolean
Required: false
default: undefined

Immediately stop dragging.

boundingRect

Type: ClientRect
Required: false
default: undefined

Constrains dragging to within the bounds of the rectangle.

boundingElement

Type: HtmlElement
Required: false
default: undefined

Constrains dragging to within the bounds of the element.

boundingRectMargin

Type: MarginOptions
Required: false
default: undefined

When using boundingRect or boundingElement, you can pass an object with top, left, bottom, and right properties, to define a margin between the elements and the boundaries.

draggable-vue-directive's People

Contributors

cavanmflynn avatar deckele avatar gobeli avatar israelzablianov avatar safrmo avatar tpaksu avatar zearin 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

draggable-vue-directive's Issues

draggable instance in events

Hello,

IMHO it would be better to give the dragged instance reference out in event parameters instead of finding out with event.target parents. What do you think?

Possibility to set position programmatically

Hi!

sometimes I need to set the position programmatically, for example if the window is resized and the draggable element is left out of it.
I do it modifying the position of element manually and accessing the draggable-state via getAttribute to change the startDragPosition and currentDragPosition, but it's tricky

Now is possible? If not, is a possible future feature?

Thank!

Doesn't seem to set initial pos correctly

I have a scenario where I have a few tabs and each will show different things to drag, and each one of those objects has a position property which is updated (and synced back up to main object) when the position changed event is raised. This information is pumped out to the console so I can see the x/y is correct and being updated.

Now the problem occurs when I swap tabs (i.e current elements vanish and new are put on) and I return to the previous tab where I moved things around, they are just shown at 0,0 even though they have a position property with values different to 0,0, this is with initialPosition being set too.

So just to be clear code looks like:

 public draggableOptions = {
	handle: this.$refs.headerElement,
	onPositionChange: this.updatePosition,
	initialPosition: this.node.position
};

public updatePosition(newPosition) {
	this.$emit("update:position", newPosition); // parent assigns this to this.node.position
}

Then when I go to drag the elements shown at 0,0 they they pop back to where they were, so it looks like its a case of when the elements come back on the position is only updated when I start to drag, but I was expecting that the position would just automatically be set when the directive is applied.

Anyway feel free to say this is as per designed and I need to seed the position manually myself, but I just wanted to raise it.

Issue with Safari and Dragging

On Safari on MacOS, doing a simple drag and drop sample doesn't seem to function correctly.

Clicking and dragging on a draggable div does not initiate a correct drag. On drag start, a copy of the div is under the mouse - the original div is still in the same place. On mouse up, the div snaps back to the start, but moving the mouse will show another image of the div under the cursor. Clicking will "drop" it.

.vue file:

<template>
  <div class="main">
    <img alt="Vue logo" src="../assets/logo.png">
    <!-- <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/> -->
    <div class="draggable-container" v-draggable>Drag Me</div>

    <div class="draggable-with-handler" v-draggable="draggableWithHandler">Use Handler To Drag Me
      <div class="handler" ref="handler">I am Handler</div>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
import { Draggable, DraggableValue } from 'draggable-vue-directive';

@Component({
  components: {
    HelloWorld,
  },

  directives: {
    Draggable,
  },

})
export default class Home extends Vue {

  private draggableWithHandler: DraggableValue = { handle: undefined };

  public mounted() {
    this.draggableWithHandler.handle = this.$refs.handler as HTMLElement;
  }
}
</script>

<style >
.main {
  display: flex;
  justify-content: space-around;
  height: 100%;
  width: 100%;
}
.control-group {
  display: flex;
  flex-direction: column;
  margin-top: 25px;
}
.control-btn {
  border-radius: 3px;
  background-color: #42b883;
  color: #35495e;
  cursor: pointer;
  padding: 15px;
  margin: 15px;
}
.draggable-container {
  width: 150px;
  height: 150px;
  background: white;
  border: 3px solid #42b883;
  border-radius: 3px;
  text-align: center;
  font-size: 25px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.container-for-draggable {
  background: white;
  border: 3px solid #42b883;
  border-radius: 3px;
  text-align: center;
  font-size: 25px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  align-self: flex-end;
  width: 300px;
  height: 200px;
  bottom: 20px;
}
.draggable-with-handler {
  background: white;
  border: 3px solid #42b883;
  border-radius: 3px;
  text-align: center;
  font-size: 25px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  align-self: flex-end;
  width: 300px;
  height: 200px;
  bottom: 20px;
  left: 20px;
}
.handler {
  padding: 5px;
  position: absolute;
  top: 0;
  left: 70px;
  margin-top: -45px;
  background: white;
  border: 3px solid #42b883;
  border-radius: 3px;
  text-align: center;
  font-size: 25px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.draggable-with-reset {
  background: white;
  border: 3px solid #42b883;
  border-radius: 3px;
  text-align: center;
  font-size: 25px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  align-self: flex-end;
  width: 300px;
  height: 200px;
  bottom: 20px;
  right: 20px;
}
.autor {
  align-self: flex-start;
  margin-top: 25px;
  margin-bottom: 20px;
  padding: 10px;
  border-radius: 3px;
  color: #42b883;
  background-color: #35495e;
  font-size: 25px;
  font-weight: bolder;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
</style>

package.json:

{
  "name": "vue-test",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "draggable-vue-directive": "^2.0.6",
    "vue": "^2.5.22",
    "vue-class-component": "^6.0.0",
    "vue-property-decorator": "^7.0.0",
    "vue-router": "^3.0.1"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.3.0",
    "@vue/cli-plugin-typescript": "^3.3.0",
    "@vue/cli-service": "^3.3.0",
    "typescript": "^3.0.0",
    "vue-template-compiler": "^2.5.22"
  }
}

screenrecording20190114at1

setting resetInitialPos does not work // or I don't understand

I want a thing to return to its initial Position, as long as it has not been dragged out of a certain boundry/ threshold. ..but first things first, I want to have it always return, so I do this in my .vue:

  ...
  <div v-draggable="draggableValue">
    test
  </div>
  ...
  import { Draggable } from 'draggable-vue-directive'
  ...
  export default {
        directives: {
            Draggable,
        },
        data() {
            return {
                draggableValue: {
                    resetInitialPos: true
                };
            }
        }

but that doesn't do a thing.

What am I missing here or is it a bug?

regards

Problem with openstreetmap

I want to put draggable menu on top of an openstreetmap. But the problem is when i move my menu, my map move too. Do you a solution for only moving the menu ?
There a my code :

<template>
  <div id="mapContainer">
    <div class="menu">
      <div v-draggable="draggableValue">
        <div :ref="handleId">
          <img src="../assets/arrows.png" alt="move" />
        </div>drag and drop using handler
      </div>
    </div>
  </div>
</template>

<script>
import L from "leaflet";
import { Draggable } from "draggable-vue-directive";

export default {
  name: "test",
  data() {
    return {
      map: null,
      handleId: "handle-id",
      draggableValue: {
        handle: undefined
      }
    };
  },
  directives: {
    Draggable
  },
  mounted() {
    this.draggableValue.handle = this.$refs[this.handleId];

    this.map = L.map("mapContainer").setView([51.959, -8.623], 12);

    var osmLayer = L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
      attribution: "© OpenStreetMap contributors",
      maxZoom: 19
    });

    var satellite = L.tileLayer(
      "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
      {
        attribution:
          "Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"
      }
    );

    this.map.addLayer(osmLayer);

    this.map.addControl(
      new L.Control.Layers(
        {
          "vue plan": osmLayer,
          "vue satellite": satellite
        },
        {}
      )
    );
  }
};
</script>

<style scoped>
#mapContainer {
  margin-top: 40px;
  width: 99vw;
  height: 93vh;
  z-index: 1;
}

.menu {
  position: absolute;
  z-index: 700;
}
</style>

draggble not working with modals

my draggable component has a modal attached to it which is triggered when the button is pressed that is present in the component itself....the component is indeed draggable but my screen becomes unresponsive when I open a modal
screenshot 2

Not working on element created dynamically

Hi, I'm trying to attach the directive to a dynamically created rect but is not working
I'm trying this inside a method:

var xmlns = "http://www.w3.org/2000/svg"; var stage = document.createElementNS(xmlns, "rect"); stage.setAttributeNS(null, 'v-draggable', ''); stage.setAttributeNS(null, 'width', 350); stage.setAttributeNS(null, 'height', 80); stage.style.cssText = 'fill:#f2f2f2;stroke-width:1;stroke:rgb(0,0,0)'; console.log(stage) document.getElementById('canvas').appendChild(stage)

Error in directive draggable bind hook: "ReferenceError: 'TouchEvent' is undefined"

I've been using your draggable directive on a reporting page and really appreciate how easy it is to use. Unfortunately, most of our users are still using IE 11 (I know, I know...). Just noticed that your directive raises this error in IE 11 on page load:

Error in directive draggable bind hook: "ReferenceError: 'TouchEvent' is undefined"

The good news is that it doesn't seem to be a breaking error. The elements that use your directive are still draggable with no issues. But you might want to see if there's a way to gracefully prevent that error. Thanks!

Prevent element from being dragged out of current viewport

The feature dragging within the bounds of a parent element is excellent. But I wonder is there any way to upgrade it so that it can prevent the element from dragging outside the viewport? Thanks in advance.

For now, I'm using getboundingClientRect to detect and then set the initial position.

2020-05-23_19-14

May you add an important reminder to document for resetInitialPos?

I had same problem with #22 .

resetInitialPos
Returns to the initial position of the element, before it is mounted.

I only need to initialize the position at the beginning.
And I thought it only works at the beginning until I update my component...

May you add a reminder to the document ?
It should make it unnecessary to waste time debugging code

draggable with handler doesn't work

Hi,

I am using the code from the example (Draggable with handler) but it doesn't work..

the whole div is stil draggable.. the handler seems to be not recognized.

pls help :)

Are you can add event onEndDrag?

Hi
Actually I need used both of events: onPositionChange & onEndDrag
Without onEndDrag I cant normally place other element, that dependenced from it

Prevent clink while dragging the element

Hi. Thanks for this plugin. It speeds up my prototyping. 🙂

One enhancement that I could see is that preventing the click event while dragging the element. I bind a click event for my element which is draggable. When I release the cursor after dragging, the click event gets triggered. Is there any way I can suppress this click event on drag release?

boundingRect?

Is this the correct way to use this?

data () { return { handleId:"handle-id", draggableValue: { bottom:713.234375, height:48.25, left:0, right:1920, top:664.984375, width:1920, x:0, y:664.984375 } } },

I can't select the content of the element dragged

I can't select the content of the element dragged

The issue is that , when I dragging the element , I want to copy some words of the element, but the fact is that the whole element is dragging , so, how can I copy the content of the element.

Bug with input[type===number]

When number input's one of increase/decrease arrow buttons is clicked, it is increasing/decreasing continuously until another click event is fired. It occurs with this draggable package. When package is removed everything works fine. Any idea is appreciated)

Screen.Recording.2024-01-19.at.14.48.33.mov

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.