Skip to content
Browse files

adding projects

  • Loading branch information...
1 parent f68a8a8 commit 6f3050a6650fc469efd7015c922c466c3cc80c7f @haithembelhaj committed Apr 9, 2012
Showing with 1 addition and 335 deletions.
  1. +0 −334 models/devthought.md
  2. +1 −1 models/posts.json
View
334 models/devthought.md
@@ -1,334 +0,0 @@
-## Introduction
-Lately, I've been fascinated by the Hipe given to [node.js](http://nodejs.org/) and wanted to give it a try. As a result, this is my first experiment with it, an awesome Portfolio and Blog website build with the magical frameworks [express](http://expressjs.com/) and [backbone](http://backbonejs.org/).
-I was rapidly blown away by how little code you need to start a server and mostly by the ability to control all the requests as you like with Node. Coming from PHP background with nginx as my server of choice, this was a new playground and a hole new concept. It changed the way I understand the web forever. I played with it for a couple of hours and then realized that I needed some sort of easy way to serve my routes.
-
-## Introducing Express
-If you ever heard of of the MVC pattern, Express is a framework that rely on that and makes building your Node app painless. It's sort of the [CakePHP](http://cakephp.org/) of Node. It's has all what you need to start Ruling. So this is what my server `web.js` looks like.
-
- var express = require('express'),
- posts = require('./models/post.js'), // my controller module
- app = express.createServer(express.logger()),
- pub = __dirname + '/public'; //the static files Folder
- port = process.env.PORT || 3000;
-
- //init the app
- app.use(express.static(pub));
- app.set('view engine', 'jade');
- posts.init();
-
- //the routing
- app.get('/', function(req, res) {
- //insertion the collection with locals
- res.render('index',{ collection : posts.getCollection()});
- });
-
- app.get('/post', function(req, res){
- res.send(JSON.stringify(posts.getCollection(res)));
- });
-
- app.get('/post/:id',function(req, res){
- posts.get(req.params.id,res);
- });
-## Introducing Jade
-That's it you have now a working server that can react to the your main routes. As you can see, I'm using [Jade](http://jade-lang.com/) for templating. So here is my `layout.jade` placed in the `views` folder.
-
- !!! 5
- html(lang="en")
- head
- title devThougths
- link(rel="stylesheet", href="/css/style.css")
- script(src="/js/jquery-1.7.1.min.js")
- script(src="/js/json2.js")
- script(src="/js/underscore-min.js")
- script(src="/js/backbone-min.js")
- script(src="js/core.js")
-
- body
- != body
- script(type='text/javascript')
- window.POSTS = !{JSON.stringify(collection)};
-
-What Jade does is pretty cool, as it replaces the `!= body` with the corresponding template. For the main route case, it's the `index.jade` file. The last line demonstrate the locals functionality of express combined with jade.
-
- div#header
- ul#menu
- li#blog
- a(href="#/blog") Blog
- li#projects
- a(href="#/projects") Projects
- li#about
- a(href="#/about") About
- li(style="clear:both; float: none; display:none;")
-
-
-
- div#container
- a#prev prev
- a#next next
- div#content.page.active.ddd
- div#project.page.inactive.ddd
- h2 Under heavy construction
- div#about.page.inactive.ddd
- h2 Under heavy construction
-
- div#footer
-## Introducing Backbone
-Now we have a working Index. We could just continue building all the other views with jade but I wanted to use Backbone in the client side and only serve my posts as JSON Objects to reduce the brandwith and make the website Dripping with awesomeness. But you probaly asking yourself: "What about the history of the navigation throught your site if everything is an AJAX request?". The ansower is Backbone's Homebrew History, using for browser supporting it Html5's History Api. But I'm deseabling it for the purpose of this App and using Hash tags intead.So hier it comes, after including `backbone.js` and it's dependencies, I defined the core of my App in `core.js` like this.
-
- //define the collection
- var Posts = new (Backbone.Collection.extend({
-
- //a collection helper to find posts by their tags
- getByTag : function(tag){
- var result = [];
-
- _.each(this.models,function(model){
- if(_.include(model.get('tags'),tag)) result.push(model);
- })
-
- return result;
- }
- }))();
-
- //the collection url
- //POST, GET, PUT and DELETE queries will be send here
- Posts.url = "/post";
-
- //just refreching my models
- //as I've loaded them in the end of the Body with the script tag
- Posts.reset(window.POSTS);
-
- //define the model
- var Post = Backbone.Model.extend({
-
- Collection: Posts,
-
- });
-
- Posts.model = Post;
-
- //the main View
- var coreView = Backbone.View.extend({
-
- el: $('body'),
-
- posts: [],
-
- //number of posts to display on the main page
- COUNT: 2,
-
- //the post template. A little bit ugly i know :(
- template: _.template('<div id="<%= id %>" class="post"><div class="title">
- +<a href=<%= "#/posts/"+id %>><%= title %></a></div>
- +<div class="info"><div class="date"><%= date %></div>
- +<div class="tags"><% _.each(tags,function(tag){ %>
- +<a class="tag" href=<%="#/tag/"+tag %>><%= tag %></a>
- +<% }) %></div></div>
- +<div class="content"><%= content %></div></div>'),
-
- //I have no events at this time
- events: {
-
- },
-
- initialize: function(){
- // binding "this" to these function
- _.bindAll(this, "render", "renderPost", "renderTag");
- this.initPosts();
- },
-
- //some initialization to facilitate navigation
- initPosts: function(){
- var self = this;
-
- _.each(this.collection.models, function(post){
- self.posts.push(post.id);
- //magical binding
- //This will automaticly lauch the renderPost method if the model changes
- post.on('change', self.renderPost, self);
- })
-
- },
-
- //rendering the first 2 posts
- render: function(){
- var self = this,
- counter = 0;
-
- this.reset();
-
- _.each(this.collection.models, function(post){
- if(counter < self.COUNT){
- // looking if the model has been already fetch
- if(!post.get("content"))post.fetch();
- else self.renderPost(post);
- counter++;
- }
-
- })
-
- },
-
- //post rendering using the template
- renderPost: function(model){
- $(this.template(model.toJSON())).hide().appendTo('div#content').fadeIn();
- },
-
- //these are helper functions
- renderNavigation: function(id){
- var position = _.indexOf(this.posts, id),
- prev = this.posts[position+1],
- next = this.posts[position-1];
-
- if(prev){
- $('a#prev').attr('href', '#/posts/'+prev).fadeIn();
- }else{
- $('a#prev').fadeOut();
- }
- if(next){
- $('a#next').attr('href', '#/posts/'+next).fadeIn();
- }else{
- $('a#next').fadeOut();
- }
- },
-
- renderTag : function(tag){
- var self = this;
- _.each(this.collection.getByTag(tag), function(model){
- if(!model.get("content"))model.fetch();
- else self.renderPost(model)
- });
- },
-
- reset: function(){
- //animation
- this.$('div.post').fadeOut();
- this.$('div#content').empty();
- }
-
- });
-
- //instanciate the View and pass it the Collection
- window.View = new coreView({collection : Posts});
-
- //the Router using HistoryAPI to never reload the page
- var AppRouter = Backbone.Router.extend({
-
- routes: {
- "/posts/:id": "getPost",
- "/tag/:tag" : "showTag",
- "/projects" : "showProjects",
- "/about" : "showAbout",
- "*actions": "defaultRoute"
- },
-
- //view a particular Post
- getPost: function(id) {
-
- if($("div#content").hasClass('inactive')){
- this.showBlog();
- }
-
- var post = window.View.collection.get(id);
- window.View.reset();
-
- if(!post.get("content"))post.fetch();
- else window.View.renderPost(post);
-
- window.View.renderNavigation(id);
- },
-
- //View my Projects
- showProjects: function(){
- $('a#next, a#prev').fadeOut();
- this.toggleActive("project");
- },
-
- //View the about section
- showAbout: function(){
- $('a#next, a#prev').fadeOut();
- this.toggleActive("about");
- },
-
- //Show the Blog
- showBlog: function(){
- this.toggleActive("content");
- },
-
- //Show posts with a given Tag
- showTag: function(tag){
- window.View.reset();
- $('a#next, a#prev').fadeOut();
- window.View.renderTag(tag);
- },
-
- //the default route
- defaultRoute: function(actions){
- $('a#next, a#prev').fadeOut();
- this.showBlog();
- window.View.render();
- },
-
- //helper function
- toggleActive: function(id){
- $("#container .active").removeClass("active").addClass("inactive");
- $("#"+id).removeClass("inactive").addClass("active");
- }
- });
-
- var app_router = new AppRouter;
-
- //start the browser history
- Backbone.history.start();
-## Introducing Node Modules
-Now Backbone will react to `#` links and load the needed view so I just had to implement my controller to send the JSON models to Backbone. Node gives you the possibility to implements modules that you can require on startup. Here is what it looks like.
-
- var fs = require('fs'),
- markdown = require('markdown').markdown, //Using Markdown for the posts content
- MODELS = "models/posts.json", //The collection file
- db = {},
- posts;
-
-
- //some initialization to speed things up
- exports.init = function(res){
- fs.readFile(MODELS, function(err, data){
- if (err) throw err;
- posts = JSON.parse(data.toString('utf8'));
- if(res) res.send('{"success" : "Posts database successfully initialised"}');
- posts.forEach(function(val,index){
- db[val.id] = index;
- });
- });
- };
-
- //return the collection
- exports.getCollection = function(){
- return posts;
- };
-
- exports.get = function(id, res){
- var post = posts[db[id]],
- _post= {};
-
- if(post){
- //Reading the Markdown file corresponding to the post.
- fs.readFile('models/post/'+id+'.md', function(err , data){
- if (err) throw err;
- //Lack of a better method
- //as i don't want the content saved in the collection
- _post.id = post.id;
- _post.title = post.title;
- _post.tags = post.tags;
- _post.date = post.date;
- _post.content = markdown.toHTML(data.toString('utf8'));
- res.send(JSON.stringify(_post));
- });
- }else{
- res.send('{"error" : "post do not exists"}');
- }
- };
-## Final Words
-As you can see, by exporting these method we've made it pssible to read post files and respond to according requests. As of now posts are just manually added and saved as separate markdown files but adding the functionality is plain simple, so I'll just leave it to you. All of it is hosted on [Github](https://github.com/haithembelhaj/devThoughts) so just give it a try and feel awesome as i felt using these Frameworks.
-
-I will be posting my Thougths on Web development and Programming in general so stop by now and then to check them out.
View
2 models/posts.json
@@ -1,2 +1,2 @@
-[{"title":"Getting your hand dirty with Node.js, Express and Backbone","date":"21.1.12","tags":["node","backbone","express"],"id":"devthought"},
+[{"title":"Getting your hand dirty with Node.js, Express and Backbone","date":"21.1.12","tags":["node","backbone","express"],"id":"devthoughts"},
{"title":"Lattee: add some milk to your coffescript","date":"25.3.12","tags":["coffeescript"],"id":"lattee"}]

0 comments on commit 6f3050a

Please sign in to comment.
Something went wrong with that request. Please try again.