jQuery-UI drop doesn't really drop anything in the droppable - jquery-ui

I notice in the jsfiddle here - http://jsfiddle.net/stevea/T4sGh/1/ - that when you drag and drop the red box onto the beige box, it looks like the red box goes inside the beige box, but in the HTML it actually becomes a sibling of the beige box and is just given offsets to place it over the beige box:
<body style="cursor: auto;">
<div id="box" class="ui-droppable"></div>
<div id="redBox" class="ui-draggable" style="position: relative; left: 89px; top: -213px;"></div>
</body>
This was unexpected. I don't recall any jQuery-UI documentation that talks about this.Does anyone have a feel what what is going on here and perhaps be able to point me to some documentation?
Thanks

The draggable and droppable do not change the DOM by default. If you want to do that you can utilize the events that they expose. Here's your fiddle updated. I am using the drop event in order to reposition the draggable inside your droppable container on drop:
var cell_dropOps = {
drop : box_drop,
accept : '#redBox',
drop: function (event, ui) {
$(this).append(ui.draggable);
ui.draggable.css({ top: 0, left: 0});
}
};

If you look at the example on this jQuery UI page, you'll notice that this is the default behavior.
If you wish to make dragable object a child of dropable object, you will have to append it manually in your drop function like:
$(this).append($(ui.helper[0]));
The whole purpose of mentioning accept : '#redBox' is that when you drop #redBox on your dropable div, the drop event gets fired.

Related

jQuery UI - Rotate, drag, resize DIV like in image editor

I need "user-friendly" rotate, drag and resizable DIV. But, when this DIV is rotated, RESIZE function works very wierd. Not like in image editor. User can not handle resize properly. How to make it ?
jsFiddle Example
HTML :
<div id="blue"></div>
CSS :
#blue {
top: 100px;
left: 100px;
width:200px;
height:200px;
background-color:blue;
-ms-transform: rotate(120deg); /* IE 9 */
-webkit-transform: rotate(120deg); /* Safari */
transform: rotate(120deg);
}
jQuery
$("#blue").resizable({
aspectRatio: false,
handles: 'ne, se, sw, nw'
});
$("#blue").draggable();
Worked on a similar Question: How to get four corners rotate handle for a rotatable div..?
In this, OP wanted to add rotation handles to each corner. But it's a good example of what you're reporting too.
Take a look at: https://jsfiddle.net/Twisty/7zc36sug/
HTML
<div class="box-wrapper">
<div class="box">
</div>
</div>
Wrapping the box helps out for Draggable.
jQuery
$(function() {
// Assign Draggable
$('.box-wrapper').draggable({
cancel: ".ui-rotatable-handle"
});
// Assign Rotatable
$('.box').resizable().rotatable();
});
Resizing when at a rotated angle changes the location of the box, it's width and height, and causes it to move in a sort of weird way. This is why it does not work like it might in some graphics programs.
Since you did not indicate what you would prefer the behaivor to be like, I cannot properly answer your question: User can not handle resize properly. How to make it?
I hope this helps explain the issue.

JQueryUI Draggable - Issues setting Containment [x1,x2] values

