Update comments and README for scaling changes
[deck.js.git] / extensions / scale / deck.scale.js
blobca897ffd89ed1ed7c58d9a631797759c7932a530
1 /*!
2 Deck JS - deck.scale
3 Copyright (c) 2011-2012 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 */
9 /*
10 This module adds automatic scaling to the deck.  Slides are scaled down
11 using CSS transforms to fit within the deck container. If the container is
12 big enough to hold the slides without scaling, no scaling occurs. The user
13 can disable and enable scaling with a keyboard shortcut.
15 Note: CSS transforms may make Flash videos render incorrectly.  Presenters
16 that need to use video may want to disable scaling to play them.  HTML5 video
17 works fine.
19 (function($, deck, window, undefined) {
20         var $d = $(document),
21         $w = $(window),
22         baseHeight, // Value to scale against
23         timer, // Timeout id for debouncing
24         rootSlides,
26         /*
27         Internal function to do all the dirty work of scaling the slides.
28         */
29         scaleDeck = function() {
30                 var opts = $[deck]('getOptions'),
31                 obh = opts.baseHeight,
32                 $container = $[deck]('getContainer'),
33                 baseHeight = obh ? obh : $container.height();
35                 // Scale each slide down if necessary (but don't scale up)
36                 $.each(rootSlides, function(i, $slide) {
37                         var slideHeight = $slide.innerHeight(),
38                         $scaler = $slide.find('.' + opts.classes.scaleSlideWrapper),
39                         scale = $container.hasClass(opts.classes.scale) ?
40                                 baseHeight / slideHeight :
41                                 1;
42                         
43                         $.each('Webkit Moz O ms Khtml'.split(' '), function(i, prefix) {
44                                 if (scale === 1) {
45                                         $scaler.css(prefix + 'Transform', '');
46                                 }
47                                 else {
48                                         $scaler.css(prefix + 'Transform', 'scale(' + scale + ')');
49                                 }
50                         });
51                 });
52         }
54         /*
55         Extends defaults/options.
57         options.classes.scale
58                 This class is added to the deck container when scaling is enabled.
59                 It is enabled by default when the module is included.
60         
61         options.classes.scaleSlideWrapper
62                 Scaling is done using a wrapper around the contents of each slide. This
63                 class is applied to that wrapper.
65         options.keys.scale
66                 The numeric keycode used to toggle enabling and disabling scaling.
68         options.baseHeight
69                 When baseheight is falsy, as it is by default, the deck is scaled
70                 in proportion to the height of the deck container.  You may instead specify
71                 a height and the deck will be scaled against this height regardless
72                 of the container height.
74         options.scaleDebounce
75                 Scaling on the browser resize event is debounced. This number is the
76                 threshold in milliseconds. You can learn more about debouncing here:
77                 http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
79         */
80         $.extend(true, $[deck].defaults, {
81                 classes: {
82                         scale: 'deck-scale',
83                         scaleSlideWrapper: 'deck-slide-scaler'
84                 },
86                 keys: {
87                         scale: 83 // s
88                 },
90                 baseHeight: null,
91                 scaleDebounce: 200
92         });
94         /*
95         jQuery.deck('disableScale')
97         Disables scaling and removes the scale class from the deck container.
98         */
99         $[deck]('extend', 'disableScale', function() {
100                 $[deck]('getContainer').removeClass($[deck]('getOptions').classes.scale);
101                 scaleDeck();
102         });
104         /*
105         jQuery.deck('enableScale')
107         Enables scaling and adds the scale class to the deck container.
108         */
109         $[deck]('extend', 'enableScale', function() {
110                 $[deck]('getContainer').addClass($[deck]('getOptions').classes.scale);
111                 scaleDeck();
112         });
114         /*
115         jQuery.deck('toggleScale')
117         Toggles between enabling and disabling scaling.
118         */
119         $[deck]('extend', 'toggleScale', function() {
120                 var $c = $[deck]('getContainer');
121                 $[deck]($c.hasClass($[deck]('getOptions').classes.scale) ?
122                         'disableScale' : 'enableScale');
123         });
125         $d.bind('deck.init', function() {
126                 var opts = $[deck]('getOptions'),
127                 slideTest = $.map([
128                         opts.classes.before,
129                         opts.classes.previous,
130                         opts.classes.current,
131                         opts.classes.next,
132                         opts.classes.after
133                 ], function(el, i) {
134                         return '.' + el;
135                 }).join(', ');
136                 
137                 // Build top level slides array
138                 rootSlides = [];
139                 $.each($[deck]('getSlides'), function(i, $el) {
140                         if (!$el.parentsUntil(opts.selectors.container, slideTest).length) {
141                                 rootSlides.push($el);
142                         }
143                 });
144                 
145                 // Use a wrapper on each slide to handle content scaling
146                 $.each(rootSlides, function(i, $slide) {
147                         $slide.children().wrapAll('<div class="' + opts.classes.scaleSlideWrapper + '"/>');
148                 });
150                 // Debounce the resize scaling
151                 $w.unbind('resize.deckscale').bind('resize.deckscale', function() {
152                         window.clearTimeout(timer);
153                         timer = window.setTimeout(scaleDeck, opts.scaleDebounce);
154                 })
155                 // Scale once on load, in case images or something change layout
156                 .unbind('load.deckscale').bind('load.deckscale', scaleDeck);
158                 // Bind key events
159                 $d.unbind('keydown.deckscale').bind('keydown.deckscale', function(e) {
160                         if (e.which === opts.keys.scale || $.inArray(e.which, opts.keys.scale) > -1) {
161                                 $[deck]('toggleScale');
162                                 e.preventDefault();
163                         }
164                 });
166                 // Enable scale on init
167                 $[deck]('enableScale');
168         });
169 })(jQuery, 'deck', this);