jQuery UI Sortable connected list css issues - javascript

I am using jquery ui sortable with connected lists. I have 2 problems with one most important requirement.
Items goes behind the other list while dragging li.ui-splitselect-item
Dragging item to right(when mouse is too right) creates Horizontal scroll
IMPORTANT: Lists ul.ui-splitselect-list should have overflow-y:auto; So Header of lists stay fixed
and only list items are scrolled
NOTE:
I previous asked this question on STACKOVERFLOW but didnt notice my important requirement was missing from solution so i opened question again with clarity.
JSFIDDLE: http://jsfiddle.net/bababalcksheep/z67Td/
HTML Mockup:
<div class="ui-splitselect ui-helper-clearfix ui-widget ui-widget-content" style="height:200px;" >
<div class="ui-widget-content ui-splitselect-selected">
<div class="ui-widget-header ui-helper-clearfix">
List1
</div>
<ul id="sortable1" class="ui-splitselect-list" style="height: 332px;">
<li class="ui-splitselect-item ui-state-default">
<a class='ui-splitselect-handle-drag'><span class='ui-icon ui-icon-carat-2-n-s'></span></a>
<span class="ui-splitselect-handle-select">TEST-List1</span>
<a class="ui-splitselect-handle-move" href="#"><span class="ui-icon ui-icon-plus"></span></a>
</li>
</ul>
</div>
<div class="ui-widget-content ui-splitselect-available" >
<div class="ui-widget-header ui-helper-clearfix">
List2
</div>
<ul id="sortable2" class="ui-splitselect-list" style="height: 332px;">
</ul>
</div>
</div>
CSS:
.ui-splitselect{font-size:.8em;width:100%!important;text-align:center;margin:0 auto;padding:0}
.ui-splitselect ul{-moz-user-select:none}
.ui-splitselect .ui-widget-header{border:none;font-size:11px}
.ui-splitselect-selected{height:100%!important;float:left;border:none;width:50%;margin:0;padding:0}
.ui-splitselect-available{height:100%!important;width:49.4%;float:left;border-top:none;border-bottom:none;border-right:none;margin:0;padding:0}
.ui-splitselect-list{height:92%!important;position:relative;list-style:none;overflow:auto;margin:0;padding:0}
.ui-splitselect-item{cursor:default;line-height:20px;height:20px;font-size:11px;list-style:none;display:list-item;white-space:nowrap;overflow:hidden;margin:1px;padding:0}
.ui-splitselect-item.ui-sortable-helper{z-index:99999}
.ui-splitselect-handle-select{float:left}
.ui-splitselect-handle-drag{float:left;height:20px;border-top:0;border-bottom:0;cursor:pointer;margin:0 10px 0 5px;padding:2px 5px}
.ui-splitselect-handle-move{text-decoration:none;cursor:pointer;float:right;height:20px;border-top:0;border-bottom:0;margin:0 5px 0 10px;padding:2px 5px}
JS:
$("#sortable1, #sortable2").sortable({
connectWith: ".ui-splitselect-list",
containment: ".ui-splitselect",
scroll: false,
placeholder: "ui-state-highlight ui-splitselect-item"
}).disableSelection();

Try adding appendTo: document.body and helper: clone options for sortable, like this:
$("#sortable1, #sortable2").sortable({
appendTo: document.body,
helper: "clone",
connectWith: ".ui-splitselect-list",
containment: ".ui-splitselect",
scroll: false,
placeholder: "ui-state-highlight ui-splitselect-item"
}).disableSelection();
Js fiddle: http://jsfiddle.net/XpP25/2/
Trick is in creating sorting helper that clones your original element, and then appending it to body element to resolve zIndex issues. All helpers are automatically removed after stop event of draggable and sortable, so it shouldn't mess your code :)
Hope it helps.

I was having a similar issue with nested sortable items. I have multiple sortable containers, that make up a grid, then widgets inside of those sortable containers. Inside of each widget there is a nested sortable container which takes up the width and height. Inside of the nested sortables I can have multiple nested-widgets, spanning the width of the nested sortable.
Here is how one of those sortables would look:
<div class="sortable">
<div class="widget">
<div class="nested-sortable">
<div class="nested-widget"></div>
</div>
</div>
</div>
Now, once I started dragging my nested sortable item, it would go behind every outer widget except for the one containing it. I tried changing the z-index of the items on sort start and no luck. I needed something like jQuery UI's Draggable stack option, which "stacks" the currently dragged item over all other items of the same class.
Here is jQuery UI's draggable stack function on github at line 800.
So, my friend and I modified that code a bit, and called it on the "outer" widget.
$.fn.stack = function () {
// where $(this) == '.widget'
var o = $(this).closest('.sortable').siblings('.sortable').find('.widget');
// create an array of all the widgets
var group = $(o).sort(function(a,b) {
// compare the each set of widgets
return (parseInt($(a).css("z-index"),10) || 1) - (parseInt($(b).css("z-index"),10) || 1);
});
if (!group.length) { return; }
var min = parseInt($(group[0]).css('z-index')) || 1; // first widget's z-index
$(group).each(function(i) {
// increase each widget's z-index by min + $(this) widget's index value
$(this).css('z-index', min + i);
});
// make currently dragged widget's z-index min + length of group
$(this[0]).css('z-index', min + group.length);
}
Then call in sortable start:
$('.nested-sortable').sortable({
start: function(event, ui) {
$(this).closest('.widget').stack();
}
});
Here is my codepen for reference: Nested Grid System

