Dependencies
The code for this post is built with Ember.js 1.0.0-RC1, handlebars RC3, and jQuery 1.9.1
Objective
We will see how the Ember.View updates when changing the model properties using mouse event coordinates. The end result is drawing a box which is an Ember.Object using click and drag.
Demo
This jsFiddle demonstrates the end result: Completed Fiddle. Click on the gray box and hold down the mouse button. Drag to create and update a box object.
Ember Application Setup
Here we have defined two handlebars templates. The first is unnamed and will be used by the Application View. The second is called “box” using data-template-name and will be used by the Box View.
1 2 3 4 5 6 7 | |
Here we setup the App, Router, Routes, and Ember Object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Application View / Controller
The Application View and Controller will be auto-generated by Ember if they are not declared. For this demo, the Application View will be handling the mouse events.
1 2 3 | |
The needs property lists other controllers so that you can access them from this controller by using this.get(‘controllers.otherController’). ‘otherController’ being ‘box’ in this case.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Event Handling
Ember.View’s can handle many/most of the browser events, a description may be found here: Ember View API .
Here we have used the mouseDown, mouseMove, and mouseUp events to capture a click and drag in the browser. We declare a ‘boxCon’ variable that is set to the Box Controller, which was made available
by using needs on the Application Controller.
The mouseMove event is using the pageX and pageY attributes of the event. The reason for this is moving the mouse over a Box View would give the offsets relative to that view
instead of the App View’s offsets. Since we are using event.pageX and event.pageY, we should account for the offset of the App View relative to the absolute top and left of the page.
@$() or this.$() is a jQuery element which we then call the jQuery offset() method on. This returns an object with top and left properties.
Each event then passes on the event information to the Box Controller via a method call or setting an attribute.
BoxController and BoxView Setup
The BoxController has an ‘isUpdating’ flag, and the initial coordinates of the mouseDown event. The two methods are to create a box object at the click and to update the area of the new box based on mouse movements.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
The BoxView is what allows the updated box object to be displayed. attributeBindings will attach an attribute to the view element. In this case the attribute we want is style. ‘Style’ is defined here as a computed property which returns a string. The result is the view element will have style=”height:50px;width=50px; etc…” This value will update whenever the properties of the box update, and cause the view to be re-rendered.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Improving the System
Here is the working jsFiddle showing the results of this demo: Completed Fiddle
What can we improve? Currently, during the box update there is a flag on the controller called ‘isUpdating’ which is set to true, then when
the update ends this flag is set to false. We could run into problems in the future if we add more features and forget what this flag is for.
Then we could run into some crazy behavior since those mouse events are still firing when we move the mouse. A better solution might be to use
a state machine instead of a flag and change states when appropriate. Each state would handle events and only the appropriate outcomes would
be allowed.
That wraps it up, thanks for reading!