4

I'm using jQuery 1.8.2 & jQuery UI 1.9.0.

Here is an extension of the sortable demo from the jQuery UI Tabs Demo page with two sets of tabs + sortable, connected with each other http://jsfiddle.net/sujay/cUDLF/.

The move works fine but even after refresh the tabs don't work as expected.

To reproduce the issue try moving an unselected tab from the top-set to the bottom-set and then select it.

You'll see that the tab & the panel both have been moved to the bottom-set(The bottom-set selection will be unselected). But on selection the top-set tabs get unselected.

Update

I'm now able to make it work. Check http://jsfiddle.net/cUDLF/6/.

But sine the receive event only gets the absolute position and not the index. the position is lost. It always appends to the end of the tabs list.

If there was a way to find the index the problem will be solved.

Sujay
  • 2,198
  • 23
  • 32

4 Answers4

1

Replace:

tabs.tabs( "refresh" );

with:

tabs.tabs('destroy');
tabs.tabs();
luliandro
  • 192
  • 6
  • But what is the difference between calling `refresh` and your method. `destroy` and creating again has a visible flicker, in some cases. – Sujay Nov 16 '12 at 17:44
1

I've finally found a way to solve this problem.

A working solution can be found at http://jsfiddle.net/cUDLF/12/.

Thanks to the tip in this answer.

The receive snippet looks like

            receive: function (event, ui) {
            var receiver = $(this).parent(),
                sender = $(ui.sender[0]).parent(),
                tab = ui.item[0],
                tab$ = $(ui.item[0]),
            // Find the id of the associated panel
                panelId = tab$.attr( "aria-controls" ),
                insertBefore = document.elementFromPoint(event.pageX,event.pageY);

            tab$ = $(tab$.removeAttr($.makeArray(tab.attributes).
                          map(function(item){ return item.name;}).
                          join(' ')).remove());
            tab$.find('a').removeAttr('id tabindex role class');
            if(insertBefore.parentElement == tab){
                insertBefore = document.elementFromPoint(event.pageX + insertBefore.offsetWidth, event.pageY);
            }
            insertBefore = $(insertBefore).closest('li[role="tab"]').get(0);
            if(insertBefore)
                tab$.insertBefore(insertBefore);
            else
                $(this).append(tab$);

            $($( "#" + panelId ).remove()).appendTo(receiver);
            tabs.tabs('refresh');
        }

Do let me know if you find any issues with this approach.

Community
  • 1
  • 1
Sujay
  • 2,198
  • 23
  • 32
0

Here is working example : http://jsfiddle.net/5qY5B/

Workaround is to block event on tab change if newTab and oldTab are from different tab container :)

Example :

insted of this :

var tabs = $( "#tabs_1, #tabs_2" ).tabs();

use this (Updated) :

var tabs = $( "#tabs_1, #tabs_2" ).tabs({
        beforeActivate : function( event, ui ) {        
            if(ui.oldTab.parent().parent().attr("id") != ui.newTab.parent().parent().attr("id")) {
                if( $( this ).tabs( "option", "active") == -1) $( this ).tabs( "option", "active", 0); // NEW
                return false;
            }        
        }    
    });
Nikola Loncar
  • 2,611
  • 1
  • 26
  • 38
  • Your solution won't work in all cases. When the user tries to drag back a moved tab, two tabs will be highlighted in the same tabs group(this is just a trivial test case). This might cause more problems – Sujay Nov 16 '12 at 17:32
  • I'm still able to find erroneous conditions. One of them you can reproduce by activating 'Proin dolor' in the 1st set n then moving it down to the 2nd set. The 1st set now has no active tabs. But the 2nd set has two. – Sujay Nov 19 '12 at 09:09
  • Yes, there is an error in that case. I suggest to try experiment with this callback events : [beforeActivate](http://api.jqueryui.com/tabs/#event-beforeActivate) and [activate](http://api.jqueryui.com/tabs/#event-activate) – Nikola Loncar Nov 20 '12 at 19:35
0

This seems to work for the recieve:

            tabs.tabs("destroy");
            $( "#" + panelId ).appendTo(receiver);
            tabs.tabs();

Demo here http://jsfiddle.net/nxtwrld/yxgUR/1/

nxtwrld
  • 1,942
  • 14
  • 15
  • This works. But has a visual flicker, in some cases, which I'd like to avoid. The flicker happens due to the destruction & construction again. I thought the `refresh` method will be able to do what this does. – Sujay Nov 16 '12 at 17:45