Related

How to implement jquery ui sortable placeholder vertical and horizontal?

I want to show jquery ui placeholder both horizontally(top and bottom) and vertically (left or right) as like my sample image. But currently my code shows only top or bottom placeholder. When I place an element, placeholder appears bottom or top position but when i drop element it placed incorrectly.
Here is my sample code
helper: function (event, ui) {
this.copyHelper = ui.clone().insertAfter(ui);
return ui.clone();
},
placeholder: {
element: function(currentItem) {
return $('<div style="height: 5px; padding: 0; background-color: #F78828;" ></div>');
},
update: function(container, p) {$(container.element[0]).addClass("place_here_div");
return;
}
},
Here row column just an example. It may be any kind of element.(div, paragraph, span etc.)
I don't know if my answer will be useful for you, as it's idea with native HTML5 drag'n'drop. You need to introduce an additional element "row":
<div class="root">
<div class="row">
<div class="col-3">component 1</div>
<div class="col-3">component 2</div>
<div class="col-3">component 3</div>
<div class="col-3">component 4</div>
</div>
<div class="row"><div>
<div class="row"><div>
</div>
And then subscribe on dragover event. In the event, you will have property target and then you can define where you are. Then find the closest drop container (row or root) to target. If in the row - place vertically, otherwise place horizontally.

How to clone jQueryUI draggable object

