Search code examples
javascriptjqueryjquery-uidraggable

How to implement reference line on jquery-ui draggable as the guidance for dragging?


I have an answer from this question: Javascript drag/drop - Illustrator style 'smart guides'

From one of the answers, I tried to implement it to my project, but there is one thing that I am still struggling with it. The "guide" line still doesn't work on the same side of the objects.

For example, based on my jsfiddle (http://jsfiddle.net/yusrilmaulidanraji/A6CpP/119/), if I drag the square, it will show the yellow reference line only if both of the sides are different. For the same side (ex: right side on square 1 with right side on squre 2), it still doesn't show the guide line.

I have tried to modify it in many ways, but still have no clue how to make it. here is the code:

HTML:

<div id="parent">
    <div class="object1 dropped" style="left:0px;top:300px;background:#a00;"></div>
    <div class="object2 dropped"></div>
    <div class="object3 dropped" style="left:400px;top:20px;"></div>
    <div class="objectx"></div>
    <div class="objecty"></div>
</div>

JS:

$.ui.plugin.add("draggable", "smartguides", {
    start: function(event, ui) {
        var i = $(this).data("draggable"), o = i.options;
        i.elements = [];
        $(o.smartguides.constructor != String ? ( o.smartguides.items || ':data(draggable)' ) : o.smartguides).each(function() {
            var $t = $(this); var $o = $t.offset();
            if(this != i.element[0]) i.elements.push({
                item: this,
                width: $t.outerWidth(), height: $t.outerHeight(),
                top: $o.top, left: $o.left
            });
        });
    },
    stop: function(event, ui) {
        $(".objectx").css({"display":"none"});
        $(".objecty").css({"display":"none"});
    },
    drag: function(event, ui) {
        var inst = $(this).data("draggable"), o = inst.options;
        var d = o.tolerance;
        $(".objectx").css({"display":"none"});
        $(".objecty").css({"display":"none"});
            var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
                y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height,
                xc = (x1 + x2) / 2, yc = (y1 + y2) / 2;
            for (var i = inst.elements.length - 1; i >= 0; i--){
                var l = inst.elements[i].left, r = l + inst.elements[i].width,
                    t = inst.elements[i].top, b = t + inst.elements[i].height,
                    hc = (l + r) / 2, vc = (t + b) / 2;
                    var ls = Math.abs(l - x2) <= d;
                    var rs = Math.abs(r - x1) <= d;
                    var ts = Math.abs(t - y2) <= d;
                    var bs = Math.abs(b - y1) <= d;
                    var hs = Math.abs(hc - xc) <= d;
                    var vs = Math.abs(vc - yc) <= d; 
                if(ls) {
                    ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
                    $(".objectx").css({"left":l-d-4,"display":"block"});
                }
                if(rs) {
                    ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
                     $(".objectx").css({"left":r-d-4,"display":"block"});
                }

                if(ts) {
                    ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
                    $(".objecty").css({"top":t-d-4,"display":"block"});
                }
                if(bs) {
                    ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
                    $(".objecty").css({"top":b-d-4,"display":"block"});
                }
                if(hs) {
                    ui.position.left = inst._convertPositionTo("relative", { top: 0, left: hc - inst.helperProportions.width/2 }).left - inst.margins.left;
                     $(".objectx").css({"left":hc-d-4,"display":"block"});
                }
                if(vs) {
                    ui.position.top = inst._convertPositionTo("relative", { top: vc - inst.helperProportions.height/2, left: 0 }).top - inst.margins.top;
                    $(".objecty").css({"top":vc-d-4,"display":"block"});
                }


            };
        }
});
$('.dropped').draggable({
    containment: 'parent',
    smartguides:".dropped",
    tolerance:5
});

CSS:

#parent{
    width:600px;
    height:500px;
    border:1px solid #000;
    position:relative;
}
.object1{
    background:#aaa;
    width:100px;
    height:100px;
    display:block;
    position:absolute;
    left:140px;
    top:50px;
}
.object2{
    background:#aaa;
    width:100px;
    height:150px;
    display:block;
    position:absolute;
    left:140px;
    top:50px;
}
.object3{
    background:#aaa;
    width:150px;
    height:100px;
    display:block;
    position:absolute;
    left:140px;
    top:50px;
}
.objectx{
    display:none;
    //background:#fff;
    width:0px;
    height:100%;
    position:absolute;
    top:0px;
    left:10px;
    border-left: 1px solid yellow;
}
.objecty{
    display:none;
    //background:#fff;
    width:100%;
    height:0px;
    position:absolute;
    top:10px;
    left:0px;
    border-bottom: 1px solid yellow;
}

