Wilsonhut

Deal with it or don't

Knockout + jQueryUI draggable/droppable – the end

In earlier posts, I went through the simple and a slightly more than simple implementations of using jQueryUI’s dragon drop with knockout. Now I’m going to round it out with my final post on the topic. This time, I’ll add binding capability to other properties of the draggables and droppables. I’m only going to demonstrate binding the ‘disabled’ option of both the draggable and the droppable, but you can use the same process for binding any of the options.

Example

The contrived example this time is a teacher’s seating chart. Go ahead and check out the example. The “Locked” checkbox is bound to the draggables ‘disabled’ option. The droppables get disabled when the seat already has a student in it.

The Code [Find the latest on GitHub]

(function ($, ko) {

  var _dragged, _hasBeenDropped, _draggedIndex;

  ko.bindingHandlers.drag = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dragElement = $(element);

      var dragOptions = {

        helper: function () {

          return dragElement.clone().addClass(“ui-dragon”);

        },

        revert: true,

        revertDuration: 0,

        start: function () {

          _hasBeenDropped = false;

          _dragged = ko.utils.unwrapObservable(valueAccessor().value);

          if ($.isFunction(valueAccessor().value)) {

            valueAccessor().value(undefined);

            dragElement.draggable(“option”, “revertDuration”, 500);

          } else if (valueAccessor().array) {

            _draggedIndex = valueAccessor().array.indexOf(_dragged);

            valueAccessor().array.splice(_draggedIndex, 1);

          }

        },

        stop: function (e, ui) {

          if (!_hasBeenDropped) {

            if ($.isFunction(valueAccessor().value)) {

              valueAccessor().value(_dragged);

            } else if (valueAccessor().array) {

              valueAccessor().array.splice(_draggedIndex, 0, _dragged);

            }

          }

        },

        cursor: ‘default’

      };

      dragElement.draggable(dragOptions).disableSelection();

    },

    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dragElement = $(element);

      var disabled = !!ko.utils.unwrapObservable(valueAccessor().disabled);

      dragElement.draggable(“option”, “disabled”, disabled);

    }

  };

  ko.bindingHandlers.drop = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dropElement = $(element);

      var dropOptions = {

        tolerance: ‘pointer’,

        drop: function (event, ui) {

          _hasBeenDropped = true;

          valueAccessor().value(_dragged);

          ui.draggable.draggable(“option”, “revertDuration”, 0);

        }

      };

      dropElement.droppable(dropOptions);

    },

    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dropElement = $(element);

      var disabled = !!ko.utils.unwrapObservable(valueAccessor().disabled);

      //dropElement.droppable(“option”, “disabled”, disabled); didn’t work. jQueryUI bug?

      dropElement.droppable(“option”, “accept”, disabled ? “.nothing” : “*”);

    }

  };

})(jQuery, ko);

The thing that’s different from last time is the implementation of the ‘update’ methods in the binding handlers. The update method gets called when the value of any of the ko.observables change, so I just get the observable from the valueAccessor() and call ko.utils.unwrapObservable() with that sucka, and you have the value to update the options with.

Usage

The usage is very similar to the last example, with the addition of the disabled binding, as in the excerpt from the HTML in the jsfiddle example:

<span data-bind=“drag: {value: student, disabled: $root.isLocked}”>

…shows how I bind the value of the isLocked viewModel property to the ‘disabled’ option of the drag (The checkbox is also bound to the isLocked viewModel property), and…

<td data-bind=“drop: {value: student, disabled: !!student()}”>

…shows how I bind the ‘disabled’ option of the drop to the existence of a student in the seat.

Future

I might update this page sometime in the future to add other options bindings, or to add new functionality. For example, there’s a spot already for a hook to add a ‘revert‘ event to the draggable inside the if (!_hasBeenDropped)  block.

Advertisements

10 responses to “Knockout + jQueryUI draggable/droppable – the end

  1. Pingback: Knockout + jQueryUI Draggable/Droppable « Wilsonhut

  2. Alex April 3, 2013 at 4:18 pm

    Hi,
    I’m trying to use this however this line never fires:
    dragElement.draggable(“option”, “disabled”, disabled);

    So, my dragElement is never actually disabled (can’t bind CSS to it, or stop it from being dragged again etc…)… Am I missing something?

  3. Alex April 3, 2013 at 4:22 pm

    Actually, ignore me…
    I forgot to add the disabled part in:

    {value: $data, disabled: myCondition()}

  4. Pingback: Alex James BrownUsing custom options with KnockoutJS Drag and Drop » Alex James Brown

  5. Alex April 3, 2013 at 11:27 pm

    Have you thought about putting this on github? I’d love to contribute my change to allow custom dragOptions – http://www.alexjamesbrown.com/blog/development/using-custom-options-with-knockoutjs-drag-and-drop/

  6. Phillipp August 5, 2013 at 10:06 am

    Great article. I will be facing many of these issues as well.
    .

  7. Mois Moshev November 6, 2013 at 6:33 pm

    That’s a really nice article. Now I am diving into knockout+drag’n’drop and it’s wonderful!
    I built a project without jqueryUI (and some data on the nodes, bound with observables, of course) and it works . Site will be launched soon, and then I’ll look at sharing the code, too.
    Thank you for posting this!

  8. Mois Moshev November 6, 2013 at 6:34 pm

    …and think about what it can do with svg! Data-driven games… sounds good 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: