Using jQuery UI, I've just set up a simple test with draggable and droppable
HTML:
<div>
<img src="img/2.jpg" alt="Donut" id="a" class="drag"><span id="4" class="drop" >Eclair</span>
</div>
<div>
<img src="img/3.jpg" alt="Eclair" id="b" class="drag"><span id="3" class="drop">Donut</span>
</div>
I am trying to drag the first image and drop into the related span.Along with this if i drag and drop first image at id="4" it should revert back to its original position.Similarly when i drag and drop second image at id="3" it should revert back to its original position.
script:
$(function () {
$("#a").draggable({
revert: "valid",
});
$("#b").draggable({
revert: "invalid",
});
$(".drop").droppable({
accept: '.drop',
});
});
I can drag the image but could not drop it in a correct position.What i am doing wrong?
css:
.drag,.drop{
width:130px !important;
height: 130px !important;
border:2px solid !important;
margin-top:10px !important;
margin-left: 15% !important;
}
.drop{
float: right !important;
margin-right: 30% !important;
}
https://jsfiddle.net/jjewhwLt/
You need to style the elements a bit different, add the draggable() to the .drag class and you can then append the droppable() to the .drag elements. I've also added data-id to both drag and drop elements to be able to match them. I hope this is what you're looking for:
Updated FIDDLE.
$(".drag").draggable({
revert: 'invalid'
});
$(".drop").droppable({
accept: function(drag) {
var drop_id = $(this).attr('data-id');
var drag_id = $(drag).attr('data-id');
return drop_id === drag_id;
}
});
I had a bit of trouble understanding the question here, but i'll give it my best shot at explaining what I think you're trying to achieve.
I'd recommend in the future to start naming out what you're trying to do clearly so that you yourself can understand it while you're working. Stuff like "A" and "B", "3" and "4" etc. will get confusing very very fast with what you're working on.
What I took from this was that you are trying to get each container to accept it's corresponding image. Here's a cleaned up version of your jsfiddle: https://jsfiddle.net/8hr3vf3L/
I've separated out the images + drop areas in the HTML first and replaced the images that were broken with placeholders:
<div class="images">
<img src="http://placehold.it/120?text=donut" alt="Donut" id="donut" class="drag">
<img src="http://placehold.it/120?text=eclair" alt="Eclair" id="eclair" class="drag">
</div>
<div class="drop-areas">
<div class="drop-area" id="eclairArea">Eclair</div>
<div class="drop-area" id="donutArea">Donut</div>
</div>
Then cleaned up the CSS a little to make it a bit more generic:
.drop-areas {
margin-top: 40px;
}
.drop-area,
.drag {
display: inline-block;
width: 120px;
height: 120px;
border: 2px solid black;
margin-right: 20px;
}
.drag { border: none; }
Then finally your JS, which I hope makes more sense for you now. revert within a draggable function when named invalid will send the square back to where it was if it isn't in an area where it's accepted, which is explained by the droppable functions, which in this case I've separated out to make a little more sense to you, but you could I assume, make this programmatically check which image is being dropped in. As you can see, #eclairArea is set up to only accept the #eclair and vice-versa.
$(function () {
$(".drag").draggable({
revert: "invalid",
});
$("#eclairArea").droppable({
accept: '#eclair'
});
$("#donutArea").droppable({
accept: '#donut'
});
});
Related
I have a series of HTML spans, such as:
<span class="dragable" id="Apple">
<span class="dragable" id="Banana">
<span class="dragable" id="Carrot">
...etc. My goal is to make each span dragable onto any other span. Upon this occurring, a JavaScript function will be invoked, which will somehow determine the ID of both the dragged and dropped elements, and then log them to the console (for debugging purposes of course)
Making these spans dragable is simple, but I'm not sure how to go out about passing the IDs to JavaScript. I've seen some tutorials on passing the IDs through events, but not any clear ones.
Any advice would be greatly appreciated.
You can use jQuery UI. It provides drag and drop just like you need it:
$(document).ready(function() {
var $output = $('#output');
$(".draggable").draggable({revert: true}).droppable({
drop: function(event, ui) {
var $dragged = $(ui.draggable[0]);
$output.text($dragged.attr('id') + " was dropped on " + $(this).attr('id'));
}
});
});
.draggable {
width: 50px;
height: 50px;
display: inline-block;
border: 1px solid black;
background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<span class="draggable" id="Apple"></span>
<span class="draggable" id="Banana"></span>
<span class="draggable" id="Carrot"></span>
<div id="output"></div>
Have a closer look to the docs of draggable and droppable to see full functionality.
I'm asking as a last resort before I tear the last of my hair out. At the moment I am showing an initial 2 divs. The user can then add these two divs below the original as many times as they want. They can also remove the 2 divs if necessary. I am trying to allow reording of the divs using drage and drop. I've tried numerous methods but I just can't get it working. As an extra note, the divs need to reindex themselves once the user has dragged and dropped. Here is the code that I have. Please take into consideration that I have added and deleted lots of code attempts before settling on this basic implementation. Thanks in advance.
Load JQuery
Display first div to end user
<!--Div contains each answer step-->
<div id = "answer_step" class = "answer_step">
<!--This placeholder text is styled from CSS and will empty the div once the user starts typing-->
<div id="answer_step_equation0" class="answer_step_equation" contenteditable="true" placeholder="Enter The Next Solution Step This Question"></div>
<div id="answer_step_description0" class = "answer_step_description" contenteditable="true" placeholder="Enter A Description as to how this step was reached or how to solve the next step"></div>
</div>
</div>
<!-- Buttons to dynamically add and remove answer divs. The remove functionality is added in JQuery for the add button-->
<button id="add_answer_step_button" class="add_answer_step_button">+ Add next Step</button>
This code appends the new divs. I have to put the three divs within a div like above but I can't get it to work.
<!--Script to append/remove div when user clicks on add_answer_step_button-->
<script type = "text/javascript" language = "javascript">
$(document).ready(function() {
<!--This variable gives each new set of answer divs a unique id by appending a number to the end of th id-->
<!--The first set of answer divs will have an id of zero-->
var answer_identifier_number = 1;
$("button.add_answer_step_button").click(function () {
$("div.answer_steps").append('<div id="answer_step_equation' + answer_identifier_number + '" class="answer_step_equation" contenteditable="true" placeholder="Enter The Next Solution Step This Question"></div>');
$("div.answer_steps").append('<div id="answer_step_description' + answer_identifier_number + '" class = "answer_step_description" contenteditable="true" placeholder="Enter A Description as to how this step was reached or how to solve the next step"></div>');
$("div.answer_steps").append('<button id="remove_answer_step_button' + answer_identifier_number + '" class = "remove_answer_step_button">- Remove This Step</button>');
answer_identifier_number++;
});
});
</script>
Allow the divs to be draggable
<script type = "text/javascript" language = "javascript">
$(function() {
$( "#answer_steps" ).sortable();
$( "#answer_steps" ).disableSelection();
cursor: move;
});
</script>
I haven't figured out how to reindex the names yet but I have experience of that part so I should be fine. Thanks for your help.
ok, before you go tearing your hair out, have a look at this 'drag and drop' fiddle - its a heres-one-I made-earlier one jsfiddle.net/RachGal/ahnx7kwc It'll give you an idea about how the whole drag and drop thing works – Rachel Gallen 2 days ago
The HTML from this fiddle
<div class="common">
<div class="container-fluid">
<div class="row">
<ul class="col-sm-3 col-md-2 sidebar nav nav-sidebar" >
<li class="group" class="draggable" ><a href="#" class="list-group-item">
<h4>
dsad
<br /><small>dsadsa</small>
<br /><small>dsadsa</small>
</h4>
</a>
</li>
<li class="group" class="draggable"><h2>
BAH
</h2><br><small>hello</small>
</ul>
<div id="drophere" class="col-sm-9 col-md-9">MAIN PANEL</div>
</div>
</div>
The Javascript from this fiddle
$(".draggable").draggable();
var draggableArguments={
revert: 'invalid',
helper:'clone',
appendTo: '#drophere',
refreshPositions: true,
containment: 'DOM',
zIndex: 1500,
addClasses: false
};
$('.group').draggable(draggableArguments);
$('.group').droppable();
$(".nav-sidebar").droppable({
tolerance: "intersect",
accept: ".group",
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
drop: function(event, ui) {
$(".nav-sidebar").append($(ui.draggable));
}
});
$('#drophere').droppable({
tolerance: "intersect",
accept: ".group",
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
drop: function(event, ui) {
$('#drophere').append($(ui.draggable));
}
});
$('#drophere').sortable();
The CSS from this Fiddle
.draggable {
border: solid 2px gray;
}
.sidebar {
position:fixed;
width:200px;
top: 51px;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
padding: 20px;
overflow-y: auto;
/* Scrollable contents if viewport is shorter than content. */
overflow-x: visible;
background-color: #f5f5f5;
white-space: nowrap;
border-right: 1px solid #eee;
padding-left: 30px;
padding-right: 30px;
}
/* Sidebar navigation */
.nav-sidebar {
width:200px;
height:100vh;
margin-right: -21px;
/* 20px padding + 1px border */
margin-bottom: 20px;
margin-left: -20px;
}
.group{width:150px;
height:auto;
}
#drophere{width:700px;left:200px; height:100vh;}
By setting droppable widget's greedy to true, only the top-most element should respond to a drop event. There's really no complexity here but I just cannot get it to work. And this is all I have so not much to work on:
CSS:
.page{
position: absolute;
width: 150px;
height: 150px;
left: 0px;
top: 0px;
text-align: center;
background: #F0FFFF;
border: 1px solid #89B;
}
HTML:
<div class = 'page' id = 'page1'> page1 </div>
<div class = 'page' id = 'page2'> page2 </div>
<div class = 'page' id = 'page3'> page3 </div>
JS:
document.ready = function(){
$('.page').draggable()
$('.page').droppable({
greedy: true,
drop: function( event, ui ){
console.log( 'assert drop once')
}
})
}
what's happening right now is that all the dropped on elements are responding to the drop event. Since there's so little code to hold on to, I have no idea how to diagnose this.
Reading the documentation for the greedy property I'm not sure I understand the same as you:
By default, when an element is dropped on nested droppables, each droppable will receive the element. However, by setting this option to true, any parent droppables will not receive the element.
For me it means if you have a large div droppable which contains another smaller div droppable then if you drop an element in the small one only the small one will receive the event.
Check this demo to understand what I'm explaining : http://jquery-ui.googlecode.com/svn/tags/1.6rc4/demos/droppable/greedy.html
Example:
<div>
<div class='drop'>
<div class='drag'></div>
</div>
<div class='drop'>
</div>
<div class='drop'>
</div>
<div class='drop'>
</div>
<div>
</div>
</div>
$('div.drag').draggable({ containment: 'div.drop' });
Normally, if there is only 1 "div.drop" element, it works as intended. If there are more than 1(like in the example above), I thought that it would be dragged/dropped in any of the "div.drop" divs. As it turns out, it is only draggable/droppable to the first element matched by the "div.drop" selector.
Is there a workaround for this(that is, make it contained/droppable/draggable only in the "div.drop" divs)?
EDIT: I guess you are right guys. After some introspection, I realized that I didn't go for your suggested solutions since there are padding between the divs and I don't want the the "div.drag" divs to be dropped on the padded area.
It don't works like that !!
The containment is to constraint bound of dragging.
You want drag and drop.
Then you have to configure drag for div.grag:
$('div.drag').draggable();
And configure drop for div.drop:
$('div.drop').droppable();
You can add containment for your drag element with your first div level:
<div id='dragZone'>
<div class='drop'>
<div class='drag'></div>
</div>
<div class='drop'>
</div>
</div>
$('div.drag').draggable({ containment: '#dragZone'});
containment restricts the movement of a draggable within the bounds of the given element(s). You could set containment to the parent of the div.drops.
You should make the div.drops droppable, append the draggable on drop, and use the revert: 'invalid' option so that the draggable reverts if it's not dropped on a droppable
$('div.drop').droppable({drop: function(e, ui) {
ui.draggable.appendTo(this);
}});
$('div.drag').draggable({
helper: 'clone',
revert: 'invalid'
});
As the guys have pointed out the containment selector does not work like that as it Constrains dragging to within the bounds of the specified element or region.
You could try something like below:
JQuery References:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
HTML:
<div id="dragContainer">
<div class='drop'>
<div class='drag'>drag</div>
</div>
<div class='drop'>drop
</div>
<div class='drop'>drop
</div>
<div class='drop'>drop
</div>
<div class='nodrop'>
</div>
</div>
JQuery:
<script type="text/javascript">
$('div.drag').draggable({ containment: '#dragContainer', revert: "invalid" });
$('div.drop').droppable( {
drop: handleDropEvent
} );
function handleDropEvent( event, ui ) {
var draggable = ui.draggable;
alert( 'Ok to drop here onto me!' );
}
</script>
Do try my code
<style>
.container {
border: 2px solid #000;
}
.container img {
width: 45px;
height: 45px;
}
.draggable {
width: 40px;
height: 40px;
background: #F90;
border-radius: 10px;
margin: 0 0 0 0;
float: top;
}
.draggable.is-pointer-down {
background: #09F;
z-index: 2; /* above other draggies */
}
.draggable.is-dragging { opacity: 0.7; }
</style>
<script>
$(document).ready( function() {
var $draggables = $('.draggable').draggabilly({
// contain to parent element
**containment: "#box"**
});
});
</script>
Hello. I think this might help you :)
<div class="container" id="box">
and my images are inside this div.
Hey there,i'm creating a simple inventory using jQuery droppable. For now, it's like :
$(document).ready(function() {
$( ".weapon, .helmet" ).draggable({ revert: "invalid", cursor: "move" });
$( "#weapon_spot" ).droppable({accept: ".weapon"});
$( "#helmet_spot" ).droppable({accept: ".helmet"});
// make inventory slots droppable as well
$( ".inv_slot" ).droppable({accept: ".weapon"});
});
I'm kinda new to JQuery and have some trouble setting an image to be aligned inside a certain div. Everything(.weapon, .helmet etc) is a div. Inside them, there can be images. The divs are 70x70 and the images are of that size as well.
The css is like :
.inv_slot, #weapon_spot, #helmet_spot {
width: 70px;
padding: 10px;
height: 70px;
margin: 10px;
border: 1px solid black;
float: left;
text-align: center;
}
and the image inside a div is like :
<div class='inv_slot'>
<img class='weapon' src= "..." />
</div>
My problem is that when i drop an image to another div, it's not aligned in the center of the div, it's not locked and it can be moved inside it. It seems that i can use Drag.Move somehow to do that, but i can't find some good resource explaining that. Could you please help ? :)
EDIT : I have created a demo at http://jsfiddle.net/kzuRn/2/
Add a drop callback to the droppables and apply the style changes necessary. Because right now the item is still positioned absolutely it will not recognize your center css.
Something like this: WRONG (see below)
drop: function(ev, ui) {
$(this).css({position: 'static'})
}
I updated the fiddle. I was wrong before. this is the droppable, and ui.draggable is the draggable.
drop: function(ev, ui) {
$(this).append(ui.draggable.css('position','static'))
}