I am trying to make a simple game in which I show five movie posters and the user has to order them by release date, like shown in the attached picture (these posters are random ones I found).
Each picture is coded like this:
<div id="div11" ondrop="drop(event)" ondragover="allowDrop(event)" style="display:inline-block; position:relative">
<img value="5" src="../images/movies/hobbit.png" draggable="true" ondragstart="drag(event)" id="drag15" width="162" height="240">
</div>
Where div11 means div1,image1, so the others will be like div12, div13...The image id drag15 means that this images is the fifth in the correct order, so the others are drag11, drag12...
And the div where they are going to be put is like this:
<div id="div21" ondrop="drop(event)" ondragover="allowDrop(event)" style="display:inline-block; position:relative"></div>
So the image with the id="drag13", for example, has to be put in the div with id="div23". I have the following function to allow the dragging and dropping of the images in the blank divs, but when I drag an image to a div where there is already an image, the second one disappears:
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
Here you can find a jsfiddle to try and help you understand what I mean and what I have at the moment: http://jsfiddle.net/3GKPn/2/
The problem is in the ondrop event handler, when dropping on an img (not a div), you use this code:
ev.target.appendChild(document.getElementById(data));
That will append the dragged image to the target which is also an image. Hence the dragged image disappears. You have to check if the dropping target is an image or not, if it's an image, the natural behavior is swapping the 2 images. Here is the code it should be:
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
var dragged = document.getElementById(data);
//check if the dropping target is an image
if(ev.target.tagName == "IMG") {
//preparing to swap the 2 images (the dragged image and the target image)
var parent = ev.target.parentElement || ev.target.parentNode;
dragged.parentElement.appendChild(ev.target);
parent.appendChild(dragged);
} else {
//check if the div already has some img,
//swap the 2 images
if(ev.target.children.length > 0) {
dragged.parentElement.appendChild(ev.target.children[0]);
}
ev.target.appendChild(dragged);
}
}
I've also modifying the CSS a little to make the images smaller for better rendering (and testing) right in jsFiddle.
Updated demo.
Try this fiddle : DragAndDropModule
$(function() {
// there's the gallery and the transfer
var $gallery = $( "#gallery" ),
$transfer = $( "#transfer" ),
$gen_dialog = $( '#gen_dialog' );
// let the gallery items be draggable
$( "li", $gallery ).draggable({
cancel: "a.ui-icon", // clicking an icon won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
// let the transfer be droppable, accepting the gallery items
$transfer.droppable({
accept: "#gallery > li",
activeClass: "ui-state-highlight",
drop: function( event, ui ) {
deleteImage( ui.draggable );
}
});
// let the gallery be droppable as well, accepting items from the transfer
$gallery.droppable({
accept: "#transfer li",
activeClass: "custom-state-active",
drop: function( event, ui ) {
recycleImage( ui.draggable );
}
});
// set up the generate button's dialog box
$gen_dialog.dialog({
autoOpen:false,
height:140,
'title': 'Generated Report',
modal:true
});
// function for generating info of icon/s in drop box
$('button.generate').click(function() {
var content = $('ul li h5', $transfer).map(function(i, v) {
return $(this).text();
}).get();
$gen_dialog.find('.diag-content').html(content.join(', ')).end().dialog('open');
});
//function for resetting the icons back to original positions
$('button.reset').click(function() {
$('ul li', $transfer).each(function() {
recycleImage($(this));
});
});
toggleButtons();
// image deletion function
var recycle_icon = "<a href='link/to/recycle/script/when/we/have/js/off' title='Transfer this icon back' class='ui-icon ui-icon-transfer-e-w'>Transfer this icon back</a>";
function deleteImage( $item ) {
$item.fadeOut(function() {
var $list = $( "ul", $transfer ).length ?
$( "ul", $transfer ) :
$( "<ul class='gallery ui-helper-reset'/>" ).appendTo( $transfer );
$item.find( "a.ui-icon-transferthick-e-w" ).remove();
$item.append( recycle_icon ).appendTo( $list ).fadeIn(function() {
$item
.animate({ width: "48px" })
.find( "img" )
.animate({ height: "36px" }, function() {
toggleButtons();
});
});
});
}
// image recycle function
var transfer_icon = "<a href='link/to/transfer/script/when/we/have/js/off' title='Transfer Across' class='ui-icon ui-icon-transferthick-e-w'>Transfer Across</a>";
function recycleImage( $item ) {
$item.fadeOut(function() {
$item
.find( "a.ui-icon-transfer-e-w" )
.remove()
.end()
.css( "width", "96px")
.append( transfer_icon )
.find( "img" )
.css( "height", "72px" )
.end()
.appendTo( $gallery )
.fadeIn(function() {
toggleButtons();
});
});
}
// display buttons when icon transferred across
function toggleButtons() {
$('div.col3 button').toggle($('> ul > li', $transfer).length > 0);
}
// resolve the icons behavior with event delegation
$( "ul.gallery > li" ).click(function( event ) {
var $item = $( this ),
$target = $( event.target );
if ( $target.is( "a.ui-icon-transferthick-e-w" ) ) {
deleteImage( $item );
} else if ( $target.is( "a.ui-icon-transfer-e-w" ) ) {
recycleImage( $item );
}
return false;
});
});
Related
I would appreciate if someone can help me out,
here's my code :
`https://jsfiddle.net/m796a3ud/`
What I want to do is drag an image from these list of Images and be able to get a clone that's draggable, and when I put it inside the box it counts how many images are inside, it works good for the most part but when I try to drag the cloned image in and out of the box a couple of times the clone gets cloned it self which is not what I want, I would really appreciate the help!
thanks.
You have to call ui.helper.remove(); on the out event, try this:
$(function() {
// document.addEventListener('mousemove', function(event) {
// console.log($(':hover').hasClass('draggable'))
// })
var n = 0;
$( ".draggable" ).draggable({helper: 'clone'});
$( ".wrong" ).draggable();
$( "#droppable" ).droppable({
accept: ".draggable",
drop: function( event, ui) {
console.log(ui.draggable)
console.log($(':hover').hasClass('draggable'))
var new_signature = $(ui.helper).clone().removeClass('draggable');
new_signature.draggable();
$(this).append(new_signature);
if($(new_signature).hasClass("ui-draggable") && !$(new_signature).hasClass("dropped")){
$(new_signature).addClass("dropped draggable")
n++;
$(".count").text("There are " + n + " divs inside parent box detail.");
}
},
out: function(event, ui) {
ui.helper.remove();
if($(ui.draggable).hasClass("draggable") && $(ui.draggable).hasClass("dropped")) {
$(ui.draggable).removeClass("dropped")
console.log(ui.helper)
}
if( n > 0) {
n--
}
$(".count").text("There are " + n + " divs inside parent box detail.");
}
});
});
This is the jquery function which makes the ul draggable and and a particular area droppable.
//Jquery
$(function () {
// there's the gallery5 and the trash
var $gallery5 = $("#gallery5"),
$trash = $("#trash");
// let the gallery5 items be draggable
$("ul", $gallery5).draggable({
cancel: "a.ui-icon", // clicking an icon won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move",
});
// let the trash be droppable, accepting the gallery items
$trash.droppable({
accept: "#gallery > li",
accept: "#gallery2 > li",
activeClass: "ui-state-highlight",
drop: function (event, ui) {
alert("trash");
deleteImage(ui.draggable);
}
});
// let the gallery be droppable as well, accepting items from the trash
$gallery5.droppable({
accept: "#gallery li , #gallery2 li , #gallery4 li , #gallery3 li",
activeClass: "custom-state-active",
drop: function (event, ui) {
alert("gallery5");
recycleImage(ui.draggable);
}
});
// image deletion function
var recycle_icon = "<a href='link/to/recycle/script/when/we/have/js/off' title='Recycle this image' class='ui-icon ui-icon-refresh'>Recycle image</a>";
// image recycle function
var trash_icon = "<a href='link/to/trash/script/when/we/have/js/off' title='Delete this image' class='ui-icon ui-icon-trash'>Delete image</a>";
function recycleImage ($item) {
// alert("recycleImage");
$item.fadeOut(function () {
$item
.find("a.ui-icon-refresh")
.remove()
.end()
.css("width", "250px")
.find("img")
.css("height", "50px")
.end()
.fadeIn()
.appendTo($gallery5);
});
}
// image preview function, demonstrating the ui.dialog used as a modal window
});
This is called in a loop and the data is coming from the database.
//BODY
<ul id=coming from database>
<li>
description
id
</li>
</ul>
There are multiple uls in the output. I want to check the id of that particular ul which i am dragging.
Thanx.
jQuery
$('ul').each(function(){
var ulID = $(this).attr('id');
});
This will get the ID from each ul, you can then do what you need with it . . .
Have you ever try this:
var ids = '';
$('ul').each(function(){
ids += $(this).attr('id');
});
Try this:
$('ul').each(function()
{
var ids= $(this).attr('id'); // This is your rel value
});
What I'm trying to do is combine two projects:
One is an example of draggable and sortable list-items
The other is jEditable, which I'm using to make the list-items editable
Now I was able to append the edit class to the existing list items in the first link without any trouble. When I go to create a new draggable item (a clone) and move it to the sortable list, I want it to take on the css class of the older items. I have tried adding code to the draggable's stop event and the sortable's receive event with no luck. It's the original's style that changes, not the clone's.
receive: function(event, ui) {
alert("dropped item ID: " + ui.item.attr('id'));
$("#draggable").attr('class', 'edit');
}
stop: function() {
if ( !$( "#draggable" ).hasClass( "ui-state-hover" ) ) {
$( "#draggable" ).removeClass( "ui-state-highlight" );
$( "#draggable" ).addClass( "ui-state-default" );
$( "#draggable" ).addClass( "edit" );
}
}
How can I achieve this?
JSFiddle is here
You can actually utilize the ui in your sortable event stop. Here short definition of them:
ui.
helper: The jQuery object representing the helper being sorted
item: The jQuery object representing the current dragged element
offset: The current absolute position of the helper represented as { top, left }
position: The current position of the helper represented as { top, left }
originalPosition: The original position of the element represented as { top, left }
sender: The sortable that the item comes from if moving from one sortable to another
So you need to use stop event and change the ui.item style like this:
$(ui.item).attr('class', 'ui-state-default edit');
And you have to re-initiate the editable like this:
$(document).ready(function() {
initEditable();
});
function initEditable(){
$('.edit').editable('http://www.example.com/save.php', {
indicator : 'Saving...',
tooltip : 'Click to edit...'
});
$('.edit_area').editable('http://www.example.com/save.php', {
type : 'textarea',
cancel : 'Cancel',
submit : 'OK',
indicator : '<img src="img/indicator.gif">',
tooltip : 'Click to edit...'
});
}
$(function() {
$( "#sortable" ).sortable({
revert: true,
update: function() {
var orders = [];
$.each($(this).children(), function(i, item) {
orders.push($(item).data("x"));
});
$("#info").text("Order: " + orders.join(","));
},
stop: function(event, ui) {
$(ui.item).attr('class', 'ui-state-default edit');
initEditable();
}
});
});
See modified code here: http://jsfiddle.net/xvsMh/1/
Your events are correct, but as you realized, #draggable is the original item, not the cloned one. One way to get your cloned item would be to search for an item with identical classes in the sortable list. So instead of using:
$("#draggable").attr('class', 'edit');
you use:
$('#sortable .ui-draggable')
.removeClass('ui-state-highlight ui-draggable')
.addClass('ui-state-default edit');
Demo at JSFiddle
Hi all i have a function where i have to drag and drop elements here is my code:
$(document).ready(function() {
var i = 0;
$("button[id='columnadd']").click(function () {
alert(1);
var domElement = $('<aside id="shoppingCart' + i + '" class="shoppingCart"><h2 class="ui-widget-header">Add Menu Items Here</h2><aside class="ui-widget-content" id="droppable"><ol><li class="placeholder">Add your items here</li></ol></aside></aside>');
i++;
$(this).after(domElement);
});
$(".small_box li" ).draggable({
appendTo: "body",
helper: "clone"
});
});
$('#shoppingCart ol').droppable({
accept: '.small_box li',
drop: function (event, ui) {
alert(1);
$(this).find(".placeholder").remove();
$("<li></li>").text(ui.draggable.text()).appendTo(this);
}
});
here is my html:
<aside class="small_box">
<h4>BRANDS</h4>
<ul>
<li id ="brand1"><a class="" href="#">Brand1</a></li>
<li id ="brand2">Brand2</li>
<li id ="brand3">Brand3</li>
<li id ="brand4">Brand4</li>
</ul>
</aside>
i should be able to drop in at this place <li class="placeholder">Add your items here</li>
var domElement = $('<aside id="shoppingCart' + i + '" class="shoppingCart"><h2 class="ui-widget-header">Add Menu Items Here</h2><aside class="ui-widget-content" id="droppable"><ol><li class="placeholder">Add your items here</li></ol></aside></aside>');
any help is much appreciated
First, please fix your code indentations.
There are some mistakes on your code:
var i = 0;
I think it should be a global variable. So put it outside your $(document).ready(function() {}) block;
You create a DOM Element (which is the drop area) upon click and this element is not in your page until you click the trigger. By doing $('#shoppingCart ol').droppable({...}) in $(document).ready(function() {}) block you try to add droppable to an element that even not in your page, so this won't do a thing.
What you should do is make the element droppable after you create that element and put it on your page. here's an example:
$("button[id='columnadd']").click(function () {
// create the element
var domElement = $('<aside id="shoppingCart' + i++ + '" class="shoppingCart"><h2 class="ui-widget-header">Add Menu Items Here</h2><aside class="ui-widget-content" id="droppable"><ol><li class="placeholder">Add your items here</li></ol></aside></aside>');
// put it after $(this)
$(this).after(domElement);
// at this point you have domElement in your page
// make it droppable
domElement.find("ol").droppable({
// put options here
greedy: true,
drop: function (event, ui) {
makeItDroppableToo(event, ui, this);
}
});
});
and this is the function to make your dropped element has its own placeholder
function makeItDroppableToo(e, ui, obj) {
$(obj).find(".placeholder").remove();
var placeholder = $("<ol><li class='placeholder'>You can also drop it here</li></ol>");
$("<li></li>").append(ui.draggable.text()).append(placeholder).appendTo($(obj));
// this is the same as the previous one
placeholder.droppable({
// put options here
greedy: true,
drop: function (event, ui) {
makeItDroppableToo(event, ui, this);
}
});
}
Try this fiddle, I was working with JQueryUI
http://jsfiddle.net/ashpriom/yHLGP/
$(function() {
$( "#draggable" ).draggable();
$( "#droppable" ).droppable({
drop: function( event, ui ) {
$( this )
.addClass( "ui-state-highlight" )
.find( "p" )
.html( "Dropped!" );
}
});
});
I am trying to develop a simple drag and drop 'game'. In simple terms all you do is drag and drop various items into a area and it will say correct or wrong depending on the item dragged. This is what I have so far and its not working at all and I dont know why. My knowledge of JS and jQuery leaves a lot to be desired too.
<script>
$(function() {
$( "#draggable" ).draggable();
$( "#wrong" ).draggable();
$( "#droppable" ).droppable({
drop: function( event, ui ) {
var currentId = $(this).attr('id');
if (currentId == "draggable") {
$( this )
.addClass( "highlight" )
.find( "p" )
.html( "Correct! :)" );
} else {
$( this )
.find( "p" )
.html( "Wrong! :(" );
}
}
});
});
</script>
Now that I have it working I need more instances of the draggable images but when I add more the the new ones that have been added don't work.
http://jsfiddle.net/KcruJ/9/
var currentId = $(this).attr('id');
if (currentId == "draggable")
...
Will never result true, as $(this) represents the droppable the draggable is dropped on. ui.draggable represents the draggable[1]
Try:
var currentId = $(ui.draggable).attr('id');
if (currentId == "draggable")
...
This works: http://jsfiddle.net/T6nu3/2/
$(this).attr('id');
Will always return droppable.
You need to access the dragged element:
$(ui.draggable).attr('id');
Take a look at the jQuery UI Documentation for more information.
Code:
$(function() {
$("#draggable").draggable();
$("#wrong").draggable();
$("#droppable").droppable({
drop: function(event, ui) {
var currentId = $(ui.draggable).attr('id');
if (currentId == "draggable") {
$(this).addClass("highlight").find("p").html("Correct! :)");
} else {
$(this).find("p").html("Wrong! :(");
}
}
});
});
haha well, Alex seems to have this one on lock.
There's the answer: http://jsfiddle.net/aGqHh/1/