jQuery's draggable grid
Asked Answered
S

4

6

It looks like that the 'grid' option in the constructor of Draggable is relatively bound to the original coordinates of the element being dragged - so simply put, if you have three draggable divs with their top set respectively to 100, 200, 254 pixels relative to their parent:

<div class="parent-div" style="position: relative;">
    <div id="div1" class="draggable" style="top: 100px; position: absolute;"></div>
    <div id="div2" class="draggable" style="top: 200px; position: absolute;"></div>
    <div id="div3" class="draggable" style="top: 254px; position: absolute;"></div>
</div>

Adn all of them are getting enabled for dragging with 'grid' set to [1, 100]:

draggables = $('.draggable');
$.each(draggables, function(index, elem) {
    $(elem).draggable({
                       containment: $('#parent-div'),
                       opacity: 0.7,
                       revert: 'invalid',
                       revertDuration: 300,
                       grid: [1, 100],
                       refreshPositions: true
    });
});

Problem here is that as soon as you drag div3, say, down, it's top is increased by 100, moving it to 354px instead of being increased by just mere 46px (254 + 46 = 300), which would get it to the next stop in the grid - 300px, if we are looking at the parent-div as a point of reference and "grid holder".

I had a look at the draggable sources and it seem to be an in-built flaw - they just do all the calculations relative to the original position of the draggable element.

I would like to avoid monkey-patching the code of draggable library and what I am really looking for here is the way how to make the Draggable calculate the grid positions relative to containing parent. However if monkey-patching is unavoidable, I guess I'll have to live with it.

Spiv answered 14/6, 2010 at 9:43 Comment(0)
S
2

I got around this problem by simply adding my own script to drag: under draggable and setting it to

divide math.Floor(x/100)*100 

and the same for Y.

Stricklan answered 14/6, 2010 at 9:56 Comment(0)
S
12

Since @Pez's answer is lost (404), here's how I did it:

$('#elem').draggable({
    ....,
    drag: function(e, ui) {
        ui.position.left = Math.floor(ui.position.left / 10) * 10;
        ui.position.top = Math.floor(ui.position.top / 10) * 10;
    }
});

Demo: http://jsfiddle.net/ThiefMaster/yGsSE/

Sibert answered 15/6, 2011 at 14:9 Comment(3)
I'm trying to implement the fiddle you've got above, but i'm having difficulties knowing which resources i'll need. 1.5.2 seems to be suficient, if i also have 1.8.9 UI, but which UI files? I like your solution since it's very streamlined and elegant, which is what i've been looking for.Forgiveness
There is usually no good reason to use an old jQuery version. So, go with 1.6.1 and whatever is the newest UI version. Besides that, use the UI package builder and include Draggable - it should select everything necessary.Sibert
With grid size larger than 10 pixels one might want the element to snap to both directions, not just to left (which happens with floor): ui.position.left = Math.round((ui.position.left - offset) / 100) * 100 + offset (where offset is position of grid's left border).Sugary
S
2

I got around this problem by simply adding my own script to drag: under draggable and setting it to

divide math.Floor(x/100)*100 

and the same for Y.

Stricklan answered 14/6, 2010 at 9:56 Comment(0)
F
0

I've started using JQuery draggable over the last couple of days and found an easy fix to this.

Set the position property to absolute and add your widgets with top and left set to values that line up to your grid.

As the values for top/left are absolute they also make more sense when going off and storing them in a db.

Frosting answered 6/2, 2011 at 13:25 Comment(0)
M
0

Jquery Desktop:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js"></script>
<link rel="stylesheet/less" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/themes/base/jquery-ui.css">

<div class="parent-div" style="position: relative;">
    <div id="div1" class="draggable" style="top: 100px; position: absolute;">1</div>
    <div id="div2" class="draggable" style="top: 200px; position: absolute;">2</div>
    <div id="div3" class="draggable" style="top: 254px; position: absolute;">3</div>
</div>

<script>
var Z_INDEX_APP = 0;
var Z_INDEX_WINDOW_COUNTER = 1;
var Z_INDEX_NOTE_COUNTER = 999;
var Z_INDEX_FOR_DRAGGED = 99999;
var Z_INDEX_FOR_NOTIF = 999999; 
var ICONS_GRID_CELL_SIZE = 75;
var ICONS_GRID_PADDING_LEFT = 20;
var ICONS_GRID_PADDING_TOP = 50; 
draggables = $('.draggable');
$.each(draggables, function(index, elem) {
    $(elem).draggable({
        containment: $('#parent-div'),
        start: function(event) {
        icon = $(this);
        icon.css('z-Index', Z_INDEX_FOR_DRAGGED);
        dragStartLeft = icon.css('left');
        dragStartTop = icon.css('top');
        icon.addClass('desktop-app-dragging');
        icon.removeClass('desktop-app-pressed');
    },
    stop: function(event) {         
        icon.css('z-Index', Z_INDEX_APP);
        var appId = icon.attr('id').split('_')[1];
        icon.removeClass('desktop-app-dragging');
        var alignedX = ICONS_GRID_PADDING_LEFT + Math.floor(parseInt(icon.css('left'))/ICONS_GRID_CELL_SIZE) * ICONS_GRID_CELL_SIZE;
        var alignedY = ICONS_GRID_PADDING_TOP + Math.floor(parseInt(icon.css('top'))/ICONS_GRID_CELL_SIZE)  * ICONS_GRID_CELL_SIZE;
        if ( alignedX < ICONS_GRID_PADDING_LEFT ) alignedX = ICONS_GRID_PADDING_LEFT;
        if ( alignedY < ICONS_GRID_PADDING_TOP ) alignedY = ICONS_GRID_PADDING_TOP;         
        var iconToSwitch = null;
        $(".desktop-app").each(function(index, app) {           
            if ( app.style.top == ( alignedY + 'px' ) && app.style.left == ( alignedX + 'px' ) ) {
                iconToSwitch = app;
            }
        });
        if ( iconToSwitch != null ) {
            var appToSwitchId = iconToSwitch.id.split('_')[1];
            var updateUrl = 'api/desktop?cmd=update&id=' + appToSwitchId + '&x=' + parseInt(dragStartLeft) + '&y=' + parseInt(dragStartTop);
            //$.getJSON(updateUrl);
            iconToSwitch.style.left = dragStartLeft;
            iconToSwitch.style.top = dragStartTop;
        }       
        icon.css('left', alignedX + 'px');
        icon.css('top', alignedY + 'px');
        var updateUrl = 'api/desktop?cmd=update&id=' + appId + '&x=' + alignedX + '&y=' + alignedY;
        //$.getJSON(updateUrl);
    }

    });
});
</script>
Manse answered 30/1, 2012 at 17:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.