I am having trouble setting the containment value of the jqueryUI draggable function when using the [x1,y1,x2,y2] format. Here is the js:
<script type="text/javascript">
//slideTest.js
$(document).ready(function(){
$('.slideMin').each(function(){
$(this).draggable({
containment: [$(this).parent().offset().left,$(this).parent().offset().top,$(this).next('div').offset().left,$(this).parent().offset().top]
});
});
</script>
And the html which the script is interacting with:
<div class="slideBar">
<div class="slideMin"></div>
<div class="slideMax"></div>
</div>
I am trying to set the drag containment (of the slideMin div) based on the offset().left of the next div, in this case (slideMax).
In other words, I want the draggable behavior to stop (for the slideMin div) when it reaches the left of the next (slideMax) div.
The x1 seems to be working as the drag is stopping at the position defined, however, it is overlapping and extending beyond the next div, which i do not want to happen. There must be something wrong with how I am setting the x2 value but I am not sure what it is.
Any advice?
Figured it out... I had two divs, both draggable. The first div was to stop when it reached the next div. The above code accomplished this until I was to drag either div: once either div was dragged, the draggable range for the other div was not updating, therefore, I received the error where the draggable range was overlapping the other div. To fix it, I had to re-initiate and set the draggable range for the other div within the draggable function for the div that was being moved.
The new code goes something like this:
$(this).draggable({
containment: [$(this).position().left, $(this).position().top, $(this).next().position().left - $(this).width()+4, $(this).position().top],
drag: function(e){
$(this).next().draggable({
containment: [parseFloat($(this).position().left) + parseFloat($(this).width())-4, $(this).next().position().top, parseFloat($(this).parent().position().left) + parseFloat($(this).parent().width())-3, $(this).next().position().top]
});
}
});
$(this).draggable({
containment: [parseFloat($(this).prev().position().left) + parseFloat($(this).prev().width())-4, $(this).position().top, $(this).position().left, $(this).position().top],
drag: function(e){
$(this).prev().draggable({
containment: [$(this).parent().offset().left-$(this).prev().width()+5, $(this).prev().position().top, $(this).position().left - $(this).prev().width()+4, $(this).prev().position().top]
});
}
});
PS, the numbers -3 -4 +5, etc. were to add spacing for the handles on my draggable divs (4px handles), if you don't have handles you don't need the extra -3 -4 +5 portions of the code.

jQueryUI: Move sortable's element into droppable and back (or mootools alternative)

I have one sortable which contains tiles. In addition, I have a bunch of droppables. I want the following interaction:
The user can drag tiles out of the sortable onto some droppable. Ideally, this would move the tile out of the sortable and append it to the droppable. In addition, the droppable should not accept anything anymore, i.e. there may be at most one tile on one droppable. I tried it in this fiddle http://jsfiddle.net/yXeMw/2/ but can't get the "move" to work.
Once that works, the user should also be able to move the tile out of the droppable back to the sortable, which I tried out here: (removed link due to 2 links limit, was version 3 of that same fiddle.) but fails too. (I only tried with an alert as I think the "move from .. to .." part should be the same.) See update 1.
I've been trying this for a few days and just can't figure it out.
PS: I've read tons of similar questions here on SO, but none is really the same as my issue, i.e. moving the element from the sortable to the droppable.
Edit: I would welcome an alternative solution using Mootools aswell.
Update 1: The droppable -> sortable direction only didn't work because my tiles inside the sortable had the float: left attribute which effectively made the sortable itself be of size 0px thus impossible to hover. Fixed fiddle: http://jsfiddle.net/yXeMw/5/
Update 2: Although I found a workaround (see my answer), I would still like to have a solution which moves the element. I couldn't get any of appendTo or append to work.
So, I found out how to emulate it. I am not 100% satisfied with this solution because it doesn't really move the element, so I will accept any better solution.
Rather, I create a new element, remove the old one and hide the helper. Both clone and appendTo don't seem to work.
Here is the fiddle: http://jsfiddle.net/VyfkE/1/
Aswell as the code in case the fiddle will get lost.
html:
<div class="slot">Drop one here</div>
<div class="slot">Or one here</div>
<div class="sortable">
<div class="tile">item 1</div>
<div class="tile">item 2</div>
<div class="tile">item 3</div>
</div>
css:
.slot {
background-color: forestgreen;
width:100px;
height:100px;
border: 1px solid black;
}
.sortable {
display:table-row;
background: #44F;
}
.tile {
display:table-cell;
background: firebrick;
border: 1px solid black;
width: 50px;
height: 25px;
}
and finally the javascript:
$(".slot").droppable({
drop: function(ev, ui) {
// Only want one tile per droppable!
if ($(this).children().length === 0) {
// Create the new element which will be inside the droppable.
cl = $('<div>').addClass('tile').text(ui.draggable.text()).css({
background: 'cornflowerblue'
});
// Make it draggable back into the sortable.
cl.draggable({
connectToSortable: '.sortable',
helper: 'clone' // <-- This is important!
});
$(this).append(cl);
// And remove the element from the sortable.
ui.helper.hide();
ui.draggable.remove();
}
}
});
$(".sortable").sortable({
connectWith: '.slot',
revert: true,
helper: 'clone', // <-- This is important, again!
receive: function(ev, ui) {
// If we get some item from a droppable, remove it from there.
ui.item.remove();
}
});

message in empty <div> to drag

I am working on drag and drop tool using jQuery UI's sortable widget.
I'd like to add a message into an empty div where something can be dragged into, like: "drag here". I'd like to remove this message as soon as something is in that div. There will be times when the page loads with something already in that div, so it can't be only on action, but onload needs to check it too.
How do I go about it?
Here's my code:
$("#divFrom, #divTo").sortable({
connectWith: '.connectedSortable'
}).disableSelection();
You should be able to set up a draggable, and droppable and tap into droppable's drop event handler, which is fired when an item is dropped:
$("#target").droppable({
drop: function() {
// Empty the droppable div:
$(".message").remove();
}
});
Demo here: http://jsfiddle.net/andrewwhitaker/rUgJF/2/
As for doing something similar on load, if you provided your markup it would make providing a solution a little easier (is there a specific element inside the droppable div that you could check for?)
Hope that helps.

jQuery Draggable Handler inside IFrame

What a mouthful.
Basically I have a parent <div> and inside that an <iframe>. I need an element inside the iframe to be the handle to drag the parent div. Is this even possible?
I have tried:
$(node).draggable("option","handle",$('iframe',node).contents().find('#handle'));
$(node).draggable("option","handle",$('iframe',node).contents().find('#handle')[0]);
It is targeting the right DOM element but it just won't drag. It might be possible to overlay a hidden div ontop of the iframe but I have found the iframe takes the event over the div when position is absolute. Strange.
try this
$('#Div').draggable({ iframeFix: true });
this should work
I decided to take a stab at this and boy, it's a lot of work with little progress using an internal iframe node as a handle. Anyway, here are two solutions, the first one doesn't work really well, but if you can get it to work, it may be more desirable.
main.html (plagiarized from the demo)
<div id="draggable" class="ui-widget-content" style="position:relative;">
<p class="ui-widget-header">I can be dragged only by this handle</p>
<iframe name="iframe1" src="inner-handle.html" height=50 width=80></iframe>
</div>
inner-handle.html
<html>
<head>
<script type="text/javascript" src="../../jquery-1.4.2.js"></script>
</head>
<body>
<div id="innerHandle">handle</div>
</body>
</html>
JavaScript
$(function () {
var moveEvent;
$(document).mousemove(function (e) {
moveEvent = e;
});
$("#draggable").draggable();
$('iframe', '#draggable').load(function () {
$('iframe', '#draggable')[0].contentWindow.$('#innerHandle').mousedown(function (e) {
$('#draggable').draggable().data('draggable')._mouseDown(moveEvent);
return false;
});
});
});
It took me a while to find something that "worked." The problem here was that since the mousedown event occurred on an element inside the iframe, the mouse event is relative to the iframe, not the main document. The workaround is to have a move event on the document and grab the mouse position from there. The problem, once again, is that if the mouse is inside of the iframe, it is "not" moving according to the parent document. This means that the drag event only happens when the mouse reaches the edge of the iframe into the parent document.
A workaround for this might be to manually generate events with the calculated position of the iframe relative to its mouse movement. So when your mouse moves within the iframe, calculate its movement using the coordinate of the iframe to the parent document. This means that you need to use the event from the mousedown and not the mousemove,
$('iframe', '#draggable')[0].contentWindow.$('#innerHandle').mousedown(function (e) {
// do something with e
$('#draggable').draggable().data('draggable')._mouseDown(e);
return false;
});
The second solution is the way you have mentioned, have an absolute positioned div over the iframe itself. I have no trouble in getting the div to be on top of the iframe, that is,
<div id="draggable" class="ui-widget-content" style="position:relative;">
<p class="ui-widget-header">I can be dragged only by this handle</p>
<iframe name="iframe1" src="inner-handle.html" height=50 width=80></iframe>
<div style="position: absolute; height: 30px; width: 30px; background-color: black; z-index: 1000;"></div>
</div>
The problem with your div being behind the iframe might be because the z-index is off. If you declare your div before the iframe and you didn't specify the z-index, then the iframe will be on top.
Whichever way you choose, good luck!
what happens when you do this (with firebug activated):
var frameContent = $('iframe',node).contents()
var handle = frameContent.find('#handle');
console.debug(frameContent, handle)
Does handle contain a list of elements? And if so, look carefully at the Document object which is frameContent - is the URL "about:blank"? It's just a hunch, but if you get these outputs, it's probably executing the jQuery selector before the frame content has loaded (i.e., before the #handle element exists).
In which case, you can add an event to the IFRAME'd document, and communicate with the parent frame via window.parent.

Resources