I have a list of draggable items, and I wish to be able to drag them onto a sortable content block. Here’s my markup:
<div class='items'>
<div class="one">One</div>
<div class="two">Two</div>
</div>
<div class="content">
<div class="block">Foo</div>
<div class="block">Bar</div>
</div>
The thing is, that I want the dragged item to "become" a block as soon as the dragging starts and remain a block when it’s dropped. I have tried this:
$('.items div').draggable({
helper: function(e) {
return $('<div>').addClass('block').text( $(e.target).text() );
},
connectToSortable: ".content"
});
$('.content').sortable();
Fiddle: http://jsfiddle.net/MF4qu/
But even if I create a custom helper that looks like a block, it reverts back to the original dragged element as soon as it’s dropped. Does anyone know how to properly insert a block in my example page? I already looked through the UI API but I can’t figure it out.
When the draggable element is dropped into sortable, it triggers the sortable update event. One solution is to listen to that event, and turn the dropped item into a block:
$('.items div').draggable({
helper: function(e) {
return $('<div>').addClass('block').text( $(e.target).text() );
},
connectToSortable: ".content"
});
$('.content').sortable({
update: function (event, ui) {
ui.item.addClass('block');
}
});
Working demo: http://jsfiddle.net/DaXuT/1/
Related
Im using jquery-UI droppable, When I drag the small green box over the blue ones from top to bottom everything works as I want but when I drag the box from bot to top the parent box trigger the over event and gets highlighted, i want that just one element being highligthed at same time, one of the siblings or the parent.
HTML:
<div class="box">Drag me</div>
<div class="drop">Drophere
<div class="drop">Drophere</div>
<div class="drop">Drophere</div>
<div class="drop">Drophere</div>
</div>
JS:
$(".box").draggable();
$(".drop").droppable({
accept: ".box",
hoverClass: "drophere",
greedy:true
});
http://jsfiddle.net/Deivid11/44bg1bz4/4/
You can check on over event if a child .drop has class .drophere and if so, remove .drophere from the parent. Like this:
over: function (e, ui) {
$('.drop .drophere').parent().removeClass('drophere');
}
http://jsfiddle.net/p1wjk56h/1/
I am trying to drop an element on top of multiple droppable DIVs, but I have a problem with event bubbling. The droppable event gets executed multiple times, based on how many elements are layered on top of each other. I would like to execute it only for the last/top element.
Please see this jsFiddle.
HTML:
<div id="1" class="box droppable">1
<div id="2" class="box droppable">2
<div id="3" class="box droppable">3</div>
</div>
</div>
<div id="drag" class="draggable">Drag me! I dare you!</div>
<div id="output"></div>
jQuery:
$(function () {
$(".draggable").draggable({
revert: "invalid"
});
$(".droppable").droppable({
tolerance: 'pointer',
drop: function (event, ui) {
content = $('#output').html();
$('#output').html(content + "Dropped "+ui.draggable.prop('id') + " on " +$(this).attr('id')+".<br/>");
}
});
});
When you drop the draggable on element 1 it will say that you dropped it on 1. That's correct. If you drop it on element 3, it will say you dropped it on 1,2,3. I need to limit this only to the third/top-most element. How can I achieve this please?
I've experienced this in the past in a different situation, where it required a confirmation, so the droppable target ID could be stored in an invisible field (the last value), but I need to make it directly this time, no workarounds :(
Thanks!
If I only weren't so lazy to browse around the documentation for a bit. The solution to this problem can be found here. By specifying the greedy option user can limit the affected droppable elements.
In other words
$(".droppable").droppable({
tolerance: 'pointer',
greedy: true, //limit to only top-most droppable element
drop: function (event, ui) {
content = $('#output').html();
$('#output').html(content + "Dropped "+ui.draggable.prop('id') + " on " +$(this).attr('id')+".<br/>");
}
});
I want it to be possible to drag (draggables) several HTML elements into several other HTML elements. (droppables)
I found the jQuery UI draggable/droppable.
Currently, I define all li elements inside an ul as draggable. I also have three divs which accept all the draggable li elements.
<ul>
<li>foo</li>
<li>bar</li>
<li>baz</li>
</ul>
Defining them as draggable:
$('li').draggable({ revert: 'invalid' });
My droppable divs:
<div class="droppable" id="div1"></div>
<div class="droppable" id="div2"></div>
<div class="droppable" id="div3"></div>
Make the divs droppable:
$('div.droppable').droppable({ accept: 'li', drop: funcDrop, out: funcOut });
I now want that only one li element can be dropped into a div at the same time. I am trying to do that by disabling the droppability inside the div element I dropped the draggable, like so:
funcDrop = function(event, ui) {
$(this).droppable('disable');
}
This works. Now I am not able drop any further li elements into this div. The problem is, how/when to enable the div again? Clearly if the contianing draggable was removed. So I tried to enable the div inside funcOut:
funcOut= function(event, ui) {
strIdValue = event.target.id;
$('#' + strIdValue).droppable('enable');
}
But this does not work.
It seems also that I can't work with $(this) selector inside the funcOut.
Does anyone have a hint?
Best regards
I use jQuery 2.1 and UI 1.10.4
I figured out an alternative solution:
It seems if an element once was disabled, the out event does not fire and I am therefore not able to enable it again using the element itself. So what I did, is this:
If you drop a draggable element on a droppable element, the drop event is triggered and does this:
$(this).droppable({ accept: ('#' + $(ui.draggable).attr('id')) });
So the droppable is not disabled, but accepts only the received draggable by its unique HTML id. Because it is not disabled the out event will now be triggered. This is what I do in it:
$(this).droppable({ accept: 'li' });
Now the droppable accepts all HTML li elements as ever. Now each droppable accepts only one draggable. The droppable is now "locked" if it receives a draggable.
I wonder if this is a valid solution or just a dirty hack.
(Possible duplicate/related: jQuery UI - Droppable only accept one draggable)
Based on the JSFiddle you've shared (which currently is not doing what you asked), here is a modified version of the droppable function that you can use to achieve the desired result:
$(".droppable").droppable({
accept: "li",
drop: function(event, ui) {
$(this).droppable('option', 'accept', ui.draggable);
},
out: function(event, ui){
$(this).droppable('option', 'accept', 'li');
}
});
As the other answer stated, the trick is to make our droppable div accept 'ui.draggable', being ui the item that is currently being dragged to our droppable div.
Hope that helps!
(EDITED: Grammar)
I am using jQuery's draggable and droppable in order to drop content elements onto a page element:
<h2>Page</h2>
<div id='page-content'>
</div>
<div id='content-elements'>
<div id='text-element' class='content-element'>Text</div>
<div id='date-element' class='content-element'>Date</div>
</div>
My JS for the draggable looks like this:
$elements.draggable({
revert: true
});
The reason I have that revert in there is that I want the content element to return to the list of elements and a 'duplicate' to be added to the page.
I tried doing this using this js for the droppable (created using coffeescript):
$('#page-content').droppable({
drop: function(event, ui) {
var $element, $me;
$me = $(this);
$element = $(ui.draggable);
console.log($element.clone(false));
return $element.clone().appendTo($me);
}
});
What this does is get the ui element that was dragged, attempt to clone it and then append it to the page.
This however does not work! Even though I CAN get the div, etc from the ui.draggable.
I created a jsfiddle to illustrate the problem:
http://jsfiddle.net/sw4Gc/2/
Why oh why?
The element was cloned in a state where it is in position relative and is outside the element. you have to remove the element styles:
var $newElement = $element.clone();
$newElement.attr('style', '');
$newElement.appendTo($me);
I have a problem with jQuery UI and get some information of a dropped item.
I have three areas on the screen:
<div id="area1"></div>
<div id="area2"></div>
<div id="area3"></div>
In these areas, I put elements which are draggable with jQuery UI.
Now if an element is dropped from one to another area, I will not only get the area number in which the element is dropped to, I also want the area number where the element was dropped before the new drop.
I created a full working example: http://jsbin.com/iyaya3/
There is a blue draggable element and if I drag it from area1 to area2, I want to have the alert message with "dragged from area1 - dropped to area2".
How can this be done?
Best Regards, Tim-.
Hey, I updated your jsbin - http://jsbin.com/iyaya3/3
It works like this:
Take initial parent element's id and save it on draggable using jQuery.data
When dropping it on droppable, update data
I've got two ideas:
1) You can put a class or ID on the elements in each div:
<div id="area1"><node class="from1"></node></div>
<div id="area2"><node class="from2"></node></div>
<div id="area2"><node class="from2"></node></div>
And then test for that when you have the item
2) Write a function to do the clone instead of relying on the drag and drop to do it for you (http://ui-dev.jquery.com/demos/draggable/#option-helper) and then test for the parent and store that (in a singleton outside the scope of the dragger) where you can get it later.
I think I would prefer the first (even if you don't have html access to add these classes, just add it with javascript)
In your draggable setup, add this:
start: function(event,ui){
ui.helper.data('from-id', $(this).parent().attr('id') );
}
This will attach, as data, the ID of the container from which the element is being dragged.
Then, in the droppable, you can have:
alert( 'I was dragged from ' + ui.draggable.data('from-id') );
Here's the updated jsBin.
Edit: The start function creates a closure, so $(this).parent().attr('id') continues to point to the original parent. One solution to this problem (if you wish to keep a start function) is to clear start when the drag stops:
stop: function(event,ui){
ui.helper.draggable({ start: null });
}
This will allow the data methods in the droppable handlers to update the from-id without being immediately reverted to the original value by the start function.
Here's a revised jsBin example.
$(element.draggable).parent().attr('id')) works for me
I removed the duplicated code and solved the problem by saving the previous element id by the data() function.
JS Bin
<script type="text/javascript">
$(document).ready(function() {
$('#area1').append('<div class="shoulddraggable" style="width:100px;height:100px;top:0px;left:0px;background-color:blue;" data-elementid="100"></div>');
$(".shoulddraggable").draggable({
scroll: false,
revert: "invalid",
scope: "items",
});
$(".shoulddraggable").data('previousId', 'area1');
$('.droppable').droppable({
scope: "items",
drop: function(event, ui) {
alert('Previous container id: ' + ui.draggable.data('previousId'));
alert("Element: "+ui.draggable.data("elementid")+" dragged into" + $(this).attr('id'));
ui.draggable.data('previousId', $(this).attr('id'));
}
});
});
</script>
</body>
</html>