Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to go from DOM node to viewModel object?

When the drop function is called back, this is set to the droppable DOM node (the target) and ui.draggable is the DOM node which was dragged.

Is there an idiomatic way of getting the model object which has been rendered as a particular DOM node?

(I'm using jQuery templates, if it matters. There may be more than one rendering of a single modelView object.)

like image 644
fadedbee Avatar asked Dec 03 '10 15:12

fadedbee


1 Answers

There may be a better way to do this but I cheated. Here are my bindings.

EDIT

Since the below example was incomplete I have done a simple complete example which can be found here.

http://pastie.org/1446229

Where you store the currently dragging element is up to you. In the example I use a global variable as a proxy for the viewModel item. You could give each of your draggables and droppables a reference to their parent model and access the property this way, it's up to you.

Hope this helps.

ko.bindingHandlers.drag = {
                init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
                    var $element = $(element),
                        dragOptions = { 
                            revert: 'invalid',
                            revertDuration: 250,
                            cancel: 'span.handle',
                            cursorAt: { left: 28, bottom: 0 },
                            appendTo : 'body',
                            helper: function () { 
                                return $('<div class="drag-icon"><img src="images/folder-large.png" alt="move" width="32" height="32" /></div>'); 
                            },
                            cursor: "pointer",
                            addClasses: false,
                            distance: 10,
                            start : function (e, ui) { 
                                viewModel.isDragging();
                            }
                        };

                    $element.draggable(dragOptions);
                },
                update : function (element, valueAccessor, allBindingsAccessor, viewModel) {
                    var $element = $(element),
                        active = valueAccessor();

                    if (!active) {
                        $element.draggable('disable');
                    }
                    else {
                        $element.draggable('enable');
                    }
                }
            };

ko.bindingHandlers.drop = {
                init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
                    var $element = $(element),
                        value = valueAccessor() || {},
                        handler = ko.utils.unwrapObservable(value.onDropComplete),
                        dropOptions = { 
                            greedy: true,
                            tolerance: 'pointer',
                            addClasses: false,
                            drop: function (e, ui) {
                                setTimeout(function () { 
                                                handler(viewModel.dragging()); 
                                            }, 0);
                            }
                        };
                    $element.droppable(dropOptions);
                }
            };

So I setup draggable and in the start function I store the currently dragging node viewModel.isDragging(); then I can access it again in the drop handler.

Cheers,

Ian

like image 147
madcapnmckay Avatar answered Nov 09 '22 03:11

madcapnmckay