Last active
December 21, 2015 03:28
-
-
Save arktisklada/6242116 to your computer and use it in GitHub Desktop.
Backbone.js Blog Sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is the code-along example to work through and build during class. It demonstrates creating a model, collection, views, and a router. All the code is in scripts.js. | |
Components: | |
* A Post model for blog posts | |
* A Posts collection to hold all the blog posts | |
* Views for home and post view | |
* A basic object to hold the template strings | |
* PostListView subview with a click event | |
* The application router |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Backbone.JS-powered Blog</title> | |
<link href="styles.css" rel="stylesheet" /> | |
</head> | |
<body> | |
<!-- This will be our main container --> | |
<div id="main"> | |
</div> | |
<script src="http://code.jquery.com/jquery-1.10.2.min.js" language="javascript" type="text/javascript"></script><!-- for selectors, and eventually ajax --> | |
<script src="http://underscorejs.org/underscore-min.js" language="javascript" type="text/javascript"></script><!-- requirement for backbone --> | |
<script src="http://tryhandlebarsjs.com/js/libs/handlebars.js" language="javascript" type="text/javascript"></script><!-- handlebars templating --> | |
<script src="http://backbonejs.org/backbone-min.js" language="javascript" type="text/javascript"></script><!-- backbone.js library --> | |
<script src="scripts.js"></script><!-- our backbone app code --> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(function() { | |
// Object to hold the template HTML | |
var templates = { | |
appView: '<h1>Recent Posts</h1><ul id="posts"></ul>', | |
// blogList: '<a href="#/posts/{{slug}}">{{title}}</a>', // optional replacement for blogList template that uses <a> tags | |
blogList: '{{title}}', | |
blogView: '<div class="post"><h1 class="title">{{title}}</h1><h3 class="slug">{{slug}}</h3><div class="content">{{{content}}}</div></div>' | |
} | |
// Create a model for the posts | |
var Post = Backbone.Model.extend({ | |
// let's look up our blog post by slug instead of id | |
idAttribute: 'slug', | |
// Posts have a title and content, and here we set default values | |
defaults:{ | |
title: 'New post', | |
slug: 'new-post', | |
content: 'title' | |
} | |
}); | |
// Create a collection of blog posts | |
var Posts = Backbone.Collection.extend({ | |
// Declare the model for this collection | |
model: Post | |
}); | |
// This view turns a post model into rendered HTML for the home page | |
var PostListView = Backbone.View.extend({ | |
// This is the tag type that each of our post titles will be nested under | |
tagName: 'li', | |
// Creating a click event on each view object to show the contents and navigate to the post view | |
events:{ | |
'click': 'view' | |
}, | |
// this function is called when the object is created | |
initialize: function() { | |
}, | |
// our render function; populates the template with object data onto the page | |
render: function() { | |
// Generate the handlebars template from our templates object | |
var template = Handlebars.compile(templates.blogList); | |
// Genreate the post list view html from the object data. The .toJSON() function pulls out the data object from the model, and is important here because the templating system accepts an object of key:value pairs | |
this.$el.html(template(this.model.toJSON())); | |
// Returning the object is a good practice so we can do chaining | |
return this; | |
}, | |
// Event handler for the click event | |
view: function() { | |
// navigates to the post view route (/posts/post-slug) | |
app.navigate('posts/' + this.model.get('slug'), true); | |
} | |
}); | |
// This view displays a post title, slug, and contents | |
var PostView = Backbone.View.extend({ | |
// this is the main element to send our template into | |
el: $('#main'), | |
initialize: function() { | |
// This section is NOT IDEAL -- the contents of this function should be in a render function, but demonstrates how this function is called on a new object creation as well as the flexibility. | |
// Generate the Handlebars template from our object | |
var template = Handlebars.compile(templates.blogView); | |
// populate the template with model data and replace our main content with this new template view | |
this.$el.html(template(this.model.toJSON())); | |
} | |
}); | |
// The main view of the application | |
var AppView = Backbone.View.extend({ | |
// Base the view on a specific existing element | |
el: $('#main'), | |
// Let's initialize this view by populating the template and caching a selector | |
initialize: function() { | |
// Populate the main container with our appView template | |
this.$el.html(templates.appView); | |
// Cache commonly used selectors | |
this.list = $('#posts'); | |
}, | |
// let's render the sub tempaltes for our main app | |
render: function() { | |
// Create views for each post in the Posts collection and append them to the list (underscore style) | |
this.collection.each(function(post) { | |
// generate the backbone view object and set the model | |
var view = new PostListView({ model: post }); | |
// using our cached object from the initialize function, append the new view to the list for display | |
this.list.append(view.render().el); | |
}, this); // "this" is the context in the callback | |
return this; | |
} | |
}); | |
// This is our router/controller for our app | |
var AppRouter = Backbone.Router.extend({ | |
// This is a simple object of routes. The key is the route, and the value is the action | |
routes: { | |
'': 'index', // root path (/) | |
'posts/:slug': 'getPost' // post view path (/posts/post-slug) | |
}, | |
// Initialize the router with test data | |
initialize: function(options) { | |
// pass the options through just in case | |
this.options = options; | |
// Test collection data with 4 posts | |
this.posts = new Posts([ | |
new Post({ title: 'web development', slug: 'web-development', content: '<p>Aliquam condimentum porta dui, at ullamcorper nibh malesuada nec. Nam ornare egestas odio, vitae luctus orci porta sed. Curabitur luctus, metus sed ornare faucibus, velit tellus scelerisque lacus, a tempor risus augue sed lectus.</p><p>Morbi placerat vehicula lectus in pretium. Curabitur orci dui, imperdiet vitae vulputate eget, dapibus sed tortor. Phasellus facilisis fringilla sem nec euismod. Vestibulum eleifend libero non neque imperdiet blandit. Donec adipiscing at ante sed sollicitudin. Etiam elementum ante et placerat posuere.</p>'}), | |
new Post({ title: 'web design', slug: 'web-design', content: '<p>Morbi placerat vehicula lectus in pretium. Curabitur orci dui, imperdiet vitae vulputate eget, dapibus sed tortor. Phasellus facilisis fringilla sem nec euismod. Vestibulum eleifend libero non neque imperdiet blandit. Donec adipiscing at ante sed sollicitudin. Etiam elementum ante et placerat posuere. Nullam eget orci sed turpis dictum condimentum ut eget neque. Integer adipiscing ante quis eros tincidunt, sed scelerisque odio dictum.</p>'}), | |
new Post({ title: 'photography', slug: 'photography', content: '<p>no content</p>'}), | |
new Post({ title: 'coffee drinking', slug: 'coffee-drinking', content: '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In accumsan interdum quam vitae suscipit. </p>'}) | |
]); | |
}, | |
// Index action: renders the AppView with the collection of test posts | |
index: function() { | |
var appView = new AppView({collection: this.posts}); | |
appView.render(); | |
}, | |
// GetPost action: renders an individual post view | |
getPost: function(slug) { | |
// Get our post by slug (the "id") | |
var post = this.posts.get(slug); | |
// Create the view and set the model. Notice how there is no render function called. All display functionality was in the initializer (demonstrates flexibility) | |
new PostView({model: post}); | |
} | |
}); | |
// create the app from the router | |
var app = new AppRouter(); | |
// start our backbone history | |
Backbone.history.start(); | |
// Shows how you can capture the event when a URL change occurs | |
Backbone.history.on('route', function() { | |
// This is how to retrieve the request URI / fragment | |
var fragment = Backbone.history.getFragment(); | |
console.log(Backbone.history.getFragment()); | |
}); | |
// Demonstrates an alterate way of handling routing events, perhaps by breaking apart the router into a router and controller | |
// app.on('route:getPost', function(slug) { | |
// alert("getPost " + slug); | |
// }); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* { | |
margin: 0; | |
padding: 0; | |
} | |
html, body { | |
background-color: #edf0f4; | |
color: #4f4f4f; | |
font: 14px 'Futura', sans-serif; | |
} | |
a, a:visited { | |
outline: none; | |
color: #389dc1; | |
} | |
a:hover { | |
text-decoration: none; | |
} | |
#main { | |
background-color: #fff; | |
color: #6b6b6b; | |
font: bold 24px 'Futura', sans-serif; | |
margin: 30px auto; | |
padding: 30px 0px; | |
width: 700px; | |
border-radius: 6px; | |
box-shadow: 0px 0px 1px #ccc; | |
} | |
#main h1 { | |
font-size: 36px; | |
padding: 0px 0px 20px; | |
text-align: center; | |
text-transform: uppercase; | |
} | |
#posts { | |
list-style: none; | |
margin: 0px auto; | |
width: 600px; | |
} | |
#posts li { | |
background-color: #fbfbfc; | |
color: #85898b; | |
cursor: pointer; | |
font-size:22px; | |
margin-bottom: 15px; | |
padding: 20px 30px; | |
border-radius: 5px; | |
box-shadow: 0px 1px 1px #eee; | |
} | |
.post { | |
padding: 0px 30px; | |
} | |
#main .post h1.title { | |
font-size: 30px; | |
margin-bottom: 0px; | |
padding-bottom: 0px; | |
} | |
.post .slug { | |
font-size: 10px; | |
font-style: italic; | |
text-align: center; | |
} | |
.post .content { | |
font-size: 14px; | |
margin-top: 30px; | |
} | |
.post .content p { | |
margin-top: 20px; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment