1
votes

i'm developing a drag-and-drop interface using jQuery-UI Draggable + jQuery-UI Sortable inside a jQuery-UI Tabs

here's the HTML code:

<div id="tabs">
<ul>
    <li><a href="#tabs-1">One</a></li>
    <li><a href="#tabs-2">Two</a></li>
    <li><a href="#tabs-3">Three</a></li>
</ul>
<div id="tabs-1">
    One
</div>
<div id="tabs-2">
    Two
</div>
<div id="tabs-3">
    <!-- BEGIN: DRAG & DROP INTERFACE  -->
    <div class="toolbar">
        <div class="item">
            <div class="in">
                Satu
            </div>
        </div>
        <div class="clear"></div>
    </div>

    <div class="sortable">
        <div class="target">
            <div class="clear"></div>
        </div>
    </div>        
    <!-- END: DRAG & DROP INTERFACE  -->
</div>

And here's the javascript code:

jQuery(function() {    
    jQuery( "#tabs" ).tabs({ selected: 0 });
    jQuery(".sortable .target").sortable({
        opacity: 0.5
    });    
    jQuery(".sortable .item, .toolbar .item").disableSelection();
    jQuery(".toolbar .item").draggable({
        connectToSortable: ".sortable .target",
        helper: "clone",
        revert: "invalid"
    });
});

(you can see the whole code here: http://jsfiddle.net/dwiash/CWhFe/)

it works well if the drag-and-drop interface is placed inside a tab that initially shown. But it doesn't work if it placed in an initially inactive/hidden tab. The problem is, the drag-and-drop interface must be placed inside a tab that initially hidden/inactive

Can anyone help me fix this problem?

thx :)

3

3 Answers

1
votes

You can use the tabsshow event on the tabs to bind the drag'n'drop stuff, http://jsfiddle.net/kMZPR/1/:

function initDnD(event, ui) {
    if(ui.index != 2)
        return;
    jQuery(".sortable .target").sortable({ opacity: 0.5 });
    jQuery(".sortable .item, .toolbar .item").disableSelection();
    jQuery(".toolbar .item").draggable({
        connectToSortable: ".sortable .target",
        helper: "clone",
        revert: "invalid"
    });
    jQuery('#tabs').unbind('tabsshow', initDnD);
}

jQuery(function() {
    jQuery("#tabs").tabs({ selected: 0 }).bind('tabsshow', initDnD);
});

Note that this unbinds the event as soon as it has done its work, there's no need to keep calling this over and over again; this is also why the tabsshow event handler is in a separate named function BTW.

Also, it looks like the jQuery-UI tabs don't call the tabsshow event handlers for the initially selected tab. If you want the "Three" tab selected initially then it looks like you're better off doing it by hand rather than through the options:

jQuery("#tabs").tabs().bind('tabsshow', initDnD);
jQuery("#tabs").tabs('select', 2);  // Ensure that the event gets triggered

You're not doing anything like this in your example, just something that you should be aware off.

This is a fairly common technique when you're dealing with things that need to be fully realized/visible/positioned before they can have extra functionality added.

0
votes

Wait till the tab is clicked on to activate your draggable/sortable. So, give your tab-3 link an id:

<li><a href="#tabs-3" id="tab3">Three</a></li>

And then, change your jQuery to activate your draggable/sortable on click:

jQuery(function() {

    jQuery( "#tabs" ).tabs({ selected: 0 });

    $('#tab3').click(function() {
        jQuery(".sortable .target").sortable({
            opacity: 0.5
        });

        jQuery(".sortable .item, .toolbar .item").disableSelection();

        jQuery(".toolbar .item").draggable({
            connectToSortable: ".sortable .target",
            helper: "clone",
            revert: "invalid"
        });
    });
});
0
votes

I know i'm a couple months late, but i just encountered this issue.. Besides this post, I also found this jqueryui ticket while searching on the web...

In the ticket a work-around is suggested:

$( ".draggable-class-name").draggable({
  connectToSortable: ".sortable-class-name",
  // other options here
  start: function(event, ui) {
      $( ".sortable-class-name" ).sortable("refresh");
  }
});

The work-around seems to work ok. This should help a bit, at least until the jqueryui team gets to solving it.

Hope this is useful