How to get an object of the new element, which was placed instead of previous object in jQuery UI sortable? - jquery-ui

The source:
<ul class="supercategory">
<li>
<div class="supcat">
<h4>
<a class="new" href="/header1.html">header 1</a>
</h4>
<ul class="category">
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
</li>
<li style="" class="">
<div class="supcat">
<h4>
<a class="new" href="/header2.html">Header 2</a>
</h4>
<ul class="category">
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
</li>
</ul>
<div id="test">
</div>
a lit bit of css:
ul.supercategory { background: lightblue; }
.new{ background: yellow; }
and a jQuery UI force:
$('.supercategory').sortable({
cursor: 'move',
axis: 'y',
revert: true,
stop: function (event, ui) { }
});
I know that to get an object of the current dragged element I simply must to make something this:
stop: function(event, ui) { var obj = ui.item; }
But how to get an object of placed element instead of I dragged to new position?
For example, if I dragged first li on the new position (it will 2nd li) the second li was placed on the place instead of my, how to get this element as object in jQuery UI sortable?
Watch my fiddle: http://jsfiddle.net/Stasonix/jCMuQ/1/
upd 1. First of all a fiddle. http://jsfiddle.net/Stasonix/jCMuQ/5/
Than code:
var is_received = false;
$('.supercategory').sortable({
cursor: 'move',
axis: 'y',
revert: true,
receive: function(event, ui){ is_received = true; },
stop: function (event, ui) {
is_received = true;
},
deactivate: function(event, ui) {
if (is_received){
$('#test').text(ui.item.find('.new').attr('href'));
is_received=false;
}
}
});
Well... still need a solution, it's not works seems.

You can try this to get the new object you dragged by keeping track of your object's index / position, and by using the events start and deactivate like this:
// Define static variables to keep track of the index / position of your dragged object
var prev_index = null; // Previous index / position of your dragged object
var next_index = null; // Next index / position of your dragged object
$('.supercategory').sortable({
cursor: 'move',
axis: 'y',
revert: true,
start : function(event, ui) {
prev_pos = ui.item.index();
},
deactivate : function(event, ui) {
next_pos = ui.item.index();
},
stop : function(event, ui) {
// Your new object: "el"
var el = null;
if(next_pos > prev_pos)
el = $(".mydrag").get(next_pos-1); // Your previous object has been dragged! Your previous object was initially above your new object (Dragging downward)
else if(next_pos<prev_pos)
el = $(".mydrag").get(next_pos+1); // Your previous object has been dragged! Your previous object was initially below your new object (Dragging upward)
else
el = $(".mydrag").get(prev_pos); // Your previous object was not dragged and is at the same position
$('#test').text($(el).find('.new').attr('href'));
}
});
The thing is,
if your object was dragged successfully, depending on whether you drag your object downward or upward, the new object you're looking for will be located above or below the dragged object, so: at the new index / position of your dragged object -1 / +1
however, if your object was not dragged successfully, there is "no new object", so your new object is your dragged object.
Make sure to add the class .mydrag to your draggable li elements:
<ul class="supercategory">
<li class="mydrag">
<div class="supcat">
<h4>
<a class="new" href="/header1.html">header 1</a>
</h4>
<ul class="category">
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
</li>
<li class="mydrag">
<div class="supcat">
<h4>
<a class="new" href="/header2.html">Header 2</a>
</h4>
<ul class="category">
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
</li>
</ul>
<div id="test">
</div>
I'm not sure if this solution is what you were exactly looking for...
You can ask me question if I was not clear.

Related

jquery ui drop event did not fire for last li item between 2 lists

I am using a draggable and droppable UL LI items that makes it possible to drop the list items from one to another. When an item is dropped I need to handle them using jquery-ui droppable drop event. This works for all the items excepts the last LI element in the List.
My HTML code:
<ul class="ui-helper-reset">
<li id="event-start1" class="ui-state-default">
List Item 1
</li>
<li id="event-drag1" class="ui-state-default">List item 2</li>
<li id="event-stop1" class="ui-state-default">
List Item 3
</li>
</ul>
<br />
<ul class="ui-helper-reset">
<li id="event-start2" class="ui-state-default">
List Item 1
</li>
<li id="event-drag2" class="ui-state-default">List item 2</li>
<li id="event-stop2" class="ui-state-default">
List Item 3
</li>
</ul>
My javascript code:
$(function () {
$(".ui-state-default").draggable({
helper:'clone',
cursorAt:{top:-10,left:-10},
stop:function(event, ui){
alert(event.originalEvent.target.id)
}
});
$(".ui-helper-reset li").droppable({
drop: function (event, ui) {
if ($(event.originalEvent.target).hasClass("ui-droppable"))
alert("drop");
}
});
});
http://jsfiddle.net/b7j2k1Ln/22/
Why is the event not triggered for the last LI and how to resolve this?
Thanks in advance

Combinate JQuery UI sortable and draggable with Bootstrap Tab navigation

I try build page based on Bootstrap with JQuery UI sortable list.
I have one list in global space and two lists in Tabs
and I like to drag items from external list and drop it to tab navigation for adding into list
However when I switch to bootstrap tab navigation the external item on drop disappear but doesn't appear in tab list
this is my example based on JQ UI "Connect list with Tab"
This is my JS FIDDLE
$(function() {
$( "#sortable0, #sortable1, #sortable2" ).sortable().disableSelection();
var $tabs = $( "#tabs" );//.tabs();
$('#myTab a:last').tab('show');
var $tab_items = $( "ul:first li", $tabs ).droppable({
accept: ".connectedSortable li",
hoverClass: "ui-state-hover",
drop: function( event, ui ) {
var $item = $( this );
var $list = $( $item.find( "a" ).attr( "href" ) )
.find( ".connectedSortable" );
ui.draggable.hide( "slow", function() {
$tabs.tabs( "option", "active", $tab_items.index( $item ) );
$( this ).appendTo( $list ).show( "slow" );
});
}
});
});
HTML
<div id="external-tab">
<ul id="sortable0" class="connectedSortable ui-helper-reset">
<li class="ui-state-default">ExItem 1</li>
<li class="ui-state-default">ExItem 2</li>
<li class="ui-state-default">ExItem 3</li>
</ul>
</div>
<div id="tabs" class="tabbable">
<ul id="myTab" class="nav nav-tabs">
<li>Nunc tincidunt</li>
<li>Proin dolor</li>
</ul>
<div class="tab-content">
<div id="tabs-1" class="tab-pane">
<ul id="sortable1" class="connectedSortable ui-helper-reset">
<li class="ui-state-default">Item 1</li>
<li class="ui-state-default">Item 2</li>
<li class="ui-state-default">Item 3</li>
</ul>
</div>
<div id="tabs-2" class="tab-pane">
<ul id="sortable2" class="connectedSortable ui-helper-reset">
<li class="ui-state-highlight">Item 1</li>
<li class="ui-state-highlight">Item 2</li>
<li class="ui-state-highlight">Item 3</li>
</ul>
</div>
</div>
</div>
It's a shame nobody else got to your question in the past year... I'm guessing this is no longer relevant for you personally, but maybe we can help to resolve this issue for any other user searching on Google for solutions to include jQuery UI's API for Draggable/Droppable items, integrated with Bootstrap's tabbed component.
If I'm reading your question correctly, you'd like to be able to drag items from the external list into either of the two tabs. If your problem is similar to the one I'm personally tackling at the moment, you might also want to drag items from tab one into tab two, and vice-versa. I've updated your fiddle with a solution that accommodates both of these needs. The lists are also sortable, as they were previously, and the classes of items dragged from one space to the other are retained as well.
Items I might consider adding in the future are:
The ability to drag not only onto the tab, but also the space below it
Adding all attributes from the parent element dragged, not just the class list
However, for the moment, all I've done is to rectify the solution you posted.
The updated fiddle is here: http://jsfiddle.net/cr8s/96dsB/30/
Also, since the Internet is a fickle place and things disappear all the time, here's the updated JS (I left your HTML unchanged, and that's already in the question above):
$(function() {
$('.tab-pane > ul').sortable().disableSelection();
var
$tabs = $('#tabs'),
$tabItems = $('#myTab > li', $tabs);
$('#myTab a:last').tab('show');
$tabItems.droppable({
accept: ".connectedSortable li",
hoverClass: "ui-state-hover",
drop: function(event, ui) {
var
$item = $(this),
href = $item.children('a').attr('href'),
$list = $(href).find('.connectedSortable');
console.log($list);
$list.append($('<li />').html(ui.draggable.html()).attr('class', ui.draggable.attr('class')));
$list.closest('.tab-pane').addClass('active').siblings().removeClass('active');
$item.addClass('active').siblings().removeClass('active');
}// drop(event, ui)
});// $tabItems.droppable()
$('#external-tab > ul > li').draggable({
appendTo: 'body',
helper: 'clone'
});
});// end of doc ready
Hope that solves this problem for some folks! It certainly gets me closer to solving my own use case, and I'll likely continue to update the fiddle linked above as I add additional features like the two I mentioned earlier.

