Nestable icon indicating copy to clipboard operation
Nestable copied to clipboard

4 callbacks added

Open BeFiveINFO opened this issue 9 years ago • 23 comments

I added 4 callbacks: afterInit, onStartEvent, onMoveEvent and onEndEvent. Any chance we could add those callbacks?

Test code as follows.

$('#example-list-element').nestable({
    afterInit: function ( event ) { 
        console.log( event ); 
    }
})
.on('beforeDragStart', function(handle) {
    console.log('dragStart', handle);
})
.on('dragStart', function(event, item, source) {
    console.log('dragStart', event, item, source);
})
.on('dragMove', function(event, item, source, destination) {
    console.log('dragMove', event, item, source);
})
.on('dragEnd', function(event, item, source, destination) {
    console.log('dragEnd', event, item, source, destination);
})
.on('beforeDragEnd', function(event, item, source, destination, position, feedback) {
    // If you need to persist list items order if changes, you need to comment the next line
    if (source[0] === destination[0]) { feedback.abort = true; return; }

    feedback.abort = !window.confirm('Continue?');
})
.on('dragEnd', function(event, item, source, destination, position) {
    // Make an ajax request to persist move on database
    // here you can pass item-id, source-id, destination-id and position index to the server
    // ....

    console.log('dragEnd', event, item, source, destination, position);
});

BeFiveINFO avatar Apr 01 '15 15:04 BeFiveINFO

What you think about this solution instead?

            var onEndEvent = function(e)
            {
                if (list.dragEl) {
                    e.preventDefault();

                    var item = list.dragEl.find('.'+list.options.itemClass);
                    list.dragRootEl.trigger('dragEnd', [
                        item,           // List item
                        list.el,        // Source list
                        list.dragRootEl // Destination list
                    ]);

                    list.dragStop(e.touches ? e.touches[0] : e);
                }
            };

Usage:

            $('.dd').nestable()
                .on('dragEnd', function(event, item, source, destination) {
                    console.log(item, source, destination);
                });

bigfoot90 avatar Apr 03 '15 11:04 bigfoot90

Thanks bigfoot, I do not really know the differences. Perhaps could you please tell me benefits of your solution? Thank you in advance!

BeFiveINFO avatar Apr 03 '15 12:04 BeFiveINFO

By this way you can attach more than one listener on dragEnd event. You can also add or remove listeners at runtime.

The code listeners are decoupled from the list initialization, so you can also split your code in more files, for example 3rd party plugins. You can also create or remove lists at runtime, useful when you have a single page application.

I've also added three parameters because I need to know the list item I'm moving, and the source and destination lists.

This same method is also applicable to dragStart and move events.

bigfoot90 avatar Apr 03 '15 18:04 bigfoot90

bigfoot90, Thanks a lot for the detailed explanation! I have pushed the changes to the repo just as you kindly suggested.

BeFiveINFO avatar Apr 04 '15 13:04 BeFiveINFO

Thank you. I made the changes

BeFiveINFO avatar Apr 04 '15 16:04 BeFiveINFO

destination list from dragMove is back now.

BeFiveINFO avatar Apr 05 '15 06:04 BeFiveINFO

Would be nice if the new position of the dragged element could be added to the dragEnd event arguments. Having this information, would simplify back-end handling/storage of the tree.

webtweakers avatar Apr 08 '15 17:04 webtweakers

@webtweakers For position in destination you can use list.placeEl.index() as fourth parameter in dragEnd and move events.

list.dragRootEl.trigger('dragEnd', [
    item,               // List item
    list.el,            // Source list
    list.dragRootEl,    // Destination list
    list.placeEl.index()  // Position
]);

bigfoot90 avatar Apr 09 '15 08:04 bigfoot90

@bigfoot90 Nice one, thanks.

webtweakers avatar Apr 09 '15 17:04 webtweakers

@BeFiveINFO What is the state of this?

bigfoot90 avatar Apr 19 '15 21:04 bigfoot90

hello bigfoot90, thanks for checking up!

I just wanted to ask you about the timing where the trigger function should be at. Currently the trigger is called before "list.dragStop(e.touches ? e.touches[0] : e);" (ref: line 156) The action is not completed yet at the point of trigger to be precise. But placing the trigger for dragEnd right after dragStop let dragEl and dragRootEl inaccessible.

I wonder what we could do for this issue.

I am now thinking to place the trigger function right after the dragStop, then return just ID of the handle (as String) with the trigger. For example:

var onEndEvent = function(e)
            {
                if (list.dragEl) {
                    e.preventDefault();
                    var item_id = list.dragRootEl.find('li:first').data('id');
                    list.dragStop(e.touches ? e.touches[0] : e);
                    /* callback for dragEnd */
                    list.el.trigger('dragEnd',[item_id]);
                }
            };

Thank you for your advices in advance!

BeFiveINFO avatar Apr 20 '15 03:04 BeFiveINFO

Placing the trigger after is right, but there is no way to prevent dragStop. Maybe split it into two eventsdragEnd and beforeDragEnd.

Currently I'm using this ugly workaround:

            var onEndEvent = function(e)
            {
                if (!list.dragEl) return;
                e.preventDefault();

                var feedback = {abort: false};

                var item = list.dragEl.find('.'+list.options.itemClass);
                var sourceList = list.el;
                var destinationList = list.dragRootEl;
                var position = list.placeEl.index();

                destinationList.trigger('beforeDragEnd', [
                    item,               // List item
                    sourceList,         // Source list
                    destinationList,    // Destination list
                    position,           // Position
                    feedback
                ]);

                if (feedback.abort) return;

                list.dragStop(e.touches ? e.touches[0] : e);

                destinationList.trigger('dragEnd', [
                    item,               // List item
                    sourceList,         // Source list
                    destinationList,    // Destination list
                    position            // Position
                ]);
            };

