Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: 621b760089
Fetching contributors…

Cannot retrieve contributors at this time

2256 lines (1885 sloc) 62.396 kB
<!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>
<section><p>(This is an HTML slide deck. Press "h" for help, or use the arrow keys to navigate. Press "p" for presenter notes, where you'll find a bunch of links, especially towards the end.)</p>
</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">
1/20
</aside>
</footer>
</div>
</div>
<!-- slide source: slides/index.md -->
<div class="slide-wrapper">
<div class="slide">
<div class="inner">
<header><h1>Web apps shifting client-side</h1></header>
</div>
<div class="presenter_notes">
<header><h1>Presenter Notes</h1></header>
<section>
<ul>
<li>These days, some web apps have more code on the client than on the server.</li>
<li>Who is seeing these trends? What are you doing about it?</li>
<li>
<p>How much JS?</p>
<ul>
<li>Airbrake: Almost 0</li>
<li>Copycopter: 30%</li>
<li>Trajectory 41%</li>
<li>IoraHealth: 62%</li>
</ul>
</li>
<li>
<p>Hands up: Ruby, Rails, JavaScript, web apps, csmvc</p>
</li>
</ul>
</section>
</div>
<footer>
<aside class="source">
Source: <a href="slides/index.md">slides/index.md</a>
</aside>
<aside class="page_number">
2/20
</aside>
</footer>
</div>
</div>
<!-- slide source: slides/index.md -->
<div class="slide-wrapper">
<div class="slide">
<div class="inner">
<header><h1>This talk</h1></header>
<section><ul>
<li>Client-side frameworks</li>
<li>Moving parts of Backbone</li>
<li>Example</li>
<li>Code dive</li>
<li>Bonus topics</li>
<li>Resources</li>
</ul>
</section>
</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">
3/20
</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>Where do frameworks come from?</li>
<li>Paradigm -&gt; path-least-resistance -&gt; implementation -&gt; architecture -&gt; technical debt</li>
<li>Server: Req/response (CGI, EHTML) -&gt; procedural &amp; tag soup *SP.</li>
<li>Client: Async ($) -&gt; Deeply nested callbacks (if-like), Stateful (DOM) -&gt; app data stored in the DOM.</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>CS-MVC in GUI is stateful. THIS IS OKAY!</li>
</ul>
</section>
</div>
<footer>
<aside class="source">
Source: <a href="slides/index.md">slides/index.md</a>
</aside>
<aside class="page_number">
4/20
</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, readable, intended for modification, 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/20
</aside>
</footer>
</div>
</div>
<!-- slide source: slides/index.md -->
<div class="slide-wrapper">
<div class="slide">
<div class="inner">
<header><h1>Backbone.js</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">
6/20
</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 - Takes model data, presents in DOM. Binds to DOM events, triggers app logic. 1:1 <code>el</code>, <code>this.$</code>, <code>events</code>, <code>$.delegate</code>, 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">
7/20
</aside>
</footer>
</div>
</div>
<!-- slide source: slides/index.md -->
<div class="slide-wrapper">
<div class="slide">
<div class="inner">
<header><h1>Example</h1></header>
<section><ul>
<li>http://backbonechat.herokuapp.com</li>
<li>https://github.com/jasonm/chat_app</li>
</ul>
</section>
</div>
<div class="presenter_notes">
<header><h1>Presenter Notes</h1></header>
<section>
<ul>
<li>https://github.com/jasonm/chat_app</li>
<li>URI: <code>/projects/oss/stories/#1</code></li>
<li><code>GET /projects/oss/stories/</code></li>
<li>Rails response: HTML, <code>&lt;script&gt;</code>s, JSON</li>
<li>Bootstrap collections</li>
<li>Instantiate router</li>
<li><code>Backbone.history.start()</code></li>
<li>Route fragment</li>
<li>Dispatch to backbone action</li>
<li>Create view</li>
<li>event and data bindings</li>
<li><code>view.render()</code></li>
<li><code>_.template()</code></li>
<li><code>$('#some-elem').html(someHtml)</code></li>
</ul>
</section>
</div>
<footer>
<aside class="source">
Source: <a href="slides/index.md">slides/index.md</a>
</aside>
<aside class="page_number">
8/20
</aside>
</footer>
</div>
</div>
<!-- slide source: slides/index.md -->
<div class="slide-wrapper">
<div class="slide">
<div class="inner">
<header><h1>Rails integration</h1></header>
<section><ul>
<li>File organization</li>
<li>JSON API</li>
<li>CSRF</li>
</ul>
</section>
</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> / wrap_parameters</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">
9/20
</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">
10/20
</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>
<ul>
<li>Business and presentation logic</li>
<li>Stateful</li>
<li>Asynchronous</li>
<li>Modular, decoupled JS</li>
</ul>
</section>
</div>
<footer>
<aside class="source">
Source: <a href="slides/index.md">slides/index.md</a>
</aside>
<aside class="page_number">
11/20
</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">
12/20
</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>GitHub's source browser uses it with <a href="https://github.com/defunkt/jquery-pjax">pjax</a></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">
13/20
</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">
14/20
</aside>
</footer>
</div>
</div>
<!-- slide source: slides/index.md -->
<div class="slide-wrapper">
<div class="slide">
<div class="inner">
<header><h1>Resources</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">
15/20
</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">
16/20
</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">
17/20
</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://workshops.thoughtbot.com/backbone-js-on-rails?utm_source=jm-talk">Backbone on Rails eBook</a></li>
<li><a href="http://documentcloud.github.com/backbone/">Official Backbone docs</a></li>
<li><a href="http://documentcloud.github.com/backbone/docs/backbone.html">Annotated source code</a></li>
<li><a href="http://documentcloud.github.com/underscore/">Underscore docs</a> and <a href="http://documentcloud.github.com/underscore/docs/underscore.html">source</a></li>
<li><a href="https://groups.google.com/group/backbonejs">Backbone Google Group</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">
18/20
</aside>
</footer>
</div>
</div>
<!-- slide source: slides/index.md -->
<div class="slide-wrapper">
<div class="slide">
<div class="inner">
<header><h1>Recap</h1></header>
<section><ul>
<li>Client-side frameworks</li>
<li>Moving parts of Backbone</li>
<li>Example</li>
<li>Code dive</li>
<li>Bonus topics</li>
<li>Resources</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">
19/20
</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">http://twitter.com/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>
<li>Code:<ul>
<li><a href="http://github.com/jasonm/chat_app">View chat app 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">
20/20
</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">Web apps shifting client-side</a></th>
<td><a href="#slide2">2</a></td>
</tr>
<tr id="toc-row-3">
<th><a href="#slide3">This talk</a></th>
<td><a href="#slide3">3</a></td>
</tr>
<tr id="toc-row-4">
<th><a href="#slide4">Organize your JavaScript</a></th>
<td><a href="#slide4">4</a></td>
</tr>
<tr id="toc-row-5">
<th><a href="#slide5">But which framework?</a></th>
<td><a href="#slide5">5</a></td>
</tr>
<tr id="toc-row-6">
<th><a href="#slide6">Backbone.js</a></th>
<td><a href="#slide6">6</a></td>
</tr>
<tr id="toc-row-7">
<th><a href="#slide7">Moving parts</a></th>
<td><a href="#slide7">7</a></td>
</tr>
<tr id="toc-row-8">
<th><a href="#slide8">Example</a></th>
<td><a href="#slide8">8</a></td>
</tr>
<tr id="toc-row-9">
<th><a href="#slide9">Rails integration</a></th>
<td><a href="#slide9">9</a></td>
</tr>
<tr id="toc-row-10">
<th><a href="#slide10">Bonus stuff!</a></th>
<td><a href="#slide10">10</a></td>
</tr>
<tr id="toc-row-11">
<th><a href="#slide11">Testing</a></th>
<td><a href="#slide11">11</a></td>
</tr>
<tr id="toc-row-12">
<th><a href="#slide12">Testing</a></th>
<td><a href="#slide12">12</a></td>
</tr>
<tr id="toc-row-13">
<th><a href="#slide13">pushState</a></th>
<td><a href="#slide13">13</a></td>
</tr>
<tr id="toc-row-14">
<th><a href="#slide14">Push synchronization</a></th>
<td><a href="#slide14">14</a></td>
</tr>
<tr id="toc-row-15">
<th><a href="#slide15">Resources</a></th>
<td><a href="#slide15">15</a></td>
</tr>
<tr id="toc-row-16">
<th><a href="#slide16">Get your code on</a></th>
<td><a href="#slide16">16</a></td>
</tr>
<tr id="toc-row-17">
<th><a href="#slide17">Further reading: Books on JavaScript</a></th>
<td><a href="#slide17">17</a></td>
</tr>
<tr id="toc-row-18">
<th><a href="#slide18">Further reading: Online resources</a></th>
<td><a href="#slide18">18</a></td>
</tr>
<tr id="toc-row-19">
<th><a href="#slide19">Recap</a></th>
<td><a href="#slide19">19</a></td>
</tr>
<tr id="toc-row-20">
<th><a href="#slide20">Thanks!</a></th>
<td><a href="#slide20">20</a></td>
</tr>
</table>
</div>
<div id="help" class="sidebar hidden">
<h2>Help</h2>
<table>
<caption>Help</caption>
<tr>
<th>Table of Contents</th>
<td>t</td>
</tr>
<tr>
<th>Exposé</th>
<td>ESC</td>
</tr>
<tr>
<th>Full screen slides</th>
<td>e</td>
</tr>
<tr>
<th>Presenter View</th>
<td>p</td>
</tr>
<tr>
<th>Source Files</th>
<td>s</td>
</tr>
<tr>
<th>Slide Numbers</th>
<td>n</td>
</tr>
<tr>
<th>Toggle screen blanking</th>
<td>b</td>
</tr>
<tr>
<th>Show/hide slide context</th>
<td>c</td>
</tr>
<tr>
<th>Notes</th>
<td>2</td>
</tr>
<tr>
<th>Help</th>
<td>h</td>
</tr>
</table>
</div>
<script>main()</script>
</body>
</html>
Jump to Line
Something went wrong with that request. Please try again.