I'm making an activity that requires certain letters to be put in certain places to complete words.
Here's a screenshot:
The Activity I'm Working On
(linking it because it's too big)
The two small wooden boards at the bottom contain the letters that should be dragged to the blank boxes on the bigger wooden boards. The problem is that every time I try to drag the letters into the blank spaces, it does this:
And if I don't drag it to that certain spot (for example, I want to place it exactly at the center of the red box), it reverts to its original position as if I never dropped it in a droppable.
Is this a bug? Is there a workaround?
Here's the script:
$(".drag").draggable({ revert: 'invalid' });
/*======================================================*/
$( "#dropArea1A" ).droppable({
accept: '.drag',
drop: function( event, ui) {
console.log(ui.draggable.attr('class'));
console.log(answers);
console.log(correct);
if(ui.draggable.hasClass('letterH')){ choice1 = 'correct'; $('#dropArea1A').addClass('correct') }
$(".drag").css('cursor', 'default');
$(".drag").append(ui.draggable.css('margin','0'));
$(".draggable").draggable({ disabled: false });
$(this).append(ui.draggable.css('position','static'));
$(this).droppable( 'disable' );
},
});
And some additional info that might be useful: I used position: absolute a lot in the stylesheet to get the droppable divs into the correct position. The wooden boards (and the static letter boxes) are background images. Would this be the culprit?
After some chat room traversing and playing around with jsfiddle, I found that droppable areas have problems with the css margin property, not position: absolute. What happens is, if you set a margin-top or a margin-left or any other value for the margin property, only the element will move -- the drop area will not.
I hope this helps someone!
This issue was reported four years ago here: http://bugs.jqueryui.com/ticket/6876
It was recently fixed in jquery-ui 1.11.2
Related
Further to the question here, I realized using li won't work best for me & hence upon further research & following the example here, I've manged to implement a customized version of draggable div.In the example (quoted in the answer of the question mentioned above), moving the scroll bar of the chart doesn't move the chart. However, implementing the charting by making the div that contains the chart draggable according to (link), trying to scroll the scroll bar movs the div & with it the chart.
In (link), I've commented out the code inside the sortable function as I don't need it which makes it look as below
$(function () {
$(".grid").sortable({
/*tolerance: 'pointer',
revert: 'invalid',
placeholder: 'span2 well placeholder tile',
forceHelperSize: true*/
});
});
In addition, to make the chart not to move when scrolled, I tried adding the below code
$(function () {
$(".grid").sortable({
/*tolerance: 'pointer',
revert: 'invalid',
placeholder: 'span2 well placeholder tile',
forceHelperSize: true*/
cancel: ".amcharts-main-div"
});
});
$(". grid" ).disableSelection();
However, adding the "cancel" & disableSelection() makes the chart immovable.
This is tricky situation. Could I request some guidance on clubbing these two functionalities namely making the div draggable & also when the chart's scroll bar is moved the chart shouldn't move please?
This is pretty simple. The only thing you have to do is replacing the <li> tags with divs.
To keep it running correctly you need to modify the css selector #sortable li to #sortable > div, so it will only apply to the first level children divs and hence not mess up the AmCharts internal divs.
Heres the modified demo.
What is the best way to check if element is above another one?
I have container with a lot of children with absolute position, and each of the children is draggable with jQuery-ui draggable..
I need to check in the drag stop if the dragged element is dropped above another one.
I know I could take the element center and iterate all the other elements and check if it is in their area, but I'm looking for more elegant way to check this.
Check this fiddle please: http://jsfiddle.net/g36gLss9/1/
$(function() {
$( ".draggable" ).draggable({
stop: function( event, ui ) {
$( ".draggable" ).each(function(obj){
$(this).html( 'z-index: ' + $(this).css("z-index"));
});
},
drag: function( ) {
$(this).html( 'z-index while dragging: ' + $(this).css("z-index"));
}
});
});
As the example demonstrates, the draggable feature from jquery ui leaves the z-index value of the dragged elements untouched.
therefore you can assume that an element appearing after another draggable item would be positioned above said item.
That might not be true though, in case you set z-index manually before. Bu the example also states how to retrieve the z-index of a draggable item. So to be on the safe side you could compae values for z-index first. and in case of equality compare the order of appearance in the code.
Also you can hande the z-index of draggable items with the zIndex option documented here: http://api.jqueryui.com/draggable/#option-zIndex
check out this fiddle in IE:
http://jsfiddle.net/GA4Qs/108/
notice the style style="position:relative;clear:both;max-height:100px;overflow:auto;"
basically, I want it so that when you scroll and drag down to the bottom of the scrollable div, it will scroll accordingly. The problem is in IE, you will be able to drag the item to the bottom such that it will scroll infinitely
Is there a way to prevent that from happening in IE so that it will stop at the bottom when dragging the sortable item down instead of having it scroll infinitely?
I don't know much on this subject but you can use the containment option that JQuery has on its movable objects Like so:
$('#psP').sortable({
placeholder: "ui-state-highlight",
helper:'clone',
containment: "parent"
});
Also remove Overflow:auto;
here is your updated jsFiddle.
NOTE: you will need to fiddle around with the sizes of things as with the fiddle i gave you it doesn't allow you to drop into the sortable area. this is due to the containment area and the sizes of your DIV's. It shouldn't be to hard to figure out.
I Hope this is what you were looking for.
$(".sortable_portlets").sortable({
connectWith: ".portlet-drag",
revert: 'true',
items: ".sortable_portlets",
containment: "document",
axis :'x',
scroll: false,
});
the containment option will limit your scrolling. there are other ways as well.you may set axis to restrict this.
use Overflow :hidden ,containment :'parent' and also if needed restrict with axis : 'x' or 'y' as needed.
I have a small problem which i can't seem to solve myself.
Look at this fiddle:JSfiddle
This is a basic example of the problem I have.
I have a large div which is a droppable area. Inside this droppable area are multiple other droppable areas.
The inner droppable area should walk trough its code when the element is dropped. Instead the code from the outer div seems to run.
Am i doing something wrong? The area around the divs should stay this way because elements can be placed here (not officially dropped).
I hope my question is clear enough, but I think the fiddler speaks for itself.
P.S. - resizing in this example isn't functioning but is functioning in my development environment.
Rusty and Mark,
Thank you for your replies.
I'm sorry for the confusing resizer. I just removed that from the code.
New Fiddler
Just to clarify things. The box div is a container which has multiple images in it. I am trying to achieve the following:
http://postimage.org/image/qwhtik04f/
The grey dotted boxes are the dropbox2 div from my example.
The space around those drop boxes are dropbox div.
The space with the board is the only place where images may be dropped without anything happening.
The dragged images can snap back to the dropbox2 divs.
If the images are dragged onto the dropbox div, the images should revert.
Setting the greedy: true option on the inner droppable will prevent the event from happening on the outer droppable:
jQuery('#dropbox2').droppable({
greedy: true,
drop: function(event, ui) {
// ...
}
});
Your code has this for the outer <div>:
$("#dropbox").droppable({
drop: function(event, ui) {
ui.draggable.draggable( 'option', 'revert', true );
}
});
This says to set the revert option to true when you drag into the outer <div>. However, when you drop in the smaller <div>, the option is still set to true. All you need to do is change the revert value on your draggable element after a successful drop in your inner <div>:
$("#dropbox2").droppable({
drop: function(event, ui) {
ui.draggable.position( { of: $(this), my: 'center', at: 'center' } );
// Add this line
ui.draggable.draggable( 'option', 'revert', false );
}
});
Update:
Mark pointed out that my solution doesn't stop the propagation of the event to the parent container. As his answer shows, you need to add greedy: true in your initial options. The jQuery documentation says:
If true, will prevent event propagation on nested droppables.
That sounds like what you're looking for. You still need to change the revert property on your draggable, since greedy is only set on your droppables and won't affect your draggable reactions.
I have been pulling my hair out trying to make this work.
I have two connected sortables, defined like so:
var sortlists = $("#List1, #List2").sortable(
{
appendTo: 'body',
tolerance: 'pointer',
connectWith: '#List1, #List2',
revert: 'invalid',
forceHelperSize: true,
helper: 'clone',
scroll: true
});
Here is a link to an example of jsfiddle
Because of the page setup, both sortables are being contained in div's with overflow: auto they are also wrapped in parent containers with overflow set to hidden. For arguments sake, lets say there is no way around that.
Is there a way to make the container element scroll when the helper is being positioned towards the lower or upper edge of the container?
Any help would be appreciated!
With helper:'original', I get the scrolling behaviour you seek, (in Opera 11.61).
forked fiddle
Edit: Here's a version of the fiddle with "ganged-scrolling"
I think this is what you want. Drag from div (with scrollable) to div (with scrollable) without the dragged item appearing behind the div.
http://jsfiddle.net/nURN5/1/
.document.body.appendChild //required to add code with link...
The next best approach would be to actually drag a clone of the item...
The forked fiddle with "ganged-scrolling" unfortunately exhibits the very nasty side effect of constraining (visually) the selected item to it's own div.