Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to refresh sortables while dragging a sortable item?

I have sections and each section has items. These items are sortable objects which I can drag and drop from one section to another. A few of our clients have a TON of sections with a TON of items which makes the browser fall to it's knees. I was pretty green when I initially designed it so efficiency wasn't really on my radar but now I'm revisiting the script and I've bumped into a problem.

To solve the problem I use lazy loading using ajax on my section lists where the items are only fetched from the server when they click on the "open section" button. A feature we have in the inefficient system is that a user can hold a dragged item over a close sections for 500ms and it will open the section.

This is the generated HTML:

<ul class="sections ui-sortable" style="display: block;">
    <li id="s_3" class="ui-droppable">
        <input type="hidden" value="3" name="section_id">
        <span class="sectionName">Section 1</span>      
        <ul class="items ui-sortable" style="">
            <!-- Items can go here -->
        </ul>
    </li>
    <li id="s_11" class="ui-droppable">
        <input type="hidden" value="11" name="section_id">
        <span class="sectionName">Section 2</span>
        <ul class="items ui-sortable" style="display: block;">
            <li id="i_32">
                <input type="hidden" value="32" name="item_id">
                <span class="itemName">Item 1</span>
            </li>
        </ul>
    </li>
</ul>

The problem I have is that the sorting function gets all screwie with a newly populated item list.

This is how I make it so lists can be opened by hovering over them:

//sElement is the .sections ul
function initItemDroppable( sElement ) {
    sElement.find('> li').droppable({
        accept: '.items > li',
        over: function( event, ui ) {
            var section = $(this);
            var section_id = section.find('input[name="section_id"]').val();

            // only start the counter if  the container isn't already visible
            if( !$(section).find('.items').is(':visible') ) {
                $( document ).oneTime( '500ms', 'expandCategoryTimer', function(){
                    //get the items and populated the list
                    getItems( section_id );
                    //according to jquery, refreshes the positions of all the sortable objects
                    $('.sections, .items').sortable('refreshPositions');
                } );
            }
        },
        out: function( event, ui ) {
            $( document ).stopTime( 'expandCategoryTimer' );
        }
    });
}

I thought all I needed was the "refreshPosition" method on the sortable stuff but it's not quite doing the trick. I'm allowed to drop an item at the END of the list but I can't drop it inbetween other ones unless I drop it and pick it back up again. Any ideas?

like image 869
Gazillion Avatar asked Dec 17 '22 09:12

Gazillion


1 Answers

You know what I hate, when you're stuck on something for hours, ask for help, and then find the answer moments later.

Turns out I wasn't actually looking for refreshPositions but just plain ol' refresh. When I get items and move them on the screen I refresh their position and then call refresh to have newly added items to be recognized by the current drag.

I was going to delete my question but then thought maybe this could help someone aside from me ;)

like image 192
Gazillion Avatar answered Dec 21 '22 22:12

Gazillion