views:

130

answers:

3

I am monkey-patching some of the jQuery's Draggable code*

The goal is to avoid modifying the original source files and patch dynamically one of the internal functions.

The function _generatePosition is declared like this:

(function($) {

    $.widget("ui.draggable", $.ui.mouse, {
        ...
        _generatePosition: function(event) {
            ...
        }
    }
})(jQuery);

Is it possible to achieve the dynamic replacement of it?


*so it calculates the snapping grid relative to the top of parent element and not relative to the top of element being dragged. See here for more details

+3  A: 

Edit for below comments: It seems you can edit these (after the last widget re-write), but I would still steer clear. Here's an example of the base method, you can modify from there if you wish, but keep in mind this can and probably will break in a future release. Also any "inheritors" of the widget won't pick up these changes, not sure if that's an issue.


As for the reason, to deny you access isn't the reason really (not in this case). In library cases like this it's more to be clean than deny you access, or because the library may want to change architecture later, and still break as few people as possible when they do so...letting you only access the "public" members of their code gives the authors more flexibility in changing anything that's "private".

Case in point: jQuery UI 1.8 moved a lot of code into the position utility, allowing a lot of private code cleanup that you didn't see happen, since it was all private before this allowed a fairly big optimization/code reduction without breaking people left and right.

Nick Craver
It has a leading underscore, so should be treated as private...but are you sure you can't dig up the object and set the property to a different function? It's not private like [this](http://www.crockford.com/javascript/private.html)...?
sje397
@sje397 - It is private not just the `_` in the front, that's just convention to recognize it as private (pretty consistent through the library). It's passed into the widget creator which assigns various private methods to the objects (again just how *they* do it). If you look in the code that's why it has to be called via `this._generatePosition` :)
Nick Craver
They're not really private if you can access them though (see my other post), they're just more inaccessible :)
peol
@peol - You're correct that since the widget rewrite these are exposed in some fashion, but there are still issues and a much larger chance of breaking in any future upgrades, this should definitely be mentioned. They aren't strictly private in their implementation, but that's certainly the author's intent here. I updated the above answer to point this out better.
Nick Craver
+3  A: 

You can actually modify these, but only on a per-element basic as far as I know. But you could easily create your own $.fn.draggable wrapper, and just call the original wrapper and run this: draggableElement.data('draggable')._generatePosition = fn

  • As Jörn Zaefferer pointed out, you could also modify the draggable prototype, by using $.ui.draggable.prototype._generatePosition = fn
peol
+2  A: 

You can manipulate individual instances:

.draggable().data("draggable")._generatePosition = function() {};

Or modify the prototype, affecting all instances:

$.ui.draggable.prototype._generatePosition = function() {};
Jörn Zaefferer
Modifying prototype is definitely a win over .data(), thanks!
Art