Combining draggable and sortable leads to css height issue - javascript

When I drag from one box to another the 'ul.box' class height is too tall sometimes, here's my code:
http://jsfiddle.net/akjfnkfd/
Here's an example which can be reproduced by dragging list items from one box to another, the bottom green on the bar box sticking out is wrong
I've tried to set height: auto but then the ul disappears completely
day_containers.droppable({
accept: ".box-container",
drop: function (event, ui) {
var dropped = ui.draggable;
var droppedOn = $(this);
$(dropped).detach().css({
top: 0,
left: 0,
height: auto /* <---- doesn't fix my issue */
}).appendTo(droppedOn);
},
});

This problem arises due to jQuery draggable/droppable automatically adding inline styles to certain elements (height and width for example). To solve your problem you could either modify only the height with something like ui.helper.first().css({height: ''}); or simply remove the inline styles all together with something like ui.helper.first().removeAttr('style'); and just add it to day_containers.droppable like so:
jQuery
day_containers.droppable({
accept: ".box-container",
drop: function (event, ui) {
var dropped = ui.draggable;
var droppedOn = $(this);
//remove inline styles
ui.helper.first().removeAttr('style');
$(dropped).detach().css({
top: 0,
left: 0,
}).appendTo(droppedOn);
},
over: function (event, elem) {
$(this).addClass("over");
},
out: function (event, elem) {
$(this).removeClass("over");
}
});
Updated fiddle

Related

jQuery UI Droppable - How to allow only 1 element per drop zone, instead of stacking

My current script: https://jsfiddle.net/uoyp37bj/11/
The issue is that currently it's possible to "stack" droppable elements by dragging them on-top of each other. I'm trying to make it so that only the latest dropped element stays there, and any previous elements are removed.
I originally just "hid" the additional items using CSS, but as I'm using an input box to keep track of which items exist in the drop zones, this is no longer possible. Any help would be really appreciated, hoping it's something relatively simple within the jQuery UI API, but currently nothing has worked for me.
$(".social-msl-link-label").draggable({
connectToSortable: ".social-msl-group-list",
revert: "invalid",
helper: "clone"
});
var orderMSLids = [];
var droppableOptions = {
accept: ".social-msl-link-label",
tolerance: 'pointer',
greedy: true,
hoverClass: 'highlight',
drop: function(ev, ui) {
orderMSLids = [];
$(ui.draggable).clone(true).detach().css({
position: 'relative',
top: 'auto',
left: 'auto'
}).appendTo(this);
orderMSLids.push($(this).find('.social-msl-link-label').attr('id'));
$(this).siblings().filter(function() {
return $(this).text().trim() === $(ui.draggable).text().trim();
}).empty();
str = [];
$(".social-msl-links-order li").each(function(index) {
var res = $(this).children().attr('id');
if (res) {
str.push(res);
}
});
var string = str.join(",");
$('#msl-order').val(string);
}
};
$(".social-msl-links-order li.social-msl-drop").droppable(droppableOptions);
$('.social-msl-add').click(function() {
var $droppable = $('<li class="social-msl-drop"></li>').droppable(droppableOptions);
$droppable.insertBefore('.social-msl-add');
});
$('#msl-order').prop('value').split(',').forEach(function(id) {
var $droppable = $('.social-msl-drop.ui-droppable:empty').first();
if (id) {
$('.draggable #' + id).clone(true).appendTo($droppable);
}
});
Just had a thought, but haven't progressed - may be possible to iterate over all of the elements inside the "drop" call, and remove any duplicates. Within this loop, could also check if any drop zones have 2 elements and remove all except 1. Not sure how to script that, but the initial logic makes sense to me.
Instead of appending the draggable to droppable, just replace it's entire content with the draggable like this:
$(this).html(ui.draggable.clone(true).css({
position: 'relative',
top: 'auto',
left: 'auto'
}));
Instead of:
$(ui.draggable).clone(true).detach().css({
position: 'relative',
top: 'auto',
left: 'auto'
}).appendTo(this);

jQuery draggable bug (element not in line with cursor)

