├── test ├── full.html ├── full-multi.html ├── timesource.html ├── portable.html ├── vimeo.html └── jquery.min.js ├── MIT-LICENSE.txt ├── README.md ├── fathom.sample.css ├── fathom.min.js └── fathom.js /test/full.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Fathom.js - Full Screen Test 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 |
18 |
19 |

Slide 1

20 |
21 |
22 |

Slide 2

23 |
24 |
25 |

Slide 3

26 |
27 |
28 |

Slide 4

29 |
30 |
31 |

Slide 5

32 |
33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /test/full-multi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Fathom.js - Full Screen Test 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 |
20 |
21 |

Slide 1

22 |
23 |
24 |

Slide 2

25 |
26 |
27 |

Slide 3

28 |
29 |
30 |

Slide 4

31 |
32 |
33 |

Slide 5

34 |
35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /test/timesource.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Fathom.js - Full Screen Test 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 |
20 |
21 |

Slide 1

22 |
23 |
24 |

Slide 2

25 |
26 |
27 |

Slide 3

28 |
29 |
30 |

Slide 4

31 |
32 |
33 |

Slide 5

34 |
35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Mark Dalgleish 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /test/portable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Fathom.js - Portable Test 6 | 7 | 32 | 33 | 34 | 39 | 40 | 41 |
42 |
43 |
44 |

Slide 1

45 |
46 |
47 |

Slide 2

48 |
49 |
50 |

Slide 3

51 |
52 |
53 |

Slide 4

54 |
55 |
56 |

Slide 5

