jQuery sortable containment breaks when scrolling - jquery-ui

I'm working on a widget that uses a sortable list and I'm stuck in this small issue arising when the container is scrolling. I don't want the <li> to go outside of the <ul>, so I set containment: "parent" when applying sortable to the list.
The containment works just fine when the container is not scrolling. But when it does, if an item is dragged to any of the ends of the list not displayed, the containment stops working as expected and the item moves beyond.
I'm not sure if I'm missing something of the sortable API, or this is just a jquery-ui bug. These are the options I have set:
$(".sortable").sortable({
axis: "y",
containment: "parent",
cursor: "move",
items: "li",
tolerance: "pointer",
});
The CSS of the container is as follows:
.list-holder {
max-height: 250px;
overflow-y: auto;
overflow-x: hidden;
}
This jsFiddle shows both cases, with and without scrolling.

Add this code to your ul
ul{
max-height: 240px;
overflow: hidden;
}
The element scrolls down because the actual list height is still present in the page even if it is not visible to us.
Here is the modified fiddle

Related

Icroll.js Child Element overflow: scroll not working on IOS

Im using Iscroll.js for a project that requires all elements to fit the height of the screen with a large horizontal scroll. My issue is there are certain elements that overflow vertically depending on the amount of content they have.
I have used "overflow-y: scroll" on these elements and it works fine on desktop browsers but not on mobile.
I have tried the webkit prefix -webkit-overflow-scrolling: touch but that also does not work.
the css for my vertical scroll elements is:
white-space: nowrap;
overflow-x: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
You can find the site at http://govanhillpeopleshistory.com/dev/
For anyone that interested I managed to fix this by reverting to IScrolll = and using multiple nested scrollers inside my main scroller. Used a similar solution to this question.
Basically create an array to hold all of your IScroll objects, iterate over every element you want to be scrollable, grab its ID and and then create a new array element and Iscroll Object using the ID you Grabbed. Heres my code:
articleBottomState.find('.cards-wrapper').each(function(){
$(this).find('.content-card').each(function(){
//console.log(counter++);
var currentCardID = '#' + this.id; //Get Scrollable Areas ID
console.log(currentCardID);
//Add another array element to the myscrollers array
myscrollers[vertScrollCOunter++] = new IScroll(currentCardID, {
scrollX: true,
scrollY: true,
mouseWheel: true,
momentum: false
});
});
});

jQuery UI selectable and scrollbar