how to disable a specific element of selectable list

I want to disable a specific element of a selectable list.
I am able to disable the whole list, but when I try with specific element, it doesn't work.
$('#disableButton').click(function(){
$('#selectable li#b ').selectable('disable');
});
http://jsfiddle.net/Komlan/RYWaZ/1/
Here is my code
//reset seats
function resetSelect(){
var options = { filter: "li.selectable" };
$( "#selectable").selectable(options);
}
//Ajax get taken seats
$('input[name="choice"]').change(function(){
resetSelect();
var sc_id = $('input:radio[name=choice]:checked').val();
$.ajax({
url: 'seatings.php',
data:{ sc_id:sc_id},
type: "POST",
dataType:'text',
success: function(data){
var id = data.split(",");
for (var i=0;i<id.length -1;i++){
alert(id[i]);
var string = "#"+id[i];
$(string).css("color","red");
$('#selectable li'+string).removeClass("selectable ui-selected");
}
var options = { filter: "li.selectable" };
$( "#selectable" ).selectable('destroy').selectable(options);
}
});
});
In summary, I'm getting a series of id and disable them one after the other, every time there is a change on my radio button group.
There is no straight way to do this (AFAIK), but here's a little hack you can use (and remember, it's just a hack and maybe not the best):
Add the css class "selectable" (or whatever you want):
<ol id="selectable">
<li class="ui-widget-content selectable" id="ok"> 1</li>
<li class="ui-widget-content selectable"> 2</li>
<li class="ui-widget-content selectable"> 3</li>
<li class="ui-widget-content selectable"> 4</li>
<li class="ui-widget-content selectable"> 5</li>
<li class="ui-widget-content selectable"> 6</li>
<li class="ui-widget-content selectable"> 7</li>
</ol>
And then use a filter on that css class:
// Create a filter to only make <li> with the specified css class, selectable.
var options = { filter: "li.selectable" };
$( "#selectable" ).selectable(options);
$('#lol').click(function(){
console.log('dsfds');
// Remove/add (toggle) the class used in the filter on the <li> you want to remove the selectable.
// (Also remove the ui-selected in case it's selected.)
$('#selectable li#ok').toggleClass("selectable").removeClass("ui-selected");
// Now destroy the selectable and re-create it with the filter again.
// We removed the css class from a <li> used in the filter, so it won't be selectable again.
$( "#selectable" ).selectable('destroy').selectable(options);
});
Updated: http://jsfiddle.net/RYWaZ/7/
References:
Selectable filter
.toggleClass()
Actually you can achieve this now.
You've got to add the class you want to your item, for example "unselectable", and use this css trick in your filter option : item:not(.unselectable)
Html :
<ul id="selectable">
<li class="unselectable"> 1</li>
<li> 2</li>
<li> 3</li>
</ul>
Jquery :
$( "#selectable" ).selectable({
filter:"li:not(.unselectable)"
});
You'll be able to select all the li children of #selectable, excepted the li which has the .unselectable class. Then you just have to toggle this class when it is necessary.

jquery ui sortable, div block in first item not visible

