JQuery Drag and Drop positioning issues - javascript

I am having issues with drag and drop functionality and I'm hoping someone can help. The rules in a nutshell are:
the "stage" (.stage) of which there can be more than one can accept cloned .pageControl. It is the only class it can accept.
Once dropped on .stage, .pageControl becomes .pageControlDropped and can accept cloned .wfcControl. It is the only class it can accept.
Once .wfcControl is dropped, it is replaced with new html and becomes .wfcControlDropped.
My problems are:
When I drag cloned .pageControl to .stage, it jumps to a position on .stage that is not the position I'm dropping it. I can drag it back to where I want it but it needs to drop where I drop it. I tried CSS positioning but it seems to work on .pageControl. Once .pageControl -> .pageControlDropped, it jumps to another position. Also, its not a very fluid drag like in the examples
If I drag multiple .pageControls to .stage, any of them should accept .wfcControl. But it seems like only the first .pageControl (now .pageControlDropped) receives it. I can't get the second .pageControlDropped to receive it.
How do I get successive .pageControl to not overlay existing ones on .stage?
CSS:
<style type="text/css">
.stage { margin-left: -.3em; width: 500px; height: 550px; padding: 0.0em;}
.pageControl {height:15px; width:15px; background-color:#EAEEFF; border:1px solid blue;}
.pageControlDropped {height:450px; width:600px;background-color:#F9FAFF;border:1px solid blue;}
.wfcControl { }
.wfcControlDropped { }
</style>
JQuery:
$('.pageControl').draggable({
helper: 'clone',
snap: false,
containment: '.stage',
handle: '.wfcHandle',
stop: function (event, ui) {
var pos = $(ui.helper).offset();
$(this).css({
"left": pos.left,
"top": pos.top
});
}
});
$('.wfcControl').draggable({ helper: 'clone', containment: '.pageControlDropped' });
$('.stage').droppable({
accept: '.pageControl',
greedy: true,
drop: function (event, ui) {
$(this).append($(ui.helper).clone());
$('.stage .pageControl')
.removeClass('pageControl')
.addClass('pageControlDropped')
.resizable()
.draggable({
containment: '.stage',
handle: '.wfcHandle'
})
.droppable({
accept: '.wfcControl',
greedy: true,
drop: function (event, ui) {
switch (ui.helper[0].title) {
case "Play Greeting Control":
wfcControlDropped = wfcPlayGreetingControl
break;
case "Input Control":
wfcControlDropped = wfcInputControl
break;
}
$(this).append($(ui.helper).clone());
$('.pageControlDropped .wfcControl').replaceWith($(wfcControlDropped));
$('.pageControlDropped .wfcControlDropped')
.draggable({
containment: '.pageControlDropped'
})
}
}).clone(false)
return false;
}
});
Finally, the HTML:
<div id = "divPageControl" title = "Page Control" class="pageControl">
<table style = "width:100%" border = "0">
<tr>
<td colspan = "1" width = "100%"></td>
</tr>
</table>
</div>
<div id = "divInputControl" title = "Input Control" class="wfcControl" style="height:15px; width:15px; background-color:light green; border:1px solid green;">
<table style = "width:100%" border = "0">
<tr class = "wfcHandle">
<td colspan = "1" width = "100%"> </td>
</tr>
</table>
</div>
Thanks for any help on this.

This should get you WELL ON YOUR WAY:
HTML:
<div class="pageControl"></div>
<div class="wfcControl"></div>
<div class="stage"> STAGE</div>
<div class="stage"> STAGE</div>
JAVASCRIPT:
$('.pageControl,.wfcControl').draggable({
helper:"clone",
opacity:0.5
});
//=========================================
$('.stage').droppable(
{
tolerance: "fit",
greedy:true,
accept: ".pageControl",
drop: function(e,ui){
$(this).append(
$(ui.draggable).clone()
.css({
position:"absolute",
//IMPORTANT
top: e.clientY-e.offsetY,
left: e.clientX-e.offsetX
})
//note containment:parent => IMPORTANT
.draggable({containment:"parent",
snap:true,
snapMode:"outer",
//MY ATTEMPT TO STOP USERS FROM OVERLAPPING
snapTolerance:15
})
.removeClass("pageControl")
.addClass("pageControlDropped")
.resizable()
.droppable({
accept: ".wfcControl",
drop: function(ev,ui){
$(this).append(
$(ui.draggable).clone()
.css({
position:"absolute",
top:ev.clientY-ev.offsetY-$(this).offset().top,
left: ev.clientX-ev.offsetX - $(this).offset().left
})
//note containment:parent
.draggable({containment:"parent"})
.removeClass("wfcControl")
.addClass("wfcControlDropped")
);
}
})
);
}
}
);
DEMO:
http://jsbin.com/orepew
Let me know if you had any questions

Related

Drag and Drop multiple files using JqueryUI

I struggle with the following problem
I have a Page where a user can drag and drop files into another DIV. The user now wants to Drag and Drop multiple files with one drag. The problem however is, I found a codesnippet online (cant find it anymore sadly), customised the code to meet the design requests and now I'm stuck with enabling that multifile Drag and Drop.
I'm a complete beginner if it comes to JqueryUI.
The idea is to add checkboxes in the corners of the files/pictures. All selected items should be moved at once with a Drag and Drop.
Idealy the user should be able to mark the necessary file with the mouse Drag and Drop, but that's just nice to have and not a crucial requirement.
I don't want to ask fora complete solution from someone, but rather for possible sources or examples where i can try and create a personal custom solution from.
CODE:
HTML:
<ul class="gallery col-md-8 borderBoxes" id="gallery">
#foreach (var item in Model.PageList)
{
<li class="imageListItem ui-icon-zoomin" id="#item.ID">
<img class="pages small" src="data:image/jpeg;base64,#item.ImageBaase64" onclick="imageLarger(this)" />
</li>
}
</ul>
<div id="trash" class="col-md-3">
</div>
<div id="documentContainer" class="document-container">
<div class="row justify-content-between">
<button id="addNewDocument" class="col-2 btn btn-primary add-doc-button">new document</button>
<form method="post" class="col-md-2 offset-md-10 forward-form">
</form>
</div>
<ul id="newDocuments"></ul>
</div>
<div style="display: none;">
<div id="docDescription" class='col-md-4 form-group documentDescription'>
<label class='control-label input-label'>Dokumenttyp</label>
<select>
<!--stuff that is not important for this post-->
</select>
</div>
</div>
JavaScript:
function imageLarger(image, liID) {
if ($(image).width() === 700) {
$(image).width(100);
setTimeout(function () {
$(image).removeClass("largePages");
}, 300);
} else {
$(image).width(700);
$(image).addClass("largePages");
}
};
$("#addNewDocument").click(function () {
var uid = Math.floor(Math.random() * 26) + Date.now()
var newDocumentBox = $("<li class='row documentContainer justify-content-between' id='" + uid + "'></li>").prependTo("#newDocuments");
var newDocumentDescription = $("#docDescription").clone(true);
newDocumentDescription.appendTo(newDocumentBox);
var newDroppableBox = $("<div class='documents col-md-7 droppableBox' ></div>").appendTo(newDocumentBox);
var newDeleteButton = $("<div class='close-container deleteButton' onclick='deleteDocument(" + uid + ")'><div class='leftright'></div><div class='rightleft'></div></div>").appendTo(newDroppableBox);
newDroppableBox.droppable({
accept: "#gallery > li",
drop: function (event, ui) {
ui.draggable.appendTo(this).fadeIn(function () {
ui.draggable
.animate()
.find("img")
});
}
});
});
function deleteDocument(elementID) {
var element = document.getElementById(elementID);
var listOfPages = element.getElementsByClassName("imageListItem");
var amounOfPages = listOfPages.length;
if (element.style.display !== "none") {
element.style.display = "none";
for (var i = 0; i < amounOfPages; i++) {
$("#gallery").append(listOfPages[0]); // 0 because removing an object decreases $children.length by 1
}
}
};
$(function () {
var $gallery = $("#gallery"),
$trash = $("#trash"),
$document = $("#document"),
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>",
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>";
$("li", $gallery)
.draggable({
cancel: "a.ui-icon",
revert: "invalid",
containment: "document",
helper: "clone",
cursor: "move"
});
$trash
.droppable({
accept: "li",
drop: function (event, ui) {
deleteImage(ui.draggable);
}
});
$gallery
.droppable({
accept: "li",
drop: function (event, ui) {
recycleImage(ui.draggable);
}
});
$document
.droppable({
accept: "li",
drop: function (event, ui) {
ui.draggable.appendTo(this).fadeIn(function () {
$item
.animate()
.find("img")
});
deleteImage(ui.draggable);
}
});
function deleteImage($item) {
$item.fadeOut(function () {
var $list = $("ul", $trash).length ?
$("ul", $trash) :
$("<ul class='gallery ui-helper-reset'/>").appendTo($trash);
$item.find("a.ui-icon-trash").remove();
$item.append(recycle_icon).appendTo($list).fadeIn(function () {
$item.addClass('removedPage');
$item
.animate()
.find("img")
});
});
}
function recycleImage($item) {
$item.fadeOut(function () {
$item.removeClass('removedPage');
$item
.find("a.ui-icon-refresh")
.remove()
.end()
.find("img")
.end()
.appendTo($gallery)
.fadeIn();
});
}
$("#recycleAllDocuments")
.on("click", function () {
if ($('#trash').children().length > 0) {
var listOfDeletedItems = document.getElementById("trash").getElementsByClassName("imageListItem");
for (var i = 0; i < listOfDeletedItems.length; i++) {
var $item = $(listOfDeletedItems[i]);
recycleImage($item);
}
}
});
$("deleteButton")
.on("click", function () {
var $item = $(this);
recycleImages($item);
});
$("ul.gallery > li")
.on("click", function (event) {
var $item = $(this),
$target = $(event.target);
if ($target.is("a.ui-icon-trash")) {
deleteImage($item);
} else if ($target.is("a.ui-icon-zoomin")) {
viewLargerImage($target);
} else if ($target.is("a.ui-icon-refresh")) {
recycleImage($item);
}
return false;
});
});
Consider the following example.
$(function() {
var $gallery = $("#gallery"),
$trash = $("#trash"),
$document = $("#document"),
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>",
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>";
$("li", $gallery)
.draggable({
cancel: "a.ui-icon",
revert: "invalid",
containment: "document",
helper: function() {
var help = $("<div>", {
class: "ui-draggable-helper"
});
if ($(".ui-selected").length) {
help.data("items", $(".ui-selected"));
help.addClass("multiple");
} else {
help.data("items", $(this));
}
return help;
},
cursor: "move"
});
$gallery.selectable();
$trash
.droppable({
accept: "li",
drop: function(event, ui) {
deleteImage(ui.helper.data("items"));
}
});
$gallery
.droppable({
accept: "li",
drop: function(event, ui) {
recycleImage(ui.draggable);
}
});
$document
.droppable({
accept: "li",
drop: function(event, ui) {
ui.draggable.appendTo(this).fadeIn(function() {
$item
.animate()
.find("img")
});
deleteImage(ui.draggable);
}
});
function deleteImage($item) {
$item.fadeOut(function() {
var $list = $("ul", $trash).length ?
$("ul", $trash) :
$("<ul class='gallery ui-helper-reset'/>").appendTo($trash);
$item.find("a.ui-icon-trash").remove();
$item.append(recycle_icon).appendTo($list).removeClass("ui-selected").fadeIn(function() {
$item.addClass('removedPage');
$item
.animate()
.find("img")
});
});
}
function recycleImage($item) {
$item.fadeOut(function() {
$item.removeClass('removedPage');
$item
.find("a.ui-icon-refresh")
.remove()
.end()
.find("img")
.end()
.appendTo($gallery)
.fadeIn();
});
}
$("#recycleAllDocuments")
.on("click", function() {
if ($('#trash').children().length > 0) {
var listOfDeletedItems = document.getElementById("trash").getElementsByClassName("imageListItem");
for (var i = 0; i < listOfDeletedItems.length; i++) {
var $item = $(listOfDeletedItems[i]);
recycleImage($item);
}
}
});
$("deleteButton")
.on("click", function() {
var $item = $(this);
recycleImages($item);
});
$("ul.gallery > li")
.on("click", function(event) {
var $item = $(this),
$target = $(event.target);
if ($target.is("a.ui-icon-trash")) {
deleteImage($item);
} else if ($target.is("a.ui-icon-zoomin")) {
viewLargerImage($target);
} else if ($target.is("a.ui-icon-refresh")) {
recycleImage($item);
}
return false;
});
});
.gallery {
list-style: none;
}
.gallery .ui-selecting {
background: #ccc;
border-color: #999;
}
.gallery .ui-selected {
background: #eee;
border-color: #222
}
.imageListItem {
width: 100px;
height: 100px;
border: 1px solid #ccc;
border-radius: 3px;
display: inline-block;
margin: 3px;
}
.ui-draggable-helper {
background: #fff;
width: 50px;
height: 65px;
border: 1px solid #999;
border-radius: 3px;
position: relative;
z-index: 100;
}
.ui-draggable-helper:after {
content: "";
width: 0;
height: 0;
border-bottom: 20px solid #999;
border-right: 20px solid #fff;
position: absolute;
left: 29px;
top: -1px;
}
.ui-draggable-helper.multiple:before {
content: "";
width: 50px;
height: 65px;
border-left: 1px solid #999;
border-bottom: 1px solid #999;
border-radius: 3px;
position: absolute;
top: 5px;
left: -5px;
z-index: 0;
}
#trash {
border: 1px solid #ccc;
width: 200px;
height: 200px;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<ul class="gallery col-md-8 borderBoxes" id="gallery">
<li class="imageListItem ui-icon-zoomin" id="item-1">
<img class="pages small" src="data:image/jpeg;base64,#item.ImageBaase64" onclick="imageLarger(this)" />
</li>
<li class="imageListItem ui-icon-zoomin" id="item-2">
<img class="pages small" src="data:image/jpeg;base64,#item.ImageBaase64" onclick="imageLarger(this)" />
</li>
<li class="imageListItem ui-icon-zoomin" id="item-3">
<img class="pages small" src="data:image/jpeg;base64,#item.ImageBaase64" onclick="imageLarger(this)" />
</li>
</ul>
<div id="trash" class="col-md-3">
</div>
<div id="documentContainer" class="document-container">
<div class="row justify-content-between">
<button id="addNewDocument" class="col-2 btn btn-primary add-doc-button">new document</button>
<form method="post" class="col-md-2 offset-md-10 forward-form">
</form>
</div>
<ul id="newDocuments"></ul>
</div>
<div style="display: none;">
<div id="docDescription" class='col-md-4 form-group documentDescription'>
<label class='control-label input-label'>Dokumenttyp</label>
<select>
<!--stuff that is not important for this post-->
</select>
</div>
</div>
With Draggable, you can create your own helper with a Function call.
Allows for a helper element to be used for dragging display. Multiple types supported:
String: If set to "clone", then the element will be cloned and the clone will be dragged.
Function: A function that will return a DOMElement to use while dragging.
So if you want to represent multiple items, you can make a helper looks like this and you can use .data() to carry all the items. When you drop the helper, you can then perform the actions needed on each of the items.
Making use of Selectable, the User can select a number of items in the gallery and then drag them to the Trash, in this example.

make a dropped div, droppable again

I am trying to make an editor of a sort were you choose your layout for the given section and then drop another paragraph, button, img etc. on to the content area of that layout.
The thing is that when ever i drop the first div "layout" and i try to drop an item to that div, it chooses the wrong droppable area, because it is located "behind" the, as if the z-index is wrong, but the correct area is visible.
i made i jsfiddle as an example of the code, I'am logging the id of the droppable area and the dropped item in the console:
https://jsfiddle.net/g9aragsp/3/
so i would to add one of the "items" to the "insidedrop" instead of the "editor". Ive only set the id "insidedrop" on the first layout for testing purpose.
My html:
<div class="container-fluid">
<div class="row content">
<div class="col-sm-8 col-sm-offset-2">
<div class="row htmlEditor">
<div class="col-sm-3" style="background-color: gray; min-height: 800px;">
<p style="border-bottom: 5px solid black">Layouts</p>
<ul id="layouts" style="list-style-type: none;">
<li id="layout1" class="PickerButton">layout1</li>
<li id="layout2" class="PickerButton">layout2</li>
<li id="layout3" class="PickerButton">layout3</li>
</ul>
<p style="border-bottom: 5px solid black">Items</p>
<ul id="items" style="list-style-type: none;">
<li id="item1" class="PickerButton">button</li>
<li id="item2" class="PickerButton">img</li>
<li id="item3" class="PickerButton">text</li>
</ul>
</div>
<div id="editor" class="col-sm-9" style="background-color: lightgray; min-height: 800px; padding: 20px;">
</div>
</div>
</div>
</div>
</div>
My Javascript:
$(function () {
var $layouts = $("#layouts"),
$items = $("#items"),
$insideDrop = $("#insideDrop"),
$trash = $("#editor");
$("li", $layouts).draggable({
cancel: "button", // these elements won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
$("li", $items).draggable({
cancel: "button", // these elements won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
$trash.droppable({
//accept: "#list1 > li",
drop: function (event, ui) {
console.log(ui.draggable.attr("id"));
console.log($(this).attr("id"));
if (ui.draggable.attr("id") == "layout1")
$("#editor").append("<div class='layout1Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout1imageplaceholder' style='background-color:#8a2be2;height:150px'></div><div class='layout1content' id='insideDrop' style='background-color:bisque;min-height:250px'></div></div>");
if (ui.draggable.attr("id") == "layout2")
$("#editor").append("<div class='layout2Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout2imageplaceholder' style='background-color:#8a2be2;float:right;height:400px;width:40%'></div><div class='layout2content' style='background-color:bisque;float:left;min-height:400px;width:60%'></div></div>");
if (ui.draggable.attr("id") == "layout3")
$("#editor").append("<div class='layout3Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout3imageplaceholder' style='background-color:#8a2be2;float:left;height:400px;width:40%'></div><div class='layout3content' style='background-color:bisque;float:right;min-height:400px;width:60%'></div></div>");
}
});
$insideDrop.droppable({
drop: function (event, ui) {
if (ui.draggable.attr("id") == "item1")
$("#insideDrop").append("<span id='button' style='background-color:#dc143c;padding: 10px; width: 50px'>BUTTON</span>");
if (ui.draggable.attr("id") == "item2")
$("#insideDrop").append("<img src='http://via.placeholder.com/50x50'>");
if (ui.draggable.attr("id") == "item3")
$("#insideDrop").append("<p style='background- color: #284B63; padding: 10px; width: 200px; color: white;'>Insert text here</p>");
console.log(ui.draggable.attr("id"));
}
});
});
I figured out a solution to the problem. instead of targeting a nested "droppable" container. i reused the same function and on hover made javascript return the current hovered object, and then append the item to that specific object as so:
var hoveredObj;
function getid(obj) {
hoveredObj = obj;
}
var $layouts = $("#layouts"),
$items = $("#items"),
$insideDrop = $("#insideDrop"),
$editor = $("#editor");
$("li", $layouts).draggable({
cancel: "button", // these elements won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
$("li", $items).draggable({
cancel: "button", // these elements won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
$editor.droppable({
//accept: "#list1 > li",
drop: function (event, ui) {
console.log(ui.draggable.attr("id"));
console.log($(this).attr("id"));
if (ui.draggable.attr("id") == "layout1")
$("#editor").append("<div class='layout1Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout1imageplaceholder' style='background-color:#8a2be2;height:150px'></div><div class='layout1content' id='insideDrop' onmouseover='getid(this)' style='background-color:bisque;min-height:250px'></div></div>");
if (ui.draggable.attr("id") == "layout2")
$("#editor").append("<div class='layout3Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout3imageplaceholder' style='background-color:#8a2be2;float:left;height:400px;width:40%'></div><div class='layout3content' style='background-color:bisque;float:right;min-height:400px;width:60%'></div></div>");
if (ui.draggable.attr("id") == "layout3")
$("#editor").append("<div class='layout2Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout2imageplaceholder' style='background-color:#8a2be2;float:right;height:400px;width:40%'></div><div class='layout2content' style='background-color:bisque;float:left;min-height:400px;width:60%'></div></div>");
if (ui.draggable.attr("id") == "item1")
$(hoveredObj).append("<span id='button' style='background-color:#dc143c;padding: 10px; width: 50px'>BUTTON</span>");
if (ui.draggable.attr("id") == "item2")
$(hoveredObj).append("<img src='http://via.placeholder.com/50x50'>");
if (ui.draggable.attr("id") == "item3")
$(hoveredObj).append("<p style='background- color: #284B63; padding: 10px; width: 200px; color: white;'>Insert text here</p>");
}
});

Detect MouseUp while something is following the cursor

I have been working on a online file system and I want to have users be able to drag and drop files to a new location. I don't really like how the default drag and drop visuals look so I am not using the conventional methond. This is what I have so far.
This code is in a .php file which is loaded onto the main page with jQuery
<td draggable = "true" ondragstart="dragFolder(event, \''.$folderId.'\', \''.$folderName.'\')">
<div class = "single-folder" onMouseUp = "folderDropUp(event, \''.$folderId.'\');">
<div class = "single-folder-name" id = "single-folder-name-'.$folderId.'">
<span id = "single-folder-rename-'.$folderId.'" class = "rename-folder-hover">
'.$folderName.'
</span>
</div>
</div>
</td>
Here is the dragFolder function that I have being fired from "ondragstart".
function dragFolder(e, folderId, folderName) {
var posX, posY, clicked, isDown = false;
var newFolder;
document.getElementById("folder_drag_image").setAttribute("folderId", folderId);
$(".single-folder").mousedown(function() {
clicked = true;
isDown = true;
followCursor(event);
});
$(document).mouseup(function() {
clicked = false;
$('#folder_drag_image').hide();
if(isDown){
//dropOnFolder(event, document.getElementById("folder_drag_image").getAttribute("folderId"), )
isDown = false;
}
});
$(document).mousemove(function(e) {
if(clicked == true) {
$('#folder_drag_image').show();
$('#folder_drag_image').stop(true, true);
followCursor(event);
}
});
function followCursor(e) {
clicked = true;
posX = e.pageX;
posY = e.pageY;
$('#folder_drag_image').animate({left: posX, top: posY});
}
}
function folderDropUp(e, newFolderId) {
alert(newFolderId);
isDown = true;
}
Basically what it does is it does is when the mouse goes down over a folder div it shows a fake dragging folder with the id of "folder_drag_image" which follows the mouse until the mouse goes up.
The problem comes here when I want to release the folder ontop of the new folder it will be put in. Here is the function for that.
function folderDropUp(e, newFolderId) {
alert(newFolderId);
isDown = true;
}
I took out the ajax because that is not part of the problem. If you look back up the the first code snippet there is a "onMouseUp" listener which triggers a "folderDropUp" event.
The problem is that if I drag my mouse onto folder with the fake drag image the folderDropUp function does not fire. If I just drag my mouse from anywhere else and it does not have the fake drag image when the function will fire off.
I did try jQuery mouseup function but just got the same output.
I don't know how helpful this will be, but by using jQueryUI you could do something like this:
HTML:
<html>
<head>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/base/jquery-ui.css"/>
<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
</head>
<body>
<table>
<tr>
<td>
<div class="single-folder">
<div class="single-folder-name" id="single-folder-name-nhaca">
<div id="single-folder-rename-nhaca" class="rename-folder-hover">
<div>Folder 1</div><div class="folder-drag-image" id="nhaca-drag-image">Folder 1</div>
</div>
</div>
</div>
</td>
<td>
<div class="single-folder">
<div class="single-folder-name" id="single-folder-name-other">
<span id="single-folder-rename-other" class="rename-folder-hover">
<div>Folder 2</div><div class="folder-drag-image" id="other-drag-image">Folder 2</div>
</span>
</div>
</div>
</td>
</tr>
</table>
</body>
</html>
CSS:
.single-folder{
border: 1px solid black;
cursor: pointer;
width: 60px;
}
.folder-drag-image{
position: absolute;
height: 20px;
width: 60px;
border: 1px solid black;
display: none;
}
.droppable-ready-to-receive{
background-color: yellow;
}
JS:
$( document ).ready(function() {
//displaying draggable element based on hovered element
$(".single-folder").on("mouseenter", function(e){
var drag_image = $(this).find(".folder-drag-image");
drag_image.css({"display": "block", "top": $(this).offset().top + 20, "left": $(this).offset().left});
});
//resetting draggable element when moving outside the "single-folder" div
$(".single-folder").on("mouseleave", function(e){
var drag_image = $(this).find(".folder-drag-image");
drag_image.css("display", "none");
});
//resetting draggable element when not being dragged any longer
$(".folder-drag-image").draggable({
stop: function(e) {
var parent = $(this).parents(".single-folder");
$(this).css({"display": "none", "top": parent.offset().top, "left": parent.offset().left});
}
});
//defining what elements can be dropped and what to do when dropped
$(".single-folder").droppable({
accept: '.folder-drag-image',
hoverClass: "droppable-ready-to-receive",
drop: function(e, ui) {
console.log("Dropped folder " + ui.draggable.text() + " into " + $(this).find(".folder-drag-image").text());
//handle folder drop however you need from here
}
});
});
EXAMPLE:http://jsfiddle.net/skdfLk5b/3/
I'm guessing this is far from a good solution to this, but hopefully it helps somehow.

jQuery draggable and scroll not working : mobile devices

i am trying to figure out how to make draggable and scollable work simulatnoeusuly:
http://159.8.132.20/alldevice/
when u try to drag image on either side draggable action also starts, i want that area to be easily scrollable, means when i am scrolling draggble event should not be there
var $drop = $('#canvas-drop-area,#canvas-drop-area1'),
$gallery = $('#image-list li'),
$draggedImage = null,
$canvasp1old = null,
$canvasp2old = null;
$gallery.draggable({
//refreshPositions: true,
scroll: false,
start: function(e) {
$draggedImage = event.target;
$drop.css({
'display': 'block'
});
},
helper: function(e) {
return $('<img src="' + $(this).find('img').attr("src") + '" width="'+imgwidth+'">');
},
stop: function() {
$draggedImage = null;
},
revert: true
});
This might help you.
HTML
$("#draggable").draggable({
snap: true
});
$("#draggable2").draggable({
snap: ".ui-widget-header"
});
$("#draggable3").draggable({
snap: ".ui-widget-header",
snapMode: "outer"
});
$("#draggable4").draggable({
grid: [20, 20]
});
$("#draggable5").draggable({
grid: [80, 80]
});
.draggable {
width: 90px;
height: 80px;
padding: 5px;
float: left;
margin: 0 10px 10px 0;
font-size: .9em;
}
.ui-widget-header p,
.ui-widget-content p {
margin: 0;
}
#snaptarget {
height: 600px;
width: 200px;
}
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<table>
<tr>
<td>
<div id="draggable" class="draggable ui-widget-content">
<p>Default (snap: true), snaps to all other draggable elements</p>
</div>
<div id="draggable2" class="draggable ui-widget-content">
<p>I only snap to the big box</p>
</div>
</td>
<td>
<div id="snaptarget" class="ui-widget-header">
<p>I'm a snap target</p>
</div>
</td>
<td>
<div id="draggable3" class="draggable ui-widget-content">
<p>I only snap to the outer edges of the big box</p>
</div>
<div id="draggable4" class="draggable ui-widget-content">
<p>I snap to a 20 x 20 grid</p>
</div>
<div id="draggable5" class="draggable ui-widget-content">
<p>I snap to a 80 x 80 grid</p>
</div>
</td>
</tr>
</table>
javascript
$(function() {
$("#draggable").draggable({
snap: true
});
$("#draggable2").draggable({
snap: ".ui-widget-header"
});
$("#draggable3").draggable({
snap: ".ui-widget-header",
snapMode: "outer"
});
$("#draggable4").draggable({
grid: [20, 20]
});
$("#draggable5").draggable({
grid: [80, 80]
});
});
For Mobile you can use jquery ui touch punch it will help you and best solution is here
as per my knowledge jquery and jquery-ui is working awesome on 159.8.132.20/alldevice/.

jQuery sortable obtain 2 elements being swapped

I cannot find out how to obtain destination element with jQuery UI sortable.
$("#pages").sortable({
opacity: 0.6,
update: function(event, ui) {
var first = ui.item; // First element to swap
var second = ???? // Second element to swap
swapOnServer(first, second);
}
});
All the options I've tried point to the element being dragged, but not the one it is swapped with: ui.item[0], event.srcElement, event.toElement.
Additionally, this points to the LIST (OL) element.
Saying second I mean following:
Original order is:
| 0 | 1 | 2 | 3 |
We drag element 1 and drop it in position 3. Which will end up with:
| 0 | 3 | 2 | 1 |
So the first element is 1 and the second is 3 (WRONG! See below).
UPDATE: I have realised that I got it wrong. The new order in this case will be.
| 0 | 2 | 3 | 1 |
As a result my question does not really makes sense. Thanks everybody for the help. I'll mark vote and mark an answer.
So the question is how to obtain the second element here?
THE CURRENT WORKAROUND (as there is no term as swapping in sortable) is below. It uses temporary array with orders.
var prevPagesOrder = [];
$("#pages").sortable({
start: function(event, ui) {
prevPagesOrder = $(this).sortable('toArray');
},
update: function(event, ui) {
var currentOrder = $(this).sortable('toArray');
var first = ui.item[0].id;
var second = currentOrder[prevPagesOrder.indexOf(first)];
swapOnServer(first, second);
}
});
Thanks,
Dmitriy.
You can use draggable and droppable instead of sortable to achieve swappable effect. In practise, this will look like this:
(function() {
var droppableParent;
$('ul .element').draggable({
revert: 'invalid',
revertDuration: 200,
start: function () {
droppableParent = $(this).parent();
$(this).addClass('being-dragged');
},
stop: function () {
$(this).removeClass('being-dragged');
}
});
$('ul li').droppable({
hoverClass: 'drop-hover',
drop: function (event, ui) {
var draggable = $(ui.draggable[0]),
draggableOffset = draggable.offset(),
container = $(event.target),
containerOffset = container.offset();
$('.element', event.target).appendTo(droppableParent).css({opacity: 0}).animate({opacity: 1}, 200);
draggable.appendTo(container).css({left: draggableOffset.left - containerOffset.left, top: draggableOffset.top - containerOffset.top}).animate({left: 0, top: 0}, 200);
}
});
} ());
Demo, http://jsfiddle.net/FZ42C/1/.
Try using the serialize function which gives you a hash of the list of items in order.
If you just need the item that the new item go dropped before you can do this:
$("#pages").sortable({
opacity: 0.6,
update: function(event, ui) {
var first = ui.item; // First element to swap
var second = ui.item.prev();
swapOnServer(first, second);
}
});
second will be null if its at the start of the list.
take a look at the "Swapable" jQuery plugin:
http://plugins.jquery.com/project/Swapable
It similar to "Sortable", but only two elements of the selected group are affected: dragged element and dropped one which are swapped. All other elements stay at their current positions. This plugin is built based on existing "Sortable" jQuery plugin and inherits all sortable options.
There's not really a "second" item per se. You have an item, and you are simply placing it in another location. The items around it adjust their positions accordingly. If you want to get an array of all the items, you can use the toArray method.
You can use http://plugins.jquery.com/project/Swapable
but this is not too good plugin
After reviewing the code I have made some behavior improvements:
<!doctype html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title></title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex, nofollow">
<meta name="googlebot" content="noindex, nofollow">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style id="compiled-css" type="text/css">
ul,
li{ margin: 0; padding: 0; }
ul { float:left; height: 120px; background: #CCC; overflow:auto; }
li { list-style: none; float: left; width: 100px; height: 100px; background: yellow; margin: 10px; position: relative; border: "1px solid yellow"}
li.drop-hover .element { opacity: .5; }
.element { position: absolute; width: 100px; height: 100px; background: #00f; color: #fff; text-align: center; line-height: 100px; z-index: 5; }
.element.being-dragged { background-color: #f00; z-index: 9999; }
</style>
<script src="//...jquery-3.6.0.min.js"></script>
<script src="//...jquery-ui.min.js"></script>
</head>
<body style="cursor: auto;">
<ul>
<li class="ui-droppable">
<div class="element a ui-draggable">a</div>
</li>
<li class="ui-droppable">
<div class="element b ui-draggable">b</div>
</li>
<li class="ui-droppable">
<div class="element c ui-draggable">c</div>
</li>
</ul>
<script type="text/javascript">
(function() {
var droppableParent;
var superDrop;
$('ul .element').draggable({
revert: true,
revertDuration: 200,
start: function (event, ui) {
droppableParent = $(this).parent();
ui.helper.css({zIndex: 9999, opacity: 0.5, border: "1px solid black"})
},
stop: function (event, ui) {
ui.helper.css({zIndex: 1, opacity: 1, border: "1px solid blue"})
}
});
$('ul li').droppable({
over: function( event, ui ) {
var draggable_clase = ui.draggable.attr("class");
var clase_actual = $(event.target).find(" > .element").attr("class")
var droppable = $(this).find(" > .element");
superDrop = $(this).find(" > .element")
if(draggable_clase != clase_actual)
droppable.css({border: "3px solid red", backgroundColor : "yellow"});
console.log(draggable_clase + "\n" + clase_actual)
},
out: function( event, ui ) {
var draggable_clase = ui.draggable.attr("class");
var clase_actual = $(event.target).find(" > .element").attr("class")
var droppable = $(this).find(" > .element");
if(draggable_clase != clase_actual)
droppable.css({border: "0px solid red", backgroundColor : "blue"});
var droppable = $(this).find(" > .element");
//droppable.css({border: "0px", backgroundColor : "#00f"});
},
drop: function (event, ui) {
var draggable = $(ui.draggable[0]),
draggableOffset = draggable.offset(),
container = $(event.target),
containerOffset = container.offset();
$(this).find(" > .element").appendTo(droppableParent);
//$(this).find(" > .element").css({zIndex: 1, opacity: 0.5, border: "1px solid black"})
//$(this).find(" > .element").css({opacity: 0.35}).animate({opacity: 1}, 200);
superDrop.css({border: "0px solid orange", backgroundColor : "blue"});
draggable.appendTo(container).css({
left: draggableOffset.left - containerOffset.left,
top: draggableOffset.top - containerOffset.top})
.animate({left: 0, top: 0}, 200);
}
});
} ());
</script>

Categories