├── .gitignore ├── 2011-12-12-cross-domain-backbone-apps.textile ├── CNAME ├── README.md ├── _config.yml ├── _layouts ├── default.html └── post.html ├── _posts ├── 2011-01-26-what-is-a-collection.md ├── 2011-01-27-what-is-a-router.md ├── 2011-01-28-what-is-a-view.md ├── 2011-01-29-what-is-a-model.md ├── 2011-02-01-why-would-you-use-backbone.md ├── 2011-10-10-organizing-backbone-using-modules.md ├── 2011-4-22-nodejs-restify-mongodb-mongoose.md ├── 2011-4-28-infinite-scrolling.md ├── 2011-5-1-cross-domain-sessions.md ├── 2012-8-1-seo-for-single-page-apps.md └── 2013-8-29-real-time-backbone-with-pubnub.md ├── _site ├── 2011-12-12-cross-domain-backbone-apps.html ├── CNAME ├── README.md ├── about.html ├── atom.xml ├── backbone.png ├── chat.html ├── contact.html ├── contribute.html ├── cross-domain-sessions │ └── index.html ├── css │ ├── bootstrap.css │ ├── reset.css │ ├── ribbon.css │ ├── stacklayout.css │ ├── style.css │ └── syntax.css ├── earbits-b.png ├── earbits.png ├── examples.html ├── examples │ ├── cross-domain │ │ ├── README.md │ │ ├── build │ │ │ ├── build.js │ │ │ ├── build.sh │ │ │ ├── output │ │ │ │ ├── css │ │ │ │ │ └── styles.css │ │ │ │ ├── index.html │ │ │ │ └── js │ │ │ │ │ └── main.js │ │ │ ├── r.js │ │ │ └── server │ │ ├── csrf.js │ │ ├── css │ │ │ ├── layout.css │ │ │ ├── menus.css │ │ │ ├── normalize.css │ │ │ ├── styles.css │ │ │ └── theme.css │ │ ├── index.html │ │ ├── js │ │ │ ├── boilerplate.js │ │ │ ├── collections │ │ │ │ └── twitter.js │ │ │ ├── events.js │ │ │ ├── libs │ │ │ │ ├── backbone │ │ │ │ │ ├── backbone-min.js │ │ │ │ │ └── backbone-optamd3-min.js │ │ │ │ ├── jquery │ │ │ │ │ └── jquery-min.js │ │ │ │ ├── require │ │ │ │ │ ├── require.js │ │ │ │ │ └── text.js │ │ │ │ ├── springy │ │ │ │ │ ├── springy.js │ │ │ │ │ └── springyui.js │ │ │ │ └── underscore │ │ │ │ │ └── underscore-min.js │ │ │ ├── main.js │ │ │ ├── models │ │ │ │ ├── model.js │ │ │ │ └── session.js │ │ │ ├── router.js │ │ │ ├── views │ │ │ │ ├── app.js │ │ │ │ └── example │ │ │ │ │ └── page.js │ │ │ └── vm.js │ │ ├── package.json │ │ ├── server.js │ │ └── templates │ │ │ ├── example │ │ │ ├── login.html │ │ │ ├── logout.html │ │ │ └── page.html │ │ │ └── layout.html │ ├── infinite-scroll │ │ ├── README.md │ │ ├── build │ │ │ ├── build.js │ │ │ ├── build.sh │ │ │ ├── output │ │ │ │ ├── css │ │ │ │ │ └── styles.css │ │ │ │ ├── index.html │ │ │ │ └── js │ │ │ │ │ └── main.js │ │ │ ├── r.js │ │ │ └── server │ │ ├── config-sample.js │ │ ├── css │ │ │ ├── layout.css │ │ │ ├── menus.css │ │ │ ├── normalize.css │ │ │ ├── styles.css │ │ │ └── theme.css │ │ ├── index.html │ │ ├── js │ │ │ ├── boilerplate.js │ │ │ ├── collections │ │ │ │ └── twitter.js │ │ │ ├── events.js │ │ │ ├── libs │ │ │ │ ├── backbone │ │ │ │ │ ├── backbone-min.js │ │ │ │ │ └── backbone-optamd3-min.js │ │ │ │ ├── jquery │ │ │ │ │ └── jquery-min.js │ │ │ │ ├── require │ │ │ │ │ ├── require.js │ │ │ │ │ └── text.js │ │ │ │ ├── springy │ │ │ │ │ ├── springy.js │ │ │ │ │ └── springyui.js │ │ │ │ └── underscore │ │ │ │ │ └── underscore-min.js │ │ │ ├── main.js │ │ │ ├── router.js │ │ │ ├── views │ │ │ │ ├── app.js │ │ │ │ └── twitter │ │ │ │ │ └── widget.js │ │ │ └── vm.js │ │ ├── package.json │ │ ├── server.js │ │ └── templates │ │ │ ├── dashboard │ │ │ └── page.html │ │ │ ├── layout.html │ │ │ └── twitter │ │ │ └── list.html │ ├── modular-backbone │ │ ├── README.md │ │ ├── css │ │ │ ├── bootstrap.css │ │ │ ├── style.css │ │ │ └── styles.css │ │ ├── imgs │ │ │ ├── backbone_logo.png │ │ │ └── require_logo.png │ │ ├── index.html │ │ ├── js │ │ │ ├── app.js │ │ │ ├── boilerplate.js │ │ │ ├── collections │ │ │ │ ├── contributors │ │ │ │ │ └── ContributorsCollection.js │ │ │ │ └── projects │ │ │ │ │ └── ProjectsCollection.js │ │ │ ├── libs │ │ │ │ ├── backbone │ │ │ │ │ └── backbone-min.js │ │ │ │ ├── jquery │ │ │ │ │ ├── jquery-min.js │ │ │ │ │ └── jquery-serialize.js │ │ │ │ ├── require │ │ │ │ │ └── require.js │ │ │ │ └── underscore │ │ │ │ │ └── underscore-min.js │ │ │ ├── main.js │ │ │ ├── models │ │ │ │ ├── contributor │ │ │ │ │ └── ContributorModel.js │ │ │ │ ├── owner │ │ │ │ │ └── OwnerModel.js │ │ │ │ └── project │ │ │ │ │ └── ProjectModel.js │ │ │ ├── router.js │ │ │ ├── text.js │ │ │ └── views │ │ │ │ ├── contributors │ │ │ │ ├── ContributorsListView.js │ │ │ │ ├── ContributorsView.js │ │ │ │ └── contributor │ │ │ │ │ └── ContributorView.js │ │ │ │ ├── footer │ │ │ │ └── FooterView.js │ │ │ │ ├── home │ │ │ │ └── HomeView.js │ │ │ │ ├── projects │ │ │ │ ├── ProjectsListView.js │ │ │ │ └── ProjectsView.js │ │ │ │ └── sidebar │ │ │ │ └── SidebarView.js │ │ └── templates │ │ │ ├── contributors │ │ │ ├── contributorsListTemplate.html │ │ │ └── contributorsTemplate.html │ │ │ ├── footer │ │ │ └── footerTemplate.html │ │ │ ├── home │ │ │ └── homeTemplate.html │ │ │ ├── projects │ │ │ ├── projectsListTemplate.html │ │ │ └── projectsTemplate.html │ │ │ └── sidebar │ │ │ └── sidebarTemplate.html │ ├── nodejs-mongodb-mongoose-restify │ │ ├── Gruntfile.js │ │ ├── README.md │ │ ├── app │ │ │ ├── 404.html │ │ │ ├── about │ │ │ │ └── index.html │ │ │ ├── css │ │ │ │ ├── layout.css │ │ │ │ ├── menus.css │ │ │ │ ├── normalize.css │ │ │ │ ├── styles.css │ │ │ │ └── theme.css │ │ │ ├── favicon.ico │ │ │ ├── index.html │ │ │ ├── js │ │ │ │ ├── collections │ │ │ │ │ └── MessagesCollection.js │ │ │ │ ├── libs │ │ │ │ │ ├── backbone │ │ │ │ │ │ └── backbone-min.js │ │ │ │ │ ├── jquery │ │ │ │ │ │ └── jquery-min.js │ │ │ │ │ ├── require │ │ │ │ │ │ ├── require.js │ │ │ │ │ │ └── text.js │ │ │ │ │ └── underscore │ │ │ │ │ │ └── underscore-min.js │ │ │ │ ├── main.js │ │ │ │ ├── models │ │ │ │ │ └── MessageModel.js │ │ │ │ ├── router │ │ │ │ │ └── MainRouter.js │ │ │ │ └── views │ │ │ │ │ ├── MainView.js │ │ │ │ │ ├── cabin │ │ │ │ │ └── CabinView.js │ │ │ │ │ └── guestbook │ │ │ │ │ ├── GuestbookFormView.js │ │ │ │ │ └── GuestbookListView.js │ │ │ ├── messages │ │ │ │ └── index.html │ │ │ └── templates │ │ │ │ ├── guestbook │ │ │ │ ├── guestbookFormTemplate.html │ │ │ │ ├── guestbookListTemplate.html │ │ │ │ └── guestbookTemplate.html │ │ │ │ └── mainTemplate.html │ │ ├── configSample.js │ │ ├── package.json │ │ ├── robots.txt │ │ ├── server-http.js │ │ ├── server-mongo │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ └── server-mongo.js │ │ ├── server.js │ │ └── test │ │ │ ├── index.html │ │ │ ├── lib │ │ │ ├── chai.js │ │ │ ├── expect.js │ │ │ └── mocha │ │ │ │ ├── mocha.css │ │ │ │ └── mocha.js │ │ │ └── runner │ │ │ └── mocha.js │ └── todo-app │ │ ├── css │ │ ├── destroy.png │ │ └── todos.css │ │ ├── index.html │ │ └── js │ │ ├── collections │ │ └── todos.js │ │ ├── libs │ │ ├── backbone │ │ │ ├── backbone-optamd3-min.js │ │ │ └── localstorage.js │ │ ├── jquery │ │ │ └── jquery-min.js │ │ ├── require │ │ │ ├── require.js │ │ │ └── text.js │ │ └── underscore │ │ │ └── underscore-min.js │ │ ├── main.js │ │ ├── models │ │ └── todo.js │ │ ├── templates │ │ ├── stats.html │ │ └── todos.html │ │ └── views │ │ ├── app.js │ │ └── todos.js ├── googleaa49fe030680ef6c.html ├── index.html ├── infinite-scrolling │ └── index.html ├── lessons.html ├── nodejs-restify-mongodb-mongoose │ └── index.html ├── organizing-backbone-using-modules │ └── index.html ├── pygments │ ├── CNAME │ ├── README.md │ ├── about.html │ ├── atom.xml │ ├── chat.html │ ├── contact.html │ ├── contribute.html │ ├── css │ │ ├── reset.css │ │ ├── ribbon.css │ │ ├── stacklayout.css │ │ ├── style.css │ │ └── syntax.css │ ├── examples.html │ ├── examples │ │ └── modular-backbone │ │ │ ├── css │ │ │ └── style.css │ │ │ ├── index.html │ │ │ ├── js │ │ │ ├── app.js │ │ │ ├── boilerplate.js │ │ │ ├── collections │ │ │ │ ├── projects.js │ │ │ │ └── template.js │ │ │ ├── libs │ │ │ │ ├── backbone │ │ │ │ │ ├── backbone-min.js │ │ │ │ │ └── backbone.js │ │ │ │ ├── jquery │ │ │ │ │ ├── jquery-min.js │ │ │ │ │ ├── jquery-serialize.js │ │ │ │ │ └── jquery.js │ │ │ │ ├── require │ │ │ │ │ └── require.js │ │ │ │ └── underscore │ │ │ │ │ ├── underscore-min.js │ │ │ │ │ └── underscore.js │ │ │ ├── main.js │ │ │ ├── models │ │ │ │ └── projects.js │ │ │ ├── order.js │ │ │ ├── router.js │ │ │ ├── text.js │ │ │ └── views │ │ │ │ ├── home │ │ │ │ └── main.js │ │ │ │ ├── projects │ │ │ │ └── list.js │ │ │ │ └── users │ │ │ │ └── list.js │ │ │ └── templates │ │ │ ├── home │ │ │ └── main.html │ │ │ ├── projects │ │ │ └── list.html │ │ │ └── users │ │ │ └── list.html │ ├── index.html │ ├── lessons.html │ ├── organizing-backbone-using-modules │ │ └── index.html │ ├── what-is-a-collection │ │ └── index.html │ ├── what-is-a-model │ │ └── index.html │ ├── what-is-a-router │ │ └── index.html │ ├── what-is-a-view │ │ └── index.html │ └── why-would-you-use-backbone │ │ └── index.html ├── real-time-backbone-with-pubnub │ └── index.html ├── rss.xml ├── seo-for-single-page-apps │ └── index.html ├── videos.html ├── videos │ └── beginner │ │ ├── README.md │ │ ├── index.html │ │ └── phpversion │ │ ├── client │ │ ├── README.md │ │ └── index.html │ │ ├── server │ │ ├── .htaccess │ │ ├── README.md │ │ └── index.php │ │ └── tests │ │ ├── README.md │ │ ├── mirror.php │ │ ├── mirror_test.js │ │ ├── qunit.html │ │ ├── qunit_mirror.html │ │ └── server_test.js ├── what-is-a-collection │ └── index.html ├── what-is-a-model │ └── index.html ├── what-is-a-router │ └── index.html ├── what-is-a-view │ └── index.html └── why-would-you-use-backbone │ └── index.html ├── about.textile ├── atom.xml ├── backbone.png ├── chat.textile ├── contact.textile ├── contribute.textile ├── css ├── bootstrap.css ├── reset.css ├── ribbon.css ├── stacklayout.css ├── style.css └── syntax.css ├── earbits-b.png ├── earbits.png ├── examples.textile ├── examples ├── cross-domain │ ├── README.md │ ├── build │ │ ├── build.js │ │ ├── build.sh │ │ ├── output │ │ │ ├── css │ │ │ │ └── styles.css │ │ │ ├── index.html │ │ │ └── js │ │ │ │ └── main.js │ │ ├── r.js │ │ └── server │ ├── csrf.js │ ├── css │ │ ├── layout.css │ │ ├── menus.css │ │ ├── normalize.css │ │ ├── styles.css │ │ └── theme.css │ ├── index.html │ ├── js │ │ ├── boilerplate.js │ │ ├── collections │ │ │ └── twitter.js │ │ ├── events.js │ │ ├── libs │ │ │ ├── backbone │ │ │ │ ├── backbone-min.js │ │ │ │ └── backbone-optamd3-min.js │ │ │ ├── jquery │ │ │ │ └── jquery-min.js │ │ │ ├── require │ │ │ │ ├── require.js │ │ │ │ └── text.js │ │ │ ├── springy │ │ │ │ ├── springy.js │ │ │ │ └── springyui.js │ │ │ └── underscore │ │ │ │ └── underscore-min.js │ │ ├── main.js │ │ ├── models │ │ │ ├── model.js │ │ │ └── session.js │ │ ├── router.js │ │ ├── views │ │ │ ├── app.js │ │ │ └── example │ │ │ │ └── page.js │ │ └── vm.js │ ├── package.json │ ├── server.js │ └── templates │ │ ├── example │ │ ├── login.html │ │ ├── logout.html │ │ └── page.html │ │ └── layout.html ├── infinite-scroll │ ├── README.md │ ├── build │ │ ├── build.js │ │ ├── build.sh │ │ ├── output │ │ │ ├── css │ │ │ │ └── styles.css │ │ │ ├── index.html │ │ │ └── js │ │ │ │ └── main.js │ │ ├── r.js │ │ └── server │ ├── config-sample.js │ ├── css │ │ ├── layout.css │ │ ├── menus.css │ │ ├── normalize.css │ │ ├── styles.css │ │ └── theme.css │ ├── index.html │ ├── js │ │ ├── boilerplate.js │ │ ├── collections │ │ │ └── twitter.js │ │ ├── events.js │ │ ├── libs │ │ │ ├── backbone │ │ │ │ ├── backbone-min.js │ │ │ │ └── backbone-optamd3-min.js │ │ │ ├── jquery │ │ │ │ └── jquery-min.js │ │ │ ├── require │ │ │ │ ├── require.js │ │ │ │ └── text.js │ │ │ ├── springy │ │ │ │ ├── springy.js │ │ │ │ └── springyui.js │ │ │ └── underscore │ │ │ │ └── underscore-min.js │ │ ├── main.js │ │ ├── router.js │ │ ├── views │ │ │ ├── app.js │ │ │ └── twitter │ │ │ │ └── widget.js │ │ └── vm.js │ ├── package.json │ ├── server.js │ └── templates │ │ ├── dashboard │ │ └── page.html │ │ ├── layout.html │ │ └── twitter │ │ └── list.html ├── modular-backbone │ ├── README.md │ ├── css │ │ ├── bootstrap.css │ │ ├── style.css │ │ └── styles.css │ ├── imgs │ │ ├── backbone_logo.png │ │ └── require_logo.png │ ├── index.html │ ├── js │ │ ├── app.js │ │ ├── boilerplate.js │ │ ├── collections │ │ │ ├── contributors │ │ │ │ └── ContributorsCollection.js │ │ │ └── projects │ │ │ │ └── ProjectsCollection.js │ │ ├── libs │ │ │ ├── backbone │ │ │ │ └── backbone-min.js │ │ │ ├── jquery │ │ │ │ ├── jquery-min.js │ │ │ │ └── jquery-serialize.js │ │ │ ├── require │ │ │ │ └── require.js │ │ │ └── underscore │ │ │ │ └── underscore-min.js │ │ ├── main.js │ │ ├── models │ │ │ ├── contributor │ │ │ │ └── ContributorModel.js │ │ │ ├── owner │ │ │ │ └── OwnerModel.js │ │ │ └── project │ │ │ │ └── ProjectModel.js │ │ ├── router.js │ │ ├── text.js │ │ └── views │ │ │ ├── contributors │ │ │ ├── ContributorsListView.js │ │ │ ├── ContributorsView.js │ │ │ └── contributor │ │ │ │ └── ContributorView.js │ │ │ ├── footer │ │ │ └── FooterView.js │ │ │ ├── home │ │ │ └── HomeView.js │ │ │ ├── projects │ │ │ ├── ProjectsListView.js │ │ │ └── ProjectsView.js │ │ │ └── sidebar │ │ │ └── SidebarView.js │ └── templates │ │ ├── contributors │ │ ├── contributorsListTemplate.html │ │ └── contributorsTemplate.html │ │ ├── footer │ │ └── footerTemplate.html │ │ ├── home │ │ └── homeTemplate.html │ │ ├── projects │ │ ├── projectsListTemplate.html │ │ └── projectsTemplate.html │ │ └── sidebar │ │ └── sidebarTemplate.html ├── nodejs-mongodb-mongoose-restify │ ├── .editorconfig │ ├── .gitattributes │ ├── .gitignore │ ├── .jshintrc │ ├── .npmignore │ ├── Gruntfile.js │ ├── README.md │ ├── app │ │ ├── 404.html │ │ ├── about │ │ │ └── index.html │ │ ├── css │ │ │ ├── layout.css │ │ │ ├── menus.css │ │ │ ├── normalize.css │ │ │ ├── styles.css │ │ │ └── theme.css │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── js │ │ │ ├── collections │ │ │ │ └── MessagesCollection.js │ │ │ ├── libs │ │ │ │ ├── backbone │ │ │ │ │ └── backbone-min.js │ │ │ │ ├── jquery │ │ │ │ │ └── jquery-min.js │ │ │ │ ├── require │ │ │ │ │ ├── require.js │ │ │ │ │ └── text.js │ │ │ │ └── underscore │ │ │ │ │ └── underscore-min.js │ │ │ ├── main.js │ │ │ ├── models │ │ │ │ └── MessageModel.js │ │ │ ├── router │ │ │ │ └── MainRouter.js │ │ │ └── views │ │ │ │ ├── MainView.js │ │ │ │ ├── cabin │ │ │ │ └── CabinView.js │ │ │ │ └── guestbook │ │ │ │ ├── GuestbookFormView.js │ │ │ │ └── GuestbookListView.js │ │ ├── messages │ │ │ └── index.html │ │ └── templates │ │ │ ├── guestbook │ │ │ ├── guestbookFormTemplate.html │ │ │ ├── guestbookListTemplate.html │ │ │ └── guestbookTemplate.html │ │ │ └── mainTemplate.html │ ├── configSample.js │ ├── package.json │ ├── robots.txt │ ├── server-http.js │ ├── server-mongo │ │ ├── README.md │ │ ├── package.json │ │ └── server-mongo.js │ ├── server.js │ └── test │ │ ├── index.html │ │ ├── lib │ │ ├── chai.js │ │ ├── expect.js │ │ └── mocha │ │ │ ├── mocha.css │ │ │ └── mocha.js │ │ └── runner │ │ └── mocha.js └── todo-app │ ├── css │ ├── destroy.png │ └── todos.css │ ├── index.html │ └── js │ ├── collections │ └── todos.js │ ├── libs │ ├── backbone │ │ ├── backbone-optamd3-min.js │ │ └── localstorage.js │ ├── jquery │ │ └── jquery-min.js │ ├── require │ │ ├── require.js │ │ └── text.js │ └── underscore │ │ └── underscore-min.js │ ├── main.js │ ├── models │ └── todo.js │ ├── templates │ ├── stats.html │ └── todos.html │ └── views │ ├── app.js │ └── todos.js ├── googleaa49fe030680ef6c.html ├── index.html ├── lessons.textile ├── pygments ├── CNAME ├── README.md ├── about.html ├── atom.xml ├── chat.html ├── contact.html ├── contribute.html ├── css │ ├── reset.css │ ├── ribbon.css │ ├── stacklayout.css │ ├── style.css │ └── syntax.css ├── examples.html ├── examples │ └── modular-backbone │ │ ├── css │ │ └── style.css │ │ ├── index.html │ │ ├── js │ │ ├── app.js │ │ ├── boilerplate.js │ │ ├── collections │ │ │ ├── projects.js │ │ │ └── template.js │ │ ├── libs │ │ │ ├── backbone │ │ │ │ ├── backbone-min.js │ │ │ │ └── backbone.js │ │ │ ├── jquery │ │ │ │ ├── jquery-min.js │ │ │ │ ├── jquery-serialize.js │ │ │ │ └── jquery.js │ │ │ ├── require │ │ │ │ └── require.js │ │ │ └── underscore │ │ │ │ ├── underscore-min.js │ │ │ │ └── underscore.js │ │ ├── main.js │ │ ├── models │ │ │ └── projects.js │ │ ├── order.js │ │ ├── router.js │ │ ├── text.js │ │ └── views │ │ │ ├── home │ │ │ └── main.js │ │ │ ├── projects │ │ │ └── list.js │ │ │ └── users │ │ │ └── list.js │ │ └── templates │ │ ├── home │ │ └── main.html │ │ ├── projects │ │ └── list.html │ │ └── users │ │ └── list.html ├── index.html ├── lessons.html ├── organizing-backbone-using-modules │ └── index.html ├── what-is-a-collection │ └── index.html ├── what-is-a-model │ └── index.html ├── what-is-a-router │ └── index.html ├── what-is-a-view │ └── index.html └── why-would-you-use-backbone │ └── index.html ├── rss.xml ├── videos.textile └── videos └── beginner ├── README.md ├── index.html └── phpversion ├── client ├── README.md └── index.html ├── server ├── .htaccess ├── README.md └── index.php └── tests ├── README.md ├── mirror.php ├── mirror_test.js ├── qunit.html ├── qunit_mirror.html └── server_test.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *config.js 3 | *node_modules/ 4 | .DS_Store 5 | *.sublime-project 6 | *.sublime-workspace -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | backbonetutorials.com 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Backbone Tutorials 3 | 4 | This site is by no means the definitive guide to backbone.js and all corrections and contributions are welcome. 5 | 6 | About Backbone Tutorials: 7 | 8 | As single page apps and large scale javascript applications become more prominent on the web, useful resources for those developers who are jumping the ship are crucial. 9 | 10 | I started this site to not only consolidate my understanding of backbone.js, but to also document what I have learned thus far for myself and others. 11 | 12 | Thomas Davis - [@neutralthoughts](http://twitter.com/neutralthoughts) - Twitter 13 | 14 | ## Contributions 15 | 16 | * Thanks to Cactus([https://github.com/cactus](https://github.com/cactus)) for creating the blog feed 17 | * Thanks to Wes Bos ([https://github.com/wesbos](https://github.com/wesbos)) for CSS fixes 18 | * Thanks to Paul Irish ([https://github.com/paulirish](https://github.com/paulirish)) for tutorial clarification 19 | 20 | ## About the author 21 | 22 | **Contact:** 23 | 24 | * [@neutralthoughts](http://twitter.com/neutralthoughts) on twitter 25 | * GitHub - https://github.com/thomasdavis 26 | * thomasalwyndavis@gmail.com 27 | 28 | **Projects:** 29 | 30 | * JavaScript Library CDN - http://cdnjs.com 31 | * Backbone.js Tutorials - http://backbonetutorials.com 32 | * Proposal Generation Start up - http://protosal.com 33 | * Technical Blog - http://thomasdavis.github.com 34 | * Quora - http://www.quora.com/Thomas-Davis 35 | * StackOverflow - http://stackoverflow.com/users/580675/thomas-davis 36 | 37 | Love you mum! 38 | Clicky 39 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | markdown: redcarpet 2 | pygments: true 3 | permalink: /:title 4 | -------------------------------------------------------------------------------- /_layouts/post.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | 6 | 7 | 8 |
9 | {{ content }} 10 |
11 |
12 |
13 |
14 |
15 | 16 |

Thomas Davis

17 |

Founder of cdnjs.com, jsonresume.org

18 |

Work with Drones, Open Source, Tech Policy, Javascript and Music.

19 |
20 |
21 | github.com/thomasdavis 22 |
23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 |
31 | 42 | -------------------------------------------------------------------------------- /_site/CNAME: -------------------------------------------------------------------------------- 1 | backbonetutorials.com 2 | -------------------------------------------------------------------------------- /_site/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Backbone Tutorials 3 | 4 | This site is by no means the definitive guide to backbone.js and all corrections and contributions are welcome. 5 | 6 | About Backbone Tutorials: 7 | 8 | As single page apps and large scale javascript applications become more prominent on the web, useful resources for those developers who are jumping the ship are crucial. 9 | 10 | I started this site to not only consolidate my understanding of backbone.js, but to also document what I have learned thus far for myself and others. 11 | 12 | Thomas Davis - [@neutralthoughts](http://twitter.com/neutralthoughts) - Twitter 13 | 14 | ## Contributions 15 | 16 | * Thanks to Cactus([https://github.com/cactus](https://github.com/cactus)) for creating the blog feed 17 | * Thanks to Wes Bos ([https://github.com/wesbos](https://github.com/wesbos)) for CSS fixes 18 | * Thanks to Paul Irish ([https://github.com/paulirish](https://github.com/paulirish)) for tutorial clarification 19 | 20 | ## About the author 21 | 22 | **Contact:** 23 | 24 | * [@neutralthoughts](http://twitter.com/neutralthoughts) on twitter 25 | * GitHub - https://github.com/thomasdavis 26 | * thomasalwyndavis@gmail.com 27 | 28 | **Projects:** 29 | 30 | * JavaScript Library CDN - http://cdnjs.com 31 | * Backbone.js Tutorials - http://backbonetutorials.com 32 | * Proposal Generation Start up - http://protosal.com 33 | * Technical Blog - http://thomasdavis.github.com 34 | * Quora - http://www.quora.com/Thomas-Davis 35 | * StackOverflow - http://stackoverflow.com/users/580675/thomas-davis 36 | 37 | Love you mum! 38 | Clicky 39 | -------------------------------------------------------------------------------- /_site/backbone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/backbone.png -------------------------------------------------------------------------------- /_site/css/stacklayout.css: -------------------------------------------------------------------------------- 1 | /* 2 | * StackLayout by Campbell McGuiness 3 | * 4 | * http://stacklayout.com/ 5 | * http://twitter.com/stacklayout 6 | * http://www.decalcms.com/ 7 | * http://workingsoftware.com.au/ 8 | * 9 | * This work is licensed under Creative Commons * Attribution-ShareAlike 3.0 Australia License * http://creativecommons.org/licenses/by-sa/3.0/au/ 10 | * 11 | * Please retain this credit and let us know if you use StackLayout for inclusion on http://stacklayout.com/who.html 12 | * 13 | * cam@workingsoftware.com.au 14 | */ 15 | .stack, 16 | .stack1of2, 17 | .stack1of3, 18 | .stack2of3, 19 | .stack1of4, 20 | .stack3of4, 21 | .stack1of5, 22 | .stack2of5, 23 | .stack3of5, 24 | .stack4of5, 25 | .stackAuto 26 | { 27 | display:inline-block; 28 | letter-spacing:-0.65em; 29 | word-spacing:-0.65em; 30 | text-align:center; 31 | vertical-align:top; 32 | } 33 | .stackContent 34 | { 35 | display:block; 36 | letter-spacing:normal; 37 | word-spacing:normal; 38 | text-align:left; 39 | } 40 | .stackContent:after 41 | { 42 | content:"."; 43 | display:block; 44 | height:0; 45 | clear:both; 46 | visibility:hidden; 47 | } 48 | .stackAuto .stackContent 49 | { 50 | text-align:center; 51 | } 52 | .stackAuto 53 | { 54 | width:auto; 55 | } 56 | .stack 57 | { 58 | width:100%; 59 | } 60 | .stack1of2 61 | { 62 | width:50%; 63 | } 64 | .stack1of3 65 | { 66 | width:33.334%; 67 | } 68 | .stack2of3 69 | { 70 | width:66.667%; 71 | } 72 | .stack1of4 73 | { 74 | width:25%; 75 | } 76 | .stack3of4 77 | { 78 | width:75%; 79 | } 80 | .stack1of5 81 | { 82 | width:20%; 83 | } 84 | .stack2of5 85 | { 86 | width:40%; 87 | } 88 | .stack3of5 89 | { 90 | width:60%; 91 | } 92 | .stack4of5 93 | { 94 | width:80%; 95 | } 96 | -------------------------------------------------------------------------------- /_site/css/style.css: -------------------------------------------------------------------------------- 1 | #post h1 { 2 | font-size: 32px !important; 3 | } 4 | #post h2 { 5 | font-size: 26px !important; 6 | } 7 | #post h3 { 8 | font-size: 20px !important; 9 | } 10 | 11 | .container { 12 | max-width: 840px !important ; 13 | } 14 | /* 15 | body { 16 | font: 1em "Arvo","Helvetica Neue",Helvetica,Arial,sans-serif !important; 17 | text-shadow: 0 0 4px #CCC !important; 18 | color: #333; 19 | font-size: 14px !important; 20 | } 21 | */ 22 | 23 | pre { 24 | background-color: #49483e !important; 25 | } -------------------------------------------------------------------------------- /_site/earbits-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/earbits-b.png -------------------------------------------------------------------------------- /_site/earbits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/earbits.png -------------------------------------------------------------------------------- /_site/examples/cross-domain/README.md: -------------------------------------------------------------------------------- 1 | Message me if you need a hand getting this to work 2 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/build/build.js: -------------------------------------------------------------------------------- 1 | ({ 2 | name: '../js/main', 3 | baseUrl: '../js', 4 | out: 'output/js/main.js', 5 | findNestedDependencies: true, 6 | mainConfigFile: '../js/main.js' 7 | }) 8 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/build/build.sh: -------------------------------------------------------------------------------- 1 | rm -rf output 2 | node r.js -o build.js 3 | node r.js -o cssIn=../css/styles.css out=output/css/styles.css 4 | 5 | cp ../index.html output/index.html 6 | sed -i 's/js\/libs\/require\/require.js/http:\/\/requirejs.org\/docs\/release\/1.0.5\/minified\/require.js/g' output/index.html 7 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/build/output/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Backbone Boilerplate 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/build/output/js/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/examples/cross-domain/build/output/js/main.js -------------------------------------------------------------------------------- /_site/examples/cross-domain/build/server: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var express = require("express"); 3 | var site = express.createServer(); 4 | 5 | site.use(express.static(__dirname + '/..')); 6 | 7 | site.use(express.favicon("./favicon.ico")); 8 | 9 | site.get("*", function(req, res) { 10 | fs.createReadStream("./index.html").pipe(res); 11 | }); 12 | 13 | site.listen(1337); 14 | 15 | console.log("Server listening on http://localhost:1337"); 16 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/csrf.js: -------------------------------------------------------------------------------- 1 | 2 | // TODO - Write a better csrf module lol 3 | // hacked this together for the tutorial 4 | 5 | var crypto = require('crypto'); 6 | 7 | var generateToken = function(len) { 8 | return crypto.randomBytes(Math.ceil(len * 3 / 4)) 9 | .toString('base64') 10 | .slice(0, len); 11 | }; 12 | function defaultValue(req) { 13 | return (req.body && req.body._csrf) 14 | || (req.query && req.query._csrf) 15 | || (req.headers['x-csrf-token']); 16 | } 17 | var checkToken = function(req, res, next){ 18 | var token = req.session._csrf || (req.session._csrf = generateToken(24)); 19 | if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next(); 20 | var val = defaultValue(req); 21 | if (val != token) return next(function(){ 22 | res.send({auth: false}); 23 | }); 24 | next(); 25 | } 26 | var newToken = function(req, res, next) { 27 | var token = req.session._csrf || (req.session._csrf = generateToken(24)); 28 | next(); 29 | } 30 | module.exports = { 31 | check: checkToken, 32 | generate: newToken 33 | }; 34 | 35 | 36 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/css/layout.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | .container { 6 | margin: auto; 7 | width: 400px; 8 | } 9 | .page { 10 | margin: 10px 0 10px 0; 11 | } 12 | .submenu { 13 | width: 200px; 14 | float: left; 15 | } 16 | .content { 17 | width: 460px; 18 | float: left; 19 | } 20 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/css/menus.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | } 6 | .menu li { 7 | float: left; 8 | margin-left: 10px; 9 | } 10 | 11 | .menu li.other-link { 12 | float: right; 13 | } 14 | 15 | a.active { 16 | color: #000; 17 | text-decoration: none; 18 | } 19 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Not really too concerned with how to organize CSS 2 | the opinions are too diverse */ 3 | 4 | /* Third party helper libraries */ 5 | @import url("normalize.css"); 6 | 7 | /* Custom themes */ 8 | @import url("theme.css"); 9 | @import url("menus.css"); 10 | @import url("layout.css"); 11 | 12 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/css/theme.css: -------------------------------------------------------------------------------- 1 | .container { 2 | background-color: #fff; 3 | } 4 | h1 { 5 | font-size: 16px; 6 | } 7 | [disabled=disabled] { 8 | opacity: 0.5; 9 | } 10 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Cross-domain Backbone.js with sessions using CORS 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | // Use this as a quick template for future modules 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone' 6 | ], function($, _, Backbone){ 7 | 8 | return {}; 9 | }); 10 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/collections/twitter.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone' 5 | ], function($, _, Backbone){ 6 | var Tweets = Backbone.Collection.extend({ 7 | url: function () { 8 | return 'http://search.twitter.com/search.json?q=' + this.query + '&page=' + this.page + '&callback=?' 9 | }, 10 | // Because twitter doesn't return an array of models by default we need 11 | // to point Backbone.js at the correct property 12 | parse: function(resp, xhr) { 13 | return resp.results; 14 | }, 15 | page: 1, 16 | query: 'backbone.js' 17 | }); 18 | 19 | return Tweets; 20 | }); 21 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/events.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone' 5 | ], function($, _, Backbone){ 6 | var vent = _.extend({}, Backbone.Events); 7 | return vent; 8 | }); -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/main.js: -------------------------------------------------------------------------------- 1 | // Require.js allows us to configure shortcut alias 2 | // Their usage will become more apparent futher along in the tutorial. 3 | require.config({ 4 | paths: { 5 | // Major libraries 6 | jquery: 'libs/jquery/jquery-min', 7 | underscore: 'libs/underscore/underscore-min', // https://github.com/amdjs 8 | backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs 9 | sinon: 'libs/sinon/sinon.js', 10 | 11 | // Require.js plugins 12 | text: 'libs/require/text', 13 | order: 'libs/require/order', 14 | 15 | // Just a short cut so we can put our html outside the js dir 16 | // When you have HTML/CSS designers this aids in keeping them out of the js directory 17 | templates: '../templates' 18 | }, 19 | urlArgs: "bust=" + (new Date()).getTime() 20 | 21 | }); 22 | 23 | // Let's kick off the application 24 | 25 | require([ 26 | 'views/app', 27 | 'router', 28 | 'vm' 29 | ], function(AppView, Router, Vm){ 30 | var appView = Vm.create({}, 'AppView', AppView); 31 | Router.initialize({appView: appView}); 32 | appView.render(); // render() calls Backbone.history when its ready to start 33 | }); 34 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/models/model.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone' 4 | ], function(_, Backbone) { 5 | var projectsModel = Backbone.Model.extend({ 6 | defaults: { 7 | score: 10 8 | }, 9 | initialize: function(){ 10 | } 11 | 12 | }); 13 | return projectsModel; 14 | 15 | }); 16 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/router.js: -------------------------------------------------------------------------------- 1 | // Filename: router.js 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'vm' 7 | ], function ($, _, Backbone, Vm) { 8 | var AppRouter = Backbone.Router.extend({ 9 | routes: { 10 | '*actions': 'defaultAction' // All urls will trigger this route 11 | } 12 | }); 13 | 14 | var initialize = function(options){ 15 | var appView = options.appView; 16 | var router = new AppRouter(options); 17 | 18 | router.on('route:defaultAction', function (actions) { 19 | require(['views/example/page'], function (ExamplePage) { 20 | var examplePage = Vm.create(appView, 'ExamplePage', ExamplePage); 21 | examplePage.render(); 22 | }); 23 | }); 24 | 25 | }; 26 | return { 27 | initialize: initialize 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/views/app.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'vm', 6 | 'events', 7 | 'models/session', 8 | 'text!templates/layout.html' 9 | ], function($, _, Backbone, Vm, Events, Session, layoutTemplate){ 10 | var AppView = Backbone.View.extend({ 11 | el: '.container', 12 | initialize: function () { 13 | 14 | // This snipper should usually be loaded elsewhere 15 | // It simply takes a
and converts its values to an object 16 | $.fn.serializeObject = function() { 17 | var o = {}; 18 | var a = this.serializeArray(); 19 | $.each(a, function() { 20 | if (o[this.name] !== undefined) { 21 | if (!o[this.name].push) { 22 | o[this.name] = [o[this.name]]; 23 | } 24 | o[this.name].push(this.value || ''); 25 | } else { 26 | o[this.name] = this.value || ''; 27 | } 28 | }); 29 | return o; 30 | }; 31 | 32 | 33 | $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { 34 | // Your server goes below 35 | options.url = 'http://localhost:8000' + options.url; 36 | // options.url = 'http://cross-domain.nodejitsu.com' + options.url; 37 | }); 38 | 39 | }, 40 | render: function () { 41 | var that = this; 42 | $(this.el).html(layoutTemplate); 43 | // This is the entry point to your app, therefore 44 | // when the user refreshes the page we should 45 | // really know if they're authed. We will give it 46 | // A call back when we know what the auth status is 47 | Session.getAuth(function () { 48 | Backbone.history.start(); 49 | }) 50 | } 51 | }); 52 | return AppView; 53 | }); 54 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/views/example/page.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/session', 6 | 'text!templates/example/login.html', 7 | 'text!templates/example/logout.html' 8 | ], function($, _, Backbone, Session, exampleLoginTemplate, exampleLogoutTemplate){ 9 | var ExamplePage = Backbone.View.extend({ 10 | el: '.page', 11 | initialize: function () { 12 | var that = this; 13 | // Bind to the Session auth attribute so we 14 | // make our view act recordingly when auth changes 15 | Session.on('change:auth', function (session) { 16 | that.render(); 17 | }); 18 | }, 19 | render: function () { 20 | // Simply choose which template to choose depending on 21 | // our Session models auth attribute 22 | if(Session.get('auth')){ 23 | this.$el.html(_.template(exampleLogoutTemplate, {username: Session.get('username')})); 24 | } else { 25 | this.$el.html(exampleLoginTemplate); 26 | } 27 | }, 28 | events: { 29 | 'submit form.login': 'login', // On form submission 30 | 'click .logout': 'logout' 31 | }, 32 | login: function (ev) { 33 | // Disable the button 34 | $('[type=submit]', ev.currentTarget).val('Logging in').attr('disabled', 'disabled'); 35 | // Serialize the form into an object using a jQuery plgin 36 | var creds = $(ev.currentTarget).serializeObject(); 37 | Session.login(creds); 38 | return false; 39 | }, 40 | logout: function (ev) { 41 | // Disable the button 42 | $(ev.currentTarget).text('Logging out').attr('disabled', 'disabled'); 43 | Session.logout(); 44 | } 45 | }); 46 | return ExamplePage; 47 | }); 48 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/js/vm.js: -------------------------------------------------------------------------------- 1 | // Use this as a quick template for future modules 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'events' 7 | ], function($, _, Backbone, Events){ 8 | var views = {}; 9 | var create = function (context, name, View, options) { 10 | // View clean up isn't actually implemented yet but will simply call .clean, .remove and .unbind 11 | if(typeof views[name] !== 'undefined') { 12 | views[name].undelegateEvents(); 13 | if(typeof views[name].clean === 'function') { 14 | views[name].clean(); 15 | } 16 | } 17 | var view = new View(options); 18 | views[name] = view; 19 | if(typeof context.children === 'undefined'){ 20 | context.children = {}; 21 | context.children[name] = view; 22 | } else { 23 | context.children[name] = view; 24 | } 25 | Events.trigger('viewCreated'); 26 | return view; 27 | } 28 | 29 | 30 | return { 31 | create: create 32 | }; 33 | }); 34 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cross-domain", 3 | "subdomain": "cross-domain", 4 | "scripts": { 5 | "start": "server.js" 6 | }, 7 | "version": "0.0.0-20", 8 | "engines": { 9 | "node": "0.6.x" 10 | }, 11 | "dependencies": { 12 | "express": "2.5.x", 13 | "connect": "2.2.x" 14 | } 15 | } -------------------------------------------------------------------------------- /_site/examples/cross-domain/templates/example/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/templates/example/logout.html: -------------------------------------------------------------------------------- 1 |

Hello, <%= username %>. Time to logout?

2 | 3 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/templates/example/page.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 | 7 | 8 |
9 | -------------------------------------------------------------------------------- /_site/examples/cross-domain/templates/layout.html: -------------------------------------------------------------------------------- 1 |
2 |

Cross-domain Backbone.js with sessions using CORS

3 |

Simply clone this repo and host it on `localhost` to get it to work. Run the example server with `node server.js`. Make sure to change the baseUrl in app.js though!

4 | 5 | Notice that this page is separate from any server. 6 |
7 |
8 |
9 |
Checking auth....
10 |
11 |
12 | 13 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/README.md: -------------------------------------------------------------------------------- 1 | Message me if you need a hand getting this to work 2 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/build/build.js: -------------------------------------------------------------------------------- 1 | ({ 2 | name: '../js/main', 3 | baseUrl: '../js', 4 | out: 'output/js/main.js', 5 | findNestedDependencies: true, 6 | mainConfigFile: '../js/main.js' 7 | }) 8 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/build/build.sh: -------------------------------------------------------------------------------- 1 | rm -rf output 2 | node r.js -o build.js 3 | node r.js -o cssIn=../css/styles.css out=output/css/styles.css 4 | 5 | cp ../index.html output/index.html 6 | sed -i 's/js\/libs\/require\/require.js/http:\/\/requirejs.org\/docs\/release\/1.0.5\/minified\/require.js/g' output/index.html 7 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/build/output/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Backbone Boilerplate 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/build/output/js/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/examples/infinite-scroll/build/output/js/main.js -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/build/server: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var express = require("express"); 3 | var site = express.createServer(); 4 | 5 | site.use(express.static(__dirname + '/..')); 6 | 7 | site.use(express.favicon("./favicon.ico")); 8 | 9 | site.get("*", function(req, res) { 10 | fs.createReadStream("./index.html").pipe(res); 11 | }); 12 | 13 | site.listen(1337); 14 | 15 | console.log("Server listening on http://localhost:1337"); 16 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/config-sample.js: -------------------------------------------------------------------------------- 1 | // Don't commit this file to your public repos 2 | exports.creds = { 3 | // Your mongo auth uri goes here 4 | // e.g. mongodb://username:server@mongoserver:10059/somecollection 5 | mongoose_auth: '' 6 | } 7 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/css/layout.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | .container { 6 | margin: auto; 7 | width: 400px; 8 | } 9 | .page { 10 | margin: 10px 0 10px 0; 11 | } 12 | .submenu { 13 | width: 200px; 14 | float: left; 15 | } 16 | .content { 17 | width: 460px; 18 | float: left; 19 | } 20 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/css/menus.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | } 6 | .menu li { 7 | float: left; 8 | margin-left: 10px; 9 | } 10 | 11 | .menu li.other-link { 12 | float: right; 13 | } 14 | 15 | a.active { 16 | color: #000; 17 | text-decoration: none; 18 | } 19 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Not really too concerned with how to organize CSS 2 | the opinions are too diverse */ 3 | 4 | /* Third party helper libraries */ 5 | @import url("normalize.css"); 6 | 7 | /* Custom themes */ 8 | @import url("theme.css"); 9 | @import url("menus.css"); 10 | @import url("layout.css"); 11 | 12 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/css/theme.css: -------------------------------------------------------------------------------- 1 | .container { 2 | background-color: #fff; 3 | } 4 | body { 5 | color: #444; 6 | 7 | } 8 | .twitter-widget { 9 | overflow-y: scroll; 10 | overflow-x: hidden; 11 | height: 500px; 12 | } 13 | code { 14 | border:1px dashed #E1E1E1; 15 | color:#333344; 16 | background:#FAFAFA; 17 | font-family:monospace; 18 | overflow:auto; 19 | font-size:11px; 20 | padding:0.2em; 21 | } 22 | 23 | a, a:visited { 24 | color: #444; 25 | } 26 | 27 | a:hover { 28 | color: #000; 29 | text-decoration: none; 30 | } 31 | 32 | .tweets { 33 | list-style: none; 34 | } 35 | .tweets li { 36 | margin-top: 50px; 37 | } 38 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Playground 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | // Use this as a quick template for future modules 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone' 6 | ], function($, _, Backbone){ 7 | 8 | return {}; 9 | }); 10 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/js/collections/twitter.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone' 5 | ], function($, _, Backbone){ 6 | var Tweets = Backbone.Collection.extend({ 7 | url: function () { 8 | return 'http://search.twitter.com/search.json?q=' + this.query + '&page=' + this.page + '&callback=?' 9 | }, 10 | // Because twitter doesn't return an array of models by default we need 11 | // to point Backbone.js at the correct property 12 | parse: function(resp, xhr) { 13 | return resp.results; 14 | }, 15 | page: 1, 16 | query: 'backbone.js' 17 | }); 18 | 19 | return Tweets; 20 | }); 21 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/js/events.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone' 5 | ], function($, _, Backbone){ 6 | var vent = _.extend({}, Backbone.Events); 7 | return vent; 8 | }); -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/js/main.js: -------------------------------------------------------------------------------- 1 | // Require.js allows us to configure shortcut alias 2 | // Their usage will become more apparent futher along in the tutorial. 3 | require.config({ 4 | paths: { 5 | // Major libraries 6 | jquery: 'libs/jquery/jquery-min', 7 | underscore: 'libs/underscore/underscore-min', // https://github.com/amdjs 8 | backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs 9 | sinon: 'libs/sinon/sinon.js', 10 | 11 | // Require.js plugins 12 | text: 'libs/require/text', 13 | order: 'libs/require/order', 14 | 15 | // Just a short cut so we can put our html outside the js dir 16 | // When you have HTML/CSS designers this aids in keeping them out of the js directory 17 | templates: '../templates' 18 | }, 19 | urlArgs: "bust=" + (new Date()).getTime() 20 | 21 | }); 22 | 23 | // Let's kick off the application 24 | 25 | require([ 26 | 'views/app', 27 | 'router', 28 | 'vm' 29 | ], function(AppView, Router, Vm){ 30 | var appView = Vm.create({}, 'AppView', AppView); 31 | Router.initialize({appView: appView}); 32 | appView.render(); // render() calls Backbone.history when its ready to start 33 | }); 34 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/js/router.js: -------------------------------------------------------------------------------- 1 | // Filename: router.js 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'vm' 7 | ], function ($, _, Backbone, Vm) { 8 | var AppRouter = Backbone.Router.extend({ 9 | routes: { 10 | '*actions': 'defaultAction' // All urls will trigger this route 11 | } 12 | }); 13 | 14 | var initialize = function(options){ 15 | var appView = options.appView; 16 | var router = new AppRouter(options); 17 | 18 | router.on('route:defaultAction', function (actions) { 19 | require(['views/twitter/widget'], function (TwitterWidget) { 20 | var twitterWidget = Vm.create(appView, 'TwitterWidget', TwitterWidget); 21 | twitterWidget.render(); 22 | }); 23 | }); 24 | 25 | }; 26 | return { 27 | initialize: initialize 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/js/views/app.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'vm', 6 | 'events', 7 | 'text!templates/layout.html' 8 | ], function($, _, Backbone, Vm, Events, layoutTemplate){ 9 | var AppView = Backbone.View.extend({ 10 | el: '.container', 11 | initialize: function () { 12 | 13 | }, 14 | render: function () { 15 | var that = this; 16 | $(this.el).html(layoutTemplate); 17 | Backbone.history.start(); 18 | } 19 | }); 20 | return AppView; 21 | }); 22 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/js/vm.js: -------------------------------------------------------------------------------- 1 | // Use this as a quick template for future modules 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'events' 7 | ], function($, _, Backbone, Events){ 8 | var views = {}; 9 | var create = function (context, name, View, options) { 10 | // View clean up isn't actually implemented yet but will simply call .clean, .remove and .unbind 11 | if(typeof views[name] !== 'undefined') { 12 | views[name].undelegateEvents(); 13 | if(typeof views[name].clean === 'function') { 14 | views[name].clean(); 15 | } 16 | } 17 | var view = new View(options); 18 | views[name] = view; 19 | if(typeof context.children === 'undefined'){ 20 | context.children = {}; 21 | context.children[name] = view; 22 | } else { 23 | context.children[name] = view; 24 | } 25 | Events.trigger('viewCreated'); 26 | return view; 27 | } 28 | 29 | 30 | return { 31 | create: create 32 | }; 33 | }); 34 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backbonetutorials", 3 | "subdomain": "backbonetutorials", 4 | "scripts": { 5 | "start": "server.js" 6 | }, 7 | "version": "0.0.0-10", 8 | "engines": { 9 | "node": "0.6.x" 10 | }, 11 | "dependencies": { 12 | "restify": "1.4.x", 13 | "mongoose": "2.6.x" 14 | } 15 | } -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/templates/dashboard/page.html: -------------------------------------------------------------------------------- 1 | 2 |

Guestbook

3 | 4 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/templates/layout.html: -------------------------------------------------------------------------------- 1 |
2 |

Light weight infinite scroll

3 |

This is a super light weight infinite scroll using twitters search api. Scrolling 100px from the bottom will cause the Twitter Collection to set it's current page + 1 and then call a fetch constructing a new url to the twitter search api.

4 |
5 |
6 |
7 |
8 |
9 |
10 | 11 | -------------------------------------------------------------------------------- /_site/examples/infinite-scroll/templates/twitter/list.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/README.md: -------------------------------------------------------------------------------- 1 | ## MODULAR BACKBONE 2 | 3 | authors: [Thomas Davis](https://github.com/thomasdavis), [Brandon Flowers](https://github.com/headwinds) 4 | 5 | ![contributors](http://www.headwinds.net/lab/backbonetutorials/modular-backbone/contributors.png) 6 | 7 | Learn how to use Backbone and Require together to create modular applications that are easy to maintain for solo and team-based projects. As you build your application, you will create many small javascript files with usually no more than 100 lines of code per file. Some developers say that each file does one thing, but we won't hold you to that but we do recommended trying to write smaller files and breaking up the tasks. 8 | 9 | Once you have a working application and you're ready to go to production, you can apply R.js (or alternatively grunt.js) to minify and concatenate this code base into one javascript file that you'll deploy to your website. 10 | 11 | [demo](http://backbonetutorials.com/examples/modular-backbone) | [discussion](http://backbonetutorials.com/organizing-backbone-using-modules/) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/css/styles.css: -------------------------------------------------------------------------------- 1 | @import url('style.css'); 2 | @import url('bootstrap.css'); -------------------------------------------------------------------------------- /_site/examples/modular-backbone/imgs/backbone_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/examples/modular-backbone/imgs/backbone_logo.png -------------------------------------------------------------------------------- /_site/examples/modular-backbone/imgs/require_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/examples/modular-backbone/imgs/require_logo.png -------------------------------------------------------------------------------- /_site/examples/modular-backbone/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 26 | 27 | 36 | 37 | 38 |
39 | Loading.... 40 |
41 | 42 |
43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/app.js: -------------------------------------------------------------------------------- 1 | // Filename: app.js 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'router', // Request router.js 7 | ], function($, _, Backbone, Router){ 8 | var initialize = function(){ 9 | // Pass in our Router module and call it's initialize function 10 | Router.initialize(); 11 | }; 12 | 13 | return { 14 | initialize: initialize 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone' 5 | ], function($, _, Backbone){ 6 | 7 | return {}; 8 | }); 9 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/collections/contributors/ContributorsCollection.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone', 4 | 'models/contributor/ContributorModel' 5 | ], function(_, Backbone, ContributorModel){ 6 | 7 | var ContributorsCollection = Backbone.Collection.extend({ 8 | 9 | model: ContributorModel, 10 | 11 | initialize : function(models, options) {}, 12 | 13 | url : function() { 14 | return 'https://api.github.com/repos/thomasdavis/backbonetutorials/contributors'; 15 | }, 16 | 17 | parse : function(data) { 18 | var uniqueArray = this.removeDuplicates(data.data); 19 | return uniqueArray; 20 | }, 21 | 22 | removeDuplicates: function(myArray) { 23 | 24 | //credit: http://newcodeandroll.blogspot.ca/2012/01/how-to-find-duplicates-in-array-in.html 25 | // I was hoping underscore's _uniq would work here but it only seems to work for single values not objects 26 | var length = myArray.length; 27 | var ArrayWithUniqueValues = []; 28 | 29 | var objectCounter = {}; 30 | 31 | for (i = 0; i < length; i++) { 32 | 33 | var currentMemboerOfArrayKey = JSON.stringify(myArray[i]); 34 | var currentMemboerOfArrayValue = myArray[i]; 35 | 36 | if (objectCounter[currentMemboerOfArrayKey] === undefined){ 37 | ArrayWithUniqueValues.push(currentMemboerOfArrayValue); 38 | objectCounter[currentMemboerOfArrayKey] = 1; 39 | }else{ 40 | objectCounter[currentMemboerOfArrayKey]++; 41 | } 42 | } 43 | 44 | return ArrayWithUniqueValues; 45 | } 46 | 47 | }); 48 | 49 | return ContributorsCollection; 50 | 51 | }); -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/collections/projects/ProjectsCollection.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/project/ProjectModel' 6 | ], function($, _, Backbone, ProjectModel){ 7 | var ProjectsCollection = Backbone.Collection.extend({ 8 | model: ProjectModel, 9 | 10 | initialize: function(){ 11 | 12 | //this.add([project0, project1, project2, project3, project4]); 13 | 14 | } 15 | 16 | }); 17 | 18 | return ProjectsCollection; 19 | }); 20 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/libs/jquery/jquery-serialize.js: -------------------------------------------------------------------------------- 1 | jQuery.fn.serializeObject = function(){ 2 | var arrayData, objectData; 3 | arrayData = this.serializeArray(); 4 | objectData = {}; 5 | 6 | jQuery.each(arrayData, function() { 7 | var value; 8 | 9 | if (this.value != null) { 10 | value = this.value; 11 | } else { 12 | value = ''; 13 | } 14 | 15 | if (objectData[this.name] != null) { 16 | if (!objectData[this.name].push) { 17 | objectData[this.name] = [objectData[this.name]]; 18 | } 19 | 20 | objectData[this.name].push(value); 21 | } else { 22 | objectData[this.name] = value; 23 | } 24 | }); 25 | 26 | return objectData; 27 | } 28 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/main.js: -------------------------------------------------------------------------------- 1 | // Author: Thomas Davis 2 | // Filename: main.js 3 | 4 | // Require.js allows us to configure shortcut alias 5 | // Their usage will become more apparent futher along in the tutorial. 6 | require.config({ 7 | paths: { 8 | jquery: 'libs/jquery/jquery-min', 9 | underscore: 'libs/underscore/underscore-min', 10 | backbone: 'libs/backbone/backbone-min', 11 | templates: '../templates' 12 | } 13 | 14 | }); 15 | 16 | require([ 17 | // Load our app module and pass it to our definition function 18 | 'app', 19 | 20 | ], function(App){ 21 | // The "app" dependency is passed in as "App" 22 | // Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function 23 | App.initialize(); 24 | }); 25 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/models/contributor/ContributorModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone', 4 | ], function(_, Backbone) { 5 | 6 | var ContributorModel = Backbone.Model.extend({ 7 | 8 | defaults : { 9 | medalHex : '#A67D3D', 10 | picWidth : '100px', 11 | githubPath : 'concat github and login' 12 | } 13 | 14 | }); 15 | 16 | return ContributorModel; 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/models/owner/OwnerModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone', 4 | ], function(_, Backbone) { 5 | 6 | var OwnerModel = Backbone.Model.extend({ 7 | 8 | defaults : { 9 | query : "unknown" 10 | }, 11 | 12 | initialize: function( options ) { 13 | this.query = options.query; 14 | }, 15 | 16 | url : function() { 17 | return 'https://api.github.com/users/' + this.query; 18 | }, 19 | 20 | parse : function(res) { 21 | // because of jsonp 22 | return res.data; 23 | } 24 | 25 | }); 26 | 27 | return OwnerModel; 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/models/project/ProjectModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone' 4 | ], function(_, Backbone) { 5 | 6 | var ProjectModel = Backbone.Model.extend({}); 7 | 8 | return ProjectModel; 9 | 10 | }); 11 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/views/footer/FooterView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/owner/OwnerModel', 6 | 'text!templates/footer/footerTemplate.html' 7 | ], function($, _, Backbone, OwnerModel, footerTemplate){ 8 | 9 | var FooterView = Backbone.View.extend({ 10 | el: $("#footer"), 11 | 12 | initialize: function() { 13 | 14 | var that = this; 15 | var options = {query: 'thomasdavis'} 16 | 17 | 18 | var onDataHandler = function(collection) { 19 | that.render(); 20 | } 21 | 22 | this.model = new OwnerModel(options); 23 | this.model.fetch({ success : onDataHandler, dataType: "jsonp"}); 24 | 25 | }, 26 | 27 | render: function(){ 28 | 29 | var data = { 30 | owner: this.model.toJSON(), 31 | _: _ 32 | }; 33 | 34 | var compiledTemplate = _.template( footerTemplate, data ); 35 | this.$el.html(compiledTemplate); 36 | } 37 | 38 | }); 39 | 40 | return FooterView; 41 | 42 | }); 43 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/views/home/HomeView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'views/sidebar/SidebarView', 6 | 'text!templates/home/homeTemplate.html' 7 | ], function($, _, Backbone, SidebarView, homeTemplate){ 8 | 9 | var HomeView = Backbone.View.extend({ 10 | el: $("#page"), 11 | 12 | render: function(){ 13 | 14 | $('.menu li').removeClass('active'); 15 | $('.menu li a[href="#"]').parent().addClass('active'); 16 | this.$el.html(homeTemplate); 17 | 18 | var sidebarView = new SidebarView(); 19 | sidebarView.render(); 20 | 21 | } 22 | 23 | }); 24 | 25 | return HomeView; 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/views/projects/ProjectsListView.js: -------------------------------------------------------------------------------- 1 | // Filename: views/projects/list 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | // Pull in the Collection module from above, 7 | 'models/project/ProjectModel', 8 | 'collections/projects/ProjectsCollection', 9 | 'text!templates/projects/projectsListTemplate.html' 10 | 11 | ], function($, _, Backbone, ProjectModel, ProjectsCollection, projectsListTemplate){ 12 | var ProjectListView = Backbone.View.extend({ 13 | el: $("#projects-list"), 14 | 15 | render: function(){ 16 | 17 | var data = { 18 | projects: this.collection.models, 19 | _: _ 20 | }; 21 | 22 | var compiledTemplate = _.template( projectsListTemplate, data ); 23 | $("#projects-list").html( compiledTemplate ); 24 | } 25 | }); 26 | return ProjectListView; 27 | }); 28 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/js/views/sidebar/SidebarView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'text!templates/sidebar/sidebarTemplate.html' 6 | ], function($, _, Backbone, sidebarTemplate){ 7 | 8 | var SidebarView = Backbone.View.extend({ 9 | el: $(".sidebar"), 10 | 11 | render: function(){ 12 | 13 | var that = this; 14 | 15 | var backbone_ad = { site_url : "http://www.backbonejs.org" , 16 | image_url : "./imgs/backbone_logo.png", 17 | title : "Backbone.js", 18 | description: "Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface." }; 19 | 20 | var require_ad = { site_url : "http://www.requirejs.org" , 21 | image_url : "./imgs/require_logo.png", 22 | title : "Require.js", 23 | description: "RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node." }; 24 | 25 | var data = { 26 | ads: [backbone_ad, require_ad] 27 | }; 28 | 29 | var compiledTemplate = _.template( sidebarTemplate, data ); 30 | 31 | $(".sidebar").append(compiledTemplate); 32 | } 33 | 34 | }); 35 | 36 | return SidebarView; 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/templates/contributors/contributorsListTemplate.html: -------------------------------------------------------------------------------- 1 |
2 |

<%= podium.achievement %>

3 |
4 |
5 | 27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/templates/contributors/contributorsTemplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
ContributionsContributors
<%= total_contributions %><%= total_contributors %>
9 |
10 |
11 |
12 |
13 |
14 | 15 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/templates/footer/footerTemplate.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
    5 |
  • <%= owner.name %>

  • 6 |
  • <%= owner.location %>

  • 7 |
  • Followers: <%= owner.followers %>

  • 8 |
9 |
10 |
-------------------------------------------------------------------------------- /_site/examples/modular-backbone/templates/home/homeTemplate.html: -------------------------------------------------------------------------------- 1 |
2 |

Organizing your application using Modules (require.js)

3 |

4 | Unfortunately Backbone.js does not tell you how to organize your code, leaving many developers in the dark regarding how to load scripts and lay out their development environments. 5 |

6 |

7 | This was quite a different decision to other JavaScript MVC frameworks who were more in favor of setting a development philosophy. Hopefully this tutorial will allow you to build a much more robust project with great separation of concerns between design and code. 8 |

9 |

10 | This tutorial will get you started on combining Backbone.js with AMD (Asynchronous Module Definitions) through Require.js. In addition to Require.js, Text.js plays a significant role by loading the html templates and preparing them for the underscore templating process. 11 |

12 | read full article 13 |

14 |

15 | Take advantage of Require.js compiler! My dying words would be to tell you to try r.js 16 |

17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/templates/projects/projectsListTemplate.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/templates/projects/projectsTemplate.html: -------------------------------------------------------------------------------- 1 |
2 |

Projects

3 |

4 | This site is by no means the definite guide to backbone.js and all corrections and contributions are welcome. About Backbone Tutorials 5 |

6 |

7 | As single page apps and large scale javascript applications become more prominent on the web, useful resources for those developers who are jumping the ship are crucial 8 |

9 |

10 | I started this site to not only consolidate my understanding of backbone.js but to also document what I have learned thus far for myself and others. 11 |

12 |
13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /_site/examples/modular-backbone/templates/sidebar/sidebarTemplate.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |

<%= ads[0].title %>

7 |

<%= ads[0].description %>

8 |
9 |
10 |
11 |
12 | 13 |
14 |
15 |

<%= ads[1].title %>

16 |

<%= ads[1].description %>

17 |
18 |
19 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/about/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | About 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |

About

19 |

20 | see: backbone tutorials 21 |

22 | 23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/css/layout.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | .about { 7 | margin: auto; 8 | width: 960px; 9 | } 10 | 11 | .container { 12 | margin: auto; 13 | width: 960px; 14 | } 15 | .page { 16 | margin: 10px 0 10px 0; 17 | } 18 | .submenu { 19 | width: 200px; 20 | float: left; 21 | } 22 | .content { 23 | width: 460px; 24 | float: left; 25 | } 26 | 27 | .resources { 28 | margin: auto; 29 | width: 960px; 30 | } -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/css/menus.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | } 6 | .menu li { 7 | float: left; 8 | margin-left: 10px; 9 | } 10 | 11 | .menu li.other-link { 12 | float: right; 13 | } 14 | 15 | a.active { 16 | color: #000; 17 | text-decoration: none; 18 | } 19 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Not really too concerned with how to organize CSS 2 | the opinions are too diverse */ 3 | 4 | /* Third party helper libraries */ 5 | @import url("normalize.css"); 6 | 7 | /* Custom themes */ 8 | @import url("theme.css"); 9 | @import url("menus.css"); 10 | @import url("layout.css"); 11 | 12 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/css/theme.css: -------------------------------------------------------------------------------- 1 | .container { 2 | background-color: #fff; 3 | } 4 | body { 5 | color: #444; 6 | } 7 | 8 | code { 9 | border:1px dashed #E1E1E1; 10 | color:#333344; 11 | background:#FAFAFA; 12 | font-family:monospace; 13 | overflow:auto; 14 | font-size:11px; 15 | padding:0.2em; 16 | } 17 | 18 | a, a:visited { 19 | color: #444; 20 | } 21 | 22 | a:hover { 23 | color: #000; 24 | text-decoration: none; 25 | } 26 | 27 | .un-bulleted { 28 | list-style: none; 29 | } 30 | 31 | .guestbook-form-container { 32 | width: 500px 33 | } 34 | 35 | .message { 36 | font-size: 110%; 37 | width: 500px; 38 | height: 40px; 39 | margin-bottom: 10px; 40 | } 41 | 42 | .post-message { 43 | clear: both; 44 | } 45 | 46 | 47 | 48 | .date { 49 | color: #ccc; 50 | font-size: 90%; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/examples/nodejs-mongodb-mongoose-restify/app/favicon.ico -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/js/collections/MessagesCollection.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/MessageModel' 6 | ], function($, _, Backbone, MessageModel){ 7 | var MessagesCollection = Backbone.Collection.extend({ 8 | model: MessageModel, 9 | url: 'http://localhost:8888/messages' 10 | //url: 'http://nationalpark-mongodb.jit.su/messages' 11 | }); 12 | 13 | return MessagesCollection; 14 | }); 15 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/js/main.js: -------------------------------------------------------------------------------- 1 | // Require.js allows us to configure shortcut alias 2 | // Their usage will become more apparent futher along in the tutorial. 3 | require.config({ 4 | paths: { 5 | // Major libraries 6 | jquery: 'libs/jquery/jquery-min', 7 | underscore: 'libs/underscore/underscore-min', // https://github.com/amdjs 8 | backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs 9 | 10 | // Require.js plugins 11 | text: 'libs/require/text', 12 | 13 | // Just a short cut so we can put our html outside the js dir 14 | // When you have HTML/CSS designers this aids in keeping them out of the js directory 15 | templates: '../templates' 16 | } 17 | 18 | }); 19 | 20 | // Let's kick off the application 21 | 22 | require([ 23 | 'router/MainRouter' 24 | ], function(MainRouter){ 25 | 26 | MainRouter.initialize(); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/js/models/MessageModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone' 4 | ], function(_, Backbone) { 5 | var MessageModel = Backbone.Model.extend({ 6 | url: 'http://localhost:8888/messages' 7 | //url: 'http://nationalpark-mongodb.jit.su/messages' 8 | }); 9 | return MessageModel; 10 | }); 11 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/js/router/MainRouter.js: -------------------------------------------------------------------------------- 1 | 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'views/MainView', 7 | 'views/cabin/CabinView' 8 | ], function ($, _, Backbone, MainView, CabinView) { 9 | 10 | var MainRouter = Backbone.Router.extend({ 11 | routes: { 12 | '*actions': 'defaultAction', 13 | 'messages': 'showMessageAboutMongo', // All urls will trigger this route 14 | 'about': 'showAbout' 15 | } 16 | }); 17 | 18 | var initialize = function(){ 19 | 20 | //var vent = _.extend({}, Backbone.Events); 21 | var router = new MainRouter(); 22 | 23 | console.log("MainRouter / initialize"); 24 | 25 | router.on('route:defaultAction', function (actions) { 26 | 27 | var mainView = new MainView(); 28 | mainView.render(); 29 | 30 | var cabinView = new CabinView(); 31 | cabinView.render(); 32 | 33 | console.log("default route"); 34 | 35 | }); 36 | 37 | router.on('route:showMessageAboutMongo', function () { 38 | 39 | console.log("display helpful message about setting up mongo"); 40 | 41 | }); 42 | 43 | router.on('route:showAbout', function () { 44 | 45 | console.log("display about"); 46 | 47 | }); 48 | 49 | Backbone.history.start(); 50 | 51 | }; 52 | return { 53 | initialize: initialize 54 | }; 55 | }); 56 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/js/views/MainView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'text!templates/mainTemplate.html' 6 | ], function($, _, Backbone, mainTemplate){ 7 | 8 | var MainView = Backbone.View.extend({ 9 | el: '.container', 10 | initialize: function () { 11 | 12 | }, 13 | render: function () { 14 | var that = this; 15 | $(this.el).html(mainTemplate); 16 | 17 | } 18 | }); 19 | return MainView; 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/js/views/cabin/CabinView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'views/guestbook/GuestbookFormView', 6 | 'views/guestbook/GuestbookListView', 7 | 'text!templates/guestbook/guestbookTemplate.html' 8 | ], function($, _, Backbone, GuestbookFormView, GuestbookListView, guestbookTemplate){ 9 | 10 | var CabinView = Backbone.View.extend({ 11 | 12 | el: '.page', 13 | 14 | render: function () { 15 | 16 | $(this.el).html(guestbookTemplate); 17 | 18 | // Create new Backbone views using the view manager (does some extra goodies); 19 | var guestbookFormView = new GuestbookFormView(); 20 | guestbookFormView.render(); 21 | 22 | var guestbookListView = new GuestbookListView(); 23 | guestbookListView.render(); 24 | 25 | guestbookFormView.on('postMessage', function () { 26 | guestbookListView.render(); 27 | }); 28 | 29 | } 30 | }); 31 | 32 | return CabinView; 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/js/views/guestbook/GuestbookFormView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/MessageModel', 6 | 'text!templates/guestbook/guestbookFormTemplate.html' 7 | ], function($, _, Backbone, MessageModel, guestbookFormTemplate){ 8 | 9 | var GuestbookForm = Backbone.View.extend({ 10 | el: '.guestbook-form-container', 11 | render: function () { 12 | $(this.el).html(guestbookFormTemplate); 13 | 14 | }, 15 | events: { 16 | 'click .post-message': 'postMessage' 17 | }, 18 | 19 | postMessage: function() { 20 | var that = this; 21 | 22 | console.log("posting message from GuestbookForm") 23 | 24 | var messageModel = new MessageModel(); 25 | 26 | messageModel.save( { message: $('.message').val() }, { 27 | 28 | success: function () { 29 | console.log("GuestbookForm succes " + messageModel.get('message') ) 30 | 31 | that.trigger('postMessage'); 32 | }, 33 | error: function () { 34 | console.log("GuestbookForm error on save"); 35 | } 36 | 37 | }); 38 | } 39 | }); 40 | 41 | return GuestbookForm; 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/js/views/guestbook/GuestbookListView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'collections/MessagesCollection', 6 | 'text!templates/guestbook/guestbookListTemplate.html' 7 | ], function($, _, Backbone, MessagesCollection, guestbookListTemplate){ 8 | var GuestbookListView = Backbone.View.extend({ 9 | el: '.guestbook-list-container', 10 | render: function () { 11 | var that = this; 12 | 13 | /* no messages at the start */ 14 | 15 | that.getMessages(); 16 | }, 17 | 18 | getMessages: function(){ 19 | 20 | var that = this; 21 | 22 | var messages = new MessagesCollection(); 23 | 24 | messages.fetch({ 25 | success: function(messages) { 26 | $(that.el).html(_.template(guestbookListTemplate, {messages: messages.models, _:_})); 27 | }, 28 | error: function(response) { 29 | console.log(response, "GuestbookList error!"); 30 | } 31 | }); 32 | 33 | } 34 | 35 | }); 36 | return GuestbookListView; 37 | }); 38 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/messages/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Messages 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |

Messages

19 |

20 | This is not route you want to see your messages. If you started mongodb and your node server, you should see your messages 21 | as a json dump here:

22 | http://localhost:8888/messages/ 23 |

24 | They are available on port 8888 not 3501. 25 |

26 | 27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/templates/guestbook/guestbookFormTemplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/templates/guestbook/guestbookListTemplate.html: -------------------------------------------------------------------------------- 1 | <% _.each(messages, function(message) { %> 2 | 3 |
<%= message.get('message').replace(/
4 | <%= message.get('date') %> 5 | 6 | <% }); %> 7 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/templates/guestbook/guestbookTemplate.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/app/templates/mainTemplate.html: -------------------------------------------------------------------------------- 1 |
2 |
Loading
3 |
4 | 5 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/configSample.js: -------------------------------------------------------------------------------- 1 | // Don't commit this file to your public repos 2 | exports.creds = { 3 | // Your mongo auth uri goes here 4 | // e.g. mongodb://username:server@mongoserver:10059/somecollection 5 | // nationalpark is the name of my mongo database 6 | mongoose_auth_local: 'mongodb://localhost/nationalpark', 7 | mongoose_auth_jitsu: 'copy and paste your unique connection string uri from the nodejitsu admin' 8 | } 9 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nationalpark", 3 | "subdomain": "nationalpark", 4 | "scripts": { 5 | "start": "server-http.js" 6 | }, 7 | "version": "0.0.0-13", 8 | "engines": { 9 | "node": "0.8.x" 10 | }, 11 | "dependencies": { 12 | "restify": "1.4.x", 13 | "mongoose": "2.6.x", 14 | "connect": "2.7.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org/ 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/server-mongo/README.md: -------------------------------------------------------------------------------- 1 | # Mongodb Server 2 | 3 | In order to persist data to a mongodb database, a server is created to handle all the CRUD operations. 4 | 5 | ## LOCAL 6 | 7 | The quickest way to learn mongodb is by installing it on your local machine using a service like brew or mac ports. For instance, to install mongodb using brew open a terminal window: 8 | 9 | $ brew install mongo 10 | 11 | Once you have mongodb installed, you can start it up: 12 | 13 | $ mongod 14 | 15 | Then open another a terminal window to test it using the Mongo Shell: 16 | 17 | $ mongo 18 | 19 | For the shell, you can name and create your first database and collection. For this demo, I've created my database, "nationalpark"; added two collections: "hikers" and "notes"; and inserted a model into each collection: 20 | 21 | > use nationalpark 22 | > var hiker = { username: "headwinds", health: 100, mana: 100, backpack:[ "lighter", "solar charger", "wine gums" ] } 23 | > db.hikers.insert(hiker) 24 | > var note = { note: "Probably not a good idea to take this route with signs of rain but onwards, upwards!", username: "headwinds" } 25 | > db.notes.insert(note); 26 | > var hiker.insert 27 | 28 | ## HOSTED 29 | 30 | The hosted version relys on the mongodb platform Mongohq (http://www.mongohq.com) which Nodjitsu (http://www.nodejitsu) offers for free to their subscribers but you should be able to use this approach for other platforms. 31 | 32 | The beauty of a hosted platform is that you can share your app with the world, and you don't have to worry about installing or scaling mongodb although you do need to pay for increased traffic and adding more apps. 33 | 34 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/server-mongo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nationalpark-mongodb", 3 | "subdomain": "nationalpark-mongodb", 4 | "scripts": { 5 | "start": "server-mongo.js" 6 | }, 7 | "version": "0.0.0-14", 8 | "engines": { 9 | "node": "0.6.x" 10 | }, 11 | "dependencies": { 12 | "restify": "1.4.x", 13 | "mongoose": "2.6.x", 14 | "connect": "2.7.4", 15 | "dtrace-provider":"0.2.8" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mocha Spec Runner 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /_site/examples/nodejs-mongodb-mongoose-restify/test/runner/mocha.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var runner = mocha.run(); 3 | 4 | if(!window.PHANTOMJS) return; 5 | 6 | runner.on('test', function(test) { 7 | sendMessage('testStart', test.title); 8 | }); 9 | 10 | runner.on('test end', function(test) { 11 | sendMessage('testDone', test.title, test.state); 12 | }); 13 | 14 | runner.on('suite', function(suite) { 15 | sendMessage('suiteStart', suite.title); 16 | }); 17 | 18 | runner.on('suite end', function(suite) { 19 | if (suite.root) return; 20 | sendMessage('suiteDone', suite.title); 21 | }); 22 | 23 | runner.on('fail', function(test, err) { 24 | sendMessage('testFail', test.title, err); 25 | }); 26 | 27 | runner.on('end', function() { 28 | var output = { 29 | failed : this.failures, 30 | passed : this.total - this.failures, 31 | total : this.total 32 | }; 33 | 34 | sendMessage('done', output.failed,output.passed, output.total); 35 | }); 36 | 37 | function sendMessage() { 38 | var args = [].slice.call(arguments); 39 | alert(JSON.stringify(args)); 40 | } 41 | })(); 42 | -------------------------------------------------------------------------------- /_site/examples/todo-app/css/destroy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/_site/examples/todo-app/css/destroy.png -------------------------------------------------------------------------------- /_site/examples/todo-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Todo App - Backbone - RequireJs - Thomas Davis 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 |

Todos

15 |
16 | 17 |
18 | 19 |
20 | 21 | 22 |
23 | 24 |
25 |
    26 |
    27 | 28 |
    29 | 30 |
    31 | 32 |
    33 | 34 |
    35 |

    Modularized by 36 | Thomas Davis. 37 | Originally by 38 | Jérôme Gravel-Niquet. 39 |

    40 |
    41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /_site/examples/todo-app/js/collections/todos.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone', 4 | 'libs/backbone/localstorage', 5 | 'models/todo' 6 | ], function(_, Backbone, Store, Todo){ 7 | 8 | var TodosCollection = Backbone.Collection.extend({ 9 | 10 | // Reference to this collection's model. 11 | model: Todo, 12 | 13 | // Save all of the todo items under the `"todos"` namespace. 14 | localStorage: new Store("todos"), 15 | 16 | // Filter down the list of all todo items that are finished. 17 | done: function() { 18 | return this.filter(function(todo){ return todo.get('done'); }); 19 | }, 20 | 21 | // Filter down the list to only todo items that are still not finished. 22 | remaining: function() { 23 | return this.without.apply(this, this.done()); 24 | }, 25 | 26 | // We keep the Todos in sequential order, despite being saved by unordered 27 | // GUID in the database. This generates the next order number for new items. 28 | nextOrder: function() { 29 | if (!this.length) return 1; 30 | return this.last().get('order') + 1; 31 | }, 32 | 33 | // Todos are sorted by their original insertion order. 34 | comparator: function(todo) { 35 | return todo.get('order'); 36 | } 37 | 38 | }); 39 | return new TodosCollection; 40 | }); 41 | -------------------------------------------------------------------------------- /_site/examples/todo-app/js/main.js: -------------------------------------------------------------------------------- 1 | // Author: Thomas Davis 2 | // Filename: main.js 3 | 4 | // Require.js allows us to configure shortcut alias 5 | // Their usage will become more apparent futher along in the tutorial. 6 | require.config({ 7 | paths: { 8 | jquery: 'libs/jquery/jquery-min', 9 | underscore: 'libs/underscore/underscore-min', 10 | backbone: 'libs/backbone/backbone-optamd3-min', 11 | text: 'libs/require/text' 12 | } 13 | 14 | }); 15 | 16 | require(['views/app'], function(AppView){ 17 | var app_view = new AppView; 18 | }); 19 | -------------------------------------------------------------------------------- /_site/examples/todo-app/js/models/todo.js: -------------------------------------------------------------------------------- 1 | define(['underscore', 'backbone'], function(_, Backbone) { 2 | var TodoModel = Backbone.Model.extend({ 3 | 4 | // Default attributes for the todo. 5 | defaults: { 6 | content: "empty todo...", 7 | done: false 8 | }, 9 | 10 | // Ensure that each todo created has `content`. 11 | initialize: function() { 12 | if (!this.get("content")) { 13 | this.set({"content": this.defaults.content}); 14 | } 15 | }, 16 | 17 | // Toggle the `done` state of this todo item. 18 | toggle: function() { 19 | this.save({done: !this.get("done")}); 20 | }, 21 | 22 | // Remove this Todo from *localStorage* and delete its view. 23 | clear: function() { 24 | this.destroy(); 25 | this.view.remove(); 26 | } 27 | 28 | }); 29 | return TodoModel; 30 | }); 31 | -------------------------------------------------------------------------------- /_site/examples/todo-app/js/templates/stats.html: -------------------------------------------------------------------------------- 1 | <% if (total) { %> 2 | 3 | <%= remaining %> 4 | <%= remaining == 1 ? 'item' : 'items' %> left. 5 | 6 | <% } %> 7 | <% if (done) { %> 8 | 9 | 10 | Clear <%= done %> 11 | completed <%= done == 1 ? 'item' : 'items' %> 12 | 13 | 14 | <% } %> 15 | -------------------------------------------------------------------------------- /_site/examples/todo-app/js/templates/todos.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | /> 4 |
    5 | 6 |
    7 |
    8 | 9 |
    10 |
    11 | -------------------------------------------------------------------------------- /_site/googleaa49fe030680ef6c.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googleaa49fe030680ef6c.html -------------------------------------------------------------------------------- /_site/pygments/CNAME: -------------------------------------------------------------------------------- 1 | backbonetutorials.com 2 | -------------------------------------------------------------------------------- /_site/pygments/README.md: -------------------------------------------------------------------------------- 1 | # Backbone Tutorials 2 | 3 | This site is by no means the definite guide to backbone.js and all corrections and contributions are welcome. 4 | About Backbone Tutorials 5 | 6 | As single page apps and large scale javascript applications become more prominent on the web, useful resources for those developers who are jumping the ship are crucial 7 | 8 | I started this site to not only consolidate my understanding of backbone.js but to also document what I have learned thus far for myself and others. 9 | 10 | Thomas Davis - [@neutralthoughts](http://twitter.com/neutralthoughts) - Twitter 11 | 12 | ## Contributions 13 | 14 | * Thanks to Cactus([https://github.com/cactus](https://github.com/cactus)) for creating the blog feed 15 | * Thanks to Wes Bos ([https://github.com/wesbos](https://github.com/wesbos)) for CSS fixes 16 | * Thanks to Paul Irish ([https://github.com/https://github.com/paulirish](https://github.com/paulirish)) for tutorial clarification 17 | 18 | ## About the author 19 | 20 | Looking for feedback on my latest startup Protosal(http://protosal.com) any and all would be great! 21 | 22 | **Contact:** 23 | 24 | * \#cdnjs on freenode 25 | * @neutralthoughts on twitter 26 | * thomasalwyndavis@gmail.com 27 | 28 | **Projects:** 29 | 30 | * JavaScript Library CDN - http://cdnjs.com 31 | * Proposal Generation Start up - http://protosal.com 32 | * Backbone.js Tutorials - http://backbonetutorials.com 33 | * Technical Blog - http://thomasdavis.github.com 34 | * GitHub Account - https://github.com/thomasdavis 35 | * Freelance Blog - http://thomasalwyndavis.com 36 | * Quora - http://www.quora.com/Thomas-Davis 37 | * StackOverflow - http://stackoverflow.com/users/580675/thomas-davis 38 | 39 | Love you mum! 40 | -------------------------------------------------------------------------------- /_site/pygments/css/stacklayout.css: -------------------------------------------------------------------------------- 1 | /* 2 | * StackLayout by Campbell McGuiness 3 | * 4 | * http://stacklayout.com/ 5 | * http://twitter.com/stacklayout 6 | * http://www.decalcms.com/ 7 | * http://workingsoftware.com.au/ 8 | * 9 | * This work is licensed under Creative Commons * Attribution-ShareAlike 3.0 Australia License * http://creativecommons.org/licenses/by-sa/3.0/au/ 10 | * 11 | * Please retain this credit and let us know if you use StackLayout for inclusion on http://stacklayout.com/who.html 12 | * 13 | * cam@workingsoftware.com.au 14 | */ 15 | .stack, 16 | .stack1of2, 17 | .stack1of3, 18 | .stack2of3, 19 | .stack1of4, 20 | .stack3of4, 21 | .stack1of5, 22 | .stack2of5, 23 | .stack3of5, 24 | .stack4of5, 25 | .stackAuto 26 | { 27 | display:inline-block; 28 | font-family:'Courier New',monospace; 29 | letter-spacing:-0.65em; 30 | word-spacing:-0.65em; 31 | text-align:center; 32 | vertical-align:top; 33 | } 34 | .stackContent 35 | { 36 | display:block; 37 | letter-spacing:normal; 38 | word-spacing:normal; 39 | text-align:left; 40 | } 41 | .stackContent:after 42 | { 43 | content:"."; 44 | display:block; 45 | height:0; 46 | clear:both; 47 | visibility:hidden; 48 | } 49 | .stackAuto .stackContent 50 | { 51 | text-align:center; 52 | } 53 | .stackAuto 54 | { 55 | width:auto; 56 | } 57 | .stack 58 | { 59 | width:100%; 60 | } 61 | .stack1of2 62 | { 63 | width:50%; 64 | } 65 | .stack1of3 66 | { 67 | width:33.334%; 68 | } 69 | .stack2of3 70 | { 71 | width:66.667%; 72 | } 73 | .stack1of4 74 | { 75 | width:25%; 76 | } 77 | .stack3of4 78 | { 79 | width:75%; 80 | } 81 | .stack1of5 82 | { 83 | width:20%; 84 | } 85 | .stack2of5 86 | { 87 | width:40%; 88 | } 89 | .stack3of5 90 | { 91 | width:60%; 92 | } 93 | .stack4of5 94 | { 95 | width:80%; 96 | } 97 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
    23 | 26 | 33 |
    34 | Loading.... 35 |
    36 | 39 |
    40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/app.js: -------------------------------------------------------------------------------- 1 | // Filename: app.js 2 | define([ 3 | 'jQuery', 4 | 'Underscore', 5 | 'Backbone', 6 | 'router', // Request router.js 7 | ], function($, _, Backbone, Router){ 8 | var initialize = function(){ 9 | // Pass in our Router module and call it's initialize function 10 | Router.initialize(); 11 | } 12 | 13 | return { 14 | initialize: initialize 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone' 5 | ], function($, _, Backbone){ 6 | 7 | return {}; 8 | }); 9 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/collections/projects.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone', 5 | 'models/projects' 6 | ], function($, _, Backbone, projectsModel){ 7 | var projectsCollection = Backbone.Collection.extend({ 8 | model: projectsModel, 9 | initialize: function(){ 10 | 11 | } 12 | 13 | }); 14 | 15 | return new projectsCollection; 16 | }); 17 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/collections/template.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone' 5 | ], function($, _, Backbone){ 6 | 7 | return {}; 8 | }); 9 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/libs/backbone/backbone.js: -------------------------------------------------------------------------------- 1 | define(['order!libs/backbone/backbone-min'], function(){ 2 | _.noConflict(); 3 | $.noConflict(); 4 | return Backbone.noConflict(); 5 | }); 6 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/libs/jquery/jquery-serialize.js: -------------------------------------------------------------------------------- 1 | jQuery.fn.serializeObject = function(){ 2 | var arrayData, objectData; 3 | arrayData = this.serializeArray(); 4 | objectData = {}; 5 | 6 | jQuery.each(arrayData, function() { 7 | var value; 8 | 9 | if (this.value != null) { 10 | value = this.value; 11 | } else { 12 | value = ''; 13 | } 14 | 15 | if (objectData[this.name] != null) { 16 | if (!objectData[this.name].push) { 17 | objectData[this.name] = [objectData[this.name]]; 18 | } 19 | 20 | objectData[this.name].push(value); 21 | } else { 22 | objectData[this.name] = value; 23 | } 24 | }); 25 | 26 | return objectData; 27 | } 28 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/libs/jquery/jquery.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'order!libs/jquery/jquery-min', 3 | ], function(){ 4 | return $; 5 | }); 6 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/libs/underscore/underscore.js: -------------------------------------------------------------------------------- 1 | define(['order!libs/underscore/underscore-min'], function(){ 2 | return _; 3 | }); 4 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/main.js: -------------------------------------------------------------------------------- 1 | // Author: Thomas Davis 2 | // Filename: main.js 3 | 4 | // Require.js allows us to configure shortcut alias 5 | // Their usage will become more apparent futher along in the tutorial. 6 | require.config({ 7 | paths: { 8 | jQuery: 'libs/jquery/jquery', 9 | Underscore: 'libs/underscore/underscore', 10 | Backbone: 'libs/backbone/backbone', 11 | templates: '../templates' 12 | } 13 | 14 | }); 15 | 16 | require([ 17 | 18 | // Load our app module and pass it to our definition function 19 | 'app', 20 | 21 | // Some plugins have to be loaded in order due to their non AMD compliance 22 | // Because these scripts are not "modules" they do not pass any values to the definition function below 23 | 'order!libs/jquery/jquery-min', 24 | 'order!libs/underscore/underscore-min', 25 | 'order!libs/backbone/backbone-min' 26 | ], function(App){ 27 | // The "app" dependency is passed in as "App" 28 | // Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function 29 | App.initialize(); 30 | }); 31 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/models/projects.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'Underscore', 3 | 'Backbone' 4 | ], function(_, Backbone) { 5 | var projectsModel = Backbone.Model.extend({ 6 | defaults: { 7 | score: 10 8 | }, 9 | initialize: function(){ 10 | } 11 | 12 | }); 13 | return projectsModel; 14 | 15 | }); 16 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/order.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS order 0.27.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. 3 | Available via the MIT or new BSD license. 4 | see: http://github.com/jrburke/requirejs for details 5 | */ 6 | (function(){function k(a){var b=a.currentTarget||a.srcElement,c;if(a.type==="load"||l.test(b.readyState)){a=b.getAttribute("data-requiremodule");j[a]=!0;for(a=0;c=g[a];a++)if(j[c.name])c.req([c.name],c.onLoad);else break;a>0&&g.splice(0,a);setTimeout(function(){b.parentNode.removeChild(b)},15)}}function m(a){var b,c;a.setAttribute("data-orderloaded","loaded");for(a=0;c=h[a];a++)if((b=i[c])&&b.getAttribute("data-orderloaded")==="loaded")delete i[c],require.addScriptToDom(b);else break;a>0&&h.splice(0, 7 | a)}var f=typeof document!=="undefined"&&typeof window!=="undefined"&&document.createElement("script"),n=f&&(f.async||window.opera&&Object.prototype.toString.call(window.opera)==="[object Opera]"||"MozAppearance"in document.documentElement.style),o=f&&f.readyState==="uninitialized",l=/^(complete|loaded)$/,g=[],j={},i={},h=[],f=null;define({version:"0.27.0",load:function(a,b,c,d){var e=b.nameToUrl(a,null);require.s.skipAsync[e]=!0;n||d.isBuild?b([a],c):o?(d=require.s.contexts._,!d.urlFetched[e]&&!d.loaded[a]&& 8 | (d.urlFetched[e]=!0,require.resourcesReady(!1),d.scriptCount+=1,e=require.attach(e,d,a,null,null,m),i[a]=e,h.push(a)),b([a],c)):b.specified(a)?b([a],c):(g.push({name:a,req:b,onLoad:c}),require.attach(e,null,a,k,"script/cache"))}})})(); 9 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/router.js: -------------------------------------------------------------------------------- 1 | // Filename: router.js 2 | define([ 3 | 'jQuery', 4 | 'Underscore', 5 | 'Backbone', 6 | 'views/home/main', 7 | 'views/projects/list', 8 | 'views/users/list' 9 | ], function($, _, Backbone, mainHomeView, projectListView, userListView ){ 10 | var AppRouter = Backbone.Router.extend({ 11 | routes: { 12 | // Define some URL routes 13 | '/projects': 'showProjects', 14 | '/users': 'showUsers', 15 | 16 | // Default 17 | '*actions': 'defaultAction' 18 | }, 19 | showProjects: function(){ 20 | // Call render on the module we loaded in via the dependency array 21 | // 'views/projects/list' 22 | projectListView.render(); 23 | }, 24 | // As above, call render on our loaded module 25 | // 'views/users/list' 26 | showUsers: function(){ 27 | userListView.render(); 28 | }, 29 | defaultAction: function(actions){ 30 | // We have no matching route, lets display the home page 31 | mainHomeView.render(); 32 | } 33 | }); 34 | 35 | var initialize = function(){ 36 | var app_router = new AppRouter; 37 | Backbone.history.start(); 38 | }; 39 | return { 40 | initialize: initialize 41 | }; 42 | }); 43 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/views/home/main.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone', 5 | 'text!templates/home/main.html' 6 | ], function($, _, Backbone, mainHomeTemplate){ 7 | 8 | var mainHomeView = Backbone.View.extend({ 9 | el: $("#page"), 10 | render: function(){ 11 | this.el.html(mainHomeTemplate); 12 | } 13 | }); 14 | return new mainHomeView; 15 | }); 16 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/views/projects/list.js: -------------------------------------------------------------------------------- 1 | // Filename: views/projects/list 2 | define([ 3 | 'jQuery', 4 | 'Underscore', 5 | 'Backbone', 6 | // Pull in the Collection module from above 7 | 'collections/projects', 8 | 'text!templates/projects/list.html' 9 | 10 | ], function($, _, Backbone, projectsCollection, projectListTemplate){ 11 | var projectListView = Backbone.View.extend({ 12 | el: $("#page"), 13 | initialize: function(){ 14 | this.collection = projectsCollection; 15 | this.collection.bind("add", this.exampleBind); 16 | this.collection = projectsCollection.add({ name: "Twitter"}); 17 | this.collection = projectsCollection.add({ name: "Facebook"}); 18 | this.collection = projectsCollection.add({ name: "Myspace", score: 20}); 19 | }, 20 | exampleBind: function( model ){ 21 | //console.log(model); 22 | }, 23 | render: function(){ 24 | var data = { 25 | projects: this.collection.models, 26 | _: _ 27 | }; 28 | var compiledTemplate = _.template( projectListTemplate, data ); 29 | $("#page").html( compiledTemplate ); 30 | } 31 | }); 32 | return new projectListView; 33 | }); 34 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/js/views/users/list.js: -------------------------------------------------------------------------------- 1 | // Filename: views/projects/list 2 | define([ 3 | 'jQuery', 4 | 'Underscore', 5 | 'Backbone', 6 | 'text!templates/users/list.html' 7 | ], function($, _, Backbone, userListTemplate){ 8 | var userListView = Backbone.View.extend({ 9 | el: $("#page"), 10 | initialize: function(){ 11 | }, 12 | render: function(){ 13 | var data = {}; 14 | var compiledTemplate = _.template( userListTemplate, data ); 15 | this.el.html( compiledTemplate ); 16 | } 17 | }); 18 | return new userListView; 19 | }); 20 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/templates/home/main.html: -------------------------------------------------------------------------------- 1 | Welcome to the Modular Backbone homepage. 2 | 3 | There are many benefits of combining Require.js with Backbone.js 4 | 5 |
      6 |
    • Take advantage of Require.js compiler! My dying words would be to tell you to try r.js
    • 7 |
    8 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/templates/projects/list.html: -------------------------------------------------------------------------------- 1 |
      2 | <% _.each(projects, function(project){ %> 3 |
    • <%= project.get("name") %> - <%= project.get("score") %>
    • 4 | <% }); %> 5 |
    6 | -------------------------------------------------------------------------------- /_site/pygments/examples/modular-backbone/templates/users/list.html: -------------------------------------------------------------------------------- 1 |
      2 |
    • User 1
    • 3 |
    4 | -------------------------------------------------------------------------------- /_site/videos/beginner/phpversion/client/README.md: -------------------------------------------------------------------------------- 1 | # Version with minimal PHP server 2 | 3 | Option URL change to '../server' 4 | 5 | -------------------------------------------------------------------------------- /_site/videos/beginner/phpversion/server/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteBase /www/xxxxxxxxxxxxxxx/phpversion/server 3 | RewriteRule ^(.*)$ index.php?route=$1 [QSA,L] 4 | -------------------------------------------------------------------------------- /_site/videos/beginner/phpversion/server/README.md: -------------------------------------------------------------------------------- 1 | # Version with minimal PHP server 2 | 3 | * You need to change RewriteBase URL with the correct one /xxxxxxxxxxxxxxx/phpversion/server 4 | * Absolute needed 5 | -------------------------------------------------------------------------------- /_site/videos/beginner/phpversion/tests/README.md: -------------------------------------------------------------------------------- 1 | # Version with minimal PHP server 2 | 3 | * Run first qunit_mirror.html to be sure server works correcly 4 | * Then run qunit.html 5 | -------------------------------------------------------------------------------- /_site/videos/beginner/phpversion/tests/qunit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | QUnit Test Suite 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

    QUnit Test Suite

    12 |

    13 |
    14 |

    15 |
      16 | 17 | -------------------------------------------------------------------------------- /_site/videos/beginner/phpversion/tests/qunit_mirror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | QUnit Test Suite 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

      QUnit Test Suite

      12 |

      13 |
      14 |

      15 |
        16 | 17 | -------------------------------------------------------------------------------- /about.textile: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: About Backbone Tutorials 4 | --- 5 | 6 | h2. About Backbone Tutorials 7 | 8 | p. As single page apps and large scale javascript applications become more prominent on the web, useful resources for those developers who are jumping the ship are crucial. 9 | 10 | I started this site to not only consolidate my understanding of backbone.js but to also document what I have learned thus far for myself and others. 11 | 12 | p. You can contact the original owner of this site through "github":https://github.com/thomasdavis or via twitter("@neutralthoughts":http://twitter.com/neutralthoughts). You can also find me at #cdnjs on freenode.net. 13 | 14 | thomasalwyndavis@gmail.com 15 | -------------------------------------------------------------------------------- /atom.xml: -------------------------------------------------------------------------------- 1 | --- 2 | layout: nil 3 | --- 4 | 5 | 6 | 7 | Backbone Tutorials 8 | 9 | 10 | {{ site.time | date_to_xmlschema }} 11 | http://backbonetutorials.com/ 12 | 13 | Thomas Davis 14 | thomasalwyndavis@gmail.com 15 | 16 | {% for post in site.posts limit:10 %} 17 | 18 | {{ post.title }} 19 | 20 | {{ post.date | date_to_xmlschema }} 21 | http://backbonetutorials.com{{ post.id }} 22 | {{ post.content | xml_escape }} 23 | 24 | {% endfor %} 25 | 26 | -------------------------------------------------------------------------------- /backbone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/backbone.png -------------------------------------------------------------------------------- /chat.textile: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Chat 4 | --- 5 |

        6 | #cdnjs on irc.freenode.net, don't forget to follow me on twitter.

        7 | 8 | -------------------------------------------------------------------------------- /contact.textile: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Contact 4 | --- 5 | 6 | h2. Contact 7 | 8 | p. You can contact the original owner of this site through "github":https://github.com/thomasdavis or via twitter("@neutralthoughts":http://twitter.com/neutralthoughts). 9 | 10 | -------------------------------------------------------------------------------- /contribute.textile: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Contribute 4 | --- 5 | 6 | h2. Contribute 7 | 8 | p. The main goal behind BackboneTutorials.com is to build a comprehensive guide for developers of all levels of experience. Discussion and debate are encouraged and will hopefully breed innovation for javascript applications. 9 | 10 | All contributions will be well acknowledged on the site. 11 | -------------------------------------------------------------------------------- /css/stacklayout.css: -------------------------------------------------------------------------------- 1 | /* 2 | * StackLayout by Campbell McGuiness 3 | * 4 | * http://stacklayout.com/ 5 | * http://twitter.com/stacklayout 6 | * http://www.decalcms.com/ 7 | * http://workingsoftware.com.au/ 8 | * 9 | * This work is licensed under Creative Commons * Attribution-ShareAlike 3.0 Australia License * http://creativecommons.org/licenses/by-sa/3.0/au/ 10 | * 11 | * Please retain this credit and let us know if you use StackLayout for inclusion on http://stacklayout.com/who.html 12 | * 13 | * cam@workingsoftware.com.au 14 | */ 15 | .stack, 16 | .stack1of2, 17 | .stack1of3, 18 | .stack2of3, 19 | .stack1of4, 20 | .stack3of4, 21 | .stack1of5, 22 | .stack2of5, 23 | .stack3of5, 24 | .stack4of5, 25 | .stackAuto 26 | { 27 | display:inline-block; 28 | letter-spacing:-0.65em; 29 | word-spacing:-0.65em; 30 | text-align:center; 31 | vertical-align:top; 32 | } 33 | .stackContent 34 | { 35 | display:block; 36 | letter-spacing:normal; 37 | word-spacing:normal; 38 | text-align:left; 39 | } 40 | .stackContent:after 41 | { 42 | content:"."; 43 | display:block; 44 | height:0; 45 | clear:both; 46 | visibility:hidden; 47 | } 48 | .stackAuto .stackContent 49 | { 50 | text-align:center; 51 | } 52 | .stackAuto 53 | { 54 | width:auto; 55 | } 56 | .stack 57 | { 58 | width:100%; 59 | } 60 | .stack1of2 61 | { 62 | width:50%; 63 | } 64 | .stack1of3 65 | { 66 | width:33.334%; 67 | } 68 | .stack2of3 69 | { 70 | width:66.667%; 71 | } 72 | .stack1of4 73 | { 74 | width:25%; 75 | } 76 | .stack3of4 77 | { 78 | width:75%; 79 | } 80 | .stack1of5 81 | { 82 | width:20%; 83 | } 84 | .stack2of5 85 | { 86 | width:40%; 87 | } 88 | .stack3of5 89 | { 90 | width:60%; 91 | } 92 | .stack4of5 93 | { 94 | width:80%; 95 | } 96 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | #post h1 { 2 | font-size: 32px !important; 3 | } 4 | #post h2 { 5 | font-size: 26px !important; 6 | } 7 | #post h3 { 8 | font-size: 20px !important; 9 | } 10 | 11 | .container { 12 | max-width: 840px !important ; 13 | } 14 | /* 15 | body { 16 | font: 1em "Arvo","Helvetica Neue",Helvetica,Arial,sans-serif !important; 17 | text-shadow: 0 0 4px #CCC !important; 18 | color: #333; 19 | font-size: 14px !important; 20 | } 21 | */ 22 | 23 | pre { 24 | background-color: #49483e !important; 25 | } -------------------------------------------------------------------------------- /earbits-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/earbits-b.png -------------------------------------------------------------------------------- /earbits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/earbits.png -------------------------------------------------------------------------------- /examples.textile: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Contact 4 | --- 5 | 6 | h2. Examples of sites using Backbone.js 7 | 8 | h3. "Protosal.com":http://app.protosal.com 9 | 10 | p. Generate proposals for your clients with ease using predefined templates. Track how often your proposals get accepted or declined and who your best client are. 11 | 12 | _CouchDb and Node.js Backend_ 13 | 14 | h3. "GetFlow.com":http://getflow.com 15 | 16 | p. Flow is a task management app that makes working with your team a breeze. You can see the internals under window.Flow. 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/cross-domain/README.md: -------------------------------------------------------------------------------- 1 | Message me if you need a hand getting this to work 2 | -------------------------------------------------------------------------------- /examples/cross-domain/build/build.js: -------------------------------------------------------------------------------- 1 | ({ 2 | name: '../js/main', 3 | baseUrl: '../js', 4 | out: 'output/js/main.js', 5 | findNestedDependencies: true, 6 | mainConfigFile: '../js/main.js' 7 | }) 8 | -------------------------------------------------------------------------------- /examples/cross-domain/build/build.sh: -------------------------------------------------------------------------------- 1 | rm -rf output 2 | node r.js -o build.js 3 | node r.js -o cssIn=../css/styles.css out=output/css/styles.css 4 | 5 | cp ../index.html output/index.html 6 | sed -i 's/js\/libs\/require\/require.js/http:\/\/requirejs.org\/docs\/release\/1.0.5\/minified\/require.js/g' output/index.html 7 | -------------------------------------------------------------------------------- /examples/cross-domain/build/output/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Backbone Boilerplate 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
        20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/cross-domain/build/output/js/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/examples/cross-domain/build/output/js/main.js -------------------------------------------------------------------------------- /examples/cross-domain/build/server: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var express = require("express"); 3 | var site = express.createServer(); 4 | 5 | site.use(express.static(__dirname + '/..')); 6 | 7 | site.use(express.favicon("./favicon.ico")); 8 | 9 | site.get("*", function(req, res) { 10 | fs.createReadStream("./index.html").pipe(res); 11 | }); 12 | 13 | site.listen(1337); 14 | 15 | console.log("Server listening on http://localhost:1337"); 16 | -------------------------------------------------------------------------------- /examples/cross-domain/csrf.js: -------------------------------------------------------------------------------- 1 | 2 | // TODO - Write a better csrf module lol 3 | // hacked this together for the tutorial 4 | 5 | var crypto = require('crypto'); 6 | 7 | var generateToken = function(len) { 8 | return crypto.randomBytes(Math.ceil(len * 3 / 4)) 9 | .toString('base64') 10 | .slice(0, len); 11 | }; 12 | function defaultValue(req) { 13 | return (req.body && req.body._csrf) 14 | || (req.query && req.query._csrf) 15 | || (req.headers['x-csrf-token']); 16 | } 17 | var checkToken = function(req, res, next){ 18 | var token = req.session._csrf || (req.session._csrf = generateToken(24)); 19 | if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next(); 20 | var val = defaultValue(req); 21 | if (val != token) return next(function(){ 22 | res.send({auth: false}); 23 | }); 24 | next(); 25 | } 26 | var newToken = function(req, res, next) { 27 | var token = req.session._csrf || (req.session._csrf = generateToken(24)); 28 | next(); 29 | } 30 | module.exports = { 31 | check: checkToken, 32 | generate: newToken 33 | }; 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/cross-domain/css/layout.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | .container { 6 | margin: auto; 7 | width: 400px; 8 | } 9 | .page { 10 | margin: 10px 0 10px 0; 11 | } 12 | .submenu { 13 | width: 200px; 14 | float: left; 15 | } 16 | .content { 17 | width: 460px; 18 | float: left; 19 | } 20 | -------------------------------------------------------------------------------- /examples/cross-domain/css/menus.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | } 6 | .menu li { 7 | float: left; 8 | margin-left: 10px; 9 | } 10 | 11 | .menu li.other-link { 12 | float: right; 13 | } 14 | 15 | a.active { 16 | color: #000; 17 | text-decoration: none; 18 | } 19 | -------------------------------------------------------------------------------- /examples/cross-domain/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Not really too concerned with how to organize CSS 2 | the opinions are too diverse */ 3 | 4 | /* Third party helper libraries */ 5 | @import url("normalize.css"); 6 | 7 | /* Custom themes */ 8 | @import url("theme.css"); 9 | @import url("menus.css"); 10 | @import url("layout.css"); 11 | 12 | -------------------------------------------------------------------------------- /examples/cross-domain/css/theme.css: -------------------------------------------------------------------------------- 1 | .container { 2 | background-color: #fff; 3 | } 4 | h1 { 5 | font-size: 16px; 6 | } 7 | [disabled=disabled] { 8 | opacity: 0.5; 9 | } 10 | -------------------------------------------------------------------------------- /examples/cross-domain/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Cross-domain Backbone.js with sessions using CORS 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
        20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/cross-domain/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | // Use this as a quick template for future modules 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone' 6 | ], function($, _, Backbone){ 7 | 8 | return {}; 9 | }); 10 | -------------------------------------------------------------------------------- /examples/cross-domain/js/collections/twitter.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone' 5 | ], function($, _, Backbone){ 6 | var Tweets = Backbone.Collection.extend({ 7 | url: function () { 8 | return 'http://search.twitter.com/search.json?q=' + this.query + '&page=' + this.page + '&callback=?' 9 | }, 10 | // Because twitter doesn't return an array of models by default we need 11 | // to point Backbone.js at the correct property 12 | parse: function(resp, xhr) { 13 | return resp.results; 14 | }, 15 | page: 1, 16 | query: 'backbone.js' 17 | }); 18 | 19 | return Tweets; 20 | }); 21 | -------------------------------------------------------------------------------- /examples/cross-domain/js/events.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone' 5 | ], function($, _, Backbone){ 6 | var vent = _.extend({}, Backbone.Events); 7 | return vent; 8 | }); -------------------------------------------------------------------------------- /examples/cross-domain/js/main.js: -------------------------------------------------------------------------------- 1 | // Require.js allows us to configure shortcut alias 2 | // Their usage will become more apparent futher along in the tutorial. 3 | require.config({ 4 | paths: { 5 | // Major libraries 6 | jquery: 'libs/jquery/jquery-min', 7 | underscore: 'libs/underscore/underscore-min', // https://github.com/amdjs 8 | backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs 9 | sinon: 'libs/sinon/sinon.js', 10 | 11 | // Require.js plugins 12 | text: 'libs/require/text', 13 | order: 'libs/require/order', 14 | 15 | // Just a short cut so we can put our html outside the js dir 16 | // When you have HTML/CSS designers this aids in keeping them out of the js directory 17 | templates: '../templates' 18 | }, 19 | urlArgs: "bust=" + (new Date()).getTime() 20 | 21 | }); 22 | 23 | // Let's kick off the application 24 | 25 | require([ 26 | 'views/app', 27 | 'router', 28 | 'vm' 29 | ], function(AppView, Router, Vm){ 30 | var appView = Vm.create({}, 'AppView', AppView); 31 | Router.initialize({appView: appView}); 32 | appView.render(); // render() calls Backbone.history when its ready to start 33 | }); 34 | -------------------------------------------------------------------------------- /examples/cross-domain/js/models/model.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone' 4 | ], function(_, Backbone) { 5 | var projectsModel = Backbone.Model.extend({ 6 | defaults: { 7 | score: 10 8 | }, 9 | initialize: function(){ 10 | } 11 | 12 | }); 13 | return projectsModel; 14 | 15 | }); 16 | -------------------------------------------------------------------------------- /examples/cross-domain/js/models/session.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone' 4 | ], function(_, Backbone) { 5 | var SessionModel = Backbone.Model.extend({ 6 | 7 | urlRoot: '/session', 8 | initialize: function () { 9 | var that = this; 10 | // Hook into jquery 11 | // Use withCredentials to send the server cookies 12 | // The server must allow this through response headers 13 | $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { 14 | options.xhrFields = { 15 | withCredentials: true 16 | }; 17 | // If we have a csrf token send it through with the next request 18 | if(typeof that.get('_csrf') !== 'undefined') { 19 | jqXHR.setRequestHeader('X-CSRF-Token', that.get('_csrf')); 20 | } 21 | }); 22 | }, 23 | login: function(creds) { 24 | // Do a POST to /session and send the serialized form creds 25 | this.save(creds, { 26 | success: function () {} 27 | }); 28 | }, 29 | logout: function() { 30 | // Do a DELETE to /session and clear the clientside data 31 | var that = this; 32 | this.destroy({ 33 | success: function (model, resp) { 34 | 35 | model.clear() 36 | // Set auth to false to trigger a change:auth event 37 | // The server also returns a new csrf token so that 38 | // the user can relogin without refreshing the page 39 | that.set({auth: false, _csrf: resp._csrf}); 40 | 41 | } 42 | }); 43 | }, 44 | getAuth: function(callback) { 45 | // getAuth is wrapped around our router 46 | // before we start any routers let us see if the user is valid 47 | this.fetch({ 48 | success: callback 49 | }); 50 | } 51 | }); 52 | return new SessionModel(); 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /examples/cross-domain/js/router.js: -------------------------------------------------------------------------------- 1 | // Filename: router.js 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'vm' 7 | ], function ($, _, Backbone, Vm) { 8 | var AppRouter = Backbone.Router.extend({ 9 | routes: { 10 | '*actions': 'defaultAction' // All urls will trigger this route 11 | } 12 | }); 13 | 14 | var initialize = function(options){ 15 | var appView = options.appView; 16 | var router = new AppRouter(options); 17 | 18 | router.on('route:defaultAction', function (actions) { 19 | require(['views/example/page'], function (ExamplePage) { 20 | var examplePage = Vm.create(appView, 'ExamplePage', ExamplePage); 21 | examplePage.render(); 22 | }); 23 | }); 24 | 25 | }; 26 | return { 27 | initialize: initialize 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /examples/cross-domain/js/views/app.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'vm', 6 | 'events', 7 | 'models/session', 8 | 'text!templates/layout.html' 9 | ], function($, _, Backbone, Vm, Events, Session, layoutTemplate){ 10 | var AppView = Backbone.View.extend({ 11 | el: '.container', 12 | initialize: function () { 13 | 14 | // This snipper should usually be loaded elsewhere 15 | // It simply takes a
        and converts its values to an object 16 | $.fn.serializeObject = function() { 17 | var o = {}; 18 | var a = this.serializeArray(); 19 | $.each(a, function() { 20 | if (o[this.name] !== undefined) { 21 | if (!o[this.name].push) { 22 | o[this.name] = [o[this.name]]; 23 | } 24 | o[this.name].push(this.value || ''); 25 | } else { 26 | o[this.name] = this.value || ''; 27 | } 28 | }); 29 | return o; 30 | }; 31 | 32 | 33 | $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { 34 | // Your server goes below 35 | options.url = 'http://localhost:8000' + options.url; 36 | // options.url = 'http://cross-domain.nodejitsu.com' + options.url; 37 | }); 38 | 39 | }, 40 | render: function () { 41 | var that = this; 42 | $(this.el).html(layoutTemplate); 43 | // This is the entry point to your app, therefore 44 | // when the user refreshes the page we should 45 | // really know if they're authed. We will give it 46 | // A call back when we know what the auth status is 47 | Session.getAuth(function () { 48 | Backbone.history.start(); 49 | }) 50 | } 51 | }); 52 | return AppView; 53 | }); 54 | -------------------------------------------------------------------------------- /examples/cross-domain/js/views/example/page.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/session', 6 | 'text!templates/example/login.html', 7 | 'text!templates/example/logout.html' 8 | ], function($, _, Backbone, Session, exampleLoginTemplate, exampleLogoutTemplate){ 9 | var ExamplePage = Backbone.View.extend({ 10 | el: '.page', 11 | initialize: function () { 12 | var that = this; 13 | // Bind to the Session auth attribute so we 14 | // make our view act recordingly when auth changes 15 | Session.on('change:auth', function (session) { 16 | that.render(); 17 | }); 18 | }, 19 | render: function () { 20 | // Simply choose which template to choose depending on 21 | // our Session models auth attribute 22 | if(Session.get('auth')){ 23 | this.$el.html(_.template(exampleLogoutTemplate, {username: Session.get('username')})); 24 | } else { 25 | this.$el.html(exampleLoginTemplate); 26 | } 27 | }, 28 | events: { 29 | 'submit form.login': 'login', // On form submission 30 | 'click .logout': 'logout' 31 | }, 32 | login: function (ev) { 33 | // Disable the button 34 | $('[type=submit]', ev.currentTarget).val('Logging in').attr('disabled', 'disabled'); 35 | // Serialize the form into an object using a jQuery plgin 36 | var creds = $(ev.currentTarget).serializeObject(); 37 | Session.login(creds); 38 | return false; 39 | }, 40 | logout: function (ev) { 41 | // Disable the button 42 | $(ev.currentTarget).text('Logging out').attr('disabled', 'disabled'); 43 | Session.logout(); 44 | } 45 | }); 46 | return ExamplePage; 47 | }); 48 | -------------------------------------------------------------------------------- /examples/cross-domain/js/vm.js: -------------------------------------------------------------------------------- 1 | // Use this as a quick template for future modules 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'events' 7 | ], function($, _, Backbone, Events){ 8 | var views = {}; 9 | var create = function (context, name, View, options) { 10 | // View clean up isn't actually implemented yet but will simply call .clean, .remove and .unbind 11 | if(typeof views[name] !== 'undefined') { 12 | views[name].undelegateEvents(); 13 | if(typeof views[name].clean === 'function') { 14 | views[name].clean(); 15 | } 16 | } 17 | var view = new View(options); 18 | views[name] = view; 19 | if(typeof context.children === 'undefined'){ 20 | context.children = {}; 21 | context.children[name] = view; 22 | } else { 23 | context.children[name] = view; 24 | } 25 | Events.trigger('viewCreated'); 26 | return view; 27 | } 28 | 29 | 30 | return { 31 | create: create 32 | }; 33 | }); 34 | -------------------------------------------------------------------------------- /examples/cross-domain/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cross-domain", 3 | "subdomain": "cross-domain", 4 | "scripts": { 5 | "start": "server.js" 6 | }, 7 | "version": "0.0.0-20", 8 | "engines": { 9 | "node": "0.6.x" 10 | }, 11 | "dependencies": { 12 | "express": "2.5.x", 13 | "connect": "2.2.x" 14 | } 15 | } -------------------------------------------------------------------------------- /examples/cross-domain/templates/example/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
        6 | -------------------------------------------------------------------------------- /examples/cross-domain/templates/example/logout.html: -------------------------------------------------------------------------------- 1 |

        Hello, <%= username %>. Time to logout?

        2 | 3 | -------------------------------------------------------------------------------- /examples/cross-domain/templates/example/page.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 |
        9 | -------------------------------------------------------------------------------- /examples/cross-domain/templates/layout.html: -------------------------------------------------------------------------------- 1 |
        2 |

        Cross-domain Backbone.js with sessions using CORS

        3 |

        Simply clone this repo and host it on `localhost` to get it to work. Run the example server with `node server.js`. Make sure to change the baseUrl in app.js though!

        4 | 5 | Notice that this page is separate from any server. 6 |
        7 |
        8 |
        9 |
        Checking auth....
        10 |
        11 |
        12 | 13 | -------------------------------------------------------------------------------- /examples/infinite-scroll/README.md: -------------------------------------------------------------------------------- 1 | Message me if you need a hand getting this to work 2 | -------------------------------------------------------------------------------- /examples/infinite-scroll/build/build.js: -------------------------------------------------------------------------------- 1 | ({ 2 | name: '../js/main', 3 | baseUrl: '../js', 4 | out: 'output/js/main.js', 5 | findNestedDependencies: true, 6 | mainConfigFile: '../js/main.js' 7 | }) 8 | -------------------------------------------------------------------------------- /examples/infinite-scroll/build/build.sh: -------------------------------------------------------------------------------- 1 | rm -rf output 2 | node r.js -o build.js 3 | node r.js -o cssIn=../css/styles.css out=output/css/styles.css 4 | 5 | cp ../index.html output/index.html 6 | sed -i 's/js\/libs\/require\/require.js/http:\/\/requirejs.org\/docs\/release\/1.0.5\/minified\/require.js/g' output/index.html 7 | -------------------------------------------------------------------------------- /examples/infinite-scroll/build/output/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Backbone Boilerplate 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
        20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/infinite-scroll/build/output/js/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/examples/infinite-scroll/build/output/js/main.js -------------------------------------------------------------------------------- /examples/infinite-scroll/build/server: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var express = require("express"); 3 | var site = express.createServer(); 4 | 5 | site.use(express.static(__dirname + '/..')); 6 | 7 | site.use(express.favicon("./favicon.ico")); 8 | 9 | site.get("*", function(req, res) { 10 | fs.createReadStream("./index.html").pipe(res); 11 | }); 12 | 13 | site.listen(1337); 14 | 15 | console.log("Server listening on http://localhost:1337"); 16 | -------------------------------------------------------------------------------- /examples/infinite-scroll/config-sample.js: -------------------------------------------------------------------------------- 1 | // Don't commit this file to your public repos 2 | exports.creds = { 3 | // Your mongo auth uri goes here 4 | // e.g. mongodb://username:server@mongoserver:10059/somecollection 5 | mongoose_auth: '' 6 | } 7 | -------------------------------------------------------------------------------- /examples/infinite-scroll/css/layout.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | .container { 6 | margin: auto; 7 | width: 400px; 8 | } 9 | .page { 10 | margin: 10px 0 10px 0; 11 | } 12 | .submenu { 13 | width: 200px; 14 | float: left; 15 | } 16 | .content { 17 | width: 460px; 18 | float: left; 19 | } 20 | -------------------------------------------------------------------------------- /examples/infinite-scroll/css/menus.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | } 6 | .menu li { 7 | float: left; 8 | margin-left: 10px; 9 | } 10 | 11 | .menu li.other-link { 12 | float: right; 13 | } 14 | 15 | a.active { 16 | color: #000; 17 | text-decoration: none; 18 | } 19 | -------------------------------------------------------------------------------- /examples/infinite-scroll/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Not really too concerned with how to organize CSS 2 | the opinions are too diverse */ 3 | 4 | /* Third party helper libraries */ 5 | @import url("normalize.css"); 6 | 7 | /* Custom themes */ 8 | @import url("theme.css"); 9 | @import url("menus.css"); 10 | @import url("layout.css"); 11 | 12 | -------------------------------------------------------------------------------- /examples/infinite-scroll/css/theme.css: -------------------------------------------------------------------------------- 1 | .container { 2 | background-color: #fff; 3 | } 4 | body { 5 | color: #444; 6 | 7 | } 8 | .twitter-widget { 9 | overflow-y: scroll; 10 | overflow-x: hidden; 11 | height: 500px; 12 | } 13 | code { 14 | border:1px dashed #E1E1E1; 15 | color:#333344; 16 | background:#FAFAFA; 17 | font-family:monospace; 18 | overflow:auto; 19 | font-size:11px; 20 | padding:0.2em; 21 | } 22 | 23 | a, a:visited { 24 | color: #444; 25 | } 26 | 27 | a:hover { 28 | color: #000; 29 | text-decoration: none; 30 | } 31 | 32 | .tweets { 33 | list-style: none; 34 | } 35 | .tweets li { 36 | margin-top: 50px; 37 | } 38 | -------------------------------------------------------------------------------- /examples/infinite-scroll/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Playground 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
        20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/infinite-scroll/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | // Use this as a quick template for future modules 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone' 6 | ], function($, _, Backbone){ 7 | 8 | return {}; 9 | }); 10 | -------------------------------------------------------------------------------- /examples/infinite-scroll/js/collections/twitter.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone' 5 | ], function($, _, Backbone){ 6 | var Tweets = Backbone.Collection.extend({ 7 | url: function () { 8 | return 'http://search.twitter.com/search.json?q=' + this.query + '&page=' + this.page + '&callback=?' 9 | }, 10 | // Because twitter doesn't return an array of models by default we need 11 | // to point Backbone.js at the correct property 12 | parse: function(resp, xhr) { 13 | return resp.results; 14 | }, 15 | page: 1, 16 | query: 'backbone.js' 17 | }); 18 | 19 | return Tweets; 20 | }); 21 | -------------------------------------------------------------------------------- /examples/infinite-scroll/js/events.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone' 5 | ], function($, _, Backbone){ 6 | var vent = _.extend({}, Backbone.Events); 7 | return vent; 8 | }); -------------------------------------------------------------------------------- /examples/infinite-scroll/js/main.js: -------------------------------------------------------------------------------- 1 | // Require.js allows us to configure shortcut alias 2 | // Their usage will become more apparent futher along in the tutorial. 3 | require.config({ 4 | paths: { 5 | // Major libraries 6 | jquery: 'libs/jquery/jquery-min', 7 | underscore: 'libs/underscore/underscore-min', // https://github.com/amdjs 8 | backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs 9 | sinon: 'libs/sinon/sinon.js', 10 | 11 | // Require.js plugins 12 | text: 'libs/require/text', 13 | order: 'libs/require/order', 14 | 15 | // Just a short cut so we can put our html outside the js dir 16 | // When you have HTML/CSS designers this aids in keeping them out of the js directory 17 | templates: '../templates' 18 | }, 19 | urlArgs: "bust=" + (new Date()).getTime() 20 | 21 | }); 22 | 23 | // Let's kick off the application 24 | 25 | require([ 26 | 'views/app', 27 | 'router', 28 | 'vm' 29 | ], function(AppView, Router, Vm){ 30 | var appView = Vm.create({}, 'AppView', AppView); 31 | Router.initialize({appView: appView}); 32 | appView.render(); // render() calls Backbone.history when its ready to start 33 | }); 34 | -------------------------------------------------------------------------------- /examples/infinite-scroll/js/router.js: -------------------------------------------------------------------------------- 1 | // Filename: router.js 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'vm' 7 | ], function ($, _, Backbone, Vm) { 8 | var AppRouter = Backbone.Router.extend({ 9 | routes: { 10 | '*actions': 'defaultAction' // All urls will trigger this route 11 | } 12 | }); 13 | 14 | var initialize = function(options){ 15 | var appView = options.appView; 16 | var router = new AppRouter(options); 17 | 18 | router.on('route:defaultAction', function (actions) { 19 | require(['views/twitter/widget'], function (TwitterWidget) { 20 | var twitterWidget = Vm.create(appView, 'TwitterWidget', TwitterWidget); 21 | twitterWidget.render(); 22 | }); 23 | }); 24 | 25 | }; 26 | return { 27 | initialize: initialize 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /examples/infinite-scroll/js/views/app.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'vm', 6 | 'events', 7 | 'text!templates/layout.html' 8 | ], function($, _, Backbone, Vm, Events, layoutTemplate){ 9 | var AppView = Backbone.View.extend({ 10 | el: '.container', 11 | initialize: function () { 12 | 13 | }, 14 | render: function () { 15 | var that = this; 16 | $(this.el).html(layoutTemplate); 17 | Backbone.history.start(); 18 | } 19 | }); 20 | return AppView; 21 | }); 22 | -------------------------------------------------------------------------------- /examples/infinite-scroll/js/vm.js: -------------------------------------------------------------------------------- 1 | // Use this as a quick template for future modules 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'events' 7 | ], function($, _, Backbone, Events){ 8 | var views = {}; 9 | var create = function (context, name, View, options) { 10 | // View clean up isn't actually implemented yet but will simply call .clean, .remove and .unbind 11 | if(typeof views[name] !== 'undefined') { 12 | views[name].undelegateEvents(); 13 | if(typeof views[name].clean === 'function') { 14 | views[name].clean(); 15 | } 16 | } 17 | var view = new View(options); 18 | views[name] = view; 19 | if(typeof context.children === 'undefined'){ 20 | context.children = {}; 21 | context.children[name] = view; 22 | } else { 23 | context.children[name] = view; 24 | } 25 | Events.trigger('viewCreated'); 26 | return view; 27 | } 28 | 29 | 30 | return { 31 | create: create 32 | }; 33 | }); 34 | -------------------------------------------------------------------------------- /examples/infinite-scroll/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backbonetutorials", 3 | "subdomain": "backbonetutorials", 4 | "scripts": { 5 | "start": "server.js" 6 | }, 7 | "version": "0.0.0-10", 8 | "engines": { 9 | "node": "0.6.x" 10 | }, 11 | "dependencies": { 12 | "restify": "1.4.x", 13 | "mongoose": "2.6.x" 14 | } 15 | } -------------------------------------------------------------------------------- /examples/infinite-scroll/templates/dashboard/page.html: -------------------------------------------------------------------------------- 1 | 2 |

        Guestbook

        3 | 4 | -------------------------------------------------------------------------------- /examples/infinite-scroll/templates/layout.html: -------------------------------------------------------------------------------- 1 |
        2 |

        Light weight infinite scroll

        3 |

        This is a super light weight infinite scroll using twitters search api. Scrolling 100px from the bottom will cause the Twitter Collection to set it's current page + 1 and then call a fetch constructing a new url to the twitter search api.

        4 |
        5 |
        6 |
        7 | 8 |
        9 |
        10 | 11 | -------------------------------------------------------------------------------- /examples/infinite-scroll/templates/twitter/list.html: -------------------------------------------------------------------------------- 1 |
          2 | <% _.each(tweets, function (tweet) { %> 3 | 4 |
        • <%= tweet.get('text') %>
        • 5 | 6 | <% }); %> 7 |
        8 | -------------------------------------------------------------------------------- /examples/modular-backbone/README.md: -------------------------------------------------------------------------------- 1 | ## MODULAR BACKBONE 2 | 3 | authors: [Thomas Davis](https://github.com/thomasdavis), [Brandon Flowers](https://github.com/headwinds) 4 | 5 | ![contributors](http://www.headwinds.net/lab/backbonetutorials/modular-backbone/contributors.png) 6 | 7 | Learn how to use Backbone and Require together to create modular applications that are easy to maintain for solo and team-based projects. As you build your application, you will create many small javascript files with usually no more than 100 lines of code per file. Some developers say that each file does one thing, but we won't hold you to that but we do recommended trying to write smaller files and breaking up the tasks. 8 | 9 | Once you have a working application and you're ready to go to production, you can apply R.js (or alternatively grunt.js) to minify and concatenate this code base into one javascript file that you'll deploy to your website. 10 | 11 | [demo](http://backbonetutorials.com/examples/modular-backbone) | [discussion](http://backbonetutorials.com/organizing-backbone-using-modules/) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/modular-backbone/css/styles.css: -------------------------------------------------------------------------------- 1 | @import url('style.css'); 2 | @import url('bootstrap.css'); -------------------------------------------------------------------------------- /examples/modular-backbone/imgs/backbone_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/examples/modular-backbone/imgs/backbone_logo.png -------------------------------------------------------------------------------- /examples/modular-backbone/imgs/require_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/examples/modular-backbone/imgs/require_logo.png -------------------------------------------------------------------------------- /examples/modular-backbone/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
        23 | 26 | 27 | 36 | 37 | 38 |
        39 | Loading.... 40 |
        41 | 42 |
        43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/app.js: -------------------------------------------------------------------------------- 1 | // Filename: app.js 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'router', // Request router.js 7 | ], function($, _, Backbone, Router){ 8 | var initialize = function(){ 9 | // Pass in our Router module and call it's initialize function 10 | Router.initialize(); 11 | }; 12 | 13 | return { 14 | initialize: initialize 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone' 5 | ], function($, _, Backbone){ 6 | 7 | return {}; 8 | }); 9 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/collections/contributors/ContributorsCollection.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone', 4 | 'models/contributor/ContributorModel' 5 | ], function(_, Backbone, ContributorModel){ 6 | 7 | var ContributorsCollection = Backbone.Collection.extend({ 8 | 9 | model: ContributorModel, 10 | 11 | initialize : function(models, options) {}, 12 | 13 | url : function() { 14 | return 'https://api.github.com/repos/thomasdavis/backbonetutorials/contributors'; 15 | }, 16 | 17 | parse : function(data) { 18 | var uniqueArray = this.removeDuplicates(data.data); 19 | return uniqueArray; 20 | }, 21 | 22 | removeDuplicates: function(myArray) { 23 | 24 | //credit: http://newcodeandroll.blogspot.ca/2012/01/how-to-find-duplicates-in-array-in.html 25 | // I was hoping underscore's _uniq would work here but it only seems to work for single values not objects 26 | var length = myArray.length; 27 | var ArrayWithUniqueValues = []; 28 | 29 | var objectCounter = {}; 30 | 31 | for (i = 0; i < length; i++) { 32 | 33 | var currentMemboerOfArrayKey = JSON.stringify(myArray[i]); 34 | var currentMemboerOfArrayValue = myArray[i]; 35 | 36 | if (objectCounter[currentMemboerOfArrayKey] === undefined){ 37 | ArrayWithUniqueValues.push(currentMemboerOfArrayValue); 38 | objectCounter[currentMemboerOfArrayKey] = 1; 39 | }else{ 40 | objectCounter[currentMemboerOfArrayKey]++; 41 | } 42 | } 43 | 44 | return ArrayWithUniqueValues; 45 | } 46 | 47 | }); 48 | 49 | return ContributorsCollection; 50 | 51 | }); -------------------------------------------------------------------------------- /examples/modular-backbone/js/collections/projects/ProjectsCollection.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/project/ProjectModel' 6 | ], function($, _, Backbone, ProjectModel){ 7 | var ProjectsCollection = Backbone.Collection.extend({ 8 | model: ProjectModel, 9 | 10 | initialize: function(){ 11 | 12 | //this.add([project0, project1, project2, project3, project4]); 13 | 14 | } 15 | 16 | }); 17 | 18 | return ProjectsCollection; 19 | }); 20 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/libs/jquery/jquery-serialize.js: -------------------------------------------------------------------------------- 1 | jQuery.fn.serializeObject = function(){ 2 | var arrayData, objectData; 3 | arrayData = this.serializeArray(); 4 | objectData = {}; 5 | 6 | jQuery.each(arrayData, function() { 7 | var value; 8 | 9 | if (this.value != null) { 10 | value = this.value; 11 | } else { 12 | value = ''; 13 | } 14 | 15 | if (objectData[this.name] != null) { 16 | if (!objectData[this.name].push) { 17 | objectData[this.name] = [objectData[this.name]]; 18 | } 19 | 20 | objectData[this.name].push(value); 21 | } else { 22 | objectData[this.name] = value; 23 | } 24 | }); 25 | 26 | return objectData; 27 | } 28 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/main.js: -------------------------------------------------------------------------------- 1 | // Author: Thomas Davis 2 | // Filename: main.js 3 | 4 | // Require.js allows us to configure shortcut alias 5 | // Their usage will become more apparent futher along in the tutorial. 6 | require.config({ 7 | paths: { 8 | jquery: 'libs/jquery/jquery-min', 9 | underscore: 'libs/underscore/underscore-min', 10 | backbone: 'libs/backbone/backbone-min', 11 | templates: '../templates' 12 | } 13 | 14 | }); 15 | 16 | require([ 17 | // Load our app module and pass it to our definition function 18 | 'app', 19 | 20 | ], function(App){ 21 | // The "app" dependency is passed in as "App" 22 | // Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function 23 | App.initialize(); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/models/contributor/ContributorModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone', 4 | ], function(_, Backbone) { 5 | 6 | var ContributorModel = Backbone.Model.extend({ 7 | 8 | defaults : { 9 | medalHex : '#A67D3D', 10 | picWidth : '100px', 11 | githubPath : 'concat github and login' 12 | } 13 | 14 | }); 15 | 16 | return ContributorModel; 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/models/owner/OwnerModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone', 4 | ], function(_, Backbone) { 5 | 6 | var OwnerModel = Backbone.Model.extend({ 7 | 8 | defaults : { 9 | query : "unknown" 10 | }, 11 | 12 | initialize: function( options ) { 13 | this.query = options.query; 14 | }, 15 | 16 | url : function() { 17 | return 'https://api.github.com/users/' + this.query; 18 | }, 19 | 20 | parse : function(res) { 21 | // because of jsonp 22 | return res.data; 23 | } 24 | 25 | }); 26 | 27 | return OwnerModel; 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/models/project/ProjectModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone' 4 | ], function(_, Backbone) { 5 | 6 | var ProjectModel = Backbone.Model.extend({}); 7 | 8 | return ProjectModel; 9 | 10 | }); 11 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/views/footer/FooterView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/owner/OwnerModel', 6 | 'text!templates/footer/footerTemplate.html' 7 | ], function($, _, Backbone, OwnerModel, footerTemplate){ 8 | 9 | var FooterView = Backbone.View.extend({ 10 | el: $("#footer"), 11 | 12 | initialize: function() { 13 | 14 | var that = this; 15 | var options = {query: 'thomasdavis'} 16 | 17 | 18 | var onDataHandler = function(collection) { 19 | that.render(); 20 | } 21 | 22 | this.model = new OwnerModel(options); 23 | this.model.fetch({ success : onDataHandler, dataType: "jsonp"}); 24 | 25 | }, 26 | 27 | render: function(){ 28 | 29 | var data = { 30 | owner: this.model.toJSON(), 31 | _: _ 32 | }; 33 | 34 | var compiledTemplate = _.template( footerTemplate, data ); 35 | this.$el.html(compiledTemplate); 36 | } 37 | 38 | }); 39 | 40 | return FooterView; 41 | 42 | }); 43 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/views/home/HomeView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'views/sidebar/SidebarView', 6 | 'text!templates/home/homeTemplate.html' 7 | ], function($, _, Backbone, SidebarView, homeTemplate){ 8 | 9 | var HomeView = Backbone.View.extend({ 10 | el: $("#page"), 11 | 12 | render: function(){ 13 | 14 | $('.menu li').removeClass('active'); 15 | $('.menu li a[href="#"]').parent().addClass('active'); 16 | this.$el.html(homeTemplate); 17 | 18 | var sidebarView = new SidebarView(); 19 | sidebarView.render(); 20 | 21 | } 22 | 23 | }); 24 | 25 | return HomeView; 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/views/projects/ProjectsListView.js: -------------------------------------------------------------------------------- 1 | // Filename: views/projects/list 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | // Pull in the Collection module from above, 7 | 'models/project/ProjectModel', 8 | 'collections/projects/ProjectsCollection', 9 | 'text!templates/projects/projectsListTemplate.html' 10 | 11 | ], function($, _, Backbone, ProjectModel, ProjectsCollection, projectsListTemplate){ 12 | var ProjectListView = Backbone.View.extend({ 13 | el: $("#projects-list"), 14 | 15 | render: function(){ 16 | 17 | var data = { 18 | projects: this.collection.models, 19 | _: _ 20 | }; 21 | 22 | var compiledTemplate = _.template( projectsListTemplate, data ); 23 | $("#projects-list").html( compiledTemplate ); 24 | } 25 | }); 26 | return ProjectListView; 27 | }); 28 | -------------------------------------------------------------------------------- /examples/modular-backbone/js/views/sidebar/SidebarView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'text!templates/sidebar/sidebarTemplate.html' 6 | ], function($, _, Backbone, sidebarTemplate){ 7 | 8 | var SidebarView = Backbone.View.extend({ 9 | el: $(".sidebar"), 10 | 11 | render: function(){ 12 | 13 | var that = this; 14 | 15 | var backbone_ad = { site_url : "http://www.backbonejs.org" , 16 | image_url : "./imgs/backbone_logo.png", 17 | title : "Backbone.js", 18 | description: "Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface." }; 19 | 20 | var require_ad = { site_url : "http://www.requirejs.org" , 21 | image_url : "./imgs/require_logo.png", 22 | title : "Require.js", 23 | description: "RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node." }; 24 | 25 | var data = { 26 | ads: [backbone_ad, require_ad] 27 | }; 28 | 29 | var compiledTemplate = _.template( sidebarTemplate, data ); 30 | 31 | $(".sidebar").append(compiledTemplate); 32 | } 33 | 34 | }); 35 | 36 | return SidebarView; 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /examples/modular-backbone/templates/contributors/contributorsListTemplate.html: -------------------------------------------------------------------------------- 1 |
        2 |

        <%= podium.achievement %>

        3 |
        4 |
        5 | 27 |
        28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/modular-backbone/templates/contributors/contributorsTemplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
        ContributionsContributors
        <%= total_contributions %><%= total_contributors %>
        9 |
        10 |
        11 |
        12 |
        13 |
        14 | 15 | -------------------------------------------------------------------------------- /examples/modular-backbone/templates/footer/footerTemplate.html: -------------------------------------------------------------------------------- 1 |
        2 |
        3 |
        4 |
          5 |
        • <%= owner.name %>

        • 6 |
        • <%= owner.location %>

        • 7 |
        • Followers: <%= owner.followers %>

        • 8 |
        9 |
        10 |
        -------------------------------------------------------------------------------- /examples/modular-backbone/templates/home/homeTemplate.html: -------------------------------------------------------------------------------- 1 |
        2 |

        Organizing your application using Modules (require.js)

        3 |

        4 | Unfortunately Backbone.js does not tell you how to organize your code, leaving many developers in the dark regarding how to load scripts and lay out their development environments. 5 |

        6 |

        7 | This was quite a different decision to other JavaScript MVC frameworks who were more in favor of setting a development philosophy. Hopefully this tutorial will allow you to build a much more robust project with great separation of concerns between design and code. 8 |

        9 |

        10 | This tutorial will get you started on combining Backbone.js with AMD (Asynchronous Module Definitions) through Require.js. In addition to Require.js, Text.js plays a significant role by loading the html templates and preparing them for the underscore templating process. 11 |

        12 | read full article 13 |

        14 |

        15 | Take advantage of Require.js compiler! My dying words would be to tell you to try r.js 16 |

        17 |
        18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/modular-backbone/templates/projects/projectsListTemplate.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /examples/modular-backbone/templates/projects/projectsTemplate.html: -------------------------------------------------------------------------------- 1 |
        2 |

        Projects

        3 |

        4 | This site is by no means the definite guide to backbone.js and all corrections and contributions are welcome. About Backbone Tutorials 5 |

        6 |

        7 | As single page apps and large scale javascript applications become more prominent on the web, useful resources for those developers who are jumping the ship are crucial 8 |

        9 |

        10 | I started this site to not only consolidate my understanding of backbone.js but to also document what I have learned thus far for myself and others. 11 |

        12 |
        13 |
        14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/modular-backbone/templates/sidebar/sidebarTemplate.html: -------------------------------------------------------------------------------- 1 |
        2 |
        3 | 4 |
        5 |
        6 |

        <%= ads[0].title %>

        7 |

        <%= ads[0].description %>

        8 |
        9 |
        10 |
        11 |
        12 | 13 |
        14 |
        15 |

        <%= ads[1].title %>

        16 |

        <%= ads[1].description %>

        17 |
        18 |
        19 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 4 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/.gitignore: -------------------------------------------------------------------------------- 1 | temp 2 | dist 3 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "es5": true, 5 | "esnext": true, 6 | "bitwise": true, 7 | "camelcase": true, 8 | "curly": true, 9 | "eqeqeq": true, 10 | "immed": true, 11 | "indent": 4, 12 | "latedef": true, 13 | "newcap": true, 14 | "noarg": true, 15 | "quotmark": "single", 16 | "regexp": true, 17 | "undef": true, 18 | "unused": true, 19 | "strict": true, 20 | "trailing": true, 21 | "smarttabs": true 22 | } 23 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/.npmignore: -------------------------------------------------------------------------------- 1 | !./config.js -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/about/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | About 11 | 12 | 13 | 14 | 15 | 16 | 17 |
        18 |

        About

        19 |

        20 | see: backbone tutorials 21 |

        22 | 23 |
        24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/css/layout.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | .about { 7 | margin: auto; 8 | width: 960px; 9 | } 10 | 11 | .container { 12 | margin: auto; 13 | width: 960px; 14 | } 15 | .page { 16 | margin: 10px 0 10px 0; 17 | } 18 | .submenu { 19 | width: 200px; 20 | float: left; 21 | } 22 | .content { 23 | width: 460px; 24 | float: left; 25 | } 26 | 27 | .resources { 28 | margin: auto; 29 | width: 960px; 30 | } -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/css/menus.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | } 6 | .menu li { 7 | float: left; 8 | margin-left: 10px; 9 | } 10 | 11 | .menu li.other-link { 12 | float: right; 13 | } 14 | 15 | a.active { 16 | color: #000; 17 | text-decoration: none; 18 | } 19 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Not really too concerned with how to organize CSS 2 | the opinions are too diverse */ 3 | 4 | /* Third party helper libraries */ 5 | @import url("normalize.css"); 6 | 7 | /* Custom themes */ 8 | @import url("theme.css"); 9 | @import url("menus.css"); 10 | @import url("layout.css"); 11 | 12 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/css/theme.css: -------------------------------------------------------------------------------- 1 | .container { 2 | background-color: #fff; 3 | } 4 | body { 5 | color: #444; 6 | } 7 | 8 | code { 9 | border:1px dashed #E1E1E1; 10 | color:#333344; 11 | background:#FAFAFA; 12 | font-family:monospace; 13 | overflow:auto; 14 | font-size:11px; 15 | padding:0.2em; 16 | } 17 | 18 | a, a:visited { 19 | color: #444; 20 | } 21 | 22 | a:hover { 23 | color: #000; 24 | text-decoration: none; 25 | } 26 | 27 | .un-bulleted { 28 | list-style: none; 29 | } 30 | 31 | .guestbook-form-container { 32 | width: 500px 33 | } 34 | 35 | .message { 36 | font-size: 110%; 37 | width: 500px; 38 | height: 40px; 39 | margin-bottom: 10px; 40 | } 41 | 42 | .post-message { 43 | clear: both; 44 | } 45 | 46 | 47 | 48 | .date { 49 | color: #ccc; 50 | font-size: 90%; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/examples/nodejs-mongodb-mongoose-restify/app/favicon.ico -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/js/collections/MessagesCollection.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/MessageModel' 6 | ], function($, _, Backbone, MessageModel){ 7 | var MessagesCollection = Backbone.Collection.extend({ 8 | model: MessageModel, 9 | url: 'http://localhost:8888/messages' 10 | //url: 'http://nationalpark-mongodb.jit.su/messages' 11 | }); 12 | 13 | return MessagesCollection; 14 | }); 15 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/js/main.js: -------------------------------------------------------------------------------- 1 | // Require.js allows us to configure shortcut alias 2 | // Their usage will become more apparent futher along in the tutorial. 3 | require.config({ 4 | paths: { 5 | // Major libraries 6 | jquery: 'libs/jquery/jquery-min', 7 | underscore: 'libs/underscore/underscore-min', // https://github.com/amdjs 8 | backbone: 'libs/backbone/backbone-min', // https://github.com/amdjs 9 | 10 | // Require.js plugins 11 | text: 'libs/require/text', 12 | 13 | // Just a short cut so we can put our html outside the js dir 14 | // When you have HTML/CSS designers this aids in keeping them out of the js directory 15 | templates: '../templates' 16 | } 17 | 18 | }); 19 | 20 | // Let's kick off the application 21 | 22 | require([ 23 | 'router/MainRouter' 24 | ], function(MainRouter){ 25 | 26 | MainRouter.initialize(); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/js/models/MessageModel.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone' 4 | ], function(_, Backbone) { 5 | var MessageModel = Backbone.Model.extend({ 6 | url: 'http://localhost:8888/messages' 7 | //url: 'http://nationalpark-mongodb.jit.su/messages' 8 | }); 9 | return MessageModel; 10 | }); 11 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/js/router/MainRouter.js: -------------------------------------------------------------------------------- 1 | 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone', 6 | 'views/MainView', 7 | 'views/cabin/CabinView' 8 | ], function ($, _, Backbone, MainView, CabinView) { 9 | 10 | var MainRouter = Backbone.Router.extend({ 11 | routes: { 12 | '*actions': 'defaultAction', 13 | 'messages': 'showMessageAboutMongo', // All urls will trigger this route 14 | 'about': 'showAbout' 15 | } 16 | }); 17 | 18 | var initialize = function(){ 19 | 20 | //var vent = _.extend({}, Backbone.Events); 21 | var router = new MainRouter(); 22 | 23 | console.log("MainRouter / initialize"); 24 | 25 | router.on('route:defaultAction', function (actions) { 26 | 27 | var mainView = new MainView(); 28 | mainView.render(); 29 | 30 | var cabinView = new CabinView(); 31 | cabinView.render(); 32 | 33 | console.log("default route"); 34 | 35 | }); 36 | 37 | router.on('route:showMessageAboutMongo', function () { 38 | 39 | console.log("display helpful message about setting up mongo"); 40 | 41 | }); 42 | 43 | router.on('route:showAbout', function () { 44 | 45 | console.log("display about"); 46 | 47 | }); 48 | 49 | Backbone.history.start(); 50 | 51 | }; 52 | return { 53 | initialize: initialize 54 | }; 55 | }); 56 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/js/views/MainView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'text!templates/mainTemplate.html' 6 | ], function($, _, Backbone, mainTemplate){ 7 | 8 | var MainView = Backbone.View.extend({ 9 | el: '.container', 10 | initialize: function () { 11 | 12 | }, 13 | render: function () { 14 | var that = this; 15 | $(this.el).html(mainTemplate); 16 | 17 | } 18 | }); 19 | return MainView; 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/js/views/cabin/CabinView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'views/guestbook/GuestbookFormView', 6 | 'views/guestbook/GuestbookListView', 7 | 'text!templates/guestbook/guestbookTemplate.html' 8 | ], function($, _, Backbone, GuestbookFormView, GuestbookListView, guestbookTemplate){ 9 | 10 | var CabinView = Backbone.View.extend({ 11 | 12 | el: '.page', 13 | 14 | render: function () { 15 | 16 | $(this.el).html(guestbookTemplate); 17 | 18 | // Create new Backbone views using the view manager (does some extra goodies); 19 | var guestbookFormView = new GuestbookFormView(); 20 | guestbookFormView.render(); 21 | 22 | var guestbookListView = new GuestbookListView(); 23 | guestbookListView.render(); 24 | 25 | guestbookFormView.on('postMessage', function () { 26 | guestbookListView.render(); 27 | }); 28 | 29 | } 30 | }); 31 | 32 | return CabinView; 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/js/views/guestbook/GuestbookFormView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'models/MessageModel', 6 | 'text!templates/guestbook/guestbookFormTemplate.html' 7 | ], function($, _, Backbone, MessageModel, guestbookFormTemplate){ 8 | 9 | var GuestbookForm = Backbone.View.extend({ 10 | el: '.guestbook-form-container', 11 | render: function () { 12 | $(this.el).html(guestbookFormTemplate); 13 | 14 | }, 15 | events: { 16 | 'click .post-message': 'postMessage' 17 | }, 18 | 19 | postMessage: function() { 20 | var that = this; 21 | 22 | console.log("posting message from GuestbookForm") 23 | 24 | var messageModel = new MessageModel(); 25 | 26 | messageModel.save( { message: $('.message').val() }, { 27 | 28 | success: function () { 29 | console.log("GuestbookForm succes " + messageModel.get('message') ) 30 | 31 | that.trigger('postMessage'); 32 | }, 33 | error: function () { 34 | console.log("GuestbookForm error on save"); 35 | } 36 | 37 | }); 38 | } 39 | }); 40 | 41 | return GuestbookForm; 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/js/views/guestbook/GuestbookListView.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'underscore', 4 | 'backbone', 5 | 'collections/MessagesCollection', 6 | 'text!templates/guestbook/guestbookListTemplate.html' 7 | ], function($, _, Backbone, MessagesCollection, guestbookListTemplate){ 8 | var GuestbookListView = Backbone.View.extend({ 9 | el: '.guestbook-list-container', 10 | render: function () { 11 | var that = this; 12 | 13 | /* no messages at the start */ 14 | 15 | that.getMessages(); 16 | }, 17 | 18 | getMessages: function(){ 19 | 20 | var that = this; 21 | 22 | var messages = new MessagesCollection(); 23 | 24 | messages.fetch({ 25 | success: function(messages) { 26 | $(that.el).html(_.template(guestbookListTemplate, {messages: messages.models, _:_})); 27 | }, 28 | error: function(response) { 29 | console.log(response, "GuestbookList error!"); 30 | } 31 | }); 32 | 33 | } 34 | 35 | }); 36 | return GuestbookListView; 37 | }); 38 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/messages/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Messages 11 | 12 | 13 | 14 | 15 | 16 | 17 |
        18 |

        Messages

        19 |

        20 | This is not route you want to see your messages. If you started mongodb and your node server, you should see your messages 21 | as a json dump here:

        22 | http://localhost:8888/messages/ 23 |

        24 | They are available on port 8888 not 3501. 25 |

        26 | 27 |
        28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/templates/guestbook/guestbookFormTemplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/templates/guestbook/guestbookListTemplate.html: -------------------------------------------------------------------------------- 1 | <% _.each(messages, function(message) { %> 2 | 3 |
        <%= message.get('message').replace(/
        4 | <%= message.get('date') %> 5 | 6 | <% }); %> 7 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/templates/guestbook/guestbookTemplate.html: -------------------------------------------------------------------------------- 1 | 2 |
        3 |
        4 |
        5 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/app/templates/mainTemplate.html: -------------------------------------------------------------------------------- 1 |
        2 |
        Loading
        3 |
        4 | 5 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/configSample.js: -------------------------------------------------------------------------------- 1 | // Don't commit this file to your public repos 2 | exports.creds = { 3 | // Your mongo auth uri goes here 4 | // e.g. mongodb://username:server@mongoserver:10059/somecollection 5 | // nationalpark is the name of my mongo database 6 | mongoose_auth_local: 'mongodb://localhost/nationalpark', 7 | mongoose_auth_jitsu: 'copy and paste your unique connection string uri from the nodejitsu admin' 8 | } 9 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nationalpark", 3 | "subdomain": "nationalpark", 4 | "scripts": { 5 | "start": "server-http.js" 6 | }, 7 | "version": "0.0.0-13", 8 | "engines": { 9 | "node": "0.8.x" 10 | }, 11 | "dependencies": { 12 | "restify": "1.4.x", 13 | "mongoose": "2.6.x", 14 | "connect": "2.7.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org/ 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/server-mongo/README.md: -------------------------------------------------------------------------------- 1 | # Mongodb Server 2 | 3 | In order to persist data to a mongodb database, a server is created to handle all the CRUD operations. 4 | 5 | ## LOCAL 6 | 7 | The quickest way to learn mongodb is by installing it on your local machine using a service like brew or mac ports. For instance, to install mongodb using brew open a terminal window: 8 | 9 | $ brew install mongo 10 | 11 | Once you have mongodb installed, you can start it up: 12 | 13 | $ mongod 14 | 15 | Then open another a terminal window to test it using the Mongo Shell: 16 | 17 | $ mongo 18 | 19 | For the shell, you can name and create your first database and collection. For this demo, I've created my database, "nationalpark"; added two collections: "hikers" and "notes"; and inserted a model into each collection: 20 | 21 | > use nationalpark 22 | > var hiker = { username: "headwinds", health: 100, mana: 100, backpack:[ "lighter", "solar charger", "wine gums" ] } 23 | > db.hikers.insert(hiker) 24 | > var note = { note: "Probably not a good idea to take this route with signs of rain but onwards, upwards!", username: "headwinds" } 25 | > db.notes.insert(note); 26 | > var hiker.insert 27 | 28 | ## HOSTED 29 | 30 | The hosted version relys on the mongodb platform Mongohq (http://www.mongohq.com) which Nodjitsu (http://www.nodejitsu) offers for free to their subscribers but you should be able to use this approach for other platforms. 31 | 32 | The beauty of a hosted platform is that you can share your app with the world, and you don't have to worry about installing or scaling mongodb although you do need to pay for increased traffic and adding more apps. 33 | 34 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/server-mongo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nationalpark-mongodb", 3 | "subdomain": "nationalpark-mongodb", 4 | "scripts": { 5 | "start": "server-mongo.js" 6 | }, 7 | "version": "0.0.0-14", 8 | "engines": { 9 | "node": "0.6.x" 10 | }, 11 | "dependencies": { 12 | "restify": "1.4.x", 13 | "mongoose": "2.6.x", 14 | "connect": "2.7.4", 15 | "dtrace-provider":"0.2.8" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mocha Spec Runner 6 | 7 | 8 | 9 |
        10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /examples/nodejs-mongodb-mongoose-restify/test/runner/mocha.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var runner = mocha.run(); 3 | 4 | if(!window.PHANTOMJS) return; 5 | 6 | runner.on('test', function(test) { 7 | sendMessage('testStart', test.title); 8 | }); 9 | 10 | runner.on('test end', function(test) { 11 | sendMessage('testDone', test.title, test.state); 12 | }); 13 | 14 | runner.on('suite', function(suite) { 15 | sendMessage('suiteStart', suite.title); 16 | }); 17 | 18 | runner.on('suite end', function(suite) { 19 | if (suite.root) return; 20 | sendMessage('suiteDone', suite.title); 21 | }); 22 | 23 | runner.on('fail', function(test, err) { 24 | sendMessage('testFail', test.title, err); 25 | }); 26 | 27 | runner.on('end', function() { 28 | var output = { 29 | failed : this.failures, 30 | passed : this.total - this.failures, 31 | total : this.total 32 | }; 33 | 34 | sendMessage('done', output.failed,output.passed, output.total); 35 | }); 36 | 37 | function sendMessage() { 38 | var args = [].slice.call(arguments); 39 | alert(JSON.stringify(args)); 40 | } 41 | })(); 42 | -------------------------------------------------------------------------------- /examples/todo-app/css/destroy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdavis/backbonetutorials/8341f25f15d485c41ee12cd466e832aaaa915e1c/examples/todo-app/css/destroy.png -------------------------------------------------------------------------------- /examples/todo-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Todo App - Backbone - RequireJs - Thomas Davis 5 | 6 | 7 | 8 | 9 | 10 | 11 |
        12 | 13 |
        14 |

        Todos

        15 |
        16 | 17 |
        18 | 19 |
        20 | 21 | 22 |
        23 | 24 |
        25 |
          26 |
          27 | 28 |
          29 | 30 |
          31 | 32 |
          33 | 34 |
          35 |

          Modularized by 36 | Thomas Davis. 37 | Originally by 38 | Jérôme Gravel-Niquet. 39 |

          40 |
          41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/todo-app/js/collections/todos.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'underscore', 3 | 'backbone', 4 | 'libs/backbone/localstorage', 5 | 'models/todo' 6 | ], function(_, Backbone, Store, Todo){ 7 | 8 | var TodosCollection = Backbone.Collection.extend({ 9 | 10 | // Reference to this collection's model. 11 | model: Todo, 12 | 13 | // Save all of the todo items under the `"todos"` namespace. 14 | localStorage: new Store("todos"), 15 | 16 | // Filter down the list of all todo items that are finished. 17 | done: function() { 18 | return this.filter(function(todo){ return todo.get('done'); }); 19 | }, 20 | 21 | // Filter down the list to only todo items that are still not finished. 22 | remaining: function() { 23 | return this.without.apply(this, this.done()); 24 | }, 25 | 26 | // We keep the Todos in sequential order, despite being saved by unordered 27 | // GUID in the database. This generates the next order number for new items. 28 | nextOrder: function() { 29 | if (!this.length) return 1; 30 | return this.last().get('order') + 1; 31 | }, 32 | 33 | // Todos are sorted by their original insertion order. 34 | comparator: function(todo) { 35 | return todo.get('order'); 36 | } 37 | 38 | }); 39 | return new TodosCollection; 40 | }); 41 | -------------------------------------------------------------------------------- /examples/todo-app/js/main.js: -------------------------------------------------------------------------------- 1 | // Author: Thomas Davis 2 | // Filename: main.js 3 | 4 | // Require.js allows us to configure shortcut alias 5 | // Their usage will become more apparent futher along in the tutorial. 6 | require.config({ 7 | paths: { 8 | jquery: 'libs/jquery/jquery-min', 9 | underscore: 'libs/underscore/underscore-min', 10 | backbone: 'libs/backbone/backbone-optamd3-min', 11 | text: 'libs/require/text' 12 | } 13 | 14 | }); 15 | 16 | require(['views/app'], function(AppView){ 17 | var app_view = new AppView; 18 | }); 19 | -------------------------------------------------------------------------------- /examples/todo-app/js/models/todo.js: -------------------------------------------------------------------------------- 1 | define(['underscore', 'backbone'], function(_, Backbone) { 2 | var TodoModel = Backbone.Model.extend({ 3 | 4 | // Default attributes for the todo. 5 | defaults: { 6 | content: "empty todo...", 7 | done: false 8 | }, 9 | 10 | // Ensure that each todo created has `content`. 11 | initialize: function() { 12 | if (!this.get("content")) { 13 | this.set({"content": this.defaults.content}); 14 | } 15 | }, 16 | 17 | // Toggle the `done` state of this todo item. 18 | toggle: function() { 19 | this.save({done: !this.get("done")}); 20 | }, 21 | 22 | // Remove this Todo from *localStorage* and delete its view. 23 | clear: function() { 24 | this.destroy(); 25 | this.view.remove(); 26 | } 27 | 28 | }); 29 | return TodoModel; 30 | }); 31 | -------------------------------------------------------------------------------- /examples/todo-app/js/templates/stats.html: -------------------------------------------------------------------------------- 1 | <% if (total) { %> 2 | 3 | <%= remaining %> 4 | <%= remaining == 1 ? 'item' : 'items' %> left. 5 | 6 | <% } %> 7 | <% if (done) { %> 8 | 9 | 10 | Clear <%= done %> 11 | completed <%= done == 1 ? 'item' : 'items' %> 12 | 13 | 14 | <% } %> 15 | -------------------------------------------------------------------------------- /examples/todo-app/js/templates/todos.html: -------------------------------------------------------------------------------- 1 |
          2 |
          3 | /> 4 |
          5 | 6 |
          7 |
          8 | 9 |
          10 |
          11 | -------------------------------------------------------------------------------- /googleaa49fe030680ef6c.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googleaa49fe030680ef6c.html -------------------------------------------------------------------------------- /lessons.textile: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Lessons 4 | --- 5 | p. If you and your team are looking to learn Backbone.js and other front end development skills, I am available to fly in and coach onsite. 6 | 7 | If you would like to discuss team training with me, send an email directly to thomasalwyndavis@gmail.com 8 | -------------------------------------------------------------------------------- /pygments/CNAME: -------------------------------------------------------------------------------- 1 | backbonetutorials.com 2 | -------------------------------------------------------------------------------- /pygments/README.md: -------------------------------------------------------------------------------- 1 | # Backbone Tutorials 2 | 3 | This site is by no means the definite guide to backbone.js and all corrections and contributions are welcome. 4 | About Backbone Tutorials 5 | 6 | As single page apps and large scale javascript applications become more prominent on the web, useful resources for those developers who are jumping the ship are crucial 7 | 8 | I started this site to not only consolidate my understanding of backbone.js but to also document what I have learned thus far for myself and others. 9 | 10 | Thomas Davis - [@neutralthoughts](http://twitter.com/neutralthoughts) - Twitter 11 | 12 | ## Contributions 13 | 14 | * Thanks to Cactus([https://github.com/cactus](https://github.com/cactus)) for creating the blog feed 15 | * Thanks to Wes Bos ([https://github.com/wesbos](https://github.com/wesbos)) for CSS fixes 16 | * Thanks to Paul Irish ([https://github.com/https://github.com/paulirish](https://github.com/paulirish)) for tutorial clarification 17 | 18 | ## About the author 19 | 20 | Looking for feedback on my latest startup Protosal(http://protosal.com) any and all would be great! 21 | 22 | **Contact:** 23 | 24 | * \#cdnjs on freenode 25 | * @neutralthoughts on twitter 26 | * thomasalwyndavis@gmail.com 27 | 28 | **Projects:** 29 | 30 | * JavaScript Library CDN - http://cdnjs.com 31 | * Proposal Generation Start up - http://protosal.com 32 | * Backbone.js Tutorials - http://backbonetutorials.com 33 | * Technical Blog - http://thomasdavis.github.com 34 | * GitHub Account - https://github.com/thomasdavis 35 | * Freelance Blog - http://thomasalwyndavis.com 36 | * Quora - http://www.quora.com/Thomas-Davis 37 | * StackOverflow - http://stackoverflow.com/users/580675/thomas-davis 38 | 39 | Love you mum! 40 | -------------------------------------------------------------------------------- /pygments/css/stacklayout.css: -------------------------------------------------------------------------------- 1 | /* 2 | * StackLayout by Campbell McGuiness 3 | * 4 | * http://stacklayout.com/ 5 | * http://twitter.com/stacklayout 6 | * http://www.decalcms.com/ 7 | * http://workingsoftware.com.au/ 8 | * 9 | * This work is licensed under Creative Commons * Attribution-ShareAlike 3.0 Australia License * http://creativecommons.org/licenses/by-sa/3.0/au/ 10 | * 11 | * Please retain this credit and let us know if you use StackLayout for inclusion on http://stacklayout.com/who.html 12 | * 13 | * cam@workingsoftware.com.au 14 | */ 15 | .stack, 16 | .stack1of2, 17 | .stack1of3, 18 | .stack2of3, 19 | .stack1of4, 20 | .stack3of4, 21 | .stack1of5, 22 | .stack2of5, 23 | .stack3of5, 24 | .stack4of5, 25 | .stackAuto 26 | { 27 | display:inline-block; 28 | font-family:'Courier New',monospace; 29 | letter-spacing:-0.65em; 30 | word-spacing:-0.65em; 31 | text-align:center; 32 | vertical-align:top; 33 | } 34 | .stackContent 35 | { 36 | display:block; 37 | letter-spacing:normal; 38 | word-spacing:normal; 39 | text-align:left; 40 | } 41 | .stackContent:after 42 | { 43 | content:"."; 44 | display:block; 45 | height:0; 46 | clear:both; 47 | visibility:hidden; 48 | } 49 | .stackAuto .stackContent 50 | { 51 | text-align:center; 52 | } 53 | .stackAuto 54 | { 55 | width:auto; 56 | } 57 | .stack 58 | { 59 | width:100%; 60 | } 61 | .stack1of2 62 | { 63 | width:50%; 64 | } 65 | .stack1of3 66 | { 67 | width:33.334%; 68 | } 69 | .stack2of3 70 | { 71 | width:66.667%; 72 | } 73 | .stack1of4 74 | { 75 | width:25%; 76 | } 77 | .stack3of4 78 | { 79 | width:75%; 80 | } 81 | .stack1of5 82 | { 83 | width:20%; 84 | } 85 | .stack2of5 86 | { 87 | width:40%; 88 | } 89 | .stack3of5 90 | { 91 | width:60%; 92 | } 93 | .stack4of5 94 | { 95 | width:80%; 96 | } 97 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
          23 | 26 | 33 |
          34 | Loading.... 35 |
          36 | 39 |
          40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/app.js: -------------------------------------------------------------------------------- 1 | // Filename: app.js 2 | define([ 3 | 'jQuery', 4 | 'Underscore', 5 | 'Backbone', 6 | 'router', // Request router.js 7 | ], function($, _, Backbone, Router){ 8 | var initialize = function(){ 9 | // Pass in our Router module and call it's initialize function 10 | Router.initialize(); 11 | } 12 | 13 | return { 14 | initialize: initialize 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone' 5 | ], function($, _, Backbone){ 6 | 7 | return {}; 8 | }); 9 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/collections/projects.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone', 5 | 'models/projects' 6 | ], function($, _, Backbone, projectsModel){ 7 | var projectsCollection = Backbone.Collection.extend({ 8 | model: projectsModel, 9 | initialize: function(){ 10 | 11 | } 12 | 13 | }); 14 | 15 | return new projectsCollection; 16 | }); 17 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/collections/template.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone' 5 | ], function($, _, Backbone){ 6 | 7 | return {}; 8 | }); 9 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/libs/backbone/backbone.js: -------------------------------------------------------------------------------- 1 | define(['order!libs/backbone/backbone-min'], function(){ 2 | _.noConflict(); 3 | $.noConflict(); 4 | return Backbone.noConflict(); 5 | }); 6 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/libs/jquery/jquery-serialize.js: -------------------------------------------------------------------------------- 1 | jQuery.fn.serializeObject = function(){ 2 | var arrayData, objectData; 3 | arrayData = this.serializeArray(); 4 | objectData = {}; 5 | 6 | jQuery.each(arrayData, function() { 7 | var value; 8 | 9 | if (this.value != null) { 10 | value = this.value; 11 | } else { 12 | value = ''; 13 | } 14 | 15 | if (objectData[this.name] != null) { 16 | if (!objectData[this.name].push) { 17 | objectData[this.name] = [objectData[this.name]]; 18 | } 19 | 20 | objectData[this.name].push(value); 21 | } else { 22 | objectData[this.name] = value; 23 | } 24 | }); 25 | 26 | return objectData; 27 | } 28 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/libs/jquery/jquery.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'order!libs/jquery/jquery-min', 3 | ], function(){ 4 | return $; 5 | }); 6 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/libs/underscore/underscore.js: -------------------------------------------------------------------------------- 1 | define(['order!libs/underscore/underscore-min'], function(){ 2 | return _; 3 | }); 4 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/main.js: -------------------------------------------------------------------------------- 1 | // Author: Thomas Davis 2 | // Filename: main.js 3 | 4 | // Require.js allows us to configure shortcut alias 5 | // Their usage will become more apparent futher along in the tutorial. 6 | require.config({ 7 | paths: { 8 | jQuery: 'libs/jquery/jquery', 9 | Underscore: 'libs/underscore/underscore', 10 | Backbone: 'libs/backbone/backbone', 11 | templates: '../templates' 12 | } 13 | 14 | }); 15 | 16 | require([ 17 | 18 | // Load our app module and pass it to our definition function 19 | 'app', 20 | 21 | // Some plugins have to be loaded in order due to their non AMD compliance 22 | // Because these scripts are not "modules" they do not pass any values to the definition function below 23 | 'order!libs/jquery/jquery-min', 24 | 'order!libs/underscore/underscore-min', 25 | 'order!libs/backbone/backbone-min' 26 | ], function(App){ 27 | // The "app" dependency is passed in as "App" 28 | // Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function 29 | App.initialize(); 30 | }); 31 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/models/projects.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'Underscore', 3 | 'Backbone' 4 | ], function(_, Backbone) { 5 | var projectsModel = Backbone.Model.extend({ 6 | defaults: { 7 | score: 10 8 | }, 9 | initialize: function(){ 10 | } 11 | 12 | }); 13 | return projectsModel; 14 | 15 | }); 16 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/order.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS order 0.27.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. 3 | Available via the MIT or new BSD license. 4 | see: http://github.com/jrburke/requirejs for details 5 | */ 6 | (function(){function k(a){var b=a.currentTarget||a.srcElement,c;if(a.type==="load"||l.test(b.readyState)){a=b.getAttribute("data-requiremodule");j[a]=!0;for(a=0;c=g[a];a++)if(j[c.name])c.req([c.name],c.onLoad);else break;a>0&&g.splice(0,a);setTimeout(function(){b.parentNode.removeChild(b)},15)}}function m(a){var b,c;a.setAttribute("data-orderloaded","loaded");for(a=0;c=h[a];a++)if((b=i[c])&&b.getAttribute("data-orderloaded")==="loaded")delete i[c],require.addScriptToDom(b);else break;a>0&&h.splice(0, 7 | a)}var f=typeof document!=="undefined"&&typeof window!=="undefined"&&document.createElement("script"),n=f&&(f.async||window.opera&&Object.prototype.toString.call(window.opera)==="[object Opera]"||"MozAppearance"in document.documentElement.style),o=f&&f.readyState==="uninitialized",l=/^(complete|loaded)$/,g=[],j={},i={},h=[],f=null;define({version:"0.27.0",load:function(a,b,c,d){var e=b.nameToUrl(a,null);require.s.skipAsync[e]=!0;n||d.isBuild?b([a],c):o?(d=require.s.contexts._,!d.urlFetched[e]&&!d.loaded[a]&& 8 | (d.urlFetched[e]=!0,require.resourcesReady(!1),d.scriptCount+=1,e=require.attach(e,d,a,null,null,m),i[a]=e,h.push(a)),b([a],c)):b.specified(a)?b([a],c):(g.push({name:a,req:b,onLoad:c}),require.attach(e,null,a,k,"script/cache"))}})})(); 9 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/router.js: -------------------------------------------------------------------------------- 1 | // Filename: router.js 2 | define([ 3 | 'jQuery', 4 | 'Underscore', 5 | 'Backbone', 6 | 'views/home/main', 7 | 'views/projects/list', 8 | 'views/users/list' 9 | ], function($, _, Backbone, mainHomeView, projectListView, userListView ){ 10 | var AppRouter = Backbone.Router.extend({ 11 | routes: { 12 | // Define some URL routes 13 | '/projects': 'showProjects', 14 | '/users': 'showUsers', 15 | 16 | // Default 17 | '*actions': 'defaultAction' 18 | }, 19 | showProjects: function(){ 20 | // Call render on the module we loaded in via the dependency array 21 | // 'views/projects/list' 22 | projectListView.render(); 23 | }, 24 | // As above, call render on our loaded module 25 | // 'views/users/list' 26 | showUsers: function(){ 27 | userListView.render(); 28 | }, 29 | defaultAction: function(actions){ 30 | // We have no matching route, lets display the home page 31 | mainHomeView.render(); 32 | } 33 | }); 34 | 35 | var initialize = function(){ 36 | var app_router = new AppRouter; 37 | Backbone.history.start(); 38 | }; 39 | return { 40 | initialize: initialize 41 | }; 42 | }); 43 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/views/home/main.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jQuery', 3 | 'Underscore', 4 | 'Backbone', 5 | 'text!templates/home/main.html' 6 | ], function($, _, Backbone, mainHomeTemplate){ 7 | 8 | var mainHomeView = Backbone.View.extend({ 9 | el: $("#page"), 10 | render: function(){ 11 | this.el.html(mainHomeTemplate); 12 | } 13 | }); 14 | return new mainHomeView; 15 | }); 16 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/views/projects/list.js: -------------------------------------------------------------------------------- 1 | // Filename: views/projects/list 2 | define([ 3 | 'jQuery', 4 | 'Underscore', 5 | 'Backbone', 6 | // Pull in the Collection module from above 7 | 'collections/projects', 8 | 'text!templates/projects/list.html' 9 | 10 | ], function($, _, Backbone, projectsCollection, projectListTemplate){ 11 | var projectListView = Backbone.View.extend({ 12 | el: $("#page"), 13 | initialize: function(){ 14 | this.collection = projectsCollection; 15 | this.collection.bind("add", this.exampleBind); 16 | this.collection = projectsCollection.add({ name: "Twitter"}); 17 | this.collection = projectsCollection.add({ name: "Facebook"}); 18 | this.collection = projectsCollection.add({ name: "Myspace", score: 20}); 19 | }, 20 | exampleBind: function( model ){ 21 | //console.log(model); 22 | }, 23 | render: function(){ 24 | var data = { 25 | projects: this.collection.models, 26 | _: _ 27 | }; 28 | var compiledTemplate = _.template( projectListTemplate, data ); 29 | $("#page").html( compiledTemplate ); 30 | } 31 | }); 32 | return new projectListView; 33 | }); 34 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/js/views/users/list.js: -------------------------------------------------------------------------------- 1 | // Filename: views/projects/list 2 | define([ 3 | 'jQuery', 4 | 'Underscore', 5 | 'Backbone', 6 | 'text!templates/users/list.html' 7 | ], function($, _, Backbone, userListTemplate){ 8 | var userListView = Backbone.View.extend({ 9 | el: $("#page"), 10 | initialize: function(){ 11 | }, 12 | render: function(){ 13 | var data = {}; 14 | var compiledTemplate = _.template( userListTemplate, data ); 15 | this.el.html( compiledTemplate ); 16 | } 17 | }); 18 | return new userListView; 19 | }); 20 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/templates/home/main.html: -------------------------------------------------------------------------------- 1 | Welcome to the Modular Backbone homepage. 2 | 3 | There are many benefits of combining Require.js with Backbone.js 4 | 5 |
            6 |
          • Take advantage of Require.js compiler! My dying words would be to tell you to try r.js
          • 7 |
          8 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/templates/projects/list.html: -------------------------------------------------------------------------------- 1 |
            2 | <% _.each(projects, function(project){ %> 3 |
          • <%= project.get("name") %> - <%= project.get("score") %>
          • 4 | <% }); %> 5 |
          6 | -------------------------------------------------------------------------------- /pygments/examples/modular-backbone/templates/users/list.html: -------------------------------------------------------------------------------- 1 |
            2 |
          • User 1
          • 3 |
          4 | -------------------------------------------------------------------------------- /rss.xml: -------------------------------------------------------------------------------- 1 | --- 2 | layout: nil 3 | --- 4 | 5 | 6 | 7 | Backbone Tutorials 8 | 9 | 10 | {{ site.time | date_to_xmlschema }} 11 | http://backbonetutorials.com/ 12 | 13 | Thomas Davis 14 | thomasalwyndavis@gmail.com 15 | 16 | {% for post in site.posts limit:10 %} 17 | 18 | {{ post.title }} 19 | 20 | {{ post.date | date_to_xmlschema }} 21 | http://backbonetutorials.com{{ post.id }} 22 | {{ post.content | xml_escape }} 23 | 24 | {% endfor %} 25 | 26 | -------------------------------------------------------------------------------- /videos.textile: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: About Backbone Tutorials 4 | --- 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /videos/beginner/phpversion/client/README.md: -------------------------------------------------------------------------------- 1 | # Version with minimal PHP server 2 | 3 | Option URL change to '../server' 4 | 5 | -------------------------------------------------------------------------------- /videos/beginner/phpversion/server/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteBase /www/xxxxxxxxxxxxxxx/phpversion/server 3 | RewriteRule ^(.*)$ index.php?route=$1 [QSA,L] 4 | -------------------------------------------------------------------------------- /videos/beginner/phpversion/server/README.md: -------------------------------------------------------------------------------- 1 | # Version with minimal PHP server 2 | 3 | * You need to change RewriteBase URL with the correct one /xxxxxxxxxxxxxxx/phpversion/server 4 | * Absolute needed 5 | -------------------------------------------------------------------------------- /videos/beginner/phpversion/tests/README.md: -------------------------------------------------------------------------------- 1 | # Version with minimal PHP server 2 | 3 | * Run first qunit_mirror.html to be sure server works correcly 4 | * Then run qunit.html 5 | -------------------------------------------------------------------------------- /videos/beginner/phpversion/tests/qunit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | QUnit Test Suite 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

          QUnit Test Suite

          12 |

          13 |
          14 |

          15 |
            16 | 17 | -------------------------------------------------------------------------------- /videos/beginner/phpversion/tests/qunit_mirror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | QUnit Test Suite 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

            QUnit Test Suite

            12 |

            13 |
            14 |

            15 |
              16 | 17 | --------------------------------------------------------------------------------