zlide 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +47 -0
  5. data/Rakefile +8 -0
  6. data/bin/zlide +9 -0
  7. data/lib/zlide.rb +9 -0
  8. data/lib/zlide/cli/base.rb +40 -0
  9. data/lib/zlide/deck.rb +56 -0
  10. data/lib/zlide/layouts/deckjs.haml +44 -0
  11. data/lib/zlide/redcarpet/renderers.rb +5 -0
  12. data/lib/zlide/redcarpet/renderers/html.rb +35 -0
  13. data/lib/zlide/redcarpet/renderers/mock.rb +31 -0
  14. data/lib/zlide/redcarpet/renderers/pdf.rb +214 -0
  15. data/lib/zlide/server/base.rb +45 -0
  16. data/lib/zlide/templates/README.md.tt +5 -0
  17. data/lib/zlide/templates/config/deck.yml.tt +1 -0
  18. data/lib/zlide/templates/stylesheets/deck-theme.css +214 -0
  19. data/lib/zlide/templates/stylesheets/highlight-theme.css +127 -0
  20. data/lib/zlide/templates/stylesheets/slides.css +10 -0
  21. data/lib/zlide/version.rb +3 -0
  22. data/spec/spec_helper.rb +3 -0
  23. data/spec/zlide/deck_spec.rb +32 -0
  24. data/spec/zlide/server/base_spec.rb +23 -0
  25. data/vendor/javascripts/deck.js +1 -0
  26. data/vendor/javascripts/deck/deck.core.js +498 -0
  27. data/vendor/javascripts/deck/deck.edit.js +33 -0
  28. data/vendor/javascripts/deck/deck.goto.js +170 -0
  29. data/vendor/javascripts/deck/deck.hash.js +142 -0
  30. data/vendor/javascripts/deck/deck.menu.js +187 -0
  31. data/vendor/javascripts/deck/deck.navigation.js +92 -0
  32. data/vendor/javascripts/deck/deck.scale.js +170 -0
  33. data/vendor/javascripts/deck/deck.status.js +95 -0
  34. data/vendor/javascripts/highlight.js +1 -0
  35. data/vendor/javascripts/jquery-1.7.2.min.js +4 -0
  36. data/vendor/javascripts/modernizr.custom.js +4 -0
  37. data/vendor/stylesheets/deck.css +4 -0
  38. data/vendor/stylesheets/deck/deck.core.css +407 -0
  39. data/vendor/stylesheets/deck/deck.goto.css +41 -0
  40. data/vendor/stylesheets/deck/deck.hash.css +13 -0
  41. data/vendor/stylesheets/deck/deck.menu.css +47 -0
  42. data/vendor/stylesheets/deck/deck.navigation.css +43 -0
  43. data/vendor/stylesheets/deck/deck.scale.css +28 -0
  44. data/vendor/stylesheets/deck/deck.status.css +18 -0
  45. data/vendor/stylesheets/deck/transition/fade.css +43 -0
  46. data/vendor/stylesheets/deck/transition/fade.scss +69 -0
  47. data/vendor/stylesheets/deck/transition/horizontal-slide.css +76 -0
  48. data/vendor/stylesheets/deck/transition/horizontal-slide.scss +90 -0
  49. data/vendor/stylesheets/deck/transition/vertical-slide.css +94 -0
  50. data/vendor/stylesheets/deck/transition/vertical-slide.scss +112 -0
  51. data/vendor/stylesheets/test.css +3 -0
  52. data/zlide.gemspec +27 -0
  53. metadata +229 -0