And use case:

$(this)
            .nestable()
            .on('beforeDragEnd', function(event, item, source, destination, position, feedback) {
                if (source[0] === destination[0]) return;
                feedback.abort = !window.confirm('Continue?');
            })
            .on('dragEnd', function(event, item, source, destination, position) {
                if (source[0] === destination[0]) return;

                // Make an ajax request to persist move on database
                // here i need to pass item-id, source-id, destination-id, position index to the server
                // ....
            });

@BeFiveINFO What do you think?

bigfoot90 avatar Apr 23 '15 08:04 bigfoot90

Thanks @bigfoot90! I have made the changes just as you suggested.

BeFiveINFO avatar May 04 '15 12:05 BeFiveINFO

Good ;-)

Just few questions/suggesstions:

  • How you are using the event dragJustBeforeStart?
  • Rename dragJustBeforeStart to beforeDragStart to keep the same nomenclature, and also the shorter name is better.
  • The solution with feedback parameter is not good. I've made it only as a quick workaround. A better solution could be jQuery.Event, you can then check event.isPropagationStopped(). But currently I don't have time to work/test this.
  • Why you have renamed the script file? Maybe keeping the original name helps this PR to be merged in the future.

bigfoot90 avatar May 05 '15 02:05 bigfoot90

@bigfoot90 Thank you for the suggestions!

  • How you are using the event dragJustBeforeStart? ** I use it to change the color of current item in the list
  • Rename dragJustBeforeStart to beforeDragStart ** I agree. It makes more sense that way. I think that the name was from my random thought at that moment.

I will work on the issue below. I will post as soon as I have something to show.

  • The solution with feedback parameter is not good.

BeFiveINFO avatar May 06 '15 13:05 BeFiveINFO

I have noticed there are some minor errors in README.md and in the first issue's post:

Corrected:

$('#example-list-element').nestable({
    afterInit: function ( event ) { 
        console.log( event ); 
    }
})
.on('beforeDragStart', function(handle) {
    console.log('dragStart', handle);
})
.on('dragStart', function(event, item, source) {
    console.log('dragStart', event, item, source);
})
.on('dragMove', function(event, item, source, destination) {
    console.log('dragMove', event, item, source);
})
.on('dragEnd', function(event, item, source, destination) {
    console.log('dragEnd', event, item, source, destination);
})
.on('beforeDragEnd', function(event, item, source, destination, position, feedback) {
    // If you need to persist list items order if changes, you need to comment the next line
    if (source[0] === destination[0]) { feedback.abort = true; return; }

    feedback.abort = !window.confirm('Continue?');
})
.on('dragEnd', function(event, item, source, destination, position) {
    // Make an ajax request to persist move on database
    // here you can pass item-id, source-id, destination-id and position index to the server
    // ....

    console.log('dragEnd', event, item, source, destination, position);
});

bigfoot90 avatar May 07 '15 20:05 bigfoot90

Is there a clever way of canceling drop and return item to previous position ? something like this: .on('dragEnd', function(event, item, source, destination, position) { if(destination[0].id=='1337') { /* cancel working here, maybe this event.preventDefault(); return false; */ } }); but this not working. any ideas?

Sysa avatar May 09 '15 14:05 Sysa

@Sysa Currently the feedback method is the only that works. The script must be modified to use jQuery.Event.

@BeFiveINFO You have reverted your commit, What is the problem?

bigfoot90 avatar May 10 '15 15:05 bigfoot90

@bigfoot90 Please see : https://github.com/dbushell/Nestable/pull/143#discussion_r29993318

BeFiveINFO avatar May 10 '15 15:05 BeFiveINFO

For what it is worth, I used your code to get the element and write it to the database. Here was what I used:

<?
if ($_REQUEST){
    if ($_REQUEST['do'] == 'updatemenu'){
        print_r($_REQUEST);
        $dbicons = new SQLite3('./database/icons.sqlite'); 
        $dbicons->busyTimeout(200);
            $update = "UPDATE icons SET parent_id = :parent_id WHERE id = :id";
            $stmt = $dbicons->prepare($update);
            $stmt->bindParam(':parent_id', $_REQUEST["parent_id"]);
            $stmt->bindParam(':id', $_REQUEST["id"]);
            $stmt->execute();
            if (!empty($_REQUEST['deletetask'])){
                $id = $_REQUEST['deletetask'];

                    $delete = "DELETE FROM icons where id = :id";
                    $stmt = $db->prepare($delete);
                    $stmt->bindParam(':id', $id);
                    $stmt->execute();
            }   
            $dbicons->close();
            unset($dbicons);

    };
}else{};
?>

Javascript:

    $(".dd").on('dragEnd', function(event, item, source, destination, position) {
        var currentItem = $(item).attr('data-id');
        var itemParent = $(item).parent().parent().attr('data-id');
        $.ajax({
        method: "POST",
        url: "iconadmin.php",
        data: { id: currentItem, parent_id: itemParent, do: "updatemenu" }
        })
        .done(function( msg ) {
        });
    });```

ajhalls avatar May 11 '15 18:05 ajhalls

+1 ;-)

FlashJunior avatar May 22 '15 18:05 FlashJunior

+1 This new feature helped me a lot!

marcelostrappini avatar May 23 '15 11:05 marcelostrappini

Would someone consider pushing the Merge button on this one? Two years and its still not merged? This is very helpful functionality.

litzinger avatar Oct 17 '17 12:10 litzinger