Solution

  • Well, finally I have my own solution. Here is the jsfiddle:http://jsfiddle.net/yusrilmaulidanraji/A6CpP/120/

    And here is the code:

    HTML:

    <div id="parent">
        <div class="object1 dropped" style="left:0px;top:300px;background:#a00;"></div>
        <div class="object2 dropped"></div>
        <div class="object3 dropped" style="left:400px;top:20px;"></div>
        <div class="objectx"></div>
        <div class="objecty"></div>
    </div>
    

    CSS:

    #parent{
        width:600px;
        height:500px;
        border:1px solid #000;
        position:relative;
    }
    .object1{
        background:#aaa;
        width:100px;
        height:100px;
        display:block;
        position:absolute;
        left:140px;
        top:50px;
    }
    .object2{
        background:#aaa;
        width:100px;
        height:150px;
        display:block;
        position:absolute;
        left:140px;
        top:50px;
    }
    .object3{
        background:#aaa;
        width:150px;
        height:100px;
        display:block;
        position:absolute;
        left:140px;
        top:50px;
    }
    .objectx{
        display:none;
        //background:#fff;
        width:0px;
        height:100%;
        position:absolute;
        top:0px;
        left:10px;
        border-left: 1px solid yellow;
    }
    .objecty{
        display:none;
        //background:#fff;
        width:100%;
        height:0px;
        position:absolute;
        top:10px;
        left:0px;
        border-bottom: 1px solid yellow;
    }
    

    JS:

    $.ui.plugin.add("draggable", "smartguides", {
        start: function(event, ui) {
            var i = $(this).data("draggable"), o = i.options;
            i.elements = [];
            $(o.smartguides.constructor != String ? ( o.smartguides.items || ':data(draggable)' ) : o.smartguides).each(function() {
                var $t = $(this); var $o = $t.offset();
                if(this != i.element[0]) i.elements.push({
                    item: this,
                    width: $t.outerWidth(), height: $t.outerHeight(),
                    top: $o.top, left: $o.left
                });
            });
        },
        stop: function(event, ui) {
            $(".objectx").css({"display":"none"});
            $(".objecty").css({"display":"none"});
        },
        drag: function(event, ui) {
            var inst = $(this).data("draggable"), o = inst.options;
            var d = o.tolerance;
            $(".objectx").css({"display":"none"});
            $(".objecty").css({"display":"none"});
                var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
                    y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height,
                    xc = (x1 + x2) / 2, yc = (y1 + y2) / 2;
                for (var i = inst.elements.length - 1; i >= 0; i--){
                    var l = inst.elements[i].left, r = l + inst.elements[i].width,
                        t = inst.elements[i].top, b = t + inst.elements[i].height,
                        hc = (l + r) / 2, vc = (t + b) / 2;
                         var lss = Math.abs(l - x1) <= d;
                                var ls = Math.abs(l - x2) <= d;
                                var rss = Math.abs(r - x2) <= d;
                                var rs = Math.abs(r - x1) <= d;
                                var tss = Math.abs(t - y1) <= d;
                                var ts = Math.abs(t - y2) <= d;
                                var bss = Math.abs(b - y2) <= d;
                                var bs = Math.abs(b - y1) <= d;
                                var hs = Math.abs(hc - xc) <= d;
                                var vs = Math.abs(vc - yc) <= d; 
                            if(lss) {
                                ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
                                $(".objectx").css({"left":ui.position.left,"display":"block"});
                            }
                            if(rss) {
                                ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
                                $(".objectx").css({"left":ui.position.left + ui.helper.width(),"display":"block"});
                            }
                            if(ls) {
                                ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
                                $(".objectx").css({"left":ui.position.left + ui.helper.width(),"display":"block"});
                            }
                            if(rs) {
                                ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
                                $(".objectx").css({"left":ui.position.left,"display":"block"});
                            }
                            if(tss) {
                                ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
                                $(".objecty").css({"top":ui.position.top,"display":"block"});
                            }
                            if(ts) {
                                ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
                                $(".objecty").css({"top":ui.position.top + ui.helper.height(),"display":"block"});
                            }
                            if(bss) {
                                ui.position.top = inst._convertPositionTo("relative", { top: b-inst.helperProportions.height, left: 0 }).top - inst.margins.top;
                                $(".objecty").css({"top":ui.position.top + ui.helper.height(),"display":"block"});
                            }
                            if(bs) {
                                ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
                                $(".objecty").css({"top":ui.position.top,"display":"block"});
                            }
                            if(hs) {
                                ui.position.left = inst._convertPositionTo("relative", { top: 0, left: hc - inst.helperProportions.width/2 }).left - inst.margins.left;
                                $(".objectx").css({"left":ui.position.left + (ui.helper.width()/2),"display":"block"});
                            }
                            if(vs) {
                                ui.position.top = inst._convertPositionTo("relative", { top: vc - inst.helperProportions.height/2, left: 0 }).top - inst.margins.top;
                                $(".objecty").css({"top":ui.position.top + (ui.helper.height()/2),"display":"block"});
                            }
    
    
                };
            }
    });
    $('.dropped').draggable({
        containment: 'parent',
        smartguides:".dropped",
        tolerance:5
    });