Search and Top Navigation
#4454 closed enhancement (worksforme)
Opened April 10, 2009 06:48PM UTC
Closed October 12, 2010 02:43AM UTC
Last modified May 19, 2013 04:03AM UTC
Draggable Grid Option Demands "beforeStart" Callback
Reported by: | rgrwkmn | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | 1.8 |
Component: | ui.draggable | Version: | 1.7.1 |
Keywords: | start callback | Cc: | |
Blocked by: | Blocking: |
Description
Since the grid option snaps a dragged element to a grid relative to the element's starting position, it is necessary to reset the position of the dragged element when showing a visible grid on the page that the element is not already aligned with. At the time that the start callback is triggered, the dragger has full control of the draggable, the position of which cannot be programmatically reset.
I worked around this by adding a beforeStart callback in _mouseStart in ui.draggable.js. I put it at the latest possible point in the function where I could still control the draggable's position and get access to the helper. The code is as follows (note that I removed some comments that were messing up this ticket's formatting):
_mouseStart: function(event) { var o = this.options; //Create and append the visible helper this.helper = this._createHelper(event); //Cache the helper size this._cacheHelperProportions(); //If ddmanager is used for droppables, set the global draggable if($.ui.ddmanager) $.ui.ddmanager.current = this; /* * - Position generation - * This block generates everything position related - it's the core of draggables. */ //Cache the margins of the original element this._cacheMargins(); //Store the helper's css position this.cssPosition = this.helper.css("position"); this.scrollParent = this.helper.scrollParent(); //Call beforeStart callback, fired before the //draggables position is in the control of the dragger this._trigger("beforeStart", event); //The element's absolute position on the page minus margins this.offset = this.element.offset(); this.offset = { top: this.offset.top - this.margins.top, left: this.offset.left - this.margins.left }; $.extend(this.offset, { click: { //Where the click happened, relative to the element left: event.pageX - this.offset.left, top: event.pageY - this.offset.top }, parent: this._getParentOffset(), relative: this._getRelativeOffset() }); //Generate the original position this.originalPosition = this._generatePosition(event); this.originalPageX = event.pageX; this.originalPageY = event.pageY; if(o.cursorAt) this._adjustOffsetFromHelper(o.cursorAt); //Set a containment if given in the options if(o.containment) this._setContainment(); //Call plugins and callbacks this._trigger("start", event); //Recache the helper size this._cacheHelperProportions(); //Prepare the droppable offsets if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, event); this.helper.addClass("ui-draggable-dragging"); this._mouseDrag(event, true); return true; }
And this is the code I use to snap the draggable to my grid:
beforeStart: function(event, ui) { if (global.snap2grid) { var ttop = parseInt(ui.helper.css('top')); var left = parseInt(ui.helper.css('left')); ui.helper.css({ top: (ttop - (ttop % global.gridScale))+'px', left: (left - (left % global.gridScale))+'px' }); } }
I hope this is a useful suggestion, I'd love to see it in an official release. There are probably many uses for this callback and some more thought should go into where it actually happens (I just shoved it in based on my immediate needs). It should be in _mouseStart as opposed to _mouseCapture because someone clicking on a draggable element isn't necessarily going to drag it and that initial click could have any number of meanings on a website.
Attachments (0)
Change History (6)
Changed May 07, 2009 12:42PM UTC by comment:1
milestone: | TBD → 1.next |
---|
Changed September 17, 2009 09:31AM UTC by comment:2
I'd like to make vote that this feature is included in a future release. The solution posted here has proved very useful in my project!
Changed April 01, 2010 11:09AM UTC by comment:3
Another vote for this feature here. This is exactly what my project needed!
Changed October 12, 2010 02:43AM UTC by comment:4
resolution: | → worksforme |
---|---|
status: | new → closed |
You can change the position of the draggable by modifying the ui.position object in the callbacks. For example, this would force the draggable to always have it's top moving along the 200px line:
$( "#draggable" ).draggable({ drag: function( event, ui ) { ui.position.top = 200; } });
Changed October 03, 2012 04:56PM UTC by comment:5
milestone: | 1.next → 1.8 |
---|