Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Master points to gh-pages

  • Loading branch information...
commit f4e136339f3f5de8ce4e0bf4e1dccf26fef27c57 1 parent edbac4e
@jasonm authored
View
8 Gemfile
@@ -1,8 +0,0 @@
-source 'http://rubygems.org'
-
-gem 'guard'
-
-if RUBY_PLATFORM.downcase.include?("darwin")
- gem 'rb-fsevent'
- gem 'growl'
-end
View
16 Gemfile.lock
@@ -1,16 +0,0 @@
-GEM
- remote: http://rubygems.org/
- specs:
- growl (1.0.3)
- guard (0.6.3)
- thor (~> 0.14.6)
- rb-fsevent (0.4.1)
- thor (0.14.6)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- growl
- guard
- rb-fsevent
View
34 Guardfile
@@ -1,34 +0,0 @@
-require 'guard/guard'
-
-module ::Guard
- class Landslide < Guard
- def start
- UI.info "landslide is waiting for slide changes..."
- end
-
- def run_all
- true
- end
-
- def run_on_change(paths)
- UI.info "landslide is generating a new presentation..."
- output = `landslide landslide.cfg`
-
- command_failure = ($?.to_i != 0)
-
- if command_failure
- UI.error output
-
- UI.error "*"*80
- UI.error "Errors in generation listed above!"
- UI.error "*"*80
- else
- UI.info "Done."
- end
- end
- end
-end
-
-guard 'landslide' do
- watch (%r{landslide\.cfg|slides/})
-end
View
27 README.md
@@ -1,26 +1,3 @@
-# Backbone.js on Rails talk slides
+The content is on the gh-pages branch:
-## Building
-
-1. Install landslide, with `pip`, `easy_install`, or `git`:
-
- https://github.com/adamzap/landslide
-
-2. Bundle:
-
- gem install bundler
- bundle
-
-3. Rebuild slides when any files change:
-
- bundle exec guard
-
-## Publishing
-
-Push to the gh-pages branch:
-
- git push -f origin gh-pages
-
-## View
-
-http://jayunit.net/backbone-js-on-rails-talk/
+[https://github.com/jasonm/backbone-js-on-rails-talk/tree/gh-pages](https://github.com/jasonm/backbone-js-on-rails-talk/tree/gh-pages)
View
2,383 index.html
@@ -1,2383 +0,0 @@
-<!DOCTYPE html>
-<!--
- Copyright 2010 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- Original slides: Marcin Wichary (mwichary@google.com)
- Modifications: Ernest Delgado (ernestd@google.com)
- Alex Russell (slightlyoff@chromium.org)
-
- landslide modifications: Adam Zapletal (adamzap@gmail.com)
- Nicolas Perriault (nperriault@gmail.com)
--->
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="chrome=1">
- <title>Backbone.js on Rails</title>
- <!-- Styles -->
-
- <style type="text/css" media="print">
- * {
- margin: 0;
- padding: 0;
-}
-@page {
- size: landscape;
-}
-body {
- font: 100% "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
- padding: 0;
- margin: 0;
-}
-div.slide {
- min-width: 800px;
- min-height: 600px;
- padding: 1em;
- overflow: hidden;
- page-break-after: always;
- border: 1px solid black;
- border-radius: 20px;
-}
-div.slide div.inner {
- width: 800px;
- height: 600px;
- margin: auto;
- display: table-cell;
-}
-h1 {
- font-size: 2.4em;
-}
-h2 {
- font-size: 1.4em;
-}
-h3 {
- margin: 1em 0;
-}
-ul {
- margin: 0;
- padding: 0;
-}
-p, li, pre {
- margin: 1em 0;
-}
-li {
- margin-left: 2em;
-}
-a {
- color: #000000;
-}
-pre, code {
- max-width: 800px;
- background: #eee;
- font-family: Monaco, monospace;
- font-size: 90%;
-}
-pre {
- padding: .2em .5em;
- overflow: hidden;
- border-radius: .8em;
-}
-code {
- padding: 0 .2em;
-}
-.slide header:only-child h1 {
- line-height: 180%;
- text-align: center;
- display: table-cell;
- vertical-align: middle;
- height: 600px;
- width: 800px;
- font-size: 48px;
- margin-top:100px;
- margin-bottom:100px;
-}
-#toc, #help, .slide aside, .slide footer, .slide .notes {
- display: none;
-}
-
- </style>
- <style type="text/css" media="screen, projection">
- body {
- font: 14px "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
- background: #fff;
- padding: 0;
- margin: 0;
- overflow: hidden;
-}
-
-div.presentation {
- position: absolute;
- width: 100%;
- display: table-cell;
- vertical-align: middle;
- height: 100%;
- background: inherit;
-}
-
-div.slides, body.expose div.slides.nocontext {
- width: 100%;
- height: 100%;
- left: 0;
- top: 0;
- position: absolute;
- display: block;
- background-color: #fff;
-}
-
-
-div.slides.nocontext {
- width: 900px;
- margin: 0 auto;
- overflow: hidden;
- position: relative;
- left: auto;
- top: auto;
-}
-
-div.slide {
- display: none;
- position: absolute;
- overflow: hidden;
- width: 900px;
- height: 700px;
- left: 50%;
- top: 50%;
- margin-top: -350px;
- background: -webkit-gradient(linear, left bottom, left top, from(#fff), to(#eeeeec));
- background-color: #eee;
- background: -moz-linear-gradient(bottom, #fff, #eeeeec);
- -webkit-transition: margin 0.25s ease-in-out;
- -moz-transition: margin 0.25s ease-in-out;
- -o-transition: margin 0.25s ease-in-out;
- border-top-right-radius: 20px;
- -moz-border-radius-topright: 20px;
- -webkit-border-top-right-radius: 20px;
- border-bottom-left-radius: 0px;
- -moz-border-radius-bottomleft: 0px;
- -webkit-border-bottom-left-radius: 0px;
- border-top-left-radius: 20px;
- -moz-border-radius-topleft: 20px;
- -webkit-border-top-left-radius: 20px;
- border-bottom-right-radius: 0px;
- -moz-border-radius-bottomright: 0px;
- -webkit-border-bottom-right-radius: 0px;
-
-}
-
-div.slide p {
- font-size: 20px;
-}
-
-.slide.far-past {
- display: block;
- margin-left: -2400px;
-}
-
-.slide.past {
- display: block;
- margin-left: -1400px;
-}
-
-.slide.current {
- display: block;
- margin-left: -450px;
-}
-
-.slide.future {
- display: block;
- margin-left: 500px;
-}
-
-.slide.far-future {
- display: block;
- margin-left: 1500px;
-}
-
-body.three-d div.slides {
- -webkit-transform: translateX(50px) scale(0.8) rotateY(10deg);
- -moz-transform: translateX(50px) scale(0.8) rotateY(10deg);
- -o-transform: translateX(50px) scale(0.8) rotateY(10deg);
-}
-
-
-/* Content */
-
-header:not(:only-child) {
- font-family: "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
- font-weight: normal;
- font-size: 50px;
- letter-spacing: -.05em;
- color: white;
- color: black;
- text-shadow: rgba(0, 0, 0, 0.2) 0 2px 5px;
- position: absolute;
- left: 30px;
- top: 25px;
- margin: 0;
- padding: 0;
-}
-
-header h1, header h2, header h3, header h4, header h5, header h6 {
- display: inline;
- font-size: 100%;
- font-weight: normal;
- padding: 0;
- margin: 0;
-}
-
-header h2:first-child {
- margin-top: 0;
-}
-
-section, .slide header:only-child h1 {
- font-family: "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
- color: #3f3f3f;
- text-shadow: rgba(0, 0, 0, 0.2) 0 2px 5px;
- margin-left: 30px;
- margin-right: 30px;
- margin-top: 100px;
- display: block;
- overflow: hidden;
-}
-
-section img.align-center {
- display: block;
- margin-left: auto;
- margin-right: auto;
-}
-
-section img.align-right {
- display: block;
- margin-left: auto;
- margin-right: 0;
-}
-
-section img.align-left {
- display: block;
- margin-right: auto;
- margin-left: 0;
-}
-
-a {
- color: inherit;
- display: inline-block;
- text-decoration: none;
- line-height: 110%;
- border-bottom: 2px solid #3f3f3f;
-}
-
-pre {
- font-size: 16px;
- font-family: Monaco, Courier, monospace;
-}
-
-li {
- padding: 10px 0;
- font-size: 20px;
-}
-
-.slide header:only-child h1 {
- line-height: 180%;
- text-align: center;
- display: table-cell;
- vertical-align: middle;
- height: 700px;
- width: 900px;
- font-size: 50px;
- margin-top:100px;
- margin-bottom:100px;
-}
-
-.sidebar {
- background: -webkit-gradient(linear, top right, bottom right, from(#dde), to(#fff));
- -webkit-transition: margin 0.25s ease-in-out;
- background-color: #eee;
- background: -moz-linear-gradient(right, #dde, #fff);
- border-right: 5px solid #ccd;
- z-index: 9999999;
- height: 100%;
- overflow: hidden;
- top: 0;
- position: absolute;
- display: block;
- margin: 0;
- margin-left: -400px;
- padding: 10px 16px;
- overflow: auto;
- -webkit-transition: margin 0.2s ease-in-out;
- -moz-transition: margin 0.2s ease-in-out;
- -o-transition: margin 0.2s ease-in-out;
-}
-
-.sidebar h2 {
- text-shadow: rgba(0, 0, 0, 0.2) 0 2px 5px;
- margin: 0 0 16px;
- padding: 0;
-}
-
-.sidebar table {
- width: 100%;
- margin: 0;
- padding: 0;
- border-collapse: collapse;
-}
-
-.sidebar table caption {
- display: none;
-}
-
-.sidebar tr {
- margin: 2px 0;
- border-bottom: 1px solid #ccc;
-}
-
-.sidebar th {
- text-align: left;
- font-weight: normal;
- max-width: 300px;
- overflow: hidden;
-}
-
-.sidebar tr.sub th {
- text-indent: 20px;
-}
-
-.sidebar td {
- text-align: right;
- min-width: 20px;
-}
-
-.sidebar a {
- display: block;
- text-decoration: none;
- border-bottom: none;
- padding: 4px 0;
-}
-
-.sidebar tr.active {
- background: #ff0;
-}
-
-aside {
- display: none;
-}
- aside.source {
- position: absolute;
- bottom: 6px;
- left: 10px;
- text-indent: 10px;
- }
- aside.page_number {
- position: absolute;
- bottom: 6px;
- right: 10px;
- text-indent: 10px;
- }
-
-.notes {
- display: none;
- padding: 10px;
- background: #ccc;
- border-radius: 10px;
- -moz-border-radius: 10px;
- -webkit-border-radius: 10px;
-}
- div.slide p.notes {
- font-size: 90%;
-}
-
-img { display: block; margin: auto; }
-
-/* Expose */
-
-body.expose div.slides {
- float: left;
- position: relative;
- overflow: auto;
- margin-bottom: 10px;
-}
-
-body.expose div.slide {
- display: block;
- float: left;
- position: relative;
- left: auto !important;
- top: auto !important;
- margin: 10px !important;
- -webkit-transition: none;
- -moz-transition: none;
- -o-transition: none;
- -moz-transform: scale(.33, .33);
- -moz-transform-origin: 0 0;
- -webkit-transform: scale(.33, .33);
- -webkit-transform-origin: 0 0;
- -o-transform: scale(.33, .33);
- -o-transform-origin: 0 0;
- -webkit-transition: none;
- -moz-transition: none;
- -o-transition: none;
- cursor: pointer;
-}
-
-body.expose div.slide:hover {
- background: -webkit-gradient(linear, left bottom, left top, from(#bdd), to(#fff));
- background-color: #eee;
- background: -moz-linear-gradient(bottom, #bdd, #fff);
-}
-
-body.expose .slide-wrapper {
- float: left;
- position: relative;
- margin: .5%;
- width: 300px;
- height: 233px;
-}
-
-body.expose .slide footer {
-}
-
-body.expose .slide .inner {
-}
-
-body.expose .slide.far-past,
-body.expose .slide.past,
-body.expose .slide.future,
-body.expose .slide.far-future {
- margin-left: 0;
-}
-
-body.expose .slide.current {
- background: -webkit-gradient(linear, left bottom, left top, from(#ddb), to(#fff));
- background-color: #eee;
- background: -moz-linear-gradient(bottom, #ddb, #fff);
- border: 16px solid #fff;
- -moz-transform: scale(.315, .315);
- -moz-transform-origin: 0 0;
- -webkit-transform: scale(.315, .315);
- -webkit-transform-origin: 0 0;
- -o-transform: scale(.315, .315);
- -o-transform-origin: 0 0;
-}
-
-/* Pygments default theme */
-.hll { background-color: #ffffcc }
-.c { color: #408080; font-style: italic } /* Comment */
-.err { border: 1px solid #FF0000 } /* Error */
-.k { color: #008000; font-weight: bold } /* Keyword */
-.o { color: #666666 } /* Operator */
-.cm { color: #408080; font-style: italic } /* Comment.Multiline */
-.cp { color: #BC7A00 } /* Comment.Preproc */
-.c1 { color: #408080; font-style: italic } /* Comment.Single */
-.cs { color: #408080; font-style: italic } /* Comment.Special */
-.gd { color: #A00000 } /* Generic.Deleted */
-.ge { font-style: italic } /* Generic.Emph */
-.gr { color: #FF0000 } /* Generic.Error */
-.gh { color: #000080; font-weight: bold } /* Generic.Heading */
-.gi { color: #00A000 } /* Generic.Inserted */
-.go { color: #808080 } /* Generic.Output */
-.gp { color: #000080; font-weight: bold } /* Generic.Prompt */
-.gs { font-weight: bold } /* Generic.Strong */
-.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
-.gt { color: #0040D0 } /* Generic.Traceback */
-.kc { color: #008000; font-weight: bold } /* Keyword.Constant */
-.kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
-.kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
-.kp { color: #008000 } /* Keyword.Pseudo */
-.kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
-.kt { color: #B00040 } /* Keyword.Type */
-.m { color: #666666 } /* Literal.Number */
-.s { color: #BA2121 } /* Literal.String */
-.na { color: #7D9029 } /* Name.Attribute */
-.nb { color: #008000 } /* Name.Builtin */
-.nc { color: #0000FF; font-weight: bold } /* Name.Class */
-.no { color: #880000 } /* Name.Constant */
-.nd { color: #AA22FF } /* Name.Decorator */
-.ni { color: #999999; font-weight: bold } /* Name.Entity */
-.ne { color: #D2413A; font-weight: bold } /* Name.Exception */
-.nf { color: #0000FF } /* Name.Function */
-.nl { color: #A0A000 } /* Name.Label */
-.nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
-.nt { color: #008000; font-weight: bold } /* Name.Tag */
-.nv { color: #19177C } /* Name.Variable */
-.ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
-.w { color: #bbbbbb } /* Text.Whitespace */
-.mf { color: #666666 } /* Literal.Number.Float */
-.mh { color: #666666 } /* Literal.Number.Hex */
-.mi { color: #666666 } /* Literal.Number.Integer */
-.mo { color: #666666 } /* Literal.Number.Oct */
-.sb { color: #BA2121 } /* Literal.String.Backtick */
-.sc { color: #BA2121 } /* Literal.String.Char */
-.sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
-.s2 { color: #BA2121 } /* Literal.String.Double */
-.se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
-.sh { color: #BA2121 } /* Literal.String.Heredoc */
-.si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
-.sx { color: #008000 } /* Literal.String.Other */
-.sr { color: #BB6688 } /* Literal.String.Regex */
-.s1 { color: #BA2121 } /* Literal.String.Single */
-.ss { color: #19177C } /* Literal.String.Symbol */
-.bp { color: #008000 } /* Name.Builtin.Pseudo */
-.vc { color: #19177C } /* Name.Variable.Class */
-.vg { color: #19177C } /* Name.Variable.Global */
-.vi { color: #19177C } /* Name.Variable.Instance */
-.il { color: #666666 } /* Literal.Number.Integer.Long */
-
-/* Presenter Mode */
-
-body.presenter_view div.slide {
- display: inline;
- position: absolute;
- overflow: hidden;
- -moz-transform: scale(.5, .5);
- -moz-transform-origin: 0 0;
- -webkit-transform: scale(.5, .5);
- -webkit-transform-origin: 0 0;
- -o-transform: scale(.5, .5);
- -o-transform-origin: 0 0;
- margin-top: -300px;
-}
-
-body.presenter_view .slide.far-past {
- display: block;
- margin-left: -1500px;
-}
-
-body.presenter_view .slide.past {
- display: block;
- margin-left: -975px;
-}
-
-body.presenter_view .slide.current {
- display: block;
- margin-left: -475px;
- border: 8px solid maroon;
- z-index: 2;
-}
-
-body.presenter_view .slide.future {
- display: block;
- margin-left: 25px;
- z-index: 1;
-}
-
-body.presenter_view .slide.far-future {
- display: block;
- margin-left: 525px;
-}
-
-body.presenter_view div#current_presenter_notes {
- visibility: visible;
- display: block;
- position: absolute;
- overflow: auto;
- vertical-align: middle;
- left: 50%;
- top: 50%;
- margin-left: -475px;
- margin-top: 100px;
- z-index: 2;
- width: 950px;
- border-style: solid;
- height: 30%;
- background-color: silver;
-}
-
-body.presenter_view div#current_presenter_notes section {
- font-family: "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
- color: black;
- text-shadow: rgba(0, 0, 0, 0.2) 0 2px 5px;
- display: block;
- overflow: visible;
- position: relative;
- background-color: #fffeff;
- height: 120px;
- margin-right: 30px;
- margin-top: 60px;
- margin-left: 30px;
- padding-right: 10px;
- padding-left: 10px;
- padding-top: 10px;
-}
-
-body.presenter_view div#current_presenter_notes section p {
- margin: 0;
-}
-
-body.presenter_view div#current_presenter_notes h1 {
- font-size: 50%;
- display: block;
-}
-
-div#current_presenter_notes {
- display: none;
-}
-
-div.slide div.presenter_notes {
- display: none;
-}
-
-#blank {
- position: absolute;
- top: 0;
- left: 0;
- background-color: black;
- width: 100%;
- height: 100%;
- z-index: 64;
- display: none;
-}
-
- </style>
-
-
-
- <style type="text/css" media="screen, projection">
- div.slide p {
- font-size: 40px;
-}
-
-pre {
- font-size: 32px;
-}
-
-li {
- font-size: 40px;
-}
-
-
-
-body.presenter_view div#current_presenter_notes li {
- font-size: 14px;
- padding: 0;
-}
-
-body.presenter_view div#current_presenter_notes section {
- height: 170px;
-}
-
- </style>
-
-
- <!-- /Styles -->
- <!-- Javascripts -->
-
- <script>
- function main() {
- // Since we don't have the fallback of attachEvent and
- // other IE only stuff we won't try to run JS for IE.
- // It will run though when using Google Chrome Frame
- if (document.all) { return; }
-
- var currentSlideNo;
- var notesOn = false;
- var expanded = false;
- var hiddenContext = false;
- var blanked = false;
- var slides = document.getElementsByClassName('slide');
- var touchStartX = 0;
- var spaces = /\s+/, a1 = [''];
- var tocOpened = false;
- var helpOpened = false;
- var overviewActive = false;
- var modifierKeyDown = false;
- var scale = 1;
- var showingPresenterView = false;
- var presenterViewWin = null;
- var isPresenterView = false;
-
- var str2array = function(s) {
- if (typeof s == 'string' || s instanceof String) {
- if (s.indexOf(' ') < 0) {
- a1[0] = s;
- return a1;
- } else {
- return s.split(spaces);
- }
- }
- return s;
- };
-
- var trim = function(str) {
- return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
- };
-
- var addClass = function(node, classStr) {
- classStr = str2array(classStr);
- var cls = ' ' + node.className + ' ';
- for (var i = 0, len = classStr.length, c; i < len; ++i) {
- c = classStr[i];
- if (c && cls.indexOf(' ' + c + ' ') < 0) {
- cls += c + ' ';
- }
- }
- node.className = trim(cls);
- };
-
- var removeClass = function(node, classStr) {
- var cls;
- if (!node) {
- throw 'no node provided';
- }
- if (classStr !== undefined) {
- classStr = str2array(classStr);
- cls = ' ' + node.className + ' ';
- for (var i = 0, len = classStr.length; i < len; ++i) {
- cls = cls.replace(' ' + classStr[i] + ' ', ' ');
- }
- cls = trim(cls);
- } else {
- cls = '';
- }
- if (node.className != cls) {
- node.className = cls;
- }
- };
-
- var getSlideEl = function(slideNo) {
- if (slideNo > 0) {
- return slides[slideNo - 1];
- } else {
- return null;
- }
- };
-
- var getSlideTitle = function(slideNo) {
- var el = getSlideEl(slideNo);
- if (el) {
- var headers = el.getElementsByTagName('header');
- if (headers.length > 0) {
- return el.getElementsByTagName('header')[0].innerText;
- }
- }
- return null;
- };
-
- var getSlidePresenterNote = function(slideNo) {
- var el = getSlideEl(slideNo);
- if (el) {
- var n = el.getElementsByClassName('presenter_notes');
- if (n.length > 0) {
- return n[0];
- }
- }
- return null;
- };
-
- var changeSlideElClass = function(slideNo, className) {
- var el = getSlideEl(slideNo);
- if (el) {
- removeClass(el, 'far-past past current future far-future');
- addClass(el, className);
- }
- };
-
- var updateSlideClasses = function(updateOther) {
- window.location.hash = (isPresenterView ? "presenter" : "slide") + currentSlideNo;
-
- for (var i=1; i<currentSlideNo-1; i++) {
- changeSlideElClass(i, 'far-past');
- }
-
- changeSlideElClass(currentSlideNo - 1, 'past');
- changeSlideElClass(currentSlideNo, 'current');
- changeSlideElClass(currentSlideNo + 1, 'future');
-
- for (i=currentSlideNo+2; i<slides.length+1; i++) {
- changeSlideElClass(i, 'far-future');
- }
-
- highlightCurrentTocLink();
-
- processContext();
-
- document.getElementsByTagName('title')[0].innerText = getSlideTitle(currentSlideNo);
-
- updatePresenterNotes();
-
- if (updateOther) { updateOtherPage(); }
- };
-
- var updatePresenterNotes = function() {
- if (!isPresenterView) { return; }
-
- var existingNote = document.getElementById('current_presenter_notes');
- var currentNote = getSlidePresenterNote(currentSlideNo).cloneNode(true);
- currentNote.setAttribute('id', 'presenter_note');
-
- existingNote.replaceChild(currentNote, document.getElementById('presenter_note'));
- };
-
- var highlightCurrentTocLink = function() {
- var toc = document.getElementById('toc');
-
- if (toc) {
- var tocRows = toc.getElementsByTagName('tr');
- for (var i=0; i<tocRows.length; i++) {
- removeClass(tocRows.item(i), 'active');
- }
-
- var currentTocRow = document.getElementById('toc-row-' + currentSlideNo);
- if (currentTocRow) {
- addClass(currentTocRow, 'active');
- }
- }
- };
-
- var updateOtherPage = function() {
- if (!showingPresenterView) { return; }
-
- var w = isPresenterView ? window.opener : presenterViewWin;
- w.postMessage('slide#' + currentSlideNo, '*');
- };
-
- var nextSlide = function() {
- if (currentSlideNo < slides.length) {
- currentSlideNo++;
- }
- updateSlideClasses(true);
- };
-
- var prevSlide = function() {
- if (currentSlideNo > 1) {
- currentSlideNo--;
- }
- updateSlideClasses(true);
- };
-
- var showNotes = function() {
- var notes = getSlideEl(currentSlideNo).getElementsByClassName('notes');
- for (var i = 0, len = notes.length; i < len; i++) {
- notes.item(i).style.display = (notesOn) ? 'none':'block';
- }
- notesOn = !notesOn;
- };
-
- var showSlideNumbers = function() {
- var asides = document.getElementsByClassName('page_number');
- var hidden = asides[0].style.display != 'block';
- for (var i = 0; i < asides.length; i++) {
- asides.item(i).style.display = hidden ? 'block' : 'none';
- }
- };
-
- var showSlideSources = function() {
- var asides = document.getElementsByClassName('source');
- var hidden = asides[0].style.display != 'block';
- for (var i = 0; i < asides.length; i++) {
- asides.item(i).style.display = hidden ? 'block' : 'none';
- }
- };
-
- var showToc = function() {
- if (helpOpened) {
- showHelp();
- }
- var toc = document.getElementById('toc');
- if (toc) {
- toc.style.marginLeft = tocOpened ? '-' + (toc.clientWidth + 20) + 'px' : '0px';
- tocOpened = !tocOpened;
- }
- updateOverview();
- };
-
- var showHelp = function() {
- if (tocOpened) {
- showToc();
- }
-
- var help = document.getElementById('help');
-
- if (help) {
- help.style.marginLeft = helpOpened ? '-' + (help.clientWidth + 20) + 'px' : '0px';
- helpOpened = !helpOpened;
- }
- };
-
- var showPresenterView = function() {
- if (isPresenterView) { return; }
-
- if (showingPresenterView) {
- presenterViewWin.close();
- presenterViewWin = null;
- showingPresenterView = false;
- } else {
- presenterViewWin = open(window.location.pathname + "#presenter" + currentSlideNo, 'presenter_notes',
- 'directories=no,location=no,toolbar=no,menubar=no,copyhistory=no');
- showingPresenterView = true;
- }
- };
-
- var switch3D = function() {
- if (document.body.className.indexOf('three-d') == -1) {
- document.getElementsByClassName('presentation')[0].style.webkitPerspective = '1000px';
- document.body.className += ' three-d';
- } else {
- window.setTimeout('document.getElementsByClassName(\'presentation\')[0].style.webkitPerspective = \'0\';', 2000);
- document.body.className = document.body.className.replace(/three-d/, '');
- }
- };
-
- var toggleOverview = function() {
- if (!overviewActive) {
- addClass(document.body, 'expose');
- overviewActive = true;
- setScale(1);
- } else {
- removeClass(document.body, 'expose');
- overviewActive = false;
- if (expanded) {
- setScale(scale); // restore scale
- }
- }
- processContext();
- updateOverview();
- };
-
- var updateOverview = function() {
- try {
- var presentation = document.getElementsByClassName('presentation')[0];
- } catch (e) {
- return;
- }
-
- if (isPresenterView) {
- var action = overviewActive ? removeClass : addClass;
- action(document.body, 'presenter_view');
- }
-
- var toc = document.getElementById('toc');
-
- if (!toc) {
- return;
- }
-
- if (!tocOpened || !overviewActive) {
- presentation.style.marginLeft = '0px';
- presentation.style.width = '100%';
- } else {
- presentation.style.marginLeft = toc.clientWidth + 'px';
- presentation.style.width = (presentation.clientWidth - toc.clientWidth) + 'px';
- }
- };
-
- var computeScale = function() {
- var cSlide = document.getElementsByClassName('current')[0];
- var sx = cSlide.clientWidth / window.innerWidth;
- var sy = cSlide.clientHeight / window.innerHeight;
- return 1 / Math.max(sx, sy);
- };
-
- var setScale = function(scale) {
- var presentation = document.getElementsByClassName('slides')[0];
- var transform = 'scale(' + scale + ')';
- presentation.style.MozTransform = transform;
- presentation.style.WebkitTransform = transform;
- presentation.style.OTransform = transform;
- presentation.style.msTransform = transform;
- presentation.style.transform = transform;
- };
-
- var expandSlides = function() {
- if (overviewActive) {
- return;
- }
- if (expanded) {
- setScale(1);
- expanded = false;
- } else {
- scale = computeScale();
- setScale(scale);
- expanded = true;
- }
- };
-
- var showContext = function() {
- try {
- var presentation = document.getElementsByClassName('slides')[0];
- removeClass(presentation, 'nocontext');
- } catch (e) {}
- };
-
- var hideContext = function() {
- try {
- var presentation = document.getElementsByClassName('slides')[0];
- addClass(presentation, 'nocontext');
- } catch (e) {}
- };
-
- var processContext = function() {
- if (hiddenContext) {
- hideContext();
- } else {
- showContext();
- }
- };
-
- var toggleContext = function() {
- hiddenContext = !hiddenContext;
- processContext();
- };
-
- var toggleBlank = function() {
- blank_elem = document.getElementById('blank');
-
- blank_elem.style.display = blanked ? 'none' : 'block';
-
- blanked = !blanked;
- };
-
- var isModifierKey = function(keyCode) {
- switch (keyCode) {
- case 16: // shift
- case 17: // ctrl
- case 18: // alt
- case 91: // command
- return true;
- break;
- default:
- return false;
- break;
- }
- };
-
- var checkModifierKeyUp = function(event) {
- if (isModifierKey(event.keyCode)) {
- modifierKeyDown = false;
- }
- };
-
- var checkModifierKeyDown = function(event) {
- if (isModifierKey(event.keyCode)) {
- modifierKeyDown = true;
- }
- };
-
- var handleBodyKeyDown = function(event) {
- switch (event.keyCode) {
- case 13: // Enter
- if (overviewActive) {
- toggleOverview();
- }
- break;
- case 27: // ESC
- toggleOverview();
- break;
- case 37: // left arrow
- case 33: // page up
- prevSlide();
- break;
- case 39: // right arrow
- case 32: // space
- case 34: // page down
- nextSlide();
- break;
- case 50: // 2
- if (!modifierKeyDown) {
- showNotes();
- }
- break;
- case 51: // 3
- if (!modifierKeyDown && !overviewActive) {
- switch3D();
- }
- break;
- case 190: // .
- case 48: // 0
- case 66: // b
- if (!modifierKeyDown && !overviewActive) {
- toggleBlank();
- }
- break;
- case 67: // c
- if (!modifierKeyDown && !overviewActive) {
- toggleContext();
- }
- break;
- case 69: // e
- if (!modifierKeyDown && !overviewActive) {
- expandSlides();
- }
- break;
- case 72: // h
- showHelp();
- break;
- case 78: // n
- if (!modifierKeyDown && !overviewActive) {
- showSlideNumbers();
- }
- break;
- case 80: // p
- if (!modifierKeyDown && !overviewActive) {
- showPresenterView();
- }
- break;
- case 83: // s
- if (!modifierKeyDown && !overviewActive) {
- showSlideSources();
- }
- break;
- case 84: // t
- showToc();
- break;
- }
- };
-
- var handleWheel = function(event) {
- if (tocOpened || helpOpened || overviewActive) {
- return;
- }
-
- var delta = 0;
-
- if (!event) {
- event = window.event;
- }
-
- if (event.wheelDelta) {
- delta = event.wheelDelta/120;
- if (window.opera) delta = -delta;
- } else if (event.detail) {
- delta = -event.detail/3;
- }
-
- if (delta && delta <0) {
- nextSlide();
- } else if (delta) {
- prevSlide();
- }
- };
-
- var addSlideClickListeners = function() {
- for (var i=0; i < slides.length; i++) {
- var slide = slides.item(i);
- slide.num = i + 1;
- slide.addEventListener('click', function(e) {
- if (overviewActive) {
- currentSlideNo = this.num;
- toggleOverview();
- updateSlideClasses(true);
- e.preventDefault();
- }
- return false;
- }, true);
- }
- };
-
- var addRemoteWindowControls = function() {
- window.addEventListener("message", function(e) {
- if (e.data.indexOf("slide#") != -1) {
- currentSlideNo = Number(e.data.replace('slide#', ''));
- updateSlideClasses(false);
- }
- }, false);
- };
-
- var addTouchListeners = function() {
- document.addEventListener('touchstart', function(e) {
- touchStartX = e.touches[0].pageX;
- }, false);
- document.addEventListener('touchend', function(e) {
- var pixelsMoved = touchStartX - e.changedTouches[0].pageX;
- var SWIPE_SIZE = 150;
- if (pixelsMoved > SWIPE_SIZE) {
- nextSlide();
- }
- else if (pixelsMoved < -SWIPE_SIZE) {
- prevSlide();
- }
- }, false);
- };
-
- var addTocLinksListeners = function() {
- var toc = document.getElementById('toc');
- if (toc) {
- var tocLinks = toc.getElementsByTagName('a');
- for (var i=0; i < tocLinks.length; i++) {
- tocLinks.item(i).addEventListener('click', function(e) {
- currentSlideNo = Number(this.attributes['href'].value.replace('#slide', ''));
- updateSlideClasses(true);
- e.preventDefault();
- }, true);
- }
- }
- };
-
- // initialize
-
- (function() {
- if (window.location.hash == "") {
- currentSlideNo = 1;
- } else if (window.location.hash.indexOf("#presenter") != -1) {
- currentSlideNo = Number(window.location.hash.replace('#presenter', ''));
- isPresenterView = true;
- showingPresenterView = true;
- presenterViewWin = window;
- addClass(document.body, 'presenter_view');
- } else {
- currentSlideNo = Number(window.location.hash.replace('#slide', ''));
- }
-
- document.addEventListener('keyup', checkModifierKeyUp, false);
- document.addEventListener('keydown', handleBodyKeyDown, false);
- document.addEventListener('keydown', checkModifierKeyDown, false);
- document.addEventListener('DOMMouseScroll', handleWheel, false);
-
- window.onmousewheel = document.onmousewheel = handleWheel;
- window.onresize = expandSlides;
-
- for (var i = 0, el; el = slides[i]; i++) {
- addClass(el, 'slide far-future');
- }
- updateSlideClasses(false);
-
- // add support for finger events (filter it by property detection?)
- addTouchListeners();
-
- addTocLinksListeners();
-
- addSlideClickListeners();
-
- addRemoteWindowControls();
- })();
-}
-
- </script>
-
-
- <!-- /Javascripts -->
-</head>
-<body>
- <div id="blank"></div>
- <div class="presentation">
- <div id="current_presenter_notes">
- <div id="presenter_note"></div>
- </div>
- <div class="slides">
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Backbone.js on Rails</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 1/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Goals for this talk</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <h2>After this talk, you will:</h2>
-<ul>
-<li>Know why and how to use a client-side framework</li>
-<li>Be able to read up on a few of them</li>
-<li>Be able to follow along with Backbone tutorials</li>
-<li>Know how to add Backbone to a new or existing Rails app</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 2/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Apps shifting client-side</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <p>These days, some web apps have more code on the client than on the server.</p>
-<p>Learn how Backbone.js is put together, how to use it with Rails, and how to make building JavaScript-heavy apps a pleasure.</p>
-<p>How much JS?</p>
-<ul>
-<li>Airbrake: Almost 0</li>
-<li>Copycopter: 30%</li>
-<li>Trajectory 41%</li>
-<li>IoraHealth: 62%</li>
-<li>Substance.io: 100%</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 3/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Organize your JavaScript</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>Hands up: Procedural apps? Tag-soup PHP/JSP/whatever-SP? Now, framework?</li>
-<li>Patterns for organization. MVC is one. Good for GUI.</li>
-<li>MVC over HTTP is often stateless. Some state maintained with session</li>
-<li>MVC in GUI is stateful. Embrace this.</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 4/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>But which framework?</h1></header>
-
-
- <section><ul>
-<li>Cappuccino</li>
-<li>SproutCore (1.x, 2.x)</li>
-<li>Knockout.js</li>
-<li>Batman.js</li>
-<li>JavaScriptMVC</li>
-<li>Spine.js</li>
-<li>Backbone.js</li>
-<li>Angular, Coherent, PureMVC-js, AFrameJS, TrimPath Junction, ...</li>
-</ul>
-</section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li><a href="http://www.nytimes.com/2011/08/21/magazine/do-you-suffer-from-decision-fatigue.html">Decision Fatigue NY Times Mag article</a></li>
-<li>Cappuccino/SproutCore: UI controls. Desktop like.</li>
-<li>SC2: Similar, larger. Less doc. Declarative bindings, even in templates.</li>
-<li>Knockout: MVVM. WCF, Silverlight.</li>
-<li>Batman: Node server, share models, data-bind templates</li>
-<li>JavaScriptMVC: Larger, older, generators, dep mgmt, builds, testing, jQuery-based-and-like, JSON/REST transport</li>
-<li>Spine.js: Very similar. Even smaller. Coffee. Fully async, client rules.</li>
-<li>Backbone: Small, pragmatic, extracted from DocumentCloud</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 5/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Moving parts</h1></header>
-
-
- <section><ul>
-<li>History</li>
-<li>Router</li>
-<li>View</li>
-<li>Model</li>
-<li>Collection</li>
-<li>Sync</li>
-<li>Underscore</li>
-<li>$</li>
-</ul>
-</section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>History - Handles hashchange, pushstate, BB.history.start()</li>
-<li>Router - read fragment, dispatch to action</li>
-<li>View - Root DOM <code>el</code>, class/id/tagName, <code>this.$</code>, <code>events</code>, <code>$.delegate</code>, any templating</li>
-<li>Model - Conversions, computed properties, validations, access control, events change/change:attr,destroy,error</li>
-<li>Collection - Ordered set of models. URL, fetch(), reset(json), _.methods, comparator, events reset/add/remove/all model events</li>
-<li>Sync - Encapsulation of persistence. Default <code>$.ajax</code> to RESTful JSON API. Designed for override, global or per-class.</li>
-<li>Underscore - FP (select, reduce), bind, template, deep isEqual, clone, tap</li>
-<li>$ - jQuery || Zepto</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 6/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Example</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>Trajectory on local</li>
-<li>stories#index</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 7/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Walk through a request</h1></header>
-
-
- <section><ul>
-<li>URI: <code>/projects/oss/stories#84245</code></li>
-<li><code>GET /projects/oss/stories</code></li>
-<li>Rails response: HTML, <code>&lt;script&gt;</code>s, JSON</li>
-</ul></section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 8/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Walk through a request</h1></header>
-
-
- <section><ul>
-<li>Bootstrap collections</li>
-<li>Instantiate router</li>
-<li><code>Backbone.history.start()</code></li>
-</ul></section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 9/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Walk through a request</h1></header>
-
-
- <section><ul>
-<li>Route <code>'#84245'</code> fragment</li>
-<li>Dispatch to action</li>
-<li><code>new View(modelOrCollection)</code></li>
-<li>event and data bindings</li>
-<li><code>view.render()</code></li>
-<li><code>_.template()</code></li>
-<li><code>$('#app').html(theViewHtmls)</code></li>
-</ul></section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 10/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Code tour: client side</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>Back to front.<ul>
-<li>Script load</li>
-<li>JSON collection bootstrapping</li>
-<li>Init -&gt; Backbone.history.start()</li>
-<li>Routing</li>
-<li>View class</li>
-<li>Models and collections</li>
-<li>Templating</li>
-<li>Underscore.js. Mixed into collections.</li>
-</ul>
-</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 11/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Code tour: server side</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>Rails integration. Back to front.<ul>
-<li>File organization for 3.0: JS, JST, Jammit</li>
-<li>File organization for 3.1: Asset pipeline, <a href="https://github.com/codebrew/backbone-rails"><code>rails-backbone</code> gem</a></li>
-<li>JSON APIs<ul>
-<li><a href="https://github.com/jasonm/wizards/blob/master/config/initializers/wrap_parameters.rb"><code>ActiveRecord.include_root_in_json</code></a></li>
-<li>Rails 3.1 <a href="https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/params_wrapper.rb">Params Wrapper</a></li>
-<li>Model#as_json probably isnt the best place for presentation: Presenter object, <a href="https://github.com/nesquena/rabl">rabl</a></li>
-</ul>
-</li>
-<li><a href="https://github.com/codebrew/backbone-rails/blob/master/vendor/assets/javascripts/backbone_rails_sync.js#L26-27">CSRF Token</a></li>
-</ul>
-</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 12/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Bonus stuff!</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>What is left?<ul>
-<li>Testing</li>
-<li>pushState</li>
-<li>push sync (WebSocket)</li>
-</ul>
-</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 13/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Testing</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 14/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Testing</h1></header>
-
-
- <section><ul>
-<li>It's just JavaScript!</li>
-</ul>
-</section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>Yes it's just JavaScript.</li>
-<li>But...</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 15/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Testing</h1></header>
-
-
- <section><ul>
-<li>It's just <strong>stateful and asynchronous business and presentation logic written in</strong> JavaScript!</li>
-</ul>
-</section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>Luckily...</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 16/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Testing</h1></header>
-
-
- <section><ul>
-<li>It's just stateful and asynchronous business and presentation logic written in <strong>modular, decoupled</strong> JavaScript!</li>
-</ul></section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 17/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Testing</h1></header>
-
-
- <section><ul>
-<li>Isolation: Jasmine</li>
-<li>Integration: capybara-webkit, selenium</li>
-</ul>
-</section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li><a href="http://pivotal.github.com/jasmine/">Jasmine</a> goodies! Get these.<ul>
-<li>Spy/stub/mock, even your HTTP, with <a href="http://sinonjs.org/">sinon.js</a></li>
-<li>If you're looking for factory_girl.js, it's called <a href="https://github.com/bkeepers/rosie">Rosie</a></li>
-<li><a href="https://github.com/netzpirat/guard-jasmine">guard-jasmine</a> autotest your Jasmine with headless webkit (<a href="http://www.phantomjs.org/">phantomjs</a>)</li>
-<li>Write in CoffeeScript and use the 3.1 asset pipeline with <a href="https://github.com/bradphelan/jasminerice">jasminerice</a></li>
-<li>Get started with James Newbery's excellent blog posts on <a href="http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html">testing Backbone with Jasmine</a></li>
-<li>Check out his <a href="https://github.com/froots/backbone-jasmine-examples">examples on GitHub</a></li>
-</ul>
-</li>
-<li>Integration test with:<ul>
-<li><a href="https://github.com/thoughtbot/capybara-webkit">capybara-webkit</a> for fast, headless, accurate WebKit testing</li>
-<li>Selenium for other browsers, or if capybara-webkit has issues.</li>
-</ul>
-</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 18/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>pushState</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>Look at github.</li>
-<li>Opt-in.</li>
-<li><code>Backbone.history.start({pushState: true});</code></li>
-<li>Server-side support.</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 19/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Push synchronization</h1></header>
-
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- <ul>
-<li>Rails <code>Model#save</code> cascades to clients: <a href="https://github.com/jasonm/backbone_sync-rails">backbone_sync-rails</a> over pubsub bus <a href="http://faye.jcoglan.com/">Faye</a></li>
-<li>Work-in-progress <a href="http://en.wikipedia.org/wiki/Software_transactional_memory">Software transactional memory</a> sync: <a href="https://github.com/codeparty/racer">https://github.com/codeparty/racer</a><ul>
-<li>Future plans: <a href="http://code.google.com/p/google-diff-match-patch/">diff-match-patch</a>, <a href="http://en.wikipedia.org/wiki/Operational_transformation">Operational transform</a></li>
-</ul>
-</li>
-<li><a href="http://nowjs.org/">Now.js</a></li>
-<li><a href="https://github.com/substack/dnode">Substack DNode</a></li>
-<li><a href="http://substance.io/michael/data-js">Data.js</a>: Data Manipulation and Graph Persistence for Node.js and the Browser. Can ride now.js transport.<ul>
-<li>substance.io, above, is written with Backbone.js, and is open source <a href="https://github.com/michael/substance">https://github.com/michael/substance</a></li>
-</ul>
-</li>
-<li><a href="http://andyet.net/blog/2011/feb/15/re-using-backbonejs-models-on-the-server-with-node/">Backbone on the server with node.js</a>... with DNode or NowJS (?!)</li>
-</ul>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 20/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Get your code on</h1></header>
-
-
- <section><ul>
-<li><a href="http://documentcloud.github.com/backbone/#examples-todos">Todo App example</a></li>
-<li><a href="https://github.com/froots/backbone-jasmine-examples/tree/master/public/javascripts">James Newbery's jasmine examples</a></li>
-</ul></section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 21/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Further reading: Books on JavaScript</h1></header>
-
-
- <section><ul>
-<li><a href="http://shop.oreilly.com/product/9780596517748.do">JavaScript: The Good Parts</a> by Douglas Crockford</li>
-<li><a href="http://shop.oreilly.com/product/0636920018421.do">JavaScript Web Applications</a> by Alex MacCaw (Spine.js author)</li>
-<li><a href="http://tddjs.com/">Test-Driven JavaScript Development</a> by Christian Johansen</li>
-<li><a href="http://shop.oreilly.com/product/9780596806767.do">JavaScript Patterns</a> by Stoyan Stefanov</li>
-<li><a href="http://shop.oreilly.com/product/9780596805531.do">JavaScript: The Definitive Guide</a> by David Flanagan</li>
-</ul></section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 22/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Further reading: Online resources</h1></header>
-
-
- <section><ul>
-<li><a href="http://documentcloud.github.com/backbone/">Official Backbone docs</a> - they're excellent!</li>
-<li><a href="https://groups.google.com/group/backbonejs">Backbone Google Group</a></li>
-<li><a href="http://workshops.thoughtbot.com/backbone-js-on-rails">Backbone on Rails eBook</a></li>
-<li><a href="http://peepcode.com/products/backbone-js">Peepcode episodes on Backbone</a></li>
-</ul></section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 23/24
- </aside>
- </footer>
- </div>
- </div>
-
- <!-- slide source: slides/index.md -->
- <div class="slide-wrapper">
- <div class="slide">
- <div class="inner">
-
- <header><h1>Thanks!</h1></header>
-
-
- <section><ul>
-<li>Me:<ul>
-<li><a href="mailto:jason.p.morrison@gmail.com">jason.p.morrison@gmail.com</a></li>
-<li><a href="http://twitter.com/jayunit">@jayunit</a></li>
-<li><a href="http://jayunit.net">http://jayunit.net</a></li>
-</ul>
-</li>
-<li>Slides:<ul>
-<li><a href="http://jayunit.net/backbone-js-on-rails-talk">View slides online</a></li>
-<li><a href="http://github.com/jasonm/backbone-js-on-rails-talk">View slides source on GitHub</a></li>
-</ul>
-</li>
-</ul></section>
-
- </div>
- <div class="presenter_notes">
- <header><h1>Presenter Notes</h1></header>
- <section>
-
- </section>
- </div>
- <footer>
-
- <aside class="source">
- Source: <a href="slides/index.md">slides/index.md</a>
- </aside>
-
- <aside class="page_number">
- 24/24
- </aside>
- </footer>
- </div>
- </div>
-
- </div>
- </div>
-
- <div id="toc" class="sidebar hidden">
- <h2>Table of Contents</h2>
- <table>
- <caption>Table of Contents</caption>
-
- <tr id="toc-row-1">
- <th><a href="#slide1">Backbone.js on Rails</a></th>
- <td><a href="#slide1">1</a></td>
- </tr>
-
-
- <tr id="toc-row-2">
- <th><a href="#slide2">Goals for this talk</a></th>
- <td><a href="#slide2">2</a></td>
- </tr>
-
-
- <tr id="toc-row-3">
- <th><a href="#slide3">Apps shifting client-side</a></th>
- <td><a href="#slide3">3</a></td>
- </tr>