Cómo enlazar datos a la parte superior de CSS, a la izquierda, el ancho y la altura de un elemento DOM?

StackOverflow https://stackoverflow.com/questions/4717485

Pregunta

Estoy intentando utilizar KnockoutJS para construir un cuadro de mandos interactivo con enlaces de datos sobre diferentes aspectos de la propiedad style; a saber left, top, width, y height. Por ejemplo, estoy usando jQuery UI, junto con la interfaz de usuario se puede arrastrar-y-ui efectos de tamaño variable para permitir a los usuarios a los paneles de arrastre alrededor de un lienzo y cambiar su tamaño sin embargo les parezca. Sin KnockoutJS, yo era simplemente itera sobre cada div y el robo de estas propiedades del elemento DOM. Estoy seguro de que hay una mejor manera usando KnockoutJS, ¿verdad?

Para explicar mi problema un poco mejor, considere lado a lado dos paneles:

<div id='dashboard'> 
  <div id='panel1' class='ui-draggable ui-resizable' data-bind='?????'> 
    <!-- content goes here -->
  </div> 
  <div id='panel2' class='ui-draggable ui-resizable' data-bind='?????'> 
    <!-- content goes here --> 
  </div> 
  <button data-bind='click: send'>Update</button> 
</div> 

Mi modelo de vista es como la siguiente (nota: la pseudo codificado por razones de brevedad):

var viewModel = { 
  panels: [ 
   { id: 'panel1', left: 0, top: 0, width: 50; height: 50 }, 
   { id: 'panel2', left: 50, top: 0, width: 50; height: 50 } ], 
  send: function() { 
   ko.utils.postJson( location.href , { panels: this.panels } ); 
  } 
}; 
ko.applyBindings( '#dashboard', viewModel ); 

Me gustaría para obligar a éste de tal manera que cuando el usuario tamaño de cualquiera de los elementos div (es decir. Los paneles), que sería entonces actualizar el modelo de vista subyacente utilizando el construido en OnMouseUp enlace de datos. Luego, cuando el usuario hace clic en el botón "Actualizar", yo luego publicar las coordenadas al servidor.

Estoy pensando que podría tener algo que ver con las plantillas personalizadas, pero incluso allí me encontré con algunas complejidades que no pude captar en la gestión de los eventos del ratón sobre cada panel.

<script type='text/html' id='panelTemplate'>
    <div class='ui-draggable ui-resizable' 
         style='top: ${ top }; left: ${ left }; width: ${ width }px; height: ${ height }px;'>
        <!-- content goes here -->
    </div>
</script>

Las ideas?

¿Fue útil?

Solución

Yo estaba teniendo exactamente el mismo problema: se unen a un modelo KnockoutJS colección de divs que pueden arrastrarse y de tamaño variable. La solución es utilizar la costumbre vinculante y controlar el evento de final de cambio de tamaño y al final de la fricción, como explico aquí .

$(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);
        });

Otros consejos

Con el paso del tiempo la forma en que lo hace yo no era capaz de ver la solución de verde en jsFiddle y la solución de Awais parecía un poco largo, así que golpeé a través de él un poco más.

He encontrado las siguientes obras de unión para establecer el ancho. Los parens y el 'px' parecen ser importantes. En mi caso 'aWidth' es el ancho de una etiqueta div.

data-bind="style: {width: AWidth() + 'px'}"

Yo era capaz de conseguir que funcione con una solución simple, se construye fuera de la vista Ryans.

Esto me permite guardar mis cambios en tiempo real como elementos estación de E arrastre, con BreezeJS

en viewmodel

ko.bindingHandlers.draggable = {
    init: bindDraggable
};

function bindDraggable(element, value) {
    $(element).draggable({
        stop: onStopDrag
    });

    function onStopDrag(event, ui) {
        ko.dataFor(element).PositionX(ui.position.left);
        ko.dataFor(element).PositionY(ui.position.top);
        datacontext.saveChanges(); //if you want real time updating on drop
    }
}

y en mi opinión

<div data-bind="foreach: posts">
<div class="BoardPost" data-bind="style: { top: PositionY() + 'px', left: PositionX() + 'px' }, draggable:null">
    <div class="Title" data-bind="text: Content"></div>
</div>

scroll top