showoff 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt CHANGED
@@ -2,13 +2,13 @@ ShowOff Presentation Software
2
2
  =============================
3
3
 
4
4
  ShowOff is a Sinatra web app that reads simple configuration files for a
5
- presentation. It is sort of like a Keynote web app engine - think S5 +
6
- Slidedown. I am using it to do all my talks in 2010, because I have a deep
5
+ presentation. It is sort of like a Keynote web app engine - think S5 +
6
+ Slidedown. I am using it to do all my talks in 2010, because I have a deep
7
7
  hatred in my heart for Keynote and yet it is by far the best in the field.
8
8
 
9
9
  The idea is that you setup your markdown slide files in section subdirectories
10
10
  and then startup the showoff server in that directory. It will read in your
11
- showoff.json file for which sections go in which order and then will give
11
+ showoff.json file for which sections go in which order and then will give
12
12
  you a URL to present from.
13
13
 
14
14
  It can:
@@ -20,10 +20,10 @@ It can:
20
20
  * re-enact command line interactions
21
21
  * call up a menu of sections/slides at any time to jump around
22
22
  * execute javascript or ruby live and display results
23
+ * do simple transitions (instant, fade, slide in)
23
24
 
24
25
  It might will can:
25
26
 
26
- * do simple transitions (instant, fade, slide in)
27
27
  * show a timer - elapsed / remaining
28
28
  * perform simple animations of images moving between keyframes
29
29
  * show syncronized, hidden notes on another browser (like an iphone)
@@ -48,7 +48,7 @@ it has a showoff.json file and a number of sections (subdirectories) with markdo
48
48
  $ cd (showoff-repo)
49
49
  $ showoff serve
50
50
 
51
- If you run 'showoff' in the ShowOff directory itself, it will show an example
51
+ If you run 'showoff' in the ShowOff directory itself, it will show an example
52
52
  presentation from the 'example' subdirectory, so you can see what it's like.
53
53
 
54
54
  Slide Format
@@ -60,7 +60,7 @@ your showoff.json file for any markdown files (.md). Each markdown file can
60
60
  have any number of slides in it, seperating each slide with the '!SLIDE'
61
61
  keyword and optional slide styles.
62
62
 
63
- For example, if you run 'showoff create my_new_pres' it will create a new
63
+ For example, if you run 'showoff create my_new_pres' it will create a new
64
64
  starter presentation for you with one .md file at one/slide.md which will have
65
65
  the following contents:
66
66
 
@@ -68,7 +68,7 @@ the following contents:
68
68
 
69
69
  # My Presentation #
70
70
 
71
- !SLIDE bullets incremental
71
+ !SLIDE bullets incremental transition=fade
72
72
 
73
73
  # Bullet Points #
74
74
 
@@ -76,17 +76,17 @@ the following contents:
76
76
  * second point
77
77
  * third point
78
78
 
79
- That represents two slides, one with just a large title and one with three
80
- bullets that are incrementally updated when the slide is shown. In order for
81
- ShowOff to see those slides, your showoff.json file needs to look something
82
- like this:
79
+ That represents two slides, the first contains just a large title, and the
80
+ second is faded into view showing the title and three bullets that are then
81
+ incrementally shown. In order for ShowOff to see those slides, your
82
+ showoff.json file needs to look something like this:
83
83
 
