I've got a sortable panel (jQuery UI) on my website, but need to limit the amount of elements in each column to a maximum of 12.
I've tried a few things, but can't seem to get it to work. I need to see if 'i' is 12 or greater, and if so, don't update but I can't seem to do it!
Anyone got any advice or can push me the right way?
The jQuery is below!
function updateWidgetData(){
var items=[];
$('.column').each(function(){
var columnId=$(this).attr('id');
$('.dragbox', this).each(function(i){
var collapsed=0;
if($(this).find('.dragbox-content').css('display')=="none")
collapsed=1;
var item={
id: $(this).attr('ID'),
collapsed: collapsed,
order : i,
column: columnId
};
items.push(item);
});
});
var sortorder={ items: items };
//Pass sortorder variable to server using ajax to save state
$.post('includes/updatePanels.php', 'data='+$.toJSON(sortorder), function(response){
if(response=="success")
$("#console").html('<div class="success">Your preferences have been saved</div>').hide().fadeIn(1000);
setTimeout(function(){
$('#console').fadeOut(1000);
}, 2000);
});
}
Sortables
For connected sortables, the solution is to count the elements in each sortable when dragging starts, and disable the ones which have the maximum number of allowed elements. We need to exclude the current sortable, so we can re-order the items within and allow the current element to be dragged.
The problem here is that if we do the above on any of the sortables' events, it's already too late and disabling them won't have any effect. The solution is to do the bind the check to the mousedown event of the items themselves, which will fire before the sortable would get any control. We also need to re-enable all sortables when dragging stops.
Have a look at this example, using <ul> sortables with <li> items, the maximum number of items in each sortable is 3: http://jsfiddle.net/qqqm6/10/
$('.sort').sortable({
revert: 'invalid',
connectWith: '.sort',
stop: function(){
// Enable all sortables
$('.sort').each(function(){
$(this).sortable('enable');
});
}
});
$('.sort li').mousedown(function(){
// Check number of elements already in each sortable
$('.sort').not($(this).parent()).each(function(){
var $this = $(this);
if($this.find('li').length >= 3){
$this.sortable('disable');
} else {
$this.sortable('enable');
}
});
})
Draggables and droppables
The theory is simple, the solution is a bit tricky, there should really be a proper option in jQuery UI to cancel the operation on drop. If there is, but I missed something, please let me know.
Anyways, here's how you check for maximum count in the drop event (maximum of 4 in this example):
$('.drag').draggable({
revert: 'invalid',
stop: function(){
// Make it properly draggable again in case it was cancelled
$(this).draggable('option','revert','invalid');
}
});
$('.drop').droppable({
drop: function(event,ui){
var $this = $(this);
// Check number of elements already in
if($this.find('.drag').length >= 4){
// Cancel drag operation (make it always revert)
ui.draggable.draggable('option','revert',true);
return;
}
// Put dragged item into container
ui.draggable.appendTo($this).css({
top: '0px',
left: '0px'
});
// Do whatever you want with ui.draggable, which is a valid dropped object
}
});
See this fiddle in action: http://jsfiddle.net/qqqm6/
Related
I have the following setup:
$('.my-list').sortable({
handle: '.drag-handle',
start: function(event, ui ) {
//check to see if allow drag and drop
var should_disable = check-code-goes-here ;
if (should_disable) {
//how to disable
}
},
stop: function(event, ui ) {
}
});
When dragging a .drag-handle element, I need to check a condition to see if it is allowed to be dragged and dropped. If yes, go as normal. If not, I would like to disable the whole drag/drop operation. Note that I cannot determine whether a .drag-handle element should be draggable or not at page load, which is why I need to check at the time of each drag/drop operation.
Thanks and regards.
Check this JSFiddle link
http://jsfiddle.net/shuklendu/uacc7/17/
in that example a class 'fixed' added to item which don't want to drag and cancel property set to sortable by
$("#sortable").sortable({
cancel: ".fixed"
});
Trying to have a drop zone with only one item. Items are dragged from a sortable1 ul to a droppable ul, if there is already an item in the drop zone it must first be moved to sortable2 ul, can't get li to move to sortable2. All li will contain a table and they must retain their ids.
http://jsfiddle.net/qLS4s/6/
$("#drop_zone").droppable({
accept: ".connectedSortable li",
hoverClass: "ui-state-hover",
drop: function (ev, ui) {
var drop_id = String('#').concat(jQuery(ui.helper).attr("id"));
$("#drop_zone li").each(function(index, item) {
var drop_zone_id = jQuery(item).attr("id");
if (typeof(drop_zone_li_id) != "undefined")
{
if (drop_zone_li_id != '' && drop_zone_li_id != drop_id)
{
$(drop_zone_li_id).appendTo('#sortable2'); // This should move item but doesn't
}
}
});
$("<li></li>").html(ui.draggable.html()).appendTo(this);
ui.draggable.remove();
}
});
All these string/id manipulations are rather confusing and completely unnecessary. You're overcomplicating it: you can simply .appendTo(otherParent) all the children in the drop event (especially since you're rejecting all natural drops and manually re-creating each element). All you need is something like this:
$("#drop_zone li").appendTo('#sortable2');
Here's an example update: http://jsfiddle.net/z9Ad9/
I know I'm missing something very basic, but when using jQuery in a situation where you have stacked "droppable" DIVs on top of each other (think nested boxes), how do you allow and accept an element drop on the top most DIV and then cancel the drag/drop event so it is not also sent to the other "droppable" DIVs below?
$('#'+objectID+" .task-droppable").droppable({
accept: function(d) {
if(d.hasClass("source-task")||d.hasClass("source-sequence")){ //sequences can contain both sequences and tasks
return true;
} //end if
}, //end accept
activeClass: "isDropDest",
//hoverClass: "isDragging",
//this is used for both drag/drop and item moves
drop: function(event, ui) {
var draggableId = ui.draggable.attr("id");
var droppableId = $(this).attr("id");
//var sender_id = ui.sender.attr('id');
//var receiver_id = $(this).attr('id');
//var item_id = ui.item.attr('id');
//var above_id = ui.item.prev().attr('id');
//var below_id = ui.item.next().attr('id');
//check if this is a drag/drop or a move by looking for the object class
if(!$('#'+draggableId).hasClass('object')) {
$('#'+draggableId).css('top', '0px');
$('#'+draggableId).css('left', '0px');
createObject(draggableId, droppableId);
} else {
//handle the move - do nothing
} //end if
event.stopPropagation();
} //end drop
}); //end droppable
Sorry, not enough coffee today.
Sounds like you may need to use the greedy option
By default, when an element is dropped on nested droppables, each
droppable will receive the element. However, by setting this option to
true, any parent droppables will not receive the element.
$( ".selector" ).droppable({ greedy: true });
Working Example
I have a jquery UI drag and drop for an inventory. It works but i want it to not happen if my inventory already has 20 items in (if it's full).
I'm not that great at javascript/jquery, I can't figure out how to fix my code to do this. I want it to revert back to it's original position if the inventory is full.
Here's the function I'm using to drag/drop
function itemInSpot(drag_item,spot) {
// this is my count. i don't want it to drop an item if it's 20 or more.
var inv_count = parseInt(<? echo count($inv_item) ?>, 10);
var oldSpotItem = $(spot).find('img');
oldSpotItem.appendTo('#inventory').draggable({ revert: 'invalid' });
var item = $('<img />');
drag_item.empty().remove();
item.attr('src',drag_item.attr('src')).attr('title',drag_item.attr('title')).attr('id',drag_item.attr('id')).attr('class',drag_item.attr('class')).appendTo(spot).draggable({ revert: 'invalid' });
}
This is the code that runs the function, set on pageload:
$(document).ready(function() {
$(".weapons,.shield").draggable({ stack: "div", revert: 'invalid'});
$('#inventory').droppable();
$("#weapon_spot").droppable({ accept: '.weapons'})
$('#shield_spot').droppable({ accept: '.shield'});
$('#weapon_spot,#shield_spot,#inventory').bind('drop', function(ev,ui) { itemInSpot(ui.draggable,this); });
});
So how can I add a if inv_count > 19 then revert item back to it's original position in?
Here's a basic jsFiddle example that has six draggable/droppable items, and after the third item is dropped on the target, an alert is triggered and no other draggables are allowed in the droppable area. The elements retain thair draggable property and revert to their original position if a drop is attempted.
jQuery:
$(".ui-widget-content").draggable({
revert: "invalid"
});
$("#droppable").droppable({
drop: function(event, ui) {
$(this).addClass("ui-state-highlight").find("p").html("Dropped!");
$(ui.draggable).addClass('in');
if ($('.in').length == 3) {
$("#droppable").droppable("option", "accept", ".in");
alert('Full!');
}
}
});
I'm working on an app that requires drag-drop. Upon drop, the selected draggable needs to remain present but become disabled. Then the new 'dropped' item is appended with a 'close' button. Upon clicking the close button, the item disappears from the 'droppable' area and re-activates as a draggable.
The issue is that once I disable the draggable (after successful drop), i cannot re-enable that one unique item in my separate 'remove' function. here's some sample code - alot of it is stripped out for purposes of simplicity in hopes of getting advice on this particular issues i'm having.
// DROP: initiate droppables
$(".droppable").droppable({
hoverClass: 'drag-state-hover',
accept: '.draggable li img',
tolerance: 'fit',
drop: function(event, ui) {
var elementID = $(ui.draggable).attr("id") // get the dynamically set li id for each list item chosen
if( $(this).children('img').attr('src') == 'images/elements/blank.gif' ) {
// disable the element once it's been dragged and dropped
$(ui.draggable).draggable( 'option', 'disabled', true );
// turn on the remove link
$(this).find('a.remove').toggle();
}
}
});
// ITEM REMOVE: function for removing items
$('.remove').click(function(e) {
var targetID = $(this).parent('li').attr('id');
$('#' + targetID).children('img').draggable( 'option', 'disabled', false );
e.preventDefault();
});
I've also tried this with no success...
// ITEM REMOVE: function for removing items
$('.remove').click(function(e) {
var targetID = $(this).parent('li').attr('id');
$(".droppable").droppable({
hoverClass: 'drag-state-hover',
accept: '.draggable li img',
tolerance: 'fit',
drop: function(event, ui) {
$(ui.draggable).draggable( 'option', 'disabled', false );
}
});
e.preventDefault();
});
I've spent days searching on google for a solution, but I'm banging my head at this point. any assistance would be much appreciated. Thanks!!
Rather than using .draggable( 'option', 'disabled', false ); you can use .draggable( 'enable' );. I don't know if that will solve your problem, but that's how I'd start with debugging it.
In your remove function, have you tried to re-instantiate the element as a draggable? $('#' + targetID).children('img').draggable{}