EDIT: JSFIDDLE: http://jsfiddle.net/h9yzsqfr/
--
Code:
elem.editor.find("div.ui-widget").draggable(
{
handle:"div.content",
containment:elem.editor,
snap:"*",
start: function(e,ui)
{
$(ui.helper).addClass("dragging");
},
drag: function(e,ui)
{
checkTop(ui);
if($(ui.helper).parents("div.lo-content").length > 0)
{
$(ui.helper).appendTo(elem.editor);
ui.position = { 'top': e.pageY, 'left': e.pageX };
}
},
stop: function(e,ui)
{
oldWidget.saveState($(ui.helper),1);
setTimeout(function() {
$(ui.helper).removeClass("dragging");
}, 300);
}
});
I have some draggable objects within a container defined by elem.editor; however I have some other draggable objects inside div.lo-content which is also inside elem.editor.
Whenever an object inside div.lo-content is dragged, it should reattach to the elem.editor container which is working fine; however as demonstrated in the following GIF (below), it is not setting the position of the draggable object to where the mouse cursor is.
What is a workaround for this problem?
The problem is your width: 100% and the containment option. As soon as its appended to body it stays 100%, but of the body, then it gets smaller but the containment has already been calculated.
One way to solve it is to reset containment. There are probably different ways to do it, one way could be like this:
start: function (e, ui) {
if ($(this).parents(".inner").length > 0) {
$(ui.helper).addClass("dragging");
ui.helper.css({
'width': '100px',
'left': '0px',
'top': '0px'
});
ui.helper.data()['ui-draggable'].containment = [0,0,$('body').width(), $('body').height()]
ui.helper.appendTo("body");
}
},
http://jsfiddle.net/puurqx8r/6/
connectToSortable 
It's a  Selector that Allows the draggable to be dropped onto the specified sortables. If this option is used, a draggable can be dropped onto a sortable list and then becomes part of it. Note: The helper option must be set to "clone" in order to work flawlessly. Requires the jQuery UI Sortable plugin to be included.
Code examples:
Initialize the draggable with the connectToSortableoption specified:
$( ".selector" ).draggable({
connectToSortable: "#my-sortable"
cursorAt:{top: 5, left: t}
});
Use cursorAt: top:, left: and appendTo: 'body'
See my answer with example here.
jQuery draggable shows helper in wrong place after page scrolled
I had the same problem. This is caused by the use of margins to center elements. Try using position absolute!
I removed position:absolute on dragable object

slider tooltip extension without jquery mobile

I'd like to imitate what jquery mobile does here but without loading the library. Just using jquery and jquery-ui (I'd probably stop using jquery-ui if I knew how to create sliders without it).
I want to show the slider value (ui.value) inside the slider handle (ui.handle) and also in a div above the handle, like in the third example (Both options together):
var initialValue = 5;
$("#slider").slider({
min: 1,
max: 50,
value: initialValue,
start: function( event, ui ) {
$(ui.handle).find('.ui-slider-tooltip').show();
},
stop: function( event, ui ) {
$(ui.handle).find('.ui-slider-tooltip').hide();
},
slide: function( event, ui) {
$(ui.handle).find('.ui-slider-tooltip').text(ui.value);
$(ui.handle).text(ui.value);
},
create: function( event, ui ) {
var tooltip = $('<div class="ui-slider-tooltip" />').css({
position: 'absolute',
top: -25,
left: 0,
border: '1px grey'
});
$(event.target).find('.ui-slider-handle').append(tooltip);
$('.ui-slider-handle').text(initialValue);
}
});
But for some unknown reason, manipulating the slider handle is preventing to append anything to it or show/hide it.
I'm also having trouble to set the border of the tooltip, when inspecting the code it adds none automatically, and I don't know why... (jquery-ui ofc but why?)
I just want something like jquery mobile.
http://jsfiddle.net/udxgkbmv/1/
I was going to try to do it with a fancy text-shadow, but that wasn't going to work. I was able to add another inner DIV and appended it after the tooltip DIV. By default both the tooltip DIV and the inner DIV would have the initialValue in it. The slide event now updates both the inner and tooltip DIVs.
The issue with the border not showing up was just missing the border type (e.g., solid). I didn't add any styling to the tooltip or inner, and will leave that up to you.
$(document).ready(function () {
var initialValue = 5;
$("#slider").slider({
min: 1,
max: 50,
value: initialValue,
start: function( event, ui ) {
$(ui.handle).find('.ui-slider-tooltip').show();
},
stop: function( event, ui ) {
$(ui.handle).find('.ui-slider-tooltip').hide();
},
slide: function( event, ui) {
$(ui.handle).find('div').text(ui.value);
//$(ui.handle).text(ui.value);
},
create: function( event, ui ) {
var tooltip = $('<div class="ui-slider-tooltip" />').css({
position: 'absolute',
top: -25,
left: 0,
border: '1px solid gray',
display: 'none'
}).text(initialValue);
var inner = $('<div class="ui-slider-inner" />').css({
position: 'absolute',
top: 0,
left: 0,
display: 'block'
}).text(initialValue);
$(event.target).find('.ui-slider-handle').append(tooltip).append(inner);
//$('.ui-slider-handle').text(initialValue);
}
});
});
JSFiddle: http://jsfiddle.net/udxgkbmv/3/