84
- [
85
- {"section":"one"}
84
+ [
85
+ {"section":"one"}
86
86
  ]
87
87
 
88
- If you have multiple sections in your talk, you can make this json array
89
- include all the sections you want to show in which order you want to show
88
+ If you have multiple sections in your talk, you can make this json array
89
+ include all the sections you want to show in which order you want to show
90
90
  them.
91
91
 
92
92
  Some useful styles for each slide are:
@@ -96,7 +96,7 @@ Some useful styles for each slide are:
96
96
  * smbullets - sizes and seperates more bullets (smaller, closer together)
97
97
  * subsection - creates a different background for titles
98
98
  * command - monospaces h1 title slides
99
- * commandline - for pasted commandline sections
99
+ * commandline - for pasted commandline sections
100
100
  (needs leading '$' for commands, then output on subsequent lines)
101
101
  * code - monospaces everything on the slide
102
102
  * incremental - can be used with 'bullets' and 'commandline' styles,
@@ -108,6 +108,43 @@ Some useful styles for each slide are:
108
108
 
109
109
  Check out the example directory included to see examples of most of these.
110
110
 
111
+ Transitions can be supplied through the use of transition=tname on the !SLIDE
112
+ definition, where tname is one of the following supported transitions:
113
+
114
+ * blindX
115
+ * blindY
116
+ * blindZ
117
+ * cover
118
+ * curtainX
119
+ * curtainY
120
+ * fade
121
+ * fadeZoom
122
+ * growX
123
+ * growY
124
+ * none (this is the default)
125
+ * scrollUp
126
+ * scrollDown
127
+ * scrollLeft
128
+ * scrollRight
129
+ * scrollHorz
130
+ * scrollVert
131
+ * shuffle
132
+ * slideX
133
+ * slideY
134
+ * toss
135
+ * turnUp
136
+ * turnDown
137
+ * turnLeft
138
+ * turnRight
139
+ * uncover
140
+ * wipe
141
+ * zoom
142
+
143
+ The transitions are provided by jQuery Cycle plugin. See
144
+ http://www.malsup.com/jquery/cycle/browser.html to view the effects and
145
+ http://www.malsup.com/jquery/cycle/adv2.html for how to add
146
+ custom effects.
147
+
111
148
  You can manage the presentation with the following keys:
112
149
 
113
150
  * space, cursor right: next slide
@@ -115,7 +152,7 @@ You can manage the presentation with the following keys:
115
152
  * d: debug mode
116
153
  * c: table of contents (vi)
117
154
  * f: toggle footer
118
- * z: toggle help
155
+ * z: toggle help
119
156
 
120
157
  Real World Usage
121
158
  ====================
@@ -134,6 +171,18 @@ So far, ShowOff has been used in the following presentations:
134
171
  * LRUG's February meeting - Showing Off with Ruby - Joel Chippindale
135
172
  http://github.com/mocoso/showing-off-with-ruby
136
173
 
174
+ * PyCon 2010 - Hg and Git; Can't we all just get along? - Scott Chacon
175
+ http://github.com/schacon/pycon-hg-git
176
+
177
+ * PdxJs Tech Talk - Asynchronous Coding For My Tiny Ruby Brain - Rick Olson
178
+ http://github.com/technoweenie/pdxjs-twitter-node
179
+
180
+ * RORO Perth Talk - Rails 3; A Brief Introduction — Darcy Laycock
181
+ http://github.com/Sutto/roro-perth-rails-3
182
+
183
+ * PDXRB Tech Talk - Here's Sinatra - Jesse Cooke
184
+ http://github.com/jc00ke/pdxrb_sinatra
185
+
137
186
  If you use it for something, please let me know so I can add it.
138
187
 
139
188
  Future Plans
data/lib/showoff.rb CHANGED
@@ -3,13 +3,7 @@ require 'sinatra/base'
3
3
  require 'json'
4
4
  require 'nokogiri'
5
5
  require 'showoff_utils'
6
-
7
- begin
8
- require 'prawn'
9
- require 'princely'
10
- rescue LoadError
11
- puts 'pdf generation disabled - install prawn'
12
- end
6
+ require 'princely'
13
7
 
14
8
  begin
15
9
  require 'rdiscount'
@@ -52,7 +46,7 @@ class ShowOff < Sinatra::Application
52
46
  Dir.glob("#{options.pres_dir}/*.js").map { |path| File.basename(path) }
53
47
  end
54
48
 
55
- def process_markdown(name, content, wrap = false)
49
+ def process_markdown(name, content)
56
50
  slides = content.split(/^!SLIDE/)
57
51
  slides.delete('')
58
52
  final = ''
@@ -61,21 +55,30 @@ class ShowOff < Sinatra::Application
61
55
  end
62
56
  slides.each do |slide|
63
57
  md = ''
58
+ # extract content classes
64
59
  lines = slide.split("\n")
65
- classes = lines.shift
60
+ content_classes = lines.shift.split
66
61
  slide = lines.join("\n")
67
- md += '<div class="' + wrap + '">' if wrap
62
+ # add content class too
63
+ content_classes.unshift "content"
64
+ # extract transition, defaulting to none
65
+ transition = 'none'
66
+ content_classes.delete_if { |x| x =~ /^transition=(.+)/ && transition = $1 }
67
+ puts "classes: #{content_classes.inspect}"
68
+ puts "transition: #{transition}"
69
+ # create html
70
+ md += "<div class=\"slide\" data-transition=\"#{transition}\">"
68
71
  if seq
69
- md += "<div class=\"slide #{classes}\" ref=\"#{name}/#{seq.to_s}\">\n"
72
+ md += "<div class=\"#{content_classes.join(' ')}\" ref=\"#{name}/#{seq.to_s}\">\n"
70
73
  seq += 1
71
74
  else
72
- md += "<div class=\"slide #{classes}\" ref=\"#{name}\">\n"
75
+ md += "<div class=\"#{content_classes.join(' ')}\" ref=\"#{name}\">\n"
73
76
  end
74
77
  sl = Markdown.new(slide).to_html
75
78
  sl = update_image_paths(name, sl)
76
79
  md += sl
77
80
  md += "</div>\n"
78
- md += "</div>\n" if wrap
81
+ md += "</div>\n"
79
82
  final += update_commandline_code(md)
80
83
  end
81
84
  final
@@ -124,7 +127,7 @@ class ShowOff < Sinatra::Application
124
127
  html.root.to_s
125
128
  end
126
129
 
127
- def get_slides_html(wrap = false)
130
+ def get_slides_html
128
131
  index = File.join(options.pres_dir, 'showoff.json')
129
132
  files = []
130
133
  if File.exists?(index)
@@ -138,7 +141,7 @@ class ShowOff < Sinatra::Application
138
141
  data = ''
139
142
  files.each do |f|
140
143
  fname = f.gsub(options.pres_dir + '/', '').gsub('.md', '')
141
- data += process_markdown(fname, File.read(f), wrap)
144
+ data += process_markdown(fname, File.read(f))
142
145
  end
143
146
  end
144
147
  data
@@ -189,12 +192,12 @@ class ShowOff < Sinatra::Application
189
192
  end
190
193
 
191
194
  get '/onepage' do
192
- @slides = get_slides_html('preso')
195
+ @slides = get_slides_html
193
196
  erb :onepage
194
197
  end
195
198
 
196
199
  get '/pdf' do
197
- @slides = get_slides_html('preso')
200
+ @slides = get_slides_html
198
201
  @no_js = true
199
202
  html = erb :onepage
200
203
  p = Princely.new
@@ -1,4 +1,4 @@
1
- .preso {
1
+ .slide {
2
2
  margin: 10px;
3
3
  padding: 0;
4
4
  width: 1020px;
data/public/css/pdf.css CHANGED
@@ -1,4 +1,4 @@
1
- .preso {
1
+ .slide {
2
2
  margin: 0;
3
3
  padding: 0;
4
4
  width: 100%;
@@ -0,0 +1,53 @@
1
+ /* http://meyerweb.com/eric/tools/css/reset/ */
2
+ /* v1.0 | 20080212 */
3
+
4
+ html, body, div, span, applet, object, iframe,
5
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
6
+ a, abbr, acronym, address, big, cite, code,
7
+ del, dfn, em, font, img, ins, kbd, q, s, samp,
8
+ small, strike, strong, sub, sup, tt, var,
9
+ b, u, i, center,
10
+ dl, dt, dd, ol, ul, li,
11
+ fieldset, form, label, legend,
12
+ table, caption, tbody, tfoot, thead, tr, th, td {
13
+ margin: 0;
14
+ padding: 0;
15
+ border: 0;
16
+ outline: 0;
17
+ font-size: 100%;
18
+ vertical-align: baseline;
19
+ background: transparent;
20
+ }
21
+ body {
22
+ line-height: 1;
23
+ }
24
+ ol, ul {
25
+ list-style: none;
26
+ }
27
+ blockquote, q {
28
+ quotes: none;
29
+ }
30
+ blockquote:before, blockquote:after,
31
+ q:before, q:after {
32
+ content: '';
33
+ content: none;
34
+ }
35
+
36
+ /* remember to define focus styles! */
37
+ :focus {
38
+ outline: 0;
39
+ }
40
+
41
+ /* remember to highlight inserts somehow! */
42
+ ins {
43
+ text-decoration: none;
44
+ }
45
+ del {
46
+ text-decoration: line-through;
47
+ }
48
+
49
+ /* tables still need 'cellspacing="0"' in the markup */
50
+ table {
51
+ border-collapse: collapse;
52
+ border-spacing: 0;
53
+ }
@@ -1,33 +1,25 @@
1
1
  body {
2
2
  font-family: "Gill Sans", Helvetica, Arial, sans-serif;
3
- padding: 0;
4
- margin: 0;
5
- border: 0;
6
3
  }
7
4
 
8
- #preso {
9
- margin: 0;
10
- padding: 0;
5
+ #preso, .slide {
6
+ background: #fff;
11
7
  width: 1020px;
12
8
  height: 740px;
13
- margin-left:auto;
9
+ margin-left:auto;
14
10
  margin-right:auto;
15
11
  overflow:hidden;
16
12
  }
17
- #footer {
13
+
14
+ #footer {
18
15
  background: #eee;
19
- margin: 0;
20
16
  padding: 2px;
21
17
  width: 1010px;
22
18
  height: 20px;
23
- margin-left:auto;
19
+ margin-left:auto;
24
20
  margin-right:auto;
25
21
  }
26
22
 
27
- .slide {
28
- border: 1px solid #fff;
29
- }
30
-
31
23
  .center img {
32
24
  display:block;
33
25
  margin-left:auto;
@@ -35,13 +27,7 @@ body {
35
27
  }
36
28
 
37
29
  .bullets ul {
38
- display: block;
39
- height: 600px;
40
30
  font-size: 3em;
41
- list-style: none;
42
- margin-left: 0;
43
- padding-left: 1em;
44
- text-indent: -1em;
45
31
  }
46
32
  .bullets ul li {
47
33
  text-align: center;
@@ -49,13 +35,7 @@ body {
49
35
  }
50
36
 
51
37
  .smbullets ul {
52
- display: block;
53
- height: 600px;
54
38
  font-size: 2em;
55
- list-style: none;
56
- margin-left: 0;
57
- padding-left: 1em;
58
- text-indent: -1em;
59
39
  }
60
40
  .smbullets ul li {
61
41
  text-align: center;
@@ -102,9 +82,14 @@ h1 { font-size: 5em; font-weight: normal; text-align: center;}
102
82
  h2 { font-size: 3em; font-weight: normal; text-align: center; }
103
83
  h3 { font-size: 2em; font-weight: normal; text-align: center; }
104
84
 
85
+ h1, h2, h3 {
86
+ margin: 0.5em 0;
87
+ }
88
+
105
89
  pre { margin-left: 40px; font-size: 2.8em; }
106
90
 
107
91
  .hidden { position:absolute; top:0; left:-9999px; width:1px; height:1px; overflow:hidden; }
92
+ .offscreen { position:absolute; top:0; left:-9999px; overflow:hidden; }
108
93
  #debugInfo { margin-left: 30px; }
109
94
 
110
95
  #help {
@@ -112,6 +97,7 @@ pre { margin-left: 40px; font-size: 2.8em; }
112
97
  position: absolute;
113
98
  right: 80px;
114
99
  display: none;
100
+ z-index: 2147483647; //max, see http://www.puidokas.com/max-z-index/
115
101
  }
116
102
  #help table tr td.key {
117
103
  text-align: right;
@@ -120,6 +106,10 @@ pre { margin-left: 40px; font-size: 2.8em; }
120
106
  font-weight: bold;
121
107
  }
122
108
 
109
+ .fg-menu-container {
110
+ z-index: 2147483647; //max, see http://www.puidokas.com/max-z-index/
111
+ }
112
+
123
113
  .fg-button { clear:left; margin:0 4px 40px 20px; padding: .4em 1em; text-decoration:none !important; cursor:pointer; position: relative; text-align: center; zoom: 1; }
124
114
  .fg-button .ui-icon { position: absolute; top: 50%; margin-top: -8px; left: 50%; margin-left: -8px; }
125
115
  a.fg-button { float:left; }
@@ -190,7 +180,7 @@ a.fg-button { float:left; }
190
180
  .code .vi { color: #008080 } /* Name.Variable.Instance */
191
181
  .code .il { color: #009999 } /* Literal.Number.Integer.Long */
192
182
 
193
- .results {
183
+ .results {
194
184
  background-color:#002200;
195
185
  color:#00AA00;
196
186
  font-size:2em;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Plugin which is applied on a list of img objects and calls
3
+ * the specified callback function, only when all of them are loaded (or errored).
4
+ * @author: H. Yankov (hristo.yankov at gmail dot com)
5
+ * @version: 1.0.0 (Feb/22/2010)
6
+ * http://yankov.us
7
+ */
8
+
9
+ (function($) {
10
+ $.fn.batchImageLoad = function(options) {
11
+ var images = $(this);
12
+ var originalTotalImagesCount = images.size();
13
+ var totalImagesCount = originalTotalImagesCount;
14
+ var elementsLoaded = 0;
15
+
16
+ // Init
17
+ $.fn.batchImageLoad.defaults = {
18
+ loadingCompleteCallback: null,
19
+ imageLoadedCallback: null
20
+ }
21
+ var opts = $.extend({}, $.fn.batchImageLoad.defaults, options);
22
+
23
+ // Start
24
+ images.each(function() {
25
+ // The image has already been loaded (cached)
26
+ if ($(this)[0].complete) {
27
+ totalImagesCount--;
28
+ if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
29
+ // The image is loading, so attach the listener
30
+ } else {
31
+ $(this).load(function() {
32
+ elementsLoaded++;
33
+
34
+ if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
35
+
36
+ // An image has been loaded
37
+ if (elementsLoaded >= totalImagesCount)
38
+ if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
39
+ });
40
+ $(this).error(function() {
41
+ elementsLoaded++;
42
+
43
+ if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
44
+
45
+ // The image has errored
46
+ if (elementsLoaded >= totalImagesCount)
47
+ if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
48
+ });
49
+ }
50
+ });
51
+
52
+ // There are no unloaded images
53
+ if (totalImagesCount <= 0)
54
+ if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
55
+ };
56
+ })(jQuery);