I want to make the div - "small_box" in the first item of sortable list to be always not visible. I tried with jquery first() but that works only once and only for one and same element whenever it's dragged. How can i simple make it back to be visible when I dragg it into other than first place and then make invisible "small_box" for the item which jumps in the first place?
I put the live example here: http://jsfiddle.net/kriskasper/3knnn/
<ul id="sortable" class='connectedSortable'>
<li>
<div class="small_box">small box</div>
<div class="big_box">big box</div>
</li>
<li>
<div class="small_box">small box</div>
<div class="big_box">big box</div>
</li>
<li>
<div class="small_box">small box</div>
<div class="big_box">big box</div>
</li>
<li>
<div class="small_box">small box</div>
<div class="big_box">big box</div>
</li>
</ul>
And here is jquery ui function:
$(function() {
$( "#sortable" ).sortable({
connectWith: ".connectedSortable",
placeholder: "ui-state-highlight",
forcePlaceholderSize: true,
opacity: 0.6,
revert: 70
});
});
Please help.
You should play with the sortable plugin events. The sortreceive event is fired when the connected element receives an item. My guess would be something like ...
$("#sortable").bind("sortreceive", function(event, ui) {
$(".connectedSortable .small_box").show();
$("#sortable .small_box").first().hide();
});

jQuery: keep toggled child element open when hovering over it

My question is similar, but different from jquery-hover-menu-when-hovering-over-child-menu-disappears.
I originally had the hover event on the li.item, which was a little quirky, but did what i needed it to do. I switched the hover to the span so that the event would fire on the text block, rather than the list block, which expands the full width of the list.
The effect I'm trying to achieve is when hovering over ul.sub. I'd like it to continue with the animation in queue from span.text's hover, which is displaying it, but also keep it open.
What is happening is that the mouse is leaving the span, so the li.item is firing its mouseout portion of the trigger.
jsFiddle Page
HTML
<ul id="main">
<li class="head">Title Bar</li>
<li class="item odd">
<span class="text">A</span>
<ul class="sub">
<li>1</li>
<li>2</li>
</ul>
</li>
<li class="item even">
<span class="text">B</span>
<ul class="sub">
<li>3</li>
<li>4</li>
</ul>
</li>
<li class="item odd">
<span class="text">C</span>
<ul class="sub">
<li>5</li>
<li>6</li>
</ul>
</li>
<li class="item even">
<span class="text">D</span>
<ul class="sub">
<li>7</li>
<li>8</li>
</ul>
</li>
</ul>
CSS
/* colors used are not for production; they are
used only to enhance the example's visual distinction */
#main{width:10em;}
.head,.item{border:1px solid black;padding:.5em;}
.head{font-weight:bold; background:#336; color:#fff; cursor:pointer;}
.item{background:#f90;}
.sub{display:none;}
.sub li{padding-left:1em;}
.text,.sub{cursor:pointer;}
JavaScript
$(document).ready(function(){
// specific here because of other divs/list items
$('#main li.item span.text').hover(function(){
$(this).siblings().stop(true,true).toggle('slow');
});
$('li.head').hover(function(){
$(this).parent().find('ul.sub').stop(true,true).toggle('slow');
});
});
Edit:
I think something along these lines is what I need, however the animation is refired when going from the sub to the span.
$(document).ready(function(){
// specific here because of other divs/list items
$('#main li.item span.text').hover(
function(){$(this).siblings().stop(false,true).show('slow');}
,function(){$(this).siblings().stop(true,true).hide('slow');}
);
$('#main li.item ul.sub').hover(
function(){$(this).stop(false,true).show();}
,function(){$(this).stop(false,true).hide('slow');}
);
$('li.head').hover(function(){
$(this).parent().find('ul.sub').stop(true,true).toggle('slow');
});
});
Split the hover behavior into its two constituents, mouseenter and mouseleave. Also split toggle() into show() and hide(). Bind mouseenter to the span.text and mouseleave to the li.item:
$(document).ready(function() {
// specific here because of other divs/list items
$('#main li.item span.text').mouseenter(function() {
$(this).siblings().stop(true, true).show('slow');
});
$('#main li.item').mouseleave(function() {
$(this).children("ul").stop(true, true).hide('slow');
});
$('li.head').hover(function() {
$(this).parent().find('ul.sub').stop(true, true).toggle('slow');
});
});
That way, the hover is not triggered by whitespace, which is what you want.

Resources