StatCounter

Sunday, January 18, 2015

AngularJS And HTML5 ContentEditable

Getting Angular to Play Well With HTML5 ContentEditable


HTML5 introduced a cool new attribute, which can be attached to any element to make it editable (contenteditable="true"). However, that's just the theory. To make that work, you have to use a data binding library (e.g. AngularJS, BackboneJS) or build your own using JavaScript.

I recently created a todos application using pure JavaScript (with jQuery) with a Node/Mongo backend, i.e. without using any data binding framework. This is a good exercise to ensure that you understand JavaScript well enough before you start leaning on hefty frameworks that obscure a lot of what goes on behind the scenes. If you understand JavaScript, you'll be better able to troubleshoot and fix issues that come up when you're using frameworks.

My pure JavaScript app is deployed on Heroku here. The code is on GitHub here.

Once I was happy enough with the pure JavaScript application, my next goal was to redo it using AngularJS (I had previously done some prototyping with Mustache, Handlebars, Backbone, etc.). I also decided to use Bootstrap in order to explore that in the process.

AngularJS Context


If you've played around a little with AngularJS, you know that one of its coolest features is the ng-repeat built-in directive. This directive can be applied to almost any HTML element to cause the element to be repeated for each member of your model. So, it's great for displaying something like a todo list. For example, a single ng-repeat="todo in todos" nested in a paragraph element would cause several paragraph elements to be added to the DOM, one for each todo in your model.

AngularJS uses the model to provide two-way data binding between your database and your displayed data. The idea is that AngularJS keeps track of your edits via the model and makes it easy to save those edits to a database at appropriate junctures.

Also, AngularJS provides a templating engine that allows you to easily control data formatting. So, I could do something like {{ todo.created_date | date }} in order to format the date using Angular's default date format. I could also specify a custom format.

First, Here Are the Requirements for What I Wanted to Achieve


I wanted to be able to edit my todos inline or in place. So I would be able to click to edit my todo description and have the enter key result in saving the edited todo. Sweet and simple. No forms or popups. Definitely no new pages! (Pressing escape or clicking outside the element being edited would cause it to lose focus, but not lose the edits until the user either returns to complete the edits and presses enter to save or performs some other action that causes the changes to be discarded.)

There's a bunch of directives people have written to get this to work, but none of them performed satisfactorily enough for me despite plenty of tinkering from me.

Along the way, I discovered HTML5's super cool contenteditable feature. Upon this discovery I was hell bent on using it rather than any other fancy approach. As it happens, there's no good documentation on how to get AngularJS (I'm using version 1.4 beta) with contenteditable.

I'll come back to this blog post shortly and provide more detail, but after struggling with this for a while, here's a summary of what I found out.

The Issue and the Resolution


The foundation for my effort was provided by Dmitri Akatov's library.

The odd behavior I saw was that if I used a template on a contenteditable element, as soon as I typed a single key, AngularJS would move the cursor to the beginning of the text. Very frustrating, of course. After trying a number of directives, libraries, etc., the solution that worked for me is rather simple.

If I am going to make an element editable, then I don't use a template. Instead, I provide a model for it, e.g. ng-model="todo.description". If I'm not making an element editable, I provide a template for it, e.g. {{ todo.created_date | date }}.

Careful observers will note that both model and template provide granular information about how the data maps to the model. So, you really should only need to provide one or the other. I learned this the hard way, because there are no good documents or examples on the web showing how to do exactly what I was attempting.

Caveats


Although contenteditable is cool to explore, be aware that support for it is still a bit shaky and will vary across browsers. There's a good discussion on some of the pros and cons here.

Next Steps


Over the next few days, I will test this solution out more thoroughly to look for any gaps. Then I will deploy the application to Heroku and add the code to GitHub. I'll return to this blog post and add links so that you can follow along more easily.

You can help to spread the good word by liking and sharing!

Thanks and cheers.


Update


Folks, as promised, here are the links.

App

Code

Saturday, January 3, 2015

Adriano, the Arduino Robot | Step 3 (L293D Controlled)


[Everything in this robot is built from scratch, no kits used (except for the chassis).]

Click here to view the previous steps in this series.

Step 1 (Basic Operation)

Step 2 (Remote Controlled)

Further to adding the remote control feature, I added the L293D H bridge chip to allow the Arduino to reverse motor direction. This also allows for the removal of the 2N2222 transistors that were previously managing the power supply to the motors based on signals received from the Arduino.


As you can see from the video and the schematic, using the L293D chip significantly reduces the complexity and bulk of the circuit. On the other hand, you now need to respond to one more remote key press (down/reverse) and issue two more pin signals (reverse action, one for each motor).

Friday, January 2, 2015

Adriano, the Arduino 2WD Robot | Step 2 (Remote Controlled)


[Everything in this robot is built from scratch, no kits used (except for the chassis).]

I finally found the time to add remote control capability to the robot I had created around this time last year. Check out my earlier blog entry for details on how I created the core robot.

After building the core robot (see link above) and getting it working, I decided that the next best step would be to add remote control capability to it so that it could be moved around as desired. I decided to try the Vishay TSOP4838 infrared remote receiver/sensor. I first created a proof of concept for the remote and the receiver.


Even though I have several remotes at home, I decided to buy a cheap and simple remote just for the robot so that I could do all of my testing without interrupting those at home who wanted to watch TV. As it turns out, any infrared remote can be made to work with the robot. Just get your program to spit out (to the serial console) the received raw codes from the remote for each key. Then you can program the actions you want the robot to take in response to each key. I ended up programing the arrow keys (forward, backward, left, right) and the OK key (stop). The Comcast remote turned out to be the most usable of the lot due to the size and placement of its arrow keys. Everything works reasonably well. Occasionally the remote seems to ignore a remote key press even though the key press is received. I added an LED to indicate when a key press is received so that I know whether the key press wasn't received or whether the key press was just ignored. In the cases where the key press is ignored, I'm guessing that their the Arduino is too busy to process the key press or the key press code got mangled due to interference and the code received was not a code that the program recognized. This is a good topic for further research/investigation.

Anyhow, here's how I integrated the remote capability into the core robot I had build earlier.


Click here to view the other steps in this series.

Step 1 (Basic Operation)

Step 3 (L293D Controlled)