@@ -0,0 +1,33 @@
1
+ (function($, deck, undefined) {
2
+
3
+ var $d = $(document),
4
+
5
+ loadSlide = function() {
6
+ var currentSlide = $['deck']('getSlide');
7
+ var index = currentSlide.attr('id').replace(/slide-/, '')
8
+ $.get('/slide/' + index, function(data) {
9
+ currentSlide.html('<textarea rows="10" cols="80">' + data + '</textarea>');
10
+ var button = $('<button>Save</button>');
11
+ currentSlide.append(button);
12
+ button.click(saveSlide);
13
+ });
14
+ },
15
+
16
+ saveSlide = function() {
17
+ var currentSlide = $['deck']('getSlide');
18
+ var index = currentSlide.attr('id').replace(/slide-/, '')
19
+ $.post('/slide/' + index, {'slide': currentSlide.find('textarea').val()}, function() {
20
+ window.location.reload();
21
+ });
22
+ };
23
+
24
+ $d.bind('deck.init', function() {
25
+ $d.unbind('keydown.edit').bind('keydown.edit', function(e) {
26
+ if (e.which == 69) {
27
+ e.preventDefault();
28
+ loadSlide();
29
+ }
30
+ });
31
+ });
32
+
33
+ })(jQuery, 'deck');
@@ -0,0 +1,170 @@
1
+ /*!
2
+ Deck JS - deck.goto
3
+ Copyright (c) 2011 Caleb Troughton
4
+ Dual licensed under the MIT license and GPL license.
5
+ https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
6
+ https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
7
+ */
8
+
9
+ /*
10
+ This module adds the necessary methods and key bindings to show and hide a form
11
+ for jumping to any slide number/id in the deck (and processes that form
12
+ accordingly). The form-showing state is indicated by the presence of a class on
13
+ the deck container.
14
+ */
15
+ (function($, deck, undefined) {
16
+ var $d = $(document);
17
+
18
+ /*
19
+ Extends defaults/options.
20
+
21
+ options.classes.goto
22
+ This class is added to the deck container when showing the Go To Slide
23
+ form.
24
+
25
+ options.selectors.gotoDatalist
26
+ The element that matches this selector is the datalist element that will
27
+ be populated with options for each of the slide ids. In browsers that
28
+ support the datalist element, this provides a drop list of slide ids to
29
+ aid the user in selecting a slide.
30
+
31
+ options.selectors.gotoForm
32
+ The element that matches this selector is the form that is submitted
33
+ when a user hits enter after typing a slide number/id in the gotoInput
34
+ element.
35
+
36
+ options.selectors.gotoInput
37
+ The element that matches this selector is the text input field for
38
+ entering a slide number/id in the Go To Slide form.
39
+
40
+ options.keys.goto
41
+ The numeric keycode used to show the Go To Slide form.
42
+
43
+ options.countNested
44
+ If false, only top level slides will be counted when entering a
45
+ slide number.
46
+ */
47
+ $.extend(true, $[deck].defaults, {
48
+ classes: {
49
+ goto: 'deck-goto'
50
+ },
51
+
52
+ selectors: {
53
+ gotoDatalist: '#goto-datalist',
54
+ gotoForm: '.goto-form',
55
+ gotoInput: '#goto-slide'
56
+ },
57
+
58
+ keys: {
59
+ goto: 71 // g
60
+ },
61
+
62
+ countNested: true
63
+ });
64
+
65
+ /*
66
+ jQuery.deck('showGoTo')
67
+
68
+ Shows the Go To Slide form by adding the class specified by the goto class
69
+ option to the deck container.
70
+ */
71
+ $[deck]('extend', 'showGoTo', function() {
72
+ $[deck]('getContainer').addClass($[deck]('getOptions').classes.goto);
73
+ $($[deck]('getOptions').selectors.gotoInput).focus();
74
+ });
75
+
76
+ /*
77
+ jQuery.deck('hideGoTo')
78
+
79
+ Hides the Go To Slide form by removing the class specified by the goto class
80
+ option from the deck container.
81
+ */
82
+ $[deck]('extend', 'hideGoTo', function() {
83
+ $($[deck]('getOptions').selectors.gotoInput).blur();
84
+ $[deck]('getContainer').removeClass($[deck]('getOptions').classes.goto);
85
+ });
86
+
87
+ /*
88
+ jQuery.deck('toggleGoTo')
89
+
90
+ Toggles between showing and hiding the Go To Slide form.
91
+ */
92
+ $[deck]('extend', 'toggleGoTo', function() {
93
+ $[deck]($[deck]('getContainer').hasClass($[deck]('getOptions').classes.goto) ? 'hideGoTo' : 'showGoTo');
94
+ });
95
+
96
+ $d.bind('deck.init', function() {
97
+ var opts = $[deck]('getOptions'),
98
+ $datalist = $(opts.selectors.gotoDatalist),
99
+ slideTest = $.map([
100
+ opts.classes.before,
101
+ opts.classes.previous,
102
+ opts.classes.current,
103
+ opts.classes.next,
104
+ opts.classes.after
105
+ ], function(el, i) {
106
+ return '.' + el;
107
+ }).join(', '),
108
+ rootCounter = 1;
109
+
110
+ // Bind key events
111
+ $d.unbind('keydown.deckgoto').bind('keydown.deckgoto', function(e) {
112
+ var key = $[deck]('getOptions').keys.goto;
113
+
114
+ if (e.which === key || $.inArray(e.which, key) > -1) {
115
+ e.preventDefault();
116
+ $[deck]('toggleGoTo');
117
+ }
118
+ });
119
+
120
+ /* Populate datalist and work out countNested*/
121
+ $.each($[deck]('getSlides'), function(i, $slide) {
122
+ var id = $slide.attr('id'),
123
+ $parentSlides = $slide.parentsUntil(opts.selectors.container, slideTest);
124
+
125
+ if (id) {
126
+ $datalist.append('<option value="' + id + '">');
127
+ }
128
+
129
+ if ($parentSlides.length) {
130
+ $slide.removeData('rootIndex');
131
+ }
132
+ else if (!opts.countNested) {
133
+ $slide.data('rootIndex', rootCounter);
134
+ ++rootCounter;
135
+ }
136
+ });
137
+
138
+ // Process form submittal, go to the slide entered
139
+ $(opts.selectors.gotoForm)
140
+ .unbind('submit.deckgoto')
141
+ .bind('submit.deckgoto', function(e) {
142
+ var $field = $($[deck]('getOptions').selectors.gotoInput),
143
+ ndx = parseInt($field.val(), 10);
144
+
145
+ if (!$[deck]('getOptions').countNested) {
146
+ if (ndx >= rootCounter) return false;
147
+ $.each($[deck]('getSlides'), function(i, $slide) {
148
+ if ($slide.data('rootIndex') === ndx) {
149
+ ndx = i + 1;
150
+ return false;
151
+ }
152
+ });
153
+ }
154
+
155
+ $[deck]('go', isNaN(ndx) ? $field.val() : ndx - 1);
156
+ $[deck]('hideGoTo');
157
+ $field.val('');
158
+
159
+ e.preventDefault();
160
+ });
161
+
162
+ // Dont let keys in the input trigger deck actions
163
+ $(opts.selectors.gotoInput)
164
+ .unbind('keydown.deckgoto')
165
+ .bind('keydown.deckgoto', function(e) {
166
+ e.stopPropagation();
167
+ });
168
+ });
169
+ })(jQuery, 'deck');
170
+
@@ -0,0 +1,142 @@
1
+ /*!
2
+ Deck JS - deck.hash
3
+ Copyright (c) 2011 Caleb Troughton
4
+ Dual licensed under the MIT license and GPL license.
5
+ https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
6
+ https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
7
+ */
8
+
9
+ /*
10
+ This module adds deep linking to individual slides, enables internal links
11
+ to slides within decks, and updates the address bar with the hash as the user
12
+ moves through the deck. A permalink anchor is also updated. Standard themes
13
+ hide this link in browsers that support the History API, and show it for
14
+ those that do not. Slides that do not have an id are assigned one according to
15
+ the hashPrefix option. In addition to the on-slide container state class
16
+ kept by core, this module adds an on-slide state class that uses the id of each
17
+ slide.
18
+ */
19
+ (function ($, deck, window, undefined) {
20
+ var $d = $(document),
21
+ $window = $(window),
22
+
23
+ /* Collection of internal fragment links in the deck */
24
+ $internals,
25
+
26
+ /*
27
+ Internal only function. Given a string, extracts the id from the hash,
28
+ matches it to the appropriate slide, and navigates there.
29
+ */
30
+ goByHash = function(str) {
31
+ var id = str.substr(str.indexOf("#") + 1),
32
+ slides = $[deck]('getSlides');
33
+
34
+ $.each(slides, function(i, $el) {
35
+ if ($el.attr('id') === id) {
36
+ $[deck]('go', i);
37
+ return false;
38
+ }
39
+ });
40
+
41
+ // If we don't set these to 0 the container scrolls due to hashchange
42
+ $[deck]('getContainer').scrollLeft(0).scrollTop(0);
43
+ };
44
+
45
+ /*
46
+ Extends defaults/options.
47
+
48
+ options.selectors.hashLink
49
+ The element matching this selector has its href attribute updated to
50
+ the hash of the current slide as the user navigates through the deck.
51
+
52
+ options.hashPrefix
53
+ Every slide that does not have an id is assigned one at initialization.
54
+ Assigned ids take the form of hashPrefix + slideIndex, e.g., slide-0,
55
+ slide-12, etc.
56
+
57
+ options.preventFragmentScroll
58
+ When deep linking to a hash of a nested slide, this scrolls the deck
59
+ container to the top, undoing the natural browser behavior of scrolling
60
+ to the document fragment on load.
61
+ */
62
+ $.extend(true, $[deck].defaults, {
63
+ selectors: {
64
+ hashLink: '.deck-permalink'
65
+ },
66
+
67
+ hashPrefix: 'slide-',
68
+ preventFragmentScroll: true
69
+ });
70
+
71
+
72
+ $d.bind('deck.init', function() {
73
+ var opts = $[deck]('getOptions');
74
+ $internals = $(),
75
+ slides = $[deck]('getSlides');
76
+
77
+ $.each(slides, function(i, $el) {
78
+ var hash;
79
+
80
+ /* Hand out ids to the unfortunate slides born without them */
81
+ if (!$el.attr('id') || $el.data('deckAssignedId') === $el.attr('id')) {
82
+ $el.attr('id', opts.hashPrefix + i);
83
+ $el.data('deckAssignedId', opts.hashPrefix + i);
84
+ }
85
+
86
+ hash ='#' + $el.attr('id');
87
+
88
+ /* Deep link to slides on init */
89
+ if (hash === window.location.hash) {
90
+ $[deck]('go', i);
91
+ }
92
+
93
+ /* Add internal links to this slide */
94
+ $internals = $internals.add('a[href="' + hash + '"]');
95
+ });
96
+
97
+ if (!Modernizr.hashchange) {
98
+ /* Set up internal links using click for the poor browsers
99
+ without a hashchange event. */
100
+ $internals.unbind('click.deckhash').bind('click.deckhash', function(e) {
101
+ goByHash($(this).attr('href'));
102
+ });
103
+ }
104
+
105
+ /* Set up first id container state class */
106
+ if (slides.length) {
107
+ $[deck]('getContainer').addClass(opts.classes.onPrefix + $[deck]('getSlide').attr('id'));
108
+ };
109
+ })
110
+ /* Update permalink, address bar, and state class on a slide change */
111
+ .bind('deck.change', function(e, from, to) {
112
+ var hash = '#' + $[deck]('getSlide', to).attr('id'),
113
+ hashPath = window.location.href.replace(/#.*/, '') + hash,
114
+ opts = $[deck]('getOptions'),
115
+ osp = opts.classes.onPrefix,
116
+ $c = $[deck]('getContainer');
117
+
118
+ $c.removeClass(osp + $[deck]('getSlide', from).attr('id'));
119
+ $c.addClass(osp + $[deck]('getSlide', to).attr('id'));
120
+
121
+ $(opts.selectors.hashLink).attr('href', hashPath);
122
+ if (Modernizr.history) {
123
+ window.history.replaceState({}, "", hashPath);
124
+ }
125
+ });
126
+
127
+ /* Deals with internal links in modern browsers */
128
+ $window.bind('hashchange.deckhash', function(e) {
129
+ if (e.originalEvent && e.originalEvent.newURL) {
130
+ goByHash(e.originalEvent.newURL);
131
+ }
132
+ else {
133
+ goByHash(window.location.hash);
134
+ }
135
+ })
136
+ /* Prevent scrolling on deep links */
137
+ .bind('load', function() {
138
+ if ($[deck]('getOptions').preventFragmentScroll) {
139
+ $[deck]('getContainer').scrollLeft(0).scrollTop(0);
140
+ }
141
+ });
142
+ })(jQuery, 'deck', this);
@@ -0,0 +1,187 @@
1
+ /*!
2
+ Deck JS - deck.menu
3
+ Copyright (c) 2011 Caleb Troughton
4
+ Dual licensed under the MIT license and GPL license.
5
+ https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
6
+ https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
7
+ */
8
+
9
+ /*
10
+ This module adds the methods and key binding to show and hide a menu of all
11
+ slides in the deck. The deck menu state is indicated by the presence of a class
12
+ on the deck container.
13
+ */
14
+ (function($, deck, undefined) {
15
+ var $d = $(document),
16
+ rootSlides; // Array of top level slides
17
+
18
+ /*
19
+ Extends defaults/options.
20
+
21
+ options.classes.menu
22
+ This class is added to the deck container when showing the slide menu.
23
+
24
+ options.keys.menu
25
+ The numeric keycode used to toggle between showing and hiding the slide
26
+ menu.
27
+
28
+ options.touch.doubletapWindow
29
+ Two consecutive touch events within this number of milliseconds will
30
+ be considered a double tap, and will toggle the menu on touch devices.
31
+ */
32
+ $.extend(true, $[deck].defaults, {
33
+ classes: {
34
+ menu: 'deck-menu'
35
+ },
36
+
37
+ keys: {
38
+ menu: 77 // m
39
+ },
40
+
41
+ touch: {
42
+ doubletapWindow: 400
43
+ }
44
+ });
45
+
46
+ /*
47
+ jQuery.deck('showMenu')
48
+
49
+ Shows the slide menu by adding the class specified by the menu class option
50
+ to the deck container.
51
+ */
52
+ $[deck]('extend', 'showMenu', function() {
53
+ var $c = $[deck]('getContainer'),
54
+ opts = $[deck]('getOptions');
55
+
56
+ if ($c.hasClass(opts.classes.menu)) return;
57
+
58
+ // Hide through loading class to short-circuit transitions (perf)
59
+ $c.addClass([opts.classes.loading, opts.classes.menu].join(' '));
60
+
61
+ /* Forced to do this in JS until CSS learns second-grade math. Save old
62
+ style value for restoration when menu is hidden. */
63
+ if (Modernizr.csstransforms) {
64
+ $.each(rootSlides, function(i, $slide) {
65
+ $slide.data('oldStyle', $slide.attr('style'));
66
+ $slide.css({
67
+ 'position': 'absolute',
68
+ 'left': ((i % 4) * 25) + '%',
69
+ 'top': (Math.floor(i / 4) * 25) + '%'
70
+ });
71
+ });
72
+ }
73
+
74
+ // Need to ensure the loading class renders first, then remove
75
+ window.setTimeout(function() {
76
+ $c.removeClass(opts.classes.loading)
77
+ .scrollTop($[deck]('getSlide').offset().top);
78
+ }, 0);
79
+ });
80
+
81
+ /*
82
+ jQuery.deck('hideMenu')
83
+
84
+ Hides the slide menu by removing the class specified by the menu class
85
+ option from the deck container.
86
+ */
87
+ $[deck]('extend', 'hideMenu', function() {
88
+ var $c = $[deck]('getContainer'),
89
+ opts = $[deck]('getOptions');
90
+
91
+ if (!$c.hasClass(opts.classes.menu)) return;
92
+
93
+ $c.removeClass(opts.classes.menu);
94
+ $c.addClass(opts.classes.loading);
95
+
96
+ /* Restore old style value */
97
+ if (Modernizr.csstransforms) {
98
+ $.each(rootSlides, function(i, $slide) {
99
+ var oldStyle = $slide.data('oldStyle');
100
+
101
+ $slide.attr('style', oldStyle ? oldStyle : '');
102
+ });
103
+ }
104
+
105
+ window.setTimeout(function() {
106
+ $c.removeClass(opts.classes.loading).scrollTop(0);
107
+ }, 0);
108
+ });
109
+
110
+ /*
111
+ jQuery.deck('toggleMenu')
112
+
113
+ Toggles between showing and hiding the slide menu.
114
+ */
115
+ $[deck]('extend', 'toggleMenu', function() {
116
+ $[deck]('getContainer').hasClass($[deck]('getOptions').classes.menu) ?
117
+ $[deck]('hideMenu') : $[deck]('showMenu');
118
+ });
119
+
120
+ $d.bind('deck.init', function() {
121
+ var opts = $[deck]('getOptions'),
122
+ touchEndTime = 0,
123
+ currentSlide,
124
+ slideTest = $.map([
125
+ opts.classes.before,
126
+ opts.classes.previous,
127
+ opts.classes.current,
128
+ opts.classes.next,
129
+ opts.classes.after
130
+ ], function(el, i) {
131
+ return '.' + el;
132
+ }).join(', ');
133
+
134
+ // Build top level slides array
135
+ rootSlides = [];
136
+ $.each($[deck]('getSlides'), function(i, $el) {
137
+ if (!$el.parentsUntil(opts.selectors.container, slideTest).length) {
138
+ rootSlides.push($el);
139
+ }
140
+ });
141
+
142
+ // Bind key events
143
+ $d.unbind('keydown.deckmenu').bind('keydown.deckmenu', function(e) {
144
+ if (e.which === opts.keys.menu || $.inArray(e.which, opts.keys.menu) > -1) {
145
+ $[deck]('toggleMenu');
146
+ e.preventDefault();
147
+ }
148
+ });
149
+
150
+ // Double tap to toggle slide menu for touch devices
151
+ $[deck]('getContainer').unbind('touchstart.deckmenu').bind('touchstart.deckmenu', function(e) {
152
+ currentSlide = $[deck]('getSlide');
153
+ })
154
+ .unbind('touchend.deckmenu').bind('touchend.deckmenu', function(e) {
155
+ var now = Date.now();
156
+
157
+ // Ignore this touch event if it caused a nav change (swipe)
158
+ if (currentSlide !== $[deck]('getSlide')) return;
159
+
160
+ if (now - touchEndTime < opts.touch.doubletapWindow) {
161
+ $[deck]('toggleMenu');
162
+ e.preventDefault();
163
+ }
164
+ touchEndTime = now;
165
+ });
166
+
167
+ // Selecting slides from the menu
168
+ $.each($[deck]('getSlides'), function(i, $s) {
169
+ $s.unbind('click.deckmenu').bind('click.deckmenu', function(e) {
170
+ if (!$[deck]('getContainer').hasClass(opts.classes.menu)) return;
171
+
172
+ $[deck]('go', i);
173
+ $[deck]('hideMenu');
174
+ e.stopPropagation();
175
+ e.preventDefault();
176
+ });
177
+ });
178
+ })
179
+ .bind('deck.change', function(e, from, to) {
180
+ var container = $[deck]('getContainer');
181
+
182
+ if (container.hasClass($[deck]('getOptions').classes.menu)) {
183
+ container.scrollTop($[deck]('getSlide', to).offset().top);
184
+ }
185
+ });
186
+ })(jQuery, 'deck');
187
+