How to data bind to the css top, left, width, and height of a DOM element.

1,217 views
Skip to first unread message

TrailHacker

unread,
Jan 17, 2011, 3:03:17 PM1/17/11
to KnockoutJS
I'm trying to use KnockoutJS to build an interactive dashboard with
data bindings on different aspects of the 'style' property; namely
left, top, width, and height.

For example, I'm using JQuery UI along with ui-draggable and ui-
resizable effects to enable users to drag panels around on a canvas
and resize them however they see fit. Without knockoutjs, I was simply
iterating over each div and stealing these properties from the dom
element. I'm sure there's a better way using knockoutjs... right?

To explain my problem a little better, consider two panels side by
side:

<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: function() { viewModel.send() }'>Update</
button>

</div>

My view model looks something like this (note: pseudo coded for
brevity):

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

ko.applyBindings( '#dashboard', viewModel );

I'd like to bind it in such a way that when the user sizes any of the
div elements (ie. the panels), that it would then update the
underlying viewModel using the built in data binding on MOUSE UP. Then
when the user clicks the 'Update' button, I would then post the
coordinates to the server.

Ideas?

Thanks in advance!
Luc

green

unread,
Jan 17, 2011, 4:06:27 PM1/17/11
to knock...@googlegroups.com

TrailHacker

unread,
Jan 18, 2011, 11:19:06 PM1/18/11
to KnockoutJS
Thanks, but this isn't quite what I was looking for. That was one of
the first places I looked too, but this assumes it's a "one way" path.
I need it to go both ways. The user is able to move the panel (thus
updating the top, left, width, and height) which should write back to
the view model.

Templates don't work either:

<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>

I'd like to bind it in such a way that when the user sizes any of the
div elements (ie. the panels), that it would then update the
underlying viewModel using the some data binding on MOUSE UP.

Thanks for the tip anyway. Do you have any other ideas??

Regards,
Luc

green

unread,
Jan 18, 2011, 11:40:26 PM1/18/11
to knock...@googlegroups.com
Do you mean you need a event binding triggered on mouse event? 

TrailHacker

unread,
Jan 20, 2011, 3:22:45 PM1/20/11
to KnockoutJS
Perhaps, yes. I'm not sure exactly what to call it, but consider the
user dragging a panel around the canvas with the size and location
displayed in the content area of the panel. I'd like for KnockoutJS to
update this content when the user releases the mouse after doing their
size or drag operation with no additional interaction on my part
outside of configuring the bindings:

<div id='panel1' class='ui-draggable ui-resizable'>
<p>Top: <span data-bind="text: top"> </span></p>
<p>Left: <span data-bind="text: left"> </span></p>
<p>Height: <span data-bind="text: height"> </span></p>
<p>Width: <span data-bind="text: width"> </span></p>
</div>

Is this possible?

Thanks again!

On Jan 18, 11:40 pm, green <greenlaw...@gmail.com> wrote:
> Do you mean you need a event binding triggered on mouse event?
>

green

unread,
Jan 20, 2011, 11:41:21 PM1/20/11
to knock...@googlegroups.com
check http://jsfiddle.net/greenlaw110/UZx4J/.

Note, I have used knockout-ext library in the demo.

TrailHacker

unread,
Jan 21, 2011, 6:39:44 PM1/21/11
to KnockoutJS
Wow! Mad props, Green! :)

I had exhausted all brain power on this and was about to give up on
it. You made it look very simple with minimal js and markup.

Thank you very much for your efforts and interactive demo.
Luc


On Jan 20, 11:41 pm, green <greenlaw...@gmail.com> wrote:
> checkhttp://jsfiddle.net/greenlaw110/UZx4J/.
>
> Note, I have used knockout-ext
> <https://github.com/greenlaw110/knockout-ext> library
> in the demo.

TrailHacker

unread,
Jan 21, 2011, 9:26:21 PM1/21/11
to KnockoutJS
NOTE ==> I DON'T EXPECT YOU TO SUPPORT THIS, I'M JUST KEEPING YOU IN
THE KNOW. :)

Odd, I've updated the sample to track the x & y of the div rather than
the mouse, and also to track resizing of the panels.

Unfortunately, it's not working as I'd expect. It could be a problem
with the jquery ui resizable event, I've not dove into it yet...

Anyway, I've updated your script to show what I'm talking about:
http://jsfiddle.net/UZx4J/6/ (try sizing the panel left and right)

I still plan to move the event logic out to a parent div so that I can
have multiple panels that display their own x, y, w, & h values
independently.

I'll update you when I get that working. :)

Thanks again!
Luc

green

unread,
Jan 22, 2011, 3:46:06 PM1/22/11
to knock...@googlegroups.com
Should you need to track the viewModel associated with each draggable panel, you could implement this as a standard jquery plugin. See http://jsfiddle.net/greenlaw110/UZx4J/9/

green

unread,
Jan 22, 2011, 3:57:23 PM1/22/11
to knock...@googlegroups.com
It could be simplified as http://jsfiddle.net/greenlaw110/UZx4J/10/, which completely encapsulate your ko logic into jquery plugin and people who use this plugin even don't know you are using ko.
Reply all
Reply to author
Forward
0 new messages