I currently have some jquery draggable objects which are located in a content slider which has multiple pages. These objects are dragged out of the content slider pages and into an 'answer' box which is located outside the slider. This works up until you change pages in the content slider, the answers then 'disappear' out of the answer box until you return to the page in the slider that they were originally on. I need to find a way to create a 'copy' of the draggable object that will stay in the answer box even when the page changes in the slider.
After doing some research I found the helper: clone option but can't seem to get it to stay in the answer box once it's been cloned. Another option I looked at was moving the draggable to a new container using 'appendTo' outside the slider once it had been dropped in the answer box - this again came with it's own problems. I really don't know what to do any more with this after having spent multiple hours trying to fix it!
The code and a screenshot are below... thanks in advance!
Javascript/jQuery
// initialisation for all things regarding the drag and drop.
function init_dragDrop(){
// setup draggable interface
$(".answer").draggable({ snap: ".destinationBox", snapMode: "inner", revert: "invalid"});
$( ".destinationBox" ).droppable({
drop: function( event, ui ) {
var matchedQuestion = null;
var droppedQuestion = $(this).prevAll(".question:first").html();
$.each(questionList, function(){
if(this.body === droppedQuestion){
matchedQuestion = this;
return false;
}
});
var draggedAnswer = $(ui.draggable[0]);
matchedQuestion._onCorrect = function(){draggedAnswer.css("backgroundColor", "green"); questionList[++currentQuestion].enable();}
matchedQuestion._onIncorrect = function() {
draggedAnswer.css("backgroundColor", "red");
//resets answer to original position in the runbook, and revoves red background color
$("#reset").click(function () {
draggedAnswer.animate({
backgroundColor: "transparent",
top: "0px",
left: "0px"
});
});
}
HTML
<div id="questionDiv">
<div class="question textbox" id="q1">1. Assemble the Crisis Management Team</div><div class="destinationBox"></div>
<div class="question textbox" id="q2">i. Set up the emergency conference line</div><div class="destinationBox"></div>
</div>
<div class="content-switcher" id="answerDiv3" >
<h2>Key Contacts</h2>
<table>
<tr>
<td><p><strong>Contact</strong></p></td>
<td><p><strong>Telephone Number</strong></p></td>
<td><p><strong>Email Address</strong></p></td>
</tr>
<tr>
<td><p>Managing Director</p></td>
<td><div class="dragDropSmallBox answer a1">0123456789</div></td>
<td><div class="dragDropSmallBox answer a2">M.D#acme.com</div></td>
</tr>
</table>
</div>
Screenshot

masonry on bootstrap elements got bumped down to new row

The nature of the elements are that each one will be varied in height (due to image and the title) and its height is unknown before applying masonry. Though the width of each element is fixed with .col-lg-3.
On the rendered page where each row has 4 elements, the 5 element is visually on a row on its own and the 6, 7, 8 got pushed down to 3rd row.
html code
<div class="section-details">
<div class="container">
<div class="">
<div class="masonry" id="elements" data-reference="0">
<!-- elements will be pulled over dynamically -->
</div>
</div>
</div>
</div>
and the content of each new element is wrapped in something like the following
<div class="col-lg-3 element">
</div>
css
.element {
padding: 10px 10px 0px;
}
javascript code
// layout the elements
var layout = function(elements, $container, selector) {
$container.imagesLoaded(function () {
$container.masonry({
itemSelector: selector,
columnWidth: selector,
isAnimated: true,
animationOptions: {
duration: 750,
easing: 'linear',
queue: false
}
}).append(elements).masonry('appended', elements, true);
});
};
and it's got called in the following way
layout(elements, $('#elements'), '.element');
So anything could go wrong here?
Debugged into the masonry source code and figured out the cause, it's how the elements got prepared that matters - each of the element that got pushed to the elements array should be an HTMLElement. And once I got that fixed, the issue was gone.

jQuery draggable isn't draggable after being dropped

I have two divs, each containing a list of quantities and items. The items are draggable and the div containing the items is droppable. If an item of the same name appears in that div, that item cannot be dropped on that div again. Eventually I will be controlling the number of items that are moved, but I'm just trying to get this part to work for now.
The problem I'm having is that once I drop an item on the div, I can no longer drag it. I've tried adding draggable() to the new item that I am creating, but that just made things weird.
The exact same code worked when I was adding an li to a ul, but I wanted to move just the name of the item and not the quantity, so I am using divs instead of li.
Here is a jsfiddle of my code: http://jsfiddle.net/imjustabill/eJ4KH/
And here are the pertinent parts
$(function () {
$("#inventory1 .item").draggable({
appendTo: "body",
helper: "clone"
});
$("#inventory2").droppable({
drop: function (event, ui) {
var item = ui.draggable.attr("data-item");
var qty = ui.draggable.attr("data-qty");
var itemDesc = ui.draggable.text();
if (!$(this).find("[data-item='"+item+"']").length) {
$("<div class='qty'></div>").text(qty).appendTo(this);
$("<div class='item ui-draggable' data-qty='"+qty+"' data-item='"+item+"'></div>").text(itemDesc).appendTo(this);
}
}
});
$("#inventory2 .item").draggable({
appendTo: "body",
helper: "clone"
});
$("#inventory1").droppable({
drop: function (event, ui) {
var item = ui.draggable.attr("data-item");
var qty = ui.draggable.attr("data-qty");
var itemDesc = ui.draggable.text();
if (!$(this).find("[data-item='"+item+"']").length) {
$("<div class='qty'></div>").text(qty).appendTo(this);
$("<div class='item ui-draggable' data-qty='"+qty+"' data-item='"+item+"'></div>").text(itemDesc).appendTo(this);
}
}
});
});
<div id="inventory1">
<h4>Inventory 1</h4>
<div class="qty">7</div><div class="item" data-qty="7" data-item="item1">Item 1</div>
<div class="qty">5</div><div class="item" data-qty="5" data-item="item2">Item 2</div>
<div class="qty">2</div><div class="item" data-qty="2" data-item="item3">Item 3</div>
<div class="qty">9</div><div class="item" data-qty="9" data-item="item4">Item 4</div></div>
<div id="inventory2">
<h4>Inventory 2</h4>
<div class="qty">4</div><div class="item" data-qty="4" data-item="item1">Item 1</div>
<div class="qty">2</div><div class="item" data-qty="2" data-item="item5">Item 5</div></div>
Any ideas? Thank you.
The Problem is, that the Draggable calls it's destroy() on drop so you loose your dragging ability. One dirty way is to make your dropped element draggable again:
$("#inventory2").droppable({
drop: function (event, ui) {
var item = ui.draggable.attr("data-item");
var qty = ui.draggable.attr("data-qty");
var itemDesc = ui.draggable.text();
if (!$(this).find("[data-item='"+item+"']").length) {
$("<div class='qty'></div>").text(qty).appendTo(this);
$("<div class='item ui-draggable' data-qty='"+qty+"' data-item='"+item+"'></div>").text(itemDesc).draggable({appendTo: "body", helper: "clone"}).appendTo(this);
}
}
});
But it won't be droppable again.
Do you have to use draggable/droppable?
Just use jQueryUI's own Sortable with connected lists. Its already perfectly implemented to jQueryUI:
jQueryUI Sortable with connected lists

Jquery draggable and droppable, switch to originalPosition another draggable

I'm working with Jquery UI draggable and droppable.
I have a container that accepts all the divs of the .category1 class, and what I have to do is:
If I put a div into the container that already has another div, revert the old div back to the
original position.
This is the code I have:
$(document).ready(function () {
$(function () {
$("#Part1").draggable({ revert: "invalid", snap: "#Part1Container", snapMode: "inner"
});
$("#Part1Container").droppable({
accept: ".category1",
drop: function (event, ui) {
//Some other logic
}
}
});
And the Html
<div id="Part1" class="ui-widget-content category1"></div>
<div id="Part2" class="ui-widget-content category1"></div>
I want the Part1 to be back to the original position if I insert Part2 in the container, and viceversa. And this has to work for n divs of the same class.
Any suggestions?
Tnx in advance :)
I solved it by assigning it a class when it goes into the container the first time, and then delete it when moving another div
$(".inCategory2").animate({
top: 0,
left: 0
}).removeClass("inCategory2");
ui.draggable.addClass("inCategory2");

Categories

Resources