Drag and drop constrained to axis?

Hello,

Please tell me about current state of following desired feature, I’m using DHTMLX 4.2.1 Pro at office so it’s not recent but upgrading implies many people so things must be clear first.

We would like to configure scheduler to enable drag and drop in timeline view on a given X or Y axis only. I read the docs and found such a feature for Grid and Tree. I found forum posts on this subject but back to 2012.

Constraint must be visual and not only after drop action.

Is this feature planned? Do you have advice?

Thanks,

B. Post

Sorry, version error : we use DHTMLX 4.3.1 for scheduler and 4.2.1 for everything else.

I thought I could use jQuery UI Draggable (viewtopic.php?f=6&t=50143&p=139094) but have trouble when dropping the event, the call to

scheduler.getActionData(native_mouse_event)

gives incorrect date, because it returns the date and time blow the cursor and not corresponding to event “start_date”. I tried playing with reading coordinates of the dragged div and read the internals of “_mouse_coords()” function to use “_get_date_from_pos()” internal function but came to nothing.

So, as suggested in aforementioned linked post, I tried to use scheduler handled events but I’m not able to cancel the visual “Y” move when I decide that I should move only by “X”.

My dragAndDropInfo object stores the clientX and clientY when drag starts (scheduler event handler for “onBeforeDrag” assigns it). Then I have a “model” variable that indicates allowed drag axis/axes. I tried both mouse event “stopImmediatePropagation()” and “stopPropagation()”.

Is the mouse move visually cancellable ?

scheduler.attachEvent("onEventDrag",function(eventId, mode, native_event){
            if(this.model.canHorizontallyDrag() && !this.model.canVerticallyDrag()){
                // X can move
                var allowed = dragAndDropInfo.y == native_event.clientY;
                console.log(allowed);
                if(!allowed) {
                    native_event.stopImmediatePropagation();
                    return false;
                }

            } else if(!this.model.canHorizontallyDrag() && this.model.canVerticallyDrag()) {
                // Y can move
                var allowed = dragAndDropInfo.x == native_event.clientX;
                console.log(allowed);
                if(!allowed) {
                    native_event.stopPropagation();
                    return false;
                }
            }
            return true;
        }.bind(this));

Thanks,

B. Post

Here is my working solution with jQuery UI Draggable. There are some things to keep in mind thought, related to mouse cursor…

Commented code, timeline unit resource view.

/**
     * Adds jQuery UI Draggable to events root HTML element.
     * @private
     */
    MyJsModuleView.prototype._addDraggableToDomElements = function() {
        var axis = this.getAxisForJqueryUiDraggable(); // 'x' or 'y'
        var view = this;
        var cursorAtOptions;
        if(axis == 'x')
            cursorAtOptions = {left : 0};
        else
            cursorAtOptions = {top: 0};
// My events have 'draggable-event' class (custom event rendering)
        $$('div.draggable-event').forEach(function (elt) {
            var eventId = $(elt).readAttribute('data-event_id');
            var draggedElt = jQuery(elt).parent().get(0);
            // Event isn't modified by manual drag and drop
            var originalSchedulerEvent = scheduler.getEvent(eventId);
            if (view.isEventEditable(eventId)) { // assume true
                jQuery(draggedElt).draggable({
                    axis: axis,
                    containment: '#scheduler_data>table',
                    zIndex: 9999,
                    distance: 5, //dragging by less than 5px is ignored
                    cursorAt : cursorAtOptions, // cursor position so that cursor is at right position when dropping
                    start: function () {
                        draggedElt.addClassName('dhx_in_move');
                    },
                    drag : function(event, ui) {
                        // prevent dragging to main table column containing view units names.
                        ui.position.left = Math.max(0, ui.position.left);
                    },
                    stop: function (event, ui) {
                        draggedElt.removeClassName('dhx_in_move');
                        var dropData = scheduler.getActionData(event);
                        // When dragging along X axis, cursor left position gives date and view unit doesn't change. Override value given by mouse position.
                        if(axis == 'x')
                            dropData.section= originalSchedulerEvent.locationResourceId;
                        // When dragging along Y axis, cursor top position gives view unit and date doesn't change. Override value given by mouse position.
                        else
                            dropData.date = originalSchedulerEvent.start_date;
// my custom function that gets corrects parameters !
                        view.handleEventDrop(originalSchedulerEvent.locationResourceId, dropData.section, dropData.date, originalSchedulerEvent.id);
                    }
                });
            }
        });
    };

I feel very relieved and this might be useful for someone.