How to prevent draggable child elements from dragg

2019-05-14 19:49发布

问题:

How to prevent draggable child elements from dragging over each other in absolute position? Something like:

if( ($("#firstChild").position().left) >= ($("#secondChild").position().left) )
{
    $(this).draggable({ disabled: true });
}

but this only disables dragabble when stop dragging, the goal is to prevent from overdragging in some way...Or with Droppable???

Any ideas for CASE 2?

EDIT:

Also, this is maximum for child1 towards child2 , so no overlap occurs, but child1 can push child2 on right, and child2 can push child1 on left, important thing is that no overlap ocurrs!

回答1:

Some notes before / in order to reach the optimal solution:

  • You have declared and initialised the allBetween variablw, but not using it. I suggest to remove it.
  • At your #buttonOne event listener, you're using inconsistent values: 429 and 424: if($("#firstInput").val() > 429 )$("#firstInput").val(424);
    1. You're using the #firstInput (and #thirdInput) selector multiple times without caching a reference.
    2. You're duplicating the functions for each button. A better, less error-prone solution is to create a method to build these methods.

Final code

The optimisations have been explained previously. I will not elaborate them, since that's not the topic of the question. I have explained the function logic of the requested behavior in the scripts comments (below).

$(document).ready(function() {
    // Helper to easily bind related events to the button.
    function createButtonClickEvent(sel_selector, input_selector, left_limit, right_limit) {
        return function(){
            var $sel = $(sel_selector),
                $input = $(input_selector),
                val = $input.val();
            if (val > right_limit) input.val(val = right_limit);
            else if (val < left_limit) input.val(val = left_limit);
            $sel.css('left', val + "px");

            var $allElems = $("#second").children(".single"),
                 $between = $allElems.inRangeX("#selFirst", "#selSecond");
            $allElems.removeClass("ui-selected");
            $between.addClass("ui-selected");
        }
    }
       //setValue 1
    $("#buttonOne").click(createButtonClickEvent("#selFirst", "#firstInput", 0, 429));    
    //setValue2
    $("#buttonTwo").click(createButtonClickEvent("#selSecond", "#thirdInput", 0, 429));


    //graph values
    var valuesG = [],
        $elements = $();
    for (i = 0; i < 144; i++) {
        valuesG[i] = Math.floor(Math.random() * (30 - 20 + 1) + 10);
        $elements = $elements.add($("<div class='single'>")
                             .css('height', valuesG[i])
                             .css('margin-top', 30 - valuesG[i]));
    }
    $elements.appendTo($("#second"));
    $("#second").children(".single").addClass("ui-selected");

    //inRangeX (http://stackoverflow.com/a/8457155/938089)
    (function($) {
        $.fn.inRangeX = function(x1, x2) {

            if (typeof x1 == "string" && +x1 != x1 || x1 instanceof Element) {
                x1 = $(x1);
            }
            if (typeof x2 == "string" && +x1 != x1 || x1 instanceof Element) {
                x2 = $(x2);
            }

            if (x1 instanceof $) {
                x1 = x1.offset().left;
            }
            if (x2 instanceof $) {
                x2 = x2.offset().left;
            }
            x1 = +x1;
            x2 = +x2;


            if (x1 > x2) {
                var x = x1;
                x1 = x2;
                x2 = x;
            }
            return this.filter(function() {
                var $this = $(this),
                    offset = $this.offset(),
                    rightSide = offset.left - 5;
                return offset.left >= x1 + 5 && rightSide <= x2;
            });
        }
    })(jQuery);

    //firstPositions
    var startFirst = $(".selector#selFirst").position().left;
    var startSecond = $(".selector#selSecond").position().left;
    $('input#firstInput').val(startFirst);
    $('input#thirdInput').val(startSecond);

    // *********** Actual requested code *********** //
    //first and second-Picker
    var $selFirst = $("#selFirst"),
        $selSecond = $("#selSecond"),
        cachedWidth = $selFirst.outerWidth();

    function drag_function(event, ui){
        var $firstRightBorder = $selFirst.position().left + cachedWidth,
             $secondLeft = $selSecond.position().left,
             diff = $firstRightBorder - $secondLeft;
        /*
         * The logic is as follows:
         * dif < 0 if selFirst and selSecond do not overlap
         * dif = 0 if they're next to each other
         * dif > 0 if they overlap each other
         * To fix this (reminder: if they overlap, dif is negative):
         * If current == #selFirst,
         *    left = left + dif
         * else (if current == #selSecond),
         *    left = left - dif
         */
        if (diff > 0) {
            var currentLeft = parseFloat($(this).css("left"));
            if (this.id == "selSecond") diff = -diff;
            ui.position.left = currentLeft - diff;
            ui.helper.css("left", currentLeft - diff);
        }
        var $allElems = $("#second").children(".single"),
            $between = $allElems.inRangeX("#selFirst", "#selSecond");
        $("#firstInput").val($("#selFirst").position().left);
        $("#thirdInput").val($("#selSecond").position().left);
        $allElems.removeClass("ui-selected");
        $between.addClass("ui-selected");
        var allBetween = $('.ui-selected');
    }

    $("#selFirst, #selSecond").draggable({
        containment: 'parent',
        axis: 'x',
        drag: drag_function,
        stop: drag_function
    });
}); //eof


回答2:

you can use gamequery plugin. theres a collision detection.

second thing you can do is: when you hover your element while dragging... just trigger drop ? so he will never be able to drag it inside. make something like drag position of mouse at the right of the dragged element so you are sure thats not possible to drag it inside this element.

i hope you know what i mean

example calling drop:

$('#rightbox').live('mouseenter', function(){
  $('#leftbox').droppable.option('drop');
});

something like that... havent test it but its a way to start with