Drag and drop re-ordering in 1.3?

Myke623

Well-known member
Has anyone tried using the drag and drop functionality in xenForo 1.3 for re-ordering elements in a list, and can provide an overview of how it works?

Otherwise, I'll attempt to unravel how it's used in the MultiQuote feature.
 
Hmm, I'm not having any luck.

The difference in what I'm trying to achieve and MultiQuote, is that I already have my list of things ($categoryList) in a table. So rather than rely on user inputs to construct the list, I simply grab it from my model and pass it to my view. The template for this view is as follows:

Code:
<xen:title>Categories</xen:title>

<xen:require js="js/sortable/jquery.sortable.min.js" />

<form class="section" id="CategoriesForm">
    <h3 class="subHeading">Drag Categories to rearrange order</h3>
    <ol class="overlayScroll Sortable">
        <xen:foreach loop="$categoryList" key="$catId" value="$category">
            <li draggable="true" class="CategoryItem">
                <input type="hidden" name="catId[]" value="{$catId}" class="CategoryId" />
                {$category.title}
            </li>
        </xen:foreach>
    </ol>
    <div class="sectionFooter">
        <a class="button OverlayCloser JsOnly">{xen:phrase cancel}</a>
        <a class="button primary OverlayCloser AutoFocus"
            href="{xen:link addon/categories}"
            data-inputs="#CategoriesForm input.CategoryId">Save Order</a>
    </div>
</form>

With this, I was just hoping to drag the <LI> elements around and observe the effect in Chrome's element inspector. However, while I can drag an <LI> element, the cursor instantly turns into the circle-with-diagonal-line icon, meaning "you can't drag this here". As such, I'm unable to change the list order.

I used the MultiQuote template as the starting point, and culled the bits which I thought weren't relevant to my more generic purpose. Ignoring the Save Order button for the moment, is there anything obvious I've missed?
 
I believe you're missing this relevant code in discussion.js:

Code:
    XenForo.Sortable = function($container)
    {
        $container.sortable(
        {
            forcePlaceholderSize: true

        }).bind(
            {
                'sortupdate': function(e) {},
                'dragstart' : function(e)
                {
                    console.log('drag start, %o', e.target);
                },
                'dragend' : function(e) { console.log('drag end'); }
            }
        );
    };

    XenForo.register('.Sortable', 'XenForo.Sortable');

This binds events to the .Sortable elements and additionally activates some of the Sortable settings.

You will need to include something similar.
 
Last question (hopefully) to complete the puzzle: How can I get my re-ordered list passed to the Controller?

I figure I need to add a new class to the "Save Order" button, and register the corresponding new js function to do something with the data-inputs, but I'm at a bit of a loss.
 
The elements will already be in the correct order when passed to the controller.

With that in mind, the simplest thing to do is to loop through them with a numeric key, or assign your own incremental value when you loop, e.g:

PHP:
$categories = array();

$categoryIds = $this->_input->filterSingle('catId', XenForo_Input::UINT, array('array' => true);
foreach ($categoryIds AS $key => $categoryId)
{
    $categories[] = array(
        'category_id' => $categoryId,
        'display_order' => $key // 0, 1, 2, 3, 4, etc.
    );
}

OR

PHP:
$categories = array();

$i = 0;

$categoryIds = $this->_input->filterSingle('catId', XenForo_Input::UINT, array('array' => true);
foreach ($categoryIds AS $categoryId)
{
    $i++;

    $categories[] = array(
        'category_id' => $categoryId,
        'display_order' => $i * 10 // 10, 20, 30, 40, etc.
    );
}

Something like that, anyway. Depends exactly what you're trying to achieve.
 
Ah, of course! Not sure why I thought it wouldn't be.

Thanks again for the help, Chris, really appreciate it!
 
Top Bottom