trigger event when draggable hit edge of containment

jQuery UI draggable plugin allow you to set contain for draggable like
$('.panel').draggable({
handle: ".head",
containment: "parent",
cursor: "pointer"
}
);
My question is how can I detect if div have reached the edge of its containment?
I want to mimic the Windows effect when you drag a panel to edge it go 50% width and 100% height but I don't know how to detect/trigger an event when div reaches the edge.
Thanks
You can use the drag function to return the position of the draggable element while it's being moved. Compare that against the position of the outer edge of the parent and when the two intersect trigger the resizing action.
This fiddle is a very simplified version of what you're looking for, but it should illustrate the basic concept and get you started in the right direction. Hopefully this helps.
http://jsfiddle.net/98jpC/1/
$(function(){
var draggableRight;
var draggableWidth = $('.draggable').width();
var parentWidth = $('#parent').width();
$('.draggable').draggable({
containment: 'parent',
drag: function(e, ui){
draggableRight = ui.position.left + draggableWidth;
if(draggableRight == parentWidth){
$(document).trigger("mouseup");
$('.draggable').css({
width: '50%',
height: '100%',
top: 0,
left: '50%'
});
}
}
});
});

Expand containing div when dragging an item inside it and reaching limits

My page has several items (divs) that are draggable and resizable.
My code for doing this is given below:
part.draggable(
{
containment: 'parent',
drag: function(event, ui){
partIsDragging = true
part.prev().css('top', ui.position.top - 20 ).css('left', ui.position.left )
part.prev().show()
},
stop: function(event, ui) {
partIsDragging = false
}
}).resizable({
containment: 'parent',
handles: 'ne, se, sw, nw,n,w,e,s',
stop: function() {
}
});
The html structure for these is the following:
<body>
<div id="wrapper">
<div class="draggableItem"></div>
<div class="draggableItem"></div>
<div class="draggableItem"></div>
<div class="draggableItem"></div>
</div>
</body>
In my css files i have set body height: 100% and wrapper height: 100%. Width is always fixed for wrapper, width: 950px. I want my div to expand in height when the draggableItem reaches the bottom of the wrapper. Right now when the page is loaded, it has the height as big as the resolution allows it but in case I have more items in the wrapper then everything becomes cluttered and I would like when dragging an item to somehow expand the wrapper in height dynamically. This should happen only if I hit the bottom border.
PS: I am using jQuery and jQuery-ui.
I may have a solution. First off, I replaced part with '.draggableItem' and this where appropriate. Please tell me if that breaks the code in some critical way. In addition, I removed part.prev().css('top', ui.position.top - 20 ).css('left', ui.position.left ) in the code below.
function adjustWrapperHeight(movingObject)
{
var objectBottomPosition = $(movingObject).offset().top+$(movingObject).height()
var wrapperBottomPosition = $("#wrapper").offset().top+$("#wrapper").height()
if(wrapperBottomPosition-objectBottomPosition<distanceBuffer)
{
$("#wrapper").height($("#wrapper").height()+distanceBuffer+1)
}
}
var distanceBuffer = 20;
$('.draggableItem').draggable(
{
containment: 'parent',
drag: function(event, ui)
{
partIsDragging = true
adjustWrapperHeight(this)
},
stop: function(event, ui)
{
partIsDragging = false
}
}).resizable(
{
handles: 'ne, se, sw, nw,n,w,e,s',
resize: function(event, ui)
{
adjustWrapperHeight(this)
var objectRightPosition = $(this).offset().left+$(this).width()
var wrapperRightPosition = $("#wrapper").offset().left+$("#wrapper").width()
if(wrapperRightPosition<=objectRightPosition)
{
$(this).width(ui.originalSize.width)
var containmentLeftPosition = wrapperRightPosition-$(this).width()
$(this).offset({top:$(this).offset().top,left:containmentLeftPosition})
}
}
})
})
The function adjustWrapperHeight(movingObject) adjusts div#wrapper's height depending on a movingObject's bottom position. That is, when movingObject "pushes up" against div#wrapper's borders, it adjusts div#wrapper's height.
I had to use a hack for resizable. The containment: 'parent' for resizable (but not draggable) sets the containment to the container's ORIGINAL height or so it seems. That means as the height of div#wrapper dynamically changes, the constraint set by containment: 'parent' does not dynamically change. To fix this, I removed containment: 'parent' and indeed the entire containment and ensured that div#wrapper's right containment isn't broken within the resize event. Note that you should probably do this with div#wrapper's left containment as well.
Please tell me if this was helpful. Thank you.

Categories