Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Wednesday, 13 July 2011

Back of an Envelope Node.js Framework - Discuss

I had a quiet afternoon today and while "keeping up with recent developments in my field" or as you might call it "wasting my afternoon googling" I got to thinking what I'd like a Node.js MVC framework should or could contain.
How design shouldn't be done


Firstly, I've been playing with Node.js for about three weeks now and I'm impressed, but I can't seem to find a framework that I'm happy with. Backbone looked good, but I wasted three days on it and it was too much like hard work. Similarly Spine which tried to be less complicated, but eventually failed. Finally I really wanted Brunch to work but it was a release behind backbone (which is a major component of it) and I didn't want to get lost in the mismatching documentation (the Backbone release was pretty major).

I have spent a whole lot of time over the last couple of years using python frameworks, especially Flask and I like their approach of starting with a good foundation (in their case Werkzeug) and adding the bits that are still needed. Could that work with Node? I mean writing a basic HTTP server looks pretty straight forward and there are tons of modules to add the other functionality.

So with this possibly naive starting position I grabbed my pen and scribble down some stuff I thought I'd need. Now bear in mind that I haven't much used any of these modules yet, and I pinched several of them from the bits that go to make up Brunch.


I'd appreciate any feedback, suggestions and so on that those more learned than I might care to offer. Few of you will be less learned I imagine.


Here are the transcribed notes with some links:

Server
Routing
Data Store
Models
  • JS Object/JSON?
  • ORM?
Views
    -CSS
    -Templating
Controllers
Middleware
  • how? Express
Other Stuff

If you spot any typos, inaccuracies or just plain lies then please let me know.

Sunday, 26 June 2011

Simplest Ever Backbone.js/CoffeeScript Example

I'm teaching myself to use Backbone because after having done quite a lot of JavaScript in work lately, it has become obvious to me that I need a framework.

I'm also learning how to use CoffeeScript, which is close enough to python/ruby for me to understand.

First thing that I noticed is that most of the examples for Backbone out there are in pure JavaScript, so I thought I'd do my bit by providing something in CoffeeScript.

To that end, here is a very simple app which displays a number. You can increase or decrease the count by clicking buttons.

The app.coffee code:

window.app = {}
app.controllers = {}
app.models = {}
app.views = {}
class window.MainController extends Backbone.Controller
routes :
"": "home"
"home": "home"
home: ->
app.views.counter.render()
class window.Counter extends Backbone.Model
defaults:
count: 0
class window.CounterView extends Backbone.View
initialize: ->
@counter = new Counter()
@render()
el: $('#counter')
events:
'click button#inc-count' : 'inc'
'click button#dec-count' : 'dec'
render: ->
$(@el).find("#count").html "The count is " \
+ @counter.get("count")
@
inc: ->
ct = @counter.get("count")
@counter.set(count: ct+1)
@render()
dec: ->
ct = @counter.get("count")
@counter.set(count: ct-1)
@render()
head.ready ->
app.controllers.main = new MainController()
app.views.counter = new CounterView()
app.models.counter = new Counter()
Backbone.history.start()
view raw app.coffee hosted with ❤ by GitHub


and the html to go with that:



In detail

At the top, we set up global hashes to store our objects. In a bigger app this would make referencing bits and pieces much easier, although we don't really need it in this example.

window.app = {}
app.controllers = {}
app.models = {}
app.views = {}
view raw 1.coffee hosted with ❤ by GitHub


Next the controller. This one is almost empty except it has two routes both taking you to the home control which is also part of the controller. The route with no reference (the empty string) and the one for #home tagged on the end of your URL (by way of an example) both call the home function in this case.

The home control just tells the view to render itself.

class window.MainController extends Backbone.Controller
routes :
"": "home"
"home": "home"
home: ->
app.views.counter.render()
view raw 2.coffee hosted with ❤ by GitHub


Next the Counter model which has one attribute called count which defaults to zero. In reality I think you would want to synchronize your models with a database, but we'll do that in another post soon.

class window.Counter extends Backbone.Model
defaults:
count: 0
view raw 3.coffee hosted with ❤ by GitHub


And now for the View. The View is obviously what you are seeing in the browser. In our trivial example we only have one view, but a real app would probably have several. A view lumps together a unit of the app, sometimes nowadays we call these widgets, or blocks or display regions or whatever. You get the idea.

In the initialize function, we just connect the view to the model that backs it. The events connect the button to the functions that they call. The render function draws the result into the #count div; the @ symbol at the end is shorthand for this. In CoffeeScript (like Ruby) the last line of a function gets returned even if you don't specifically say "return". So in other words it means "return this". This is handy since it lets us chain together functions.

The inc and dec functions increase and decrease the count in the model and then update the display. Please see the update here.

class window.CounterView extends Backbone.View
initialize: ->
@counter = new Counter()
el: $('#counter')
events:
'click button#inc-count' : 'inc'
'click button#dec-count' : 'dec'
render: ->
$(@el).find("#count").html "The count is " \
+ @counter.get("count")
@
inc: ->
ct = @counter.get("count")
@counter.set(count: ct+1)
@render()
dec: ->
ct = @counter.get("count")
@counter.set(count: ct-1)
@render()
view raw 4.coffee hosted with ❤ by GitHub


Finally the equivalent of the main() function which instaniates the bits and bobs and then starts the history. I've no idea why they called it history, but basically it starts up all the listeners.

head.ready ->
app.controllers.main = new MainController()
app.views.counter = new CounterView()
app.models.counter = new Counter()
Backbone.history.start()
view raw 5.coffee hosted with ❤ by GitHub


That's all for now. Next time I'll show you how to connect all this to your database using python and Flask.

If you see anything wrong with what I've written here or if you spot spelling or other mistakes then please let me know.

Tuesday, 7 June 2011

Installing Node.js on Ubuntu 11.04 and Mint 11

Installing Node.js is simple and let's you get play with all the Javascript goodness that it offers.

Another reason to install it is to use Flask-CSS (and hence lesscss) which I mentioned in my last article, so I thought I'd better cover that now.

Let's install it in our home directory:

cd ~
rm -fr node # in case this is a fresh install

sudo apt-get install -y g++ curl libssl-dev apache2-utils git-core
wget http://nodejs.org/dist/node-v0.4.9.tar.gz
tar xfz http://nodejs.org/dist/node-v0.4.9.tar.gz
cd node-v0.4.9 && ./configure 
# or the bleeding edge version
# git clone git://github.com/joyent/node.git 
# cd node && ./configure 
make 
sudo make install


and finally you need to add the following to your ~/.bashrc file:

export PATH="$HOME/node/bin:$PATH"

Finally install NPM (Node Package Manager):

source ~/.bashrc
curl http://npmjs.org/install.sh | sudo sh

Simples!

Thanks to: