Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

jQueryUI draggable and resizable with knockout.js

2.00/5 (1 vote)
20 Jul 2013CPOL 12.2K  
jQueryUI draggable and resizable with knockout.js.

Situation: viewModel is rendered on the client using knockout.js; part of the model is a collection of resizable and draggable divs.

The problem: once the div is dragged/resised how to update the model with new coordinates?

The solution is to use custom binding and handle the event of end of resize and end of drag. See jqDraggableResizable in the following example:

XML
<html>
<head>
    <title></title>
    <link href="http://www.codeproject.com/Styles/base/jquery.ui.all.css" rel="stylesheet" type="text/css" />
    <link href="Styles/Site.css" rel="stylesheet" type="text/css" />
    <script src="http://www.codeproject.com/Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
    <script src="http://www.codeproject.com/Scripts/jquery-ui-1.8.11.min.js" type="text/javascript"></script>
    <script src="http://www.codeproject.com/Scripts/jquery.tmpl.js" type="text/javascript"></script>
    <script src="http://www.codeproject.com/Scripts/knockout-1.2.0.js" type="text/javascript"></script>

    <script>
        var viewModel = {
            Hotspots: ko.observableArray([
             {
                 X: ko.observable(527),
                 Y: ko.observable(195),
                 H: ko.observable(121),
                 W: ko.observable(140)
             },
             {
                 X: ko.observable(699),
                 Y: ko.observable(193),
                 H: ko.observable(294),
                 W: ko.observable(269)
             }
         ])
        };

        viewModel.currentHotspot = ko.observable({ Text: null });

        viewModel.addNew = function () {
            viewModel.Hotspots.push({ X: ko.observable(50), Y: ko.observable(50), 
              H: ko.observable(100), W: ko.observable(100), Text: ko.observable('new hotspot') });
        };

        //

        $(document).ready(function () {
            $('#btnSave').click(function () {
                $.ajax({
                    url: '/Save.ashx',
                    contentType: "application/json; charset=utf-8",
                    type: 'POST',
                    dataType: 'json',
                    data: ko.toJSON(viewModel),
                    error: function () { alert("ajax error"); }
                });
            });

            ko.bindingHandlers.jqDraggableResizable = {
                init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
                    var obj = valueAccessor();
                    var $elem = $(element);

                    element.dataObj = obj;

                    $elem.resizable({
                        stop: function (event, ui) {
                            this.dataObj.H(ui.size.height);
                            this.dataObj.W(ui.size.width);
                        }
                    });

                    $elem.draggable({
                        stop: function (event, ui) {
                            this.dataObj.X(ui.position.left);
                            this.dataObj.Y(ui.position.top);
                        }
                    });
                }
            }

            ko.applyBindings(viewModel);
        });

    </script>
</head>
<body>
    <div class="main">
        <div data-bind='template: "hotspotTemplate"'></div>

        <input type='button' id='btnAdd' value="add new" 
          data-bind='click: function() { viewModel.addNew(); }' />
        <input type='button' id='btnSave' value="save it!" />

        <script id='hotspotTemplate' type='text/x-jquery-tmpl'>
            {{each(i, h) Hotspots}}
                <div class="resizable" 
                   style="position:absolute; left: ${ X }px; top: ${ Y }px; width: ${ W }px; height: ${ H }px;" 
                   data-bind="jqDraggableResizable : h">
                </div>
            {{/each}}
        </script>
    </div>
</body>
</html>

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)