/* Fathom.js v1.2.2 Copyright 2011, Mark Dalgleish This content is released under the MIT License github.com/markdalgleish/fathom/blob/master/MIT-LICENSE.txt */ (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, 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, 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; i < times.length; i++) { if(times[i].time <= t && times[i+1].time > t) { 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.inactiveClass); return this; }, _getTallestSlideHeight: function() { var size = 0; this.$slides.each(function() { size = Math.max(size, $(this).innerHeight()); }); return size; }, _setMargins: function() { var displayMode = this.config.displayMode, $container = this.config.portable ? this.$portableContainer : $window, containerWidth = $container.width(), tallestSlideHeight = this._getTallestSlideHeight(), verticalSpacing = Math.ceil(($container.height() - tallestSlideHeight) / 2), firstSlideSpacing = Math.ceil((containerWidth - this.$firstSlide.innerWidth()) / 2), lastSlideSpacing = Math.ceil((containerWidth - this.$lastSlide.innerWidth()) / 2), peekabooWidth = Math.ceil(containerWidth / 25); this.$slides.each(function() { $(this).css('margin-top', Math.ceil(tallestSlideHeight - $(this).innerHeight()) / 2); }); 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 < slides.length; i++ ) { if( slides[i] === match ) { currentSlide = i; break; } } } return slides.eq( currentSlide ); } if(! this.config.timeline) return this; this._timeline = []; for(var t = this.config.timeline, i = 0; i < t.length; i++) { this._timeline.push({ time: parseTime( t[i] ), slide: parseSlide( t[i] ) }); } this._timeline.push( { time: 99999, slide: t[0].slide } ); return this; }, _setupVideo: function() { if( !this.config.video ) { this._setupDefaultTimeSource(); } else if( this.config.video.source === "vimeo" ) { this._setupVimeoVideo( this.config.video ); } else { throw "unknown video source, not supported"; } return this; }, _setupDefaultTimeSource: function() { var self = this, t0 = (new Date()).getTime(); setInterval(function() { var t1 = (new Date()).getTime(); self.setTime( (t1 - t0)/1000 ); }, 250 ); }, _setupVimeoVideo: function(vid) { var self = this, vid = this.config.video, downgrade = false; if(window.location.protocol === "file:") { ( "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"); downgrade = true; } function loadFrame() { var id = "p" + vid.id; var frameSrc = "