57 |
58 |
59 |
60 | 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > **PLEASE NOTE:** This project is no longer maintained. Instead, you should check out [Bespoke.js](https://github.com/markdalgleish/bespoke.js). 2 | 3 | # [Fathom.js](http://markdalgleish.com/projects/fathom) [![endorse](http://api.coderwall.com/markdalgleish/endorsecount.png)](http://coderwall.com/markdalgleish) 4 | 5 | ### Present JavaScript in its native environment. 6 | 7 | If you're making a presentation ***on JavaScript***, make it ***in JavaScript***. 8 | 9 | ## Usage 10 | 11 | Example HTML: 12 | 13 | ``` html 14 |
15 | 16 |
17 |

My Presentation

18 |
19 | 20 |
21 |

My Dot Points

22 | 27 |
28 | 29 |
30 | ``` 31 | 32 | --- 33 | 34 | jQuery Plugin Setup: 35 | ``` js 36 | $('#presentation').fathom(); 37 | ``` 38 | 39 | Advanced Setup: 40 | ``` js 41 | var fathom = new Fathom('#presentation'); 42 | ``` 43 | 44 | --- 45 | 46 | Full guide available at the [official Fathom.js project page](http://markdalgleish.com/projects/fathom). 47 | 48 | I've included a sample CSS file in the repo to get you started. 49 | 50 | --- 51 | 52 | Please note that Fathom.js is not trying to recreate Powerpoint or Keynote. While they're good tools, I personally find that style of interface to be inappropriate on the web. If you're wondering why feature *x* from Powerpoint is missing, this is probably why. 53 | 54 | ## How to Build 55 | 56 | The code is minified using UglifyJS using the following command: 57 | 58 | `uglifyjs -o fathom.min.js fathom.js` 59 | 60 | ## Contributing to Fathom.js 61 | 62 | If you want to contribute in a way that changes the API, please file an issue before submitting a pull request so we can dicuss how to appropriately integrate your ideas. 63 | 64 | ## Questions? 65 | 66 | Contact me on GitHub or Twitter: [@markdalgleish](http://twitter.com/markdalgleish) 67 | -------------------------------------------------------------------------------- /fathom.sample.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | 50 | input:focus { 51 | outline: 0; 52 | } 53 | 54 | #presentation { 55 | vertical-align: top; 56 | white-space: nowrap; 57 | } 58 | 59 | div.slide { 60 | -webkit-box-shadow: 0 0 50px #c0c0c0; 61 | -moz-box-shadow: 0 0 50px #c0c0c0; 62 | box-shadow: 0 0 50px #c0c0c0; 63 | -moz-border-radius: 20px; 64 | -webkit-border-radius: 20px; 65 | border-radius: 20px; 66 | -moz-background-clip: padding; 67 | -webkit-background-clip: padding-box; 68 | background-clip: padding-box; 69 | display: inline-block; 70 | height: 700px; 71 | padding: 20px; 72 | position: relative; 73 | vertical-align: top; 74 | width: 900px; 75 | } 76 | div.inactiveslide { 77 | opacity: 0.4; 78 | } 79 | div.activeslide { 80 | opacity: 1; 81 | } 82 | 83 | /* iPad */ 84 | @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) { 85 | div.inactiveslide { 86 | opacity: 1; 87 | } 88 | } 89 | 90 | /* iPhone */ 91 | @media only screen and (max-device-width: 480px) { 92 | div.inactiveslide { 93 | opacity: 1; 94 | } 95 | } -------------------------------------------------------------------------------- /test/vimeo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Fathom.js - Vimeo Video Test 8 | 9 | 18 | 19 | 20 | 34 | 35 | 36 |
37 |
38 |

AURORA

39 |
40 |
41 |

Tromsø, Norway.

42 |

Photography: Tor Even Mathisen
43 | Music: Per Wollen
44 | Vocal: Silje Beate Nilssen

45 | tittentem.no 46 |
47 |
48 |

Auroras are associated with the solar wind, a flow of ions continuously flowing outward from the Sun.

49 |
50 |
51 |

The Earth's magnetic field traps these particles, many of which travel toward the poles where they are accelerated toward Earth.

52 |
53 |
54 |

Collisions between these ions and atmospheric atoms and molecules cause energy releases in the form of auroras appearing in large circles around the poles.

55 |
56 |
57 |

Auroras are more frequent and brighter during the intense phase of the solar cycle when coronal mass ejections increase the intensity of the solar wind.

58 |
59 |
60 |

oxygen emissions

61 |

Green or brownish-red, depending on the amount of energy absorbed.

62 |
63 |
64 |

nitrogen emissions

65 |

Blue or red. Blue if the atom regains an electron after it has been ionized. Red if returning to ground state from an excited state.

66 |
67 |
68 |
The stars are putting on their glittering belts. 69 | They throw around their shoulders cloaks that flash 70 | Like a great shadow's last embellishment

71 |
72 |
73 |
The Valkyrior are warlike virgins, mounted upon horses and armed with helmets and spears. When they ride forth on their errand, their armour sheds a strange flickering light, which flashes up over the northern skies
74 |
75 |
76 |
77 | 78 | -------------------------------------------------------------------------------- /fathom.min.js: -------------------------------------------------------------------------------- 1 | (function($,window,undefined){var Fathom=function(container,options){this.container=container;this.options=options;return this.init()},$window=$(window),$document=$(document);Fathom.prototype={defaults:{portable:undefined,portableTagName:"div",portableClass:"fathom-container",displayMode:"single",slideTagName:"div",slideClass:"slide",activeClass:"activeslide",inactiveClass:"inactiveslide",margin:100,onScrollInterval:300,scrollLength:600,easing:"swing",timeline:undefined,video:undefined,onActivateSlide:undefined,onDeactivateSlide:undefined},init:function(){this.config=$.extend({},this.defaults,this.options);this.$container=$(this.container);this.$slides=this.$container.find(this.config.slideTagName+(this.config.slideClass?"."+this.config.slideClass:""));this.$firstSlide=this.$slides.filter(":first");this.$lastSlide=this.$slides.filter(":last");this.$activeSlide=this.activateSlide(this.$firstSlide);return this._detectPortable()._setStyles()._setClasses()._setMargins()._setupEvents()._setupTimeline()._setupVideo()._setupScrollHandler()},nextSlide:function(){return this.scrollToSlide(this.$activeSlide.next())},prevSlide:function(){return this.scrollToSlide(this.$activeSlide.prev())},scrollToSlide:function($elem){var self=this,$scrollingElement=this.config.portable?this.$portableContainer:$("html,body"),$container=this.config.portable?this.$portableContainer:$window,portableScrollLeft=this.config.portable?this.$portableContainer.scrollLeft():0;if($elem.length!==1){return $elem}this.isAutoScrolling=true;$scrollingElement.stop().animate({scrollLeft:$elem.position().left+portableScrollLeft-($container.width()-$elem.innerWidth())/2},self.config.scrollLength,self.config.easing,function(){self.isAutoScrolling=false});return this.activateSlide($elem)},activateSlide:function($elem){var elem=$elem.get(0),activeSlide;if(this.$activeSlide!==undefined){activeSlide=this.$activeSlide.get(0);if(activeSlide===elem){return $elem}this.$activeSlide.removeClass(this.config.activeClass).addClass(this.config.inactiveClass).trigger("deactivateslide.fathom");if(typeof this.config.onDeactivateSlide==="function"){this.config.onDeactivateSlide.call(activeSlide)}}$elem.removeClass(this.config.inactiveClass).addClass(this.config.activeClass);this.$activeSlide=$elem;$elem.trigger("activateslide.fathom");if(typeof this.config.onActivateSlide==="function"){this.config.onActivateSlide.call(elem)}return $elem},setTime:function(t){var times=this._timeline||[];for(var i=0;it){if(this.$activeSlide[0]!==times[i].slide[0]){this.scrollToSlide(times[i].slide)}break}}},_detectPortable:function(){if(this.config.portable===undefined){if(this.$container.parent().is("body")){this.config.portable=false}else{this.config.portable=true}}return this},_setupEvents:function(){var self=this;this.$container.delegate(this.config.slideTagName+"."+this.config.inactiveClass,"click",function(event){event.preventDefault();self.scrollToSlide($(this))});$document.keydown(function(event){var key=event.which;if(key===39||key===32){event.preventDefault();self.nextSlide()}else if(key===37){event.preventDefault();self.prevSlide()}});$window.resize(function(){self._setMargins()});return this},_setStyles:function(){this.$container.css("white-space","nowrap");this.$slides.css({"white-space":"normal",display:"inline-block","vertical-align":"top"});if(this.config.portable){this.$portableContainer=$("<"+this.config.portableTagName+' class="'+this.config.portableClass+'" />');this.$container.before(this.$portableContainer).appendTo(this.$portableContainer)}return this},_setClasses:function(){this.$slides.addClass(this.config.inactiveClass);this.$activeSlide.removeClass(this.config.inactiveClass).addClass(this.config.activeClass);return this},_setMargins:function(){var displayMode=this.config.displayMode,$container=this.config.portable?this.$portableContainer:$window,containerWidth=$container.width(),verticalSpacing=Math.ceil(($container.height()-this.$firstSlide.innerHeight())/2),firstSlideSpacing=Math.ceil((containerWidth-this.$firstSlide.innerWidth())/2),lastSlideSpacing=Math.ceil((containerWidth-this.$lastSlide.innerWidth())/2),peekabooWidth=Math.ceil(containerWidth/25);this.$container.css("margin-top",verticalSpacing);if(displayMode==="single"){this.$slides.css("margin-right",firstSlideSpacing-peekabooWidth)}else if(displayMode==="multi"){this.$slides.css("margin-right",this.config.margin)}this.$firstSlide.css("margin-left",firstSlideSpacing);this.$lastSlide.css("margin-right",lastSlideSpacing);if(this.config.portable){var slidesWidth=parseInt(this.$container.css("padding-left"))+parseInt(this.$container.css("padding-right"));this.$slides.each(function(){slidesWidth+=$(this).outerWidth(true)});this.$container.width(slidesWidth)}return this},_setupTimeline:function(){var slides=this.$slides;function parseTime(point){for(var m=(point.time||point).toString().match(/(((\d+):)?(\d+):)?(\d+)/),a=0,i=3;i<=5;i++){a=a*60+parseInt(m[i]||0)}return a}var currentSlide=-1;function parseSlide(point){if(point.slide==null){currentSlide++}else if($.type(point.slide)==="number"){currentSlide=point.slide}else{for(var match=slides.filter(point.slide)[0],i=0;i';return $(frameSrc).appendTo(vid.parent||"body")[0]}if(downgrade){$(loadFrame()).bind("load",function(){self._setupDefaultTimeSource()})}else{$.getScript("http://a.vimeocdn.com/js/froogaloop2.min.js?",function(){$f(loadFrame()).addEvent("ready",function(player_id){var vimeo=$f(player_id),timer=false;vimeo.addEvent("play",function(data){if(timer===false){timer=setInterval(function(){vimeo.api("getCurrentTime",function(value,player_id){self.setTime(value)})},250)}});vimeo.addEvent("pause",function(data){clearInterval(timer);timer=false});vid.autoplay&&vimeo.api("play")})})}},_setupScrollHandler:function(){var self=this,slideSelector=self.config.slideTagName+(self.config.slideClass?"."+self.config.slideClass:""),$scrollContainer=this.config.portable?this.$portableContainer:$window,isIOS=navigator.userAgent.match(/like Mac OS X/i)===null?false:true,$elem;self.scrolling=false;setInterval(function(){if(self.scrolling&&(self.isAutoScrolling===false||self.isAutoScrolling===undefined)){self.scrolling=false;if($scrollContainer.scrollLeft()===0){self.activateSlide(self.$firstSlide)}else{var offsetX=self.config.portable?$scrollContainer.position().left:0,offsetY=self.config.portable?$scrollContainer.position().top:0,midpoint={x:offsetX+$scrollContainer.width()/2+(isIOS?$window.scrollLeft():0),y:offsetY+$scrollContainer.height()/2+(isIOS?$window.scrollTop():0)};$elem=$(document.elementFromPoint(midpoint.x,midpoint.y));if($elem.is(slideSelector)){self.activateSlide($elem)}else{$elem=$elem.parents(slideSelector+":first").each(function(){self.activateSlide($(this))})}}}},self.config.onScrollInterval);$scrollContainer.scroll(function(){self.scrolling=true});return this}};$.fn.fathom=function(options){new Fathom(this,options);return this};Fathom.defaults=Fathom.prototype.defaults;Fathom.setDefaults=function(options){$.extend(Fathom.defaults,options)};window.Fathom=Fathom})(jQuery,window); -------------------------------------------------------------------------------- /fathom.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Fathom.js v1.2.5 3 | * Copyright 2012-15, Mark Dalgleish 4 | * 5 | * This content is released under the MIT License 6 | * markdalgleish.mit-license.org 7 | */ 8 | 9 | (function($, window, undefined){ 10 | var Fathom = function(container, options){ 11 | this.container = container; 12 | this.options = options; 13 | 14 | return this.init(); 15 | }, 16 | $window = $(window), 17 | $document = $(document); 18 | 19 | Fathom.prototype = { 20 | defaults: { 21 | portable: undefined, 22 | portableTagName: 'div', 23 | portableClass: 'fathom-container', 24 | displayMode: 'single', 25 | slideTagName: 'div', 26 | slideClass: 'slide', 27 | activeClass: 'activeslide', 28 | inactiveClass: 'inactiveslide', 29 | margin: 100, 30 | onScrollInterval: 300, 31 | scrollLength: 600, 32 | easing: 'swing', 33 | 34 | timeline: undefined, 35 | video: undefined, 36 | 37 | onActivateSlide: undefined, 38 | onDeactivateSlide: undefined 39 | }, 40 | 41 | init: function() { 42 | this.config = $.extend({}, this.defaults, this.options); 43 | 44 | this.$container = $(this.container); 45 | this.$slides = this.$container.find(this.config.slideTagName + 46 | (this.config.slideClass ? '.' + this.config.slideClass : '')); 47 | this.$firstSlide = this.$slides.filter(':first'); 48 | this.$lastSlide = this.$slides.filter(':last'); 49 | this.$activeSlide = this.activateSlide(this.$firstSlide); 50 | 51 | return this 52 | ._detectPortable() 53 | ._setStyles() 54 | ._setClasses() 55 | ._setMargins() 56 | ._setupEvents() 57 | ._setupTimeline() 58 | ._setupVideo() 59 | ._setupScrollHandler(); 60 | }, 61 | 62 | nextSlide: function() { 63 | return this.scrollToSlide(this.$activeSlide.next()); 64 | }, 65 | 66 | prevSlide: function() { 67 | return this.scrollToSlide(this.$activeSlide.prev()); 68 | }, 69 | 70 | scrollToSlide: function($elem) { 71 | var self = this, 72 | $scrollingElement = this.config.portable ? this.$portableContainer : $('html,body'), 73 | $container = this.config.portable ? this.$portableContainer : $window, 74 | portableScrollLeft = this.config.portable ? this.$portableContainer.scrollLeft() : 0; 75 | 76 | if ($elem.length !== 1) { 77 | return $elem; 78 | } 79 | 80 | this.isAutoScrolling = true; 81 | 82 | $scrollingElement.stop().animate({ 83 | scrollLeft: ($elem.position().left + portableScrollLeft - 84 | (($container.width() - $elem.innerWidth()) / 2)) 85 | }, self.config.scrollLength, self.config.easing, function() { 86 | self.isAutoScrolling = false; 87 | }); 88 | 89 | return this.activateSlide($elem); 90 | }, 91 | 92 | activateSlide: function($elem) { 93 | var elem = $elem.get(0), 94 | activeSlide; 95 | 96 | if (this.$activeSlide !== undefined) { 97 | activeSlide = this.$activeSlide.get(0) 98 | 99 | if (activeSlide === elem) { 100 | return $elem; 101 | } 102 | 103 | this.$activeSlide.removeClass(this.config.activeClass) 104 | .addClass(this.config.inactiveClass) 105 | .trigger('deactivateslide.fathom'); 106 | 107 | if (typeof this.config.onDeactivateSlide === 'function') { 108 | this.config.onDeactivateSlide.call(activeSlide); 109 | } 110 | } 111 | 112 | $elem.removeClass(this.config.inactiveClass).addClass(this.config.activeClass); 113 | 114 | this.$activeSlide = $elem; 115 | 116 | $elem.trigger('activateslide.fathom'); 117 | 118 | if (typeof this.config.onActivateSlide === 'function') { 119 | this.config.onActivateSlide.call(elem); 120 | } 121 | 122 | return $elem; 123 | }, 124 | 125 | setTime: function( t ) { 126 | var times = this._timeline || []; 127 | for(var i = 0; i < times.length; i++) { 128 | if(times[i].time <= t && times[i+1].time > t) { 129 | if(this.$activeSlide[0] !== times[i].slide[0]) { 130 | this.scrollToSlide( times[i].slide ); 131 | } 132 | break; 133 | } 134 | } 135 | }, 136 | 137 | _detectPortable: function() { 138 | if (this.config.portable === undefined) { 139 | if (this.$container.parent().is('body')) { 140 | this.config.portable = false; 141 | } else { 142 | this.config.portable = true; 143 | } 144 | } 145 | 146 | return this; 147 | }, 148 | 149 | _setupEvents: function() { 150 | var self = this; 151 | 152 | this.$container.delegate(this.config.slideTagName + '.' + this.config.inactiveClass, 'click', function(event) { 153 | event.preventDefault(); 154 | self.scrollToSlide($(this)); 155 | }); 156 | 157 | $document.keydown(function(event) { 158 | var key = event.which; 159 | 160 | if (key === 39 || key === 32) { 161 | event.preventDefault(); 162 | self.nextSlide(); 163 | } else if ( key === 37) { 164 | event.preventDefault(); 165 | self.prevSlide(); 166 | } 167 | }); 168 | 169 | $window.resize(function(){ 170 | self._setMargins(); 171 | }); 172 | 173 | return this; 174 | }, 175 | 176 | _setStyles: function() { 177 | this.$container.css('white-space', 'nowrap'); 178 | 179 | this.$slides.css({ 180 | 'white-space': 'normal', 181 | 'display': 'inline-block', 182 | 'vertical-align': 'top' 183 | }); 184 | 185 | if (this.config.portable) { 186 | this.$portableContainer = $('<' + this.config.portableTagName + ' class="' + this.config.portableClass + '" />'); 187 | this.$container.before(this.$portableContainer).appendTo(this.$portableContainer); 188 | } 189 | 190 | return this; 191 | }, 192 | 193 | _setClasses: function() { 194 | this.$slides.addClass(this.config.inactiveClass); 195 | 196 | this.$activeSlide 197 | .removeClass(this.config.inactiveClass) 198 | .addClass(this.config.activeClass); 199 | 200 | return this; 201 | }, 202 | 203 | _setMargins: function() { 204 | var displayMode = this.config.displayMode, 205 | $container = this.config.portable ? this.$portableContainer : $window, 206 | containerWidth = $container.width(), 207 | verticalSpacing = Math.ceil(($container.height() - this.$firstSlide.innerHeight()) / 2), 208 | firstSlideSpacing = Math.ceil((containerWidth - this.$firstSlide.innerWidth()) / 2), 209 | lastSlideSpacing = Math.ceil((containerWidth - this.$lastSlide.innerWidth()) / 2), 210 | peekabooWidth = Math.ceil(containerWidth / 25); 211 | 212 | this.$container.css('margin-top', verticalSpacing); 213 | 214 | if (displayMode === 'single') { 215 | this.$slides.css('margin-right', firstSlideSpacing - peekabooWidth); 216 | } else if (displayMode === 'multi') { 217 | this.$slides.css('margin-right', this.config.margin); 218 | } 219 | 220 | this.$firstSlide.css('margin-left', firstSlideSpacing); 221 | this.$lastSlide.css('margin-right', lastSlideSpacing); 222 | 223 | if (this.config.portable) { 224 | var slidesWidth = parseInt(this.$container.css('padding-left')) + parseInt(this.$container.css('padding-right')); 225 | this.$slides.each(function() { 226 | slidesWidth += $(this).outerWidth(true); 227 | }); 228 | this.$container.width(slidesWidth); 229 | } 230 | 231 | return this; 232 | }, 233 | 234 | _setupTimeline: function() { 235 | var slides = this.$slides; 236 | 237 | function parseTime(point) { 238 | for(var m = (point.time || point).toString().match(/(((\d+):)?(\d+):)?(\d+)/), a = 0, i = 3; i <= 5; i++) { 239 | a = (a * 60) + parseInt(m[i] || 0); 240 | } 241 | return a; 242 | } 243 | 244 | var currentSlide = -1; 245 | function parseSlide(point) { 246 | if( point.slide == null ) { 247 | currentSlide++; 248 | } else if($.type(point.slide) === 'number') { 249 | currentSlide = point.slide; 250 | } else{ 251 | for(var match = slides.filter( point.slide )[0], i = 0; i < slides.length; i++ ) { 252 | if( slides[i] === match ) { 253 | currentSlide = i; 254 | break; 255 | } 256 | } 257 | } 258 | return slides.eq( currentSlide ); 259 | } 260 | 261 | if(! this.config.timeline) 262 | return this; 263 | 264 | this._timeline = []; 265 | for(var t = this.config.timeline, i = 0; i < t.length; i++) { 266 | this._timeline.push({ time: parseTime( t[i] ), slide: parseSlide( t[i] ) }); 267 | } 268 | this._timeline.push( { time: 99999, slide: t[0].slide } ); 269 | return this; 270 | }, 271 | 272 | _setupVideo: function() { 273 | if( !this.config.video ) { 274 | this._setupDefaultTimeSource(); 275 | } else if( this.config.video.source === "vimeo" ) { 276 | this._setupVimeoVideo( this.config.video ); 277 | } else { 278 | throw "unknown video source, not supported"; 279 | } 280 | return this; 281 | }, 282 | 283 | _setupDefaultTimeSource: function() { 284 | var self = this, t0 = (new Date()).getTime(); 285 | setInterval(function() { 286 | var t1 = (new Date()).getTime(); 287 | self.setTime( (t1 - t0)/1000 ); 288 | }, 250 ); 289 | }, 290 | 291 | _setupVimeoVideo: function(vid) { 292 | var self = this, vid = this.config.video, downgrade = false; 293 | 294 | if(window.location.protocol === "file:") { 295 | ( "console" in window ) && console.log("vimeo video player api does not work with local files. Downgrading video support\nsee http://vimeo.com/api/docs/player-js"); 296 | downgrade = true; 297 | } 298 | 299 | function loadFrame() { 300 | var id = "p" + vid.id; 301 | var frameSrc = "