I have a div with divs inside. The outer one has overflow-y: auto;, so with many internal items the right scrollbar appears. After doing $('#container').selectable(); when I press left mouse button over the scrollbar, it doesn't scroll, but a dotted frame for selecting is shown.
I have found this solution: JQuery UI Selectable plugin: Make scroll bar not selectable when div overflows
Unfortunately, it doesn't work for me, because when I scroll to the bottom, the items stop being selectable. (Though the top ones continue). So, the question is: how make the scrollbar... mmm... a scrolling bar, without splitting the container into 2 divs.
Well, it seems to be all browsers problem: when you click on a scrollbar, a mouse event is fired. This is the real problem, jQuery UI just doesn't solve it. Let's fix it on our own in the jQuery UI .js file (not applied to the min version as it should be obfuscated AFAIK).
Add this condition
if (event.pageX > $(event.target)[0].clientWidth + $(event.target).offset().left)
return;
right after the
_mouseDown: function(event) {
I have seen a lot of such hacks with HasScrollbar() detectors, but don't get why didn't they just sum up client width (that is without scrollbar) and offset to make it relative to the document and compare with pageX. For me it works perfectly.
Use a wrapper div for this , Its working fine for me.
.selectable-wrapper { border-radius: 5px; min-height: 200px; max-height: 200px; overflow-y: auto; border: 1px solid #D1D1D1;}
.selectable { list-style-type: none;padding: 5px;}
<div class="selectable-wrapper">
<ul class="selectable">
</ul>
</div>

Draggable element hidden outside container

Using jQuery UI, I am trying to create an interface with two scrollable containers, each containing many draggable elements. The user can drag an element from one container to the other.
The dropping feature is not an issue. When dropped, the element is detached and recreated in the right place under its new parent.
My problem is that the draggable element cannot be displayed outside its container when the container has position:relative; applied, so while dragging, the element will disappear when it is moved outside the container boundaries.
This default behaviour makes sense, as normally the user would want to drag an element inside its container. As a workaround I had assumed the solution would be to use the draggable property 'appendTo', which I thought would move the element outside its container, but unfortunately this hasn't seemed to have had any effect.
DOM: (each view is scrollable and each container has position:relative and is as large as it needs to be to hold all elements)
BODY
VIEW 1
CONTAINER
DRAGGABLE ELEMENTS
VIEW 2
CONTAINER
DRAGGABLE ELEMENTS
Javascript:
$('div.card').draggable({
appendTo: 'body',
scroll: false //stops scrolling container when moved outside boundaries
});
Please see JSFiddle for a simplified explanation of the problem. I didn't want to bloat the example with droppable code, so this just illustrates the dragging issue. http://jsfiddle.net/Em7Ak/
Many thanks in advance.
I'm not sure if this will fix your exact problem, but I came across this question looking for the same answer and this is what I found.
In the options for .draggable(), pass in helper:'clone' to make a clone of the item automatically so that it can be dragged out of the container. And use appendTo:'body' to put it at the end of the <body> tag. So in my case, my options look somewhat like this, adding in revert:'invalid' to cause it to spring back if it isn't dropped somewhere valid:
jQuery(".myselector").draggable({
helper: 'clone',
revert: 'invalid',
appendTo: 'body'
});
use the "clone" helper and hide the item while dragging it and show it again on stop.
$(".removalbe-recom").draggable({
appendTo: "body",
helper: "clone",
revert: "invalid",
cursor: "move",
containment: "document",
zIndex: 10000,
scroll:false,
start: function (event, ui) {
$(this).hide();
},
stop: function (event, ui) {
$(this).show();
}
});
I had similar problem some months ago.
My need was to be able to use the auto scrolling of one big container from others
Here is my question for more details, JqueryUI, drag elements into cells of a scrolling dropable div containing large table
I found a workaround. The idea is to append the element clone to the scrollable container during the helper construction callback, then append the helper to the body using a setTimeout function after 1ms. The helper position must be mapped on the mouse position to avoid offset problem.
Here is my solution (JSFiddle seems to be down now, try it later if no code is displaying in the windows) : http://jsfiddle.net/QvRjL/134/
$('[id^="drag-"]').each(function() {
$(this).draggable({
opacity: 0.7,
cursorAt: { top: 15, left: 50 },
appendTo: 'body',
containment: 'body',
scroll: true,
helper: function(){
//Hack to append the cartridge to the body (visible above others divs),
//but still belonging to the scrollable container
$('#container').append('<div id="clone" class="cartridge">' + $(this).html() + '</div>');
$("#clone").hide();
setTimeout(function(){
$('#clone').appendTo('body');
$("#clone").show();
},1);
return $("#clone");
}
});
});​
Add position:absolute to card style:
div.card {
position:absolute;
width:100px; height:50px;
border:1px black solid;
background-color:orange;
text-align:center; vertical-align:middle;
}

jQuery autocomplete list position change

I would like to move position a bit to the left of my jQuery UI suggestion list. Here function and everything work very fine
Unfortunately I have no idea how to move that list a bit to left align left about 10px the page is responsive that is why scared that how to move left.
I think this is the documentation: http://docs.jquery.com/Plugins/Autocomplete/autocomplete.
You can set the style in this class
.ui-menu .ui-menu-item a.ui-state-hover, .ui-menu .ui-menu-item a.ui-state-active
{
margin-left: -10px !important;
}
Try adding this in your CSS and not in the jQuery-ui CSS file
you can add margin-left: -11px; in to the list DIV

jQueryUI: Move sortable's element into droppable and back (or mootools alternative)

I have one sortable which contains tiles. In addition, I have a bunch of droppables. I want the following interaction:
The user can drag tiles out of the sortable onto some droppable. Ideally, this would move the tile out of the sortable and append it to the droppable. In addition, the droppable should not accept anything anymore, i.e. there may be at most one tile on one droppable. I tried it in this fiddle http://jsfiddle.net/yXeMw/2/ but can't get the "move" to work.
Once that works, the user should also be able to move the tile out of the droppable back to the sortable, which I tried out here: (removed link due to 2 links limit, was version 3 of that same fiddle.) but fails too. (I only tried with an alert as I think the "move from .. to .." part should be the same.) See update 1.
I've been trying this for a few days and just can't figure it out.
PS: I've read tons of similar questions here on SO, but none is really the same as my issue, i.e. moving the element from the sortable to the droppable.
Edit: I would welcome an alternative solution using Mootools aswell.
Update 1: The droppable -> sortable direction only didn't work because my tiles inside the sortable had the float: left attribute which effectively made the sortable itself be of size 0px thus impossible to hover. Fixed fiddle: http://jsfiddle.net/yXeMw/5/
Update 2: Although I found a workaround (see my answer), I would still like to have a solution which moves the element. I couldn't get any of appendTo or append to work.
So, I found out how to emulate it. I am not 100% satisfied with this solution because it doesn't really move the element, so I will accept any better solution.
Rather, I create a new element, remove the old one and hide the helper. Both clone and appendTo don't seem to work.
Here is the fiddle: http://jsfiddle.net/VyfkE/1/
Aswell as the code in case the fiddle will get lost.
html:
<div class="slot">Drop one here</div>
<div class="slot">Or one here</div>
<div class="sortable">
<div class="tile">item 1</div>
<div class="tile">item 2</div>
<div class="tile">item 3</div>
</div>
css:
.slot {
background-color: forestgreen;
width:100px;
height:100px;
border: 1px solid black;
}
.sortable {
display:table-row;
background: #44F;
}
.tile {
display:table-cell;
background: firebrick;
border: 1px solid black;
width: 50px;
height: 25px;
}
and finally the javascript:
$(".slot").droppable({
drop: function(ev, ui) {
// Only want one tile per droppable!
if ($(this).children().length === 0) {
// Create the new element which will be inside the droppable.
cl = $('<div>').addClass('tile').text(ui.draggable.text()).css({
background: 'cornflowerblue'
});
// Make it draggable back into the sortable.
cl.draggable({
connectToSortable: '.sortable',
helper: 'clone' // <-- This is important!
});
$(this).append(cl);
// And remove the element from the sortable.
ui.helper.hide();
ui.draggable.remove();
}
}
});
$(".sortable").sortable({
connectWith: '.slot',
revert: true,
helper: 'clone', // <-- This is important, again!
receive: function(ev, ui) {
// If we get some item from a droppable, remove it from there.
ui.item.remove();
}
});

Resources