initial commit
This commit is contained in:
commit
be0dfdea74
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
*.gem
|
||||||
|
*.rbc
|
||||||
|
.bundle
|
||||||
|
.config
|
||||||
|
.yardoc
|
||||||
|
Gemfile.lock
|
||||||
|
InstalledFiles
|
||||||
|
_yardoc
|
||||||
|
coverage
|
||||||
|
doc/
|
||||||
|
lib/bundler/man
|
||||||
|
pkg
|
||||||
|
rdoc
|
||||||
|
spec/reports
|
||||||
|
test/tmp
|
||||||
|
test/version_tmp
|
||||||
|
tmp
|
4
Gemfile
Normal file
4
Gemfile
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
# Specify your gem's dependencies in attentive.gemspec
|
||||||
|
gemspec
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Copyright (c) 2012 John Bintz
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Attentive
|
||||||
|
|
||||||
|
TODO: Write a gem description
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Add this line to your application's Gemfile:
|
||||||
|
|
||||||
|
gem 'attentive'
|
||||||
|
|
||||||
|
And then execute:
|
||||||
|
|
||||||
|
$ bundle
|
||||||
|
|
||||||
|
Or install it yourself as:
|
||||||
|
|
||||||
|
$ gem install attentive
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
TODO: Write usage instructions here
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork it
|
||||||
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||||
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
||||||
|
4. Push to the branch (`git push origin my-new-feature`)
|
||||||
|
5. Create new Pull Request
|
34
attentive.gemspec
Normal file
34
attentive.gemspec
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
require File.expand_path('../lib/attentive/version', __FILE__)
|
||||||
|
|
||||||
|
Gem::Specification.new do |gem|
|
||||||
|
gem.authors = ["John Bintz"]
|
||||||
|
gem.email = ["john@coswellproductions.com"]
|
||||||
|
gem.description = %q{TODO: Write a gem description}
|
||||||
|
gem.summary = %q{TODO: Write a gem summary}
|
||||||
|
gem.homepage = ""
|
||||||
|
|
||||||
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||||
|
gem.files = `git ls-files`.split("\n")
|
||||||
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||||
|
gem.name = "attentive"
|
||||||
|
gem.require_paths = ["lib"]
|
||||||
|
gem.version = Attentive::VERSION
|
||||||
|
|
||||||
|
gem.add_dependency 'sinatra'
|
||||||
|
|
||||||
|
gem.add_dependency 'sprockets', '~> 2.1.0'
|
||||||
|
gem.add_dependency 'sprockets-vendor_gems'
|
||||||
|
gem.add_dependency 'coffee-script'
|
||||||
|
gem.add_dependency 'sprockets-sass'
|
||||||
|
gem.add_dependency 'compass', '~> 0.12.rc'
|
||||||
|
|
||||||
|
gem.add_dependency 'haml'
|
||||||
|
|
||||||
|
gem.add_dependency 'nokogiri'
|
||||||
|
gem.add_dependency 'rdiscount'
|
||||||
|
gem.add_dependency 'pygments.rb'
|
||||||
|
|
||||||
|
gem.add_dependency 'jquery-rails'
|
||||||
|
end
|
||||||
|
|
26
bin/attentive
Executable file
26
bin/attentive
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'rubygems'
|
||||||
|
require 'bundler'
|
||||||
|
|
||||||
|
begin
|
||||||
|
Bundler.setup(:default)
|
||||||
|
rescue Bundler::GemfileNotFound
|
||||||
|
$: << File.expand_path('../../lib', __FILE__)
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'rack'
|
||||||
|
require 'attentive'
|
||||||
|
require 'pygments'
|
||||||
|
require 'coffee_script'
|
||||||
|
require 'sass'
|
||||||
|
|
||||||
|
load 'presentation.rb'
|
||||||
|
|
||||||
|
# make sure pygments is ready
|
||||||
|
Pygments.highlight("attentive")
|
||||||
|
|
||||||
|
Rack::Handler::WEBrick.run(Attentive::Server, :Port => 9393) do |server|
|
||||||
|
trap(:INT) { server.shutdown }
|
||||||
|
end
|
||||||
|
|
7
lib/assets/javascripts/attentive.js.coffee
Normal file
7
lib/assets/javascripts/attentive.js.coffee
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#= require jquery
|
||||||
|
#= require fathom
|
||||||
|
|
||||||
|
$(->
|
||||||
|
$('#slides').fathom(displayMode: 'multi', scrollLength: 250)
|
||||||
|
)
|
||||||
|
|
66
lib/assets/stylesheets/attentive.css.scss
Normal file
66
lib/assets/stylesheets/attentive.css.scss
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
body, html {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#slides {
|
||||||
|
.slide {
|
||||||
|
width: 75%;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.highlight {
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
padding: 1em;
|
||||||
|
|
||||||
|
font-size: 160%;
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.style-larger {
|
||||||
|
div.highlight {
|
||||||
|
font-size: 200%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.style-even-larger {
|
||||||
|
div.highlight {
|
||||||
|
font-size: 250%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.activeslide {
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.inactiveslide {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
17
lib/attentive.rb
Normal file
17
lib/attentive.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
require "attentive/version"
|
||||||
|
|
||||||
|
module Attentive
|
||||||
|
autoload :Server, 'attentive/server'
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_accessor :title
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.configure
|
||||||
|
yield self
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.root
|
||||||
|
Pathname(File.expand_path('../..', __FILE__))
|
||||||
|
end
|
||||||
|
end
|
107
lib/attentive/server.rb
Normal file
107
lib/attentive/server.rb
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
require 'sprockets'
|
||||||
|
require 'sprockets-vendor_gems'
|
||||||
|
require 'sprockets-sass'
|
||||||
|
require 'compass'
|
||||||
|
require 'sinatra'
|
||||||
|
require 'nokogiri'
|
||||||
|
require 'rdiscount'
|
||||||
|
require 'pygments'
|
||||||
|
require 'sinatra/base'
|
||||||
|
|
||||||
|
require 'rack/builder'
|
||||||
|
|
||||||
|
module Attentive
|
||||||
|
class Server < Rack::Builder
|
||||||
|
def self.call(env)
|
||||||
|
@app ||= Rack::Builder.new do
|
||||||
|
map '/assets' do
|
||||||
|
env = Sprockets::EnvironmentWithVendoredGems.new
|
||||||
|
env.append_path 'assets/javascripts'
|
||||||
|
env.append_path 'assets/stylesheets'
|
||||||
|
env.append_path Attentive.root.join('vendor/assets/javascripts')
|
||||||
|
env.append_path Attentive.root.join('lib/assets/javascripts')
|
||||||
|
env.append_path Attentive.root.join('lib/assets/stylesheets')
|
||||||
|
|
||||||
|
run env
|
||||||
|
end
|
||||||
|
|
||||||
|
map '/' do
|
||||||
|
run Attentive::Sinatra
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@app.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Sinatra < Sinatra::Base
|
||||||
|
set :logging, true
|
||||||
|
|
||||||
|
helpers do
|
||||||
|
def trim_lines(code)
|
||||||
|
code.lines.collect(&:strip).join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
def slides
|
||||||
|
highlights = []
|
||||||
|
|
||||||
|
output = Dir['presentation/*.html'].sort.collect do |file|
|
||||||
|
xml = Nokogiri::XML("<doc>#{File.read(file)}</doc>")
|
||||||
|
|
||||||
|
xml.search('slide').collect do |node|
|
||||||
|
classes = %w{slide}
|
||||||
|
|
||||||
|
if style = node.attributes['style']
|
||||||
|
style.to_s.split(' ').each { |s| classes << "style-#{s}" }
|
||||||
|
end
|
||||||
|
|
||||||
|
node.search('code').collect do |code|
|
||||||
|
highlighted_code = Pygments.highlight(code.inner_text.strip, :lexer => code.attributes['lang'].to_s)
|
||||||
|
|
||||||
|
code.add_next_sibling("{highlight#{highlights.length}}")
|
||||||
|
|
||||||
|
code.remove
|
||||||
|
|
||||||
|
highlights << highlighted_code
|
||||||
|
end
|
||||||
|
|
||||||
|
content = node.inner_html
|
||||||
|
|
||||||
|
content = case node.attributes['content'].to_s
|
||||||
|
when 'html'
|
||||||
|
content
|
||||||
|
else
|
||||||
|
RDiscount.new(trim_lines(content)).to_html
|
||||||
|
end
|
||||||
|
|
||||||
|
%{<div class="#{classes.join(' ')}"><div class="content">#{content}</div></div>}
|
||||||
|
end.join
|
||||||
|
end.join
|
||||||
|
|
||||||
|
highlights.each_with_index do |highlight, index|
|
||||||
|
output.gsub!("{highlight#{index}}", highlight)
|
||||||
|
end
|
||||||
|
|
||||||
|
output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/' do
|
||||||
|
haml :index, :ugly => true
|
||||||
|
end
|
||||||
|
|
||||||
|
set :views, [ File.join(Dir.pwd, 'views'), Attentive.root.join('views')]
|
||||||
|
|
||||||
|
private
|
||||||
|
def render(engine, data, options = {}, locals = {}, &block)
|
||||||
|
settings.views.each do |view|
|
||||||
|
template = "#{data}.#{engine}"
|
||||||
|
|
||||||
|
if File.file?(File.join(view, template))
|
||||||
|
return super(engine, data, options.merge(:views => view), locals, &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
3
lib/attentive/version.rb
Normal file
3
lib/attentive/version.rb
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module Attentive
|
||||||
|
VERSION = "0.0.1"
|
||||||
|
end
|
401
vendor/assets/javascripts/fathom.js
vendored
Normal file
401
vendor/assets/javascripts/fathom.js
vendored
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
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 = "<iframe id=\"" + id + "\" width=\""+ ( vid.width || 360 ) + "\" height=\"" + (vid.height || 203 ) + "\" frameborder=\"0\" src=\"http://player.vimeo.com/video/" + vid.id + "?api=1&player_id=" + id + "\">";
|
||||||
|
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);
|
||||||
|
|
2
views/index.haml
Normal file
2
views/index.haml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#slides= slides
|
||||||
|
|
11
views/layout.haml
Normal file
11
views/layout.haml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
!!!
|
||||||
|
%html
|
||||||
|
%head
|
||||||
|
%title= Attentive.title
|
||||||
|
%script{:type => 'text/javascript', :src => '/assets/application.js'}
|
||||||
|
%link{:rel => 'stylesheet', :href => '/assets/application.css', :type => 'text/css'}/
|
||||||
|
%style{:type => 'text/css'}= Pygments.css
|
||||||
|
= haml :"_header"
|
||||||
|
%body
|
||||||
|
= yield
|
||||||
|
|
Loading…
Reference in New Issue
Block a user