#

Jump to Table of Contents

# Example: Fish Sort - Multi Outer Join

This example has 2 sortable lists, each with floated nodes. The lists are outer joined together. The small fish on the left can move into the groups on the right, and become sortable (and larger). However, the items in the groups on the right cannot move back into the list of small fish.

- Cat. #34620
- Cat. #31899
- Cat. #32230
- Cat. #32003
- Cat. #34551
- Cat. #32398
- Cat. #36667
- Cat. #34821
- Cat. #38144
- Cat. #32445
- Cat. #32201
- Cat. #32011

- Group A
- Cat. #34114
- Group B
- Group C
- Group D

Images of fish etchings are from Jacob Theodor Klein, mid 1700s. Source: http://www.flickr.com/photos/biodivlibrary/sets/72157627937663760/. Contributed by: MBLWHOI Library, Woods Hole.

Note: When using an outer or inner joined list, you must pick a moveType of 'move' or 'copy', the default 'swap' won't give you the results you expect.

This example assumes that you have seen the Multiple Sortable Lists - Full Join example and continues from there.

### Setting Up the List

First we need to create the HTML structure for the lists. Since `Sortable` uses `Y.DD.Delegate`, we need to set up the delegation containers (`#list1, #lists2`) and the list items (`li`).

    <div id="demo" class="yui-g">
        <div id="col-left" class="yui3-u">
            <ul id="list1">
                <li class="fish"><img src="../assets/sortable/images/efish_03.png" alt="Fish:Round, 2 stripes"/><div class="cat-num">Cat. #34620</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_09.png" alt="Fish:Spiked dorsal, dark"/><div class="cat-num">Cat. #31899</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_12.png" alt="Fish:Long comb dorsal"/><div class="cat-num">Cat. #32230</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_05.png" alt="Fish:Sole, medium"/><div class="cat-num">Cat. #32003</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_04.png" alt="Fish:Round, 3 stripes"/><div class="cat-num">Cat. #34551</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_06.png" alt="Fish:Sole, light"/><div class="cat-num">Cat. #32398</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_08.png" alt="Fish:Lots of spiked fins"/><div class="cat-num">Cat. #36667</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_02.png" alt="Fish:Round, 4 stripes"/><div class="cat-num">Cat. #34821</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_10.png" alt="Fish:Big Spiked dorsal, light"/><div class="cat-num">Cat. #38144</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_13.png" alt="Fish:Long comb dorsal"/><div class="cat-num">Cat. #32445</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_07.png" alt="Fish:Sole, dark"/><div class="cat-num">Cat. #32201</div></li>
                <li class="fish"><img src="../assets/sortable/images/efish_11.png" alt="Fish:Long comb dorsal, pointy"/><div class="cat-num">Cat. #32011</div></li>
            </ul>
        </div>
        <div id="col-right" class="yui3-u">
            <ul id="list2">
                <li class="group-hd">Group A</li>
                <!-- This fish has already been pre-placed in a group -->
                <li class="fish"><img src="../assets/sortable/images/efish_01.png" alt="Fish:Round, 5 stripes"/><div class="cat-num">Cat. #34114</div></li>
                <li class="group-hd">Group B</li>
                <li class="group-hd">Group C</li>
                <li class="group-hd">Group D</li>
            </ul>
        </div>
    </div>

