Skip to content
This repository was archived by the owner on Jan 13, 2020. It is now read-only.

Conversation

BeFiveINFO
Copy link

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);
});

@bigfoot90
Copy link

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);
                });

@BeFiveINFO
Copy link
Author

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

@bigfoot90
Copy link

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.

@BeFiveINFO BeFiveINFO changed the title 4 callbacks added 3 callbacks added Apr 4, 2015
@BeFiveINFO BeFiveINFO changed the title 3 callbacks added 4 callbacks added Apr 4, 2015
@BeFiveINFO
Copy link
Author

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is not a destination list on dragStart event

@BeFiveINFO
Copy link
Author

Thank you. I made the changes

@BeFiveINFO
Copy link
Author

destination list from dragMove is back now.

@webtweakers
Copy link

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.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the destination parameter yet.
I there any reason why you have removed it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bigfoot90 Thanks for checking up. I double checked my previous modification few days ago. See the line 138, list.dragRootEl // Destination.

@webtweakers I just woke up now. I get back to you as soon as I can.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, having some other functionality available at the dragEnd event would be really helpful as well:

  1. a reference to the new parent, if any
  2. being able to return false in the dragEnd callback/listener as a way to undo the move

As far as I have checked the code, this kind of functionality seems to fall slightly out of the scope of the project. Unfortunately I have a lack of time at the moment, otherwise I'd implement it myself.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that I have, but I might have made a mistake?
BeFiveINFO@0f3282d

@bigfoot90
Copy link

@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
]);

@webtweakers
Copy link

@bigfoot90 Nice one, thanks.

@bigfoot90
Copy link

@BeFiveINFO What is the state of this?

@BeFiveINFO
Copy link
Author

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!

@bigfoot90
Copy link

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?

@BeFiveINFO
Copy link
Author

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

@bigfoot90
Copy link

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.

@BeFiveINFO
Copy link
Author

@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.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List events with the correct timeline order

afterInit
beforeDragStart
dragStart
dragMove
beforeDragEnd
dragEnd

@bigfoot90
Copy link

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);
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update beforeDragStart event to pass the same parameters as dragStart event do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, bigfoot90.

Readme has been updated.

Updating the file so that beforeDragStart returns the parameters. I forgot declaring the item variables. hold on

FYI I just added you as a collaborator at the repo, https://github.com/BeFiveINFO/Nestable Please feel free to make any changes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bigfoot90 , I just realised that the code needed to return just handle, because item may not exist depending on cases.

In my case, I use "beforeDragStart" event to determine a clicked handle element (item). When the handle is clicked, there is an information pane right next to nestable where you can edit details of selected item. I hope that you will get the image of my case scenario.

@Sysa
Copy link

Sysa commented May 9, 2015

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?

@bigfoot90
Copy link

@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?

@BeFiveINFO
Copy link
Author

@bigfoot90
Please see : #143 (comment)

@ajhalls
Copy link

ajhalls commented May 11, 2015

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 ) {
        });
    });```

@FlashJunior
Copy link

+1 ;-)

@marcelostrappini
Copy link

+1
This new feature helped me a lot!

@litzinger
Copy link

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants