How to get element in jQueryUI draggable revert function? - javascript

I know that jQuery draggable can accept a function for revert action.
$(".clipboard-li").draggable({
revert: function (event) {
console.log(event) // boolean value
}
});
But the parameter being passed to this function is a boolean.
How can I get the the element currently being dragged in this function?

revert is an option where you can set
Whether the element should revert to its start position when dragging stops
If you want to get the element after you drag it somewhere use stop event
$(".clipboard-li").draggable({
revert: function(event) {
return $(this).hasClass("revert"); //You can set it either to true or false
},
stop: function( event, ui ) {
console.log($(event.target).attr("class"));
}
});
.clipboard-li {
cursor: move;
width: 150px;
height: 150px;
border: 1px solid #000;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
<div class="container">
<div class="clipboard-li">
</div>
<div class="clipboard-li revert">
</div>
<div class="clipboard-li">
</div>
</div>

The revert handler function runs under the scope of the element being dragged; it's not passed in as an argument. As such you can use the this keyword to reference the element:
$('.drag').draggable({
revert: function() {
return this.prop('id') != 'allow';
}
})
.drag {
width: 75px;
height: 75px;
background-color: #CCC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<div class="drag" id="allow">Allowed</div>
<div class="drag" id="deny">Denied</div>

Related

jQuery UI Sortable: Log origin and destination when dragging elements between columns

I need that, when moving Sortable elements between columns, the previous column and the column into which the element is being dragged, both get logged, and to be able to register this change.
As you can see I tried to send 'My parent has changed' to console whenever destination column's data-priority attribute doesnt match attribute of the original column, and to add updated class to the dragged element, but to no avail, so perhaps Im doing something wrong?
It seems the variable rootParent is set as both the original column data-priority attr, as well as the new column's, which is not what I want
$(document).ready(function() {
$('.quadrants').sortable({
connectWith: '.quadrants',
cursor: 'move',
dropOnEmpty: true,
update: function(e, ui) {
var rootParent = $(e.target).attr('data-priority');
console.log(rootParent);
$(this).children().each(function(index) {
if ($(this).parent().attr('data-priority') != rootParent) {
console.log('My parent has changed');
$(this).addClass('updated');
}
});
}
});
});
.quadrants {
background: #FFFFFF;
margin: 2px;
border-radius: 4px;
border: 1.5px solid #d4dce2;
min-height: 160px !important;
padding: 3px !important;
}
.quadrants>div {
font-family: sans-serif;
font-size: 1em;
padding: 10px;
margin: 5px !important;
background: #C1FFF8;
border-radius: 4px;
}
.updated{
background: #FFD2C1;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container row">
<div class="quadrants col-xs-3" data-priority="1">
<div>
Draggable
</div>
<div>
Draggable
</div>
</div>
<div class="quadrants col-xs-3" data-priority="2">
<div>
Draggable
</div>
</div>
<div class="quadrants col-xs-3" data-priority="3">
<div>
Draggable
</div>
</div>
</div>
I gave up on using Sortable by itself to get column attributes and used Droppable instead, in combination with Sortable to get a log of element ordering inside columns
$( ".quadrants" ).droppable({
accept: ".tasks",
drop: function( e, ui ) {
var draggedElement = ui.draggable;
var newColumn = [];
newColumn.push([draggedElement.attr('data-index'), $(e.target).attr('data-priority')]);
console.log(newColumn);
console.log('My parent changed');
}
});
$('.quadrants').sortable({
connectWith: '.quadrants',
cursor: 'move',
dropOnEmpty: true,
update: function(e, ui) {
$(this).children().each(function(index) {
if ($(this).parent().attr('data-priority') != index+1) {
$(this).attr('data-position', (index+1)).addClass('updated');
console.log('My position changed');
}
});
}
});

Removing certain elements from a selector binded to the body

I have a click event binded to the body element but I don't want it to fire for when the user clicks on certain elements, that being when the element has an attribute of data-dropdown-target, however what I have tried isn't working, it always fires.
CodePen: http://codepen.io/anon/pen/ORQkrb
HTML:
<body>
<div class="foo">foo</div>
<div class="bar" data-dropdown-target="something">bar</div>
<div class="moo">moo</div>
</body>
CSS:
.foo, .bar, .moo {
padding: 10px;
margin: 5px;
}
.foo {
background-color: gray;
}
.bar {
background-color: teal;
}
.moo {
background-color: green;
}
JS:
$('body').not('[data-dropdown-target]').on('click', function(e) {
console.log('Hi!');
});
I assume this is because it is trying to remove body elements that have this attribute, rather than it's children - correct?
How do I go about stopping it from firing on children elements that have this attribute - do I have to loop through everything, as I would like to avoid that because of performance reasons, especially since it's on the body.
Actually your code try to bind event click on every <body> without data-dropdown-target attribute.
This could solve your problem :
$('body').on('click', function(e) {
if($(e.target).data('dropdown-target') || $(e.target).parents('[data-dropdown-target]').length !== 0) return false;
console.log('Hi!');
});
.foo, .bar, .moo {
padding: 10px;
margin: 5px;
}
.foo {
background-color: gray;
}
.bar {
background-color: teal;
}
.moo {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="foo">foo</div>
<div class="bar" data-dropdown-target="something">bar</div>
<div data-dropdown-target="something">
<div class="moo">moo</div>
</div>
</body>
The not selector just remove the body element if it has [data-dropdown-target] attribute.
Remove elements from the set of matched elements.
$('body').on('click', function(e) {
console.log('Hi!');
});
$('[data-dropdown-target]').on('click',function(e){
return false;
});

Manipulate connections between elements dropped on canvas

Here I have been able to drop elements onto a canvas and create connections between them. But every time I drag a dropped element within the canvas, the anchors do not move along with the dragged element. Instead when I try to create a connection from the isolated anchor to another element it immediately re-positions itself with its parent element. This is one issue and I would also like to delete the anchors/ connections whenever its parent element is deleted.
<!doctype html>
<html>
<head>
<script src="../lib/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script src="../lib/jquery-ui.min.js"></script>
<script src="../lib/jquery.jsPlumb-1.6.4-min.js"></script>
<style>
.chevron-toolbox{
position: absolute;
width: 72px;
height: 80px;
background-color: powderblue;
background-image: url("../dist/img/bigdot.png");
border: solid 3px red;
}
#dropArea{
cursor: pointer;
border: solid 1px gray;
width: 800px;
margin-left: 80px;
height: 400px;
position: relative;
overflow-x: scroll;
overflow-y: scroll;
}
.chevron {
position:absolute;
cursor:pointer;
width: 72px;
height: 80px;
background-color: powderblue;
background-image: url("../dist/img/bigdot.png");
}
</style>
</head>
<body>
<div class="chevron-toolbox" id="cId">
</div>
<div id="dropArea">
</div>
<button id="go">Double Click Me</button>
<script>
jsPlumb.ready(function(e)
{
jsPlumb.setContainer($('#dropArea'));
$(".chevron-toolbox").draggable
({
helper : 'clone',
cursor : 'pointer',
tolerance : 'fit',
revert : true
});
$("#dropArea").droppable
({
accept : '.chevron-toolbox',
containment : 'dropArea',
drop : function (e, ui) {
droppedElement = ui.helper.clone();
ui.helper.remove();
$(droppedElement).removeAttr("class");
jsPlumb.repaint(ui.helper);
$(droppedElement).addClass("chevron");
$(droppedElement).draggable({containment: "dropArea"});
$(droppedElement).appendTo('#dropArea');
setId(droppedElement);
var droppedId = $(droppedElement).attr('id');
var common = {
isSource:true,
isTarget:true,
connector: ["Flowchart"],
};
jsPlumb.addEndpoint(droppedId, {
anchors:["Right"]
}, common);
jsPlumb.addEndpoint(droppedId, {
anchors:["Left"]
}, common);
alert(droppedId);
//Delete an element on double click
var dataToPass = {msg: "Confirm deletion of Item"};
$(droppedElement).dblclick(dataToPass, function(event) {
alert(event.data.msg);
$(this).remove();
});
}
});
//Set a unique ID for each dropped Element
var indexer = 0;
function setId(element){
indexer++;
element.attr("id",indexer);
}
});
</script>
</body>
</html>
In order to properly manipulate the connections, you can use the connect method in jsPlumb placing anchors at desired points.
jsPlumb.connect({
source:'window2',
target:'window3',
paintStyle:{lineWidth:8, strokeStyle:'rgb(189,11,11 )'},
anchors:["Bottom", "Top"],
endpoint:"Rectangle"
});
This is merely an example. Following this pattern in your implementation will be useful when it comes to accessing details regarding those connections and deleting the connections alongside the elements

Using ESC event to cancel Drag and Drop

I am looking for a way to allow a user to cancel a mouse drag operation by pressing the ESC key.
Can this be done using Javascript?
Thank you
Update
When the mouse is dragging a div element over a droppable area, pressing the ESC key should drag the element to an area that is not droppable. Once the element is dragged to a non-droppable area, I invoke a "mouseup" event on the dragged element, which causes the dragged element to be dropped onto a non-droppable area.
How can I do this using jQuery Draggable and jQuery Droppable?
When the mouse is dragging a div element over a droppable area, pressing the ESC key should drag the element to an area that is not droppable
I´ve created a demo of a possible solution that you can check in plunker.
As stated by #ioneyed, you can select the dragged element directly using the selector .ui-draggable-dragging, which should be more efficient if you have lots of draggable elements.
The code used is the following, however, apparently it's not working in the snippet section. Use the fullscreen feature on the plunker or reproduce it locally.
var CANCELLED_CLASS = 'cancelled';
$(function() {
$(".draggable").draggable({
revert: function() {
// if element has the flag, remove the flag and revert the drop
if (this.hasClass(CANCELLED_CLASS)) {
this.removeClass(CANCELLED_CLASS);
return true;
}
return false;
}
});
$("#droppable").droppable();
});
function cancelDrag(e) {
if (e.keyCode != 27) return; // ESC = 27
$('.draggable') // get all draggable elements
.filter('.ui-draggable-dragging') // filter to remove the ones not being dragged
.addClass(CANCELLED_CLASS) // flag the element for a revert
.trigger('mouseup'); // trigger the mouseup to emulate the drop & force the revert
}
$(document).on('keyup', cancelDrag);
.draggable {
padding: 10px;
margin: 10px;
display: inline-block;
}
#droppable {
padding: 25px;
margin: 10px;
display: inline-block;
}
<div id="droppable" class="ui-widget-header">
<p>droppable</p>
</div>
<div class="ui-widget-content draggable">
<p>draggable</p>
</div>
<div class="ui-widget-content draggable">
<p>draggable</p>
</div>
<div class="ui-widget-content draggable">
<p>draggable</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.css">
I tried to help but without the expected result...
Searching on google you can find that while dragging other events are locked, similar behaviour to what happens during a window.alert...
By the way, I am on a Mac and I can capture all keyboard events but not "controls key such as command, ctrl, esc, ecc."
Hope help you as a starter point!
function DragAndDropCtrl($) {
var self = this;
self.ESC = 27;
self.draggables = $('.draggable');
self.dropArea = $('#droppable');
self.currentDraggingElement = null;
self.currentDismissed = false;
self.dismissDragging = function(event, eventManager) {
self.currentDismissed = true;
//Using the manager you can't use the revert function OMG!
//return eventManager.cancel();
};
self.dropArea.droppable();
self.draggables.draggable({
revert: function() {
var revert = self.currentDismissed;
self.currentDismissed = false;
console.log(revert, self.currentDismissed)
return revert;
},
start: function() {
self.currentDraggingElement = $(this);
},
end: function() {
self.currentDraggingElement = null;
}
});
$(document).keypress(function(event) {
console.log('key pressed', event)
//How to intercept the esc keypress?
self.dismissDragging(event, $.ui.ddmanager.current);
if(event.which === self.ESC || event.keyCode === self.ESC) {
self.dismissDragging(event, $.ui.ddmanager.current);
}
});
}
jQuery(document).ready(DragAndDropCtrl);
#droppable {
border: 1px solid #ddd;
background: lightseagreen;
text-align: center;
line-height: 200px;
margin: 1em .3em;
}
.draggable {
border: 1px solid #ddd;
display: inline-block;
width: 100%;
margin: .5em 0;
padding: 1em 2em;
cursor: move;
}
.sidebar { width: 30%; float: left; }
.main { width: 70%; float: right; }
* { box-sizing: border-box; }
<div class="sidebar">
<div class="ui-widget-content draggable">
<p>draggable</p>
</div>
<div class="ui-widget-content draggable">
<p>draggable</p>
</div>
<div class="ui-widget-content draggable">
<p>draggable</p>
</div>
</div>
<div class="main">
<div id="droppable" class="ui-widget-header">
<p>droppable</p>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.css">

How to set a result if draggable is dropped in droppable in Jquery?

I am trying to increase the value of a counter (var counter = 0;), if the draggable image on screen is dropped into the dropzone (also a image, not a div).
$( "#goldbag" ).draggable({ revert: "invalid", containment: "parent" });
$( "#jack2" ).droppable({
drop: function(event, ui) {
draggedObj = ui.draggable.attr('id');
$("#"+draggedObj).fadeOut(function() { $(this).remove(); });
$( "img" ).draggable({ disabled: true });
}
});
This code just fades out the droppable after its dropped on the image. Before/after it fades out I want to increment the counter by 1.
Note: Both #goldbag and #jack2 are images (<img>) inside a single container div.
You can just extend your drop callback function.
Here is an over simplified example, where you can drag and drop the same item multiple times while increasing a counter.
Most of this code was taken from the docs here: https://jqueryui.com/droppable/#default
$(function() {
var $counter = $("#counter");
var count = 0;
$("#draggable").draggable();
$("#droppable").droppable({
drop: function(event, ui) {
$(this)
.addClass("ui-state-highlight")
.find("p")
.html("Dropped!");
count++;
$counter.html(count);
}
});
});
#draggable {
width: 100px;
height: 100px;
padding: 0.5em;
float: left;
margin: 10px 10px 10px 0;
}
#droppable {
width: 150px;
height: 150px;
padding: 0.5em;
float: left;
margin: 10px;
}
<link href="http://code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
<div id="draggable" class="ui-widget-content">
<p>Drag me to my target</p>
</div>
<div id="droppable" class="ui-widget-header">
<p>Drop here</p>
</div>
<p>Counter: <span id="counter">0</span>
</p>

Categories