Now we give the lists some CSS to make them visible.

    .example {
        background-color: #DCCFBB;
        font-family: georgia;
        /* a repeating grid image in the background */
        background-image: url(../assets/sortable/images/grid.png);
    }
    #demo {
        float: none;
        border: solid 1px #C8B9A4;
        width: 655px;
        margin: auto;
        -moz-border-radius: 3px;
        -webkit-border-radius: 3px;
        border-radius: 3px;
    }
    #demo #col-left{
        width: 231px;
    }
    #demo #col-right {
        width: 417px;
        padding-bottom: 2em; /* needs bottom padding so objects can drag below last .group-hd */
        border-left: solid 1px #C8B9A4;
    }
    #demo ul{
        margin: 0;
        padding: 0;
        list-style-type: none;
    }
    #demo #list1 li,
    #demo #list2 li{
        float: left; /* the li objects are floated */
        margin: 3px;
        background-color: #E9CE98;
    }
    #demo #list1 li{
        height: 56px;
        width: 68px;
        overflow: hidden; /* this hides the catalog number on the small fish */
    }
    /* the width and height of the .fish items are larger in #list2 */
    #demo #list2 .fish{
        width: 130px;
        height: 115px; /* The .fish items are taller when on the right to show the catalog number */
        text-align: center;
    }
    /* catalog number style */
    #demo #list2 .cat-num{
        font-size: 80%;
        margin: -0.2em 0.5em;
        font-style: italic;
        color: #9F8A6C;
        height: 1.3em;
        line-height: 0.9em;
    }
    /* group heads are sortable like other objects but have different style */
    #demo #list2 .group-hd{
        background-color: #6F6452;
        border-color: #EBD6B3 #63532E #63532E #EBD6B3;
        width: 406px;
        height: 20px;
        text-indent: 0.5em;
        font-weight: bold;
        color: #B0986A;
        line-height: 20px;
    }
    #demo li img{
        width: 100%; /* image scales with size of it's li container */
    }
    #demo li {
        border: solid 1px;
        -moz-border-radius: 4px;
        -webkit-border-radius: 4px;
        border-radius: 4px;
        border-color: #FFEFC2 #9D8F70 #9D8F70 #FFEFC2;
        -moz-box-shadow: 3px 4px 8px rgba(0, 0, 0, 0.25);
        -webkit-box-shadow: 3px 4px 8px rgba(0, 0, 0, 0.25);
        box-shadow: 3px 4px 8px rgba(0, 0, 0, 0.25);
    }

### Setting Up the YUI Instance

Now we need to create our YUI instance and tell it to load the `sortable` module.

In this example we are also going to attach a `DD` plugin to the `Sortable` instances.

    YUI().use('dd-constrain', 'sortable', function (Y) {
        // Code here.
    });

### Making the Lists Draggable

Now that we have a YUI instance with the `sortable` module, we need to instantiate a `Sortable` instance on each of the lists.

    YUI().use('dd-constrain', 'sortable', function(Y) {
        var list1 = new Y.Sortable({
            container: '#list1',
            nodes: 'li',
            opacity: '.1'
        });

        var list2 = new Y.Sortable({
            container: '#list2',
            nodes: 'li',
            opacity: '.1'
        });

    });

### Applying a DD Plugin

Since `Sortable` uses `DD.Delegate`, there is a dd instance available after instantiation.

The `DD.Delegate` reference is found on the `.delegate` property of the `Sortable`. This `DD.Delegate` instance has a `DD.Drag` instance bound to the `dd` property on the `DD.Delegate`

    list1.delegate.dd.plug(Y.Plugin.DDConstrained, {
        constrain2node: '#demo'
    });
    list2.delegate.dd.plug(Y.Plugin.DDConstrained, {
        constrain2node: '#demo'
    });

Applying the `Plugin.DDConstrained` to the `Sortable` instance.

    YUI().use('dd-constrain', 'sortable', function(Y) {
        var list1 = new Y.Sortable({
            container: '#list1',
            nodes: 'li',
            opacity: '.1'
        });

        var list2 = new Y.Sortable({
            container: '#list2',
            nodes: 'li',
            opacity: '.1'
        });

        list1.delegate.dd.plug(Y.Plugin.DDConstrained, {
            constrain2node: '#demo'
        });
        list2.delegate.dd.plug(Y.Plugin.DDConstrained, {
            constrain2node: '#demo'
        });

    });

### Joining the Lists

Joining the lists is as simple as calling the `join` method on one list passing in another list. By default, we use a full join which joins both lists both ways.

You can optionally specify the join type: `inner` or `outer`. The `moveType` can also be specified on the list: `swap`, `move` or `copy`. `swap` is the default, as seen in this example.

    list1.join(list2);              //Full join <-- both ways -->
    list1.join(list2, 'outer');     //Outer join --> one way -->
    list1.join(list2, 'inner');     //Inner join <-- one way <--

### Putting it together

    YUI().use('dd-constrain', 'sortable', function(Y) {
        var list1 = new Y.Sortable({
            container: '#list1',
            nodes: 'li',
            opacity: '.1'
        });

        var list2 = new Y.Sortable({
            container: '#list2',
            nodes: 'li',
            opacity: '.1'
        });

        list1.join(list2, 'outer');
    });