Change out old github.com pages links
[deck.js.git] / extensions / scale / deck.scale.js
blob0e21631880dfdb43d843b32dcf27834376dc2336
1 /*!
2 Deck JS - deck.scale
3 Copyright (c) 2011-2014 Caleb Troughton
4 Dual licensed under the MIT license.
5 https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
6 */
8 /*
9 This module adds automatic scaling to the deck.  Slides are scaled down
10 using CSS transforms to fit within the deck container. If the container is
11 big enough to hold the slides without scaling, no scaling occurs. The user
12 can disable and enable scaling with a keyboard shortcut.
14 Note: CSS transforms may make Flash videos render incorrectly.  Presenters
15 that need to use video may want to disable scaling to play them.  HTML5 video
16 works fine.
18 (function($, undefined) {
19   var $document = $(document);
20   var $window = $(window);
21   var baseHeight, timer, rootSlides;
23   /*
24   Internal function to do all the dirty work of scaling the slides.
25   */
26   var scaleDeck = function() {
27     var options = $.deck('getOptions');
28     var $container = $.deck('getContainer');
29     var baseHeight = options.baseHeight;
31     if (!baseHeight) {
32       baseHeight = $container.height();
33     }
35     // Scale each slide down if necessary (but don't scale up)
36     $.each(rootSlides, function(i, $slide) {
37       var slideHeight = $slide.innerHeight();
38       var $scaler = $slide.find('.' + options.classes.scaleSlideWrapper);
39       var shouldScale = $container.hasClass(options.classes.scale);
40       var scale = shouldScale ? baseHeight / slideHeight : 1;
42       if (scale === 1) {
43         $scaler.css('transform', '');
44       }
45       else {
46         $scaler.css('transform', 'scale(' + scale + ')');
47         window.setTimeout(function() {
48           $container.scrollTop(0)
49         }, 1);
50       }
51     });
52   };
54   var populateRootSlides = function() {
55     var options = $.deck('getOptions');
56     var slideTest = $.map([
57       options.classes.before,
58       options.classes.previous,
59       options.classes.current,
60       options.classes.next,
61       options.classes.after
62     ], function(el, i) {
63       return '.' + el;
64     }).join(', ');
66     rootSlides = [];
67     $.each($.deck('getSlides'), function(i, $slide) {
68       var $parentSlides = $slide.parentsUntil(
69         options.selectors.container,
70         slideTest
71       );
72       if (!$parentSlides.length) {
73         rootSlides.push($slide);
74       }
75     });
76   };
78   var wrapRootSlideContent = function() {
79     var options = $.deck('getOptions');
80     var wrap = '<div class="' + options.classes.scaleSlideWrapper + '"/>';
81     $.each(rootSlides, function(i, $slide) {
82       $slide.children().wrapAll(wrap);
83     });
84   };
86   var scaleOnResizeAndLoad = function() {
87     var options = $.deck('getOptions');
89     $window.unbind('resize.deckscale');
90     $window.bind('resize.deckscale', function() {
91       window.clearTimeout(timer);
92       timer = window.setTimeout(scaleDeck, options.scaleDebounce);
93     });
94     $.deck('enableScale');
95     $window.unbind('load.deckscale');
96     $window.bind('load.deckscale', scaleDeck);
97   };
99   var bindKeyEvents = function() {
100     var options = $.deck('getOptions');
101     $document.unbind('keydown.deckscale');
102     $document.bind('keydown.deckscale', function(event) {
103       var isKey = event.which === options.keys.scale;
104       isKey = isKey || $.inArray(event.which, options.keys.scale) > -1;
105       if (isKey) {
106         $.deck('toggleScale');
107         event.preventDefault();
108       }
109     });
110   };
112   /*
113   Extends defaults/options.
115   options.classes.scale
116     This class is added to the deck container when scaling is enabled.
117     It is enabled by default when the module is included.
119   options.classes.scaleSlideWrapper
120     Scaling is done using a wrapper around the contents of each slide. This
121     class is applied to that wrapper.
123   options.keys.scale
124     The numeric keycode used to toggle enabling and disabling scaling.
126   options.baseHeight
127     When baseHeight is falsy, as it is by default, the deck is scaled in
128     proportion to the height of the deck container. You may instead specify
129     a height as a number of px, and slides will be scaled against this
130     height regardless of the container size.
132   options.scaleDebounce
133     Scaling on the browser resize event is debounced. This number is the
134     threshold in milliseconds. You can learn more about debouncing here:
135     http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
137   */
138   $.extend(true, $.deck.defaults, {
139     classes: {
140       scale: 'deck-scale',
141       scaleSlideWrapper: 'deck-slide-scaler'
142     },
144     keys: {
145       scale: 83 // s
146     },
148     baseHeight: null,
149     scaleDebounce: 200
150   });
152   /*
153   jQuery.deck('disableScale')
155   Disables scaling and removes the scale class from the deck container.
156   */
157   $.deck('extend', 'disableScale', function() {
158     $.deck('getContainer').removeClass($.deck('getOptions').classes.scale);
159     scaleDeck();
160   });
162   /*
163   jQuery.deck('enableScale')
165   Enables scaling and adds the scale class to the deck container.
166   */
167   $.deck('extend', 'enableScale', function() {
168     $.deck('getContainer').addClass($.deck('getOptions').classes.scale);
169     scaleDeck();
170   });
172   /*
173   jQuery.deck('toggleScale')
175   Toggles between enabling and disabling scaling.
176   */
177   $.deck('extend', 'toggleScale', function() {
178     var $container = $.deck('getContainer');
179     var isScaled = $container.hasClass($.deck('getOptions').classes.scale);
180     $.deck(isScaled? 'disableScale' : 'enableScale');
181   });
183   $document.bind('deck.init', function() {
184     populateRootSlides();
185     wrapRootSlideContent();
186     scaleOnResizeAndLoad();
187     bindKeyEvents();
188   });
189 })(jQuery, 'deck', this);